2 * Copyright(c) 2008 Intel Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 * Maintained at www.Open-FCoE.org
22 #include <asm/unaligned.h>
23 #include <linux/utsname.h>
26 * F_CTL values for simple requests and responses.
28 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
29 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
30 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
33 struct fc_ns_fid fid
; /* port ID object */
34 struct fc_ns_fts fts
; /* FC4-types object */
40 struct fc_ns_gid_ft gid
;
41 struct fc_ns_rn_id rn
;
43 struct fc_ns_rff_id rff
;
45 struct fc_ns_rsnn snn
;
46 struct fc_ns_rspn spn
;
47 struct fc_fdmi_rhba rhba
;
48 struct fc_fdmi_rpa rpa
;
49 struct fc_fdmi_dprt dprt
;
50 struct fc_fdmi_dhba dhba
;
54 static inline void __fc_fill_fc_hdr(struct fc_frame_header
*fh
,
56 u32 did
, u32 sid
, enum fc_fh_type type
,
57 u32 f_ctl
, u32 parm_offset
)
61 hton24(fh
->fh_d_id
, did
);
62 hton24(fh
->fh_s_id
, sid
);
64 hton24(fh
->fh_f_ctl
, f_ctl
);
67 fh
->fh_parm_offset
= htonl(parm_offset
);
71 * fill FC header fields in specified fc_frame
73 static inline void fc_fill_fc_hdr(struct fc_frame
*fp
, enum fc_rctl r_ctl
,
74 u32 did
, u32 sid
, enum fc_fh_type type
,
75 u32 f_ctl
, u32 parm_offset
)
77 struct fc_frame_header
*fh
;
79 fh
= fc_frame_header_get(fp
);
80 __fc_fill_fc_hdr(fh
, r_ctl
, did
, sid
, type
, f_ctl
, parm_offset
);
84 * fc_adisc_fill() - Fill in adisc request frame
86 * @fp: fc frame where payload will be placed.
88 static inline void fc_adisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
90 struct fc_els_adisc
*adisc
;
92 adisc
= fc_frame_payload_get(fp
, sizeof(*adisc
));
93 memset(adisc
, 0, sizeof(*adisc
));
94 adisc
->adisc_cmd
= ELS_ADISC
;
95 put_unaligned_be64(lport
->wwpn
, &adisc
->adisc_wwpn
);
96 put_unaligned_be64(lport
->wwnn
, &adisc
->adisc_wwnn
);
97 hton24(adisc
->adisc_port_id
, lport
->port_id
);
101 * fc_ct_hdr_fill- fills ct header and reset ct payload
102 * returns pointer to ct request.
104 static inline struct fc_ct_req
*fc_ct_hdr_fill(const struct fc_frame
*fp
,
105 unsigned int op
, size_t req_size
,
106 enum fc_ct_fs_type fs_type
,
109 struct fc_ct_req
*ct
;
112 ct_plen
= sizeof(struct fc_ct_hdr
) + req_size
;
113 ct
= fc_frame_payload_get(fp
, ct_plen
);
114 memset(ct
, 0, ct_plen
);
115 ct
->hdr
.ct_rev
= FC_CT_REV
;
116 ct
->hdr
.ct_fs_type
= fs_type
;
117 ct
->hdr
.ct_fs_subtype
= subtype
;
118 ct
->hdr
.ct_cmd
= htons((u16
) op
);
123 * fc_ct_ns_fill() - Fill in a name service request frame
124 * @lport: local port.
125 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
126 * @fp: frame to contain payload.
128 * @r_ctl: pointer to FC header R_CTL.
129 * @fh_type: pointer to FC-4 type.
131 static inline int fc_ct_ns_fill(struct fc_lport
*lport
,
132 u32 fc_id
, struct fc_frame
*fp
,
133 unsigned int op
, enum fc_rctl
*r_ctl
,
134 enum fc_fh_type
*fh_type
)
136 struct fc_ct_req
*ct
;
141 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_gid_ft
),
142 FC_FST_DIR
, FC_NS_SUBTYPE
);
143 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
147 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_fid
),
148 FC_FST_DIR
, FC_NS_SUBTYPE
);
149 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
150 hton24(ct
->payload
.fid
.fp_fid
, fc_id
);
154 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rft
),
155 FC_FST_DIR
, FC_NS_SUBTYPE
);
156 hton24(ct
->payload
.rft
.fid
.fp_fid
, lport
->port_id
);
157 ct
->payload
.rft
.fts
= lport
->fcts
;
161 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rff_id
),
162 FC_FST_DIR
, FC_NS_SUBTYPE
);
163 hton24(ct
->payload
.rff
.fr_fid
.fp_fid
, lport
->port_id
);
164 ct
->payload
.rff
.fr_type
= FC_TYPE_FCP
;
165 if (lport
->service_params
& FCP_SPPF_INIT_FCN
)
166 ct
->payload
.rff
.fr_feat
= FCP_FEAT_INIT
;
167 if (lport
->service_params
& FCP_SPPF_TARG_FCN
)
168 ct
->payload
.rff
.fr_feat
|= FCP_FEAT_TARG
;
172 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rn_id
),
173 FC_FST_DIR
, FC_NS_SUBTYPE
);
174 hton24(ct
->payload
.rn
.fr_fid
.fp_fid
, lport
->port_id
);
175 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.rn
.fr_wwn
);
179 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
180 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rspn
) + len
,
181 FC_FST_DIR
, FC_NS_SUBTYPE
);
182 hton24(ct
->payload
.spn
.fr_fid
.fp_fid
, lport
->port_id
);
183 strncpy(ct
->payload
.spn
.fr_name
,
184 fc_host_symbolic_name(lport
->host
), len
);
185 ct
->payload
.spn
.fr_name_len
= len
;
189 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
190 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rsnn
) + len
,
191 FC_FST_DIR
, FC_NS_SUBTYPE
);
192 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.snn
.fr_wwn
);
193 strncpy(ct
->payload
.snn
.fr_name
,
194 fc_host_symbolic_name(lport
->host
), len
);
195 ct
->payload
.snn
.fr_name_len
= len
;
201 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
202 *fh_type
= FC_TYPE_CT
;
207 * fc_ct_ms_fill() - Fill in a mgmt service request frame
208 * @lport: local port.
209 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
210 * @fp: frame to contain payload.
212 * @r_ctl: pointer to FC header R_CTL.
213 * @fh_type: pointer to FC-4 type.
215 static inline int fc_ct_ms_fill(struct fc_lport
*lport
,
216 u32 fc_id
, struct fc_frame
*fp
,
217 unsigned int op
, enum fc_rctl
*r_ctl
,
218 enum fc_fh_type
*fh_type
)
220 struct fc_ct_req
*ct
;
222 struct fc_fdmi_attr_entry
*entry
;
223 struct fs_fdmi_attrs
*hba_attrs
;
229 len
= sizeof(struct fc_fdmi_rhba
);
230 len
-= sizeof(struct fc_fdmi_attr_entry
);
231 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
232 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
233 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
234 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
235 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
236 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
237 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
238 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
239 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
240 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
241 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
242 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
246 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.rhba
.hbaid
.id
);
247 /* Number of Ports - always 1 */
248 put_unaligned_be32(1, &ct
->payload
.rhba
.port
.numport
);
250 put_unaligned_be64(lport
->wwpn
,
251 &ct
->payload
.rhba
.port
.port
[0].portname
);
254 put_unaligned_be32(numattrs
,
255 &ct
->payload
.rhba
.hba_attrs
.numattrs
);
256 hba_attrs
= &ct
->payload
.rhba
.hba_attrs
;
257 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
259 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
260 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
261 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME
,
263 put_unaligned_be16(len
, &entry
->len
);
264 put_unaligned_be64(lport
->wwnn
,
265 (__be64
*)&entry
->value
[0]);
268 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
269 FC_FDMI_HBA_ATTR_NODENAME_LEN
);
270 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
271 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
272 put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER
,
274 put_unaligned_be16(len
, &entry
->len
);
275 strncpy((char *)&entry
->value
,
276 fc_host_manufacturer(lport
->host
),
277 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
280 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
281 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
282 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
283 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
284 put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER
,
286 put_unaligned_be16(len
, &entry
->len
);
287 strncpy((char *)&entry
->value
,
288 fc_host_serial_number(lport
->host
),
289 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
292 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
293 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
294 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
295 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
296 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL
,
298 put_unaligned_be16(len
, &entry
->len
);
299 strncpy((char *)&entry
->value
,
300 fc_host_model(lport
->host
),
301 FC_FDMI_HBA_ATTR_MODEL_LEN
);
303 /* Model Description */
304 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
305 FC_FDMI_HBA_ATTR_MODEL_LEN
);
306 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
307 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
308 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION
,
310 put_unaligned_be16(len
, &entry
->len
);
311 strncpy((char *)&entry
->value
,
312 fc_host_model_description(lport
->host
),
313 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
315 /* Hardware Version */
316 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
317 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
318 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
319 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
320 put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION
,
322 put_unaligned_be16(len
, &entry
->len
);
323 strncpy((char *)&entry
->value
,
324 fc_host_hardware_version(lport
->host
),
325 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
328 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
329 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
330 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
331 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
332 put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION
,
334 put_unaligned_be16(len
, &entry
->len
);
335 strncpy((char *)&entry
->value
,
336 fc_host_driver_version(lport
->host
),
337 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
339 /* OptionROM Version */
340 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
341 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
342 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
343 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
344 put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION
,
346 put_unaligned_be16(len
, &entry
->len
);
347 strncpy((char *)&entry
->value
,
348 fc_host_optionrom_version(lport
->host
),
349 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
351 /* Firmware Version */
352 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
353 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
354 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
355 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
356 put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION
,
358 put_unaligned_be16(len
, &entry
->len
);
359 strncpy((char *)&entry
->value
,
360 fc_host_firmware_version(lport
->host
),
361 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
363 /* OS Name and Version */
364 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
365 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
366 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
367 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
368 put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION
,
370 put_unaligned_be16(len
, &entry
->len
);
371 snprintf((char *)&entry
->value
,
372 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
,
374 init_utsname()->sysname
,
375 init_utsname()->release
);
379 len
= sizeof(struct fc_fdmi_rpa
);
380 len
-= sizeof(struct fc_fdmi_attr_entry
);
381 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
382 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
383 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
384 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
385 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
386 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
387 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
388 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
392 put_unaligned_be64(lport
->wwpn
,
393 &ct
->payload
.rpa
.port
.portname
);
395 /* Port Attributes */
396 put_unaligned_be32(numattrs
,
397 &ct
->payload
.rpa
.hba_attrs
.numattrs
);
399 hba_attrs
= &ct
->payload
.rpa
.hba_attrs
;
400 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
403 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
404 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
405 put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES
,
407 put_unaligned_be16(len
, &entry
->len
);
408 memcpy(&entry
->value
, fc_host_supported_fc4s(lport
->host
),
409 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
411 /* Supported Speed */
412 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
413 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
414 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
415 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
416 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED
,
418 put_unaligned_be16(len
, &entry
->len
);
420 put_unaligned_be32(fc_host_supported_speeds(lport
->host
),
423 /* Current Port Speed */
424 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
425 FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
);
426 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
427 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
428 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED
,
430 put_unaligned_be16(len
, &entry
->len
);
431 put_unaligned_be32(lport
->link_speed
,
435 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
436 FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
);
437 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
438 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
439 put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE
,
441 put_unaligned_be16(len
, &entry
->len
);
442 put_unaligned_be32(fc_host_maxframe_size(lport
->host
),
446 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
447 FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
);
448 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
449 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
450 put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME
,
452 put_unaligned_be16(len
, &entry
->len
);
453 /* Use the sysfs device name */
454 strncpy((char *)&entry
->value
,
455 dev_name(&lport
->host
->shost_gendev
),
456 strnlen(dev_name(&lport
->host
->shost_gendev
),
457 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
460 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
461 FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
);
462 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
463 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
464 put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME
,
466 put_unaligned_be16(len
, &entry
->len
);
467 if (strlen(fc_host_system_hostname(lport
->host
)))
468 strncpy((char *)&entry
->value
,
469 fc_host_system_hostname(lport
->host
),
470 strnlen(fc_host_system_hostname(lport
->host
),
471 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
473 strncpy((char *)&entry
->value
,
474 init_utsname()->nodename
,
475 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
);
478 len
= sizeof(struct fc_fdmi_dprt
);
479 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
482 put_unaligned_be64(lport
->wwpn
,
483 &ct
->payload
.dprt
.port
.portname
);
486 len
= sizeof(struct fc_fdmi_dhba
);
487 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
490 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.dhba
.hbaid
.id
);
495 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
496 *fh_type
= FC_TYPE_CT
;
501 * fc_ct_fill() - Fill in a common transport service request frame
502 * @lport: local port.
503 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
504 * @fp: frame to contain payload.
506 * @r_ctl: pointer to FC header R_CTL.
507 * @fh_type: pointer to FC-4 type.
509 static inline int fc_ct_fill(struct fc_lport
*lport
,
510 u32 fc_id
, struct fc_frame
*fp
,
511 unsigned int op
, enum fc_rctl
*r_ctl
,
512 enum fc_fh_type
*fh_type
, u32
*did
)
517 case FC_FID_MGMT_SERV
:
518 rc
= fc_ct_ms_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
519 *did
= FC_FID_MGMT_SERV
;
521 case FC_FID_DIR_SERV
:
523 rc
= fc_ct_ns_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
524 *did
= FC_FID_DIR_SERV
;
531 * fc_plogi_fill - Fill in plogi request frame
533 static inline void fc_plogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
,
536 struct fc_els_flogi
*plogi
;
537 struct fc_els_csp
*csp
;
538 struct fc_els_cssp
*cp
;
540 plogi
= fc_frame_payload_get(fp
, sizeof(*plogi
));
541 memset(plogi
, 0, sizeof(*plogi
));
542 plogi
->fl_cmd
= (u8
) op
;
543 put_unaligned_be64(lport
->wwpn
, &plogi
->fl_wwpn
);
544 put_unaligned_be64(lport
->wwnn
, &plogi
->fl_wwnn
);
546 csp
= &plogi
->fl_csp
;
547 csp
->sp_hi_ver
= 0x20;
548 csp
->sp_lo_ver
= 0x20;
549 csp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
550 csp
->sp_bb_data
= htons((u16
) lport
->mfs
);
551 cp
= &plogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
552 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
553 csp
->sp_features
= htons(FC_SP_FT_CIRO
);
554 csp
->sp_tot_seq
= htons(255); /* seq. we accept */
555 csp
->sp_rel_off
= htons(0x1f);
556 csp
->sp_e_d_tov
= htonl(lport
->e_d_tov
);
558 cp
->cp_rdfs
= htons((u16
) lport
->mfs
);
559 cp
->cp_con_seq
= htons(255);
564 * fc_flogi_fill - Fill in a flogi request frame.
566 static inline void fc_flogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
568 struct fc_els_csp
*sp
;
569 struct fc_els_cssp
*cp
;
570 struct fc_els_flogi
*flogi
;
572 flogi
= fc_frame_payload_get(fp
, sizeof(*flogi
));
573 memset(flogi
, 0, sizeof(*flogi
));
574 flogi
->fl_cmd
= (u8
) ELS_FLOGI
;
575 put_unaligned_be64(lport
->wwpn
, &flogi
->fl_wwpn
);
576 put_unaligned_be64(lport
->wwnn
, &flogi
->fl_wwnn
);
578 sp
->sp_hi_ver
= 0x20;
579 sp
->sp_lo_ver
= 0x20;
580 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
581 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
582 cp
= &flogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
583 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
584 if (lport
->does_npiv
)
585 sp
->sp_features
= htons(FC_SP_FT_NPIV
);
589 * fc_fdisc_fill - Fill in a fdisc request frame.
591 static inline void fc_fdisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
593 struct fc_els_csp
*sp
;
594 struct fc_els_cssp
*cp
;
595 struct fc_els_flogi
*fdisc
;
597 fdisc
= fc_frame_payload_get(fp
, sizeof(*fdisc
));
598 memset(fdisc
, 0, sizeof(*fdisc
));
599 fdisc
->fl_cmd
= (u8
) ELS_FDISC
;
600 put_unaligned_be64(lport
->wwpn
, &fdisc
->fl_wwpn
);
601 put_unaligned_be64(lport
->wwnn
, &fdisc
->fl_wwnn
);
603 sp
->sp_hi_ver
= 0x20;
604 sp
->sp_lo_ver
= 0x20;
605 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
606 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
607 cp
= &fdisc
->fl_cssp
[3 - 1]; /* class 3 parameters */
608 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
612 * fc_logo_fill - Fill in a logo request frame.
614 static inline void fc_logo_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
616 struct fc_els_logo
*logo
;
618 logo
= fc_frame_payload_get(fp
, sizeof(*logo
));
619 memset(logo
, 0, sizeof(*logo
));
620 logo
->fl_cmd
= ELS_LOGO
;
621 hton24(logo
->fl_n_port_id
, lport
->port_id
);
622 logo
->fl_n_port_wwn
= htonll(lport
->wwpn
);
626 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
628 static inline void fc_rtv_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
630 struct fc_els_rtv
*rtv
;
632 rtv
= fc_frame_payload_get(fp
, sizeof(*rtv
));
633 memset(rtv
, 0, sizeof(*rtv
));
634 rtv
->rtv_cmd
= ELS_RTV
;
638 * fc_rec_fill - Fill in rec request frame
640 static inline void fc_rec_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
642 struct fc_els_rec
*rec
;
643 struct fc_exch
*ep
= fc_seq_exch(fr_seq(fp
));
645 rec
= fc_frame_payload_get(fp
, sizeof(*rec
));
646 memset(rec
, 0, sizeof(*rec
));
647 rec
->rec_cmd
= ELS_REC
;
648 hton24(rec
->rec_s_id
, lport
->port_id
);
649 rec
->rec_ox_id
= htons(ep
->oxid
);
650 rec
->rec_rx_id
= htons(ep
->rxid
);
654 * fc_prli_fill - Fill in prli request frame
656 static inline void fc_prli_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
659 struct fc_els_prli prli
;
660 struct fc_els_spp spp
;
663 pp
= fc_frame_payload_get(fp
, sizeof(*pp
));
664 memset(pp
, 0, sizeof(*pp
));
665 pp
->prli
.prli_cmd
= ELS_PRLI
;
666 pp
->prli
.prli_spp_len
= sizeof(struct fc_els_spp
);
667 pp
->prli
.prli_len
= htons(sizeof(*pp
));
668 pp
->spp
.spp_type
= FC_TYPE_FCP
;
669 pp
->spp
.spp_flags
= FC_SPP_EST_IMG_PAIR
;
670 pp
->spp
.spp_params
= htonl(lport
->service_params
);
674 * fc_scr_fill - Fill in a scr request frame.
676 static inline void fc_scr_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
678 struct fc_els_scr
*scr
;
680 scr
= fc_frame_payload_get(fp
, sizeof(*scr
));
681 memset(scr
, 0, sizeof(*scr
));
682 scr
->scr_cmd
= ELS_SCR
;
683 scr
->scr_reg_func
= ELS_SCRF_FULL
;
687 * fc_els_fill - Fill in an ELS request frame
689 static inline int fc_els_fill(struct fc_lport
*lport
,
691 struct fc_frame
*fp
, unsigned int op
,
692 enum fc_rctl
*r_ctl
, enum fc_fh_type
*fh_type
)
696 fc_adisc_fill(lport
, fp
);
700 fc_plogi_fill(lport
, fp
, ELS_PLOGI
);
704 fc_flogi_fill(lport
, fp
);
708 fc_fdisc_fill(lport
, fp
);
712 fc_logo_fill(lport
, fp
);
716 fc_rtv_fill(lport
, fp
);
720 fc_rec_fill(lport
, fp
);
724 fc_prli_fill(lport
, fp
);
728 fc_scr_fill(lport
, fp
);
735 *r_ctl
= FC_RCTL_ELS_REQ
;
736 *fh_type
= FC_TYPE_ELS
;
739 #endif /* _FC_ENCODE_H_ */