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