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