cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fc_encode.h (29534B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2/*
      3 * Copyright(c) 2008 Intel Corporation. All rights reserved.
      4 *
      5 * Maintained at www.Open-FCoE.org
      6 */
      7
      8#ifndef _FC_ENCODE_H_
      9#define _FC_ENCODE_H_
     10#include <asm/unaligned.h>
     11#include <linux/utsname.h>
     12#include <scsi/fc/fc_ms.h>
     13
     14/*
     15 * F_CTL values for simple requests and responses.
     16 */
     17#define FC_FCTL_REQ	(FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
     18#define FC_FCTL_RESP	(FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
     19			FC_FC_END_SEQ | FC_FC_SEQ_INIT)
     20
     21struct fc_ns_rft {
     22	struct fc_ns_fid fid;	/* port ID object */
     23	struct fc_ns_fts fts;	/* FC4-types object */
     24};
     25
     26struct fc_ct_req {
     27	struct fc_ct_hdr hdr;
     28	union {
     29		struct fc_ns_gid_ft gid;
     30		struct fc_ns_rn_id  rn;
     31		struct fc_ns_rft rft;
     32		struct fc_ns_rff_id rff;
     33		struct fc_ns_fid fid;
     34		struct fc_ns_rsnn snn;
     35		struct fc_ns_rspn spn;
     36		struct fc_fdmi_rhba rhba;
     37		struct fc_fdmi_rpa  rpa;
     38		struct fc_fdmi_dprt dprt;
     39		struct fc_fdmi_dhba dhba;
     40	} payload;
     41};
     42
     43/**
     44 * fc_adisc_fill() - Fill in adisc request frame
     45 * @lport: local port.
     46 * @fp: fc frame where payload will be placed.
     47 */
     48static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
     49{
     50	struct fc_els_adisc *adisc;
     51
     52	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
     53	memset(adisc, 0, sizeof(*adisc));
     54	adisc->adisc_cmd = ELS_ADISC;
     55	put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
     56	put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
     57	hton24(adisc->adisc_port_id, lport->port_id);
     58}
     59
     60/**
     61 * fc_ct_hdr_fill- fills ct header and reset ct payload
     62 * returns pointer to ct request.
     63 */
     64static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
     65					       unsigned int op, size_t req_size,
     66					       enum fc_ct_fs_type fs_type,
     67					       u8 subtype)
     68{
     69	struct fc_ct_req *ct;
     70	size_t ct_plen;
     71
     72	ct_plen  = sizeof(struct fc_ct_hdr) + req_size;
     73	ct = fc_frame_payload_get(fp, ct_plen);
     74	memset(ct, 0, ct_plen);
     75	ct->hdr.ct_rev = FC_CT_REV;
     76	ct->hdr.ct_fs_type = fs_type;
     77	ct->hdr.ct_fs_subtype = subtype;
     78	ct->hdr.ct_cmd = htons((u16) op);
     79	return ct;
     80}
     81
     82/**
     83 * fc_ct_ns_fill() - Fill in a name service request frame
     84 * @lport: local port.
     85 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
     86 * @fp: frame to contain payload.
     87 * @op: CT opcode.
     88 * @r_ctl: pointer to FC header R_CTL.
     89 * @fh_type: pointer to FC-4 type.
     90 */
     91static inline int fc_ct_ns_fill(struct fc_lport *lport,
     92		      u32 fc_id, struct fc_frame *fp,
     93		      unsigned int op, enum fc_rctl *r_ctl,
     94		      enum fc_fh_type *fh_type)
     95{
     96	struct fc_ct_req *ct;
     97	size_t len;
     98
     99	switch (op) {
    100	case FC_NS_GPN_FT:
    101		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft),
    102				    FC_FST_DIR, FC_NS_SUBTYPE);
    103		ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
    104		break;
    105
    106	case FC_NS_GPN_ID:
    107		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid),
    108				    FC_FST_DIR, FC_NS_SUBTYPE);
    109		ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
    110		hton24(ct->payload.fid.fp_fid, fc_id);
    111		break;
    112
    113	case FC_NS_RFT_ID:
    114		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft),
    115				    FC_FST_DIR, FC_NS_SUBTYPE);
    116		hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
    117		ct->payload.rft.fts = lport->fcts;
    118		break;
    119
    120	case FC_NS_RFF_ID:
    121		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id),
    122				    FC_FST_DIR, FC_NS_SUBTYPE);
    123		hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
    124		ct->payload.rff.fr_type = FC_TYPE_FCP;
    125		if (lport->service_params & FCP_SPPF_INIT_FCN)
    126			ct->payload.rff.fr_feat = FCP_FEAT_INIT;
    127		if (lport->service_params & FCP_SPPF_TARG_FCN)
    128			ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
    129		break;
    130
    131	case FC_NS_RNN_ID:
    132		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id),
    133				    FC_FST_DIR, FC_NS_SUBTYPE);
    134		hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
    135		put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
    136		break;
    137
    138	case FC_NS_RSPN_ID:
    139		len = strnlen(fc_host_symbolic_name(lport->host), 255);
    140		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len,
    141				    FC_FST_DIR, FC_NS_SUBTYPE);
    142		hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
    143		strncpy(ct->payload.spn.fr_name,
    144			fc_host_symbolic_name(lport->host), len);
    145		ct->payload.spn.fr_name_len = len;
    146		break;
    147
    148	case FC_NS_RSNN_NN:
    149		len = strnlen(fc_host_symbolic_name(lport->host), 255);
    150		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len,
    151				    FC_FST_DIR, FC_NS_SUBTYPE);
    152		put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
    153		strncpy(ct->payload.snn.fr_name,
    154			fc_host_symbolic_name(lport->host), len);
    155		ct->payload.snn.fr_name_len = len;
    156		break;
    157
    158	default:
    159		return -EINVAL;
    160	}
    161	*r_ctl = FC_RCTL_DD_UNSOL_CTL;
    162	*fh_type = FC_TYPE_CT;
    163	return 0;
    164}
    165
    166static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry *entry,
    167				    const char *in, size_t len)
    168{
    169	int copied;
    170
    171	copied = strscpy(entry->value, in, len);
    172	if (copied > 0 && copied + 1 < len)
    173		memset(entry->value + copied + 1, 0, len - copied - 1);
    174}
    175
    176/**
    177 * fc_ct_ms_fill() - Fill in a mgmt service request frame
    178 * @lport: local port.
    179 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
    180 * @fp: frame to contain payload.
    181 * @op: CT opcode.
    182 * @r_ctl: pointer to FC header R_CTL.
    183 * @fh_type: pointer to FC-4 type.
    184 */
    185static inline int fc_ct_ms_fill(struct fc_lport *lport,
    186		      u32 fc_id, struct fc_frame *fp,
    187		      unsigned int op, enum fc_rctl *r_ctl,
    188		      enum fc_fh_type *fh_type)
    189{
    190	struct fc_ct_req *ct;
    191	size_t len;
    192	struct fc_fdmi_attr_entry *entry;
    193	struct fs_fdmi_attrs *hba_attrs;
    194	int numattrs = 0;
    195	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
    196
    197	switch (op) {
    198	case FC_FDMI_RHBA:
    199		numattrs = 11;
    200		len = sizeof(struct fc_fdmi_rhba);
    201		len -= sizeof(struct fc_fdmi_attr_entry);
    202		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
    203		len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
    204		len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
    205		len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
    206		len += FC_FDMI_HBA_ATTR_MODEL_LEN;
    207		len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
    208		len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
    209		len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
    210		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
    211		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
    212		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
    213		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
    214
    215		if (fc_host->fdmi_version == FDMI_V2) {
    216			numattrs += 7;
    217			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
    218			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
    219			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
    220			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
    221			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
    222			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
    223			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
    224		}
    225
    226		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
    227				FC_FDMI_SUBTYPE);
    228
    229		/* HBA Identifier */
    230		put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
    231		/* Number of Ports - always 1 */
    232		put_unaligned_be32(1, &ct->payload.rhba.port.numport);
    233		/* Port Name */
    234		put_unaligned_be64(lport->wwpn,
    235				   &ct->payload.rhba.port.port[0].portname);
    236
    237		/* HBA Attributes */
    238		put_unaligned_be32(numattrs,
    239				   &ct->payload.rhba.hba_attrs.numattrs);
    240		hba_attrs = &ct->payload.rhba.hba_attrs;
    241		entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
    242		/* NodeName*/
    243		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    244		len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
    245		put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME,
    246				   &entry->type);
    247		put_unaligned_be16(len, &entry->len);
    248		put_unaligned_be64(lport->wwnn,
    249				   (__be64 *)&entry->value);
    250
    251		/* Manufacturer */
    252		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    253					FC_FDMI_HBA_ATTR_NODENAME_LEN);
    254		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    255		len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
    256		put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER,
    257				   &entry->type);
    258		put_unaligned_be16(len, &entry->len);
    259		fc_ct_ms_fill_attr(entry,
    260			fc_host_manufacturer(lport->host),
    261			FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
    262
    263		/* SerialNumber */
    264		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    265					FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
    266		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    267		len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
    268		put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER,
    269				   &entry->type);
    270		put_unaligned_be16(len, &entry->len);
    271		fc_ct_ms_fill_attr(entry,
    272			fc_host_serial_number(lport->host),
    273			FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
    274
    275		/* Model */
    276		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    277					FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
    278		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    279		len += FC_FDMI_HBA_ATTR_MODEL_LEN;
    280		put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL,
    281				   &entry->type);
    282		put_unaligned_be16(len, &entry->len);
    283		fc_ct_ms_fill_attr(entry,
    284			fc_host_model(lport->host),
    285			FC_FDMI_HBA_ATTR_MODEL_LEN);
    286
    287		/* Model Description */
    288		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    289					FC_FDMI_HBA_ATTR_MODEL_LEN);
    290		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    291		len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
    292		put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
    293				   &entry->type);
    294		put_unaligned_be16(len, &entry->len);
    295		fc_ct_ms_fill_attr(entry,
    296			fc_host_model_description(lport->host),
    297			FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
    298
    299		/* Hardware Version */
    300		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    301					FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
    302		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    303		len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
    304		put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
    305				   &entry->type);
    306		put_unaligned_be16(len, &entry->len);
    307		fc_ct_ms_fill_attr(entry,
    308			fc_host_hardware_version(lport->host),
    309			FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
    310
    311		/* Driver Version */
    312		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    313					FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
    314		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    315		len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
    316		put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION,
    317				   &entry->type);
    318		put_unaligned_be16(len, &entry->len);
    319		fc_ct_ms_fill_attr(entry,
    320			fc_host_driver_version(lport->host),
    321			FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
    322
    323		/* OptionROM Version */
    324		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    325					FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
    326		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    327		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
    328		put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
    329				   &entry->type);
    330		put_unaligned_be16(len, &entry->len);
    331		fc_ct_ms_fill_attr(entry,
    332			"unknown",
    333			FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
    334
    335		/* Firmware Version */
    336		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    337					FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
    338		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    339		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
    340		put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
    341				   &entry->type);
    342		put_unaligned_be16(len, &entry->len);
    343		fc_ct_ms_fill_attr(entry,
    344			fc_host_firmware_version(lport->host),
    345			FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
    346
    347		/* OS Name and Version */
    348		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    349					FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
    350		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    351		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
    352		put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
    353				   &entry->type);
    354		put_unaligned_be16(len, &entry->len);
    355		snprintf((char *)&entry->value,
    356			FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
    357			"%s v%s",
    358			init_utsname()->sysname,
    359			init_utsname()->release);
    360
    361		/* Max CT payload */
    362		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    363					FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN);
    364		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    365		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
    366		put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
    367				&entry->type);
    368		put_unaligned_be16(len, &entry->len);
    369		put_unaligned_be32(fc_host_max_ct_payload(lport->host),
    370				&entry->value);
    371
    372		if (fc_host->fdmi_version == FDMI_V2) {
    373			/* Node symbolic name */
    374			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    375					FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
    376			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    377			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
    378			put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
    379					&entry->type);
    380			put_unaligned_be16(len, &entry->len);
    381			fc_ct_ms_fill_attr(entry,
    382					fc_host_symbolic_name(lport->host),
    383					FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
    384
    385			/* Vendor specific info */
    386			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    387					FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
    388			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    389			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
    390			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
    391					&entry->type);
    392			put_unaligned_be16(len, &entry->len);
    393			put_unaligned_be32(0,
    394					&entry->value);
    395
    396			/* Number of ports */
    397			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    398					FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN);
    399			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    400			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
    401			put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
    402					&entry->type);
    403			put_unaligned_be16(len, &entry->len);
    404			put_unaligned_be32(fc_host_num_ports(lport->host),
    405					&entry->value);
    406
    407			/* Fabric name */
    408			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    409					FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN);
    410			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    411			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
    412			put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME,
    413					&entry->type);
    414			put_unaligned_be16(len, &entry->len);
    415			put_unaligned_be64(fc_host_fabric_name(lport->host),
    416					&entry->value);
    417
    418			/* BIOS version */
    419			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    420					FC_FDMI_HBA_ATTR_FABRICNAME_LEN);
    421			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    422			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
    423			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION,
    424					&entry->type);
    425			put_unaligned_be16(len, &entry->len);
    426			fc_ct_ms_fill_attr(entry,
    427					fc_host_bootbios_version(lport->host),
    428					FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
    429
    430			/* BIOS state */
    431			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    432					FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
    433			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    434			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
    435			put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE,
    436					&entry->type);
    437			put_unaligned_be16(len, &entry->len);
    438			put_unaligned_be32(fc_host_bootbios_state(lport->host),
    439					&entry->value);
    440
    441			/* Vendor identifier  */
    442			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    443					FC_FDMI_HBA_ATTR_BIOSSTATE_LEN);
    444			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    445			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
    446			put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
    447					&entry->type);
    448			put_unaligned_be16(len, &entry->len);
    449			fc_ct_ms_fill_attr(entry,
    450					fc_host_vendor_identifier(lport->host),
    451					FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
    452		}
    453
    454		break;
    455	case FC_FDMI_RPA:
    456		numattrs = 6;
    457		len = sizeof(struct fc_fdmi_rpa);
    458		len -= sizeof(struct fc_fdmi_attr_entry);
    459		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
    460		len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
    461		len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
    462		len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
    463		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
    464		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
    465		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
    466
    467
    468		if (fc_host->fdmi_version == FDMI_V2) {
    469			numattrs += 10;
    470
    471			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
    472			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
    473			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
    474			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
    475			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
    476			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
    477			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
    478			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
    479			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
    480			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
    481
    482		}
    483
    484		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
    485				    FC_FDMI_SUBTYPE);
    486
    487		/* Port Name */
    488		put_unaligned_be64(lport->wwpn,
    489				   &ct->payload.rpa.port.portname);
    490
    491		/* Port Attributes */
    492		put_unaligned_be32(numattrs,
    493				   &ct->payload.rpa.hba_attrs.numattrs);
    494
    495		hba_attrs = &ct->payload.rpa.hba_attrs;
    496		entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
    497
    498		/* FC4 types */
    499		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    500		len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
    501		put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES,
    502				   &entry->type);
    503		put_unaligned_be16(len, &entry->len);
    504		memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
    505		       FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
    506
    507		/* Supported Speed */
    508		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    509					FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
    510		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    511		len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
    512		put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
    513				   &entry->type);
    514		put_unaligned_be16(len, &entry->len);
    515
    516		put_unaligned_be32(fc_host_supported_speeds(lport->host),
    517				   &entry->value);
    518
    519		/* Current Port Speed */
    520		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    521					FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
    522		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    523		len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
    524		put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
    525				   &entry->type);
    526		put_unaligned_be16(len, &entry->len);
    527		put_unaligned_be32(lport->link_speed,
    528				   &entry->value);
    529
    530		/* Max Frame Size */
    531		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    532					FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
    533		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    534		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
    535		put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
    536				   &entry->type);
    537		put_unaligned_be16(len, &entry->len);
    538		put_unaligned_be32(fc_host_maxframe_size(lport->host),
    539				   &entry->value);
    540
    541		/* OS Device Name */
    542		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    543					FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
    544		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    545		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
    546		put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME,
    547				   &entry->type);
    548		put_unaligned_be16(len, &entry->len);
    549		/* Use the sysfs device name */
    550		fc_ct_ms_fill_attr(entry,
    551			dev_name(&lport->host->shost_gendev),
    552			strnlen(dev_name(&lport->host->shost_gendev),
    553				FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
    554
    555		/* Host Name */
    556		entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    557					FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN);
    558		len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    559		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
    560		put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME,
    561				   &entry->type);
    562		put_unaligned_be16(len, &entry->len);
    563		if (strlen(fc_host_system_hostname(lport->host)))
    564			fc_ct_ms_fill_attr(entry,
    565				fc_host_system_hostname(lport->host),
    566				strnlen(fc_host_system_hostname(lport->host),
    567					FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
    568		else
    569			fc_ct_ms_fill_attr(entry,
    570				init_utsname()->nodename,
    571				FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
    572
    573
    574		if (fc_host->fdmi_version == FDMI_V2) {
    575
    576			/* Node name */
    577			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    578					FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
    579			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    580			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
    581			put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME,
    582					&entry->type);
    583			put_unaligned_be16(len, &entry->len);
    584			put_unaligned_be64(fc_host_node_name(lport->host),
    585					&entry->value);
    586
    587			/* Port name  */
    588			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    589					FC_FDMI_PORT_ATTR_NODENAME_LEN);
    590			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    591			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
    592			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME,
    593					&entry->type);
    594			put_unaligned_be16(len, &entry->len);
    595			put_unaligned_be64(lport->wwpn,
    596					&entry->value);
    597
    598			/* Port symbolic name */
    599			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    600					FC_FDMI_PORT_ATTR_PORTNAME_LEN);
    601			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    602			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
    603			put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
    604					&entry->type);
    605			put_unaligned_be16(len, &entry->len);
    606			fc_ct_ms_fill_attr(entry,
    607					fc_host_symbolic_name(lport->host),
    608					FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
    609
    610			/* Port type */
    611			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    612					FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
    613			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    614			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
    615			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE,
    616					&entry->type);
    617			put_unaligned_be16(len, &entry->len);
    618			put_unaligned_be32(fc_host_port_type(lport->host),
    619					&entry->value);
    620
    621			/* Supported class of service */
    622			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    623					FC_FDMI_PORT_ATTR_PORTTYPE_LEN);
    624			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    625			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
    626			put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
    627					&entry->type);
    628			put_unaligned_be16(len, &entry->len);
    629			put_unaligned_be32(fc_host_supported_classes(lport->host),
    630					&entry->value);
    631
    632			/* Port Fabric name */
    633			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    634					FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN);
    635			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    636			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
    637			put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME,
    638					&entry->type);
    639			put_unaligned_be16(len, &entry->len);
    640			put_unaligned_be64(fc_host_fabric_name(lport->host),
    641					&entry->value);
    642
    643			/* Port active FC-4 */
    644			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    645					FC_FDMI_PORT_ATTR_FABRICNAME_LEN);
    646			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    647			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
    648			put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
    649					&entry->type);
    650			put_unaligned_be16(len, &entry->len);
    651			memcpy(&entry->value, fc_host_active_fc4s(lport->host),
    652					FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
    653
    654			/* Port state */
    655			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    656					FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
    657			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    658			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
    659			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE,
    660					&entry->type);
    661			put_unaligned_be16(len, &entry->len);
    662			put_unaligned_be32(fc_host_port_state(lport->host),
    663					&entry->value);
    664
    665			/* Discovered ports */
    666			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    667					FC_FDMI_PORT_ATTR_PORTSTATE_LEN);
    668			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    669			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
    670			put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
    671					&entry->type);
    672			put_unaligned_be16(len, &entry->len);
    673			put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
    674					&entry->value);
    675
    676			/* Port ID */
    677			entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
    678					FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN);
    679			len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
    680			len += FC_FDMI_PORT_ATTR_PORTID_LEN;
    681			put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID,
    682					&entry->type);
    683			put_unaligned_be16(len, &entry->len);
    684			put_unaligned_be32(fc_host_port_id(lport->host),
    685					&entry->value);
    686		}
    687
    688		break;
    689	case FC_FDMI_DPRT:
    690		len = sizeof(struct fc_fdmi_dprt);
    691		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
    692				    FC_FDMI_SUBTYPE);
    693		/* Port Name */
    694		put_unaligned_be64(lport->wwpn,
    695				   &ct->payload.dprt.port.portname);
    696		break;
    697	case FC_FDMI_DHBA:
    698		len = sizeof(struct fc_fdmi_dhba);
    699		ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
    700				    FC_FDMI_SUBTYPE);
    701		/* HBA Identifier */
    702		put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id);
    703		break;
    704	default:
    705		return -EINVAL;
    706	}
    707	*r_ctl = FC_RCTL_DD_UNSOL_CTL;
    708	*fh_type = FC_TYPE_CT;
    709	return 0;
    710}
    711
    712/**
    713 * fc_ct_fill() - Fill in a common transport service request frame
    714 * @lport: local port.
    715 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
    716 * @fp: frame to contain payload.
    717 * @op: CT opcode.
    718 * @r_ctl: pointer to FC header R_CTL.
    719 * @fh_type: pointer to FC-4 type.
    720 */
    721static inline int fc_ct_fill(struct fc_lport *lport,
    722		      u32 fc_id, struct fc_frame *fp,
    723		      unsigned int op, enum fc_rctl *r_ctl,
    724		      enum fc_fh_type *fh_type, u32 *did)
    725{
    726	int rc = -EINVAL;
    727
    728	switch (fc_id) {
    729	case FC_FID_MGMT_SERV:
    730		rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type);
    731		*did = FC_FID_MGMT_SERV;
    732		break;
    733	case FC_FID_DIR_SERV:
    734	default:
    735		rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
    736		*did = FC_FID_DIR_SERV;
    737		break;
    738	}
    739
    740	return rc;
    741}
    742/**
    743 * fc_plogi_fill - Fill in plogi request frame
    744 */
    745static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
    746				 unsigned int op)
    747{
    748	struct fc_els_flogi *plogi;
    749	struct fc_els_csp *csp;
    750	struct fc_els_cssp *cp;
    751
    752	plogi = fc_frame_payload_get(fp, sizeof(*plogi));
    753	memset(plogi, 0, sizeof(*plogi));
    754	plogi->fl_cmd = (u8) op;
    755	put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
    756	put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
    757
    758	csp = &plogi->fl_csp;
    759	csp->sp_hi_ver = 0x20;
    760	csp->sp_lo_ver = 0x20;
    761	csp->sp_bb_cred = htons(10);	/* this gets set by gateway */
    762	csp->sp_bb_data = htons((u16) lport->mfs);
    763	cp = &plogi->fl_cssp[3 - 1];	/* class 3 parameters */
    764	cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
    765	csp->sp_features = htons(FC_SP_FT_CIRO);
    766	csp->sp_tot_seq = htons(255);	/* seq. we accept */
    767	csp->sp_rel_off = htons(0x1f);
    768	csp->sp_e_d_tov = htonl(lport->e_d_tov);
    769
    770	cp->cp_rdfs = htons((u16) lport->mfs);
    771	cp->cp_con_seq = htons(255);
    772	cp->cp_open_seq = 1;
    773}
    774
    775/**
    776 * fc_flogi_fill - Fill in a flogi request frame.
    777 */
    778static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
    779{
    780	struct fc_els_csp *sp;
    781	struct fc_els_cssp *cp;
    782	struct fc_els_flogi *flogi;
    783
    784	flogi = fc_frame_payload_get(fp, sizeof(*flogi));
    785	memset(flogi, 0, sizeof(*flogi));
    786	flogi->fl_cmd = (u8) ELS_FLOGI;
    787	put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
    788	put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
    789	sp = &flogi->fl_csp;
    790	sp->sp_hi_ver = 0x20;
    791	sp->sp_lo_ver = 0x20;
    792	sp->sp_bb_cred = htons(10);	/* this gets set by gateway */
    793	sp->sp_bb_data = htons((u16) lport->mfs);
    794	cp = &flogi->fl_cssp[3 - 1];	/* class 3 parameters */
    795	cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
    796	if (lport->does_npiv)
    797		sp->sp_features = htons(FC_SP_FT_NPIV);
    798}
    799
    800/**
    801 * fc_fdisc_fill - Fill in a fdisc request frame.
    802 */
    803static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
    804{
    805	struct fc_els_csp *sp;
    806	struct fc_els_cssp *cp;
    807	struct fc_els_flogi *fdisc;
    808
    809	fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
    810	memset(fdisc, 0, sizeof(*fdisc));
    811	fdisc->fl_cmd = (u8) ELS_FDISC;
    812	put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
    813	put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
    814	sp = &fdisc->fl_csp;
    815	sp->sp_hi_ver = 0x20;
    816	sp->sp_lo_ver = 0x20;
    817	sp->sp_bb_cred = htons(10);	/* this gets set by gateway */
    818	sp->sp_bb_data = htons((u16) lport->mfs);
    819	cp = &fdisc->fl_cssp[3 - 1];	/* class 3 parameters */
    820	cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
    821}
    822
    823/**
    824 * fc_logo_fill - Fill in a logo request frame.
    825 */
    826static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
    827{
    828	struct fc_els_logo *logo;
    829
    830	logo = fc_frame_payload_get(fp, sizeof(*logo));
    831	memset(logo, 0, sizeof(*logo));
    832	logo->fl_cmd = ELS_LOGO;
    833	hton24(logo->fl_n_port_id, lport->port_id);
    834	logo->fl_n_port_wwn = htonll(lport->wwpn);
    835}
    836
    837/**
    838 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
    839 */
    840static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
    841{
    842	struct fc_els_rtv *rtv;
    843
    844	rtv = fc_frame_payload_get(fp, sizeof(*rtv));
    845	memset(rtv, 0, sizeof(*rtv));
    846	rtv->rtv_cmd = ELS_RTV;
    847}
    848
    849/**
    850 * fc_rec_fill - Fill in rec request frame
    851 */
    852static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
    853{
    854	struct fc_els_rec *rec;
    855	struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
    856
    857	rec = fc_frame_payload_get(fp, sizeof(*rec));
    858	memset(rec, 0, sizeof(*rec));
    859	rec->rec_cmd = ELS_REC;
    860	hton24(rec->rec_s_id, lport->port_id);
    861	rec->rec_ox_id = htons(ep->oxid);
    862	rec->rec_rx_id = htons(ep->rxid);
    863}
    864
    865/**
    866 * fc_prli_fill - Fill in prli request frame
    867 */
    868static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
    869{
    870	struct {
    871		struct fc_els_prli prli;
    872		struct fc_els_spp spp;
    873	} *pp;
    874
    875	pp = fc_frame_payload_get(fp, sizeof(*pp));
    876	memset(pp, 0, sizeof(*pp));
    877	pp->prli.prli_cmd = ELS_PRLI;
    878	pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
    879	pp->prli.prli_len = htons(sizeof(*pp));
    880	pp->spp.spp_type = FC_TYPE_FCP;
    881	pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
    882	pp->spp.spp_params = htonl(lport->service_params);
    883}
    884
    885/**
    886 * fc_scr_fill - Fill in a scr request frame.
    887 */
    888static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
    889{
    890	struct fc_els_scr *scr;
    891
    892	scr = fc_frame_payload_get(fp, sizeof(*scr));
    893	memset(scr, 0, sizeof(*scr));
    894	scr->scr_cmd = ELS_SCR;
    895	scr->scr_reg_func = ELS_SCRF_FULL;
    896}
    897
    898/**
    899 * fc_els_fill - Fill in an ELS  request frame
    900 */
    901static inline int fc_els_fill(struct fc_lport *lport,
    902		       u32 did,
    903		       struct fc_frame *fp, unsigned int op,
    904		       enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
    905{
    906	switch (op) {
    907	case ELS_ADISC:
    908		fc_adisc_fill(lport, fp);
    909		break;
    910
    911	case ELS_PLOGI:
    912		fc_plogi_fill(lport, fp, ELS_PLOGI);
    913		break;
    914
    915	case ELS_FLOGI:
    916		fc_flogi_fill(lport, fp);
    917		break;
    918
    919	case ELS_FDISC:
    920		fc_fdisc_fill(lport, fp);
    921		break;
    922
    923	case ELS_LOGO:
    924		fc_logo_fill(lport, fp);
    925		break;
    926
    927	case ELS_RTV:
    928		fc_rtv_fill(lport, fp);
    929		break;
    930
    931	case ELS_REC:
    932		fc_rec_fill(lport, fp);
    933		break;
    934
    935	case ELS_PRLI:
    936		fc_prli_fill(lport, fp);
    937		break;
    938
    939	case ELS_SCR:
    940		fc_scr_fill(lport, fp);
    941		break;
    942
    943	default:
    944		return -EINVAL;
    945	}
    946
    947	*r_ctl = FC_RCTL_ELS_REQ;
    948	*fh_type = FC_TYPE_ELS;
    949	return 0;
    950}
    951#endif /* _FC_ENCODE_H_ */