Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[cascardo/linux.git] / drivers / scsi / bfa / bfa_fcbuild.c
1 /*
2  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
3  * Copyright (c) 2014- QLogic Corporation.
4  * All rights reserved
5  * www.qlogic.com
6  *
7  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
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
22 #include "bfad_drv.h"
23 #include "bfa_fcbuild.h"
24
25 /*
26  * static build functions
27  */
28 static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
29                                  __be16 ox_id);
30 static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
31                                  __be16 ox_id);
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;
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;
40 static struct fchs_s fcp_fchs_tmpl;
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 =
52                 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
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 =
63                 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
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;
72         fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
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 =
82                 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
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;
98         plogi_tmpl.csp.ciro = 0x1;
99         plogi_tmpl.csp.cisc = 0x0;
100         plogi_tmpl.csp.altbbcred = 0x0;
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);
104
105         plogi_tmpl.class3.class_valid = 1;
106         plogi_tmpl.class3.sequential = 1;
107         plogi_tmpl.class3.conseq = 0xFF;
108         plogi_tmpl.class3.ospx = 1;
109
110         /*
111          * prli_tmpl
112          */
113         prli_tmpl.command = FC_ELS_PRLI;
114         prli_tmpl.pglen = 0x10;
115         prli_tmpl.pagebytes = cpu_to_be16(0x0014);
116         prli_tmpl.parampage.type = FC_TYPE_FCP;
117         prli_tmpl.parampage.imagepair = 1;
118         prli_tmpl.parampage.servparams.rxrdisab = 1;
119
120         /*
121          * rrq_tmpl
122          */
123         rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
124
125         /*
126          * fcp_struct fchs_s mpl
127          */
128         fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
129         fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
130         fcp_fchs_tmpl.type = FC_TYPE_FCP;
131         fcp_fchs_tmpl.f_ctl =
132                 bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
133         fcp_fchs_tmpl.seq_id = 1;
134         fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
135 }
136
137 static void
138 fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
139 {
140         memset(fchs, 0, sizeof(struct fchs_s));
141
142         fchs->routing = FC_RTG_FC4_DEV_DATA;
143         fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
144         fchs->type = FC_TYPE_SERVICES;
145         fchs->f_ctl =
146                 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
147                               FCTL_SI_XFER);
148         fchs->rx_id = FC_RXID_ANY;
149         fchs->d_id = (d_id);
150         fchs->s_id = (s_id);
151         fchs->ox_id = cpu_to_be16(ox_id);
152
153         /*
154          * @todo no need to set ox_id for request
155          *       no need to set rx_id for response
156          */
157 }
158
159 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
175 void
176 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
177 {
178         memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
179         fchs->d_id = (d_id);
180         fchs->s_id = (s_id);
181         fchs->ox_id = cpu_to_be16(ox_id);
182 }
183
184 static void
185 fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
186 {
187         memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
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 {
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;
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)
204                         return FC_PARSE_BUSY;
205                 else
206                         return FC_PARSE_FAILURE;
207
208         case FC_ELS_ACC:
209                 return FC_PARSE_OK;
210         }
211         return FC_PARSE_OK;
212 }
213
214 static void
215 fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
216 {
217         memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
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,
225                  __be16 ox_id, wwn_t port_name, wwn_t node_name,
226                  u16 pdu_size, u16 bb_cr, u8 els_code)
227 {
228         struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
229
230         memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
231
232         /* For FC AL bb_cr is 0 and altbbcred is 1 */
233         if (!bb_cr)
234                 plogi->csp.altbbcred = 1;
235
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
242         plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
243         plogi->csp.bbcred  = cpu_to_be16(bb_cr);
244
245         memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
246         memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
247
248         return sizeof(struct fc_logi_s);
249 }
250
251 u16
252 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
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)
255 {
256         u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
257         __be32  *vvl_info;
258
259         memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
260
261         flogi->els_cmd.els_code = FC_ELS_FLOGI;
262         fc_els_req_build(fchs, d_id, s_id, ox_id);
263
264         flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
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
277         flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
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 */
284         vvl_info[0]     = cpu_to_be32(FLOGI_VVL_BRCD);
285
286         return sizeof(struct fc_logi_s);
287 }
288
289 u16
290 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
291                    __be16 ox_id, wwn_t port_name, wwn_t node_name,
292                    u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
293 {
294         u32        d_id = 0;
295         u16        bbscn_rxsz = (bb_scn << 12) | pdu_size;
296
297         memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
298         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
299
300         flogi->els_cmd.els_code = FC_ELS_ACC;
301         flogi->class3.rxsz = cpu_to_be16(pdu_size);
302         flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);     /* bb_scn/rxsz */
303         flogi->port_name = port_name;
304         flogi->node_name = node_name;
305
306         flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
307
308         return sizeof(struct fc_logi_s);
309 }
310
311 u16
312 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
313                 u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
314 {
315         u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
316
317         memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
318
319         flogi->els_cmd.els_code = FC_ELS_FDISC;
320         fc_els_req_build(fchs, d_id, s_id, ox_id);
321
322         flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
323         flogi->port_name = port_name;
324         flogi->node_name = node_name;
325
326         return sizeof(struct fc_logi_s);
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,
332                u16 pdu_size, u16 bb_cr)
333 {
334         return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
335                                 node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
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,
341                    u16 pdu_size, u16 bb_cr)
342 {
343         return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
344                                 node_name, pdu_size, bb_cr, FC_ELS_ACC);
345 }
346
347 enum fc_parse_status
348 fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
349 {
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;
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)
358                         return FC_PARSE_BUSY;
359                 else
360                         return FC_PARSE_FAILURE;
361         case FC_ELS_ACC:
362                 plogi = (struct fc_logi_s *) (fchs + 1);
363                 if (len < sizeof(struct fc_logi_s))
364                         return FC_PARSE_FAILURE;
365
366                 if (!wwn_is_equal(plogi->port_name, port_name))
367                         return FC_PARSE_FAILURE;
368
369                 if (!plogi->class3.class_valid)
370                         return FC_PARSE_FAILURE;
371
372                 if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
373                         return FC_PARSE_FAILURE;
374
375                 return FC_PARSE_OK;
376         default:
377                 return FC_PARSE_FAILURE;
378         }
379 }
380
381 enum fc_parse_status
382 fc_plogi_parse(struct fchs_s *fchs)
383 {
384         struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
385
386         if (plogi->class3.class_valid != 1)
387                 return FC_PARSE_FAILURE;
388
389         if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ)
390             || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ)
391             || (plogi->class3.rxsz == 0))
392                 return FC_PARSE_FAILURE;
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 {
401         struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
402
403         fc_els_req_build(fchs, d_id, s_id, ox_id);
404         memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
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
413         return sizeof(struct fc_prli_s);
414 }
415
416 u16
417 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
418                   __be16 ox_id, enum bfa_lport_role role)
419 {
420         struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
421
422         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
423         memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
424
425         prli->command = FC_ELS_ACC;
426
427         prli->parampage.servparams.initiator = 1;
428
429         prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
430
431         return sizeof(struct fc_prli_s);
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))
438                 return FC_PARSE_FAILURE;
439
440         if (prli->command != FC_ELS_ACC)
441                 return FC_PARSE_FAILURE;
442
443         if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
444             && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
445                 return FC_PARSE_FAILURE;
446
447         if (prli->parampage.servparams.target != 1)
448                 return FC_PARSE_FAILURE;
449
450         return FC_PARSE_OK;
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)
457                 return FC_PARSE_FAILURE;
458
459         if (!prli->parampage.imagepair)
460                 return FC_PARSE_FAILURE;
461
462         if (!prli->parampage.servparams.initiator)
463                 return FC_PARSE_FAILURE;
464
465         return FC_PARSE_OK;
466 }
467
468 u16
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)
471 {
472         fc_els_req_build(fchs, d_id, s_id, ox_id);
473
474         memset(logo, '\0', sizeof(struct fc_logo_s));
475         logo->els_cmd.els_code = FC_ELS_LOGO;
476         logo->nport_id = (s_id);
477         logo->orig_port_name = port_name;
478
479         return sizeof(struct fc_logo_s);
480 }
481
482 static u16
483 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
484                  u32 s_id, __be16 ox_id, wwn_t port_name,
485                  wwn_t node_name, u8 els_code)
486 {
487         memset(adisc, '\0', sizeof(struct fc_adisc_s));
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
501         return sizeof(struct fc_adisc_s);
502 }
503
504 u16
505 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
506                 u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
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,
514                    u32 s_id, __be16 ox_id, wwn_t port_name,
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))
527                 return FC_PARSE_FAILURE;
528
529         if (adisc->els_cmd.els_code != FC_ELS_ACC)
530                 return FC_PARSE_FAILURE;
531
532         if (!wwn_is_equal(adisc->orig_port_name, port_name))
533                 return FC_PARSE_FAILURE;
534
535         return FC_PARSE_OK;
536 }
537
538 enum fc_parse_status
539 fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
540                wwn_t port_name)
541 {
542         struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
543
544         if (adisc->els_cmd.els_code != FC_ELS_ACC)
545                 return FC_PARSE_FAILURE;
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))
550                 return FC_PARSE_OK;
551
552         return FC_PARSE_FAILURE;
553 }
554
555 enum fc_parse_status
556 fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
557 {
558         struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
559
560         if (pdisc->class3.class_valid != 1)
561                 return FC_PARSE_FAILURE;
562
563         if ((be16_to_cpu(pdisc->class3.rxsz) <
564                 (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
565             || (pdisc->class3.rxsz == 0))
566                 return FC_PARSE_FAILURE;
567
568         if (!wwn_is_equal(pdisc->port_name, port_name))
569                 return FC_PARSE_FAILURE;
570
571         if (!wwn_is_equal(pdisc->node_name, node_name))
572                 return FC_PARSE_FAILURE;
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 {
580         memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
581         fchs->cat_info = FC_CAT_ABTS;
582         fchs->d_id = (d_id);
583         fchs->s_id = (s_id);
584         fchs->ox_id = cpu_to_be16(ox_id);
585
586         return sizeof(struct fchs_s);
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))
594                 return FC_PARSE_OK;
595
596         return FC_PARSE_FAILURE;
597 }
598
599 u16
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)
602 {
603         fc_els_req_build(fchs, d_id, s_id, ox_id);
604
605         /*
606          * build rrq payload
607          */
608         memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
609         rrq->s_id = (s_id);
610         rrq->ox_id = cpu_to_be16(rrq_oxid);
611         rrq->rx_id = FC_RXID_ANY;
612
613         return sizeof(struct fc_rrq_s);
614 }
615
616 u16
617 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
618                   __be16 ox_id)
619 {
620         struct fc_els_cmd_s *acc = pld;
621
622         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
623
624         memset(acc, 0, sizeof(struct fc_els_cmd_s));
625         acc->els_code = FC_ELS_ACC;
626
627         return sizeof(struct fc_els_cmd_s);
628 }
629
630 u16
631 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
632                 u32 s_id, __be16 ox_id, u8 reason_code,
633                 u8 reason_code_expl)
634 {
635         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
636         memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
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
643         return sizeof(struct fc_ls_rjt_s);
644 }
645
646 u16
647 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
648                 u32 s_id, __be16 ox_id, u16 rx_id)
649 {
650         fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
651
652         memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
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
659         return sizeof(struct fc_ba_acc_s);
660 }
661
662 u16
663 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
664                 u32 s_id, __be16 ox_id)
665 {
666         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
667         memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
668         els_cmd->els_code = FC_ELS_ACC;
669
670         return sizeof(struct fc_els_cmd_s);
671 }
672
673 int
674 fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
675 {
676         int             num_pages = 0;
677         struct fc_prlo_s *prlo;
678         struct fc_tprlo_s *tprlo;
679
680         if (els_code == FC_ELS_PRLO) {
681                 prlo = (struct fc_prlo_s *) (fc_frame + 1);
682                 num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16;
683         } else {
684                 tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
685                 num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
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,
692                 u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
693 {
694         int             page;
695
696         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
697
698         memset(tprlo_acc, 0, (num_pages * 16) + 4);
699         tprlo_acc->command = FC_ELS_ACC;
700
701         tprlo_acc->page_len = 0x10;
702         tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
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         }
711         return be16_to_cpu(tprlo_acc->payload_len);
712 }
713
714 u16
715 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
716                   u32 s_id, __be16 ox_id, int num_pages)
717 {
718         int             page;
719
720         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
721
722         memset(prlo_acc, 0, (num_pages * 16) + 4);
723         prlo_acc->command = FC_ELS_ACC;
724         prlo_acc->page_len = 0x10;
725         prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
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
735         return be16_to_cpu(prlo_acc->payload_len);
736 }
737
738 u16
739 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
740                 u32 s_id, u16 ox_id, u32 data_format)
741 {
742         fc_els_req_build(fchs, d_id, s_id, ox_id);
743
744         memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
745
746         rnid->els_cmd.els_code = FC_ELS_RNID;
747         rnid->node_id_data_format = data_format;
748
749         return sizeof(struct fc_rnid_cmd_s);
750 }
751
752 u16
753 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
754                   u32 s_id, __be16 ox_id, u32 data_format,
755                   struct fc_rnid_common_id_data_s *common_id_data,
756                   struct fc_rnid_general_topology_data_s *gen_topo_data)
757 {
758         memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
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);
771                 rnid_acc->gen_topology_data = *gen_topo_data;
772                 return sizeof(struct fc_rnid_acc_s);
773         } else {
774                 return sizeof(struct fc_rnid_acc_s) -
775                         sizeof(struct fc_rnid_general_topology_data_s);
776         }
777
778 }
779
780 u16
781 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
782                 u32 s_id, u16 ox_id)
783 {
784         fc_els_req_build(fchs, d_id, s_id, ox_id);
785
786         memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
787
788         rpsc->els_cmd.els_code = FC_ELS_RPSC;
789         return sizeof(struct fc_rpsc_cmd_s);
790 }
791
792 u16
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)
795 {
796         u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
797         int i = 0;
798
799         fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
800
801         memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
802
803         rpsc2->els_cmd.els_code = FC_ELS_RPSC;
804         rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN);
805         rpsc2->num_pids  = cpu_to_be16(npids);
806         for (i = 0; i < npids; i++)
807                 rpsc2->pid_list[i].pid = pid_list[i];
808
809         return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
810 }
811
812 u16
813 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
814                 u32 d_id, u32 s_id, __be16 ox_id,
815                   struct fc_rpsc_speed_info_s *oper_speed)
816 {
817         memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
818
819         fc_els_rsp_build(fchs, d_id, s_id, ox_id);
820
821         rpsc_acc->command = FC_ELS_ACC;
822         rpsc_acc->num_entries = cpu_to_be16(1);
823
824         rpsc_acc->speed_info[0].port_speed_cap =
825                 cpu_to_be16(oper_speed->port_speed_cap);
826
827         rpsc_acc->speed_info[0].port_op_speed =
828                 cpu_to_be16(oper_speed->port_op_speed);
829
830         return sizeof(struct fc_rpsc_acc_s);
831 }
832
833 u16
834 fc_logo_rsp_parse(struct fchs_s *fchs, int len)
835 {
836         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
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
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)
848 {
849         struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
850
851         memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
852
853         pdisc->els_cmd.els_code = FC_ELS_PDISC;
854         fc_els_req_build(fchs, d_id, s_id, ox_id);
855
856         pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size);
857         pdisc->port_name = port_name;
858         pdisc->node_name = node_name;
859
860         return sizeof(struct fc_logi_s);
861 }
862
863 u16
864 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
865 {
866         struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
867
868         if (len < sizeof(struct fc_logi_s))
869                 return FC_PARSE_LEN_INVAL;
870
871         if (pdisc->els_cmd.els_code != FC_ELS_ACC)
872                 return FC_PARSE_ACC_INVAL;
873
874         if (!wwn_is_equal(pdisc->port_name, port_name))
875                 return FC_PARSE_PWWN_NOT_EQUAL;
876
877         if (!pdisc->class3.class_valid)
878                 return FC_PARSE_NWWN_NOT_EQUAL;
879
880         if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
881                 return FC_PARSE_RXSZ_INVAL;
882
883         return FC_PARSE_OK;
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 {
890         struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
891         int             page;
892
893         fc_els_req_build(fchs, d_id, s_id, ox_id);
894         memset(prlo, 0, (num_pages * 16) + 4);
895         prlo->command = FC_ELS_PRLO;
896         prlo->page_len = 0x10;
897         prlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
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
907         return be16_to_cpu(prlo->payload_len);
908 }
909
910 u16
911 fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
912 {
913         struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
914         int             num_pages = 0;
915         int             page = 0;
916
917         len = len;
918
919         if (prlo->command != FC_ELS_ACC)
920                 return FC_PARSE_FAILURE;
921
922         num_pages = ((be16_to_cpu(prlo->payload_len)) - 4) / 16;
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         }
940         return FC_PARSE_OK;
941
942 }
943
944 u16
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)
947 {
948         struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
949         int             page;
950
951         fc_els_req_build(fchs, d_id, s_id, ox_id);
952         memset(tprlo, 0, (num_pages * 16) + 4);
953         tprlo->command = FC_ELS_TPRLO;
954         tprlo->page_len = 0x10;
955         tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
956
957         for (page = 0; page < num_pages; page++) {
958                 tprlo->tprlo_params[page].type = FC_TYPE_FCP;
959                 tprlo->tprlo_params[page].opa_valid = 0;
960                 tprlo->tprlo_params[page].rpa_valid = 0;
961                 tprlo->tprlo_params[page].orig_process_assc = 0;
962                 tprlo->tprlo_params[page].resp_process_assc = 0;
963                 if (tprlo_type == FC_GLOBAL_LOGO) {
964                         tprlo->tprlo_params[page].global_process_logout = 1;
965                 } else if (tprlo_type == FC_TPR_LOGO) {
966                         tprlo->tprlo_params[page].tpo_nport_valid = 1;
967                         tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
968                 }
969         }
970
971         return be16_to_cpu(tprlo->payload_len);
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)
984                 return FC_PARSE_ACC_INVAL;
985
986         num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
987
988         for (page = 0; page < num_pages; page++) {
989                 if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
990                         return FC_PARSE_NOT_FCP;
991                 if (tprlo->tprlo_acc_params[page].opa_valid != 0)
992                         return FC_PARSE_OPAFLAG_INVAL;
993                 if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
994                         return FC_PARSE_RPAFLAG_INVAL;
995                 if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
996                         return FC_PARSE_OPA_INVAL;
997                 if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
998                         return FC_PARSE_RPA_INVAL;
999         }
1000         return FC_PARSE_OK;
1001 }
1002
1003 enum fc_parse_status
1004 fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
1005 {
1006         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1007
1008         len = len;
1009         if (els_cmd->els_code != FC_ELS_ACC)
1010                 return FC_PARSE_FAILURE;
1011
1012         return FC_PARSE_OK;
1013 }
1014
1015 u16
1016 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
1017                 u32 reason_code, u32 reason_expl)
1018 {
1019         struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
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;
1026         return sizeof(struct fc_ba_rjt_s);
1027 }
1028
1029 static void
1030 fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
1031 {
1032         memset(cthdr, 0, sizeof(struct ct_hdr_s));
1033         cthdr->rev_id = CT_GS3_REVISION;
1034         cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
1035         cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
1036         cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
1037 }
1038
1039 static void
1040 fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
1041 {
1042         memset(cthdr, 0, sizeof(struct ct_hdr_s));
1043         cthdr->rev_id = CT_GS3_REVISION;
1044         cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
1045         cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
1046         cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
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 {
1053         memset(cthdr, 0, sizeof(struct ct_hdr_s));
1054         cthdr->rev_id = CT_GS3_REVISION;
1055         cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
1056         cthdr->gs_sub_type = sub_type;
1057         cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
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 {
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);
1066         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
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
1071         memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
1072         gidpn->port_name = port_name;
1073         return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
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 {
1080         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1081         fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
1082         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
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
1087         memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
1088         gpnid->dap = port_id;
1089         return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
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 {
1096         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1097         fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
1098         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
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
1103         memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
1104         gnnid->dap = port_id;
1105         return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
1106 }
1107
1108 u16
1109 fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
1110 {
1111         if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
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
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
1136 u16
1137 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
1138                 u8 set_br_reg, u32 s_id, u16 ox_id)
1139 {
1140         u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
1141
1142         fc_els_req_build(fchs, d_id, s_id, ox_id);
1143
1144         memset(scr, 0, sizeof(struct fc_scr_s));
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
1150         return sizeof(struct fc_scr_s);
1151 }
1152
1153 u16
1154 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
1155                 u32 s_id, u16 ox_id)
1156 {
1157         u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
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;
1165         rscn->payldlen = cpu_to_be16(payldlen);
1166
1167         rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
1168         rscn->event[0].portid = s_id;
1169
1170         return sizeof(struct fc_rscn_pl_s);
1171 }
1172
1173 u16
1174 fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1175                enum bfa_lport_role roles)
1176 {
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);
1179         u32        type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
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
1185         memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
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);
1192         rftid->fc4_type[index] = cpu_to_be32(type_value);
1193
1194         return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
1195 }
1196
1197 u16
1198 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1199                    u8 *fc4_bitmap, u32 bitmap_size)
1200 {
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);
1203         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
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
1208         memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
1209
1210         rftid->dap = s_id;
1211         memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
1212                 (bitmap_size < 32 ? bitmap_size : 32));
1213
1214         return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
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 {
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);
1223         u32         d_id = bfa_hton3b(FC_NAME_SERVER);
1224
1225         fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1226         fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
1227
1228         memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
1229
1230         rffid->dap          = s_id;
1231         rffid->fc4ftr_bits  = fc4_ftrs;
1232         rffid->fc4_type     = fc4_type;
1233
1234         return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
1235 }
1236
1237 u16
1238 fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1239                 u8 *name)
1240 {
1241
1242         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1243         struct fcgs_rspnid_req_s *rspnid =
1244                         (struct fcgs_rspnid_req_s *)(cthdr + 1);
1245         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1246
1247         fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1248         fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
1249
1250         memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
1251
1252         rspnid->dap = s_id;
1253         rspnid->spn_len = (u8) strlen((char *)name);
1254         strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
1255
1256         return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
1257 }
1258
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
1280 u16
1281 fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
1282 {
1283
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);
1286         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
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
1292         memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
1293         gidft->fc4_type = fc4_type;
1294         gidft->domain_id = 0;
1295         gidft->area_id = 0;
1296
1297         return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
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 {
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);
1306         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1307
1308         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1309         fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
1310
1311         memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
1312         rpnid->port_id = port_id;
1313         rpnid->port_name = port_name;
1314
1315         return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
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 {
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);
1324         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1325
1326         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1327         fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
1328
1329         memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
1330         rnnid->port_id = port_id;
1331         rnnid->node_name = node_name;
1332
1333         return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
1334 }
1335
1336 u16
1337 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
1338                u32 cos)
1339 {
1340         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1341         struct fcgs_rcsid_req_s *rcsid =
1342                         (struct fcgs_rcsid_req_s *) (cthdr + 1);
1343         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1344
1345         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1346         fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
1347
1348         memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
1349         rcsid->port_id = port_id;
1350         rcsid->cos = cos;
1351
1352         return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
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 {
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);
1361         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1362
1363         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1364         fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
1365
1366         memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
1367         rptid->port_id = port_id;
1368         rptid->port_type = port_type;
1369
1370         return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
1371 }
1372
1373 u16
1374 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
1375 {
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);
1378         u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1379
1380         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1381         fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
1382
1383         memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
1384         ganxt->port_id = port_id;
1385
1386         return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
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
1397         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1398         u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
1399
1400         fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1401         fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
1402
1403         return sizeof(struct ct_hdr_s);
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;
1413         __be32       *ptr = (__be32 *) bit_mask;
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);
1422         ptr[index] = cpu_to_be32(type_value);
1423
1424 }
1425
1426 /*
1427  *      GMAL Request
1428  */
1429 u16
1430 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
1431 {
1432         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1433         fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
1434         u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
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
1440         memset(gmal, 0, sizeof(fcgs_gmal_req_t));
1441         gmal->wwn = wwn;
1442
1443         return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
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 {
1452         struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1453         fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
1454         u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
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
1460         memset(gfn, 0, sizeof(fcgs_gfn_req_t));
1461         gfn->wwn = wwn;
1462
1463         return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
1464 }