diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_fcbuild.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_fcbuild.c | 1410 |
1 files changed, 1410 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c new file mode 100644 index 000000000000..b7d2657ca82a --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcbuild.c | |||
@@ -0,0 +1,1410 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved | ||
4 | * www.brocade.com | ||
5 | * | ||
6 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
10 | * published by the Free Software Foundation | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | /* | ||
18 | * fcbuild.c - FC link service frame building and parsing routines | ||
19 | */ | ||
20 | |||
21 | #include "bfa_os_inc.h" | ||
22 | #include "bfa_fcbuild.h" | ||
23 | |||
24 | /* | ||
25 | * static build functions | ||
26 | */ | ||
27 | static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
28 | u16 ox_id); | ||
29 | static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
30 | u16 ox_id); | ||
31 | static struct fchs_s fc_els_req_tmpl; | ||
32 | static struct fchs_s fc_els_rsp_tmpl; | ||
33 | static struct fchs_s fc_bls_req_tmpl; | ||
34 | static struct fchs_s fc_bls_rsp_tmpl; | ||
35 | static struct fc_ba_acc_s ba_acc_tmpl; | ||
36 | static struct fc_logi_s plogi_tmpl; | ||
37 | static struct fc_prli_s prli_tmpl; | ||
38 | static struct fc_rrq_s rrq_tmpl; | ||
39 | static struct fchs_s fcp_fchs_tmpl; | ||
40 | |||
41 | void | ||
42 | fcbuild_init(void) | ||
43 | { | ||
44 | /* | ||
45 | * fc_els_req_tmpl | ||
46 | */ | ||
47 | fc_els_req_tmpl.routing = FC_RTG_EXT_LINK; | ||
48 | fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST; | ||
49 | fc_els_req_tmpl.type = FC_TYPE_ELS; | ||
50 | fc_els_req_tmpl.f_ctl = | ||
51 | bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | | ||
52 | FCTL_SI_XFER); | ||
53 | fc_els_req_tmpl.rx_id = FC_RXID_ANY; | ||
54 | |||
55 | /* | ||
56 | * fc_els_rsp_tmpl | ||
57 | */ | ||
58 | fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK; | ||
59 | fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY; | ||
60 | fc_els_rsp_tmpl.type = FC_TYPE_ELS; | ||
61 | fc_els_rsp_tmpl.f_ctl = | ||
62 | bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | | ||
63 | FCTL_END_SEQ | FCTL_SI_XFER); | ||
64 | fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; | ||
65 | |||
66 | /* | ||
67 | * fc_bls_req_tmpl | ||
68 | */ | ||
69 | fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK; | ||
70 | fc_bls_req_tmpl.type = FC_TYPE_BLS; | ||
71 | fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); | ||
72 | fc_bls_req_tmpl.rx_id = FC_RXID_ANY; | ||
73 | |||
74 | /* | ||
75 | * fc_bls_rsp_tmpl | ||
76 | */ | ||
77 | fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK; | ||
78 | fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC; | ||
79 | fc_bls_rsp_tmpl.type = FC_TYPE_BLS; | ||
80 | fc_bls_rsp_tmpl.f_ctl = | ||
81 | bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | | ||
82 | FCTL_END_SEQ | FCTL_SI_XFER); | ||
83 | fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; | ||
84 | |||
85 | /* | ||
86 | * ba_acc_tmpl | ||
87 | */ | ||
88 | ba_acc_tmpl.seq_id_valid = 0; | ||
89 | ba_acc_tmpl.low_seq_cnt = 0; | ||
90 | ba_acc_tmpl.high_seq_cnt = 0xFFFF; | ||
91 | |||
92 | /* | ||
93 | * plogi_tmpl | ||
94 | */ | ||
95 | plogi_tmpl.csp.verhi = FC_PH_VER_PH_3; | ||
96 | plogi_tmpl.csp.verlo = FC_PH_VER_4_3; | ||
97 | plogi_tmpl.csp.bbcred = bfa_os_htons(0x0004); | ||
98 | plogi_tmpl.csp.ciro = 0x1; | ||
99 | plogi_tmpl.csp.cisc = 0x0; | ||
100 | plogi_tmpl.csp.altbbcred = 0x0; | ||
101 | plogi_tmpl.csp.conseq = bfa_os_htons(0x00FF); | ||
102 | plogi_tmpl.csp.ro_bitmap = bfa_os_htons(0x0002); | ||
103 | plogi_tmpl.csp.e_d_tov = bfa_os_htonl(2000); | ||
104 | |||
105 | plogi_tmpl.class3.class_valid = 1; | ||
106 | plogi_tmpl.class3.sequential = 1; | ||
107 | plogi_tmpl.class3.conseq = 0xFF; | ||
108 | plogi_tmpl.class3.ospx = 1; | ||
109 | |||
110 | /* | ||
111 | * prli_tmpl | ||
112 | */ | ||
113 | prli_tmpl.command = FC_ELS_PRLI; | ||
114 | prli_tmpl.pglen = 0x10; | ||
115 | prli_tmpl.pagebytes = bfa_os_htons(0x0014); | ||
116 | prli_tmpl.parampage.type = FC_TYPE_FCP; | ||
117 | prli_tmpl.parampage.imagepair = 1; | ||
118 | prli_tmpl.parampage.servparams.rxrdisab = 1; | ||
119 | |||
120 | /* | ||
121 | * rrq_tmpl | ||
122 | */ | ||
123 | rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ; | ||
124 | |||
125 | /* | ||
126 | * fcp_struct fchs_s mpl | ||
127 | */ | ||
128 | fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA; | ||
129 | fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD; | ||
130 | fcp_fchs_tmpl.type = FC_TYPE_FCP; | ||
131 | fcp_fchs_tmpl.f_ctl = | ||
132 | bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); | ||
133 | fcp_fchs_tmpl.seq_id = 1; | ||
134 | fcp_fchs_tmpl.rx_id = FC_RXID_ANY; | ||
135 | } | ||
136 | |||
137 | static void | ||
138 | fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id) | ||
139 | { | ||
140 | bfa_os_memset(fchs, 0, sizeof(struct fchs_s)); | ||
141 | |||
142 | fchs->routing = FC_RTG_FC4_DEV_DATA; | ||
143 | fchs->cat_info = FC_CAT_UNSOLICIT_CTRL; | ||
144 | fchs->type = FC_TYPE_SERVICES; | ||
145 | fchs->f_ctl = | ||
146 | bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | | ||
147 | FCTL_SI_XFER); | ||
148 | fchs->rx_id = FC_RXID_ANY; | ||
149 | fchs->d_id = (d_id); | ||
150 | fchs->s_id = (s_id); | ||
151 | fchs->ox_id = bfa_os_htons(ox_id); | ||
152 | |||
153 | /** | ||
154 | * @todo no need to set ox_id for request | ||
155 | * no need to set rx_id for response | ||
156 | */ | ||
157 | } | ||
158 | |||
159 | void | ||
160 | fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) | ||
161 | { | ||
162 | bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s)); | ||
163 | fchs->d_id = (d_id); | ||
164 | fchs->s_id = (s_id); | ||
165 | fchs->ox_id = bfa_os_htons(ox_id); | ||
166 | } | ||
167 | |||
168 | static void | ||
169 | fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) | ||
170 | { | ||
171 | bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s)); | ||
172 | fchs->d_id = d_id; | ||
173 | fchs->s_id = s_id; | ||
174 | fchs->ox_id = ox_id; | ||
175 | } | ||
176 | |||
177 | enum fc_parse_status | ||
178 | fc_els_rsp_parse(struct fchs_s *fchs, int len) | ||
179 | { | ||
180 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
181 | struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd; | ||
182 | |||
183 | len = len; | ||
184 | |||
185 | switch (els_cmd->els_code) { | ||
186 | case FC_ELS_LS_RJT: | ||
187 | if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY) | ||
188 | return FC_PARSE_BUSY; | ||
189 | else | ||
190 | return FC_PARSE_FAILURE; | ||
191 | |||
192 | case FC_ELS_ACC: | ||
193 | return FC_PARSE_OK; | ||
194 | } | ||
195 | return FC_PARSE_OK; | ||
196 | } | ||
197 | |||
198 | static void | ||
199 | fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) | ||
200 | { | ||
201 | bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s)); | ||
202 | fchs->d_id = d_id; | ||
203 | fchs->s_id = s_id; | ||
204 | fchs->ox_id = ox_id; | ||
205 | } | ||
206 | |||
207 | static u16 | ||
208 | fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
209 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
210 | u16 pdu_size, u8 els_code) | ||
211 | { | ||
212 | struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); | ||
213 | |||
214 | bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
215 | |||
216 | plogi->els_cmd.els_code = els_code; | ||
217 | if (els_code == FC_ELS_PLOGI) | ||
218 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
219 | else | ||
220 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
221 | |||
222 | plogi->csp.rxsz = plogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
223 | |||
224 | bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t)); | ||
225 | bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); | ||
226 | |||
227 | return sizeof(struct fc_logi_s); | ||
228 | } | ||
229 | |||
230 | u16 | ||
231 | fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
232 | u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, | ||
233 | u8 set_npiv, u8 set_auth, u16 local_bb_credits) | ||
234 | { | ||
235 | u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); | ||
236 | u32 *vvl_info; | ||
237 | |||
238 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
239 | |||
240 | flogi->els_cmd.els_code = FC_ELS_FLOGI; | ||
241 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
242 | |||
243 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
244 | flogi->port_name = port_name; | ||
245 | flogi->node_name = node_name; | ||
246 | |||
247 | /* | ||
248 | * Set the NPIV Capability Bit ( word 1, bit 31) of Common | ||
249 | * Service Parameters. | ||
250 | */ | ||
251 | flogi->csp.ciro = set_npiv; | ||
252 | |||
253 | /* set AUTH capability */ | ||
254 | flogi->csp.security = set_auth; | ||
255 | |||
256 | flogi->csp.bbcred = bfa_os_htons(local_bb_credits); | ||
257 | |||
258 | /* Set brcd token in VVL */ | ||
259 | vvl_info = (u32 *)&flogi->vvl[0]; | ||
260 | |||
261 | /* set the flag to indicate the presence of VVL */ | ||
262 | flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */ | ||
263 | vvl_info[0] = bfa_os_htonl(FLOGI_VVL_BRCD); | ||
264 | |||
265 | return sizeof(struct fc_logi_s); | ||
266 | } | ||
267 | |||
268 | u16 | ||
269 | fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
270 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
271 | u16 pdu_size, u16 local_bb_credits) | ||
272 | { | ||
273 | u32 d_id = 0; | ||
274 | |||
275 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
276 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
277 | |||
278 | flogi->els_cmd.els_code = FC_ELS_ACC; | ||
279 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
280 | flogi->port_name = port_name; | ||
281 | flogi->node_name = node_name; | ||
282 | |||
283 | flogi->csp.bbcred = bfa_os_htons(local_bb_credits); | ||
284 | |||
285 | return sizeof(struct fc_logi_s); | ||
286 | } | ||
287 | |||
288 | u16 | ||
289 | fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
290 | u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size) | ||
291 | { | ||
292 | u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); | ||
293 | |||
294 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
295 | |||
296 | flogi->els_cmd.els_code = FC_ELS_FDISC; | ||
297 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
298 | |||
299 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
300 | flogi->port_name = port_name; | ||
301 | flogi->node_name = node_name; | ||
302 | |||
303 | return sizeof(struct fc_logi_s); | ||
304 | } | ||
305 | |||
306 | u16 | ||
307 | fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
308 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
309 | u16 pdu_size) | ||
310 | { | ||
311 | return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, | ||
312 | node_name, pdu_size, FC_ELS_PLOGI); | ||
313 | } | ||
314 | |||
315 | u16 | ||
316 | fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
317 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
318 | u16 pdu_size) | ||
319 | { | ||
320 | return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, | ||
321 | node_name, pdu_size, FC_ELS_ACC); | ||
322 | } | ||
323 | |||
324 | enum fc_parse_status | ||
325 | fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) | ||
326 | { | ||
327 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
328 | struct fc_logi_s *plogi; | ||
329 | struct fc_ls_rjt_s *ls_rjt; | ||
330 | |||
331 | switch (els_cmd->els_code) { | ||
332 | case FC_ELS_LS_RJT: | ||
333 | ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1); | ||
334 | if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY) | ||
335 | return FC_PARSE_BUSY; | ||
336 | else | ||
337 | return FC_PARSE_FAILURE; | ||
338 | case FC_ELS_ACC: | ||
339 | plogi = (struct fc_logi_s *) (fchs + 1); | ||
340 | if (len < sizeof(struct fc_logi_s)) | ||
341 | return FC_PARSE_FAILURE; | ||
342 | |||
343 | if (!wwn_is_equal(plogi->port_name, port_name)) | ||
344 | return FC_PARSE_FAILURE; | ||
345 | |||
346 | if (!plogi->class3.class_valid) | ||
347 | return FC_PARSE_FAILURE; | ||
348 | |||
349 | if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ)) | ||
350 | return FC_PARSE_FAILURE; | ||
351 | |||
352 | return FC_PARSE_OK; | ||
353 | default: | ||
354 | return FC_PARSE_FAILURE; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | enum fc_parse_status | ||
359 | fc_plogi_parse(struct fchs_s *fchs) | ||
360 | { | ||
361 | struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1); | ||
362 | |||
363 | if (plogi->class3.class_valid != 1) | ||
364 | return FC_PARSE_FAILURE; | ||
365 | |||
366 | if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ) | ||
367 | || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ) | ||
368 | || (plogi->class3.rxsz == 0)) | ||
369 | return FC_PARSE_FAILURE; | ||
370 | |||
371 | return FC_PARSE_OK; | ||
372 | } | ||
373 | |||
374 | u16 | ||
375 | fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
376 | u16 ox_id) | ||
377 | { | ||
378 | struct fc_prli_s *prli = (struct fc_prli_s *) (pld); | ||
379 | |||
380 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
381 | bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); | ||
382 | |||
383 | prli->command = FC_ELS_PRLI; | ||
384 | prli->parampage.servparams.initiator = 1; | ||
385 | prli->parampage.servparams.retry = 1; | ||
386 | prli->parampage.servparams.rec_support = 1; | ||
387 | prli->parampage.servparams.task_retry_id = 0; | ||
388 | prli->parampage.servparams.confirm = 1; | ||
389 | |||
390 | return sizeof(struct fc_prli_s); | ||
391 | } | ||
392 | |||
393 | u16 | ||
394 | fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
395 | u16 ox_id, enum bfa_lport_role role) | ||
396 | { | ||
397 | struct fc_prli_s *prli = (struct fc_prli_s *) (pld); | ||
398 | |||
399 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
400 | bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); | ||
401 | |||
402 | prli->command = FC_ELS_ACC; | ||
403 | |||
404 | prli->parampage.servparams.initiator = 1; | ||
405 | |||
406 | prli->parampage.rspcode = FC_PRLI_ACC_XQTD; | ||
407 | |||
408 | return sizeof(struct fc_prli_s); | ||
409 | } | ||
410 | |||
411 | enum fc_parse_status | ||
412 | fc_prli_rsp_parse(struct fc_prli_s *prli, int len) | ||
413 | { | ||
414 | if (len < sizeof(struct fc_prli_s)) | ||
415 | return FC_PARSE_FAILURE; | ||
416 | |||
417 | if (prli->command != FC_ELS_ACC) | ||
418 | return FC_PARSE_FAILURE; | ||
419 | |||
420 | if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD) | ||
421 | && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG)) | ||
422 | return FC_PARSE_FAILURE; | ||
423 | |||
424 | if (prli->parampage.servparams.target != 1) | ||
425 | return FC_PARSE_FAILURE; | ||
426 | |||
427 | return FC_PARSE_OK; | ||
428 | } | ||
429 | |||
430 | enum fc_parse_status | ||
431 | fc_prli_parse(struct fc_prli_s *prli) | ||
432 | { | ||
433 | if (prli->parampage.type != FC_TYPE_FCP) | ||
434 | return FC_PARSE_FAILURE; | ||
435 | |||
436 | if (!prli->parampage.imagepair) | ||
437 | return FC_PARSE_FAILURE; | ||
438 | |||
439 | if (!prli->parampage.servparams.initiator) | ||
440 | return FC_PARSE_FAILURE; | ||
441 | |||
442 | return FC_PARSE_OK; | ||
443 | } | ||
444 | |||
445 | u16 | ||
446 | fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, | ||
447 | u16 ox_id, wwn_t port_name) | ||
448 | { | ||
449 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
450 | |||
451 | bfa_os_memset(logo, '\0', sizeof(struct fc_logo_s)); | ||
452 | logo->els_cmd.els_code = FC_ELS_LOGO; | ||
453 | logo->nport_id = (s_id); | ||
454 | logo->orig_port_name = port_name; | ||
455 | |||
456 | return sizeof(struct fc_logo_s); | ||
457 | } | ||
458 | |||
459 | static u16 | ||
460 | fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
461 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
462 | wwn_t node_name, u8 els_code) | ||
463 | { | ||
464 | bfa_os_memset(adisc, '\0', sizeof(struct fc_adisc_s)); | ||
465 | |||
466 | adisc->els_cmd.els_code = els_code; | ||
467 | |||
468 | if (els_code == FC_ELS_ADISC) | ||
469 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
470 | else | ||
471 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
472 | |||
473 | adisc->orig_HA = 0; | ||
474 | adisc->orig_port_name = port_name; | ||
475 | adisc->orig_node_name = node_name; | ||
476 | adisc->nport_id = (s_id); | ||
477 | |||
478 | return sizeof(struct fc_adisc_s); | ||
479 | } | ||
480 | |||
481 | u16 | ||
482 | fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
483 | u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name) | ||
484 | { | ||
485 | return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, | ||
486 | node_name, FC_ELS_ADISC); | ||
487 | } | ||
488 | |||
489 | u16 | ||
490 | fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
491 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
492 | wwn_t node_name) | ||
493 | { | ||
494 | return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, | ||
495 | node_name, FC_ELS_ACC); | ||
496 | } | ||
497 | |||
498 | enum fc_parse_status | ||
499 | fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name, | ||
500 | wwn_t node_name) | ||
501 | { | ||
502 | |||
503 | if (len < sizeof(struct fc_adisc_s)) | ||
504 | return FC_PARSE_FAILURE; | ||
505 | |||
506 | if (adisc->els_cmd.els_code != FC_ELS_ACC) | ||
507 | return FC_PARSE_FAILURE; | ||
508 | |||
509 | if (!wwn_is_equal(adisc->orig_port_name, port_name)) | ||
510 | return FC_PARSE_FAILURE; | ||
511 | |||
512 | return FC_PARSE_OK; | ||
513 | } | ||
514 | |||
515 | enum fc_parse_status | ||
516 | fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name, | ||
517 | wwn_t port_name) | ||
518 | { | ||
519 | struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld; | ||
520 | |||
521 | if (adisc->els_cmd.els_code != FC_ELS_ACC) | ||
522 | return FC_PARSE_FAILURE; | ||
523 | |||
524 | if ((adisc->nport_id == (host_dap)) | ||
525 | && wwn_is_equal(adisc->orig_port_name, port_name) | ||
526 | && wwn_is_equal(adisc->orig_node_name, node_name)) | ||
527 | return FC_PARSE_OK; | ||
528 | |||
529 | return FC_PARSE_FAILURE; | ||
530 | } | ||
531 | |||
532 | enum fc_parse_status | ||
533 | fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name) | ||
534 | { | ||
535 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
536 | |||
537 | if (pdisc->class3.class_valid != 1) | ||
538 | return FC_PARSE_FAILURE; | ||
539 | |||
540 | if ((bfa_os_ntohs(pdisc->class3.rxsz) < | ||
541 | (FC_MIN_PDUSZ - sizeof(struct fchs_s))) | ||
542 | || (pdisc->class3.rxsz == 0)) | ||
543 | return FC_PARSE_FAILURE; | ||
544 | |||
545 | if (!wwn_is_equal(pdisc->port_name, port_name)) | ||
546 | return FC_PARSE_FAILURE; | ||
547 | |||
548 | if (!wwn_is_equal(pdisc->node_name, node_name)) | ||
549 | return FC_PARSE_FAILURE; | ||
550 | |||
551 | return FC_PARSE_OK; | ||
552 | } | ||
553 | |||
554 | u16 | ||
555 | fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) | ||
556 | { | ||
557 | bfa_os_memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s)); | ||
558 | fchs->cat_info = FC_CAT_ABTS; | ||
559 | fchs->d_id = (d_id); | ||
560 | fchs->s_id = (s_id); | ||
561 | fchs->ox_id = bfa_os_htons(ox_id); | ||
562 | |||
563 | return sizeof(struct fchs_s); | ||
564 | } | ||
565 | |||
566 | enum fc_parse_status | ||
567 | fc_abts_rsp_parse(struct fchs_s *fchs, int len) | ||
568 | { | ||
569 | if ((fchs->cat_info == FC_CAT_BA_ACC) | ||
570 | || (fchs->cat_info == FC_CAT_BA_RJT)) | ||
571 | return FC_PARSE_OK; | ||
572 | |||
573 | return FC_PARSE_FAILURE; | ||
574 | } | ||
575 | |||
576 | u16 | ||
577 | fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id, | ||
578 | u16 ox_id, u16 rrq_oxid) | ||
579 | { | ||
580 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
581 | |||
582 | /* | ||
583 | * build rrq payload | ||
584 | */ | ||
585 | bfa_os_memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s)); | ||
586 | rrq->s_id = (s_id); | ||
587 | rrq->ox_id = bfa_os_htons(rrq_oxid); | ||
588 | rrq->rx_id = FC_RXID_ANY; | ||
589 | |||
590 | return sizeof(struct fc_rrq_s); | ||
591 | } | ||
592 | |||
593 | u16 | ||
594 | fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
595 | u16 ox_id) | ||
596 | { | ||
597 | struct fc_els_cmd_s *acc = pld; | ||
598 | |||
599 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
600 | |||
601 | bfa_os_memset(acc, 0, sizeof(struct fc_els_cmd_s)); | ||
602 | acc->els_code = FC_ELS_ACC; | ||
603 | |||
604 | return sizeof(struct fc_els_cmd_s); | ||
605 | } | ||
606 | |||
607 | u16 | ||
608 | fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, | ||
609 | u32 s_id, u16 ox_id, u8 reason_code, | ||
610 | u8 reason_code_expl) | ||
611 | { | ||
612 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
613 | bfa_os_memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s)); | ||
614 | |||
615 | ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT; | ||
616 | ls_rjt->reason_code = reason_code; | ||
617 | ls_rjt->reason_code_expl = reason_code_expl; | ||
618 | ls_rjt->vendor_unique = 0x00; | ||
619 | |||
620 | return sizeof(struct fc_ls_rjt_s); | ||
621 | } | ||
622 | |||
623 | u16 | ||
624 | fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, | ||
625 | u32 s_id, u16 ox_id, u16 rx_id) | ||
626 | { | ||
627 | fc_bls_rsp_build(fchs, d_id, s_id, ox_id); | ||
628 | |||
629 | bfa_os_memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s)); | ||
630 | |||
631 | fchs->rx_id = rx_id; | ||
632 | |||
633 | ba_acc->ox_id = fchs->ox_id; | ||
634 | ba_acc->rx_id = fchs->rx_id; | ||
635 | |||
636 | return sizeof(struct fc_ba_acc_s); | ||
637 | } | ||
638 | |||
639 | u16 | ||
640 | fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id, | ||
641 | u32 s_id, u16 ox_id) | ||
642 | { | ||
643 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
644 | bfa_os_memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); | ||
645 | els_cmd->els_code = FC_ELS_ACC; | ||
646 | |||
647 | return sizeof(struct fc_els_cmd_s); | ||
648 | } | ||
649 | |||
650 | int | ||
651 | fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code) | ||
652 | { | ||
653 | int num_pages = 0; | ||
654 | struct fc_prlo_s *prlo; | ||
655 | struct fc_tprlo_s *tprlo; | ||
656 | |||
657 | if (els_code == FC_ELS_PRLO) { | ||
658 | prlo = (struct fc_prlo_s *) (fc_frame + 1); | ||
659 | num_pages = (bfa_os_ntohs(prlo->payload_len) - 4) / 16; | ||
660 | } else { | ||
661 | tprlo = (struct fc_tprlo_s *) (fc_frame + 1); | ||
662 | num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16; | ||
663 | } | ||
664 | return num_pages; | ||
665 | } | ||
666 | |||
667 | u16 | ||
668 | fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, | ||
669 | u32 d_id, u32 s_id, u16 ox_id, int num_pages) | ||
670 | { | ||
671 | int page; | ||
672 | |||
673 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
674 | |||
675 | bfa_os_memset(tprlo_acc, 0, (num_pages * 16) + 4); | ||
676 | tprlo_acc->command = FC_ELS_ACC; | ||
677 | |||
678 | tprlo_acc->page_len = 0x10; | ||
679 | tprlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
680 | |||
681 | for (page = 0; page < num_pages; page++) { | ||
682 | tprlo_acc->tprlo_acc_params[page].opa_valid = 0; | ||
683 | tprlo_acc->tprlo_acc_params[page].rpa_valid = 0; | ||
684 | tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; | ||
685 | tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0; | ||
686 | tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0; | ||
687 | } | ||
688 | return bfa_os_ntohs(tprlo_acc->payload_len); | ||
689 | } | ||
690 | |||
691 | u16 | ||
692 | fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id, | ||
693 | u32 s_id, u16 ox_id, int num_pages) | ||
694 | { | ||
695 | int page; | ||
696 | |||
697 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
698 | |||
699 | bfa_os_memset(prlo_acc, 0, (num_pages * 16) + 4); | ||
700 | prlo_acc->command = FC_ELS_ACC; | ||
701 | prlo_acc->page_len = 0x10; | ||
702 | prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
703 | |||
704 | for (page = 0; page < num_pages; page++) { | ||
705 | prlo_acc->prlo_acc_params[page].opa_valid = 0; | ||
706 | prlo_acc->prlo_acc_params[page].rpa_valid = 0; | ||
707 | prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; | ||
708 | prlo_acc->prlo_acc_params[page].orig_process_assc = 0; | ||
709 | prlo_acc->prlo_acc_params[page].resp_process_assc = 0; | ||
710 | } | ||
711 | |||
712 | return bfa_os_ntohs(prlo_acc->payload_len); | ||
713 | } | ||
714 | |||
715 | u16 | ||
716 | fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id, | ||
717 | u32 s_id, u16 ox_id, u32 data_format) | ||
718 | { | ||
719 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
720 | |||
721 | bfa_os_memset(rnid, 0, sizeof(struct fc_rnid_cmd_s)); | ||
722 | |||
723 | rnid->els_cmd.els_code = FC_ELS_RNID; | ||
724 | rnid->node_id_data_format = data_format; | ||
725 | |||
726 | return sizeof(struct fc_rnid_cmd_s); | ||
727 | } | ||
728 | |||
729 | u16 | ||
730 | fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, | ||
731 | u32 s_id, u16 ox_id, u32 data_format, | ||
732 | struct fc_rnid_common_id_data_s *common_id_data, | ||
733 | struct fc_rnid_general_topology_data_s *gen_topo_data) | ||
734 | { | ||
735 | bfa_os_memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s)); | ||
736 | |||
737 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
738 | |||
739 | rnid_acc->els_cmd.els_code = FC_ELS_ACC; | ||
740 | rnid_acc->node_id_data_format = data_format; | ||
741 | rnid_acc->common_id_data_length = | ||
742 | sizeof(struct fc_rnid_common_id_data_s); | ||
743 | rnid_acc->common_id_data = *common_id_data; | ||
744 | |||
745 | if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { | ||
746 | rnid_acc->specific_id_data_length = | ||
747 | sizeof(struct fc_rnid_general_topology_data_s); | ||
748 | bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data); | ||
749 | return sizeof(struct fc_rnid_acc_s); | ||
750 | } else { | ||
751 | return sizeof(struct fc_rnid_acc_s) - | ||
752 | sizeof(struct fc_rnid_general_topology_data_s); | ||
753 | } | ||
754 | |||
755 | } | ||
756 | |||
757 | u16 | ||
758 | fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id, | ||
759 | u32 s_id, u16 ox_id) | ||
760 | { | ||
761 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
762 | |||
763 | bfa_os_memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s)); | ||
764 | |||
765 | rpsc->els_cmd.els_code = FC_ELS_RPSC; | ||
766 | return sizeof(struct fc_rpsc_cmd_s); | ||
767 | } | ||
768 | |||
769 | u16 | ||
770 | fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id, | ||
771 | u32 s_id, u32 *pid_list, u16 npids) | ||
772 | { | ||
773 | u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id)); | ||
774 | int i = 0; | ||
775 | |||
776 | fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0); | ||
777 | |||
778 | bfa_os_memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); | ||
779 | |||
780 | rpsc2->els_cmd.els_code = FC_ELS_RPSC; | ||
781 | rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN); | ||
782 | rpsc2->num_pids = bfa_os_htons(npids); | ||
783 | for (i = 0; i < npids; i++) | ||
784 | rpsc2->pid_list[i].pid = pid_list[i]; | ||
785 | |||
786 | return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32))); | ||
787 | } | ||
788 | |||
789 | u16 | ||
790 | fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, | ||
791 | u32 d_id, u32 s_id, u16 ox_id, | ||
792 | struct fc_rpsc_speed_info_s *oper_speed) | ||
793 | { | ||
794 | bfa_os_memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); | ||
795 | |||
796 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
797 | |||
798 | rpsc_acc->command = FC_ELS_ACC; | ||
799 | rpsc_acc->num_entries = bfa_os_htons(1); | ||
800 | |||
801 | rpsc_acc->speed_info[0].port_speed_cap = | ||
802 | bfa_os_htons(oper_speed->port_speed_cap); | ||
803 | |||
804 | rpsc_acc->speed_info[0].port_op_speed = | ||
805 | bfa_os_htons(oper_speed->port_op_speed); | ||
806 | |||
807 | return sizeof(struct fc_rpsc_acc_s); | ||
808 | } | ||
809 | |||
810 | /* | ||
811 | * TBD - | ||
812 | * . get rid of unnecessary memsets | ||
813 | */ | ||
814 | |||
815 | u16 | ||
816 | fc_logo_rsp_parse(struct fchs_s *fchs, int len) | ||
817 | { | ||
818 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
819 | |||
820 | len = len; | ||
821 | if (els_cmd->els_code != FC_ELS_ACC) | ||
822 | return FC_PARSE_FAILURE; | ||
823 | |||
824 | return FC_PARSE_OK; | ||
825 | } | ||
826 | |||
827 | u16 | ||
828 | fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, | ||
829 | wwn_t port_name, wwn_t node_name, u16 pdu_size) | ||
830 | { | ||
831 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
832 | |||
833 | bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
834 | |||
835 | pdisc->els_cmd.els_code = FC_ELS_PDISC; | ||
836 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
837 | |||
838 | pdisc->csp.rxsz = pdisc->class3.rxsz = bfa_os_htons(pdu_size); | ||
839 | pdisc->port_name = port_name; | ||
840 | pdisc->node_name = node_name; | ||
841 | |||
842 | return sizeof(struct fc_logi_s); | ||
843 | } | ||
844 | |||
845 | u16 | ||
846 | fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) | ||
847 | { | ||
848 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
849 | |||
850 | if (len < sizeof(struct fc_logi_s)) | ||
851 | return FC_PARSE_LEN_INVAL; | ||
852 | |||
853 | if (pdisc->els_cmd.els_code != FC_ELS_ACC) | ||
854 | return FC_PARSE_ACC_INVAL; | ||
855 | |||
856 | if (!wwn_is_equal(pdisc->port_name, port_name)) | ||
857 | return FC_PARSE_PWWN_NOT_EQUAL; | ||
858 | |||
859 | if (!pdisc->class3.class_valid) | ||
860 | return FC_PARSE_NWWN_NOT_EQUAL; | ||
861 | |||
862 | if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ)) | ||
863 | return FC_PARSE_RXSZ_INVAL; | ||
864 | |||
865 | return FC_PARSE_OK; | ||
866 | } | ||
867 | |||
868 | u16 | ||
869 | fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, | ||
870 | int num_pages) | ||
871 | { | ||
872 | struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1); | ||
873 | int page; | ||
874 | |||
875 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
876 | bfa_os_memset(prlo, 0, (num_pages * 16) + 4); | ||
877 | prlo->command = FC_ELS_PRLO; | ||
878 | prlo->page_len = 0x10; | ||
879 | prlo->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
880 | |||
881 | for (page = 0; page < num_pages; page++) { | ||
882 | prlo->prlo_params[page].type = FC_TYPE_FCP; | ||
883 | prlo->prlo_params[page].opa_valid = 0; | ||
884 | prlo->prlo_params[page].rpa_valid = 0; | ||
885 | prlo->prlo_params[page].orig_process_assc = 0; | ||
886 | prlo->prlo_params[page].resp_process_assc = 0; | ||
887 | } | ||
888 | |||
889 | return bfa_os_ntohs(prlo->payload_len); | ||
890 | } | ||
891 | |||
892 | u16 | ||
893 | fc_prlo_rsp_parse(struct fchs_s *fchs, int len) | ||
894 | { | ||
895 | struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1); | ||
896 | int num_pages = 0; | ||
897 | int page = 0; | ||
898 | |||
899 | len = len; | ||
900 | |||
901 | if (prlo->command != FC_ELS_ACC) | ||
902 | return FC_PARSE_FAILURE; | ||
903 | |||
904 | num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16; | ||
905 | |||
906 | for (page = 0; page < num_pages; page++) { | ||
907 | if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP) | ||
908 | return FC_PARSE_FAILURE; | ||
909 | |||
910 | if (prlo->prlo_acc_params[page].opa_valid != 0) | ||
911 | return FC_PARSE_FAILURE; | ||
912 | |||
913 | if (prlo->prlo_acc_params[page].rpa_valid != 0) | ||
914 | return FC_PARSE_FAILURE; | ||
915 | |||
916 | if (prlo->prlo_acc_params[page].orig_process_assc != 0) | ||
917 | return FC_PARSE_FAILURE; | ||
918 | |||
919 | if (prlo->prlo_acc_params[page].resp_process_assc != 0) | ||
920 | return FC_PARSE_FAILURE; | ||
921 | } | ||
922 | return FC_PARSE_OK; | ||
923 | |||
924 | } | ||
925 | |||
926 | u16 | ||
927 | fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, | ||
928 | int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id) | ||
929 | { | ||
930 | struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1); | ||
931 | int page; | ||
932 | |||
933 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
934 | bfa_os_memset(tprlo, 0, (num_pages * 16) + 4); | ||
935 | tprlo->command = FC_ELS_TPRLO; | ||
936 | tprlo->page_len = 0x10; | ||
937 | tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
938 | |||
939 | for (page = 0; page < num_pages; page++) { | ||
940 | tprlo->tprlo_params[page].type = FC_TYPE_FCP; | ||
941 | tprlo->tprlo_params[page].opa_valid = 0; | ||
942 | tprlo->tprlo_params[page].rpa_valid = 0; | ||
943 | tprlo->tprlo_params[page].orig_process_assc = 0; | ||
944 | tprlo->tprlo_params[page].resp_process_assc = 0; | ||
945 | if (tprlo_type == FC_GLOBAL_LOGO) { | ||
946 | tprlo->tprlo_params[page].global_process_logout = 1; | ||
947 | } else if (tprlo_type == FC_TPR_LOGO) { | ||
948 | tprlo->tprlo_params[page].tpo_nport_valid = 1; | ||
949 | tprlo->tprlo_params[page].tpo_nport_id = (tpr_id); | ||
950 | } | ||
951 | } | ||
952 | |||
953 | return bfa_os_ntohs(tprlo->payload_len); | ||
954 | } | ||
955 | |||
956 | u16 | ||
957 | fc_tprlo_rsp_parse(struct fchs_s *fchs, int len) | ||
958 | { | ||
959 | struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1); | ||
960 | int num_pages = 0; | ||
961 | int page = 0; | ||
962 | |||
963 | len = len; | ||
964 | |||
965 | if (tprlo->command != FC_ELS_ACC) | ||
966 | return FC_PARSE_ACC_INVAL; | ||
967 | |||
968 | num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16; | ||
969 | |||
970 | for (page = 0; page < num_pages; page++) { | ||
971 | if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP) | ||
972 | return FC_PARSE_NOT_FCP; | ||
973 | if (tprlo->tprlo_acc_params[page].opa_valid != 0) | ||
974 | return FC_PARSE_OPAFLAG_INVAL; | ||
975 | if (tprlo->tprlo_acc_params[page].rpa_valid != 0) | ||
976 | return FC_PARSE_RPAFLAG_INVAL; | ||
977 | if (tprlo->tprlo_acc_params[page].orig_process_assc != 0) | ||
978 | return FC_PARSE_OPA_INVAL; | ||
979 | if (tprlo->tprlo_acc_params[page].resp_process_assc != 0) | ||
980 | return FC_PARSE_RPA_INVAL; | ||
981 | } | ||
982 | return FC_PARSE_OK; | ||
983 | } | ||
984 | |||
985 | enum fc_parse_status | ||
986 | fc_rrq_rsp_parse(struct fchs_s *fchs, int len) | ||
987 | { | ||
988 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
989 | |||
990 | len = len; | ||
991 | if (els_cmd->els_code != FC_ELS_ACC) | ||
992 | return FC_PARSE_FAILURE; | ||
993 | |||
994 | return FC_PARSE_OK; | ||
995 | } | ||
996 | |||
997 | u16 | ||
998 | fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, | ||
999 | u32 reason_code, u32 reason_expl) | ||
1000 | { | ||
1001 | struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1); | ||
1002 | |||
1003 | fc_bls_rsp_build(fchs, d_id, s_id, ox_id); | ||
1004 | |||
1005 | fchs->cat_info = FC_CAT_BA_RJT; | ||
1006 | ba_rjt->reason_code = reason_code; | ||
1007 | ba_rjt->reason_expl = reason_expl; | ||
1008 | return sizeof(struct fc_ba_rjt_s); | ||
1009 | } | ||
1010 | |||
1011 | static void | ||
1012 | fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) | ||
1013 | { | ||
1014 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1015 | cthdr->rev_id = CT_GS3_REVISION; | ||
1016 | cthdr->gs_type = CT_GSTYPE_DIRSERVICE; | ||
1017 | cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER; | ||
1018 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1019 | } | ||
1020 | |||
1021 | static void | ||
1022 | fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) | ||
1023 | { | ||
1024 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1025 | cthdr->rev_id = CT_GS3_REVISION; | ||
1026 | cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; | ||
1027 | cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER; | ||
1028 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1029 | } | ||
1030 | |||
1031 | static void | ||
1032 | fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code, | ||
1033 | u8 sub_type) | ||
1034 | { | ||
1035 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1036 | cthdr->rev_id = CT_GS3_REVISION; | ||
1037 | cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; | ||
1038 | cthdr->gs_sub_type = sub_type; | ||
1039 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1040 | } | ||
1041 | |||
1042 | u16 | ||
1043 | fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1044 | wwn_t port_name) | ||
1045 | { | ||
1046 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1047 | struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1); | ||
1048 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1049 | |||
1050 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1051 | fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); | ||
1052 | |||
1053 | bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s)); | ||
1054 | gidpn->port_name = port_name; | ||
1055 | return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s); | ||
1056 | } | ||
1057 | |||
1058 | u16 | ||
1059 | fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1060 | u32 port_id) | ||
1061 | { | ||
1062 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1063 | fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); | ||
1064 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1065 | |||
1066 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1067 | fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); | ||
1068 | |||
1069 | bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t)); | ||
1070 | gpnid->dap = port_id; | ||
1071 | return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s); | ||
1072 | } | ||
1073 | |||
1074 | u16 | ||
1075 | fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1076 | u32 port_id) | ||
1077 | { | ||
1078 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1079 | fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1); | ||
1080 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1081 | |||
1082 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1083 | fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID); | ||
1084 | |||
1085 | bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t)); | ||
1086 | gnnid->dap = port_id; | ||
1087 | return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s); | ||
1088 | } | ||
1089 | |||
1090 | u16 | ||
1091 | fc_ct_rsp_parse(struct ct_hdr_s *cthdr) | ||
1092 | { | ||
1093 | if (bfa_os_ntohs(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) { | ||
1094 | if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY) | ||
1095 | return FC_PARSE_BUSY; | ||
1096 | else | ||
1097 | return FC_PARSE_FAILURE; | ||
1098 | } | ||
1099 | |||
1100 | return FC_PARSE_OK; | ||
1101 | } | ||
1102 | |||
1103 | u16 | ||
1104 | fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, | ||
1105 | u8 set_br_reg, u32 s_id, u16 ox_id) | ||
1106 | { | ||
1107 | u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); | ||
1108 | |||
1109 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
1110 | |||
1111 | bfa_os_memset(scr, 0, sizeof(struct fc_scr_s)); | ||
1112 | scr->command = FC_ELS_SCR; | ||
1113 | scr->reg_func = FC_SCR_REG_FUNC_FULL; | ||
1114 | if (set_br_reg) | ||
1115 | scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE; | ||
1116 | |||
1117 | return sizeof(struct fc_scr_s); | ||
1118 | } | ||
1119 | |||
1120 | u16 | ||
1121 | fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, | ||
1122 | u32 s_id, u16 ox_id) | ||
1123 | { | ||
1124 | u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); | ||
1125 | u16 payldlen; | ||
1126 | |||
1127 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
1128 | rscn->command = FC_ELS_RSCN; | ||
1129 | rscn->pagelen = sizeof(rscn->event[0]); | ||
1130 | |||
1131 | payldlen = sizeof(u32) + rscn->pagelen; | ||
1132 | rscn->payldlen = bfa_os_htons(payldlen); | ||
1133 | |||
1134 | rscn->event[0].format = FC_RSCN_FORMAT_PORTID; | ||
1135 | rscn->event[0].portid = s_id; | ||
1136 | |||
1137 | return sizeof(struct fc_rscn_pl_s); | ||
1138 | } | ||
1139 | |||
1140 | u16 | ||
1141 | fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1142 | enum bfa_lport_role roles) | ||
1143 | { | ||
1144 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1145 | struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); | ||
1146 | u32 type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1147 | u8 index; | ||
1148 | |||
1149 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1150 | fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); | ||
1151 | |||
1152 | bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); | ||
1153 | |||
1154 | rftid->dap = s_id; | ||
1155 | |||
1156 | /* By default, FCP FC4 Type is registered */ | ||
1157 | index = FC_TYPE_FCP >> 5; | ||
1158 | type_value = 1 << (FC_TYPE_FCP % 32); | ||
1159 | rftid->fc4_type[index] = bfa_os_htonl(type_value); | ||
1160 | |||
1161 | return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s); | ||
1162 | } | ||
1163 | |||
1164 | u16 | ||
1165 | fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1166 | u8 *fc4_bitmap, u32 bitmap_size) | ||
1167 | { | ||
1168 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1169 | struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); | ||
1170 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1171 | |||
1172 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1173 | fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); | ||
1174 | |||
1175 | bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); | ||
1176 | |||
1177 | rftid->dap = s_id; | ||
1178 | bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap, | ||
1179 | (bitmap_size < 32 ? bitmap_size : 32)); | ||
1180 | |||
1181 | return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s); | ||
1182 | } | ||
1183 | |||
1184 | u16 | ||
1185 | fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1186 | u8 fc4_type, u8 fc4_ftrs) | ||
1187 | { | ||
1188 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1189 | struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1); | ||
1190 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1191 | |||
1192 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1193 | fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); | ||
1194 | |||
1195 | bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s)); | ||
1196 | |||
1197 | rffid->dap = s_id; | ||
1198 | rffid->fc4ftr_bits = fc4_ftrs; | ||
1199 | rffid->fc4_type = fc4_type; | ||
1200 | |||
1201 | return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s); | ||
1202 | } | ||
1203 | |||
1204 | u16 | ||
1205 | fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1206 | u8 *name) | ||
1207 | { | ||
1208 | |||
1209 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1210 | struct fcgs_rspnid_req_s *rspnid = | ||
1211 | (struct fcgs_rspnid_req_s *)(cthdr + 1); | ||
1212 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1213 | |||
1214 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1215 | fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); | ||
1216 | |||
1217 | bfa_os_memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); | ||
1218 | |||
1219 | rspnid->dap = s_id; | ||
1220 | rspnid->spn_len = (u8) strlen((char *)name); | ||
1221 | strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len); | ||
1222 | |||
1223 | return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); | ||
1224 | } | ||
1225 | |||
1226 | u16 | ||
1227 | fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type) | ||
1228 | { | ||
1229 | |||
1230 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1231 | struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1); | ||
1232 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1233 | |||
1234 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1235 | |||
1236 | fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT); | ||
1237 | |||
1238 | bfa_os_memset(gidft, 0, sizeof(struct fcgs_gidft_req_s)); | ||
1239 | gidft->fc4_type = fc4_type; | ||
1240 | gidft->domain_id = 0; | ||
1241 | gidft->area_id = 0; | ||
1242 | |||
1243 | return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s); | ||
1244 | } | ||
1245 | |||
1246 | u16 | ||
1247 | fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1248 | wwn_t port_name) | ||
1249 | { | ||
1250 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1251 | struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1); | ||
1252 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1253 | |||
1254 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1255 | fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID); | ||
1256 | |||
1257 | bfa_os_memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s)); | ||
1258 | rpnid->port_id = port_id; | ||
1259 | rpnid->port_name = port_name; | ||
1260 | |||
1261 | return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s); | ||
1262 | } | ||
1263 | |||
1264 | u16 | ||
1265 | fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1266 | wwn_t node_name) | ||
1267 | { | ||
1268 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1269 | struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1); | ||
1270 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1271 | |||
1272 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1273 | fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); | ||
1274 | |||
1275 | bfa_os_memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s)); | ||
1276 | rnnid->port_id = port_id; | ||
1277 | rnnid->node_name = node_name; | ||
1278 | |||
1279 | return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s); | ||
1280 | } | ||
1281 | |||
1282 | u16 | ||
1283 | fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1284 | u32 cos) | ||
1285 | { | ||
1286 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1287 | struct fcgs_rcsid_req_s *rcsid = | ||
1288 | (struct fcgs_rcsid_req_s *) (cthdr + 1); | ||
1289 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1290 | |||
1291 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1292 | fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID); | ||
1293 | |||
1294 | bfa_os_memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s)); | ||
1295 | rcsid->port_id = port_id; | ||
1296 | rcsid->cos = cos; | ||
1297 | |||
1298 | return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s); | ||
1299 | } | ||
1300 | |||
1301 | u16 | ||
1302 | fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1303 | u8 port_type) | ||
1304 | { | ||
1305 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1306 | struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1); | ||
1307 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1308 | |||
1309 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1310 | fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID); | ||
1311 | |||
1312 | bfa_os_memset(rptid, 0, sizeof(struct fcgs_rptid_req_s)); | ||
1313 | rptid->port_id = port_id; | ||
1314 | rptid->port_type = port_type; | ||
1315 | |||
1316 | return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s); | ||
1317 | } | ||
1318 | |||
1319 | u16 | ||
1320 | fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id) | ||
1321 | { | ||
1322 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1323 | struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1); | ||
1324 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1325 | |||
1326 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1327 | fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT); | ||
1328 | |||
1329 | bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s)); | ||
1330 | ganxt->port_id = port_id; | ||
1331 | |||
1332 | return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s); | ||
1333 | } | ||
1334 | |||
1335 | /* | ||
1336 | * Builds fc hdr and ct hdr for FDMI requests. | ||
1337 | */ | ||
1338 | u16 | ||
1339 | fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
1340 | u16 cmd_code) | ||
1341 | { | ||
1342 | |||
1343 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1344 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1345 | |||
1346 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1347 | fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); | ||
1348 | |||
1349 | return sizeof(struct ct_hdr_s); | ||
1350 | } | ||
1351 | |||
1352 | /* | ||
1353 | * Given a FC4 Type, this function returns a fc4 type bitmask | ||
1354 | */ | ||
1355 | void | ||
1356 | fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask) | ||
1357 | { | ||
1358 | u8 index; | ||
1359 | u32 *ptr = (u32 *) bit_mask; | ||
1360 | u32 type_value; | ||
1361 | |||
1362 | /* | ||
1363 | * @todo : Check for bitmask size | ||
1364 | */ | ||
1365 | |||
1366 | index = fc4_type >> 5; | ||
1367 | type_value = 1 << (fc4_type % 32); | ||
1368 | ptr[index] = bfa_os_htonl(type_value); | ||
1369 | |||
1370 | } | ||
1371 | |||
1372 | /* | ||
1373 | * GMAL Request | ||
1374 | */ | ||
1375 | u16 | ||
1376 | fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) | ||
1377 | { | ||
1378 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1379 | fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); | ||
1380 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1381 | |||
1382 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1383 | fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, | ||
1384 | CT_GSSUBTYPE_CFGSERVER); | ||
1385 | |||
1386 | bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t)); | ||
1387 | gmal->wwn = wwn; | ||
1388 | |||
1389 | return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t); | ||
1390 | } | ||
1391 | |||
1392 | /* | ||
1393 | * GFN (Get Fabric Name) Request | ||
1394 | */ | ||
1395 | u16 | ||
1396 | fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) | ||
1397 | { | ||
1398 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1399 | fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); | ||
1400 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1401 | |||
1402 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1403 | fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, | ||
1404 | CT_GSSUBTYPE_CFGSERVER); | ||
1405 | |||
1406 | bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t)); | ||
1407 | gfn->wwn = wwn; | ||
1408 | |||
1409 | return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t); | ||
1410 | } | ||