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 */
27static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
28				 __be16 ox_id);
29static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
30				 __be16 ox_id);
31static struct fchs_s fc_els_req_tmpl;
32static struct fchs_s fc_els_rsp_tmpl;
33static struct fchs_s fc_bls_req_tmpl;
34static struct fchs_s fc_bls_rsp_tmpl;
35static struct fc_ba_acc_s ba_acc_tmpl;
36static struct fc_logi_s plogi_tmpl;
37static struct fc_prli_s prli_tmpl;
38static struct fc_rrq_s rrq_tmpl;
39static struct fchs_s fcp_fchs_tmpl;
40
41void
42fcbuild_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
136static void
137fc_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
158static void
159fc_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
174void
175fc_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
183static void
184fc_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
192enum fc_parse_status
193fc_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
213static void
214fc_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
222static          u16
223fc_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
250u16
251fc_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
288u16
289fc_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
310u16
311fc_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
328u16
329fc_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
337u16
338fc_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
346enum fc_parse_status
347fc_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
380enum fc_parse_status
381fc_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
396u16
397fc_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
415u16
416fc_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
433enum fc_parse_status
434fc_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
452enum fc_parse_status
453fc_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
467u16
468fc_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
481static u16
482fc_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
503u16
504fc_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
511u16
512fc_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
520enum fc_parse_status
521fc_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
537enum fc_parse_status
538fc_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
554enum fc_parse_status
555fc_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
576u16
577fc_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
588enum fc_parse_status
589fc_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
598u16
599fc_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
615u16
616fc_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
629u16
630fc_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
645u16
646fc_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
661u16
662fc_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
672int
673fc_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
689u16
690fc_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
713u16
714fc_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
737u16
738fc_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
751u16
752fc_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
779u16
780fc_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
791u16
792fc_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
811u16
812fc_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
832u16
833fc_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
844u16
845fc_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
862u16
863fc_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
885u16
886fc_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
909u16
910fc_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
943u16
944fc_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
973u16
974fc_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
1002enum fc_parse_status
1003fc_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
1014u16
1015fc_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
1028static void
1029fc_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
1038static void
1039fc_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
1048static void
1049fc_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
1059u16
1060fc_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
1075u16
1076fc_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
1091u16
1092fc_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
1107u16
1108fc_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
1120u16
1121fc_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
1135u16
1136fc_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
1152u16
1153fc_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
1172u16
1173fc_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
1196u16
1197fc_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
1216u16
1217fc_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
1236u16
1237fc_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
1258u16
1259fc_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
1279u16
1280fc_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
1299u16
1300fc_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
1317u16
1318fc_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
1335u16
1336fc_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
1354u16
1355fc_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
1372u16
1373fc_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 */
1391u16
1392fc_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 */
1408void
1409fc_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 */
1428u16
1429fc_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 */
1448u16
1449fc_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}
1464