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>
25 * F_CTL values for simple requests and responses.
27 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
28 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
29 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
32 struct fc_ns_fid fid
; /* port ID object */
33 struct fc_ns_fts fts
; /* FC4-types object */
39 struct fc_ns_gid_ft gid
;
40 struct fc_ns_rn_id rn
;
42 struct fc_ns_rff_id rff
;
44 struct fc_ns_rsnn snn
;
45 struct fc_ns_rspn spn
;
49 static inline void __fc_fill_fc_hdr(struct fc_frame_header
*fh
,
51 u32 did
, u32 sid
, enum fc_fh_type type
,
52 u32 f_ctl
, u32 parm_offset
)
56 hton24(fh
->fh_d_id
, did
);
57 hton24(fh
->fh_s_id
, sid
);
59 hton24(fh
->fh_f_ctl
, f_ctl
);
62 fh
->fh_parm_offset
= htonl(parm_offset
);
66 * fill FC header fields in specified fc_frame
68 static inline void fc_fill_fc_hdr(struct fc_frame
*fp
, enum fc_rctl r_ctl
,
69 u32 did
, u32 sid
, enum fc_fh_type type
,
70 u32 f_ctl
, u32 parm_offset
)
72 struct fc_frame_header
*fh
;
74 fh
= fc_frame_header_get(fp
);
75 __fc_fill_fc_hdr(fh
, r_ctl
, did
, sid
, type
, f_ctl
, parm_offset
);
79 * fc_adisc_fill() - Fill in adisc request frame
81 * @fp: fc frame where payload will be placed.
83 static inline void fc_adisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
85 struct fc_els_adisc
*adisc
;
87 adisc
= fc_frame_payload_get(fp
, sizeof(*adisc
));
88 memset(adisc
, 0, sizeof(*adisc
));
89 adisc
->adisc_cmd
= ELS_ADISC
;
90 put_unaligned_be64(lport
->wwpn
, &adisc
->adisc_wwpn
);
91 put_unaligned_be64(lport
->wwnn
, &adisc
->adisc_wwnn
);
92 hton24(adisc
->adisc_port_id
, lport
->port_id
);
96 * fc_ct_hdr_fill- fills ct header and reset ct payload
97 * returns pointer to ct request.
99 static inline struct fc_ct_req
*fc_ct_hdr_fill(const struct fc_frame
*fp
,
100 unsigned int op
, size_t req_size
)
102 struct fc_ct_req
*ct
;
105 ct_plen
= sizeof(struct fc_ct_hdr
) + req_size
;
106 ct
= fc_frame_payload_get(fp
, ct_plen
);
107 memset(ct
, 0, ct_plen
);
108 ct
->hdr
.ct_rev
= FC_CT_REV
;
109 ct
->hdr
.ct_fs_type
= FC_FST_DIR
;
110 ct
->hdr
.ct_fs_subtype
= FC_NS_SUBTYPE
;
111 ct
->hdr
.ct_cmd
= htons((u16
) op
);
116 * fc_ct_fill() - Fill in a name service request frame
117 * @lport: local port.
118 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
119 * @fp: frame to contain payload.
121 * @r_ctl: pointer to FC header R_CTL.
122 * @fh_type: pointer to FC-4 type.
124 static inline int fc_ct_fill(struct fc_lport
*lport
,
125 u32 fc_id
, struct fc_frame
*fp
,
126 unsigned int op
, enum fc_rctl
*r_ctl
,
127 enum fc_fh_type
*fh_type
)
129 struct fc_ct_req
*ct
;
134 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_gid_ft
));
135 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
139 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_fid
));
140 hton24(ct
->payload
.fid
.fp_fid
, fc_id
);
144 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rft
));
145 hton24(ct
->payload
.rft
.fid
.fp_fid
, lport
->port_id
);
146 ct
->payload
.rft
.fts
= lport
->fcts
;
150 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rff_id
));
151 hton24(ct
->payload
.rff
.fr_fid
.fp_fid
, lport
->port_id
);
152 ct
->payload
.rff
.fr_type
= FC_TYPE_FCP
;
153 if (lport
->service_params
& FCP_SPPF_INIT_FCN
)
154 ct
->payload
.rff
.fr_feat
= FCP_FEAT_INIT
;
155 if (lport
->service_params
& FCP_SPPF_TARG_FCN
)
156 ct
->payload
.rff
.fr_feat
|= FCP_FEAT_TARG
;
160 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rn_id
));
161 hton24(ct
->payload
.rn
.fr_fid
.fp_fid
, lport
->port_id
);
162 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.rn
.fr_wwn
);
166 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
167 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rspn
) + len
);
168 hton24(ct
->payload
.spn
.fr_fid
.fp_fid
, lport
->port_id
);
169 strncpy(ct
->payload
.spn
.fr_name
,
170 fc_host_symbolic_name(lport
->host
), len
);
171 ct
->payload
.spn
.fr_name_len
= len
;
175 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
176 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rsnn
) + len
);
177 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.snn
.fr_wwn
);
178 strncpy(ct
->payload
.snn
.fr_name
,
179 fc_host_symbolic_name(lport
->host
), len
);
180 ct
->payload
.snn
.fr_name_len
= len
;
186 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
187 *fh_type
= FC_TYPE_CT
;
192 * fc_plogi_fill - Fill in plogi request frame
194 static inline void fc_plogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
,
197 struct fc_els_flogi
*plogi
;
198 struct fc_els_csp
*csp
;
199 struct fc_els_cssp
*cp
;
201 plogi
= fc_frame_payload_get(fp
, sizeof(*plogi
));
202 memset(plogi
, 0, sizeof(*plogi
));
203 plogi
->fl_cmd
= (u8
) op
;
204 put_unaligned_be64(lport
->wwpn
, &plogi
->fl_wwpn
);
205 put_unaligned_be64(lport
->wwnn
, &plogi
->fl_wwnn
);
207 csp
= &plogi
->fl_csp
;
208 csp
->sp_hi_ver
= 0x20;
209 csp
->sp_lo_ver
= 0x20;
210 csp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
211 csp
->sp_bb_data
= htons((u16
) lport
->mfs
);
212 cp
= &plogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
213 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
214 csp
->sp_features
= htons(FC_SP_FT_CIRO
);
215 csp
->sp_tot_seq
= htons(255); /* seq. we accept */
216 csp
->sp_rel_off
= htons(0x1f);
217 csp
->sp_e_d_tov
= htonl(lport
->e_d_tov
);
219 cp
->cp_rdfs
= htons((u16
) lport
->mfs
);
220 cp
->cp_con_seq
= htons(255);
225 * fc_flogi_fill - Fill in a flogi request frame.
227 static inline void fc_flogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
229 struct fc_els_csp
*sp
;
230 struct fc_els_cssp
*cp
;
231 struct fc_els_flogi
*flogi
;
233 flogi
= fc_frame_payload_get(fp
, sizeof(*flogi
));
234 memset(flogi
, 0, sizeof(*flogi
));
235 flogi
->fl_cmd
= (u8
) ELS_FLOGI
;
236 put_unaligned_be64(lport
->wwpn
, &flogi
->fl_wwpn
);
237 put_unaligned_be64(lport
->wwnn
, &flogi
->fl_wwnn
);
239 sp
->sp_hi_ver
= 0x20;
240 sp
->sp_lo_ver
= 0x20;
241 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
242 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
243 cp
= &flogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
244 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
245 if (lport
->does_npiv
)
246 sp
->sp_features
= htons(FC_SP_FT_NPIV
);
250 * fc_fdisc_fill - Fill in a fdisc request frame.
252 static inline void fc_fdisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
254 struct fc_els_csp
*sp
;
255 struct fc_els_cssp
*cp
;
256 struct fc_els_flogi
*fdisc
;
258 fdisc
= fc_frame_payload_get(fp
, sizeof(*fdisc
));
259 memset(fdisc
, 0, sizeof(*fdisc
));
260 fdisc
->fl_cmd
= (u8
) ELS_FDISC
;
261 put_unaligned_be64(lport
->wwpn
, &fdisc
->fl_wwpn
);
262 put_unaligned_be64(lport
->wwnn
, &fdisc
->fl_wwnn
);
264 sp
->sp_hi_ver
= 0x20;
265 sp
->sp_lo_ver
= 0x20;
266 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
267 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
268 cp
= &fdisc
->fl_cssp
[3 - 1]; /* class 3 parameters */
269 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
273 * fc_logo_fill - Fill in a logo request frame.
275 static inline void fc_logo_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
277 struct fc_els_logo
*logo
;
279 logo
= fc_frame_payload_get(fp
, sizeof(*logo
));
280 memset(logo
, 0, sizeof(*logo
));
281 logo
->fl_cmd
= ELS_LOGO
;
282 hton24(logo
->fl_n_port_id
, lport
->port_id
);
283 logo
->fl_n_port_wwn
= htonll(lport
->wwpn
);
287 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
289 static inline void fc_rtv_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
291 struct fc_els_rtv
*rtv
;
293 rtv
= fc_frame_payload_get(fp
, sizeof(*rtv
));
294 memset(rtv
, 0, sizeof(*rtv
));
295 rtv
->rtv_cmd
= ELS_RTV
;
299 * fc_rec_fill - Fill in rec request frame
301 static inline void fc_rec_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
303 struct fc_els_rec
*rec
;
304 struct fc_exch
*ep
= fc_seq_exch(fr_seq(fp
));
306 rec
= fc_frame_payload_get(fp
, sizeof(*rec
));
307 memset(rec
, 0, sizeof(*rec
));
308 rec
->rec_cmd
= ELS_REC
;
309 hton24(rec
->rec_s_id
, lport
->port_id
);
310 rec
->rec_ox_id
= htons(ep
->oxid
);
311 rec
->rec_rx_id
= htons(ep
->rxid
);
315 * fc_prli_fill - Fill in prli request frame
317 static inline void fc_prli_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
320 struct fc_els_prli prli
;
321 struct fc_els_spp spp
;
324 pp
= fc_frame_payload_get(fp
, sizeof(*pp
));
325 memset(pp
, 0, sizeof(*pp
));
326 pp
->prli
.prli_cmd
= ELS_PRLI
;
327 pp
->prli
.prli_spp_len
= sizeof(struct fc_els_spp
);
328 pp
->prli
.prli_len
= htons(sizeof(*pp
));
329 pp
->spp
.spp_type
= FC_TYPE_FCP
;
330 pp
->spp
.spp_flags
= FC_SPP_EST_IMG_PAIR
;
331 pp
->spp
.spp_params
= htonl(lport
->service_params
);
335 * fc_scr_fill - Fill in a scr request frame.
337 static inline void fc_scr_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
339 struct fc_els_scr
*scr
;
341 scr
= fc_frame_payload_get(fp
, sizeof(*scr
));
342 memset(scr
, 0, sizeof(*scr
));
343 scr
->scr_cmd
= ELS_SCR
;
344 scr
->scr_reg_func
= ELS_SCRF_FULL
;
348 * fc_els_fill - Fill in an ELS request frame
350 static inline int fc_els_fill(struct fc_lport
*lport
,
352 struct fc_frame
*fp
, unsigned int op
,
353 enum fc_rctl
*r_ctl
, enum fc_fh_type
*fh_type
)
357 fc_adisc_fill(lport
, fp
);
361 fc_plogi_fill(lport
, fp
, ELS_PLOGI
);
365 fc_flogi_fill(lport
, fp
);
369 fc_fdisc_fill(lport
, fp
);
373 fc_logo_fill(lport
, fp
);
377 fc_rtv_fill(lport
, fp
);
381 fc_rec_fill(lport
, fp
);
385 fc_prli_fill(lport
, fp
);
389 fc_scr_fill(lport
, fp
);
396 *r_ctl
= FC_RCTL_ELS_REQ
;
397 *fh_type
= FC_TYPE_ELS
;
400 #endif /* _FC_ENCODE_H_ */