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