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