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