182527734SSukumar Swaminathan /*
282527734SSukumar Swaminathan  * CDDL HEADER START
382527734SSukumar Swaminathan  *
482527734SSukumar Swaminathan  * The contents of this file are subject to the terms of the
582527734SSukumar Swaminathan  * Common Development and Distribution License (the "License").
682527734SSukumar Swaminathan  * You may not use this file except in compliance with the License.
782527734SSukumar Swaminathan  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
1082527734SSukumar Swaminathan  * See the License for the specific language governing permissions
1182527734SSukumar Swaminathan  * and limitations under the License.
1282527734SSukumar Swaminathan  *
1382527734SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
1482527734SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1582527734SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
1682527734SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
1782527734SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
1882527734SSukumar Swaminathan  *
1982527734SSukumar Swaminathan  * CDDL HEADER END
2082527734SSukumar Swaminathan  */
2182527734SSukumar Swaminathan 
2282527734SSukumar Swaminathan /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
2582527734SSukumar Swaminathan  */
2682527734SSukumar Swaminathan 
2782527734SSukumar Swaminathan #include <emlxs.h>
2882527734SSukumar Swaminathan 
29*8f23e9faSHans Rosenfeld 
3082527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3182527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI4_C);
3282527734SSukumar Swaminathan 
33*8f23e9faSHans Rosenfeld static int		emlxs_sli4_init_extents(emlxs_hba_t *hba,
34*8f23e9faSHans Rosenfeld 				MAILBOXQ *mbq);
35*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_read_status(emlxs_hba_t *hba);
36*8f23e9faSHans Rosenfeld 
37*8f23e9faSHans Rosenfeld static int		emlxs_init_bootstrap_mb(emlxs_hba_t *hba);
38*8f23e9faSHans Rosenfeld 
39*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_read_sema(emlxs_hba_t *hba);
40*8f23e9faSHans Rosenfeld 
41*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_read_mbdb(emlxs_hba_t *hba);
42*8f23e9faSHans Rosenfeld 
43*8f23e9faSHans Rosenfeld static void		emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value);
44*8f23e9faSHans Rosenfeld 
45*8f23e9faSHans Rosenfeld static void		emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value);
46*8f23e9faSHans Rosenfeld 
47*8f23e9faSHans Rosenfeld static void		emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value);
48*8f23e9faSHans Rosenfeld 
49*8f23e9faSHans Rosenfeld static void		emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value);
50*8f23e9faSHans Rosenfeld 
51*8f23e9faSHans Rosenfeld static void		emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value);
52*8f23e9faSHans Rosenfeld 
5382527734SSukumar Swaminathan static int		emlxs_sli4_create_queues(emlxs_hba_t *hba,
5482527734SSukumar Swaminathan 				MAILBOXQ *mbq);
5582527734SSukumar Swaminathan static int		emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
5682527734SSukumar Swaminathan 				MAILBOXQ *mbq);
5782527734SSukumar Swaminathan static int		emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
5882527734SSukumar Swaminathan 				MAILBOXQ *mbq);
5982527734SSukumar Swaminathan 
60a9800bebSGarrett D'Amore static int		emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
6182527734SSukumar Swaminathan 
6282527734SSukumar Swaminathan static int		emlxs_sli4_map_hdw(emlxs_hba_t *hba);
6382527734SSukumar Swaminathan 
6482527734SSukumar Swaminathan static void		emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
6582527734SSukumar Swaminathan 
6682527734SSukumar Swaminathan static int32_t		emlxs_sli4_online(emlxs_hba_t *hba);
6782527734SSukumar Swaminathan 
68*8f23e9faSHans Rosenfeld static void		emlxs_sli4_offline(emlxs_hba_t *hba,
69*8f23e9faSHans Rosenfeld 				uint32_t reset_requested);
7082527734SSukumar Swaminathan 
7182527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
7282527734SSukumar Swaminathan 				uint32_t skip_post, uint32_t quiesce);
7382527734SSukumar Swaminathan static void		emlxs_sli4_hba_kill(emlxs_hba_t *hba);
7482527734SSukumar Swaminathan 
7582527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_init(emlxs_hba_t *hba);
7682527734SSukumar Swaminathan 
7782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_bde_setup(emlxs_port_t *port,
7882527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
79a9800bebSGarrett D'Amore 
8082527734SSukumar Swaminathan static void		emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
81a9800bebSGarrett D'Amore 				CHANNEL *cp, IOCBQ *iocb_cmd);
8282527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
8382527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
8482527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
8582527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
8682527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
8782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
8882527734SSukumar Swaminathan 				emlxs_buf_t *cmd_sbp, int channel);
89*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_fct_bde_setup(emlxs_port_t *port,
90*8f23e9faSHans Rosenfeld 				emlxs_buf_t *sbp);
9182527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
9282527734SSukumar Swaminathan 
9382527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
9482527734SSukumar Swaminathan 				emlxs_buf_t *sbp, int ring);
9582527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
9682527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
9782527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
9882527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
9982527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
10082527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
101*8f23e9faSHans Rosenfeld static void		emlxs_sli4_poll_intr(emlxs_hba_t *hba);
10282527734SSukumar Swaminathan static int32_t		emlxs_sli4_intx_intr(char *arg);
10382527734SSukumar Swaminathan 
10482527734SSukumar Swaminathan #ifdef MSI_SUPPORT
10582527734SSukumar Swaminathan static uint32_t		emlxs_sli4_msi_intr(char *arg1, char *arg2);
10682527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
10782527734SSukumar Swaminathan 
10882527734SSukumar Swaminathan static void		emlxs_sli4_resource_free(emlxs_hba_t *hba);
10982527734SSukumar Swaminathan 
11082527734SSukumar Swaminathan static int		emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
111*8f23e9faSHans Rosenfeld extern void		emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba);
11282527734SSukumar Swaminathan 
113*8f23e9faSHans Rosenfeld static XRIobj_t		*emlxs_sli4_alloc_xri(emlxs_port_t *port,
114*8f23e9faSHans Rosenfeld 				emlxs_buf_t *sbp, RPIobj_t *rpip,
115*8f23e9faSHans Rosenfeld 				uint32_t type);
11682527734SSukumar Swaminathan static void		emlxs_sli4_enable_intr(emlxs_hba_t *hba);
11782527734SSukumar Swaminathan 
11882527734SSukumar Swaminathan static void		emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
11982527734SSukumar Swaminathan 
120*8f23e9faSHans Rosenfeld static void		emlxs_sli4_timer(emlxs_hba_t *hba);
12182527734SSukumar Swaminathan 
12282527734SSukumar Swaminathan static void		emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
12382527734SSukumar Swaminathan 
124a9800bebSGarrett D'Amore static void		emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
12582527734SSukumar Swaminathan 
126*8f23e9faSHans Rosenfeld extern XRIobj_t 	*emlxs_sli4_reserve_xri(emlxs_port_t *port,
127*8f23e9faSHans Rosenfeld 				RPIobj_t *rpip, uint32_t type, uint16_t rx_id);
12882527734SSukumar Swaminathan static int		emlxs_check_hdw_ready(emlxs_hba_t *);
12982527734SSukumar Swaminathan 
130*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_reg_did(emlxs_port_t *port,
131*8f23e9faSHans Rosenfeld 				uint32_t did, SERV_PARM *param,
132*8f23e9faSHans Rosenfeld 				emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
133*8f23e9faSHans Rosenfeld 				IOCBQ *iocbq);
134*8f23e9faSHans Rosenfeld 
135*8f23e9faSHans Rosenfeld static uint32_t		emlxs_sli4_unreg_node(emlxs_port_t *port,
136*8f23e9faSHans Rosenfeld 				emlxs_node_t *node, emlxs_buf_t *sbp,
137*8f23e9faSHans Rosenfeld 				fc_unsol_buf_t *ubp, IOCBQ *iocbq);
138*8f23e9faSHans Rosenfeld 
139*8f23e9faSHans Rosenfeld static void		emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba,
140*8f23e9faSHans Rosenfeld 				CQE_ASYNC_t *cqe);
141*8f23e9faSHans Rosenfeld static void		emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba,
142*8f23e9faSHans Rosenfeld 				CQE_ASYNC_t *cqe);
143*8f23e9faSHans Rosenfeld 
144*8f23e9faSHans Rosenfeld 
145*8f23e9faSHans Rosenfeld static uint16_t		emlxs_sli4_rqid_to_index(emlxs_hba_t *hba,
146*8f23e9faSHans Rosenfeld 				uint16_t rqid);
147*8f23e9faSHans Rosenfeld static uint16_t		emlxs_sli4_wqid_to_index(emlxs_hba_t *hba,
148*8f23e9faSHans Rosenfeld 				uint16_t wqid);
149*8f23e9faSHans Rosenfeld static uint16_t		emlxs_sli4_cqid_to_index(emlxs_hba_t *hba,
150*8f23e9faSHans Rosenfeld 				uint16_t cqid);
151a9800bebSGarrett D'Amore 
15282527734SSukumar Swaminathan /* Define SLI4 API functions */
15382527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli4_api = {
15482527734SSukumar Swaminathan 	emlxs_sli4_map_hdw,
15582527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw,
15682527734SSukumar Swaminathan 	emlxs_sli4_online,
15782527734SSukumar Swaminathan 	emlxs_sli4_offline,
15882527734SSukumar Swaminathan 	emlxs_sli4_hba_reset,
15982527734SSukumar Swaminathan 	emlxs_sli4_hba_kill,
16082527734SSukumar Swaminathan 	emlxs_sli4_issue_iocb_cmd,
16182527734SSukumar Swaminathan 	emlxs_sli4_issue_mbox_cmd,
16282527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
16382527734SSukumar Swaminathan 	emlxs_sli4_prep_fct_iocb,
16482527734SSukumar Swaminathan #else
16582527734SSukumar Swaminathan 	NULL,
16682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
16782527734SSukumar Swaminathan 	emlxs_sli4_prep_fcp_iocb,
16882527734SSukumar Swaminathan 	emlxs_sli4_prep_ip_iocb,
16982527734SSukumar Swaminathan 	emlxs_sli4_prep_els_iocb,
17082527734SSukumar Swaminathan 	emlxs_sli4_prep_ct_iocb,
17182527734SSukumar Swaminathan 	emlxs_sli4_poll_intr,
17282527734SSukumar Swaminathan 	emlxs_sli4_intx_intr,
17382527734SSukumar Swaminathan 	emlxs_sli4_msi_intr,
17482527734SSukumar Swaminathan 	emlxs_sli4_disable_intr,
17582527734SSukumar Swaminathan 	emlxs_sli4_timer,
176*8f23e9faSHans Rosenfeld 	emlxs_sli4_poll_erratt,
177*8f23e9faSHans Rosenfeld 	emlxs_sli4_reg_did,
178*8f23e9faSHans Rosenfeld 	emlxs_sli4_unreg_node
17982527734SSukumar Swaminathan };
18082527734SSukumar Swaminathan 
18182527734SSukumar Swaminathan 
18282527734SSukumar Swaminathan /* ************************************************************************** */
18382527734SSukumar Swaminathan 
184*8f23e9faSHans Rosenfeld static void
185*8f23e9faSHans Rosenfeld emlxs_sli4_set_default_params(emlxs_hba_t *hba)
186*8f23e9faSHans Rosenfeld {
187*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
188*8f23e9faSHans Rosenfeld 
189*8f23e9faSHans Rosenfeld 	bzero((char *)&hba->sli.sli4.param, sizeof (sli_params_t));
190*8f23e9faSHans Rosenfeld 
191*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.ProtocolType = 0x3; /* FC/FCoE */
192*8f23e9faSHans Rosenfeld 
193*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SliHint2 = 0;
194*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SliHint1 = 0;
195*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.IfType = 0;
196*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SliFamily = 0;
197*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.Revision = 0x4; /* SLI4 */
198*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.FT = 0;
199*8f23e9faSHans Rosenfeld 
200*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EqeCntMethod = 0x1; /* Bit pattern */
201*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EqPageSize = 0x1; /* 4096 */
202*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EqeSize = 0x1; /* 4 byte */
203*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EqPageCnt = 8;
204*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EqeCntMask = 0x1F; /* 256-4096 elements */
205*8f23e9faSHans Rosenfeld 
206*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CqeCntMethod = 0x1; /* Bit pattern */
207*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CqPageSize = 0x1; /* 4096 */
208*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CQV = 0;
209*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CqeSize = 0x3; /* 16 byte */
210*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CqPageCnt = 4;
211*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.CqeCntMask = 0x70; /* 256-1024 elements */
212*8f23e9faSHans Rosenfeld 
213*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MqeCntMethod = 0x1; /* Bit pattern */
214*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MqPageSize = 0x1; /* 4096 */
215*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MQV = 0;
216*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MqPageCnt = 8;
217*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MqeCntMask = 0x0F; /* 16-128 elements */
218*8f23e9faSHans Rosenfeld 
219*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WqeCntMethod = 0; /* Page Count */
220*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WqPageSize = 0x1; /* 4096 */
221*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WQV = 0;
222*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WqeSize = 0x5; /* 64 byte */
223*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WqPageCnt = 4;
224*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.WqeCntMask = 0x10; /* 256 elements */
225*8f23e9faSHans Rosenfeld 
226*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqeCntMethod = 0; /* Page Count */
227*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqPageSize = 0x1; /* 4096 */
228*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RQV = 0;
229*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqeSize = 0x2; /* 8 byte */
230*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqPageCnt = 8;
231*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqDbWin = 1;
232*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RqeCntMask = 0x100; /* 4096 elements */
233*8f23e9faSHans Rosenfeld 
234*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.Loopback = 0xf; /* unsupported */
235*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.PHWQ = 0;
236*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.PHON = 0;
237*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.TRIR = 0;
238*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.TRTY = 0;
239*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.TCCA = 0;
240*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MWQE = 0;
241*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.ASSI = 0;
242*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.TERP = 0;
243*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.TGT  = 0;
244*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.AREG = 0;
245*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.FBRR = 0;
246*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SGLR = 1;
247*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.HDRR = 1;
248*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.EXT  = 0;
249*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.FCOE = 1;
250*8f23e9faSHans Rosenfeld 
251*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SgeLength = (64 * 1024);
252*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SglAlign = 0x7 /* 4096 */;
253*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SglPageSize = 0x1; /* 4096 */
254*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.SglPageCnt = 2;
255*8f23e9faSHans Rosenfeld 
256*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MinRqSize = 128;
257*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.MaxRqSize = 2048;
258*8f23e9faSHans Rosenfeld 
259*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.RPIMax = 0x3ff;
260*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.XRIMax = 0x3ff;
261*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.VFIMax = 0xff;
262*8f23e9faSHans Rosenfeld 	hba->sli.sli4.param.VPIMax = 0xff;
263*8f23e9faSHans Rosenfeld 
264*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
265*8f23e9faSHans Rosenfeld 	    "Default SLI4 parameters set.");
266*8f23e9faSHans Rosenfeld 
267*8f23e9faSHans Rosenfeld } /* emlxs_sli4_set_default_params() */
268*8f23e9faSHans Rosenfeld 
26982527734SSukumar Swaminathan 
27082527734SSukumar Swaminathan /*
27182527734SSukumar Swaminathan  * emlxs_sli4_online()
27282527734SSukumar Swaminathan  *
27382527734SSukumar Swaminathan  * This routine will start initialization of the SLI4 HBA.
27482527734SSukumar Swaminathan  */
27582527734SSukumar Swaminathan static int32_t
27682527734SSukumar Swaminathan emlxs_sli4_online(emlxs_hba_t *hba)
27782527734SSukumar Swaminathan {
27882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
27982527734SSukumar Swaminathan 	emlxs_config_t *cfg;
28082527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
28182527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
28282527734SSukumar Swaminathan 	MAILBOX4 *mb  = NULL;
28382527734SSukumar Swaminathan 	MATCHMAP *mp  = NULL;
28482527734SSukumar Swaminathan 	uint32_t i;
28582527734SSukumar Swaminathan 	uint32_t j;
28682527734SSukumar Swaminathan 	uint32_t rval = 0;
28782527734SSukumar Swaminathan 	uint8_t *vpd_data;
28882527734SSukumar Swaminathan 	uint32_t sli_mode;
28982527734SSukumar Swaminathan 	uint8_t *outptr;
29082527734SSukumar Swaminathan 	uint32_t status;
29182527734SSukumar Swaminathan 	uint32_t fw_check;
2926a573d82SSukumar Swaminathan 	uint32_t kern_update = 0;
29382527734SSukumar Swaminathan 	emlxs_firmware_t hba_fw;
29482527734SSukumar Swaminathan 	emlxs_firmware_t *fw;
295a9800bebSGarrett D'Amore 	uint16_t ssvid;
296*8f23e9faSHans Rosenfeld 	char buf[64];
29782527734SSukumar Swaminathan 
29882527734SSukumar Swaminathan 	cfg = &CFG;
29982527734SSukumar Swaminathan 	vpd = &VPD;
30082527734SSukumar Swaminathan 
30182527734SSukumar Swaminathan 	sli_mode = EMLXS_HBA_SLI4_MODE;
30282527734SSukumar Swaminathan 	hba->sli_mode = sli_mode;
30382527734SSukumar Swaminathan 
30482527734SSukumar Swaminathan 	/* Set the fw_check flag */
30582527734SSukumar Swaminathan 	fw_check = cfg[CFG_FW_CHECK].current;
30682527734SSukumar Swaminathan 
3076a573d82SSukumar Swaminathan 	if ((fw_check & 0x04) ||
3086a573d82SSukumar Swaminathan 	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
3096a573d82SSukumar Swaminathan 		kern_update = 1;
3106a573d82SSukumar Swaminathan 	}
3116a573d82SSukumar Swaminathan 
31282527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
31382527734SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
31482527734SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
31582527734SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
31682527734SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
31782527734SSukumar Swaminathan 
31882527734SSukumar Swaminathan 	/* Networking not supported */
31982527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
32082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
321*8f23e9faSHans Rosenfeld 		    "Networking is not supported in SLI4, turning it off");
32282527734SSukumar Swaminathan 		cfg[CFG_NETWORK_ON].current = 0;
32382527734SSukumar Swaminathan 	}
32482527734SSukumar Swaminathan 
32582527734SSukumar Swaminathan 	hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
32682527734SSukumar Swaminathan 	if (hba->chan_count > MAX_CHANNEL) {
32782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
32882527734SSukumar Swaminathan 		    "Max channels exceeded, dropping num-wq from %d to 1",
32982527734SSukumar Swaminathan 		    cfg[CFG_NUM_WQ].current);
33082527734SSukumar Swaminathan 		cfg[CFG_NUM_WQ].current = 1;
33182527734SSukumar Swaminathan 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
33282527734SSukumar Swaminathan 	}
33382527734SSukumar Swaminathan 	hba->channel_fcp = 0; /* First channel */
33482527734SSukumar Swaminathan 
33582527734SSukumar Swaminathan 	/* Default channel for everything else is the last channel */
33682527734SSukumar Swaminathan 	hba->channel_ip = hba->chan_count - 1;
33782527734SSukumar Swaminathan 	hba->channel_els = hba->chan_count - 1;
33882527734SSukumar Swaminathan 	hba->channel_ct = hba->chan_count - 1;
33982527734SSukumar Swaminathan 
34082527734SSukumar Swaminathan 	hba->fc_iotag = 1;
34182527734SSukumar Swaminathan 	hba->io_count = 0;
34282527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
34382527734SSukumar Swaminathan 
34482527734SSukumar Swaminathan 	/* Initialize the local dump region buffer */
34582527734SSukumar Swaminathan 	bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
34682527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
34782527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
34882527734SSukumar Swaminathan 	    | FC_MBUF_DMA32;
34982527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
35082527734SSukumar Swaminathan 
35182527734SSukumar Swaminathan 	(void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
35282527734SSukumar Swaminathan 
35382527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt == NULL) {
35482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
35582527734SSukumar Swaminathan 		    "Unable to allocate dump region buffer.");
35682527734SSukumar Swaminathan 
35782527734SSukumar Swaminathan 		return (ENOMEM);
35882527734SSukumar Swaminathan 	}
35982527734SSukumar Swaminathan 
36082527734SSukumar Swaminathan 	/*
36182527734SSukumar Swaminathan 	 * Get a buffer which will be used repeatedly for mailbox commands
36282527734SSukumar Swaminathan 	 */
36382527734SSukumar Swaminathan 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
36482527734SSukumar Swaminathan 
36582527734SSukumar Swaminathan 	mb = (MAILBOX4 *)mbq;
36682527734SSukumar Swaminathan 
36782527734SSukumar Swaminathan reset:
36882527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
36982527734SSukumar Swaminathan 	if (emlxs_sli4_hba_init(hba)) {
37082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
37182527734SSukumar Swaminathan 		    "Unable to init hba.");
37282527734SSukumar Swaminathan 
37382527734SSukumar Swaminathan 		rval = EIO;
37482527734SSukumar Swaminathan 		goto failed1;
37582527734SSukumar Swaminathan 	}
37682527734SSukumar Swaminathan 
37782527734SSukumar Swaminathan #ifdef FMA_SUPPORT
37882527734SSukumar Swaminathan 	/* Access handle validation */
379*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
380*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
381*8f23e9faSHans Rosenfeld 		if ((emlxs_fm_check_acc_handle(hba,
382*8f23e9faSHans Rosenfeld 		    hba->pci_acc_handle) != DDI_FM_OK) ||
383*8f23e9faSHans Rosenfeld 		    (emlxs_fm_check_acc_handle(hba,
384*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.bar0_acc_handle) != DDI_FM_OK)) {
385*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
386*8f23e9faSHans Rosenfeld 			    &emlxs_invalid_access_handle_msg, NULL);
38782527734SSukumar Swaminathan 
388*8f23e9faSHans Rosenfeld 			rval = EIO;
389*8f23e9faSHans Rosenfeld 			goto failed1;
390*8f23e9faSHans Rosenfeld 		}
391*8f23e9faSHans Rosenfeld 		break;
392*8f23e9faSHans Rosenfeld 
393*8f23e9faSHans Rosenfeld 	default :
394*8f23e9faSHans Rosenfeld 		if ((emlxs_fm_check_acc_handle(hba,
395*8f23e9faSHans Rosenfeld 		    hba->pci_acc_handle) != DDI_FM_OK) ||
396*8f23e9faSHans Rosenfeld 		    (emlxs_fm_check_acc_handle(hba,
397*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.bar1_acc_handle) != DDI_FM_OK) ||
398*8f23e9faSHans Rosenfeld 		    (emlxs_fm_check_acc_handle(hba,
399*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.bar2_acc_handle) != DDI_FM_OK)) {
400*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
401*8f23e9faSHans Rosenfeld 			    &emlxs_invalid_access_handle_msg, NULL);
402*8f23e9faSHans Rosenfeld 
403*8f23e9faSHans Rosenfeld 			rval = EIO;
404*8f23e9faSHans Rosenfeld 			goto failed1;
405*8f23e9faSHans Rosenfeld 		}
406*8f23e9faSHans Rosenfeld 		break;
40782527734SSukumar Swaminathan 	}
40882527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
40982527734SSukumar Swaminathan 
41082527734SSukumar Swaminathan 	/*
41182527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
41282527734SSukumar Swaminathan 	 */
41382527734SSukumar Swaminathan 	vpd->opFwRev = 0;
41482527734SSukumar Swaminathan 	vpd->postKernRev = 0;
41582527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
41682527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
41782527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
41882527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
41982527734SSukumar Swaminathan 
42082527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
42182527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
42282527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
42382527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
42482527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
42582527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
42682527734SSukumar Swaminathan 
42782527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
42882527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
42982527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
43082527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
43182527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
43282527734SSukumar Swaminathan 
43382527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
43482527734SSukumar Swaminathan 
435*8f23e9faSHans Rosenfeld 	emlxs_mb_get_sli4_params(hba, mbq);
436*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
437*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
438*8f23e9faSHans Rosenfeld 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
439*8f23e9faSHans Rosenfeld 		    mb->mbxCommand, mb->mbxStatus);
440*8f23e9faSHans Rosenfeld 
441*8f23e9faSHans Rosenfeld 		/* Set param defaults */
442*8f23e9faSHans Rosenfeld 		emlxs_sli4_set_default_params(hba);
443*8f23e9faSHans Rosenfeld 
444*8f23e9faSHans Rosenfeld 	} else {
445*8f23e9faSHans Rosenfeld 		/* Save parameters */
446*8f23e9faSHans Rosenfeld 		bcopy((char *)&mb->un.varSLIConfig.payload,
447*8f23e9faSHans Rosenfeld 		    (char *)&hba->sli.sli4.param, sizeof (sli_params_t));
448*8f23e9faSHans Rosenfeld 
449*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "SLI_PARMS",
450*8f23e9faSHans Rosenfeld 		    (uint32_t *)&hba->sli.sli4.param,
451*8f23e9faSHans Rosenfeld 		    sizeof (sli_params_t), 0);
452*8f23e9faSHans Rosenfeld 	}
453*8f23e9faSHans Rosenfeld 
454*8f23e9faSHans Rosenfeld 	/* Reuse mbq from previous mbox */
455*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
456*8f23e9faSHans Rosenfeld 
457*8f23e9faSHans Rosenfeld 	emlxs_mb_get_port_name(hba, mbq);
458*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
459*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
460*8f23e9faSHans Rosenfeld 		    "Unable to get port names. Mailbox cmd=%x status=%x",
461*8f23e9faSHans Rosenfeld 		    mb->mbxCommand, mb->mbxStatus);
462*8f23e9faSHans Rosenfeld 
463*8f23e9faSHans Rosenfeld 		bzero(hba->sli.sli4.port_name,
464*8f23e9faSHans Rosenfeld 		    sizeof (hba->sli.sli4.port_name));
465*8f23e9faSHans Rosenfeld 	} else {
466*8f23e9faSHans Rosenfeld 		/* Save port names */
467*8f23e9faSHans Rosenfeld 		bcopy((char *)&mb->un.varSLIConfig.payload,
468*8f23e9faSHans Rosenfeld 		    (char *)&hba->sli.sli4.port_name,
469*8f23e9faSHans Rosenfeld 		    sizeof (hba->sli.sli4.port_name));
470*8f23e9faSHans Rosenfeld 	}
471*8f23e9faSHans Rosenfeld 
472*8f23e9faSHans Rosenfeld 	/* Reuse mbq from previous mbox */
473*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
474*8f23e9faSHans Rosenfeld 
47582527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
47682527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
47782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
47882527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
47982527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
48082527734SSukumar Swaminathan 
48182527734SSukumar Swaminathan 		rval = EIO;
48282527734SSukumar Swaminathan 		goto failed1;
48382527734SSukumar Swaminathan 
48482527734SSukumar Swaminathan 	}
48582527734SSukumar Swaminathan 
486*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0);
48782527734SSukumar Swaminathan 	if (mb->un.varRdRev4.sliLevel != 4) {
48882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
48982527734SSukumar Swaminathan 		    "Invalid read rev Version for SLI4: 0x%x",
49082527734SSukumar Swaminathan 		    mb->un.varRdRev4.sliLevel);
49182527734SSukumar Swaminathan 
49282527734SSukumar Swaminathan 		rval = EIO;
49382527734SSukumar Swaminathan 		goto failed1;
49482527734SSukumar Swaminathan 	}
49582527734SSukumar Swaminathan 
49682527734SSukumar Swaminathan 	switch (mb->un.varRdRev4.dcbxMode) {
49782527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CIN:	/* Mapped to nonFIP mode */
49882527734SSukumar Swaminathan 		hba->flag &= ~FC_FIP_SUPPORTED;
49982527734SSukumar Swaminathan 		break;
50082527734SSukumar Swaminathan 
50182527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CEE:	/* Mapped to FIP mode */
50282527734SSukumar Swaminathan 		hba->flag |= FC_FIP_SUPPORTED;
50382527734SSukumar Swaminathan 		break;
50482527734SSukumar Swaminathan 
50582527734SSukumar Swaminathan 	default:
50682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
50782527734SSukumar Swaminathan 		    "Invalid read rev dcbx mode for SLI4: 0x%x",
50882527734SSukumar Swaminathan 		    mb->un.varRdRev4.dcbxMode);
50982527734SSukumar Swaminathan 
51082527734SSukumar Swaminathan 		rval = EIO;
51182527734SSukumar Swaminathan 		goto failed1;
51282527734SSukumar Swaminathan 	}
51382527734SSukumar Swaminathan 
514*8f23e9faSHans Rosenfeld 	/* Set FC/FCoE mode */
515*8f23e9faSHans Rosenfeld 	if (mb->un.varRdRev4.FCoE) {
516*8f23e9faSHans Rosenfeld 		hba->sli.sli4.flag |= EMLXS_SLI4_FCOE_MODE;
517*8f23e9faSHans Rosenfeld 	} else {
518*8f23e9faSHans Rosenfeld 		hba->sli.sli4.flag &= ~EMLXS_SLI4_FCOE_MODE;
519*8f23e9faSHans Rosenfeld 	}
52082527734SSukumar Swaminathan 
52182527734SSukumar Swaminathan 	/* Save information as VPD data */
52282527734SSukumar Swaminathan 	vpd->rBit = 1;
52382527734SSukumar Swaminathan 
52482527734SSukumar Swaminathan 	vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
52582527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
52682527734SSukumar Swaminathan 
52782527734SSukumar Swaminathan 	vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
52882527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
52982527734SSukumar Swaminathan 
53082527734SSukumar Swaminathan 	vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
53182527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
53282527734SSukumar Swaminathan 
533*8f23e9faSHans Rosenfeld 	vpd->biuRev = mb->un.varRdRev4.HwRev1;
53482527734SSukumar Swaminathan 	vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
53582527734SSukumar Swaminathan 	vpd->fcphLow = mb->un.varRdRev4.fcphLow;
53682527734SSukumar Swaminathan 	vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
53782527734SSukumar Swaminathan 	vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
53882527734SSukumar Swaminathan 
53982527734SSukumar Swaminathan 	/* Decode FW labels */
540*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
541*8f23e9faSHans Rosenfeld 		bcopy(vpd->postKernName, vpd->sli4FwName, 16);
542*8f23e9faSHans Rosenfeld 	}
543*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0,
544*8f23e9faSHans Rosenfeld 	    sizeof (vpd->sli4FwName));
545*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0,
546*8f23e9faSHans Rosenfeld 	    sizeof (vpd->opFwName));
547*8f23e9faSHans Rosenfeld 	emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0,
548*8f23e9faSHans Rosenfeld 	    sizeof (vpd->postKernName));
54982527734SSukumar Swaminathan 
550a9800bebSGarrett D'Amore 	if (hba->model_info.chip == EMLXS_BE2_CHIP) {
551*8f23e9faSHans Rosenfeld 		(void) strlcpy(vpd->sli4FwLabel, "be2.ufi",
552*8f23e9faSHans Rosenfeld 		    sizeof (vpd->sli4FwLabel));
553a9800bebSGarrett D'Amore 	} else if (hba->model_info.chip == EMLXS_BE3_CHIP) {
554*8f23e9faSHans Rosenfeld 		(void) strlcpy(vpd->sli4FwLabel, "be3.ufi",
555*8f23e9faSHans Rosenfeld 		    sizeof (vpd->sli4FwLabel));
556*8f23e9faSHans Rosenfeld 	} else if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
557*8f23e9faSHans Rosenfeld 		(void) strlcpy(vpd->sli4FwLabel, "xe201.grp",
558*8f23e9faSHans Rosenfeld 		    sizeof (vpd->sli4FwLabel));
55982527734SSukumar Swaminathan 	} else {
560*8f23e9faSHans Rosenfeld 		(void) strlcpy(vpd->sli4FwLabel, "sli4.fw",
561*8f23e9faSHans Rosenfeld 		    sizeof (vpd->sli4FwLabel));
56282527734SSukumar Swaminathan 	}
56382527734SSukumar Swaminathan 
564*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
56582527734SSukumar Swaminathan 	    "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
56682527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
56782527734SSukumar Swaminathan 	    vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
56882527734SSukumar Swaminathan 	    mb->un.varRdRev4.dcbxMode);
56982527734SSukumar Swaminathan 
57082527734SSukumar Swaminathan 	/* No key information is needed for SLI4 products */
57182527734SSukumar Swaminathan 
57282527734SSukumar Swaminathan 	/* Get adapter VPD information */
57382527734SSukumar Swaminathan 	vpd->port_index = (uint32_t)-1;
57482527734SSukumar Swaminathan 
57582527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
57682527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
57782527734SSukumar Swaminathan 
57882527734SSukumar Swaminathan 	emlxs_mb_dump_vpd(hba, mbq, 0);
57982527734SSukumar Swaminathan 	vpd_data = hba->sli.sli4.dump_region.virt;
58082527734SSukumar Swaminathan 
58182527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
58282527734SSukumar Swaminathan 	    MBX_SUCCESS) {
58382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
58482527734SSukumar Swaminathan 		    "No VPD found. status=%x", mb->mbxStatus);
58582527734SSukumar Swaminathan 	} else {
58682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
58782527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
58882527734SSukumar Swaminathan 		    "VPD dumped. rsp_cnt=%d status=%x",
58982527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
59082527734SSukumar Swaminathan 
59182527734SSukumar Swaminathan 		if (mb->un.varDmp4.rsp_cnt) {
59282527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
59382527734SSukumar Swaminathan 			    0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
59482527734SSukumar Swaminathan 
595b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
596b3660a96SSukumar Swaminathan 			if (hba->sli.sli4.dump_region.dma_handle) {
597b3660a96SSukumar Swaminathan 				if (emlxs_fm_check_dma_handle(hba,
598b3660a96SSukumar Swaminathan 				    hba->sli.sli4.dump_region.dma_handle)
599b3660a96SSukumar Swaminathan 				    != DDI_FM_OK) {
600b3660a96SSukumar Swaminathan 					EMLXS_MSGF(EMLXS_CONTEXT,
601b3660a96SSukumar Swaminathan 					    &emlxs_invalid_dma_handle_msg,
602*8f23e9faSHans Rosenfeld 					    "sli4_online: hdl=%p",
603b3660a96SSukumar Swaminathan 					    hba->sli.sli4.dump_region.
604b3660a96SSukumar Swaminathan 					    dma_handle);
605b3660a96SSukumar Swaminathan 					rval = EIO;
606b3660a96SSukumar Swaminathan 					goto failed1;
607b3660a96SSukumar Swaminathan 				}
608b3660a96SSukumar Swaminathan 			}
609b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */
610b3660a96SSukumar Swaminathan 
61182527734SSukumar Swaminathan 		}
61282527734SSukumar Swaminathan 	}
61382527734SSukumar Swaminathan 
61482527734SSukumar Swaminathan 	if (vpd_data[0]) {
61582527734SSukumar Swaminathan 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
61682527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt);
61782527734SSukumar Swaminathan 
61882527734SSukumar Swaminathan 		/*
61982527734SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
62082527734SSukumar Swaminathan 		 * match the current default HBA model info,
62182527734SSukumar Swaminathan 		 * replace the default data with an entry that
62282527734SSukumar Swaminathan 		 * does match.
62382527734SSukumar Swaminathan 		 *
62482527734SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
62582527734SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
62682527734SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
62782527734SSukumar Swaminathan 		 */
62882527734SSukumar Swaminathan 
62982527734SSukumar Swaminathan 		rval = 0;
63082527734SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
63182527734SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
63282527734SSukumar Swaminathan 
63382527734SSukumar Swaminathan 			/* First scan for a V2 match */
63482527734SSukumar Swaminathan 
63582527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
63682527734SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
63782527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
63882527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
63982527734SSukumar Swaminathan 					    &hba->model_info,
64082527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
64182527734SSukumar Swaminathan 					rval = 1;
64282527734SSukumar Swaminathan 					break;
64382527734SSukumar Swaminathan 				}
64482527734SSukumar Swaminathan 			}
64582527734SSukumar Swaminathan 		}
64682527734SSukumar Swaminathan 
64782527734SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
64882527734SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
64982527734SSukumar Swaminathan 
65082527734SSukumar Swaminathan 			/* Next scan for a PN match */
65182527734SSukumar Swaminathan 
65282527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
65382527734SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
65482527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
65582527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
65682527734SSukumar Swaminathan 					    &hba->model_info,
65782527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
65882527734SSukumar Swaminathan 					break;
65982527734SSukumar Swaminathan 				}
66082527734SSukumar Swaminathan 			}
66182527734SSukumar Swaminathan 		}
66282527734SSukumar Swaminathan 
663a9800bebSGarrett D'Amore 		/* HP CNA port indices start at 1 instead of 0 */
664*8f23e9faSHans Rosenfeld 		if (hba->model_info.chip & EMLXS_BE_CHIPS) {
665a9800bebSGarrett D'Amore 			ssvid = ddi_get16(hba->pci_acc_handle,
666a9800bebSGarrett D'Amore 			    (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER));
667a9800bebSGarrett D'Amore 
668a9800bebSGarrett D'Amore 			if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) {
669a9800bebSGarrett D'Amore 				vpd->port_index--;
670a9800bebSGarrett D'Amore 			}
671a9800bebSGarrett D'Amore 		}
672a9800bebSGarrett D'Amore 
67382527734SSukumar Swaminathan 		/*
67482527734SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
67582527734SSukumar Swaminathan 		 * VPD data, if any.
67682527734SSukumar Swaminathan 		 */
67782527734SSukumar Swaminathan 
67882527734SSukumar Swaminathan 		/*
67982527734SSukumar Swaminathan 		 * Replace the default model description with vpd data
68082527734SSukumar Swaminathan 		 */
68182527734SSukumar Swaminathan 		if (vpd->model_desc[0] != 0) {
682*8f23e9faSHans Rosenfeld 			(void) strncpy(hba->model_info.model_desc,
683*8f23e9faSHans Rosenfeld 			    vpd->model_desc,
684*8f23e9faSHans Rosenfeld 			    (sizeof (hba->model_info.model_desc)-1));
68582527734SSukumar Swaminathan 		}
68682527734SSukumar Swaminathan 
68782527734SSukumar Swaminathan 		/* Replace the default model with vpd data */
68882527734SSukumar Swaminathan 		if (vpd->model[0] != 0) {
689*8f23e9faSHans Rosenfeld 			(void) strncpy(hba->model_info.model, vpd->model,
690*8f23e9faSHans Rosenfeld 			    (sizeof (hba->model_info.model)-1));
69182527734SSukumar Swaminathan 		}
69282527734SSukumar Swaminathan 
69382527734SSukumar Swaminathan 		/* Replace the default program types with vpd data */
69482527734SSukumar Swaminathan 		if (vpd->prog_types[0] != 0) {
69582527734SSukumar Swaminathan 			emlxs_parse_prog_types(hba, vpd->prog_types);
69682527734SSukumar Swaminathan 		}
69782527734SSukumar Swaminathan 	}
69882527734SSukumar Swaminathan 
69982527734SSukumar Swaminathan 	/*
70082527734SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
70182527734SSukumar Swaminathan 	 * lets double check if adapter is not supported
70282527734SSukumar Swaminathan 	 */
70382527734SSukumar Swaminathan 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
70482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
70582527734SSukumar Swaminathan 		    "Unsupported adapter found.  "
70682527734SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
70782527734SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
70882527734SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
70982527734SSukumar Swaminathan 
71082527734SSukumar Swaminathan 		rval = EIO;
71182527734SSukumar Swaminathan 		goto failed1;
71282527734SSukumar Swaminathan 	}
71382527734SSukumar Swaminathan 
714*8f23e9faSHans Rosenfeld 	(void) strncpy(vpd->boot_version, vpd->sli4FwName,
715*8f23e9faSHans Rosenfeld 	    (sizeof (vpd->boot_version)-1));
71682527734SSukumar Swaminathan 
71782527734SSukumar Swaminathan 	/* Get fcode version property */
71882527734SSukumar Swaminathan 	emlxs_get_fcode_version(hba);
71982527734SSukumar Swaminathan 
72082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
72182527734SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
72282527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
72382527734SSukumar Swaminathan 
72482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
72582527734SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
72682527734SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
72782527734SSukumar Swaminathan 
72882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
72982527734SSukumar Swaminathan 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
73082527734SSukumar Swaminathan 
73182527734SSukumar Swaminathan 	/*
73282527734SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
73382527734SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
73482527734SSukumar Swaminathan 	 */
7356a573d82SSukumar Swaminathan 	hba->fw_flag = 0;
7366a573d82SSukumar Swaminathan 	hba->fw_timer = 0;
7376a573d82SSukumar Swaminathan 
738*8f23e9faSHans Rosenfeld 	if (((fw_check & 0x1) &&
739*8f23e9faSHans Rosenfeld 	    (hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
740*8f23e9faSHans Rosenfeld 	    hba->model_info.fwid) ||
741*8f23e9faSHans Rosenfeld 	    ((fw_check & 0x2) && hba->model_info.fwid)) {
74282527734SSukumar Swaminathan 
74382527734SSukumar Swaminathan 		/* Find firmware image indicated by adapter model */
74482527734SSukumar Swaminathan 		fw = NULL;
74582527734SSukumar Swaminathan 		for (i = 0; i < emlxs_fw_count; i++) {
74682527734SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
74782527734SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
74882527734SSukumar Swaminathan 				break;
74982527734SSukumar Swaminathan 			}
75082527734SSukumar Swaminathan 		}
75182527734SSukumar Swaminathan 
75282527734SSukumar Swaminathan 		/*
75382527734SSukumar Swaminathan 		 * If the image was found, then verify current firmware
75482527734SSukumar Swaminathan 		 * versions of adapter
75582527734SSukumar Swaminathan 		 */
75682527734SSukumar Swaminathan 		if (fw) {
75782527734SSukumar Swaminathan 			/* Obtain current firmware version info */
758*8f23e9faSHans Rosenfeld 			if (hba->model_info.chip & EMLXS_BE_CHIPS) {
759*8f23e9faSHans Rosenfeld 				(void) emlxs_be_read_fw_version(hba, &hba_fw);
76082527734SSukumar Swaminathan 			} else {
76182527734SSukumar Swaminathan 				hba_fw.kern = vpd->postKernRev;
76282527734SSukumar Swaminathan 				hba_fw.stub = vpd->opFwRev;
76382527734SSukumar Swaminathan 				hba_fw.sli1 = vpd->sli1FwRev;
76482527734SSukumar Swaminathan 				hba_fw.sli2 = vpd->sli2FwRev;
76582527734SSukumar Swaminathan 				hba_fw.sli3 = vpd->sli3FwRev;
76682527734SSukumar Swaminathan 				hba_fw.sli4 = vpd->sli4FwRev;
76782527734SSukumar Swaminathan 			}
76882527734SSukumar Swaminathan 
7696a573d82SSukumar Swaminathan 			if (!kern_update &&
7706a573d82SSukumar Swaminathan 			    ((fw->kern && (hba_fw.kern != fw->kern)) ||
7716a573d82SSukumar Swaminathan 			    (fw->stub && (hba_fw.stub != fw->stub)))) {
7726a573d82SSukumar Swaminathan 
7736a573d82SSukumar Swaminathan 				hba->fw_flag |= FW_UPDATE_NEEDED;
7746a573d82SSukumar Swaminathan 
7756a573d82SSukumar Swaminathan 			} else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
77682527734SSukumar Swaminathan 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
77782527734SSukumar Swaminathan 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
77882527734SSukumar Swaminathan 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
77982527734SSukumar Swaminathan 			    (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
78082527734SSukumar Swaminathan 			    (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
78182527734SSukumar Swaminathan 
78282527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
78382527734SSukumar Swaminathan 				    "Firmware update needed. "
78482527734SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
78582527734SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
78682527734SSukumar Swaminathan 
78782527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
78882527734SSukumar Swaminathan 				/*
78982527734SSukumar Swaminathan 				 * Load the firmware image now
79082527734SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
79182527734SSukumar Swaminathan 				 * firmware image will already be defined
79282527734SSukumar Swaminathan 				 * in the emlxs_fw_table
79382527734SSukumar Swaminathan 				 */
79482527734SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
79582527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
79682527734SSukumar Swaminathan 
79782527734SSukumar Swaminathan 				if (fw->image && fw->size) {
798*8f23e9faSHans Rosenfeld 					uint32_t rc;
799*8f23e9faSHans Rosenfeld 
800*8f23e9faSHans Rosenfeld 					rc = emlxs_fw_download(hba,
801*8f23e9faSHans Rosenfeld 					    (char *)fw->image, fw->size, 0);
802*8f23e9faSHans Rosenfeld 					if ((rc != FC_SUCCESS) &&
803*8f23e9faSHans Rosenfeld 					    (rc != EMLXS_REBOOT_REQUIRED)) {
80482527734SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
80582527734SSukumar Swaminathan 						    &emlxs_init_msg,
80682527734SSukumar Swaminathan 						    "Firmware update failed.");
8076a573d82SSukumar Swaminathan 						hba->fw_flag |=
8086a573d82SSukumar Swaminathan 						    FW_UPDATE_NEEDED;
80982527734SSukumar Swaminathan 					}
81082527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
81182527734SSukumar Swaminathan 					/*
81282527734SSukumar Swaminathan 					 * Unload the firmware image from
81382527734SSukumar Swaminathan 					 * kernel memory
81482527734SSukumar Swaminathan 					 */
81582527734SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
81682527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
81782527734SSukumar Swaminathan 
81882527734SSukumar Swaminathan 					fw_check = 0;
81982527734SSukumar Swaminathan 
82082527734SSukumar Swaminathan 					goto reset;
82182527734SSukumar Swaminathan 				}
82282527734SSukumar Swaminathan 
823*8f23e9faSHans Rosenfeld 				hba->fw_flag |= FW_UPDATE_NEEDED;
824*8f23e9faSHans Rosenfeld 
82582527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
82682527734SSukumar Swaminathan 				    "Firmware image unavailable.");
82782527734SSukumar Swaminathan 			} else {
82882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
82982527734SSukumar Swaminathan 				    "Firmware update not needed.");
83082527734SSukumar Swaminathan 			}
83182527734SSukumar Swaminathan 		} else {
83282527734SSukumar Swaminathan 			/*
83382527734SSukumar Swaminathan 			 * This means either the adapter database is not
83482527734SSukumar Swaminathan 			 * correct or a firmware image is missing from the
83582527734SSukumar Swaminathan 			 * compile
83682527734SSukumar Swaminathan 			 */
83782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
83882527734SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
83982527734SSukumar Swaminathan 			    hba->model_info.id, hba->model_info.fwid);
84082527734SSukumar Swaminathan 		}
84182527734SSukumar Swaminathan 	}
84282527734SSukumar Swaminathan 
84382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
84482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
84582527734SSukumar Swaminathan 
84682527734SSukumar Swaminathan 	emlxs_mb_dump_fcoe(hba, mbq, 0);
84782527734SSukumar Swaminathan 
84882527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
84982527734SSukumar Swaminathan 	    MBX_SUCCESS) {
85082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
85182527734SSukumar Swaminathan 		    "No FCOE info found. status=%x", mb->mbxStatus);
85282527734SSukumar Swaminathan 	} else {
85382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
85482527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
85582527734SSukumar Swaminathan 		    "FCOE info dumped. rsp_cnt=%d status=%x",
85682527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
85782527734SSukumar Swaminathan 		(void) emlxs_parse_fcoe(hba,
858fe199829SSukumar Swaminathan 		    (uint8_t *)hba->sli.sli4.dump_region.virt,
859fe199829SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt);
86082527734SSukumar Swaminathan 	}
86182527734SSukumar Swaminathan 
86282527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
86382527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
86482527734SSukumar Swaminathan 
865*8f23e9faSHans Rosenfeld 	status = 0;
866*8f23e9faSHans Rosenfeld 	if (port->flag & EMLXS_INI_ENABLED) {
867*8f23e9faSHans Rosenfeld 		status |= SLI4_FEATURE_FCP_INITIATOR;
868*8f23e9faSHans Rosenfeld 	}
869*8f23e9faSHans Rosenfeld 	if (port->flag & EMLXS_TGT_ENABLED) {
870*8f23e9faSHans Rosenfeld 		status |= SLI4_FEATURE_FCP_TARGET;
871*8f23e9faSHans Rosenfeld 	}
872*8f23e9faSHans Rosenfeld 	if (cfg[CFG_NPIV_ENABLE].current) {
873*8f23e9faSHans Rosenfeld 		status |= SLI4_FEATURE_NPIV;
874*8f23e9faSHans Rosenfeld 	}
875*8f23e9faSHans Rosenfeld 	if (cfg[CFG_RQD_MODE].current) {
876*8f23e9faSHans Rosenfeld 		status |= SLI4_FEATURE_RQD;
877*8f23e9faSHans Rosenfeld 	}
878*8f23e9faSHans Rosenfeld 	if (cfg[CFG_PERF_HINT].current) {
879*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.param.PHON) {
880*8f23e9faSHans Rosenfeld 			status |= SLI4_FEATURE_PERF_HINT;
881*8f23e9faSHans Rosenfeld 		}
882*8f23e9faSHans Rosenfeld 	}
883*8f23e9faSHans Rosenfeld 
884*8f23e9faSHans Rosenfeld 	emlxs_mb_request_features(hba, mbq, status);
88582527734SSukumar Swaminathan 
88682527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
88782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
88882527734SSukumar Swaminathan 		    "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
88982527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
89082527734SSukumar Swaminathan 
89182527734SSukumar Swaminathan 		rval = EIO;
89282527734SSukumar Swaminathan 		goto failed1;
89382527734SSukumar Swaminathan 	}
894*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
895*8f23e9faSHans Rosenfeld 
896*8f23e9faSHans Rosenfeld 	/* Check to see if we get the features we requested */
897*8f23e9faSHans Rosenfeld 	if (status != mb->un.varReqFeatures.featuresEnabled) {
898*8f23e9faSHans Rosenfeld 
899*8f23e9faSHans Rosenfeld 		/* Just report descrepencies, don't abort the attach */
900*8f23e9faSHans Rosenfeld 
901*8f23e9faSHans Rosenfeld 		outptr = (uint8_t *)emlxs_request_feature_xlate(
902*8f23e9faSHans Rosenfeld 		    mb->un.varReqFeatures.featuresRequested);
903*8f23e9faSHans Rosenfeld 		(void) strlcpy(buf, (char *)outptr, sizeof (buf));
904*8f23e9faSHans Rosenfeld 
905*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
906*8f23e9faSHans Rosenfeld 		    "REQUEST_FEATURES: wanted:%s  got:%s",
907*8f23e9faSHans Rosenfeld 		    &buf[0], emlxs_request_feature_xlate(
908*8f23e9faSHans Rosenfeld 		    mb->un.varReqFeatures.featuresEnabled));
909*8f23e9faSHans Rosenfeld 
910*8f23e9faSHans Rosenfeld 	}
911*8f23e9faSHans Rosenfeld 
912*8f23e9faSHans Rosenfeld 	if ((port->flag & EMLXS_INI_ENABLED) &&
913*8f23e9faSHans Rosenfeld 	    !(mb->un.varReqFeatures.featuresEnabled &
914*8f23e9faSHans Rosenfeld 	    SLI4_FEATURE_FCP_INITIATOR)) {
915*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
916*8f23e9faSHans Rosenfeld 		    "Initiator mode not supported by adapter.");
917*8f23e9faSHans Rosenfeld 
918*8f23e9faSHans Rosenfeld 		rval = EIO;
919*8f23e9faSHans Rosenfeld 
920*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
921*8f23e9faSHans Rosenfeld 		/* Check if we can fall back to just target mode */
922*8f23e9faSHans Rosenfeld 		if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
923*8f23e9faSHans Rosenfeld 		    (mb->un.varReqFeatures.featuresEnabled &
924*8f23e9faSHans Rosenfeld 		    SLI4_FEATURE_FCP_TARGET) &&
925*8f23e9faSHans Rosenfeld 		    (cfg[CFG_DTM_ENABLE].current == 1) &&
926*8f23e9faSHans Rosenfeld 		    (cfg[CFG_TARGET_MODE].current == 1)) {
92782527734SSukumar Swaminathan 
928*8f23e9faSHans Rosenfeld 			cfg[CFG_DTM_ENABLE].current = 0;
92982527734SSukumar Swaminathan 
930*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
931*8f23e9faSHans Rosenfeld 			    &emlxs_init_failed_msg,
932*8f23e9faSHans Rosenfeld 			    "Disabling dynamic target mode. "
933*8f23e9faSHans Rosenfeld 			    "Enabling target mode only.");
934*8f23e9faSHans Rosenfeld 
935*8f23e9faSHans Rosenfeld 			/* This will trigger the driver to reattach */
936*8f23e9faSHans Rosenfeld 			rval = EAGAIN;
937*8f23e9faSHans Rosenfeld 		}
938*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
939*8f23e9faSHans Rosenfeld 		goto failed1;
940*8f23e9faSHans Rosenfeld 	}
941*8f23e9faSHans Rosenfeld 
942*8f23e9faSHans Rosenfeld 	if ((port->flag & EMLXS_TGT_ENABLED) &&
943*8f23e9faSHans Rosenfeld 	    !(mb->un.varReqFeatures.featuresEnabled &
944*8f23e9faSHans Rosenfeld 	    SLI4_FEATURE_FCP_TARGET)) {
94582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
946*8f23e9faSHans Rosenfeld 		    "Target mode not supported by adapter.");
94782527734SSukumar Swaminathan 
94882527734SSukumar Swaminathan 		rval = EIO;
949*8f23e9faSHans Rosenfeld 
950*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
951*8f23e9faSHans Rosenfeld 		/* Check if we can fall back to just initiator mode */
952*8f23e9faSHans Rosenfeld 		if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
953*8f23e9faSHans Rosenfeld 		    (mb->un.varReqFeatures.featuresEnabled &
954*8f23e9faSHans Rosenfeld 		    SLI4_FEATURE_FCP_INITIATOR) &&
955*8f23e9faSHans Rosenfeld 		    (cfg[CFG_DTM_ENABLE].current == 1) &&
956*8f23e9faSHans Rosenfeld 		    (cfg[CFG_TARGET_MODE].current == 0)) {
957*8f23e9faSHans Rosenfeld 
958*8f23e9faSHans Rosenfeld 			cfg[CFG_DTM_ENABLE].current = 0;
959*8f23e9faSHans Rosenfeld 
960*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
961*8f23e9faSHans Rosenfeld 			    &emlxs_init_failed_msg,
962*8f23e9faSHans Rosenfeld 			    "Disabling dynamic target mode. "
963*8f23e9faSHans Rosenfeld 			    "Enabling initiator mode only.");
964*8f23e9faSHans Rosenfeld 
965*8f23e9faSHans Rosenfeld 			/* This will trigger the driver to reattach */
966*8f23e9faSHans Rosenfeld 			rval = EAGAIN;
967*8f23e9faSHans Rosenfeld 		}
968*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
96982527734SSukumar Swaminathan 		goto failed1;
97082527734SSukumar Swaminathan 	}
97182527734SSukumar Swaminathan 
97282527734SSukumar Swaminathan 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
97382527734SSukumar Swaminathan 		hba->flag |= FC_NPIV_ENABLED;
97482527734SSukumar Swaminathan 	}
97582527734SSukumar Swaminathan 
976*8f23e9faSHans Rosenfeld 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_PERF_HINT) {
977*8f23e9faSHans Rosenfeld 		hba->sli.sli4.flag |= EMLXS_SLI4_PHON;
978*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.param.PHWQ) {
979*8f23e9faSHans Rosenfeld 			hba->sli.sli4.flag |= EMLXS_SLI4_PHWQ;
980*8f23e9faSHans Rosenfeld 		}
98182527734SSukumar Swaminathan 	}
98282527734SSukumar Swaminathan 
98382527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
98482527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
98582527734SSukumar Swaminathan 
98682527734SSukumar Swaminathan 	emlxs_mb_read_config(hba, mbq);
98782527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
98882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
98982527734SSukumar Swaminathan 		    "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
99082527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
99182527734SSukumar Swaminathan 
99282527734SSukumar Swaminathan 		rval = EIO;
99382527734SSukumar Swaminathan 		goto failed1;
99482527734SSukumar Swaminathan 	}
995*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
996*8f23e9faSHans Rosenfeld 
997*8f23e9faSHans Rosenfeld 	/* Set default extents */
998*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRICount = mb->un.varRdConfig4.XRICount;
999*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIExtCount = 1;
1000*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIExtSize = hba->sli.sli4.XRICount;
1001*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIBase[0] = mb->un.varRdConfig4.XRIBase;
1002*8f23e9faSHans Rosenfeld 
1003*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPICount = mb->un.varRdConfig4.RPICount;
1004*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPIExtCount = 1;
1005*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPIExtSize = hba->sli.sli4.RPICount;
1006*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPIBase[0] = mb->un.varRdConfig4.RPIBase;
1007*8f23e9faSHans Rosenfeld 
1008*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPICount = mb->un.varRdConfig4.VPICount;
1009*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPIExtCount = 1;
1010*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPIExtSize = hba->sli.sli4.VPICount;
1011*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPIBase[0] = mb->un.varRdConfig4.VPIBase;
1012*8f23e9faSHans Rosenfeld 
1013*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFICount = mb->un.varRdConfig4.VFICount;
1014*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFIExtCount = 1;
1015*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFIExtSize = hba->sli.sli4.VFICount;
1016*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFIBase[0] = mb->un.varRdConfig4.VFIBase;
1017*8f23e9faSHans Rosenfeld 
1018*8f23e9faSHans Rosenfeld 	hba->sli.sli4.FCFICount = mb->un.varRdConfig4.FCFICount;
1019*8f23e9faSHans Rosenfeld 
1020*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1021*8f23e9faSHans Rosenfeld 	    "CONFIG: xri:%d rpi:%d vpi:%d vfi:%d fcfi:%d",
1022*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.XRICount,
1023*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.RPICount,
1024*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VPICount,
1025*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VFICount,
1026*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.FCFICount);
1027*8f23e9faSHans Rosenfeld 
1028*8f23e9faSHans Rosenfeld 	if ((hba->sli.sli4.XRICount == 0) ||
1029*8f23e9faSHans Rosenfeld 	    (hba->sli.sli4.RPICount == 0) ||
1030*8f23e9faSHans Rosenfeld 	    (hba->sli.sli4.VPICount == 0) ||
1031*8f23e9faSHans Rosenfeld 	    (hba->sli.sli4.VFICount == 0) ||
1032*8f23e9faSHans Rosenfeld 	    (hba->sli.sli4.FCFICount == 0)) {
1033*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1034*8f23e9faSHans Rosenfeld 		    "Invalid extent value(s) - xri:%d rpi:%d vpi:%d "
1035*8f23e9faSHans Rosenfeld 		    "vfi:%d fcfi:%d",
1036*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.XRICount,
1037*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RPICount,
1038*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VPICount,
1039*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VFICount,
1040*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.FCFICount);
1041*8f23e9faSHans Rosenfeld 
1042*8f23e9faSHans Rosenfeld 		rval = EIO;
1043*8f23e9faSHans Rosenfeld 		goto failed1;
1044*8f23e9faSHans Rosenfeld 	}
1045*8f23e9faSHans Rosenfeld 
1046*8f23e9faSHans Rosenfeld 	if (mb->un.varRdConfig4.extents) {
1047*8f23e9faSHans Rosenfeld 		if (emlxs_sli4_init_extents(hba, mbq)) {
1048*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1049*8f23e9faSHans Rosenfeld 			    "Unable to initialize extents.");
1050*8f23e9faSHans Rosenfeld 
1051*8f23e9faSHans Rosenfeld 			rval = EIO;
1052*8f23e9faSHans Rosenfeld 			goto failed1;
1053*8f23e9faSHans Rosenfeld 		}
1054*8f23e9faSHans Rosenfeld 	}
1055*8f23e9faSHans Rosenfeld 
1056*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1057*8f23e9faSHans Rosenfeld 	    "CONFIG: port_name:%c %c %c %c",
1058*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.port_name[0],
1059*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.port_name[1],
1060*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.port_name[2],
1061*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.port_name[3]);
1062*8f23e9faSHans Rosenfeld 
1063*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1064*8f23e9faSHans Rosenfeld 	    "CONFIG: ldv:%d link_type:%d link_number:%d",
1065*8f23e9faSHans Rosenfeld 	    mb->un.varRdConfig4.ldv,
1066*8f23e9faSHans Rosenfeld 	    mb->un.varRdConfig4.link_type,
1067*8f23e9faSHans Rosenfeld 	    mb->un.varRdConfig4.link_number);
106882527734SSukumar Swaminathan 
1069*8f23e9faSHans Rosenfeld 	if (mb->un.varRdConfig4.ldv) {
1070*8f23e9faSHans Rosenfeld 		hba->sli.sli4.link_number = mb->un.varRdConfig4.link_number;
1071*8f23e9faSHans Rosenfeld 	} else {
1072*8f23e9faSHans Rosenfeld 		hba->sli.sli4.link_number = (uint32_t)-1;
1073*8f23e9faSHans Rosenfeld 	}
107482527734SSukumar Swaminathan 
107582527734SSukumar Swaminathan 	if (hba->sli.sli4.VPICount) {
107682527734SSukumar Swaminathan 		hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
107782527734SSukumar Swaminathan 	}
107882527734SSukumar Swaminathan 
107982527734SSukumar Swaminathan 	/* Set the max node count */
108082527734SSukumar Swaminathan 	if (cfg[CFG_NUM_NODES].current > 0) {
108182527734SSukumar Swaminathan 		hba->max_nodes =
108282527734SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
108382527734SSukumar Swaminathan 		    hba->sli.sli4.RPICount);
108482527734SSukumar Swaminathan 	} else {
108582527734SSukumar Swaminathan 		hba->max_nodes = hba->sli.sli4.RPICount;
108682527734SSukumar Swaminathan 	}
108782527734SSukumar Swaminathan 
108882527734SSukumar Swaminathan 	/* Set the io throttle */
108982527734SSukumar Swaminathan 	hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
1090*8f23e9faSHans Rosenfeld 
1091*8f23e9faSHans Rosenfeld 	/* Set max_iotag */
1092*8f23e9faSHans Rosenfeld 	/* We add 1 in case all XRI's are non-zero */
1093*8f23e9faSHans Rosenfeld 	hba->max_iotag = hba->sli.sli4.XRICount + 1;
1094*8f23e9faSHans Rosenfeld 
1095*8f23e9faSHans Rosenfeld 	if (cfg[CFG_NUM_IOTAGS].current) {
1096*8f23e9faSHans Rosenfeld 		hba->max_iotag = min(hba->max_iotag,
1097*8f23e9faSHans Rosenfeld 		    (uint16_t)cfg[CFG_NUM_IOTAGS].current);
1098*8f23e9faSHans Rosenfeld 	}
1099*8f23e9faSHans Rosenfeld 
1100*8f23e9faSHans Rosenfeld 	/* Set out-of-range iotag base */
1101*8f23e9faSHans Rosenfeld 	hba->fc_oor_iotag = hba->max_iotag;
110282527734SSukumar Swaminathan 
110382527734SSukumar Swaminathan 	/* Save the link speed capabilities */
1104a9800bebSGarrett D'Amore 	vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt;
110582527734SSukumar Swaminathan 	emlxs_process_link_speed(hba);
110682527734SSukumar Swaminathan 
110782527734SSukumar Swaminathan 	/*
110882527734SSukumar Swaminathan 	 * Allocate some memory for buffers
110982527734SSukumar Swaminathan 	 */
111082527734SSukumar Swaminathan 	if (emlxs_mem_alloc_buffer(hba) == 0) {
111182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
111282527734SSukumar Swaminathan 		    "Unable to allocate memory buffers.");
111382527734SSukumar Swaminathan 
111482527734SSukumar Swaminathan 		rval = ENOMEM;
111582527734SSukumar Swaminathan 		goto failed1;
111682527734SSukumar Swaminathan 	}
111782527734SSukumar Swaminathan 
111882527734SSukumar Swaminathan 	if (emlxs_sli4_resource_alloc(hba)) {
111982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
112082527734SSukumar Swaminathan 		    "Unable to allocate resources.");
112182527734SSukumar Swaminathan 
112282527734SSukumar Swaminathan 		rval = ENOMEM;
112382527734SSukumar Swaminathan 		goto failed2;
112482527734SSukumar Swaminathan 	}
1125*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
1126*8f23e9faSHans Rosenfeld 	emlxs_sli4_zero_queue_stat(hba);
112782527734SSukumar Swaminathan 
112882527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
112982527734SSukumar Swaminathan 	if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
113082527734SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports = hba->vpi_max;
113182527734SSukumar Swaminathan 	}
113282527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
113382527734SSukumar Swaminathan 
113482527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
113582527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
113682527734SSukumar Swaminathan 
113782527734SSukumar Swaminathan 	if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
113882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
113982527734SSukumar Swaminathan 		    "Unable to post sgl pages.");
114082527734SSukumar Swaminathan 
114182527734SSukumar Swaminathan 		rval = EIO;
114282527734SSukumar Swaminathan 		goto failed3;
114382527734SSukumar Swaminathan 	}
114482527734SSukumar Swaminathan 
114582527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
114682527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
114782527734SSukumar Swaminathan 
114882527734SSukumar Swaminathan 	if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
114982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
115082527734SSukumar Swaminathan 		    "Unable to post header templates.");
115182527734SSukumar Swaminathan 
115282527734SSukumar Swaminathan 		rval = EIO;
115382527734SSukumar Swaminathan 		goto failed3;
115482527734SSukumar Swaminathan 	}
115582527734SSukumar Swaminathan 
115682527734SSukumar Swaminathan 	/*
115782527734SSukumar Swaminathan 	 * Add our interrupt routine to kernel's interrupt chain & enable it
115882527734SSukumar Swaminathan 	 * If MSI is enabled this will cause Solaris to program the MSI address
115982527734SSukumar Swaminathan 	 * and data registers in PCI config space
116082527734SSukumar Swaminathan 	 */
116182527734SSukumar Swaminathan 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
116282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
116382527734SSukumar Swaminathan 		    "Unable to add interrupt(s).");
116482527734SSukumar Swaminathan 
116582527734SSukumar Swaminathan 		rval = EIO;
116682527734SSukumar Swaminathan 		goto failed3;
116782527734SSukumar Swaminathan 	}
116882527734SSukumar Swaminathan 
116982527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
117082527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
117182527734SSukumar Swaminathan 
117282527734SSukumar Swaminathan 	/* This MUST be done after EMLXS_INTR_ADD */
117382527734SSukumar Swaminathan 	if (emlxs_sli4_create_queues(hba, mbq)) {
117482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
117582527734SSukumar Swaminathan 		    "Unable to create queues.");
117682527734SSukumar Swaminathan 
117782527734SSukumar Swaminathan 		rval = EIO;
117882527734SSukumar Swaminathan 		goto failed3;
117982527734SSukumar Swaminathan 	}
118082527734SSukumar Swaminathan 
118182527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
118282527734SSukumar Swaminathan 
118382527734SSukumar Swaminathan 	/* Get and save the current firmware version (based on sli_mode) */
118482527734SSukumar Swaminathan 	emlxs_decode_firmware_rev(hba, vpd);
118582527734SSukumar Swaminathan 
118682527734SSukumar Swaminathan 
118782527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
118882527734SSukumar Swaminathan 
1189*8f23e9faSHans Rosenfeld 	if (SLI4_FC_MODE) {
1190*8f23e9faSHans Rosenfeld 		/* Reuse mbq from previous mbox */
1191*8f23e9faSHans Rosenfeld 		bzero(mbq, sizeof (MAILBOXQ));
1192*8f23e9faSHans Rosenfeld 
1193*8f23e9faSHans Rosenfeld 		emlxs_mb_config_link(hba, mbq);
1194*8f23e9faSHans Rosenfeld 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1195*8f23e9faSHans Rosenfeld 		    MBX_SUCCESS) {
1196*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1197*8f23e9faSHans Rosenfeld 			    "Unable to configure link. Mailbox cmd=%x "
1198*8f23e9faSHans Rosenfeld 			    "status=%x",
1199*8f23e9faSHans Rosenfeld 			    mb->mbxCommand, mb->mbxStatus);
1200*8f23e9faSHans Rosenfeld 
1201*8f23e9faSHans Rosenfeld 			rval = EIO;
1202*8f23e9faSHans Rosenfeld 			goto failed3;
1203*8f23e9faSHans Rosenfeld 		}
1204*8f23e9faSHans Rosenfeld 	}
1205*8f23e9faSHans Rosenfeld 
120682527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
120782527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
120882527734SSukumar Swaminathan 
120982527734SSukumar Swaminathan 	/*
121082527734SSukumar Swaminathan 	 * We need to get login parameters for NID
121182527734SSukumar Swaminathan 	 */
121282527734SSukumar Swaminathan 	(void) emlxs_mb_read_sparam(hba, mbq);
1213a9800bebSGarrett D'Amore 	mp = (MATCHMAP *)mbq->bp;
121482527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
121582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
121682527734SSukumar Swaminathan 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
121782527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
121882527734SSukumar Swaminathan 
121982527734SSukumar Swaminathan 		rval = EIO;
122082527734SSukumar Swaminathan 		goto failed3;
122182527734SSukumar Swaminathan 	}
122282527734SSukumar Swaminathan 
122382527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
1224a9800bebSGarrett D'Amore 	emlxs_mem_put(hba, MEM_BUF, (void *)mp);
122582527734SSukumar Swaminathan 	mp = NULL;
122682527734SSukumar Swaminathan 
122782527734SSukumar Swaminathan 	/* If no serial number in VPD data, then use the WWPN */
122882527734SSukumar Swaminathan 	if (vpd->serial_num[0] == 0) {
122982527734SSukumar Swaminathan 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
123082527734SSukumar Swaminathan 		for (i = 0; i < 12; i++) {
123182527734SSukumar Swaminathan 			status = *outptr++;
123282527734SSukumar Swaminathan 			j = ((status & 0xf0) >> 4);
123382527734SSukumar Swaminathan 			if (j <= 9) {
123482527734SSukumar Swaminathan 				vpd->serial_num[i] =
123582527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
123682527734SSukumar Swaminathan 			} else {
123782527734SSukumar Swaminathan 				vpd->serial_num[i] =
123882527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
123982527734SSukumar Swaminathan 			}
124082527734SSukumar Swaminathan 
124182527734SSukumar Swaminathan 			i++;
124282527734SSukumar Swaminathan 			j = (status & 0xf);
124382527734SSukumar Swaminathan 			if (j <= 9) {
124482527734SSukumar Swaminathan 				vpd->serial_num[i] =
124582527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
124682527734SSukumar Swaminathan 			} else {
124782527734SSukumar Swaminathan 				vpd->serial_num[i] =
124882527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
124982527734SSukumar Swaminathan 			}
125082527734SSukumar Swaminathan 		}
125182527734SSukumar Swaminathan 
125282527734SSukumar Swaminathan 		/*
125382527734SSukumar Swaminathan 		 * Set port number and port index to zero
125482527734SSukumar Swaminathan 		 * The WWN's are unique to each port and therefore port_num
125582527734SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
125682527734SSukumar Swaminathan 		 * in fca_bind_port()
125782527734SSukumar Swaminathan 		 */
125882527734SSukumar Swaminathan 		vpd->port_num[0] = 0;
125982527734SSukumar Swaminathan 		vpd->port_index = 0;
1260*8f23e9faSHans Rosenfeld 
1261*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1262*8f23e9faSHans Rosenfeld 		    "CONFIG: WWPN: port_index=0");
126382527734SSukumar Swaminathan 	}
126482527734SSukumar Swaminathan 
1265*8f23e9faSHans Rosenfeld 	/* Make final attempt to set a port index */
1266a9800bebSGarrett D'Amore 	if (vpd->port_index == (uint32_t)-1) {
126782527734SSukumar Swaminathan 		dev_info_t *p_dip;
126882527734SSukumar Swaminathan 		dev_info_t *c_dip;
126982527734SSukumar Swaminathan 
127082527734SSukumar Swaminathan 		p_dip = ddi_get_parent(hba->dip);
127182527734SSukumar Swaminathan 		c_dip = ddi_get_child(p_dip);
127282527734SSukumar Swaminathan 
127382527734SSukumar Swaminathan 		vpd->port_index = 0;
127482527734SSukumar Swaminathan 		while (c_dip && (hba->dip != c_dip)) {
127582527734SSukumar Swaminathan 			c_dip = ddi_get_next_sibling(c_dip);
127682527734SSukumar Swaminathan 
1277*8f23e9faSHans Rosenfeld 			if (strcmp(ddi_get_name(c_dip), "ethernet") == 0) {
1278*8f23e9faSHans Rosenfeld 				continue;
127982527734SSukumar Swaminathan 			}
1280*8f23e9faSHans Rosenfeld 
1281*8f23e9faSHans Rosenfeld 			vpd->port_index++;
128282527734SSukumar Swaminathan 		}
1283*8f23e9faSHans Rosenfeld 
1284*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT,
1285*8f23e9faSHans Rosenfeld 		    &emlxs_init_debug_msg,
1286*8f23e9faSHans Rosenfeld 		    "CONFIG: Device tree: port_index=%d",
1287*8f23e9faSHans Rosenfeld 		    vpd->port_index);
128882527734SSukumar Swaminathan 	}
128982527734SSukumar Swaminathan 
129082527734SSukumar Swaminathan 	if (vpd->port_num[0] == 0) {
1291*8f23e9faSHans Rosenfeld 		if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) {
1292*8f23e9faSHans Rosenfeld 			(void) snprintf(vpd->port_num,
1293*8f23e9faSHans Rosenfeld 			    (sizeof (vpd->port_num)-1),
1294*8f23e9faSHans Rosenfeld 			    "%d", vpd->port_index);
129582527734SSukumar Swaminathan 		}
129682527734SSukumar Swaminathan 	}
129782527734SSukumar Swaminathan 
129882527734SSukumar Swaminathan 	if (vpd->id[0] == 0) {
1299*8f23e9faSHans Rosenfeld 		(void) snprintf(vpd->id, (sizeof (vpd->id)-1),
1300*8f23e9faSHans Rosenfeld 		    "%s %d",
130182527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
130282527734SSukumar Swaminathan 
130382527734SSukumar Swaminathan 	}
130482527734SSukumar Swaminathan 
130582527734SSukumar Swaminathan 	if (vpd->manufacturer[0] == 0) {
1306*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->manufacturer, hba->model_info.manufacturer,
1307*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->manufacturer)-1));
130882527734SSukumar Swaminathan 	}
130982527734SSukumar Swaminathan 
131082527734SSukumar Swaminathan 	if (vpd->part_num[0] == 0) {
1311*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->part_num, hba->model_info.model,
1312*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->part_num)-1));
131382527734SSukumar Swaminathan 	}
131482527734SSukumar Swaminathan 
131582527734SSukumar Swaminathan 	if (vpd->model_desc[0] == 0) {
1316*8f23e9faSHans Rosenfeld 		(void) snprintf(vpd->model_desc, (sizeof (vpd->model_desc)-1),
1317*8f23e9faSHans Rosenfeld 		    "%s %d",
131882527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
131982527734SSukumar Swaminathan 	}
132082527734SSukumar Swaminathan 
132182527734SSukumar Swaminathan 	if (vpd->model[0] == 0) {
1322*8f23e9faSHans Rosenfeld 		(void) strncpy(vpd->model, hba->model_info.model,
1323*8f23e9faSHans Rosenfeld 		    (sizeof (vpd->model)-1));
132482527734SSukumar Swaminathan 	}
132582527734SSukumar Swaminathan 
132682527734SSukumar Swaminathan 	if (vpd->prog_types[0] == 0) {
1327*8f23e9faSHans Rosenfeld 		emlxs_build_prog_types(hba, vpd);
132882527734SSukumar Swaminathan 	}
132982527734SSukumar Swaminathan 
133082527734SSukumar Swaminathan 	/* Create the symbolic names */
1331*8f23e9faSHans Rosenfeld 	(void) snprintf(hba->snn, (sizeof (hba->snn)-1),
1332*8f23e9faSHans Rosenfeld 	    "Emulex %s FV%s DV%s %s",
133382527734SSukumar Swaminathan 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
133482527734SSukumar Swaminathan 	    (char *)utsname.nodename);
133582527734SSukumar Swaminathan 
1336*8f23e9faSHans Rosenfeld 	(void) snprintf(hba->spn, (sizeof (hba->spn)-1),
133782527734SSukumar Swaminathan 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
133882527734SSukumar Swaminathan 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
133982527734SSukumar Swaminathan 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
134082527734SSukumar Swaminathan 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
134182527734SSukumar Swaminathan 
134282527734SSukumar Swaminathan 
134382527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
134482527734SSukumar Swaminathan 	emlxs_sli4_enable_intr(hba);
134582527734SSukumar Swaminathan 
1346*8f23e9faSHans Rosenfeld 	/* Check persist-linkdown */
1347*8f23e9faSHans Rosenfeld 	if (cfg[CFG_PERSIST_LINKDOWN].current) {
1348*8f23e9faSHans Rosenfeld 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1349*8f23e9faSHans Rosenfeld 		goto done;
1350*8f23e9faSHans Rosenfeld 	}
1351*8f23e9faSHans Rosenfeld 
1352*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
1353*8f23e9faSHans Rosenfeld 	if ((port->mode == MODE_TARGET) &&
1354*8f23e9faSHans Rosenfeld 	    !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1355*8f23e9faSHans Rosenfeld 		goto done;
1356*8f23e9faSHans Rosenfeld 	}
1357*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
1358*8f23e9faSHans Rosenfeld 
135982527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
136082527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
136182527734SSukumar Swaminathan 
136282527734SSukumar Swaminathan 	/*
136382527734SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command
136482527734SSukumar Swaminathan 	 * At this point, the interrupt will be generated by the HW
136582527734SSukumar Swaminathan 	 */
1366*8f23e9faSHans Rosenfeld 	emlxs_mb_init_link(hba, mbq,
1367*8f23e9faSHans Rosenfeld 	    cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
136882527734SSukumar Swaminathan 
1369*8f23e9faSHans Rosenfeld 	rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1370*8f23e9faSHans Rosenfeld 	if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1371*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1372*8f23e9faSHans Rosenfeld 		    "Unable to initialize link. "
1373*8f23e9faSHans Rosenfeld 		    "Mailbox cmd=%x status=%x",
1374*8f23e9faSHans Rosenfeld 		    mb->mbxCommand, mb->mbxStatus);
1375*8f23e9faSHans Rosenfeld 
1376*8f23e9faSHans Rosenfeld 		rval = EIO;
1377*8f23e9faSHans Rosenfeld 		goto failed3;
1378*8f23e9faSHans Rosenfeld 	}
1379*8f23e9faSHans Rosenfeld 
1380*8f23e9faSHans Rosenfeld 	/* Wait for link to come up */
1381*8f23e9faSHans Rosenfeld 	i = cfg[CFG_LINKUP_DELAY].current;
1382*8f23e9faSHans Rosenfeld 	while (i && (hba->state < FC_LINK_UP)) {
1383*8f23e9faSHans Rosenfeld 		/* Check for hardware error */
1384*8f23e9faSHans Rosenfeld 		if (hba->state == FC_ERROR) {
1385*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT,
1386*8f23e9faSHans Rosenfeld 			    &emlxs_init_failed_msg,
1387*8f23e9faSHans Rosenfeld 			    "Adapter error.", mb->mbxCommand,
1388*8f23e9faSHans Rosenfeld 			    mb->mbxStatus);
138982527734SSukumar Swaminathan 
139082527734SSukumar Swaminathan 			rval = EIO;
139182527734SSukumar Swaminathan 			goto failed3;
139282527734SSukumar Swaminathan 		}
139382527734SSukumar Swaminathan 
1394*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(1000);
1395*8f23e9faSHans Rosenfeld 		i--;
139682527734SSukumar Swaminathan 	}
139782527734SSukumar Swaminathan 
1398*8f23e9faSHans Rosenfeld done:
139982527734SSukumar Swaminathan 	/*
1400*8f23e9faSHans Rosenfeld 	 * The leadville driver will now handle the FLOGI at the driver level
140182527734SSukumar Swaminathan 	 */
140282527734SSukumar Swaminathan 
1403bce54adfSSukumar Swaminathan 	if (mbq) {
1404bce54adfSSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1405bce54adfSSukumar Swaminathan 		mbq = NULL;
1406bce54adfSSukumar Swaminathan 		mb = NULL;
1407bce54adfSSukumar Swaminathan 	}
140882527734SSukumar Swaminathan 	return (0);
140982527734SSukumar Swaminathan 
141082527734SSukumar Swaminathan failed3:
141182527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
141282527734SSukumar Swaminathan 
141382527734SSukumar Swaminathan 	if (mp) {
1414a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
141582527734SSukumar Swaminathan 		mp = NULL;
141682527734SSukumar Swaminathan 	}
141782527734SSukumar Swaminathan 
141882527734SSukumar Swaminathan 
141982527734SSukumar Swaminathan 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
142082527734SSukumar Swaminathan 		(void) EMLXS_INTR_REMOVE(hba);
142182527734SSukumar Swaminathan 	}
142282527734SSukumar Swaminathan 
142382527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
142482527734SSukumar Swaminathan 
142582527734SSukumar Swaminathan failed2:
142682527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
142782527734SSukumar Swaminathan 
142882527734SSukumar Swaminathan failed1:
142982527734SSukumar Swaminathan 	if (mbq) {
143082527734SSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
143182527734SSukumar Swaminathan 		mbq = NULL;
143282527734SSukumar Swaminathan 		mb = NULL;
143382527734SSukumar Swaminathan 	}
143482527734SSukumar Swaminathan 
143582527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt) {
143682527734SSukumar Swaminathan 		(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
143782527734SSukumar Swaminathan 	}
143882527734SSukumar Swaminathan 
143982527734SSukumar Swaminathan 	if (rval == 0) {
144082527734SSukumar Swaminathan 		rval = EIO;
144182527734SSukumar Swaminathan 	}
144282527734SSukumar Swaminathan 
144382527734SSukumar Swaminathan 	return (rval);
144482527734SSukumar Swaminathan 
144582527734SSukumar Swaminathan } /* emlxs_sli4_online() */
144682527734SSukumar Swaminathan 
144782527734SSukumar Swaminathan 
144882527734SSukumar Swaminathan static void
1449*8f23e9faSHans Rosenfeld emlxs_sli4_offline(emlxs_hba_t *hba, uint32_t reset_requested)
145082527734SSukumar Swaminathan {
145182527734SSukumar Swaminathan 	/* Reverse emlxs_sli4_online */
145282527734SSukumar Swaminathan 
145382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
1454*8f23e9faSHans Rosenfeld 	if (hba->flag & FC_INTERLOCKED) {
145582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
1456*8f23e9faSHans Rosenfeld 		goto killed;
1457*8f23e9faSHans Rosenfeld 	}
1458*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_PORT_LOCK);
145982527734SSukumar Swaminathan 
1460*8f23e9faSHans Rosenfeld 	if (reset_requested) {
1461*8f23e9faSHans Rosenfeld 		(void) emlxs_sli4_hba_reset(hba, 0, 0, 0);
146282527734SSukumar Swaminathan 	}
146382527734SSukumar Swaminathan 
146482527734SSukumar Swaminathan 	/* Shutdown the adapter interface */
146582527734SSukumar Swaminathan 	emlxs_sli4_hba_kill(hba);
146682527734SSukumar Swaminathan 
1467*8f23e9faSHans Rosenfeld killed:
1468*8f23e9faSHans Rosenfeld 
146982527734SSukumar Swaminathan 	/* Free SLI shared memory */
147082527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
147182527734SSukumar Swaminathan 
147282527734SSukumar Swaminathan 	/* Free driver shared memory */
147382527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
147482527734SSukumar Swaminathan 
147582527734SSukumar Swaminathan 	/* Free the host dump region buffer */
147682527734SSukumar Swaminathan 	(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
147782527734SSukumar Swaminathan 
147882527734SSukumar Swaminathan } /* emlxs_sli4_offline() */
147982527734SSukumar Swaminathan 
148082527734SSukumar Swaminathan 
148182527734SSukumar Swaminathan /*ARGSUSED*/
148282527734SSukumar Swaminathan static int
148382527734SSukumar Swaminathan emlxs_sli4_map_hdw(emlxs_hba_t *hba)
148482527734SSukumar Swaminathan {
148582527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
148682527734SSukumar Swaminathan 	dev_info_t		*dip;
148782527734SSukumar Swaminathan 	ddi_device_acc_attr_t	dev_attr;
148882527734SSukumar Swaminathan 	int			status;
148982527734SSukumar Swaminathan 
149082527734SSukumar Swaminathan 	dip = (dev_info_t *)hba->dip;
149182527734SSukumar Swaminathan 	dev_attr = emlxs_dev_acc_attr;
149282527734SSukumar Swaminathan 
1493*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1494*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1495*8f23e9faSHans Rosenfeld 
1496*8f23e9faSHans Rosenfeld 		/* Map in Hardware BAR pages that will be used for */
1497*8f23e9faSHans Rosenfeld 		/* communication with HBA. */
1498*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.bar1_acc_handle == 0) {
1499*8f23e9faSHans Rosenfeld 			status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
1500*8f23e9faSHans Rosenfeld 			    (caddr_t *)&hba->sli.sli4.bar1_addr,
1501*8f23e9faSHans Rosenfeld 			    0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
1502*8f23e9faSHans Rosenfeld 			if (status != DDI_SUCCESS) {
1503*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1504*8f23e9faSHans Rosenfeld 				    &emlxs_attach_failed_msg,
1505*8f23e9faSHans Rosenfeld 				    "(PCI) ddi_regs_map_setup BAR1 failed. "
1506*8f23e9faSHans Rosenfeld 				    "stat=%d mem=%p attr=%p hdl=%p",
1507*8f23e9faSHans Rosenfeld 				    status, &hba->sli.sli4.bar1_addr, &dev_attr,
1508*8f23e9faSHans Rosenfeld 				    &hba->sli.sli4.bar1_acc_handle);
1509*8f23e9faSHans Rosenfeld 				goto failed;
1510*8f23e9faSHans Rosenfeld 			}
151182527734SSukumar Swaminathan 		}
151282527734SSukumar Swaminathan 
1513*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.bar2_acc_handle == 0) {
1514*8f23e9faSHans Rosenfeld 			status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
1515*8f23e9faSHans Rosenfeld 			    (caddr_t *)&hba->sli.sli4.bar2_addr,
1516*8f23e9faSHans Rosenfeld 			    0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
1517*8f23e9faSHans Rosenfeld 			if (status != DDI_SUCCESS) {
1518*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1519*8f23e9faSHans Rosenfeld 				    &emlxs_attach_failed_msg,
1520*8f23e9faSHans Rosenfeld 				    "ddi_regs_map_setup BAR2 failed. status=%x",
1521*8f23e9faSHans Rosenfeld 				    status);
1522*8f23e9faSHans Rosenfeld 				goto failed;
1523*8f23e9faSHans Rosenfeld 			}
1524*8f23e9faSHans Rosenfeld 		}
1525*8f23e9faSHans Rosenfeld 
1526*8f23e9faSHans Rosenfeld 		/* offset from beginning of register space */
1527*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MPUEPSemaphore_reg_addr =
1528*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar1_addr +
1529*8f23e9faSHans Rosenfeld 		    CSR_MPU_EP_SEMAPHORE_OFFSET);
1530*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MBDB_reg_addr =
1531*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
1532*8f23e9faSHans Rosenfeld 		hba->sli.sli4.CQDB_reg_addr =
1533*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
1534*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MQDB_reg_addr =
1535*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
1536*8f23e9faSHans Rosenfeld 		hba->sli.sli4.WQDB_reg_addr =
1537*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
1538*8f23e9faSHans Rosenfeld 		hba->sli.sli4.RQDB_reg_addr =
1539*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
1540*8f23e9faSHans Rosenfeld 
1541*8f23e9faSHans Rosenfeld 		hba->sli.sli4.STATUS_reg_addr = 0;
1542*8f23e9faSHans Rosenfeld 		hba->sli.sli4.CNTL_reg_addr = 0;
1543*8f23e9faSHans Rosenfeld 
1544*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ERR1_reg_addr =
1545*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET);
1546*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ERR2_reg_addr =
1547*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET);
1548*8f23e9faSHans Rosenfeld 
1549*8f23e9faSHans Rosenfeld 		hba->sli.sli4.PHYSDEV_reg_addr = 0;
1550*8f23e9faSHans Rosenfeld 		break;
1551*8f23e9faSHans Rosenfeld 
1552*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1553*8f23e9faSHans Rosenfeld 
1554*8f23e9faSHans Rosenfeld 		/* Map in Hardware BAR pages that will be used for */
1555*8f23e9faSHans Rosenfeld 		/* communication with HBA. */
1556*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.bar0_acc_handle == 0) {
1557*8f23e9faSHans Rosenfeld 			status = ddi_regs_map_setup(dip, PCI_BAR0_RINDEX,
1558*8f23e9faSHans Rosenfeld 			    (caddr_t *)&hba->sli.sli4.bar0_addr,
1559*8f23e9faSHans Rosenfeld 			    0, 0, &dev_attr, &hba->sli.sli4.bar0_acc_handle);
1560*8f23e9faSHans Rosenfeld 			if (status != DDI_SUCCESS) {
1561*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1562*8f23e9faSHans Rosenfeld 				    &emlxs_attach_failed_msg,
1563*8f23e9faSHans Rosenfeld 				    "(PCI) ddi_regs_map_setup BAR0 failed. "
1564*8f23e9faSHans Rosenfeld 				    "stat=%d mem=%p attr=%p hdl=%p",
1565*8f23e9faSHans Rosenfeld 				    status, &hba->sli.sli4.bar0_addr, &dev_attr,
1566*8f23e9faSHans Rosenfeld 				    &hba->sli.sli4.bar0_acc_handle);
1567*8f23e9faSHans Rosenfeld 				goto failed;
1568*8f23e9faSHans Rosenfeld 			}
156982527734SSukumar Swaminathan 		}
1570*8f23e9faSHans Rosenfeld 
1571*8f23e9faSHans Rosenfeld 		/* offset from beginning of register space */
1572*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MPUEPSemaphore_reg_addr =
1573*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1574*8f23e9faSHans Rosenfeld 		    SLIPORT_SEMAPHORE_OFFSET);
1575*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MBDB_reg_addr =
1576*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MB_DB_OFFSET);
1577*8f23e9faSHans Rosenfeld 		hba->sli.sli4.CQDB_reg_addr =
1578*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_CQ_DB_OFFSET);
1579*8f23e9faSHans Rosenfeld 		hba->sli.sli4.MQDB_reg_addr =
1580*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MQ_DB_OFFSET);
1581*8f23e9faSHans Rosenfeld 		hba->sli.sli4.WQDB_reg_addr =
1582*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_WQ_DB_OFFSET);
1583*8f23e9faSHans Rosenfeld 		hba->sli.sli4.RQDB_reg_addr =
1584*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr + PD_RQ_DB_OFFSET);
1585*8f23e9faSHans Rosenfeld 
1586*8f23e9faSHans Rosenfeld 		hba->sli.sli4.STATUS_reg_addr =
1587*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1588*8f23e9faSHans Rosenfeld 		    SLIPORT_STATUS_OFFSET);
1589*8f23e9faSHans Rosenfeld 		hba->sli.sli4.CNTL_reg_addr =
1590*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1591*8f23e9faSHans Rosenfeld 		    SLIPORT_CONTROL_OFFSET);
1592*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ERR1_reg_addr =
1593*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1594*8f23e9faSHans Rosenfeld 		    SLIPORT_ERROR1_OFFSET);
1595*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ERR2_reg_addr =
1596*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1597*8f23e9faSHans Rosenfeld 		    SLIPORT_ERROR2_OFFSET);
1598*8f23e9faSHans Rosenfeld 		hba->sli.sli4.PHYSDEV_reg_addr =
1599*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->sli.sli4.bar0_addr +
1600*8f23e9faSHans Rosenfeld 		    PHYSDEV_CONTROL_OFFSET);
1601*8f23e9faSHans Rosenfeld 
1602*8f23e9faSHans Rosenfeld 		break;
1603*8f23e9faSHans Rosenfeld 
1604*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_1:
1605*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_3:
1606*8f23e9faSHans Rosenfeld 	default:
1607*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT,
1608*8f23e9faSHans Rosenfeld 		    &emlxs_attach_failed_msg,
1609*8f23e9faSHans Rosenfeld 		    "Map hdw: Unsupported if_type %08x",
1610*8f23e9faSHans Rosenfeld 		    (hba->sli_intf & SLI_INTF_IF_TYPE_MASK));
1611*8f23e9faSHans Rosenfeld 
1612*8f23e9faSHans Rosenfeld 		goto failed;
161382527734SSukumar Swaminathan 	}
161482527734SSukumar Swaminathan 
161582527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt == 0) {
161682527734SSukumar Swaminathan 		MBUF_INFO	*buf_info;
161782527734SSukumar Swaminathan 		MBUF_INFO	bufinfo;
161882527734SSukumar Swaminathan 
161982527734SSukumar Swaminathan 		buf_info = &bufinfo;
162082527734SSukumar Swaminathan 
162182527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
162282527734SSukumar Swaminathan 		buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
162382527734SSukumar Swaminathan 		buf_info->flags =
162482527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
162582527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(dip, 1L);
162682527734SSukumar Swaminathan 
162782527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
162882527734SSukumar Swaminathan 
162982527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
163082527734SSukumar Swaminathan 			goto failed;
163182527734SSukumar Swaminathan 		}
163282527734SSukumar Swaminathan 
1633a9800bebSGarrett D'Amore 		hba->sli.sli4.bootstrapmb.virt = buf_info->virt;
163482527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
163582527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
163682527734SSukumar Swaminathan 		    MBOX_EXTENSION_SIZE;
163782527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
163882527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
163982527734SSukumar Swaminathan 		bzero((char *)hba->sli.sli4.bootstrapmb.virt,
164082527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE);
164182527734SSukumar Swaminathan 	}
164282527734SSukumar Swaminathan 
164382527734SSukumar Swaminathan 	hba->chan_count = MAX_CHANNEL;
164482527734SSukumar Swaminathan 
164582527734SSukumar Swaminathan 	return (0);
164682527734SSukumar Swaminathan 
164782527734SSukumar Swaminathan failed:
164882527734SSukumar Swaminathan 
164982527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw(hba);
165082527734SSukumar Swaminathan 	return (ENOMEM);
165182527734SSukumar Swaminathan 
165282527734SSukumar Swaminathan 
165382527734SSukumar Swaminathan } /* emlxs_sli4_map_hdw() */
165482527734SSukumar Swaminathan 
165582527734SSukumar Swaminathan 
165682527734SSukumar Swaminathan /*ARGSUSED*/
165782527734SSukumar Swaminathan static void
165882527734SSukumar Swaminathan emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
165982527734SSukumar Swaminathan {
166082527734SSukumar Swaminathan 	MBUF_INFO	bufinfo;
166182527734SSukumar Swaminathan 	MBUF_INFO	*buf_info = &bufinfo;
166282527734SSukumar Swaminathan 
1663*8f23e9faSHans Rosenfeld 
1664*8f23e9faSHans Rosenfeld 	if (hba->sli.sli4.bar0_acc_handle) {
1665*8f23e9faSHans Rosenfeld 		ddi_regs_map_free(&hba->sli.sli4.bar0_acc_handle);
1666*8f23e9faSHans Rosenfeld 		hba->sli.sli4.bar0_acc_handle = 0;
1667*8f23e9faSHans Rosenfeld 	}
1668*8f23e9faSHans Rosenfeld 
166982527734SSukumar Swaminathan 	if (hba->sli.sli4.bar1_acc_handle) {
167082527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
167182527734SSukumar Swaminathan 		hba->sli.sli4.bar1_acc_handle = 0;
167282527734SSukumar Swaminathan 	}
167382527734SSukumar Swaminathan 
167482527734SSukumar Swaminathan 	if (hba->sli.sli4.bar2_acc_handle) {
167582527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
167682527734SSukumar Swaminathan 		hba->sli.sli4.bar2_acc_handle = 0;
167782527734SSukumar Swaminathan 	}
1678*8f23e9faSHans Rosenfeld 
167982527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt) {
168082527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
168182527734SSukumar Swaminathan 
168282527734SSukumar Swaminathan 		if (hba->sli.sli4.bootstrapmb.phys) {
168382527734SSukumar Swaminathan 			buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
168482527734SSukumar Swaminathan 			buf_info->data_handle =
168582527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.data_handle;
168682527734SSukumar Swaminathan 			buf_info->dma_handle =
168782527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.dma_handle;
168882527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
168982527734SSukumar Swaminathan 		}
169082527734SSukumar Swaminathan 
1691a9800bebSGarrett D'Amore 		buf_info->virt = hba->sli.sli4.bootstrapmb.virt;
169282527734SSukumar Swaminathan 		buf_info->size = hba->sli.sli4.bootstrapmb.size;
169382527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
169482527734SSukumar Swaminathan 
1695a9800bebSGarrett D'Amore 		hba->sli.sli4.bootstrapmb.virt = NULL;
169682527734SSukumar Swaminathan 	}
169782527734SSukumar Swaminathan 
169882527734SSukumar Swaminathan 	return;
169982527734SSukumar Swaminathan 
170082527734SSukumar Swaminathan } /* emlxs_sli4_unmap_hdw() */
170182527734SSukumar Swaminathan 
170282527734SSukumar Swaminathan 
170382527734SSukumar Swaminathan static int
170482527734SSukumar Swaminathan emlxs_check_hdw_ready(emlxs_hba_t *hba)
170582527734SSukumar Swaminathan {
170682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
170782527734SSukumar Swaminathan 	uint32_t status;
170882527734SSukumar Swaminathan 	uint32_t i = 0;
1709*8f23e9faSHans Rosenfeld 	uint32_t err1;
1710*8f23e9faSHans Rosenfeld 	uint32_t err2;
171182527734SSukumar Swaminathan 
171282527734SSukumar Swaminathan 	/* Wait for reset completion */
171382527734SSukumar Swaminathan 	while (i < 30) {
171482527734SSukumar Swaminathan 
1715*8f23e9faSHans Rosenfeld 		switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1716*8f23e9faSHans Rosenfeld 		case SLI_INTF_IF_TYPE_0:
1717*8f23e9faSHans Rosenfeld 			status = emlxs_sli4_read_sema(hba);
171882527734SSukumar Swaminathan 
1719*8f23e9faSHans Rosenfeld 			/* Check to see if any errors occurred during init */
1720*8f23e9faSHans Rosenfeld 			if (status & ARM_POST_FATAL) {
1721*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1722*8f23e9faSHans Rosenfeld 				    &emlxs_reset_failed_msg,
1723*8f23e9faSHans Rosenfeld 				    "SEMA Error: status=%x", status);
1724*8f23e9faSHans Rosenfeld 
1725*8f23e9faSHans Rosenfeld 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1726*8f23e9faSHans Rosenfeld 
1727*8f23e9faSHans Rosenfeld 				return (1);
1728*8f23e9faSHans Rosenfeld 			}
1729*8f23e9faSHans Rosenfeld 
1730*8f23e9faSHans Rosenfeld 			if ((status & ARM_UNRECOVERABLE_ERROR) ==
1731*8f23e9faSHans Rosenfeld 			    ARM_UNRECOVERABLE_ERROR) {
1732*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1733*8f23e9faSHans Rosenfeld 				    &emlxs_reset_failed_msg,
1734*8f23e9faSHans Rosenfeld 				    "Unrecoverable Error: status=%x", status);
1735*8f23e9faSHans Rosenfeld 
1736*8f23e9faSHans Rosenfeld 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1737*8f23e9faSHans Rosenfeld 
1738*8f23e9faSHans Rosenfeld 				return (1);
1739*8f23e9faSHans Rosenfeld 			}
1740*8f23e9faSHans Rosenfeld 
1741*8f23e9faSHans Rosenfeld 			if ((status & ARM_POST_MASK) == ARM_POST_READY) {
1742*8f23e9faSHans Rosenfeld 				/* ARM Ready !! */
1743*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1744*8f23e9faSHans Rosenfeld 				    &emlxs_sli_detail_msg,
1745*8f23e9faSHans Rosenfeld 				    "ARM Ready: status=%x", status);
1746*8f23e9faSHans Rosenfeld 
1747*8f23e9faSHans Rosenfeld 				return (0);
1748*8f23e9faSHans Rosenfeld 			}
1749*8f23e9faSHans Rosenfeld 			break;
1750*8f23e9faSHans Rosenfeld 
1751*8f23e9faSHans Rosenfeld 		case SLI_INTF_IF_TYPE_2:
1752*8f23e9faSHans Rosenfeld 			status = emlxs_sli4_read_status(hba);
1753*8f23e9faSHans Rosenfeld 
1754*8f23e9faSHans Rosenfeld 			if (status & SLI_STATUS_READY) {
1755*8f23e9faSHans Rosenfeld 				if (!(status & SLI_STATUS_ERROR)) {
1756*8f23e9faSHans Rosenfeld 					/* ARM Ready !! */
1757*8f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT,
1758*8f23e9faSHans Rosenfeld 					    &emlxs_sli_detail_msg,
1759*8f23e9faSHans Rosenfeld 					    "ARM Ready: status=%x", status);
1760*8f23e9faSHans Rosenfeld 
1761*8f23e9faSHans Rosenfeld 					return (0);
1762*8f23e9faSHans Rosenfeld 				}
1763*8f23e9faSHans Rosenfeld 
1764*8f23e9faSHans Rosenfeld 				err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1765*8f23e9faSHans Rosenfeld 				    hba->sli.sli4.ERR1_reg_addr);
1766*8f23e9faSHans Rosenfeld 				err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1767*8f23e9faSHans Rosenfeld 				    hba->sli.sli4.ERR2_reg_addr);
1768*8f23e9faSHans Rosenfeld 
1769*8f23e9faSHans Rosenfeld 				if (status & SLI_STATUS_RESET_NEEDED) {
1770*8f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT,
1771*8f23e9faSHans Rosenfeld 					    &emlxs_sli_detail_msg,
1772*8f23e9faSHans Rosenfeld 					    "ARM Ready (Reset Needed): "
1773*8f23e9faSHans Rosenfeld 					    "status=%x err1=%x "
1774*8f23e9faSHans Rosenfeld 					    "err2=%x",
1775*8f23e9faSHans Rosenfeld 					    status, err1, err2);
1776*8f23e9faSHans Rosenfeld 
1777*8f23e9faSHans Rosenfeld 					return (1);
1778*8f23e9faSHans Rosenfeld 				}
1779*8f23e9faSHans Rosenfeld 
1780*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1781*8f23e9faSHans Rosenfeld 				    &emlxs_reset_failed_msg,
1782*8f23e9faSHans Rosenfeld 				    "Unrecoverable Error: status=%x err1=%x "
1783*8f23e9faSHans Rosenfeld 				    "err2=%x",
1784*8f23e9faSHans Rosenfeld 				    status, err1, err2);
1785*8f23e9faSHans Rosenfeld 
1786*8f23e9faSHans Rosenfeld 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
1787*8f23e9faSHans Rosenfeld 
1788*8f23e9faSHans Rosenfeld 				return (2);
1789*8f23e9faSHans Rosenfeld 			}
1790*8f23e9faSHans Rosenfeld 
1791*8f23e9faSHans Rosenfeld 			break;
1792*8f23e9faSHans Rosenfeld 
1793*8f23e9faSHans Rosenfeld 		default:
1794*8f23e9faSHans Rosenfeld 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1795*8f23e9faSHans Rosenfeld 
1796*8f23e9faSHans Rosenfeld 			return (3);
179782527734SSukumar Swaminathan 		}
179882527734SSukumar Swaminathan 
1799*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(1000);
180082527734SSukumar Swaminathan 		i++;
180182527734SSukumar Swaminathan 	}
180282527734SSukumar Swaminathan 
180382527734SSukumar Swaminathan 	/* Timeout occurred */
1804*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1805*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1806*8f23e9faSHans Rosenfeld 		err1 = ddi_get32(hba->pci_acc_handle,
1807*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
1808*8f23e9faSHans Rosenfeld 		err2 = ddi_get32(hba->pci_acc_handle,
1809*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
1810*8f23e9faSHans Rosenfeld 		break;
1811*8f23e9faSHans Rosenfeld 
1812*8f23e9faSHans Rosenfeld 	default:
1813*8f23e9faSHans Rosenfeld 		err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1814*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
1815*8f23e9faSHans Rosenfeld 		err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1816*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
1817*8f23e9faSHans Rosenfeld 		break;
1818*8f23e9faSHans Rosenfeld 	}
1819*8f23e9faSHans Rosenfeld 
1820*8f23e9faSHans Rosenfeld 	if (status & SLI_STATUS_ERROR) {
1821*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1822*8f23e9faSHans Rosenfeld 		    "Ready Timeout: Port Error: status=%x err1=%x err2=%x",
1823*8f23e9faSHans Rosenfeld 		    status, err1, err2);
1824*8f23e9faSHans Rosenfeld 	} else {
1825*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1826*8f23e9faSHans Rosenfeld 		    "Ready Timeout: status=%x err1=%x err2=%x",
1827*8f23e9faSHans Rosenfeld 		    status, err1, err2);
1828*8f23e9faSHans Rosenfeld 	}
182982527734SSukumar Swaminathan 
183082527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
183182527734SSukumar Swaminathan 
1832*8f23e9faSHans Rosenfeld 	return (3);
1833*8f23e9faSHans Rosenfeld 
1834*8f23e9faSHans Rosenfeld } /* emlxs_check_hdw_ready() */
1835*8f23e9faSHans Rosenfeld 
1836*8f23e9faSHans Rosenfeld 
1837*8f23e9faSHans Rosenfeld static uint32_t
1838*8f23e9faSHans Rosenfeld emlxs_sli4_read_status(emlxs_hba_t *hba)
1839*8f23e9faSHans Rosenfeld {
184082527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1841*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
184282527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1843*8f23e9faSHans Rosenfeld 	uint32_t status;
184482527734SSukumar Swaminathan 
1845*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1846*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1847*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1848*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.STATUS_reg_addr);
1849*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1850*8f23e9faSHans Rosenfeld 		/* Access handle validation */
1851*8f23e9faSHans Rosenfeld 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1852*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1853*8f23e9faSHans Rosenfeld 		break;
1854*8f23e9faSHans Rosenfeld 	default:
1855*8f23e9faSHans Rosenfeld 		status = 0;
1856*8f23e9faSHans Rosenfeld 		break;
1857*8f23e9faSHans Rosenfeld 	}
185882527734SSukumar Swaminathan 
1859*8f23e9faSHans Rosenfeld 	return (status);
186082527734SSukumar Swaminathan 
1861*8f23e9faSHans Rosenfeld } /* emlxs_sli4_read_status() */
186282527734SSukumar Swaminathan 
186382527734SSukumar Swaminathan 
186482527734SSukumar Swaminathan static uint32_t
1865*8f23e9faSHans Rosenfeld emlxs_sli4_read_sema(emlxs_hba_t *hba)
1866*8f23e9faSHans Rosenfeld {
1867*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1868*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
1869*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1870*8f23e9faSHans Rosenfeld 	uint32_t status;
1871*8f23e9faSHans Rosenfeld 
1872*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1873*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1874*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar1_acc_handle,
1875*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MPUEPSemaphore_reg_addr);
1876*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1877*8f23e9faSHans Rosenfeld 		/* Access handle validation */
1878*8f23e9faSHans Rosenfeld 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
1879*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1880*8f23e9faSHans Rosenfeld 		break;
1881*8f23e9faSHans Rosenfeld 
1882*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1883*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1884*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MPUEPSemaphore_reg_addr);
1885*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1886*8f23e9faSHans Rosenfeld 		/* Access handle validation */
1887*8f23e9faSHans Rosenfeld 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1888*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1889*8f23e9faSHans Rosenfeld 		break;
1890*8f23e9faSHans Rosenfeld 	default:
1891*8f23e9faSHans Rosenfeld 		status = 0;
1892*8f23e9faSHans Rosenfeld 		break;
1893*8f23e9faSHans Rosenfeld 	}
1894*8f23e9faSHans Rosenfeld 
1895*8f23e9faSHans Rosenfeld 	return (status);
1896*8f23e9faSHans Rosenfeld 
1897*8f23e9faSHans Rosenfeld } /* emlxs_sli4_read_sema() */
1898*8f23e9faSHans Rosenfeld 
1899*8f23e9faSHans Rosenfeld 
1900*8f23e9faSHans Rosenfeld static uint32_t
1901*8f23e9faSHans Rosenfeld emlxs_sli4_read_mbdb(emlxs_hba_t *hba)
190282527734SSukumar Swaminathan {
1903*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
190482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1905*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
190682527734SSukumar Swaminathan 	uint32_t status;
190782527734SSukumar Swaminathan 
1908*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1909*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1910*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar2_acc_handle,
1911*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MBDB_reg_addr);
1912*8f23e9faSHans Rosenfeld 
1913*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1914*8f23e9faSHans Rosenfeld 		/* Access handle validation */
1915*8f23e9faSHans Rosenfeld 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
1916*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1917*8f23e9faSHans Rosenfeld 		break;
1918*8f23e9faSHans Rosenfeld 
1919*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1920*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1921*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MBDB_reg_addr);
1922*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
1923*8f23e9faSHans Rosenfeld 		/* Access handle validation */
1924*8f23e9faSHans Rosenfeld 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1925*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
1926*8f23e9faSHans Rosenfeld 		break;
1927*8f23e9faSHans Rosenfeld 	default:
1928*8f23e9faSHans Rosenfeld 		status = 0;
1929*8f23e9faSHans Rosenfeld 		break;
1930*8f23e9faSHans Rosenfeld 	}
1931*8f23e9faSHans Rosenfeld 
1932*8f23e9faSHans Rosenfeld 	return (status);
1933*8f23e9faSHans Rosenfeld 
1934*8f23e9faSHans Rosenfeld } /* emlxs_sli4_read_mbdb() */
1935*8f23e9faSHans Rosenfeld 
1936*8f23e9faSHans Rosenfeld 
1937*8f23e9faSHans Rosenfeld static void
1938*8f23e9faSHans Rosenfeld emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value)
1939*8f23e9faSHans Rosenfeld {
1940*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1941*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1942*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1943*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MBDB_reg_addr, value);
1944*8f23e9faSHans Rosenfeld 		break;
1945*8f23e9faSHans Rosenfeld 
1946*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1947*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1948*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MBDB_reg_addr, value);
1949*8f23e9faSHans Rosenfeld 		break;
1950*8f23e9faSHans Rosenfeld 	}
1951*8f23e9faSHans Rosenfeld 
1952*8f23e9faSHans Rosenfeld } /* emlxs_sli4_write_mbdb() */
1953*8f23e9faSHans Rosenfeld 
1954*8f23e9faSHans Rosenfeld 
1955*8f23e9faSHans Rosenfeld static void
1956*8f23e9faSHans Rosenfeld emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value)
1957*8f23e9faSHans Rosenfeld {
1958*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1959*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1960*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1961*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.CQDB_reg_addr, value);
1962*8f23e9faSHans Rosenfeld 		break;
1963*8f23e9faSHans Rosenfeld 
1964*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1965*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1966*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.CQDB_reg_addr, value);
1967*8f23e9faSHans Rosenfeld 		break;
1968*8f23e9faSHans Rosenfeld 	}
1969*8f23e9faSHans Rosenfeld 
1970*8f23e9faSHans Rosenfeld } /* emlxs_sli4_write_cqdb() */
1971*8f23e9faSHans Rosenfeld 
1972*8f23e9faSHans Rosenfeld 
1973*8f23e9faSHans Rosenfeld static void
1974*8f23e9faSHans Rosenfeld emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value)
1975*8f23e9faSHans Rosenfeld {
1976*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1977*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1978*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1979*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RQDB_reg_addr, value);
1980*8f23e9faSHans Rosenfeld 		break;
1981*8f23e9faSHans Rosenfeld 
1982*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
1983*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
1984*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RQDB_reg_addr, value);
1985*8f23e9faSHans Rosenfeld 		break;
1986*8f23e9faSHans Rosenfeld 	}
1987*8f23e9faSHans Rosenfeld 
1988*8f23e9faSHans Rosenfeld } /* emlxs_sli4_write_rqdb() */
1989*8f23e9faSHans Rosenfeld 
1990*8f23e9faSHans Rosenfeld 
1991*8f23e9faSHans Rosenfeld static void
1992*8f23e9faSHans Rosenfeld emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value)
1993*8f23e9faSHans Rosenfeld {
1994*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1995*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
1996*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
1997*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MQDB_reg_addr, value);
1998*8f23e9faSHans Rosenfeld 		break;
1999*8f23e9faSHans Rosenfeld 
2000*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
2001*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2002*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.MQDB_reg_addr, value);
2003*8f23e9faSHans Rosenfeld 		break;
2004*8f23e9faSHans Rosenfeld 	}
2005*8f23e9faSHans Rosenfeld 
2006*8f23e9faSHans Rosenfeld } /* emlxs_sli4_write_mqdb() */
2007*8f23e9faSHans Rosenfeld 
2008*8f23e9faSHans Rosenfeld 
2009*8f23e9faSHans Rosenfeld static void
2010*8f23e9faSHans Rosenfeld emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value)
2011*8f23e9faSHans Rosenfeld {
2012*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2013*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
2014*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar2_acc_handle,
2015*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.WQDB_reg_addr, value);
2016*8f23e9faSHans Rosenfeld 		break;
2017*8f23e9faSHans Rosenfeld 
2018*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
2019*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2020*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.WQDB_reg_addr, value);
2021*8f23e9faSHans Rosenfeld 		break;
2022*8f23e9faSHans Rosenfeld 	}
2023*8f23e9faSHans Rosenfeld 
2024*8f23e9faSHans Rosenfeld } /* emlxs_sli4_write_wqdb() */
2025*8f23e9faSHans Rosenfeld 
2026*8f23e9faSHans Rosenfeld 
2027*8f23e9faSHans Rosenfeld static uint32_t
2028*8f23e9faSHans Rosenfeld emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
2029*8f23e9faSHans Rosenfeld {
2030*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
2031*8f23e9faSHans Rosenfeld 	uint32_t status = 0;
2032*8f23e9faSHans Rosenfeld 	uint32_t err1;
2033*8f23e9faSHans Rosenfeld 	uint32_t err2;
2034*8f23e9faSHans Rosenfeld 
203582527734SSukumar Swaminathan 	/* Wait for reset completion, tmo is in 10ms ticks */
203682527734SSukumar Swaminathan 	while (tmo) {
2037*8f23e9faSHans Rosenfeld 		status = emlxs_sli4_read_mbdb(hba);
203882527734SSukumar Swaminathan 
203982527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
204082527734SSukumar Swaminathan 		if (status & BMBX_READY) {
2041*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
204282527734SSukumar Swaminathan 			    "BMBX Ready: status=0x%x", status);
2043*8f23e9faSHans Rosenfeld 
204482527734SSukumar Swaminathan 			return (tmo);
204582527734SSukumar Swaminathan 		}
204682527734SSukumar Swaminathan 
2047*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(10);
204882527734SSukumar Swaminathan 		tmo--;
204982527734SSukumar Swaminathan 	}
205082527734SSukumar Swaminathan 
2051*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2052*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
2053*8f23e9faSHans Rosenfeld 		err1 = ddi_get32(hba->pci_acc_handle,
2054*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
2055*8f23e9faSHans Rosenfeld 		err2 = ddi_get32(hba->pci_acc_handle,
2056*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
2057*8f23e9faSHans Rosenfeld 		break;
2058*8f23e9faSHans Rosenfeld 
2059*8f23e9faSHans Rosenfeld 	default:
2060*8f23e9faSHans Rosenfeld 		err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2061*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
2062*8f23e9faSHans Rosenfeld 		err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2063*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
2064*8f23e9faSHans Rosenfeld 		break;
2065*8f23e9faSHans Rosenfeld 	}
2066*8f23e9faSHans Rosenfeld 
206782527734SSukumar Swaminathan 	/* Timeout occurred */
206882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2069*8f23e9faSHans Rosenfeld 	    "Timeout waiting for BMailbox: status=%x err1=%x err2=%x",
2070*8f23e9faSHans Rosenfeld 	    status, err1, err2);
207182527734SSukumar Swaminathan 
207282527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
207382527734SSukumar Swaminathan 
207482527734SSukumar Swaminathan 	return (0);
207582527734SSukumar Swaminathan 
207682527734SSukumar Swaminathan } /* emlxs_check_bootstrap_ready() */
207782527734SSukumar Swaminathan 
207882527734SSukumar Swaminathan 
207982527734SSukumar Swaminathan static uint32_t
208082527734SSukumar Swaminathan emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
208182527734SSukumar Swaminathan {
208282527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
208382527734SSukumar Swaminathan 	uint32_t *iptr;
208482527734SSukumar Swaminathan 	uint32_t addr30;
208582527734SSukumar Swaminathan 
208682527734SSukumar Swaminathan 	/*
208782527734SSukumar Swaminathan 	 * This routine assumes the bootstrap mbox is loaded
208882527734SSukumar Swaminathan 	 * with the mailbox command to be executed.
208982527734SSukumar Swaminathan 	 *
209082527734SSukumar Swaminathan 	 * First, load the high 30 bits of bootstrap mailbox
209182527734SSukumar Swaminathan 	 */
209282527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
209382527734SSukumar Swaminathan 	addr30 |= BMBX_ADDR_HI;
2094*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_mbdb(hba, addr30);
209582527734SSukumar Swaminathan 
209682527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
209782527734SSukumar Swaminathan 	if (tmo == 0) {
209882527734SSukumar Swaminathan 		return (0);
209982527734SSukumar Swaminathan 	}
210082527734SSukumar Swaminathan 
210182527734SSukumar Swaminathan 	/* Load the low 30 bits of bootstrap mailbox */
210282527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
2103*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_mbdb(hba, addr30);
210482527734SSukumar Swaminathan 
210582527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
210682527734SSukumar Swaminathan 	if (tmo == 0) {
210782527734SSukumar Swaminathan 		return (0);
210882527734SSukumar Swaminathan 	}
210982527734SSukumar Swaminathan 
211082527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
211182527734SSukumar Swaminathan 
2112*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
211382527734SSukumar Swaminathan 	    "BootstrapMB: %p Completed %08x %08x %08x",
211482527734SSukumar Swaminathan 	    hba->sli.sli4.bootstrapmb.virt,
211582527734SSukumar Swaminathan 	    *iptr, *(iptr+1), *(iptr+2));
211682527734SSukumar Swaminathan 
211782527734SSukumar Swaminathan 	return (tmo);
211882527734SSukumar Swaminathan 
211982527734SSukumar Swaminathan } /* emlxs_issue_bootstrap_mb() */
212082527734SSukumar Swaminathan 
212182527734SSukumar Swaminathan 
212282527734SSukumar Swaminathan static int
212382527734SSukumar Swaminathan emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
212482527734SSukumar Swaminathan {
212582527734SSukumar Swaminathan #ifdef FMA_SUPPORT
212682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
212782527734SSukumar Swaminathan #endif /* FMA_SUPPORT */
212882527734SSukumar Swaminathan 	uint32_t *iptr;
212982527734SSukumar Swaminathan 	uint32_t tmo;
213082527734SSukumar Swaminathan 
213182527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
213282527734SSukumar Swaminathan 		return (1);
213382527734SSukumar Swaminathan 	}
213482527734SSukumar Swaminathan 
213582527734SSukumar Swaminathan 	if (hba->flag & FC_BOOTSTRAPMB_INIT) {
213682527734SSukumar Swaminathan 		return (0);  /* Already initialized */
213782527734SSukumar Swaminathan 	}
213882527734SSukumar Swaminathan 
213982527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
214082527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, 3000);
214182527734SSukumar Swaminathan 	if (tmo == 0) {
214282527734SSukumar Swaminathan 		return (1);
214382527734SSukumar Swaminathan 	}
214482527734SSukumar Swaminathan 
2145*8f23e9faSHans Rosenfeld 	/* Issue FW_INITIALIZE command */
2146*8f23e9faSHans Rosenfeld 
214782527734SSukumar Swaminathan 	/* Special words to initialize bootstrap mbox MUST be little endian */
214882527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2149*8f23e9faSHans Rosenfeld 	*iptr = LE_SWAP32(FW_INITIALIZE_WORD0);
2150*8f23e9faSHans Rosenfeld 	*(iptr+1) = LE_SWAP32(FW_INITIALIZE_WORD1);
215182527734SSukumar Swaminathan 
215282527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
215382527734SSukumar Swaminathan 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
215482527734SSukumar Swaminathan 
2155*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "FW_INIT", (uint32_t *)iptr, 6, 0);
215682527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
215782527734SSukumar Swaminathan 		return (1);
215882527734SSukumar Swaminathan 	}
215982527734SSukumar Swaminathan 
2160b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
2161b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle)
2162b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
2163b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
2164b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
2165*8f23e9faSHans Rosenfeld 		    "init_bootstrap_mb: hdl=%p",
2166b3660a96SSukumar Swaminathan 		    hba->sli.sli4.bootstrapmb.dma_handle);
2167b3660a96SSukumar Swaminathan 		return (1);
2168b3660a96SSukumar Swaminathan 	}
2169b3660a96SSukumar Swaminathan #endif
217082527734SSukumar Swaminathan 	hba->flag |= FC_BOOTSTRAPMB_INIT;
217182527734SSukumar Swaminathan 	return (0);
217282527734SSukumar Swaminathan 
217382527734SSukumar Swaminathan } /* emlxs_init_bootstrap_mb() */
217482527734SSukumar Swaminathan 
217582527734SSukumar Swaminathan 
2176*8f23e9faSHans Rosenfeld 
2177*8f23e9faSHans Rosenfeld 
217882527734SSukumar Swaminathan static uint32_t
217982527734SSukumar Swaminathan emlxs_sli4_hba_init(emlxs_hba_t *hba)
218082527734SSukumar Swaminathan {
218182527734SSukumar Swaminathan 	int rc;
2182a9800bebSGarrett D'Amore 	uint16_t i;
218382527734SSukumar Swaminathan 	emlxs_port_t *vport;
218482527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
218582527734SSukumar Swaminathan 	CHANNEL *cp;
2186*8f23e9faSHans Rosenfeld 	VPIobj_t *vpip;
218782527734SSukumar Swaminathan 
218882527734SSukumar Swaminathan 	/* Restart the adapter */
218982527734SSukumar Swaminathan 	if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
219082527734SSukumar Swaminathan 		return (1);
219182527734SSukumar Swaminathan 	}
219282527734SSukumar Swaminathan 
219382527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
219482527734SSukumar Swaminathan 		cp = &hba->chan[i];
219582527734SSukumar Swaminathan 		cp->iopath = (void *)&hba->sli.sli4.wq[i];
219682527734SSukumar Swaminathan 	}
219782527734SSukumar Swaminathan 
219882527734SSukumar Swaminathan 	/* Initialize all the port objects */
219982527734SSukumar Swaminathan 	hba->vpi_max  = 0;
220082527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
220182527734SSukumar Swaminathan 		vport = &VPORT(i);
220282527734SSukumar Swaminathan 		vport->hba = hba;
220382527734SSukumar Swaminathan 		vport->vpi = i;
2204a9800bebSGarrett D'Amore 
2205*8f23e9faSHans Rosenfeld 		vpip = &vport->VPIobj;
2206*8f23e9faSHans Rosenfeld 		vpip->index = i;
2207*8f23e9faSHans Rosenfeld 		vpip->VPI = i;
2208*8f23e9faSHans Rosenfeld 		vpip->port = vport;
2209*8f23e9faSHans Rosenfeld 		vpip->state = VPI_STATE_OFFLINE;
2210*8f23e9faSHans Rosenfeld 		vport->vpip = vpip;
221182527734SSukumar Swaminathan 	}
221282527734SSukumar Swaminathan 
221382527734SSukumar Swaminathan 	/* Set the max node count */
221482527734SSukumar Swaminathan 	if (hba->max_nodes == 0) {
221582527734SSukumar Swaminathan 		if (cfg[CFG_NUM_NODES].current > 0) {
221682527734SSukumar Swaminathan 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
221782527734SSukumar Swaminathan 		} else {
221882527734SSukumar Swaminathan 			hba->max_nodes = 4096;
221982527734SSukumar Swaminathan 		}
222082527734SSukumar Swaminathan 	}
222182527734SSukumar Swaminathan 
222282527734SSukumar Swaminathan 	rc = emlxs_init_bootstrap_mb(hba);
222382527734SSukumar Swaminathan 	if (rc) {
222482527734SSukumar Swaminathan 		return (rc);
222582527734SSukumar Swaminathan 	}
222682527734SSukumar Swaminathan 
222782527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
222882527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
222982527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
223082527734SSukumar Swaminathan 
2231*8f23e9faSHans Rosenfeld 	if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_0) {
2232*8f23e9faSHans Rosenfeld 		/* Cache the UE MASK registers value for UE error detection */
2233*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle,
2234*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET));
2235*8f23e9faSHans Rosenfeld 		hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle,
2236*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET));
2237*8f23e9faSHans Rosenfeld 	}
2238fe199829SSukumar Swaminathan 
223982527734SSukumar Swaminathan 	return (0);
224082527734SSukumar Swaminathan 
224182527734SSukumar Swaminathan } /* emlxs_sli4_hba_init() */
224282527734SSukumar Swaminathan 
224382527734SSukumar Swaminathan 
224482527734SSukumar Swaminathan /*ARGSUSED*/
224582527734SSukumar Swaminathan static uint32_t
224682527734SSukumar Swaminathan emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
224782527734SSukumar Swaminathan 		uint32_t quiesce)
224882527734SSukumar Swaminathan {
224982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
225082527734SSukumar Swaminathan 	emlxs_port_t *vport;
225182527734SSukumar Swaminathan 	CHANNEL *cp;
225282527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
225382527734SSukumar Swaminathan 	MAILBOXQ mboxq;
2254*8f23e9faSHans Rosenfeld 	uint32_t value;
225582527734SSukumar Swaminathan 	uint32_t i;
225682527734SSukumar Swaminathan 	uint32_t rc;
2257a9800bebSGarrett D'Amore 	uint16_t channelno;
2258*8f23e9faSHans Rosenfeld 	uint32_t status;
2259*8f23e9faSHans Rosenfeld 	uint32_t err1;
2260*8f23e9faSHans Rosenfeld 	uint32_t err2;
2261*8f23e9faSHans Rosenfeld 	uint8_t generate_event = 0;
226282527734SSukumar Swaminathan 
226382527734SSukumar Swaminathan 	if (!cfg[CFG_RESET_ENABLE].current) {
226482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
226582527734SSukumar Swaminathan 		    "Adapter reset disabled.");
226682527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
226782527734SSukumar Swaminathan 
226882527734SSukumar Swaminathan 		return (1);
226982527734SSukumar Swaminathan 	}
227082527734SSukumar Swaminathan 
2271*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2272*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
2273*8f23e9faSHans Rosenfeld 		if (quiesce == 0) {
2274*8f23e9faSHans Rosenfeld 			emlxs_sli4_hba_kill(hba);
227582527734SSukumar Swaminathan 
2276*8f23e9faSHans Rosenfeld 			/*
2277*8f23e9faSHans Rosenfeld 			 * Initalize Hardware that will be used to bring
2278*8f23e9faSHans Rosenfeld 			 * SLI4 online.
2279*8f23e9faSHans Rosenfeld 			 */
2280*8f23e9faSHans Rosenfeld 			rc = emlxs_init_bootstrap_mb(hba);
2281*8f23e9faSHans Rosenfeld 			if (rc) {
2282*8f23e9faSHans Rosenfeld 				return (rc);
2283*8f23e9faSHans Rosenfeld 			}
228482527734SSukumar Swaminathan 		}
228582527734SSukumar Swaminathan 
2286*8f23e9faSHans Rosenfeld 		bzero((void *)&mboxq, sizeof (MAILBOXQ));
2287*8f23e9faSHans Rosenfeld 		emlxs_mb_resetport(hba, &mboxq);
228882527734SSukumar Swaminathan 
2289*8f23e9faSHans Rosenfeld 		if (quiesce == 0) {
2290*8f23e9faSHans Rosenfeld 			if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
2291*8f23e9faSHans Rosenfeld 			    MBX_POLL, 0) != MBX_SUCCESS) {
2292*8f23e9faSHans Rosenfeld 				/* Timeout occurred */
2293*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
2294*8f23e9faSHans Rosenfeld 				    &emlxs_reset_failed_msg,
2295*8f23e9faSHans Rosenfeld 				    "Timeout: RESET");
2296*8f23e9faSHans Rosenfeld 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
2297*8f23e9faSHans Rosenfeld 				/* Log a dump event - not supported */
2298*8f23e9faSHans Rosenfeld 				return (1);
2299*8f23e9faSHans Rosenfeld 			}
2300*8f23e9faSHans Rosenfeld 		} else {
2301*8f23e9faSHans Rosenfeld 			if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
2302*8f23e9faSHans Rosenfeld 			    MBX_POLL, 0) != MBX_SUCCESS) {
2303*8f23e9faSHans Rosenfeld 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
2304*8f23e9faSHans Rosenfeld 				/* Log a dump event - not supported */
2305*8f23e9faSHans Rosenfeld 				return (1);
2306*8f23e9faSHans Rosenfeld 			}
230782527734SSukumar Swaminathan 		}
2308*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0);
2309*8f23e9faSHans Rosenfeld 		break;
2310*8f23e9faSHans Rosenfeld 
2311*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
2312*8f23e9faSHans Rosenfeld 		if (quiesce == 0) {
2313*8f23e9faSHans Rosenfeld 			emlxs_sli4_hba_kill(hba);
2314*8f23e9faSHans Rosenfeld 		}
2315*8f23e9faSHans Rosenfeld 
2316*8f23e9faSHans Rosenfeld 		rc = emlxs_check_hdw_ready(hba);
2317*8f23e9faSHans Rosenfeld 		if (rc > 1) {
2318*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
2319*8f23e9faSHans Rosenfeld 			    "Adapter not ready for reset.");
232082527734SSukumar Swaminathan 			return (1);
232182527734SSukumar Swaminathan 		}
2322*8f23e9faSHans Rosenfeld 
2323*8f23e9faSHans Rosenfeld 		if (rc == 1) {
2324*8f23e9faSHans Rosenfeld 			err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2325*8f23e9faSHans Rosenfeld 			    hba->sli.sli4.ERR1_reg_addr);
2326*8f23e9faSHans Rosenfeld 			err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2327*8f23e9faSHans Rosenfeld 			    hba->sli.sli4.ERR2_reg_addr);
2328*8f23e9faSHans Rosenfeld 
2329*8f23e9faSHans Rosenfeld 			/* Don't generate an event if dump was forced */
2330*8f23e9faSHans Rosenfeld 			if ((err1 != 0x2) || (err2 != 0x2)) {
2331*8f23e9faSHans Rosenfeld 				generate_event = 1;
2332*8f23e9faSHans Rosenfeld 			}
2333*8f23e9faSHans Rosenfeld 		}
2334*8f23e9faSHans Rosenfeld 
2335*8f23e9faSHans Rosenfeld 		/* Reset the port now */
2336*8f23e9faSHans Rosenfeld 
2337*8f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
2338*8f23e9faSHans Rosenfeld 		value = SLI_CNTL_INIT_PORT;
2339*8f23e9faSHans Rosenfeld 
2340*8f23e9faSHans Rosenfeld 		ddi_put32(hba->sli.sli4.bar0_acc_handle,
2341*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.CNTL_reg_addr, value);
2342*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
2343*8f23e9faSHans Rosenfeld 
2344*8f23e9faSHans Rosenfeld 		break;
234582527734SSukumar Swaminathan 	}
234682527734SSukumar Swaminathan 
234782527734SSukumar Swaminathan 	/* Reset the hba structure */
234882527734SSukumar Swaminathan 	hba->flag &= FC_RESET_MASK;
234982527734SSukumar Swaminathan 
235082527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
235182527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
235282527734SSukumar Swaminathan 		cp->hba = hba;
235382527734SSukumar Swaminathan 		cp->channelno = channelno;
235482527734SSukumar Swaminathan 	}
235582527734SSukumar Swaminathan 
235682527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
235782527734SSukumar Swaminathan 	hba->io_count = 0;
235882527734SSukumar Swaminathan 	hba->iodone_count = 0;
235982527734SSukumar Swaminathan 	hba->topology = 0;
236082527734SSukumar Swaminathan 	hba->linkspeed = 0;
236182527734SSukumar Swaminathan 	hba->heartbeat_active = 0;
236282527734SSukumar Swaminathan 	hba->discovery_timer = 0;
236382527734SSukumar Swaminathan 	hba->linkup_timer = 0;
236482527734SSukumar Swaminathan 	hba->loopback_tics = 0;
236582527734SSukumar Swaminathan 
236682527734SSukumar Swaminathan 	/* Reset the port objects */
236782527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
236882527734SSukumar Swaminathan 		vport = &VPORT(i);
236982527734SSukumar Swaminathan 
237082527734SSukumar Swaminathan 		vport->flag &= EMLXS_PORT_RESET_MASK;
237182527734SSukumar Swaminathan 		vport->did = 0;
237282527734SSukumar Swaminathan 		vport->prev_did = 0;
237382527734SSukumar Swaminathan 		vport->lip_type = 0;
237482527734SSukumar Swaminathan 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2375a9800bebSGarrett D'Amore 		bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
237682527734SSukumar Swaminathan 
237782527734SSukumar Swaminathan 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
237882527734SSukumar Swaminathan 		vport->node_base.nlp_Rpi = 0;
237982527734SSukumar Swaminathan 		vport->node_base.nlp_DID = 0xffffff;
238082527734SSukumar Swaminathan 		vport->node_base.nlp_list_next = NULL;
238182527734SSukumar Swaminathan 		vport->node_base.nlp_list_prev = NULL;
238282527734SSukumar Swaminathan 		vport->node_base.nlp_active = 1;
238382527734SSukumar Swaminathan 		vport->node_count = 0;
238482527734SSukumar Swaminathan 
238582527734SSukumar Swaminathan 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
238682527734SSukumar Swaminathan 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
238782527734SSukumar Swaminathan 		}
238882527734SSukumar Swaminathan 	}
238982527734SSukumar Swaminathan 
239082527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
239182527734SSukumar Swaminathan 		return (1);
239282527734SSukumar Swaminathan 	}
239382527734SSukumar Swaminathan 
2394*8f23e9faSHans Rosenfeld 	if (generate_event) {
2395*8f23e9faSHans Rosenfeld 		status = emlxs_sli4_read_status(hba);
2396*8f23e9faSHans Rosenfeld 		if (status & SLI_STATUS_DUMP_IMAGE_PRESENT) {
2397*8f23e9faSHans Rosenfeld 			emlxs_log_dump_event(port, NULL, 0);
2398*8f23e9faSHans Rosenfeld 		}
2399*8f23e9faSHans Rosenfeld 	}
2400*8f23e9faSHans Rosenfeld 
240182527734SSukumar Swaminathan 	return (0);
240282527734SSukumar Swaminathan 
240382527734SSukumar Swaminathan } /* emlxs_sli4_hba_reset */
240482527734SSukumar Swaminathan 
240582527734SSukumar Swaminathan 
240682527734SSukumar Swaminathan #define	SGL_CMD		0
240782527734SSukumar Swaminathan #define	SGL_RESP	1
240882527734SSukumar Swaminathan #define	SGL_DATA	2
240982527734SSukumar Swaminathan #define	SGL_LAST	0x80
241082527734SSukumar Swaminathan 
241182527734SSukumar Swaminathan /*ARGSUSED*/
2412*8f23e9faSHans Rosenfeld static ULP_SGE64 *
2413*8f23e9faSHans Rosenfeld emlxs_pkt_to_sgl(emlxs_port_t *port, fc_packet_t *pkt, ULP_SGE64 *sge,
241482527734SSukumar Swaminathan     uint32_t sgl_type, uint32_t *pcnt)
241582527734SSukumar Swaminathan {
241682527734SSukumar Swaminathan #ifdef DEBUG_SGE
241782527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
2418*8f23e9faSHans Rosenfeld #endif /* DEBUG_SGE */
241982527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp;
242082527734SSukumar Swaminathan 	uint_t i;
242182527734SSukumar Swaminathan 	uint_t last;
242282527734SSukumar Swaminathan 	int32_t	size;
242382527734SSukumar Swaminathan 	int32_t	sge_size;
242482527734SSukumar Swaminathan 	uint64_t sge_addr;
242582527734SSukumar Swaminathan 	int32_t	len;
242682527734SSukumar Swaminathan 	uint32_t cnt;
242782527734SSukumar Swaminathan 	uint_t cookie_cnt;
242882527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
242982527734SSukumar Swaminathan 
243082527734SSukumar Swaminathan 	last = sgl_type & SGL_LAST;
243182527734SSukumar Swaminathan 	sgl_type &= ~SGL_LAST;
243282527734SSukumar Swaminathan 
243382527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
243482527734SSukumar Swaminathan 	switch (sgl_type) {
243582527734SSukumar Swaminathan 	case SGL_CMD:
243682527734SSukumar Swaminathan 		cp = pkt->pkt_cmd_cookie;
243782527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
243882527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
243982527734SSukumar Swaminathan 		break;
244082527734SSukumar Swaminathan 
244182527734SSukumar Swaminathan 	case SGL_RESP:
244282527734SSukumar Swaminathan 		cp = pkt->pkt_resp_cookie;
244382527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
244482527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
244582527734SSukumar Swaminathan 		break;
244682527734SSukumar Swaminathan 
244782527734SSukumar Swaminathan 
244882527734SSukumar Swaminathan 	case SGL_DATA:
244982527734SSukumar Swaminathan 		cp = pkt->pkt_data_cookie;
245082527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_data_cookie_cnt;
245182527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
245282527734SSukumar Swaminathan 		break;
2453*8f23e9faSHans Rosenfeld 
2454*8f23e9faSHans Rosenfeld 	default:
2455*8f23e9faSHans Rosenfeld 		return (NULL);
245682527734SSukumar Swaminathan 	}
245782527734SSukumar Swaminathan 
245882527734SSukumar Swaminathan #else
245982527734SSukumar Swaminathan 	switch (sgl_type) {
246082527734SSukumar Swaminathan 	case SGL_CMD:
246182527734SSukumar Swaminathan 		cp = &pkt->pkt_cmd_cookie;
246282527734SSukumar Swaminathan 		cookie_cnt = 1;
246382527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
246482527734SSukumar Swaminathan 		break;
246582527734SSukumar Swaminathan 
246682527734SSukumar Swaminathan 	case SGL_RESP:
246782527734SSukumar Swaminathan 		cp = &pkt->pkt_resp_cookie;
246882527734SSukumar Swaminathan 		cookie_cnt = 1;
246982527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
247082527734SSukumar Swaminathan 		break;
247182527734SSukumar Swaminathan 
247282527734SSukumar Swaminathan 
247382527734SSukumar Swaminathan 	case SGL_DATA:
247482527734SSukumar Swaminathan 		cp = &pkt->pkt_data_cookie;
247582527734SSukumar Swaminathan 		cookie_cnt = 1;
247682527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
247782527734SSukumar Swaminathan 		break;
2478*8f23e9faSHans Rosenfeld 
2479*8f23e9faSHans Rosenfeld 	default:
2480*8f23e9faSHans Rosenfeld 		return (NULL);
248182527734SSukumar Swaminathan 	}
248282527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
248382527734SSukumar Swaminathan 
248482527734SSukumar Swaminathan 	stage_sge.offset = 0;
2485*8f23e9faSHans Rosenfeld 	stage_sge.type = 0;
248682527734SSukumar Swaminathan 	stage_sge.last = 0;
248782527734SSukumar Swaminathan 	cnt = 0;
248882527734SSukumar Swaminathan 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
248982527734SSukumar Swaminathan 
249082527734SSukumar Swaminathan 		sge_size = cp->dmac_size;
249182527734SSukumar Swaminathan 		sge_addr = cp->dmac_laddress;
249282527734SSukumar Swaminathan 		while (sge_size && size) {
249382527734SSukumar Swaminathan 			if (cnt) {
249482527734SSukumar Swaminathan 				/* Copy staged SGE before we build next one */
249582527734SSukumar Swaminathan 				BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
249682527734SSukumar Swaminathan 				    (uint8_t *)sge, sizeof (ULP_SGE64));
249782527734SSukumar Swaminathan 				sge++;
249882527734SSukumar Swaminathan 			}
249982527734SSukumar Swaminathan 			len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
250082527734SSukumar Swaminathan 			len = MIN(size, len);
250182527734SSukumar Swaminathan 
250282527734SSukumar Swaminathan 			stage_sge.addrHigh =
250382527734SSukumar Swaminathan 			    PADDR_HI(sge_addr);
250482527734SSukumar Swaminathan 			stage_sge.addrLow =
250582527734SSukumar Swaminathan 			    PADDR_LO(sge_addr);
250682527734SSukumar Swaminathan 			stage_sge.length = len;
250782527734SSukumar Swaminathan 			if (sgl_type == SGL_DATA) {
250882527734SSukumar Swaminathan 				stage_sge.offset = cnt;
250982527734SSukumar Swaminathan 			}
251082527734SSukumar Swaminathan #ifdef DEBUG_SGE
2511a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge,
251282527734SSukumar Swaminathan 			    4, 0);
2513*8f23e9faSHans Rosenfeld #endif /* DEBUG_SGE */
251482527734SSukumar Swaminathan 			sge_addr += len;
251582527734SSukumar Swaminathan 			sge_size -= len;
251682527734SSukumar Swaminathan 
251782527734SSukumar Swaminathan 			cnt += len;
251882527734SSukumar Swaminathan 			size -= len;
251982527734SSukumar Swaminathan 		}
252082527734SSukumar Swaminathan 	}
252182527734SSukumar Swaminathan 
252282527734SSukumar Swaminathan 	if (last) {
252382527734SSukumar Swaminathan 		stage_sge.last = 1;
252482527734SSukumar Swaminathan 	}
252582527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
252682527734SSukumar Swaminathan 	    sizeof (ULP_SGE64));
2527a9800bebSGarrett D'Amore 
252882527734SSukumar Swaminathan 	sge++;
252982527734SSukumar Swaminathan 
2530*8f23e9faSHans Rosenfeld 	if (pcnt) {
2531*8f23e9faSHans Rosenfeld 		*pcnt = cnt;
2532*8f23e9faSHans Rosenfeld 	}
253382527734SSukumar Swaminathan 	return (sge);
253482527734SSukumar Swaminathan 
253582527734SSukumar Swaminathan } /* emlxs_pkt_to_sgl */
253682527734SSukumar Swaminathan 
253782527734SSukumar Swaminathan 
253882527734SSukumar Swaminathan /*ARGSUSED*/
253982527734SSukumar Swaminathan uint32_t
254082527734SSukumar Swaminathan emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
254182527734SSukumar Swaminathan {
2542*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
254382527734SSukumar Swaminathan 	fc_packet_t *pkt;
2544a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
254582527734SSukumar Swaminathan 	ULP_SGE64 *sge;
254682527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
254782527734SSukumar Swaminathan 	IOCBQ *iocbq;
254882527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
2549*8f23e9faSHans Rosenfeld 	ddi_dma_cookie_t *cp_data;
2550*8f23e9faSHans Rosenfeld 	uint64_t sge_addr;
255182527734SSukumar Swaminathan 	uint32_t cmd_cnt;
255282527734SSukumar Swaminathan 	uint32_t resp_cnt;
255382527734SSukumar Swaminathan 
255482527734SSukumar Swaminathan 	iocbq = (IOCBQ *) &sbp->iocbq;
255582527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
255682527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2557a9800bebSGarrett D'Amore 	xrip = sbp->xrip;
2558a9800bebSGarrett D'Amore 	sge = xrip->SGList.virt;
255982527734SSukumar Swaminathan 
256082527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
256182527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
2562*8f23e9faSHans Rosenfeld 	cp_data = pkt->pkt_data_cookie;
256382527734SSukumar Swaminathan #else
256482527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
2565*8f23e9faSHans Rosenfeld 	cp_data = &pkt->pkt_data_cookie;
256682527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
256782527734SSukumar Swaminathan 
256882527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
256982527734SSukumar Swaminathan 	if (iocbq->flag & IOCB_FCP_CMD) {
257082527734SSukumar Swaminathan 
257182527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
257282527734SSukumar Swaminathan 			return (1);
257382527734SSukumar Swaminathan 		}
257482527734SSukumar Swaminathan 
257582527734SSukumar Swaminathan 		/* CMD payload */
2576*8f23e9faSHans Rosenfeld 		sge = emlxs_pkt_to_sgl(port, pkt, sge, SGL_CMD, &cmd_cnt);
2577*8f23e9faSHans Rosenfeld 		if (! sge) {
2578*8f23e9faSHans Rosenfeld 			return (1);
2579*8f23e9faSHans Rosenfeld 		}
258082527734SSukumar Swaminathan 
258182527734SSukumar Swaminathan 		/* DATA payload */
258282527734SSukumar Swaminathan 		if (pkt->pkt_datalen != 0) {
258382527734SSukumar Swaminathan 			/* RSP payload */
2584*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
258582527734SSukumar Swaminathan 			    SGL_RESP, &resp_cnt);
2586*8f23e9faSHans Rosenfeld 			if (! sge) {
2587*8f23e9faSHans Rosenfeld 				return (1);
2588*8f23e9faSHans Rosenfeld 			}
258982527734SSukumar Swaminathan 
2590*8f23e9faSHans Rosenfeld 			/* Data payload */
2591*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
2592*8f23e9faSHans Rosenfeld 			    SGL_DATA | SGL_LAST, 0);
2593*8f23e9faSHans Rosenfeld 			if (! sge) {
2594*8f23e9faSHans Rosenfeld 				return (1);
2595*8f23e9faSHans Rosenfeld 			}
2596*8f23e9faSHans Rosenfeld sgl_done:
2597*8f23e9faSHans Rosenfeld 			if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2598*8f23e9faSHans Rosenfeld 				sge_addr = cp_data->dmac_laddress;
2599*8f23e9faSHans Rosenfeld 				wqe->FirstData.addrHigh = PADDR_HI(sge_addr);
2600*8f23e9faSHans Rosenfeld 				wqe->FirstData.addrLow = PADDR_LO(sge_addr);
2601*8f23e9faSHans Rosenfeld 				wqe->FirstData.tus.f.bdeSize =
2602*8f23e9faSHans Rosenfeld 				    cp_data->dmac_size;
2603*8f23e9faSHans Rosenfeld 			}
260482527734SSukumar Swaminathan 		} else {
260582527734SSukumar Swaminathan 			/* RSP payload */
2606*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
260782527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
2608*8f23e9faSHans Rosenfeld 			if (! sge) {
2609*8f23e9faSHans Rosenfeld 				return (1);
2610*8f23e9faSHans Rosenfeld 			}
261182527734SSukumar Swaminathan 		}
261282527734SSukumar Swaminathan 
261382527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrHigh =
261482527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
261582527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrLow =
261682527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
261782527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
261882527734SSukumar Swaminathan 		wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
261982527734SSukumar Swaminathan 
262082527734SSukumar Swaminathan 	} else {
262182527734SSukumar Swaminathan 
262282527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
262382527734SSukumar Swaminathan 			/* CMD payload */
2624*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
262582527734SSukumar Swaminathan 			    SGL_CMD | SGL_LAST, &cmd_cnt);
2626*8f23e9faSHans Rosenfeld 			if (! sge) {
2627*8f23e9faSHans Rosenfeld 				return (1);
2628*8f23e9faSHans Rosenfeld 			}
262982527734SSukumar Swaminathan 		} else {
263082527734SSukumar Swaminathan 			/* CMD payload */
2631*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
263282527734SSukumar Swaminathan 			    SGL_CMD, &cmd_cnt);
2633*8f23e9faSHans Rosenfeld 			if (! sge) {
2634*8f23e9faSHans Rosenfeld 				return (1);
2635*8f23e9faSHans Rosenfeld 			}
263682527734SSukumar Swaminathan 
263782527734SSukumar Swaminathan 			/* RSP payload */
2638*8f23e9faSHans Rosenfeld 			sge = emlxs_pkt_to_sgl(port, pkt, sge,
263982527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
2640*8f23e9faSHans Rosenfeld 			if (! sge) {
2641*8f23e9faSHans Rosenfeld 				return (1);
2642*8f23e9faSHans Rosenfeld 			}
264382527734SSukumar Swaminathan 			wqe->un.GenReq.PayloadLength = cmd_cnt;
264482527734SSukumar Swaminathan 		}
264582527734SSukumar Swaminathan 
264682527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrHigh =
264782527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
264882527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrLow =
264982527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
265082527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
265182527734SSukumar Swaminathan 	}
265282527734SSukumar Swaminathan 	return (0);
265382527734SSukumar Swaminathan } /* emlxs_sli4_bde_setup */
265482527734SSukumar Swaminathan 
265582527734SSukumar Swaminathan 
265682527734SSukumar Swaminathan 
265782527734SSukumar Swaminathan 
2658*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
2659*8f23e9faSHans Rosenfeld /*ARGSUSED*/
2660*8f23e9faSHans Rosenfeld static uint32_t
2661*8f23e9faSHans Rosenfeld emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
266282527734SSukumar Swaminathan {
2663*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
266482527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
2665*8f23e9faSHans Rosenfeld 	ULP_SGE64 stage_sge;
2666*8f23e9faSHans Rosenfeld 	ULP_SGE64 *sge;
2667*8f23e9faSHans Rosenfeld 	IOCB *iocb;
2668*8f23e9faSHans Rosenfeld 	IOCBQ *iocbq;
2669*8f23e9faSHans Rosenfeld 	MATCHMAP *mp;
2670*8f23e9faSHans Rosenfeld 	MATCHMAP *fct_mp;
2671*8f23e9faSHans Rosenfeld 	XRIobj_t *xrip;
2672*8f23e9faSHans Rosenfeld 	uint64_t sge_addr;
2673*8f23e9faSHans Rosenfeld 	uint32_t sge_size;
2674*8f23e9faSHans Rosenfeld 	uint32_t cnt;
2675*8f23e9faSHans Rosenfeld 	uint32_t len;
2676*8f23e9faSHans Rosenfeld 	uint32_t size;
2677*8f23e9faSHans Rosenfeld 	uint32_t *xrdy_vaddr;
2678*8f23e9faSHans Rosenfeld 	stmf_data_buf_t *dbuf;
2679*8f23e9faSHans Rosenfeld 
2680*8f23e9faSHans Rosenfeld 	iocbq = &sbp->iocbq;
2681*8f23e9faSHans Rosenfeld 	iocb = &iocbq->iocb;
2682*8f23e9faSHans Rosenfeld 	wqe = &iocbq->wqe;
2683*8f23e9faSHans Rosenfeld 	xrip = sbp->xrip;
2684*8f23e9faSHans Rosenfeld 
2685*8f23e9faSHans Rosenfeld 	if (!sbp->fct_buf) {
2686*8f23e9faSHans Rosenfeld 		return (0);
2687*8f23e9faSHans Rosenfeld 	}
2688*8f23e9faSHans Rosenfeld 
2689*8f23e9faSHans Rosenfeld 	size = sbp->fct_buf->db_data_size;
2690*8f23e9faSHans Rosenfeld 
2691*8f23e9faSHans Rosenfeld 	/*
2692*8f23e9faSHans Rosenfeld 	 * The hardware will automaticlly round up
2693*8f23e9faSHans Rosenfeld 	 * to multiple of 4.
2694*8f23e9faSHans Rosenfeld 	 *
2695*8f23e9faSHans Rosenfeld 	 * if (size & 3) {
2696*8f23e9faSHans Rosenfeld 	 *	size = (size + 3) & 0xfffffffc;
2697*8f23e9faSHans Rosenfeld 	 * }
2698*8f23e9faSHans Rosenfeld 	 */
2699*8f23e9faSHans Rosenfeld 	fct_mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2700*8f23e9faSHans Rosenfeld 
2701*8f23e9faSHans Rosenfeld 	if (sbp->fct_buf->db_sglist_length != 1) {
2702*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2703*8f23e9faSHans Rosenfeld 		    "fct_bde_setup: Only 1 sglist entry supported: %d",
2704*8f23e9faSHans Rosenfeld 		    sbp->fct_buf->db_sglist_length);
2705*8f23e9faSHans Rosenfeld 		return (1);
2706*8f23e9faSHans Rosenfeld 	}
2707*8f23e9faSHans Rosenfeld 
2708*8f23e9faSHans Rosenfeld 	sge = xrip->SGList.virt;
2709*8f23e9faSHans Rosenfeld 
2710*8f23e9faSHans Rosenfeld 	if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) {
2711*8f23e9faSHans Rosenfeld 
2712*8f23e9faSHans Rosenfeld 		mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE);
2713*8f23e9faSHans Rosenfeld 		if (!mp || !mp->virt || !mp->phys) {
2714*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2715*8f23e9faSHans Rosenfeld 			    "fct_bde_setup: Cannot allocate XRDY memory");
2716*8f23e9faSHans Rosenfeld 			return (1);
2717*8f23e9faSHans Rosenfeld 		}
2718*8f23e9faSHans Rosenfeld 		/* Save the MATCHMAP info to free this memory later */
2719*8f23e9faSHans Rosenfeld 		iocbq->bp = mp;
2720*8f23e9faSHans Rosenfeld 
2721*8f23e9faSHans Rosenfeld 		/* Point to XRDY payload */
2722*8f23e9faSHans Rosenfeld 		xrdy_vaddr = (uint32_t *)(mp->virt);
2723*8f23e9faSHans Rosenfeld 
2724*8f23e9faSHans Rosenfeld 		/* Fill in burstsize in payload */
2725*8f23e9faSHans Rosenfeld 		*xrdy_vaddr++ = 0;
2726*8f23e9faSHans Rosenfeld 		*xrdy_vaddr++ = LE_SWAP32(size);
2727*8f23e9faSHans Rosenfeld 		*xrdy_vaddr = 0;
2728*8f23e9faSHans Rosenfeld 
2729*8f23e9faSHans Rosenfeld 		/* First 2 SGEs are XRDY and SKIP */
2730*8f23e9faSHans Rosenfeld 		stage_sge.addrHigh = PADDR_HI(mp->phys);
2731*8f23e9faSHans Rosenfeld 		stage_sge.addrLow = PADDR_LO(mp->phys);
2732*8f23e9faSHans Rosenfeld 		stage_sge.length = EMLXS_XFER_RDY_SIZE;
2733*8f23e9faSHans Rosenfeld 		stage_sge.offset = 0;
2734*8f23e9faSHans Rosenfeld 		stage_sge.type = 0;
2735*8f23e9faSHans Rosenfeld 		stage_sge.last = 0;
2736*8f23e9faSHans Rosenfeld 
2737*8f23e9faSHans Rosenfeld 		/* Words  0-3 */
2738*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
2739*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
2740*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = EMLXS_XFER_RDY_SIZE;
2741*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.PayloadLength = EMLXS_XFER_RDY_SIZE;
2742*8f23e9faSHans Rosenfeld 
2743*8f23e9faSHans Rosenfeld 	} else {	/* CMD_FCP_TSEND64_CX */
2744*8f23e9faSHans Rosenfeld 		/* First 2 SGEs are SKIP */
2745*8f23e9faSHans Rosenfeld 		stage_sge.addrHigh = 0;
2746*8f23e9faSHans Rosenfeld 		stage_sge.addrLow = 0;
2747*8f23e9faSHans Rosenfeld 		stage_sge.length = 0;
2748*8f23e9faSHans Rosenfeld 		stage_sge.offset = 0;
2749*8f23e9faSHans Rosenfeld 		stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2750*8f23e9faSHans Rosenfeld 		stage_sge.last = 0;
2751*8f23e9faSHans Rosenfeld 
2752*8f23e9faSHans Rosenfeld 		/* Words  0-3 */
2753*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrHigh = PADDR_HI(fct_mp->phys);
2754*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrLow = PADDR_LO(fct_mp->phys);
2755*8f23e9faSHans Rosenfeld 
2756*8f23e9faSHans Rosenfeld 		/* The BDE should match the contents of the first SGE payload */
2757*8f23e9faSHans Rosenfeld 		len = MIN(EMLXS_MAX_SGE_SIZE, size);
2758*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = len;
2759*8f23e9faSHans Rosenfeld 
2760*8f23e9faSHans Rosenfeld 		/* The PayloadLength should be set to 0 for TSEND64. */
2761*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.PayloadLength = 0;
2762*8f23e9faSHans Rosenfeld 	}
2763*8f23e9faSHans Rosenfeld 
2764*8f23e9faSHans Rosenfeld 	dbuf = sbp->fct_buf;
2765*8f23e9faSHans Rosenfeld 	/*
2766*8f23e9faSHans Rosenfeld 	 * TotalTransferCount equals to Relative Offset field (Word 4)
2767*8f23e9faSHans Rosenfeld 	 * in both TSEND64 and TRECEIVE64 WQE.
2768*8f23e9faSHans Rosenfeld 	 */
2769*8f23e9faSHans Rosenfeld 	wqe->un.FcpCmd.TotalTransferCount = dbuf->db_relative_offset;
2770*8f23e9faSHans Rosenfeld 
2771*8f23e9faSHans Rosenfeld 	/* Copy staged SGE into SGL */
2772*8f23e9faSHans Rosenfeld 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2773*8f23e9faSHans Rosenfeld 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2774*8f23e9faSHans Rosenfeld 	sge++;
2775*8f23e9faSHans Rosenfeld 
2776*8f23e9faSHans Rosenfeld 	stage_sge.addrHigh = 0;
2777*8f23e9faSHans Rosenfeld 	stage_sge.addrLow = 0;
2778*8f23e9faSHans Rosenfeld 	stage_sge.length = 0;
2779*8f23e9faSHans Rosenfeld 	stage_sge.offset = 0;
2780*8f23e9faSHans Rosenfeld 	stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2781*8f23e9faSHans Rosenfeld 	stage_sge.last = 0;
2782*8f23e9faSHans Rosenfeld 
2783*8f23e9faSHans Rosenfeld 	/* Copy staged SGE into SGL */
2784*8f23e9faSHans Rosenfeld 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2785*8f23e9faSHans Rosenfeld 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2786*8f23e9faSHans Rosenfeld 	sge++;
2787*8f23e9faSHans Rosenfeld 
2788*8f23e9faSHans Rosenfeld 	sge_size = size;
2789*8f23e9faSHans Rosenfeld 	sge_addr = fct_mp->phys;
2790*8f23e9faSHans Rosenfeld 	cnt = 0;
2791*8f23e9faSHans Rosenfeld 
2792*8f23e9faSHans Rosenfeld 	/* Build SGEs */
2793*8f23e9faSHans Rosenfeld 	while (sge_size) {
2794*8f23e9faSHans Rosenfeld 		if (cnt) {
2795*8f23e9faSHans Rosenfeld 			/* Copy staged SGE before we build next one */
2796*8f23e9faSHans Rosenfeld 			BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2797*8f23e9faSHans Rosenfeld 			    (uint8_t *)sge, sizeof (ULP_SGE64));
2798*8f23e9faSHans Rosenfeld 			sge++;
2799*8f23e9faSHans Rosenfeld 		}
2800*8f23e9faSHans Rosenfeld 
2801*8f23e9faSHans Rosenfeld 		len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
2802*8f23e9faSHans Rosenfeld 
2803*8f23e9faSHans Rosenfeld 		stage_sge.addrHigh = PADDR_HI(sge_addr);
2804*8f23e9faSHans Rosenfeld 		stage_sge.addrLow = PADDR_LO(sge_addr);
2805*8f23e9faSHans Rosenfeld 		stage_sge.length = len;
2806*8f23e9faSHans Rosenfeld 		stage_sge.offset = cnt;
2807*8f23e9faSHans Rosenfeld 		stage_sge.type = EMLXS_SGE_TYPE_DATA;
2808*8f23e9faSHans Rosenfeld 
2809*8f23e9faSHans Rosenfeld 		sge_addr += len;
2810*8f23e9faSHans Rosenfeld 		sge_size -= len;
2811*8f23e9faSHans Rosenfeld 		cnt += len;
2812*8f23e9faSHans Rosenfeld 	}
2813*8f23e9faSHans Rosenfeld 
2814*8f23e9faSHans Rosenfeld 	stage_sge.last = 1;
2815*8f23e9faSHans Rosenfeld 
2816*8f23e9faSHans Rosenfeld 	if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2817*8f23e9faSHans Rosenfeld 		wqe->FirstData.addrHigh = stage_sge.addrHigh;
2818*8f23e9faSHans Rosenfeld 		wqe->FirstData.addrLow = stage_sge.addrLow;
2819*8f23e9faSHans Rosenfeld 		wqe->FirstData.tus.f.bdeSize = stage_sge.length;
2820*8f23e9faSHans Rosenfeld 	}
2821*8f23e9faSHans Rosenfeld 	/* Copy staged SGE into SGL */
2822*8f23e9faSHans Rosenfeld 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2823*8f23e9faSHans Rosenfeld 	    (uint8_t *)sge, sizeof (ULP_SGE64));
2824*8f23e9faSHans Rosenfeld 
2825*8f23e9faSHans Rosenfeld 	return (0);
2826*8f23e9faSHans Rosenfeld 
2827*8f23e9faSHans Rosenfeld } /* emlxs_sli4_fct_bde_setup */
2828*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
2829*8f23e9faSHans Rosenfeld 
2830*8f23e9faSHans Rosenfeld 
2831*8f23e9faSHans Rosenfeld static void
2832*8f23e9faSHans Rosenfeld emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2833*8f23e9faSHans Rosenfeld {
2834*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
2835*8f23e9faSHans Rosenfeld 	emlxs_buf_t *sbp;
2836*8f23e9faSHans Rosenfeld 	uint32_t channelno;
2837*8f23e9faSHans Rosenfeld 	int32_t throttle;
2838*8f23e9faSHans Rosenfeld 	emlxs_wqe_t *wqe;
2839*8f23e9faSHans Rosenfeld 	emlxs_wqe_t *wqeslot;
2840*8f23e9faSHans Rosenfeld 	WQ_DESC_t *wq;
2841*8f23e9faSHans Rosenfeld 	uint32_t flag;
2842*8f23e9faSHans Rosenfeld 	uint32_t wqdb;
2843*8f23e9faSHans Rosenfeld 	uint16_t next_wqe;
2844*8f23e9faSHans Rosenfeld 	off_t offset;
2845*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
2846*8f23e9faSHans Rosenfeld 	int32_t node_throttle;
2847*8f23e9faSHans Rosenfeld 	NODELIST *marked_node = NULL;
2848*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
2849*8f23e9faSHans Rosenfeld 
285082527734SSukumar Swaminathan 
285182527734SSukumar Swaminathan 	channelno = cp->channelno;
285282527734SSukumar Swaminathan 	wq = (WQ_DESC_t *)cp->iopath;
285382527734SSukumar Swaminathan 
2854*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
285582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
285682527734SSukumar Swaminathan 	    "ISSUE WQE channel: %x  %p", channelno, wq);
2857*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
285882527734SSukumar Swaminathan 
285982527734SSukumar Swaminathan 	throttle = 0;
286082527734SSukumar Swaminathan 
286182527734SSukumar Swaminathan 	/* Check if FCP ring and adapter is not ready */
286282527734SSukumar Swaminathan 	/* We may use any ring for FCP_CMD */
286382527734SSukumar Swaminathan 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
286482527734SSukumar Swaminathan 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2865*8f23e9faSHans Rosenfeld 		    (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) {
286682527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
286782527734SSukumar Swaminathan 			return;
286882527734SSukumar Swaminathan 		}
286982527734SSukumar Swaminathan 	}
287082527734SSukumar Swaminathan 
287182527734SSukumar Swaminathan 	/* Attempt to acquire CMD_RING lock */
2872a9800bebSGarrett D'Amore 	if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) {
287382527734SSukumar Swaminathan 		/* Queue it for later */
287482527734SSukumar Swaminathan 		if (iocbq) {
287582527734SSukumar Swaminathan 			if ((hba->io_count -
287682527734SSukumar Swaminathan 			    hba->channel_tx_count) > 10) {
287782527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
287882527734SSukumar Swaminathan 				return;
287982527734SSukumar Swaminathan 			} else {
288082527734SSukumar Swaminathan 
2881a9800bebSGarrett D'Amore 				mutex_enter(&EMLXS_QUE_LOCK(channelno));
288282527734SSukumar Swaminathan 			}
288382527734SSukumar Swaminathan 		} else {
288482527734SSukumar Swaminathan 			return;
288582527734SSukumar Swaminathan 		}
288682527734SSukumar Swaminathan 	}
2887a9800bebSGarrett D'Amore 	/* EMLXS_QUE_LOCK acquired */
288882527734SSukumar Swaminathan 
288982527734SSukumar Swaminathan 	/* Throttle check only applies to non special iocb */
289082527734SSukumar Swaminathan 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
289182527734SSukumar Swaminathan 		/* Check if HBA is full */
289282527734SSukumar Swaminathan 		throttle = hba->io_throttle - hba->io_active;
289382527734SSukumar Swaminathan 		if (throttle <= 0) {
289482527734SSukumar Swaminathan 			/* Hitting adapter throttle limit */
289582527734SSukumar Swaminathan 			/* Queue it for later */
289682527734SSukumar Swaminathan 			if (iocbq) {
289782527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
289882527734SSukumar Swaminathan 			}
289982527734SSukumar Swaminathan 
290082527734SSukumar Swaminathan 			goto busy;
290182527734SSukumar Swaminathan 		}
290282527734SSukumar Swaminathan 	}
290382527734SSukumar Swaminathan 
290482527734SSukumar Swaminathan 	/* Check to see if we have room for this WQE */
290582527734SSukumar Swaminathan 	next_wqe = wq->host_index + 1;
290682527734SSukumar Swaminathan 	if (next_wqe >= wq->max_index) {
290782527734SSukumar Swaminathan 		next_wqe = 0;
290882527734SSukumar Swaminathan 	}
290982527734SSukumar Swaminathan 
291082527734SSukumar Swaminathan 	if (next_wqe == wq->port_index) {
291182527734SSukumar Swaminathan 		/* Queue it for later */
291282527734SSukumar Swaminathan 		if (iocbq) {
291382527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
291482527734SSukumar Swaminathan 		}
291582527734SSukumar Swaminathan 		goto busy;
291682527734SSukumar Swaminathan 	}
291782527734SSukumar Swaminathan 
291882527734SSukumar Swaminathan 	/*
291982527734SSukumar Swaminathan 	 * We have a command ring slot available
292082527734SSukumar Swaminathan 	 * Make sure we have an iocb to send
292182527734SSukumar Swaminathan 	 */
292282527734SSukumar Swaminathan 	if (iocbq) {
292382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
292482527734SSukumar Swaminathan 
292582527734SSukumar Swaminathan 		/* Check if the ring already has iocb's waiting */
292682527734SSukumar Swaminathan 		if (cp->nodeq.q_first != NULL) {
292782527734SSukumar Swaminathan 			/* Put the current iocbq on the tx queue */
292882527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 0);
292982527734SSukumar Swaminathan 
293082527734SSukumar Swaminathan 			/*
293182527734SSukumar Swaminathan 			 * Attempt to replace it with the next iocbq
293282527734SSukumar Swaminathan 			 * in the tx queue
293382527734SSukumar Swaminathan 			 */
293482527734SSukumar Swaminathan 			iocbq = emlxs_tx_get(cp, 0);
293582527734SSukumar Swaminathan 		}
293682527734SSukumar Swaminathan 
293782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
293882527734SSukumar Swaminathan 	} else {
293982527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
294082527734SSukumar Swaminathan 	}
294182527734SSukumar Swaminathan 
294282527734SSukumar Swaminathan sendit:
294382527734SSukumar Swaminathan 	/* Process each iocbq */
294482527734SSukumar Swaminathan 	while (iocbq) {
2945*8f23e9faSHans Rosenfeld 		sbp = iocbq->sbp;
2946*8f23e9faSHans Rosenfeld 
2947*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
2948*8f23e9faSHans Rosenfeld 		if (sbp && sbp->node && sbp->node->io_throttle) {
2949*8f23e9faSHans Rosenfeld 			node_throttle = sbp->node->io_throttle -
2950*8f23e9faSHans Rosenfeld 			    sbp->node->io_active;
2951*8f23e9faSHans Rosenfeld 			if (node_throttle <= 0) {
2952*8f23e9faSHans Rosenfeld 				/* Node is busy */
2953*8f23e9faSHans Rosenfeld 				/* Queue this iocb and get next iocb from */
2954*8f23e9faSHans Rosenfeld 				/* channel */
2955*8f23e9faSHans Rosenfeld 
2956*8f23e9faSHans Rosenfeld 				if (!marked_node) {
2957*8f23e9faSHans Rosenfeld 					marked_node = sbp->node;
2958*8f23e9faSHans Rosenfeld 				}
2959*8f23e9faSHans Rosenfeld 
2960*8f23e9faSHans Rosenfeld 				mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2961*8f23e9faSHans Rosenfeld 				emlxs_tx_put(iocbq, 0);
2962*8f23e9faSHans Rosenfeld 
2963*8f23e9faSHans Rosenfeld 				if (cp->nodeq.q_first == marked_node) {
2964*8f23e9faSHans Rosenfeld 					mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2965*8f23e9faSHans Rosenfeld 					goto busy;
2966*8f23e9faSHans Rosenfeld 				}
2967*8f23e9faSHans Rosenfeld 
2968*8f23e9faSHans Rosenfeld 				iocbq = emlxs_tx_get(cp, 0);
2969*8f23e9faSHans Rosenfeld 				mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2970*8f23e9faSHans Rosenfeld 				continue;
2971*8f23e9faSHans Rosenfeld 			}
2972*8f23e9faSHans Rosenfeld 		}
2973*8f23e9faSHans Rosenfeld 		marked_node = 0;
2974*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
297582527734SSukumar Swaminathan 
297682527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
2977*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
297882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2979*8f23e9faSHans Rosenfeld 		    "ISSUE QID %d WQE iotag:%x xri:%d", wq->qid,
298082527734SSukumar Swaminathan 		    wqe->RequestTag, wqe->XRITag);
2981*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
298282527734SSukumar Swaminathan 
298382527734SSukumar Swaminathan 		if (sbp) {
298482527734SSukumar Swaminathan 			/* If exchange removed after wqe was prep'ed, drop it */
2985a9800bebSGarrett D'Amore 			if (!(sbp->xrip)) {
298682527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2987*8f23e9faSHans Rosenfeld 				    "Xmit WQE iotag:%x xri:%d aborted",
298882527734SSukumar Swaminathan 				    wqe->RequestTag, wqe->XRITag);
298982527734SSukumar Swaminathan 
299082527734SSukumar Swaminathan 				/* Get next iocb from the tx queue */
299182527734SSukumar Swaminathan 				iocbq = emlxs_tx_get(cp, 1);
299282527734SSukumar Swaminathan 				continue;
299382527734SSukumar Swaminathan 			}
299482527734SSukumar Swaminathan 
299582527734SSukumar Swaminathan 			if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
299682527734SSukumar Swaminathan 
299782527734SSukumar Swaminathan 				/* Perform delay */
299882527734SSukumar Swaminathan 				if ((channelno == hba->channel_els) &&
299982527734SSukumar Swaminathan 				    !(iocbq->flag & IOCB_FCP_CMD)) {
300082527734SSukumar Swaminathan 					drv_usecwait(100000);
300182527734SSukumar Swaminathan 				} else {
300282527734SSukumar Swaminathan 					drv_usecwait(20000);
300382527734SSukumar Swaminathan 				}
300482527734SSukumar Swaminathan 			}
300582527734SSukumar Swaminathan 
3006*8f23e9faSHans Rosenfeld 			/* Check for ULP pkt request */
300782527734SSukumar Swaminathan 			mutex_enter(&sbp->mtx);
300882527734SSukumar Swaminathan 
300982527734SSukumar Swaminathan 			if (sbp->node == NULL) {
301082527734SSukumar Swaminathan 				/* Set node to base node by default */
301182527734SSukumar Swaminathan 				iocbq->node = (void *)&port->node_base;
301282527734SSukumar Swaminathan 				sbp->node = (void *)&port->node_base;
301382527734SSukumar Swaminathan 			}
301482527734SSukumar Swaminathan 
301582527734SSukumar Swaminathan 			sbp->pkt_flags |= PACKET_IN_CHIPQ;
301682527734SSukumar Swaminathan 			mutex_exit(&sbp->mtx);
301782527734SSukumar Swaminathan 
30181a5e258fSJosef 'Jeff' Sipek 			atomic_inc_32(&hba->io_active);
3019*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
3020*8f23e9faSHans Rosenfeld 			if (sbp->node) {
3021*8f23e9faSHans Rosenfeld 				atomic_inc_32(&sbp->node->io_active);
3022*8f23e9faSHans Rosenfeld 			}
3023*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
302482527734SSukumar Swaminathan 
3025*8f23e9faSHans Rosenfeld 			sbp->xrip->flag |= EMLXS_XRI_PENDING_IO;
302682527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
302782527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
302882527734SSukumar Swaminathan 			if (sbp->fct_cmd) {
302982527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
303082527734SSukumar Swaminathan 				    EMLXS_FCT_IOCB_ISSUED);
303182527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
303282527734SSukumar Swaminathan 				    icmd->ULPCOMMAND);
303382527734SSukumar Swaminathan 			}
303482527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
303582527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
303682527734SSukumar Swaminathan 			cp->hbaSendCmd_sbp++;
303782527734SSukumar Swaminathan 			iocbq->channel = cp;
303882527734SSukumar Swaminathan 		} else {
303982527734SSukumar Swaminathan 			cp->hbaSendCmd++;
304082527734SSukumar Swaminathan 		}
304182527734SSukumar Swaminathan 
304282527734SSukumar Swaminathan 		flag = iocbq->flag;
304382527734SSukumar Swaminathan 
3044*8f23e9faSHans Rosenfeld 		/*
3045*8f23e9faSHans Rosenfeld 		 * At this point, we have a command ring slot available
3046*8f23e9faSHans Rosenfeld 		 * and an iocb to send
3047*8f23e9faSHans Rosenfeld 		 */
3048*8f23e9faSHans Rosenfeld 		wq->release_depth--;
3049*8f23e9faSHans Rosenfeld 		if (wq->release_depth == 0) {
3050*8f23e9faSHans Rosenfeld 			wq->release_depth = WQE_RELEASE_DEPTH;
3051*8f23e9faSHans Rosenfeld 			wqe->WQEC = 1;
3052*8f23e9faSHans Rosenfeld 		}
3053*8f23e9faSHans Rosenfeld 
3054*8f23e9faSHans Rosenfeld 		HBASTATS.IocbIssued[channelno]++;
3055*8f23e9faSHans Rosenfeld 		wq->num_proc++;
3056*8f23e9faSHans Rosenfeld 
305782527734SSukumar Swaminathan 		/* Send the iocb */
305882527734SSukumar Swaminathan 		wqeslot = (emlxs_wqe_t *)wq->addr.virt;
305982527734SSukumar Swaminathan 		wqeslot += wq->host_index;
306082527734SSukumar Swaminathan 
306182527734SSukumar Swaminathan 		wqe->CQId = wq->cqid;
3062*8f23e9faSHans Rosenfeld 		if (hba->sli.sli4.param.PHWQ) {
3063*8f23e9faSHans Rosenfeld 			WQE_PHWQ_WQID(wqe, wq->qid);
3064*8f23e9faSHans Rosenfeld 		}
306582527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
306682527734SSukumar Swaminathan 		    sizeof (emlxs_wqe_t));
306782527734SSukumar Swaminathan #ifdef DEBUG_WQE
3068a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0);
3069*8f23e9faSHans Rosenfeld #endif /* DEBUG_WQE */
3070b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
3071b3660a96SSukumar Swaminathan 		    wq->addr.virt) -
3072b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
3073b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
3074b3660a96SSukumar Swaminathan 
3075b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset,
307682527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
307782527734SSukumar Swaminathan 
307882527734SSukumar Swaminathan 		/* Ring the WQ Doorbell */
307982527734SSukumar Swaminathan 		wqdb = wq->qid;
308082527734SSukumar Swaminathan 		wqdb |= ((1 << 24) | (wq->host_index << 16));
308182527734SSukumar Swaminathan 
3082*8f23e9faSHans Rosenfeld 		/*
3083*8f23e9faSHans Rosenfeld 		 * After this, the sbp / iocb / wqe should not be
3084*8f23e9faSHans Rosenfeld 		 * accessed in the xmit path.
3085*8f23e9faSHans Rosenfeld 		 */
308682527734SSukumar Swaminathan 
3087*8f23e9faSHans Rosenfeld 		emlxs_sli4_write_wqdb(hba, wqdb);
308882527734SSukumar Swaminathan 		wq->host_index = next_wqe;
308982527734SSukumar Swaminathan 
3090*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
309182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
309282527734SSukumar Swaminathan 		    "WQ RING: %08x", wqdb);
3093*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
309482527734SSukumar Swaminathan 
309582527734SSukumar Swaminathan 		if (!sbp) {
3096a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
309782527734SSukumar Swaminathan 		}
309882527734SSukumar Swaminathan 
309982527734SSukumar Swaminathan 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
310082527734SSukumar Swaminathan 			/* Check if HBA is full */
310182527734SSukumar Swaminathan 			throttle = hba->io_throttle - hba->io_active;
310282527734SSukumar Swaminathan 			if (throttle <= 0) {
310382527734SSukumar Swaminathan 				goto busy;
310482527734SSukumar Swaminathan 			}
310582527734SSukumar Swaminathan 		}
310682527734SSukumar Swaminathan 
310782527734SSukumar Swaminathan 		/* Check to see if we have room for another WQE */
310882527734SSukumar Swaminathan 		next_wqe++;
310982527734SSukumar Swaminathan 		if (next_wqe >= wq->max_index) {
311082527734SSukumar Swaminathan 			next_wqe = 0;
311182527734SSukumar Swaminathan 		}
311282527734SSukumar Swaminathan 
311382527734SSukumar Swaminathan 		if (next_wqe == wq->port_index) {
311482527734SSukumar Swaminathan 			/* Queue it for later */
311582527734SSukumar Swaminathan 			goto busy;
311682527734SSukumar Swaminathan 		}
311782527734SSukumar Swaminathan 
311882527734SSukumar Swaminathan 		/* Get the next iocb from the tx queue if there is one */
311982527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
312082527734SSukumar Swaminathan 	}
312182527734SSukumar Swaminathan 
3122a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
312382527734SSukumar Swaminathan 
312482527734SSukumar Swaminathan 	return;
312582527734SSukumar Swaminathan 
312682527734SSukumar Swaminathan busy:
3127*8f23e9faSHans Rosenfeld 	wq->num_busy++;
312882527734SSukumar Swaminathan 	if (throttle <= 0) {
312982527734SSukumar Swaminathan 		HBASTATS.IocbThrottled++;
313082527734SSukumar Swaminathan 	} else {
313182527734SSukumar Swaminathan 		HBASTATS.IocbRingFull[channelno]++;
313282527734SSukumar Swaminathan 	}
313382527734SSukumar Swaminathan 
3134a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_QUE_LOCK(channelno));
313582527734SSukumar Swaminathan 
313682527734SSukumar Swaminathan 	return;
313782527734SSukumar Swaminathan 
313882527734SSukumar Swaminathan } /* emlxs_sli4_issue_iocb_cmd() */
313982527734SSukumar Swaminathan 
314082527734SSukumar Swaminathan 
314182527734SSukumar Swaminathan /*ARGSUSED*/
314282527734SSukumar Swaminathan static uint32_t
3143a9800bebSGarrett D'Amore emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb,
3144a9800bebSGarrett D'Amore     uint32_t tmo)
314582527734SSukumar Swaminathan {
3146a9800bebSGarrett D'Amore 	emlxs_hba_t *hba = HBA;
314782527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
314882527734SSukumar Swaminathan 	MAILBOX4	*mb4;
314982527734SSukumar Swaminathan 	MATCHMAP	*mp;
315082527734SSukumar Swaminathan 	uint32_t	*iptr;
315182527734SSukumar Swaminathan 	uint32_t	mqdb;
3152b3660a96SSukumar Swaminathan 	off_t		offset;
315382527734SSukumar Swaminathan 
315482527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
315582527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
315682527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
3157a9800bebSGarrett D'Amore 	hba->mbox_mqe = (void *)mqe;
315882527734SSukumar Swaminathan 
315982527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
316082527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
316182527734SSukumar Swaminathan 		/*
316282527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
316382527734SSukumar Swaminathan 		 * into the mailbox area.
316482527734SSukumar Swaminathan 		 */
316582527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
316682527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
316782527734SSukumar Swaminathan 
316882527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
316982527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
317082527734SSukumar Swaminathan 
3171a9800bebSGarrett D'Amore 		if (mb->mbxCommand != MBX_HEARTBEAT) {
3172a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe,
3173a9800bebSGarrett D'Amore 			    18, 0);
3174a9800bebSGarrett D'Amore 		}
317582527734SSukumar Swaminathan 	} else {
317682527734SSukumar Swaminathan 		/* SLI_CONFIG and non-embedded */
317782527734SSukumar Swaminathan 
317882527734SSukumar Swaminathan 		/*
317982527734SSukumar Swaminathan 		 * If this is not embedded, the MQ area
318082527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
318182527734SSukumar Swaminathan 		 * non-embedded mailbox command.
318282527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
318382527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
318482527734SSukumar Swaminathan 		 */
318582527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
318682527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
318782527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
318882527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
318982527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
319082527734SSukumar Swaminathan 		*iptr = mp->size;
319182527734SSukumar Swaminathan 
319282527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
319382527734SSukumar Swaminathan 
319482527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
319582527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
319682527734SSukumar Swaminathan 
319782527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
319882527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
319982527734SSukumar Swaminathan 
3200b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
3201b3660a96SSukumar Swaminathan 		    hba->sli.sli4.mq.addr.virt) -
3202b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
3203b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
3204b3660a96SSukumar Swaminathan 
3205b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
320682527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
320782527734SSukumar Swaminathan 
3208a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0);
320982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
321082527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
3211a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
321282527734SSukumar Swaminathan 	}
321382527734SSukumar Swaminathan 
321482527734SSukumar Swaminathan 	/* Ring the MQ Doorbell */
321582527734SSukumar Swaminathan 	mqdb = hba->sli.sli4.mq.qid;
321682527734SSukumar Swaminathan 	mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
321782527734SSukumar Swaminathan 
3218a9800bebSGarrett D'Amore 	if (mb->mbxCommand != MBX_HEARTBEAT) {
3219a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3220a9800bebSGarrett D'Amore 		    "MQ RING: %08x", mqdb);
3221a9800bebSGarrett D'Amore 	}
322282527734SSukumar Swaminathan 
3223*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_mqdb(hba, mqdb);
3224*8f23e9faSHans Rosenfeld 
322582527734SSukumar Swaminathan 	return (MBX_SUCCESS);
322682527734SSukumar Swaminathan 
322782527734SSukumar Swaminathan } /* emlxs_sli4_issue_mq() */
322882527734SSukumar Swaminathan 
322982527734SSukumar Swaminathan 
323082527734SSukumar Swaminathan /*ARGSUSED*/
323182527734SSukumar Swaminathan static uint32_t
323282527734SSukumar Swaminathan emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
323382527734SSukumar Swaminathan {
323482527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
323582527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
323682527734SSukumar Swaminathan 	MAILBOX4	*mb4;
3237b3660a96SSukumar Swaminathan 	MATCHMAP	*mp = NULL;
323882527734SSukumar Swaminathan 	uint32_t	*iptr;
3239b3660a96SSukumar Swaminathan 	int		nonembed = 0;
324082527734SSukumar Swaminathan 
324182527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
324282527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
324382527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
3244a9800bebSGarrett D'Amore 	hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt;
324582527734SSukumar Swaminathan 
324682527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
324782527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
324882527734SSukumar Swaminathan 		/*
324982527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
325082527734SSukumar Swaminathan 		 * into the bootstrap mailbox area.
325182527734SSukumar Swaminathan 		 */
325282527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
325382527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
325482527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
325582527734SSukumar Swaminathan 
325682527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
325782527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
3258a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0);
325982527734SSukumar Swaminathan 	} else {
326082527734SSukumar Swaminathan 		/*
326182527734SSukumar Swaminathan 		 * If this is not embedded, the bootstrap mailbox area
326282527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
326382527734SSukumar Swaminathan 		 * non-embedded mailbox command.
326482527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
326582527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
326682527734SSukumar Swaminathan 		 */
3267b3660a96SSukumar Swaminathan 		nonembed = 1;
326882527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
326982527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
327082527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
327182527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
327282527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
327382527734SSukumar Swaminathan 		*iptr = mp->size;
327482527734SSukumar Swaminathan 
327582527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
327682527734SSukumar Swaminathan 
327782527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
327882527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
327982527734SSukumar Swaminathan 
328082527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
328182527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
328282527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
328382527734SSukumar Swaminathan 
328482527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
328582527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
328682527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
328782527734SSukumar Swaminathan 
3288a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0);
328982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
329082527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys,
329182527734SSukumar Swaminathan 		    (uint32_t *)((uint8_t *)mp->virt));
329282527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
3293a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
329482527734SSukumar Swaminathan 	}
329582527734SSukumar Swaminathan 
329682527734SSukumar Swaminathan 
329782527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
329882527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
329982527734SSukumar Swaminathan 		return (MBX_TIMEOUT);
330082527734SSukumar Swaminathan 	}
330182527734SSukumar Swaminathan 
330282527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
330382527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
330482527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
330582527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
330682527734SSukumar Swaminathan 
330782527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
330882527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
330982527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
331082527734SSukumar Swaminathan 
3311a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0);
331282527734SSukumar Swaminathan 
331382527734SSukumar Swaminathan 	} else {
331482527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
331582527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
331682527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
331782527734SSukumar Swaminathan 
331882527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
331982527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
332082527734SSukumar Swaminathan 
332182527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
332282527734SSukumar Swaminathan 
332382527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
332482527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
332582527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
332682527734SSukumar Swaminathan 
3327a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0);
332882527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
3329a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
333082527734SSukumar Swaminathan 	}
333182527734SSukumar Swaminathan 
3332b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3333b3660a96SSukumar Swaminathan 	if (nonembed && mp) {
3334b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
3335b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
3336b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3337b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3338*8f23e9faSHans Rosenfeld 			    "sli4_issue_bootstrap: mp_hdl=%p",
3339b3660a96SSukumar Swaminathan 			    mp->dma_handle);
3340b3660a96SSukumar Swaminathan 			return (MBXERR_DMA_ERROR);
3341b3660a96SSukumar Swaminathan 		}
3342b3660a96SSukumar Swaminathan 	}
3343b3660a96SSukumar Swaminathan 
3344b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba,
3345b3660a96SSukumar Swaminathan 	    hba->sli.sli4.bootstrapmb.dma_handle)
3346b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
3347b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
3348b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
3349*8f23e9faSHans Rosenfeld 		    "sli4_issue_bootstrap: hdl=%p",
3350b3660a96SSukumar Swaminathan 		    hba->sli.sli4.bootstrapmb.dma_handle);
3351b3660a96SSukumar Swaminathan 		return (MBXERR_DMA_ERROR);
3352b3660a96SSukumar Swaminathan 	}
3353b3660a96SSukumar Swaminathan #endif
3354b3660a96SSukumar Swaminathan 
335582527734SSukumar Swaminathan 	return (MBX_SUCCESS);
335682527734SSukumar Swaminathan 
335782527734SSukumar Swaminathan } /* emlxs_sli4_issue_bootstrap() */
335882527734SSukumar Swaminathan 
335982527734SSukumar Swaminathan 
336082527734SSukumar Swaminathan /*ARGSUSED*/
336182527734SSukumar Swaminathan static uint32_t
336282527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
336382527734SSukumar Swaminathan     uint32_t tmo)
336482527734SSukumar Swaminathan {
3365a9800bebSGarrett D'Amore 	emlxs_port_t	*port;
336682527734SSukumar Swaminathan 	MAILBOX4	*mb4;
336782527734SSukumar Swaminathan 	MAILBOX		*mb;
336882527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
336982527734SSukumar Swaminathan 	MATCHMAP	*mp;
337082527734SSukumar Swaminathan 	uint32_t	*iptr;
337182527734SSukumar Swaminathan 	uint32_t	rc;
337282527734SSukumar Swaminathan 	uint32_t	i;
337382527734SSukumar Swaminathan 	uint32_t	tmo_local;
337482527734SSukumar Swaminathan 
3375a9800bebSGarrett D'Amore 	if (!mbq->port) {
3376a9800bebSGarrett D'Amore 		mbq->port = &PPORT;
3377a9800bebSGarrett D'Amore 	}
3378a9800bebSGarrett D'Amore 
3379a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
3380a9800bebSGarrett D'Amore 
338182527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mbq;
338282527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
338382527734SSukumar Swaminathan 
338482527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
338582527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
338682527734SSukumar Swaminathan 
338782527734SSukumar Swaminathan 	/* Check for minimum timeouts */
338882527734SSukumar Swaminathan 	switch (mb->mbxCommand) {
338982527734SSukumar Swaminathan 	/* Mailbox commands that erase/write flash */
339082527734SSukumar Swaminathan 	case MBX_DOWN_LOAD:
339182527734SSukumar Swaminathan 	case MBX_UPDATE_CFG:
339282527734SSukumar Swaminathan 	case MBX_LOAD_AREA:
339382527734SSukumar Swaminathan 	case MBX_LOAD_EXP_ROM:
339482527734SSukumar Swaminathan 	case MBX_WRITE_NV:
339582527734SSukumar Swaminathan 	case MBX_FLASH_WR_ULA:
339682527734SSukumar Swaminathan 	case MBX_DEL_LD_ENTRY:
339782527734SSukumar Swaminathan 	case MBX_LOAD_SM:
3398*8f23e9faSHans Rosenfeld 	case MBX_DUMP_MEMORY:
3399*8f23e9faSHans Rosenfeld 	case MBX_WRITE_VPARMS:
3400*8f23e9faSHans Rosenfeld 	case MBX_ACCESS_VDATA:
340182527734SSukumar Swaminathan 		if (tmo < 300) {
340282527734SSukumar Swaminathan 			tmo = 300;
340382527734SSukumar Swaminathan 		}
340482527734SSukumar Swaminathan 		break;
340582527734SSukumar Swaminathan 
3406*8f23e9faSHans Rosenfeld 	case MBX_SLI_CONFIG: {
3407*8f23e9faSHans Rosenfeld 		mbox_req_hdr_t *hdr_req;
3408*8f23e9faSHans Rosenfeld 
3409*8f23e9faSHans Rosenfeld 		hdr_req = (mbox_req_hdr_t *)
3410*8f23e9faSHans Rosenfeld 		    &mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3411*8f23e9faSHans Rosenfeld 
3412*8f23e9faSHans Rosenfeld 		if (hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) {
3413*8f23e9faSHans Rosenfeld 			switch (hdr_req->opcode) {
3414*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_WRITE_OBJ:
3415*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_READ_OBJ:
3416*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_READ_OBJ_LIST:
3417*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_DELETE_OBJ:
3418*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_BOOT_CFG:
3419*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_GET_PROFILE_CFG:
3420*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_PROFILE_CFG:
3421*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_GET_PROFILE_LIST:
3422*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_ACTIVE_PROFILE:
3423*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_GET_PROFILE_CAPS:
3424*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_GET_MR_PROFILE_CAPS:
3425*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_MR_PROFILE_CAPS:
3426*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_FACTORY_PROFILE_CFG:
3427*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SEND_ACTIVATION:
3428*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_RESET_LICENSES:
3429*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_SET_PHYSICAL_LINK_CFG_V1:
3430*8f23e9faSHans Rosenfeld 			case COMMON_OPCODE_GET_VPD_DATA:
3431*8f23e9faSHans Rosenfeld 				if (tmo < 300) {
3432*8f23e9faSHans Rosenfeld 					tmo = 300;
3433*8f23e9faSHans Rosenfeld 				}
3434*8f23e9faSHans Rosenfeld 				break;
3435*8f23e9faSHans Rosenfeld 			default:
3436*8f23e9faSHans Rosenfeld 				if (tmo < 30) {
3437*8f23e9faSHans Rosenfeld 					tmo = 30;
3438*8f23e9faSHans Rosenfeld 				}
3439*8f23e9faSHans Rosenfeld 			}
3440*8f23e9faSHans Rosenfeld 		} else if (hdr_req->subsystem == IOCTL_SUBSYSTEM_FCOE) {
3441*8f23e9faSHans Rosenfeld 			switch (hdr_req->opcode) {
3442*8f23e9faSHans Rosenfeld 			case FCOE_OPCODE_SET_FCLINK_SETTINGS:
3443*8f23e9faSHans Rosenfeld 				if (tmo < 300) {
3444*8f23e9faSHans Rosenfeld 					tmo = 300;
3445*8f23e9faSHans Rosenfeld 				}
3446*8f23e9faSHans Rosenfeld 				break;
3447*8f23e9faSHans Rosenfeld 			default:
3448*8f23e9faSHans Rosenfeld 				if (tmo < 30) {
3449*8f23e9faSHans Rosenfeld 					tmo = 30;
3450*8f23e9faSHans Rosenfeld 				}
3451*8f23e9faSHans Rosenfeld 			}
3452*8f23e9faSHans Rosenfeld 		} else {
3453*8f23e9faSHans Rosenfeld 			if (tmo < 30) {
3454*8f23e9faSHans Rosenfeld 				tmo = 30;
3455*8f23e9faSHans Rosenfeld 			}
3456*8f23e9faSHans Rosenfeld 		}
3457*8f23e9faSHans Rosenfeld 
3458*8f23e9faSHans Rosenfeld 		/*
3459*8f23e9faSHans Rosenfeld 		 * Also: VENDOR_MANAGE_FFV  (0x13, 0x02) (not currently used)
3460*8f23e9faSHans Rosenfeld 		 */
3461*8f23e9faSHans Rosenfeld 
3462*8f23e9faSHans Rosenfeld 		break;
3463*8f23e9faSHans Rosenfeld 	}
346482527734SSukumar Swaminathan 	default:
346582527734SSukumar Swaminathan 		if (tmo < 30) {
346682527734SSukumar Swaminathan 			tmo = 30;
346782527734SSukumar Swaminathan 		}
346882527734SSukumar Swaminathan 		break;
346982527734SSukumar Swaminathan 	}
347082527734SSukumar Swaminathan 
347182527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
347282527734SSukumar Swaminathan 	tmo_local = tmo * 100;
347382527734SSukumar Swaminathan 
347482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
347582527734SSukumar Swaminathan 
347682527734SSukumar Swaminathan 	/* Adjust wait flag */
347782527734SSukumar Swaminathan 	if (flag != MBX_NOWAIT) {
347882527734SSukumar Swaminathan 		if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
347982527734SSukumar Swaminathan 			flag = MBX_SLEEP;
348082527734SSukumar Swaminathan 		} else {
348182527734SSukumar Swaminathan 			flag = MBX_POLL;
348282527734SSukumar Swaminathan 		}
348382527734SSukumar Swaminathan 	} else {
348482527734SSukumar Swaminathan 		/* Must have interrupts enabled to perform MBX_NOWAIT */
348582527734SSukumar Swaminathan 		if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
348682527734SSukumar Swaminathan 
348782527734SSukumar Swaminathan 			mb->mbxStatus = MBX_HARDWARE_ERROR;
348882527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
348982527734SSukumar Swaminathan 
349082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3491a9800bebSGarrett D'Amore 			    "Interrupts disabled. %s failed.",
349282527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
349382527734SSukumar Swaminathan 
349482527734SSukumar Swaminathan 			return (MBX_HARDWARE_ERROR);
349582527734SSukumar Swaminathan 		}
349682527734SSukumar Swaminathan 	}
349782527734SSukumar Swaminathan 
3498bce54adfSSukumar Swaminathan 	/* Check for hardware error ; special case SLI_CONFIG */
3499bce54adfSSukumar Swaminathan 	if ((hba->flag & FC_HARDWARE_ERROR) &&
3500bce54adfSSukumar Swaminathan 	    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3501bce54adfSSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3502bce54adfSSukumar Swaminathan 	    COMMON_OPCODE_RESET))) {
350382527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
350482527734SSukumar Swaminathan 
350582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
350682527734SSukumar Swaminathan 
350782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
350882527734SSukumar Swaminathan 		    "Hardware error reported. %s failed. status=%x mb=%p",
3509*8f23e9faSHans Rosenfeld 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
351082527734SSukumar Swaminathan 
351182527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
351282527734SSukumar Swaminathan 	}
351382527734SSukumar Swaminathan 
351482527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
351582527734SSukumar Swaminathan 		/* If we are not polling, then queue it for later */
351682527734SSukumar Swaminathan 		if (flag == MBX_NOWAIT) {
351782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
351882527734SSukumar Swaminathan 			    "Busy.      %s: mb=%p NoWait.",
351982527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
352082527734SSukumar Swaminathan 
352182527734SSukumar Swaminathan 			emlxs_mb_put(hba, mbq);
352282527734SSukumar Swaminathan 
352382527734SSukumar Swaminathan 			HBASTATS.MboxBusy++;
352482527734SSukumar Swaminathan 
352582527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
352682527734SSukumar Swaminathan 
352782527734SSukumar Swaminathan 			return (MBX_BUSY);
352882527734SSukumar Swaminathan 		}
352982527734SSukumar Swaminathan 
353082527734SSukumar Swaminathan 		while (hba->mbox_queue_flag) {
353182527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
353282527734SSukumar Swaminathan 
353382527734SSukumar Swaminathan 			if (tmo_local-- == 0) {
353482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
353582527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
353682527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
353782527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
353882527734SSukumar Swaminathan 				    tmo);
353982527734SSukumar Swaminathan 
354082527734SSukumar Swaminathan 				/* Non-lethalStatus mailbox timeout */
354182527734SSukumar Swaminathan 				/* Does not indicate a hardware error */
354282527734SSukumar Swaminathan 				mb->mbxStatus = MBX_TIMEOUT;
354382527734SSukumar Swaminathan 				return (MBX_TIMEOUT);
354482527734SSukumar Swaminathan 			}
354582527734SSukumar Swaminathan 
3546*8f23e9faSHans Rosenfeld 			BUSYWAIT_MS(10);
354782527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
3548*8f23e9faSHans Rosenfeld 
3549*8f23e9faSHans Rosenfeld 			/* Check for hardware error ; special case SLI_CONFIG */
3550*8f23e9faSHans Rosenfeld 			if ((hba->flag & FC_HARDWARE_ERROR) &&
3551*8f23e9faSHans Rosenfeld 			    ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3552*8f23e9faSHans Rosenfeld 			    (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3553*8f23e9faSHans Rosenfeld 			    COMMON_OPCODE_RESET))) {
3554*8f23e9faSHans Rosenfeld 				mb->mbxStatus = MBX_HARDWARE_ERROR;
3555*8f23e9faSHans Rosenfeld 
3556*8f23e9faSHans Rosenfeld 				mutex_exit(&EMLXS_PORT_LOCK);
3557*8f23e9faSHans Rosenfeld 
3558*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
3559*8f23e9faSHans Rosenfeld 				    &emlxs_mbox_detail_msg,
3560*8f23e9faSHans Rosenfeld 				    "Hardware error reported. %s failed. "
3561*8f23e9faSHans Rosenfeld 				    "status=%x mb=%p",
3562*8f23e9faSHans Rosenfeld 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3563*8f23e9faSHans Rosenfeld 				    mb->mbxStatus, mb);
3564*8f23e9faSHans Rosenfeld 
3565*8f23e9faSHans Rosenfeld 				return (MBX_HARDWARE_ERROR);
3566*8f23e9faSHans Rosenfeld 			}
356782527734SSukumar Swaminathan 		}
356882527734SSukumar Swaminathan 	}
356982527734SSukumar Swaminathan 
357082527734SSukumar Swaminathan 	/* Initialize mailbox area */
357182527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
357282527734SSukumar Swaminathan 
3573a9800bebSGarrett D'Amore 	if (mb->mbxCommand == MBX_DOWN_LINK) {
3574a9800bebSGarrett D'Amore 		hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK;
3575a9800bebSGarrett D'Amore 	}
3576a9800bebSGarrett D'Amore 
357782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
357882527734SSukumar Swaminathan 	switch (flag) {
357982527734SSukumar Swaminathan 
358082527734SSukumar Swaminathan 	case MBX_NOWAIT:
358182527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_HEARTBEAT) {
358282527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
358382527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
358482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
358582527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
358682527734SSukumar Swaminathan 				    "Sending.   %s: mb=%p NoWait. embedded %d",
358782527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
358882527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
358982527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
359082527734SSukumar Swaminathan 			}
359182527734SSukumar Swaminathan 		}
359282527734SSukumar Swaminathan 
359382527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
359482527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
359582527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
359682527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
359782527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
359882527734SSukumar Swaminathan 		}
359982527734SSukumar Swaminathan 
360082527734SSukumar Swaminathan 		if (mbq->bp) {
360182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
360282527734SSukumar Swaminathan 			    "BDE virt %p phys %p size x%x",
360382527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->virt,
360482527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->phys,
360582527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->size);
3606a9800bebSGarrett D'Amore 			emlxs_data_dump(port, "DATA",
360782527734SSukumar Swaminathan 			    (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
360882527734SSukumar Swaminathan 		}
3609a9800bebSGarrett D'Amore 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
361082527734SSukumar Swaminathan 		break;
361182527734SSukumar Swaminathan 
361282527734SSukumar Swaminathan 	case MBX_POLL:
361382527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
361482527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
361582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
361682527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Poll. embedded %d",
361782527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
361882527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
361982527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
362082527734SSukumar Swaminathan 		}
362182527734SSukumar Swaminathan 
362282527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
362382527734SSukumar Swaminathan 
362482527734SSukumar Swaminathan 		/* Clean up the mailbox area */
362582527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
362682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
362782527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
362882527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
362982527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
363082527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
363182527734SSukumar Swaminathan 
363282527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
363382527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
363482527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
363582527734SSukumar Swaminathan 
363682527734SSukumar Swaminathan 		} else {
363782527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
363882527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
363982527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
364082527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
3641a9800bebSGarrett D'Amore 				    "Completed.   %s: mb=%p status=%x Poll. "
364282527734SSukumar Swaminathan 				    "embedded %d",
364382527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
364482527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
364582527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
364682527734SSukumar Swaminathan 			}
364782527734SSukumar Swaminathan 
364882527734SSukumar Swaminathan 			/* Process the result */
364982527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
365082527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
365182527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
365282527734SSukumar Swaminathan 				}
365382527734SSukumar Swaminathan 			}
365482527734SSukumar Swaminathan 
365582527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
365682527734SSukumar Swaminathan 		}
365782527734SSukumar Swaminathan 
365882527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
365982527734SSukumar Swaminathan 		if (mp) {
366082527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
366182527734SSukumar Swaminathan 			if (hdr_rsp->status) {
3662a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
3663a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
3664a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3665a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3666a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
3667a9800bebSGarrett D'Amore 
366882527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
366982527734SSukumar Swaminathan 			}
367082527734SSukumar Swaminathan 		}
367182527734SSukumar Swaminathan 		rc = mb->mbxStatus;
367282527734SSukumar Swaminathan 
367382527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
367482527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)emlxs_mb_get(hba);
367582527734SSukumar Swaminathan 		if (mbq) {
367682527734SSukumar Swaminathan 			/* Attempt to send pending mailboxes */
367782527734SSukumar Swaminathan 			i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
367882527734SSukumar Swaminathan 			if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
3679a9800bebSGarrett D'Amore 				emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
368082527734SSukumar Swaminathan 			}
368182527734SSukumar Swaminathan 		}
368282527734SSukumar Swaminathan 		break;
368382527734SSukumar Swaminathan 
368482527734SSukumar Swaminathan 	case MBX_SLEEP:
368582527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
368682527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
368782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
368882527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Sleep. embedded %d",
368982527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
369082527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
369182527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
369282527734SSukumar Swaminathan 		}
369382527734SSukumar Swaminathan 
369482527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
369582527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
369682527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
369782527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
369882527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
369982527734SSukumar Swaminathan 		}
370082527734SSukumar Swaminathan 
3701a9800bebSGarrett D'Amore 		rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
370282527734SSukumar Swaminathan 
370382527734SSukumar Swaminathan 		if (rc != MBX_SUCCESS) {
370482527734SSukumar Swaminathan 			break;
370582527734SSukumar Swaminathan 		}
370682527734SSukumar Swaminathan 
370782527734SSukumar Swaminathan 		/* Wait for completion */
370882527734SSukumar Swaminathan 		/* The driver clock is timing the mailbox. */
370982527734SSukumar Swaminathan 
371082527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
371182527734SSukumar Swaminathan 		while (!(mbq->flag & MBQ_COMPLETED)) {
371282527734SSukumar Swaminathan 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
371382527734SSukumar Swaminathan 		}
371482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
371582527734SSukumar Swaminathan 
371682527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
371782527734SSukumar Swaminathan 		if (mp) {
371882527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
371982527734SSukumar Swaminathan 			if (hdr_rsp->status) {
3720a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
3721a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
3722a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3723a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3724a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
3725a9800bebSGarrett D'Amore 
372682527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
372782527734SSukumar Swaminathan 			}
372882527734SSukumar Swaminathan 		}
372982527734SSukumar Swaminathan 		rc = mb->mbxStatus;
373082527734SSukumar Swaminathan 
373182527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
373282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
373382527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
373482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
373582527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
373682527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
373782527734SSukumar Swaminathan 		} else {
373882527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
373982527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
374082527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
374182527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
3742a9800bebSGarrett D'Amore 				    "Completed.   %s: mb=%p status=%x Sleep. "
374382527734SSukumar Swaminathan 				    "embedded %d",
374482527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
374582527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
374682527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
374782527734SSukumar Swaminathan 			}
374882527734SSukumar Swaminathan 		}
374982527734SSukumar Swaminathan 		break;
375082527734SSukumar Swaminathan 	}
375182527734SSukumar Swaminathan 
375282527734SSukumar Swaminathan 	return (rc);
375382527734SSukumar Swaminathan 
375482527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd() */
375582527734SSukumar Swaminathan 
375682527734SSukumar Swaminathan 
375782527734SSukumar Swaminathan 
375882527734SSukumar Swaminathan /*ARGSUSED*/
375982527734SSukumar Swaminathan static uint32_t
376082527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
376182527734SSukumar Swaminathan     uint32_t tmo)
376282527734SSukumar Swaminathan {
376382527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
376482527734SSukumar Swaminathan 	MAILBOX		*mb;
376582527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
376682527734SSukumar Swaminathan 	MATCHMAP	*mp;
376782527734SSukumar Swaminathan 	uint32_t	rc;
376882527734SSukumar Swaminathan 	uint32_t	tmo_local;
376982527734SSukumar Swaminathan 
377082527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
377182527734SSukumar Swaminathan 
377282527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
377382527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
377482527734SSukumar Swaminathan 
377582527734SSukumar Swaminathan 	if (tmo < 30) {
377682527734SSukumar Swaminathan 		tmo = 30;
377782527734SSukumar Swaminathan 	}
377882527734SSukumar Swaminathan 
377982527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
378082527734SSukumar Swaminathan 	tmo_local = tmo * 100;
378182527734SSukumar Swaminathan 
378282527734SSukumar Swaminathan 	flag = MBX_POLL;
378382527734SSukumar Swaminathan 
378482527734SSukumar Swaminathan 	/* Check for hardware error */
378582527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
378682527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
378782527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
378882527734SSukumar Swaminathan 	}
378982527734SSukumar Swaminathan 
379082527734SSukumar Swaminathan 	/* Initialize mailbox area */
379182527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
379282527734SSukumar Swaminathan 
379382527734SSukumar Swaminathan 	switch (flag) {
379482527734SSukumar Swaminathan 
379582527734SSukumar Swaminathan 	case MBX_POLL:
379682527734SSukumar Swaminathan 
379782527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
379882527734SSukumar Swaminathan 
379982527734SSukumar Swaminathan 		/* Clean up the mailbox area */
380082527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
380182527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
380282527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
380382527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
380482527734SSukumar Swaminathan 
380582527734SSukumar Swaminathan 		} else {
380682527734SSukumar Swaminathan 			/* Process the result */
380782527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
380882527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
380982527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
381082527734SSukumar Swaminathan 				}
381182527734SSukumar Swaminathan 			}
381282527734SSukumar Swaminathan 
381382527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
381482527734SSukumar Swaminathan 		}
381582527734SSukumar Swaminathan 
381682527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
381782527734SSukumar Swaminathan 		if (mp) {
381882527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
381982527734SSukumar Swaminathan 			if (hdr_rsp->status) {
3820a9800bebSGarrett D'Amore 				EMLXS_MSGF(EMLXS_CONTEXT,
3821a9800bebSGarrett D'Amore 				    &emlxs_mbox_detail_msg,
3822a9800bebSGarrett D'Amore 				    "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3823a9800bebSGarrett D'Amore 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
3824a9800bebSGarrett D'Amore 				    hdr_rsp->status, hdr_rsp->extra_status);
3825a9800bebSGarrett D'Amore 
382682527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
382782527734SSukumar Swaminathan 			}
382882527734SSukumar Swaminathan 		}
382982527734SSukumar Swaminathan 		rc = mb->mbxStatus;
383082527734SSukumar Swaminathan 
383182527734SSukumar Swaminathan 		break;
383282527734SSukumar Swaminathan 	}
383382527734SSukumar Swaminathan 
383482527734SSukumar Swaminathan 	return (rc);
383582527734SSukumar Swaminathan 
383682527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
383782527734SSukumar Swaminathan 
383882527734SSukumar Swaminathan 
383982527734SSukumar Swaminathan 
384082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
384182527734SSukumar Swaminathan /*ARGSUSED*/
384282527734SSukumar Swaminathan extern uint32_t
3843*8f23e9faSHans Rosenfeld emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
384482527734SSukumar Swaminathan {
384582527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3846*8f23e9faSHans Rosenfeld 	emlxs_config_t *cfg = &CFG;
3847*8f23e9faSHans Rosenfeld 	fct_cmd_t *fct_cmd;
3848*8f23e9faSHans Rosenfeld 	stmf_data_buf_t *dbuf;
3849*8f23e9faSHans Rosenfeld 	scsi_task_t *fct_task;
385082527734SSukumar Swaminathan 	fc_packet_t *pkt;
385182527734SSukumar Swaminathan 	CHANNEL *cp;
3852a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
3853*8f23e9faSHans Rosenfeld 	emlxs_node_t *ndlp;
385482527734SSukumar Swaminathan 	IOCBQ *iocbq;
3855*8f23e9faSHans Rosenfeld 	IOCB *iocb;
3856*8f23e9faSHans Rosenfeld 	emlxs_wqe_t *wqe;
3857*8f23e9faSHans Rosenfeld 	ULP_SGE64 stage_sge;
3858*8f23e9faSHans Rosenfeld 	ULP_SGE64 *sge;
3859*8f23e9faSHans Rosenfeld 	RPIobj_t *rpip;
3860*8f23e9faSHans Rosenfeld 	int32_t	sge_size;
3861*8f23e9faSHans Rosenfeld 	uint64_t sge_addr;
386282527734SSukumar Swaminathan 	uint32_t did;
3863*8f23e9faSHans Rosenfeld 	uint32_t timeout;
386482527734SSukumar Swaminathan 
3865*8f23e9faSHans Rosenfeld 	ddi_dma_cookie_t *cp_cmd;
386682527734SSukumar Swaminathan 
3867*8f23e9faSHans Rosenfeld 	pkt = PRIV2PKT(cmd_sbp);
386882527734SSukumar Swaminathan 
3869*8f23e9faSHans Rosenfeld 	cp = (CHANNEL *)cmd_sbp->channel;
387082527734SSukumar Swaminathan 
3871*8f23e9faSHans Rosenfeld 	iocbq = &cmd_sbp->iocbq;
3872*8f23e9faSHans Rosenfeld 	iocb = &iocbq->iocb;
387382527734SSukumar Swaminathan 
3874*8f23e9faSHans Rosenfeld 	did = cmd_sbp->did;
3875*8f23e9faSHans Rosenfeld 	if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) {
387682527734SSukumar Swaminathan 
3877*8f23e9faSHans Rosenfeld 		ndlp = cmd_sbp->node;
3878*8f23e9faSHans Rosenfeld 		rpip = EMLXS_NODE_TO_RPI(port, ndlp);
387982527734SSukumar Swaminathan 
3880*8f23e9faSHans Rosenfeld 		if (!rpip) {
3881*8f23e9faSHans Rosenfeld 			/* Use the fabric rpi */
3882*8f23e9faSHans Rosenfeld 			rpip = port->vpip->fabric_rpip;
3883*8f23e9faSHans Rosenfeld 		}
388482527734SSukumar Swaminathan 
3885*8f23e9faSHans Rosenfeld 		/* Next allocate an Exchange for this command */
3886*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_alloc_xri(port, cmd_sbp, rpip,
3887*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_SOL_BLS_TYPE);
388882527734SSukumar Swaminathan 
3889*8f23e9faSHans Rosenfeld 		if (!xrip) {
3890*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3891*8f23e9faSHans Rosenfeld 			    "Adapter Busy. Unable to allocate exchange. "
3892*8f23e9faSHans Rosenfeld 			    "did=0x%x", did);
389382527734SSukumar Swaminathan 
3894*8f23e9faSHans Rosenfeld 			return (FC_TRAN_BUSY);
3895*8f23e9faSHans Rosenfeld 		}
389682527734SSukumar Swaminathan 
3897*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3898*8f23e9faSHans Rosenfeld 		    "FCT Abort Request: xri=%d iotag=%d sbp=%p rxid=%x",
3899*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->iotag, cmd_sbp, pkt->pkt_cmd_fhdr.rx_id);
390082527734SSukumar Swaminathan 
3901*8f23e9faSHans Rosenfeld 		cmd_sbp->xrip = xrip;
390282527734SSukumar Swaminathan 
3903*8f23e9faSHans Rosenfeld 		cp->ulpSendCmd++;
390482527734SSukumar Swaminathan 
3905*8f23e9faSHans Rosenfeld 		/* Initalize iocbq */
3906*8f23e9faSHans Rosenfeld 		iocbq->port = (void *)port;
3907*8f23e9faSHans Rosenfeld 		iocbq->node = (void *)ndlp;
3908*8f23e9faSHans Rosenfeld 		iocbq->channel = (void *)cp;
390982527734SSukumar Swaminathan 
3910*8f23e9faSHans Rosenfeld 		/*
3911*8f23e9faSHans Rosenfeld 		 * Don't give the abort priority, we want the IOCB
3912*8f23e9faSHans Rosenfeld 		 * we are aborting to be processed first.
3913*8f23e9faSHans Rosenfeld 		 */
3914*8f23e9faSHans Rosenfeld 		iocbq->flag |= IOCB_SPECIAL;
391582527734SSukumar Swaminathan 
3916*8f23e9faSHans Rosenfeld 		wqe = &iocbq->wqe;
3917*8f23e9faSHans Rosenfeld 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
3918b3660a96SSukumar Swaminathan 
3919*8f23e9faSHans Rosenfeld 		wqe = &iocbq->wqe;
3920*8f23e9faSHans Rosenfeld 		wqe->un.Abort.Criteria = ABORT_XRI_TAG;
3921*8f23e9faSHans Rosenfeld 		wqe->RequestTag = xrip->iotag;
3922*8f23e9faSHans Rosenfeld 		wqe->AbortTag = pkt->pkt_cmd_fhdr.rx_id;
3923*8f23e9faSHans Rosenfeld 		wqe->Command = CMD_ABORT_XRI_CX;
3924*8f23e9faSHans Rosenfeld 		wqe->Class = CLASS3;
3925*8f23e9faSHans Rosenfeld 		wqe->CQId = 0xffff;
3926*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_ABORT;
392782527734SSukumar Swaminathan 
3928*8f23e9faSHans Rosenfeld 		if (hba->state >= FC_LINK_UP) {
3929*8f23e9faSHans Rosenfeld 			wqe->un.Abort.IA = 0;
3930*8f23e9faSHans Rosenfeld 		} else {
3931*8f23e9faSHans Rosenfeld 			wqe->un.Abort.IA = 1;
3932*8f23e9faSHans Rosenfeld 		}
393382527734SSukumar Swaminathan 
3934*8f23e9faSHans Rosenfeld 		/* Set the pkt timer */
3935*8f23e9faSHans Rosenfeld 		cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3936*8f23e9faSHans Rosenfeld 		    ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3937*8f23e9faSHans Rosenfeld 
3938*8f23e9faSHans Rosenfeld 		return (IOERR_SUCCESS);
3939*8f23e9faSHans Rosenfeld 
3940*8f23e9faSHans Rosenfeld 	} else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) {
3941*8f23e9faSHans Rosenfeld 
3942*8f23e9faSHans Rosenfeld 		timeout = pkt->pkt_timeout;
3943*8f23e9faSHans Rosenfeld 		ndlp = cmd_sbp->node;
3944*8f23e9faSHans Rosenfeld 		if (!ndlp) {
3945*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3946*8f23e9faSHans Rosenfeld 			    "Unable to find rpi. did=0x%x", did);
3947*8f23e9faSHans Rosenfeld 
3948*8f23e9faSHans Rosenfeld 			emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3949*8f23e9faSHans Rosenfeld 			    IOERR_INVALID_RPI, 0);
3950*8f23e9faSHans Rosenfeld 			return (0xff);
3951*8f23e9faSHans Rosenfeld 		}
3952*8f23e9faSHans Rosenfeld 
3953*8f23e9faSHans Rosenfeld 		cp->ulpSendCmd++;
3954*8f23e9faSHans Rosenfeld 
3955*8f23e9faSHans Rosenfeld 		/* Initalize iocbq */
3956*8f23e9faSHans Rosenfeld 		iocbq->port = (void *)port;
3957*8f23e9faSHans Rosenfeld 		iocbq->node = (void *)ndlp;
3958*8f23e9faSHans Rosenfeld 		iocbq->channel = (void *)cp;
3959*8f23e9faSHans Rosenfeld 
3960*8f23e9faSHans Rosenfeld 		wqe = &iocbq->wqe;
3961*8f23e9faSHans Rosenfeld 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
3962*8f23e9faSHans Rosenfeld 
3963*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_register_xri(port, cmd_sbp,
3964*8f23e9faSHans Rosenfeld 		    pkt->pkt_cmd_fhdr.rx_id, did);
3965*8f23e9faSHans Rosenfeld 
3966*8f23e9faSHans Rosenfeld 		if (!xrip) {
3967*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3968*8f23e9faSHans Rosenfeld 			    "Unable to register xri %x. did=0x%x",
3969*8f23e9faSHans Rosenfeld 			    pkt->pkt_cmd_fhdr.rx_id, did);
3970*8f23e9faSHans Rosenfeld 
3971*8f23e9faSHans Rosenfeld 			emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3972*8f23e9faSHans Rosenfeld 			    IOERR_NO_XRI, 0);
3973*8f23e9faSHans Rosenfeld 			return (0xff);
3974*8f23e9faSHans Rosenfeld 		}
3975*8f23e9faSHans Rosenfeld 
3976*8f23e9faSHans Rosenfeld 		cmd_sbp->iotag = xrip->iotag;
3977*8f23e9faSHans Rosenfeld 		cmd_sbp->channel = cp;
3978*8f23e9faSHans Rosenfeld 
3979*8f23e9faSHans Rosenfeld #if (EMLXS_MODREV >= EMLXS_MODREV3)
3980*8f23e9faSHans Rosenfeld 		cp_cmd = pkt->pkt_cmd_cookie;
3981*8f23e9faSHans Rosenfeld #else
3982*8f23e9faSHans Rosenfeld 		cp_cmd  = &pkt->pkt_cmd_cookie;
3983*8f23e9faSHans Rosenfeld #endif	/* >= EMLXS_MODREV3 */
3984*8f23e9faSHans Rosenfeld 
3985*8f23e9faSHans Rosenfeld 		sge_size = pkt->pkt_cmdlen;
3986*8f23e9faSHans Rosenfeld 		/* Make size a multiple of 4 */
3987*8f23e9faSHans Rosenfeld 		if (sge_size & 3) {
3988*8f23e9faSHans Rosenfeld 			sge_size = (sge_size + 3) & 0xfffffffc;
3989*8f23e9faSHans Rosenfeld 		}
3990*8f23e9faSHans Rosenfeld 		sge_addr = cp_cmd->dmac_laddress;
3991*8f23e9faSHans Rosenfeld 		sge = xrip->SGList.virt;
3992*8f23e9faSHans Rosenfeld 
3993*8f23e9faSHans Rosenfeld 		stage_sge.addrHigh = PADDR_HI(sge_addr);
3994*8f23e9faSHans Rosenfeld 		stage_sge.addrLow = PADDR_LO(sge_addr);
3995*8f23e9faSHans Rosenfeld 		stage_sge.length = sge_size;
3996*8f23e9faSHans Rosenfeld 		stage_sge.offset = 0;
3997*8f23e9faSHans Rosenfeld 		stage_sge.type = 0;
3998*8f23e9faSHans Rosenfeld 		stage_sge.last = 1;
3999*8f23e9faSHans Rosenfeld 
4000*8f23e9faSHans Rosenfeld 		/* Copy staged SGE into SGL */
4001*8f23e9faSHans Rosenfeld 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
4002*8f23e9faSHans Rosenfeld 		    (uint8_t *)sge, sizeof (ULP_SGE64));
4003*8f23e9faSHans Rosenfeld 
4004*8f23e9faSHans Rosenfeld 		/* Words  0-3 */
4005*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
4006*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
4007*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = sge_size;
4008*8f23e9faSHans Rosenfeld 		wqe->un.FcpCmd.PayloadLength = sge_size;
4009*8f23e9faSHans Rosenfeld 
4010*8f23e9faSHans Rosenfeld 		/*  Word  6 */
4011*8f23e9faSHans Rosenfeld 		wqe->ContextTag = ndlp->nlp_Rpi;
4012*8f23e9faSHans Rosenfeld 		wqe->XRITag = xrip->XRI;
4013*8f23e9faSHans Rosenfeld 
4014*8f23e9faSHans Rosenfeld 		/*  Word  7 */
4015*8f23e9faSHans Rosenfeld 		wqe->Command  = iocb->ULPCOMMAND;
4016*8f23e9faSHans Rosenfeld 		wqe->Class = cmd_sbp->class;
4017*8f23e9faSHans Rosenfeld 		wqe->ContextType = WQE_RPI_CONTEXT;
4018*8f23e9faSHans Rosenfeld 		wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4019*8f23e9faSHans Rosenfeld 
4020*8f23e9faSHans Rosenfeld 		/*  Word  8 */
4021*8f23e9faSHans Rosenfeld 		wqe->AbortTag = 0;
4022*8f23e9faSHans Rosenfeld 
4023*8f23e9faSHans Rosenfeld 		/*  Word  9 */
4024*8f23e9faSHans Rosenfeld 		wqe->RequestTag = xrip->iotag;
4025*8f23e9faSHans Rosenfeld 		wqe->OXId = (uint16_t)xrip->rx_id;
4026*8f23e9faSHans Rosenfeld 
4027*8f23e9faSHans Rosenfeld 		/*  Word  10 */
4028*8f23e9faSHans Rosenfeld 		if (xrip->flag & EMLXS_XRI_BUSY) {
4029*8f23e9faSHans Rosenfeld 			wqe->XC = 1;
4030*8f23e9faSHans Rosenfeld 		}
4031*8f23e9faSHans Rosenfeld 
4032*8f23e9faSHans Rosenfeld 		if (!(hba->sli.sli4.param.PHWQ)) {
4033*8f23e9faSHans Rosenfeld 			wqe->QOSd = 1;
4034*8f23e9faSHans Rosenfeld 			wqe->DBDE = 1; /* Data type for BDE 0 */
4035*8f23e9faSHans Rosenfeld 		}
4036*8f23e9faSHans Rosenfeld 
4037*8f23e9faSHans Rosenfeld 		/*  Word  11 */
4038*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_TRSP;
4039*8f23e9faSHans Rosenfeld 		wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4040*8f23e9faSHans Rosenfeld 
4041*8f23e9faSHans Rosenfeld 		/* Set the pkt timer */
4042*8f23e9faSHans Rosenfeld 		cmd_sbp->ticks = hba->timer_tics + timeout +
4043*8f23e9faSHans Rosenfeld 		    ((timeout > 0xff) ? 0 : 10);
4044*8f23e9faSHans Rosenfeld 
4045*8f23e9faSHans Rosenfeld 		if (pkt->pkt_cmdlen) {
4046*8f23e9faSHans Rosenfeld 			EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
4047*8f23e9faSHans Rosenfeld 			    DDI_DMA_SYNC_FORDEV);
4048*8f23e9faSHans Rosenfeld 		}
4049*8f23e9faSHans Rosenfeld 
4050*8f23e9faSHans Rosenfeld 		return (IOERR_SUCCESS);
4051*8f23e9faSHans Rosenfeld 	}
4052*8f23e9faSHans Rosenfeld 
4053*8f23e9faSHans Rosenfeld 	fct_cmd = cmd_sbp->fct_cmd;
4054*8f23e9faSHans Rosenfeld 	did = fct_cmd->cmd_rportid;
4055*8f23e9faSHans Rosenfeld 	dbuf = cmd_sbp->fct_buf;
4056*8f23e9faSHans Rosenfeld 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
4057*8f23e9faSHans Rosenfeld 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
4058*8f23e9faSHans Rosenfeld 	if (!ndlp) {
4059*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4060*8f23e9faSHans Rosenfeld 		    "Unable to find rpi. did=0x%x", did);
4061*8f23e9faSHans Rosenfeld 
4062*8f23e9faSHans Rosenfeld 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4063*8f23e9faSHans Rosenfeld 		    IOERR_INVALID_RPI, 0);
4064*8f23e9faSHans Rosenfeld 		return (0xff);
4065*8f23e9faSHans Rosenfeld 	}
4066*8f23e9faSHans Rosenfeld 
4067*8f23e9faSHans Rosenfeld 
4068*8f23e9faSHans Rosenfeld 	/* Initalize iocbq */
4069*8f23e9faSHans Rosenfeld 	iocbq->port = (void *) port;
4070*8f23e9faSHans Rosenfeld 	iocbq->node = (void *)ndlp;
4071*8f23e9faSHans Rosenfeld 	iocbq->channel = (void *) cp;
4072*8f23e9faSHans Rosenfeld 
4073*8f23e9faSHans Rosenfeld 	wqe = &iocbq->wqe;
4074*8f23e9faSHans Rosenfeld 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4075*8f23e9faSHans Rosenfeld 
4076*8f23e9faSHans Rosenfeld 	xrip = cmd_sbp->xrip;
4077*8f23e9faSHans Rosenfeld 	if (!xrip) {
4078*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4079*8f23e9faSHans Rosenfeld 		    "Unable to find xri. did=0x%x", did);
4080*8f23e9faSHans Rosenfeld 
4081*8f23e9faSHans Rosenfeld 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4082*8f23e9faSHans Rosenfeld 		    IOERR_NO_XRI, 0);
4083*8f23e9faSHans Rosenfeld 		return (0xff);
4084*8f23e9faSHans Rosenfeld 	}
4085*8f23e9faSHans Rosenfeld 
4086*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_register_xri(port, cmd_sbp,
4087*8f23e9faSHans Rosenfeld 	    xrip->XRI, ndlp->nlp_DID) == NULL) {
4088*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4089*8f23e9faSHans Rosenfeld 		    "Unable to register xri. did=0x%x", did);
4090*8f23e9faSHans Rosenfeld 
4091*8f23e9faSHans Rosenfeld 		emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4092*8f23e9faSHans Rosenfeld 		    IOERR_NO_XRI, 0);
4093*8f23e9faSHans Rosenfeld 		return (0xff);
4094*8f23e9faSHans Rosenfeld 	}
4095*8f23e9faSHans Rosenfeld 	cmd_sbp->iotag = xrip->iotag;
4096*8f23e9faSHans Rosenfeld 	cmd_sbp->channel = cp;
4097*8f23e9faSHans Rosenfeld 
4098*8f23e9faSHans Rosenfeld 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
4099*8f23e9faSHans Rosenfeld 		timeout =
4100*8f23e9faSHans Rosenfeld 		    ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
4101*8f23e9faSHans Rosenfeld 	} else {
4102*8f23e9faSHans Rosenfeld 		timeout = 0x80000000;
4103*8f23e9faSHans Rosenfeld 	}
4104*8f23e9faSHans Rosenfeld 	cmd_sbp->ticks =
4105*8f23e9faSHans Rosenfeld 	    hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
4106*8f23e9faSHans Rosenfeld 
4107*8f23e9faSHans Rosenfeld 
4108*8f23e9faSHans Rosenfeld 	iocb->ULPCT = 0;
4109*8f23e9faSHans Rosenfeld 	if (fct_task->task_flags & TF_WRITE_DATA) {
4110*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
4111*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_TRECEIVE;		/* Word 11 */
4112*8f23e9faSHans Rosenfeld 
4113*8f23e9faSHans Rosenfeld 	} else { /* TF_READ_DATA */
4114*8f23e9faSHans Rosenfeld 
4115*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
4116*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_TSEND;			/* Word 11 */
4117*8f23e9faSHans Rosenfeld 
4118*8f23e9faSHans Rosenfeld 		if ((dbuf->db_data_size >=
4119*8f23e9faSHans Rosenfeld 		    fct_task->task_expected_xfer_length)) {
4120*8f23e9faSHans Rosenfeld 			/* enable auto-rsp AP feature */
4121*8f23e9faSHans Rosenfeld 			wqe->AR = 0x1;
4122*8f23e9faSHans Rosenfeld 			iocb->ULPCT = 0x1; /* for cmpl */
4123*8f23e9faSHans Rosenfeld 		}
4124*8f23e9faSHans Rosenfeld 	}
4125*8f23e9faSHans Rosenfeld 
4126*8f23e9faSHans Rosenfeld 	(void) emlxs_sli4_fct_bde_setup(port, cmd_sbp);
4127*8f23e9faSHans Rosenfeld 
4128*8f23e9faSHans Rosenfeld 	/*  Word  6 */
4129*8f23e9faSHans Rosenfeld 	wqe->ContextTag = ndlp->nlp_Rpi;
4130*8f23e9faSHans Rosenfeld 	wqe->XRITag = xrip->XRI;
4131*8f23e9faSHans Rosenfeld 
4132*8f23e9faSHans Rosenfeld 	/*  Word  7 */
4133*8f23e9faSHans Rosenfeld 	wqe->Command  = iocb->ULPCOMMAND;
4134*8f23e9faSHans Rosenfeld 	wqe->Class = cmd_sbp->class;
4135*8f23e9faSHans Rosenfeld 	wqe->ContextType = WQE_RPI_CONTEXT;
4136*8f23e9faSHans Rosenfeld 	wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4137*8f23e9faSHans Rosenfeld 	wqe->PU = 1;
4138*8f23e9faSHans Rosenfeld 
4139*8f23e9faSHans Rosenfeld 	/*  Word  8 */
4140*8f23e9faSHans Rosenfeld 	wqe->AbortTag = 0;
4141*8f23e9faSHans Rosenfeld 
4142*8f23e9faSHans Rosenfeld 	/*  Word  9 */
4143*8f23e9faSHans Rosenfeld 	wqe->RequestTag = xrip->iotag;
4144*8f23e9faSHans Rosenfeld 	wqe->OXId = (uint16_t)fct_cmd->cmd_oxid;
4145*8f23e9faSHans Rosenfeld 
4146*8f23e9faSHans Rosenfeld 	/*  Word  10 */
4147*8f23e9faSHans Rosenfeld 	if (xrip->flag & EMLXS_XRI_BUSY) {
4148*8f23e9faSHans Rosenfeld 		wqe->XC = 1;
4149*8f23e9faSHans Rosenfeld 	}
4150*8f23e9faSHans Rosenfeld 
4151*8f23e9faSHans Rosenfeld 	if (!(hba->sli.sli4.param.PHWQ)) {
4152*8f23e9faSHans Rosenfeld 		wqe->QOSd = 1;
4153*8f23e9faSHans Rosenfeld 		wqe->DBDE = 1; /* Data type for BDE 0 */
4154*8f23e9faSHans Rosenfeld 	}
4155*8f23e9faSHans Rosenfeld 
4156*8f23e9faSHans Rosenfeld 	/*  Word  11 */
4157*8f23e9faSHans Rosenfeld 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4158*8f23e9faSHans Rosenfeld 
4159*8f23e9faSHans Rosenfeld 	/*  Word  12 */
4160*8f23e9faSHans Rosenfeld 	wqe->CmdSpecific = dbuf->db_data_size;
4161*8f23e9faSHans Rosenfeld 
4162*8f23e9faSHans Rosenfeld 	return (IOERR_SUCCESS);
4163*8f23e9faSHans Rosenfeld 
4164*8f23e9faSHans Rosenfeld } /* emlxs_sli4_prep_fct_iocb() */
4165*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
4166*8f23e9faSHans Rosenfeld 
4167*8f23e9faSHans Rosenfeld 
4168*8f23e9faSHans Rosenfeld /*ARGSUSED*/
4169*8f23e9faSHans Rosenfeld extern uint32_t
4170*8f23e9faSHans Rosenfeld emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
4171*8f23e9faSHans Rosenfeld {
4172*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
4173*8f23e9faSHans Rosenfeld 	fc_packet_t *pkt;
4174*8f23e9faSHans Rosenfeld 	CHANNEL *cp;
4175*8f23e9faSHans Rosenfeld 	RPIobj_t *rpip;
4176*8f23e9faSHans Rosenfeld 	XRIobj_t *xrip;
4177*8f23e9faSHans Rosenfeld 	emlxs_wqe_t *wqe;
4178*8f23e9faSHans Rosenfeld 	IOCBQ *iocbq;
4179*8f23e9faSHans Rosenfeld 	IOCB *iocb;
4180*8f23e9faSHans Rosenfeld 	NODELIST *node;
4181*8f23e9faSHans Rosenfeld 	uint16_t iotag;
4182*8f23e9faSHans Rosenfeld 	uint32_t did;
4183*8f23e9faSHans Rosenfeld 	off_t offset;
4184*8f23e9faSHans Rosenfeld 
4185*8f23e9faSHans Rosenfeld 	pkt = PRIV2PKT(sbp);
4186*8f23e9faSHans Rosenfeld 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4187*8f23e9faSHans Rosenfeld 	cp = &hba->chan[channel];
4188*8f23e9faSHans Rosenfeld 
4189*8f23e9faSHans Rosenfeld 	iocbq = &sbp->iocbq;
4190*8f23e9faSHans Rosenfeld 	iocbq->channel = (void *) cp;
4191*8f23e9faSHans Rosenfeld 	iocbq->port = (void *) port;
4192*8f23e9faSHans Rosenfeld 
4193*8f23e9faSHans Rosenfeld 	wqe = &iocbq->wqe;
4194*8f23e9faSHans Rosenfeld 	iocb = &iocbq->iocb;
4195*8f23e9faSHans Rosenfeld 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
4196*8f23e9faSHans Rosenfeld 	bzero((void *)iocb, sizeof (IOCB));
4197*8f23e9faSHans Rosenfeld 
4198*8f23e9faSHans Rosenfeld 	/* Find target node object */
4199*8f23e9faSHans Rosenfeld 	node = (NODELIST *)iocbq->node;
4200*8f23e9faSHans Rosenfeld 	rpip = EMLXS_NODE_TO_RPI(port, node);
4201*8f23e9faSHans Rosenfeld 
4202*8f23e9faSHans Rosenfeld 	if (!rpip) {
4203*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4204*8f23e9faSHans Rosenfeld 		    "Unable to find rpi. did=0x%x", did);
4205*8f23e9faSHans Rosenfeld 
4206*8f23e9faSHans Rosenfeld 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4207*8f23e9faSHans Rosenfeld 		    IOERR_INVALID_RPI, 0);
4208*8f23e9faSHans Rosenfeld 		return (0xff);
4209*8f23e9faSHans Rosenfeld 	}
4210*8f23e9faSHans Rosenfeld 
4211*8f23e9faSHans Rosenfeld 	sbp->channel = cp;
4212*8f23e9faSHans Rosenfeld 	/* Next allocate an Exchange for this command */
4213*8f23e9faSHans Rosenfeld 	xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4214*8f23e9faSHans Rosenfeld 	    EMLXS_XRI_SOL_FCP_TYPE);
4215*8f23e9faSHans Rosenfeld 
4216*8f23e9faSHans Rosenfeld 	if (!xrip) {
4217*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4218*8f23e9faSHans Rosenfeld 		    "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
4219*8f23e9faSHans Rosenfeld 
4220*8f23e9faSHans Rosenfeld 		return (FC_TRAN_BUSY);
4221*8f23e9faSHans Rosenfeld 	}
4222*8f23e9faSHans Rosenfeld 	sbp->bmp = NULL;
4223*8f23e9faSHans Rosenfeld 	iotag = sbp->iotag;
4224*8f23e9faSHans Rosenfeld 
4225*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
4226*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4227*8f23e9faSHans Rosenfeld 	    "FCP: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4228*8f23e9faSHans Rosenfeld 	    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4229*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
4230*8f23e9faSHans Rosenfeld 
4231*8f23e9faSHans Rosenfeld 	/* Indicate this is a FCP cmd */
4232*8f23e9faSHans Rosenfeld 	iocbq->flag |= IOCB_FCP_CMD;
4233*8f23e9faSHans Rosenfeld 
4234*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_bde_setup(port, sbp)) {
4235*8f23e9faSHans Rosenfeld 		emlxs_sli4_free_xri(port, sbp, xrip, 1);
4236*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4237*8f23e9faSHans Rosenfeld 		    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4238*8f23e9faSHans Rosenfeld 
4239*8f23e9faSHans Rosenfeld 		return (FC_TRAN_BUSY);
4240*8f23e9faSHans Rosenfeld 	}
4241*8f23e9faSHans Rosenfeld 
4242*8f23e9faSHans Rosenfeld 	/* DEBUG */
4243*8f23e9faSHans Rosenfeld #ifdef DEBUG_FCP
4244*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4245*8f23e9faSHans Rosenfeld 	    "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
4246*8f23e9faSHans Rosenfeld 	    xrip->SGList.phys, pkt->pkt_datalen);
4247*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "FCP: SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
4248*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4249*8f23e9faSHans Rosenfeld 	    "FCP: CMD virt %p len %d:%d:%d",
4250*8f23e9faSHans Rosenfeld 	    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
4251*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
4252*8f23e9faSHans Rosenfeld #endif /* DEBUG_FCP */
4253*8f23e9faSHans Rosenfeld 
4254*8f23e9faSHans Rosenfeld 	offset = (off_t)((uint64_t)((unsigned long)
4255*8f23e9faSHans Rosenfeld 	    xrip->SGList.virt) -
4256*8f23e9faSHans Rosenfeld 	    (uint64_t)((unsigned long)
4257*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.slim2.virt));
4258*8f23e9faSHans Rosenfeld 
4259*8f23e9faSHans Rosenfeld 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4260*8f23e9faSHans Rosenfeld 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4261*8f23e9faSHans Rosenfeld 
4262*8f23e9faSHans Rosenfeld 	/* if device is FCP-2 device, set the following bit */
4263*8f23e9faSHans Rosenfeld 	/* that says to run the FC-TAPE protocol. */
4264*8f23e9faSHans Rosenfeld 	if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
4265*8f23e9faSHans Rosenfeld 		wqe->ERP = 1;
4266*8f23e9faSHans Rosenfeld 	}
4267*8f23e9faSHans Rosenfeld 
4268*8f23e9faSHans Rosenfeld 	if (pkt->pkt_datalen == 0) {
4269*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
4270*8f23e9faSHans Rosenfeld 		wqe->Command = CMD_FCP_ICMND64_CR;
4271*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4272*8f23e9faSHans Rosenfeld 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
4273*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
4274*8f23e9faSHans Rosenfeld 		wqe->Command = CMD_FCP_IREAD64_CR;
4275*8f23e9faSHans Rosenfeld 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4276*8f23e9faSHans Rosenfeld 		wqe->PU = PARM_XFER_CHECK;
4277*8f23e9faSHans Rosenfeld 	} else {
4278*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
4279*8f23e9faSHans Rosenfeld 		wqe->Command = CMD_FCP_IWRITE64_CR;
428082527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
428182527734SSukumar Swaminathan 	}
428282527734SSukumar Swaminathan 	wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
428382527734SSukumar Swaminathan 
4284*8f23e9faSHans Rosenfeld 	if (!(hba->sli.sli4.param.PHWQ)) {
4285*8f23e9faSHans Rosenfeld 		wqe->DBDE = 1; /* Data type for BDE 0 */
4286*8f23e9faSHans Rosenfeld 	}
4287a9800bebSGarrett D'Amore 	wqe->ContextTag = rpip->RPI;
428882527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
4289a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
429082527734SSukumar Swaminathan 	wqe->Timer =
429182527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
429282527734SSukumar Swaminathan 
429382527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
429482527734SSukumar Swaminathan 		wqe->CCPE = 1;
429582527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
429682527734SSukumar Swaminathan 	}
429782527734SSukumar Swaminathan 
429882527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
429982527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
430082527734SSukumar Swaminathan 		wqe->Class = CLASS2;
430182527734SSukumar Swaminathan 		break;
430282527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
430382527734SSukumar Swaminathan 	default:
430482527734SSukumar Swaminathan 		wqe->Class = CLASS3;
430582527734SSukumar Swaminathan 		break;
430682527734SSukumar Swaminathan 	}
430782527734SSukumar Swaminathan 	sbp->class = wqe->Class;
430882527734SSukumar Swaminathan 	wqe->RequestTag = iotag;
4309*8f23e9faSHans Rosenfeld 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4310*8f23e9faSHans Rosenfeld 
431182527734SSukumar Swaminathan 	return (FC_SUCCESS);
431282527734SSukumar Swaminathan } /* emlxs_sli4_prep_fcp_iocb() */
431382527734SSukumar Swaminathan 
431482527734SSukumar Swaminathan 
431582527734SSukumar Swaminathan /*ARGSUSED*/
431682527734SSukumar Swaminathan static uint32_t
431782527734SSukumar Swaminathan emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
431882527734SSukumar Swaminathan {
431982527734SSukumar Swaminathan 	return (FC_TRAN_BUSY);
432082527734SSukumar Swaminathan 
432182527734SSukumar Swaminathan } /* emlxs_sli4_prep_ip_iocb() */
432282527734SSukumar Swaminathan 
432382527734SSukumar Swaminathan 
432482527734SSukumar Swaminathan /*ARGSUSED*/
432582527734SSukumar Swaminathan static uint32_t
432682527734SSukumar Swaminathan emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
432782527734SSukumar Swaminathan {
432882527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
432982527734SSukumar Swaminathan 	fc_packet_t *pkt;
433082527734SSukumar Swaminathan 	IOCBQ *iocbq;
433182527734SSukumar Swaminathan 	IOCB *iocb;
433282527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
4333a9800bebSGarrett D'Amore 	FCFIobj_t *fcfp;
4334*8f23e9faSHans Rosenfeld 	RPIobj_t *reserved_rpip = NULL;
4335a9800bebSGarrett D'Amore 	RPIobj_t *rpip = NULL;
4336a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
433782527734SSukumar Swaminathan 	CHANNEL *cp;
433882527734SSukumar Swaminathan 	uint32_t did;
433982527734SSukumar Swaminathan 	uint32_t cmd;
434082527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
434182527734SSukumar Swaminathan 	ULP_SGE64 *sge;
434282527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
434382527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_resp;
434482527734SSukumar Swaminathan 	emlxs_node_t *node;
4345b3660a96SSukumar Swaminathan 	off_t offset;
434682527734SSukumar Swaminathan 
434782527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
434882527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
434982527734SSukumar Swaminathan 
435082527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
435182527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
435282527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
435382527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
435482527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
435582527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_els];
435682527734SSukumar Swaminathan 
435782527734SSukumar Swaminathan 	/* Initalize iocbq */
435882527734SSukumar Swaminathan 	iocbq->port = (void *) port;
435982527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
436082527734SSukumar Swaminathan 
436182527734SSukumar Swaminathan 	sbp->channel = cp;
436282527734SSukumar Swaminathan 	sbp->bmp = NULL;
436382527734SSukumar Swaminathan 
436482527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
436582527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
436682527734SSukumar Swaminathan 	cp_resp = pkt->pkt_resp_cookie;
436782527734SSukumar Swaminathan #else
436882527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
436982527734SSukumar Swaminathan 	cp_resp = &pkt->pkt_resp_cookie;
437082527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
437182527734SSukumar Swaminathan 
437282527734SSukumar Swaminathan 	/* CMD payload */
437382527734SSukumar Swaminathan 	sge = &stage_sge;
437482527734SSukumar Swaminathan 	sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
437582527734SSukumar Swaminathan 	sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
437682527734SSukumar Swaminathan 	sge->length = pkt->pkt_cmdlen;
437782527734SSukumar Swaminathan 	sge->offset = 0;
4378*8f23e9faSHans Rosenfeld 	sge->type = 0;
4379*8f23e9faSHans Rosenfeld 
4380*8f23e9faSHans Rosenfeld 	cmd = *((uint32_t *)pkt->pkt_cmd);
4381*8f23e9faSHans Rosenfeld 	cmd &= ELS_CMD_MASK;
438282527734SSukumar Swaminathan 
438382527734SSukumar Swaminathan 	/* Initalize iocb */
438482527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
438582527734SSukumar Swaminathan 		/* ELS Response */
438682527734SSukumar Swaminathan 
4387*8f23e9faSHans Rosenfeld 		sbp->xrip = 0;
4388*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_register_xri(port, sbp,
4389*8f23e9faSHans Rosenfeld 		    pkt->pkt_cmd_fhdr.rx_id, did);
439082527734SSukumar Swaminathan 
4391a9800bebSGarrett D'Amore 		if (!xrip) {
439282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
439382527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
439482527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
439582527734SSukumar Swaminathan 
439682527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
439782527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
439882527734SSukumar Swaminathan 			return (0xff);
439982527734SSukumar Swaminathan 		}
440082527734SSukumar Swaminathan 
4401a9800bebSGarrett D'Amore 		rpip = xrip->rpip;
440282527734SSukumar Swaminathan 
4403a9800bebSGarrett D'Amore 		if (!rpip) {
440482527734SSukumar Swaminathan 			/* This means that we had a node registered */
440582527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
440682527734SSukumar Swaminathan 			/* has since been unregistered. */
440782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
440882527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
440982527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
441082527734SSukumar Swaminathan 
441182527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
441282527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
441382527734SSukumar Swaminathan 			return (0xff);
441482527734SSukumar Swaminathan 		}
441582527734SSukumar Swaminathan 
441682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4417*8f23e9faSHans Rosenfeld 		    "ELS: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4418a9800bebSGarrett D'Amore 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
441982527734SSukumar Swaminathan 
4420*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
442182527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_ELS_RSP64_CX;
442282527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
4423*8f23e9faSHans Rosenfeld 		if (!(hba->sli.sli4.param.PHWQ)) {
4424*8f23e9faSHans Rosenfeld 			wqe->DBDE = 1; /* Data type for BDE 0 */
4425*8f23e9faSHans Rosenfeld 		}
442682527734SSukumar Swaminathan 
442782527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
442882527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
442982527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
4430*8f23e9faSHans Rosenfeld 		wqe->un.ElsCmd.PayloadLength = pkt->pkt_cmdlen;
443182527734SSukumar Swaminathan 
443282527734SSukumar Swaminathan 		wqe->un.ElsRsp.RemoteId = did;
443382527734SSukumar Swaminathan 		wqe->PU = 0x3;
4434*8f23e9faSHans Rosenfeld 		wqe->OXId = xrip->rx_id;
443582527734SSukumar Swaminathan 
443682527734SSukumar Swaminathan 		sge->last = 1;
443782527734SSukumar Swaminathan 		/* Now sge is fully staged */
443882527734SSukumar Swaminathan 
4439a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
444082527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
444182527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
444282527734SSukumar Swaminathan 
4443*8f23e9faSHans Rosenfeld 		if (rpip->RPI == FABRIC_RPI) {
4444*8f23e9faSHans Rosenfeld 			wqe->ContextTag = port->vpip->VPI;
4445*8f23e9faSHans Rosenfeld 			wqe->ContextType = WQE_VPI_CONTEXT;
4446*8f23e9faSHans Rosenfeld 		} else {
4447*8f23e9faSHans Rosenfeld 			wqe->ContextTag = rpip->RPI;
4448*8f23e9faSHans Rosenfeld 			wqe->ContextType = WQE_RPI_CONTEXT;
4449*8f23e9faSHans Rosenfeld 		}
4450*8f23e9faSHans Rosenfeld 
4451*8f23e9faSHans Rosenfeld 		if ((cmd == ELS_CMD_ACC) && (sbp->ucmd == ELS_CMD_FLOGI)) {
4452*8f23e9faSHans Rosenfeld 			wqe->un.ElsCmd.SP = 1;
4453*8f23e9faSHans Rosenfeld 			wqe->un.ElsCmd.LocalId = 0xFFFFFE;
4454*8f23e9faSHans Rosenfeld 		}
445582527734SSukumar Swaminathan 
445682527734SSukumar Swaminathan 	} else {
445782527734SSukumar Swaminathan 		/* ELS Request */
445882527734SSukumar Swaminathan 
4459*8f23e9faSHans Rosenfeld 		fcfp = port->vpip->vfip->fcfp;
446082527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
4461a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
446282527734SSukumar Swaminathan 
4463a9800bebSGarrett D'Amore 		if (!rpip) {
4464*8f23e9faSHans Rosenfeld 			/* Use the fabric rpi */
4465*8f23e9faSHans Rosenfeld 			rpip = port->vpip->fabric_rpip;
446682527734SSukumar Swaminathan 		}
446782527734SSukumar Swaminathan 
446882527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
4469*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4470*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_SOL_ELS_TYPE);
447182527734SSukumar Swaminathan 
4472a9800bebSGarrett D'Amore 		if (!xrip) {
447382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4474a9800bebSGarrett D'Amore 			    "Adapter Busy. Unable to allocate exchange. "
447582527734SSukumar Swaminathan 			    "did=0x%x", did);
447682527734SSukumar Swaminathan 
447782527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
447882527734SSukumar Swaminathan 		}
447982527734SSukumar Swaminathan 
448082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4481*8f23e9faSHans Rosenfeld 		    "ELS: Prep xri=%d iotag=%d rpi=%d",
4482*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->iotag, rpip->RPI);
448382527734SSukumar Swaminathan 
4484*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
448582527734SSukumar Swaminathan 		wqe->Command = CMD_ELS_REQUEST64_CR;
448682527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_ELS;
4487*8f23e9faSHans Rosenfeld 		if (!(hba->sli.sli4.param.PHWQ)) {
4488*8f23e9faSHans Rosenfeld 			wqe->DBDE = 1; /* Data type for BDE 0 */
4489*8f23e9faSHans Rosenfeld 		}
449082527734SSukumar Swaminathan 
449182527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
449282527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
449382527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
449482527734SSukumar Swaminathan 
4495*8f23e9faSHans Rosenfeld 		wqe->un.ElsCmd.RemoteId = did;
4496*8f23e9faSHans Rosenfeld 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4497*8f23e9faSHans Rosenfeld 
449882527734SSukumar Swaminathan 		/* setup for rsp */
449982527734SSukumar Swaminathan 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
450082527734SSukumar Swaminathan 		iocb->ULPPU = 1;	/* Wd4 is relative offset */
450182527734SSukumar Swaminathan 
450282527734SSukumar Swaminathan 		sge->last = 0;
450382527734SSukumar Swaminathan 
4504a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
450582527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
450682527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
450782527734SSukumar Swaminathan 
450882527734SSukumar Swaminathan 		wqe->un.ElsCmd.PayloadLength =
450982527734SSukumar Swaminathan 		    pkt->pkt_cmdlen; /* Byte offset of rsp data */
451082527734SSukumar Swaminathan 
451182527734SSukumar Swaminathan 		/* RSP payload */
451282527734SSukumar Swaminathan 		sge = &stage_sge;
451382527734SSukumar Swaminathan 		sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
451482527734SSukumar Swaminathan 		sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
451582527734SSukumar Swaminathan 		sge->length = pkt->pkt_rsplen;
4516b3660a96SSukumar Swaminathan 		sge->offset = 0;
451782527734SSukumar Swaminathan 		sge->last = 1;
451882527734SSukumar Swaminathan 		/* Now sge is fully staged */
451982527734SSukumar Swaminathan 
4520a9800bebSGarrett D'Amore 		sge = xrip->SGList.virt;
452182527734SSukumar Swaminathan 		sge++;
452282527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
452382527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
452482527734SSukumar Swaminathan #ifdef DEBUG_ELS
452582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4526*8f23e9faSHans Rosenfeld 		    "ELS: SGLaddr virt %p phys %p",
4527a9800bebSGarrett D'Amore 		    xrip->SGList.virt, xrip->SGList.phys);
452882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4529*8f23e9faSHans Rosenfeld 		    "ELS: PAYLOAD virt %p phys %p",
453082527734SSukumar Swaminathan 		    pkt->pkt_cmd, cp_cmd->dmac_laddress);
4531*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "ELS: SGL", (uint32_t *)xrip->SGList.virt,
4532a9800bebSGarrett D'Amore 		    12, 0);
4533*8f23e9faSHans Rosenfeld #endif /* DEBUG_ELS */
453482527734SSukumar Swaminathan 
453582527734SSukumar Swaminathan 		switch (cmd) {
453682527734SSukumar Swaminathan 		case ELS_CMD_FLOGI:
453782527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
4538*8f23e9faSHans Rosenfeld 
4539*8f23e9faSHans Rosenfeld 			if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
4540*8f23e9faSHans Rosenfeld 			    SLI_INTF_IF_TYPE_0) {
4541*8f23e9faSHans Rosenfeld 				wqe->ContextTag = fcfp->FCFI;
4542*8f23e9faSHans Rosenfeld 				wqe->ContextType = WQE_FCFI_CONTEXT;
4543*8f23e9faSHans Rosenfeld 			} else {
4544*8f23e9faSHans Rosenfeld 				wqe->ContextTag = port->vpip->VPI;
4545*8f23e9faSHans Rosenfeld 				wqe->ContextType = WQE_VPI_CONTEXT;
4546*8f23e9faSHans Rosenfeld 			}
4547*8f23e9faSHans Rosenfeld 
454882527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
454982527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
455082527734SSukumar Swaminathan 			}
4551*8f23e9faSHans Rosenfeld 
4552*8f23e9faSHans Rosenfeld 			if (hba->topology == TOPOLOGY_LOOP) {
4553*8f23e9faSHans Rosenfeld 				wqe->un.ElsCmd.LocalId = port->did;
4554*8f23e9faSHans Rosenfeld 			}
4555*8f23e9faSHans Rosenfeld 
4556*8f23e9faSHans Rosenfeld 			wqe->ELSId = WQE_ELSID_FLOGI;
455782527734SSukumar Swaminathan 			break;
455882527734SSukumar Swaminathan 		case ELS_CMD_FDISC:
455982527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
4560*8f23e9faSHans Rosenfeld 			wqe->ContextTag = port->vpip->VPI;
456182527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
4562*8f23e9faSHans Rosenfeld 
456382527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
456482527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
456582527734SSukumar Swaminathan 			}
4566*8f23e9faSHans Rosenfeld 
4567*8f23e9faSHans Rosenfeld 			wqe->ELSId = WQE_ELSID_FDISC;
456882527734SSukumar Swaminathan 			break;
456982527734SSukumar Swaminathan 		case ELS_CMD_LOGO:
4570*8f23e9faSHans Rosenfeld 			if ((did == FABRIC_DID) &&
4571*8f23e9faSHans Rosenfeld 			    (hba->flag & FC_FIP_SUPPORTED)) {
4572*8f23e9faSHans Rosenfeld 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
4573*8f23e9faSHans Rosenfeld 			}
4574*8f23e9faSHans Rosenfeld 
4575*8f23e9faSHans Rosenfeld 			wqe->ContextTag = port->vpip->VPI;
4576*8f23e9faSHans Rosenfeld 			wqe->ContextType = WQE_VPI_CONTEXT;
4577*8f23e9faSHans Rosenfeld 			wqe->ELSId = WQE_ELSID_LOGO;
4578*8f23e9faSHans Rosenfeld 			break;
4579*8f23e9faSHans Rosenfeld 		case ELS_CMD_PLOGI:
4580*8f23e9faSHans Rosenfeld 			if (rpip->RPI == FABRIC_RPI) {
4581*8f23e9faSHans Rosenfeld 				if (hba->flag & FC_PT_TO_PT) {
4582*8f23e9faSHans Rosenfeld 					wqe->un.ElsCmd.SP = 1;
4583*8f23e9faSHans Rosenfeld 					wqe->un.ElsCmd.LocalId = port->did;
4584a9800bebSGarrett D'Amore 				}
4585*8f23e9faSHans Rosenfeld 
4586*8f23e9faSHans Rosenfeld 				wqe->ContextTag = port->vpip->VPI;
4587a9800bebSGarrett D'Amore 				wqe->ContextType = WQE_VPI_CONTEXT;
4588*8f23e9faSHans Rosenfeld 			} else {
4589*8f23e9faSHans Rosenfeld 				wqe->ContextTag = rpip->RPI;
4590*8f23e9faSHans Rosenfeld 				wqe->ContextType = WQE_RPI_CONTEXT;
459182527734SSukumar Swaminathan 			}
459282527734SSukumar Swaminathan 
4593*8f23e9faSHans Rosenfeld 			wqe->ELSId = WQE_ELSID_PLOGI;
4594*8f23e9faSHans Rosenfeld 			break;
459582527734SSukumar Swaminathan 		default:
4596*8f23e9faSHans Rosenfeld 			if (rpip->RPI == FABRIC_RPI) {
4597*8f23e9faSHans Rosenfeld 				wqe->ContextTag = port->vpip->VPI;
4598*8f23e9faSHans Rosenfeld 				wqe->ContextType = WQE_VPI_CONTEXT;
4599*8f23e9faSHans Rosenfeld 			} else {
4600*8f23e9faSHans Rosenfeld 				wqe->ContextTag = rpip->RPI;
4601*8f23e9faSHans Rosenfeld 				wqe->ContextType = WQE_RPI_CONTEXT;
4602*8f23e9faSHans Rosenfeld 			}
4603*8f23e9faSHans Rosenfeld 
4604*8f23e9faSHans Rosenfeld 			wqe->ELSId = WQE_ELSID_CMD;
460582527734SSukumar Swaminathan 			break;
460682527734SSukumar Swaminathan 		}
460782527734SSukumar Swaminathan 
4608*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
4609*8f23e9faSHans Rosenfeld 		/* This allows fct to abort the request */
4610*8f23e9faSHans Rosenfeld 		if (sbp->fct_cmd) {
4611*8f23e9faSHans Rosenfeld 			sbp->fct_cmd->cmd_oxid = xrip->XRI;
4612*8f23e9faSHans Rosenfeld 			sbp->fct_cmd->cmd_rxid = 0xFFFF;
4613*8f23e9faSHans Rosenfeld 		}
4614*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
4615*8f23e9faSHans Rosenfeld 	}
4616*8f23e9faSHans Rosenfeld 
4617*8f23e9faSHans Rosenfeld 	if (wqe->ContextType == WQE_VPI_CONTEXT) {
4618*8f23e9faSHans Rosenfeld 		reserved_rpip = emlxs_rpi_reserve_notify(port, did, xrip);
4619*8f23e9faSHans Rosenfeld 
4620*8f23e9faSHans Rosenfeld 		if (!reserved_rpip) {
4621*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4622*8f23e9faSHans Rosenfeld 			    "Unable to alloc reserved RPI. rxid=%x. Rejecting.",
4623*8f23e9faSHans Rosenfeld 			    pkt->pkt_cmd_fhdr.rx_id);
4624*8f23e9faSHans Rosenfeld 
4625*8f23e9faSHans Rosenfeld 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4626*8f23e9faSHans Rosenfeld 			    IOERR_INVALID_RPI, 0);
4627*8f23e9faSHans Rosenfeld 			return (0xff);
4628*8f23e9faSHans Rosenfeld 		}
4629*8f23e9faSHans Rosenfeld 
4630*8f23e9faSHans Rosenfeld 		/* Store the reserved rpi */
4631*8f23e9faSHans Rosenfeld 		if (wqe->Command == CMD_ELS_REQUEST64_CR) {
4632*8f23e9faSHans Rosenfeld 			wqe->OXId = reserved_rpip->RPI;
4633*8f23e9faSHans Rosenfeld 		} else {
4634*8f23e9faSHans Rosenfeld 			wqe->CmdSpecific = reserved_rpip->RPI;
4635*8f23e9faSHans Rosenfeld 		}
4636*8f23e9faSHans Rosenfeld 	}
4637*8f23e9faSHans Rosenfeld 
4638*8f23e9faSHans Rosenfeld 	offset = (off_t)((uint64_t)((unsigned long)
4639*8f23e9faSHans Rosenfeld 	    xrip->SGList.virt) -
4640*8f23e9faSHans Rosenfeld 	    (uint64_t)((unsigned long)
4641b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
4642b3660a96SSukumar Swaminathan 
4643a9800bebSGarrett D'Amore 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4644a9800bebSGarrett D'Amore 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
464582527734SSukumar Swaminathan 
464682527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
464782527734SSukumar Swaminathan 		wqe->CCPE = 1;
464882527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
464982527734SSukumar Swaminathan 	}
465082527734SSukumar Swaminathan 
465182527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
465282527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
465382527734SSukumar Swaminathan 		wqe->Class = CLASS2;
465482527734SSukumar Swaminathan 		break;
465582527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
465682527734SSukumar Swaminathan 	default:
465782527734SSukumar Swaminathan 		wqe->Class = CLASS3;
465882527734SSukumar Swaminathan 		break;
465982527734SSukumar Swaminathan 	}
466082527734SSukumar Swaminathan 	sbp->class = wqe->Class;
4661a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
4662a9800bebSGarrett D'Amore 	wqe->RequestTag = xrip->iotag;
4663*8f23e9faSHans Rosenfeld 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
466482527734SSukumar Swaminathan 	return (FC_SUCCESS);
466582527734SSukumar Swaminathan 
466682527734SSukumar Swaminathan } /* emlxs_sli4_prep_els_iocb() */
466782527734SSukumar Swaminathan 
466882527734SSukumar Swaminathan 
466982527734SSukumar Swaminathan /*ARGSUSED*/
467082527734SSukumar Swaminathan static uint32_t
467182527734SSukumar Swaminathan emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
467282527734SSukumar Swaminathan {
467382527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
467482527734SSukumar Swaminathan 	fc_packet_t *pkt;
467582527734SSukumar Swaminathan 	IOCBQ *iocbq;
467682527734SSukumar Swaminathan 	IOCB *iocb;
467782527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
467882527734SSukumar Swaminathan 	NODELIST *node = NULL;
467982527734SSukumar Swaminathan 	CHANNEL *cp;
4680a9800bebSGarrett D'Amore 	RPIobj_t *rpip;
4681a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
468282527734SSukumar Swaminathan 	uint32_t did;
4683b3660a96SSukumar Swaminathan 	off_t offset;
468482527734SSukumar Swaminathan 
468582527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
468682527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
468782527734SSukumar Swaminathan 
468882527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
468982527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
469082527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
469182527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
469282527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
469382527734SSukumar Swaminathan 
469482527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_ct];
469582527734SSukumar Swaminathan 
469682527734SSukumar Swaminathan 	iocbq->port = (void *) port;
469782527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
469882527734SSukumar Swaminathan 
469982527734SSukumar Swaminathan 	sbp->bmp = NULL;
470082527734SSukumar Swaminathan 	sbp->channel = cp;
470182527734SSukumar Swaminathan 
470282527734SSukumar Swaminathan 	/* Initalize wqe */
470382527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
470482527734SSukumar Swaminathan 		/* CT Response */
470582527734SSukumar Swaminathan 
4706*8f23e9faSHans Rosenfeld 		sbp->xrip = 0;
4707*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_register_xri(port, sbp,
4708*8f23e9faSHans Rosenfeld 		    pkt->pkt_cmd_fhdr.rx_id, did);
470982527734SSukumar Swaminathan 
4710a9800bebSGarrett D'Amore 		if (!xrip) {
471182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
471282527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
471382527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
471482527734SSukumar Swaminathan 
471582527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
471682527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
471782527734SSukumar Swaminathan 			return (0xff);
471882527734SSukumar Swaminathan 		}
471982527734SSukumar Swaminathan 
4720a9800bebSGarrett D'Amore 		rpip = xrip->rpip;
472182527734SSukumar Swaminathan 
4722a9800bebSGarrett D'Amore 		if (!rpip) {
472382527734SSukumar Swaminathan 			/* This means that we had a node registered */
472482527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
472582527734SSukumar Swaminathan 			/* has since been unregistered. */
472682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
472782527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
472882527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
472982527734SSukumar Swaminathan 
473082527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
473182527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
473282527734SSukumar Swaminathan 			return (0xff);
473382527734SSukumar Swaminathan 		}
473482527734SSukumar Swaminathan 
473582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4736*8f23e9faSHans Rosenfeld 		    "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4737*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
473882527734SSukumar Swaminathan 
473982527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
474082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
474182527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
474282527734SSukumar Swaminathan 
474382527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
474482527734SSukumar Swaminathan 		}
474582527734SSukumar Swaminathan 
4746*8f23e9faSHans Rosenfeld 		if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) {
4747*8f23e9faSHans Rosenfeld 			wqe->un.XmitSeq.Rsvd0 = 0; /* Word3 now reserved */
4748*8f23e9faSHans Rosenfeld 		}
4749*8f23e9faSHans Rosenfeld 
4750*8f23e9faSHans Rosenfeld 		if (!(hba->sli.sli4.param.PHWQ)) {
4751*8f23e9faSHans Rosenfeld 			wqe->DBDE = 1; /* Data type for BDE 0 */
4752*8f23e9faSHans Rosenfeld 		}
4753*8f23e9faSHans Rosenfeld 
4754*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CR;
475582527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
475682527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_SEQUENCE64_CR;
4757*8f23e9faSHans Rosenfeld 		wqe->LenLoc = 2;
4758*8f23e9faSHans Rosenfeld 
4759*8f23e9faSHans Rosenfeld 		if (((SLI_CT_REQUEST *) pkt->pkt_cmd)->CommandResponse.bits.
4760*8f23e9faSHans Rosenfeld 		    CmdRsp == (LE_SWAP16(SLI_CT_LOOPBACK))) {
4761*8f23e9faSHans Rosenfeld 			wqe->un.XmitSeq.xo = 1;
4762*8f23e9faSHans Rosenfeld 		} else {
4763*8f23e9faSHans Rosenfeld 			wqe->un.XmitSeq.xo = 0;
4764*8f23e9faSHans Rosenfeld 		}
476582527734SSukumar Swaminathan 
476682527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
476782527734SSukumar Swaminathan 			wqe->un.XmitSeq.ls = 1;
476882527734SSukumar Swaminathan 		}
476982527734SSukumar Swaminathan 
477082527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
477182527734SSukumar Swaminathan 			wqe->un.XmitSeq.si = 1;
477282527734SSukumar Swaminathan 		}
477382527734SSukumar Swaminathan 
477482527734SSukumar Swaminathan 		wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
477582527734SSukumar Swaminathan 		wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
477682527734SSukumar Swaminathan 		wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
4777a9800bebSGarrett D'Amore 		wqe->OXId = xrip->rx_id;
477862379b58SSukumar Swaminathan 		wqe->XC = 0; /* xri_tag is a new exchange */
4779*8f23e9faSHans Rosenfeld 		wqe->CmdSpecific = wqe->un.GenReq.Payload.tus.f.bdeSize;
478082527734SSukumar Swaminathan 
478182527734SSukumar Swaminathan 	} else {
478282527734SSukumar Swaminathan 		/* CT Request */
478382527734SSukumar Swaminathan 
478482527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
4785a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
478682527734SSukumar Swaminathan 
4787a9800bebSGarrett D'Amore 		if (!rpip) {
478882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4789*8f23e9faSHans Rosenfeld 			    "Unable to find rpi. did=0x%x rpi=%d",
4790a9800bebSGarrett D'Amore 			    did, node->nlp_Rpi);
479182527734SSukumar Swaminathan 
479282527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
479382527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
479482527734SSukumar Swaminathan 			return (0xff);
479582527734SSukumar Swaminathan 		}
479682527734SSukumar Swaminathan 
479782527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
4798*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4799*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_SOL_CT_TYPE);
480082527734SSukumar Swaminathan 
4801a9800bebSGarrett D'Amore 		if (!xrip) {
480282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4803a9800bebSGarrett D'Amore 			    "Adapter Busy. Unable to allocate exchange. "
480482527734SSukumar Swaminathan 			    "did=0x%x", did);
480582527734SSukumar Swaminathan 
480682527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
480782527734SSukumar Swaminathan 		}
480882527734SSukumar Swaminathan 
480982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4810*8f23e9faSHans Rosenfeld 		    "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4811*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
481282527734SSukumar Swaminathan 
481382527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
481482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
481582527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
481682527734SSukumar Swaminathan 
4817*8f23e9faSHans Rosenfeld 			emlxs_sli4_free_xri(port, sbp, xrip, 1);
481882527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
481982527734SSukumar Swaminathan 		}
482082527734SSukumar Swaminathan 
4821*8f23e9faSHans Rosenfeld 		if (!(hba->sli.sli4.param.PHWQ)) {
4822*8f23e9faSHans Rosenfeld 			wqe->DBDE = 1; /* Data type for BDE 0 */
4823*8f23e9faSHans Rosenfeld 		}
4824*8f23e9faSHans Rosenfeld 
4825*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR;
482682527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
482782527734SSukumar Swaminathan 		wqe->Command = CMD_GEN_REQUEST64_CR;
482882527734SSukumar Swaminathan 		wqe->un.GenReq.la = 1;
482982527734SSukumar Swaminathan 		wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
483082527734SSukumar Swaminathan 		wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
483182527734SSukumar Swaminathan 		wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
483282527734SSukumar Swaminathan 
483382527734SSukumar Swaminathan #ifdef DEBUG_CT
483482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4835*8f23e9faSHans Rosenfeld 		    "CT: SGLaddr virt %p phys %p", xrip->SGList.virt,
4836a9800bebSGarrett D'Amore 		    xrip->SGList.phys);
4837*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList.virt,
4838a9800bebSGarrett D'Amore 		    12, 0);
483982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4840*8f23e9faSHans Rosenfeld 		    "CT: CMD virt %p len %d:%d",
484182527734SSukumar Swaminathan 		    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
4842*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd,
4843*8f23e9faSHans Rosenfeld 		    20, 0);
484482527734SSukumar Swaminathan #endif /* DEBUG_CT */
4845*8f23e9faSHans Rosenfeld 
4846*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
4847*8f23e9faSHans Rosenfeld 		/* This allows fct to abort the request */
4848*8f23e9faSHans Rosenfeld 		if (sbp->fct_cmd) {
4849*8f23e9faSHans Rosenfeld 			sbp->fct_cmd->cmd_oxid = xrip->XRI;
4850*8f23e9faSHans Rosenfeld 			sbp->fct_cmd->cmd_rxid = 0xFFFF;
4851*8f23e9faSHans Rosenfeld 		}
4852*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
485382527734SSukumar Swaminathan 	}
485482527734SSukumar Swaminathan 
485582527734SSukumar Swaminathan 	/* Setup for rsp */
485682527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
485782527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
485882527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
485982527734SSukumar Swaminathan 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
486082527734SSukumar Swaminathan 
4861b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
4862a9800bebSGarrett D'Amore 	    xrip->SGList.virt) -
4863b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
4864b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
4865b3660a96SSukumar Swaminathan 
4866a9800bebSGarrett D'Amore 	EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4867a9800bebSGarrett D'Amore 	    xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
486882527734SSukumar Swaminathan 
4869a9800bebSGarrett D'Amore 	wqe->ContextTag = rpip->RPI;
487082527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
4871a9800bebSGarrett D'Amore 	wqe->XRITag = xrip->XRI;
4872*8f23e9faSHans Rosenfeld 	wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
487382527734SSukumar Swaminathan 
487482527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
487582527734SSukumar Swaminathan 		wqe->CCPE = 1;
487682527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
487782527734SSukumar Swaminathan 	}
487882527734SSukumar Swaminathan 
487982527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
488082527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
488182527734SSukumar Swaminathan 		wqe->Class = CLASS2;
488282527734SSukumar Swaminathan 		break;
488382527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
488482527734SSukumar Swaminathan 	default:
488582527734SSukumar Swaminathan 		wqe->Class = CLASS3;
488682527734SSukumar Swaminathan 		break;
488782527734SSukumar Swaminathan 	}
488882527734SSukumar Swaminathan 	sbp->class = wqe->Class;
4889a9800bebSGarrett D'Amore 	wqe->RequestTag = xrip->iotag;
4890*8f23e9faSHans Rosenfeld 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
489182527734SSukumar Swaminathan 	return (FC_SUCCESS);
489282527734SSukumar Swaminathan 
489382527734SSukumar Swaminathan } /* emlxs_sli4_prep_ct_iocb() */
489482527734SSukumar Swaminathan 
489582527734SSukumar Swaminathan 
489682527734SSukumar Swaminathan /*ARGSUSED*/
489782527734SSukumar Swaminathan static int
4898a9800bebSGarrett D'Amore emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
489982527734SSukumar Swaminathan {
490082527734SSukumar Swaminathan 	uint32_t *ptr;
490182527734SSukumar Swaminathan 	EQE_u eqe;
490282527734SSukumar Swaminathan 	int rc = 0;
4903b3660a96SSukumar Swaminathan 	off_t offset;
490482527734SSukumar Swaminathan 
4905*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_PORT_LOCK);
4906*8f23e9faSHans Rosenfeld 
490782527734SSukumar Swaminathan 	ptr = eq->addr.virt;
490882527734SSukumar Swaminathan 	ptr += eq->host_index;
490982527734SSukumar Swaminathan 
4910b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
4911b3660a96SSukumar Swaminathan 	    eq->addr.virt) -
4912b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
4913b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
4914b3660a96SSukumar Swaminathan 
4915b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
491682527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
491782527734SSukumar Swaminathan 
4918a9800bebSGarrett D'Amore 	eqe.word = *ptr;
4919a9800bebSGarrett D'Amore 	eqe.word = BE_SWAP32(eqe.word);
492082527734SSukumar Swaminathan 
4921a9800bebSGarrett D'Amore 	if (eqe.word & EQE_VALID) {
4922a9800bebSGarrett D'Amore 		rc = 1;
492382527734SSukumar Swaminathan 	}
492482527734SSukumar Swaminathan 
492582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
492682527734SSukumar Swaminathan 
492782527734SSukumar Swaminathan 	return (rc);
492882527734SSukumar Swaminathan 
4929a9800bebSGarrett D'Amore } /* emlxs_sli4_read_eq */
493082527734SSukumar Swaminathan 
493182527734SSukumar Swaminathan 
493282527734SSukumar Swaminathan static void
4933*8f23e9faSHans Rosenfeld emlxs_sli4_poll_intr(emlxs_hba_t *hba)
493482527734SSukumar Swaminathan {
493582527734SSukumar Swaminathan 	int rc = 0;
493682527734SSukumar Swaminathan 	int i;
493782527734SSukumar Swaminathan 	char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
493882527734SSukumar Swaminathan 
4939*8f23e9faSHans Rosenfeld 	/* Check attention bits once and process if required */
494082527734SSukumar Swaminathan 
4941*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->intr_count; i++) {
4942*8f23e9faSHans Rosenfeld 		rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[i]);
4943*8f23e9faSHans Rosenfeld 		if (rc == 1) {
4944*8f23e9faSHans Rosenfeld 			break;
494582527734SSukumar Swaminathan 		}
494682527734SSukumar Swaminathan 	}
494782527734SSukumar Swaminathan 
4948*8f23e9faSHans Rosenfeld 	if (rc != 1) {
4949*8f23e9faSHans Rosenfeld 		return;
4950*8f23e9faSHans Rosenfeld 	}
4951*8f23e9faSHans Rosenfeld 
4952*8f23e9faSHans Rosenfeld 	(void) emlxs_sli4_msi_intr((char *)hba,
4953*8f23e9faSHans Rosenfeld 	    (char *)(unsigned long)arg[i]);
495482527734SSukumar Swaminathan 
495582527734SSukumar Swaminathan 	return;
495682527734SSukumar Swaminathan 
495782527734SSukumar Swaminathan } /* emlxs_sli4_poll_intr() */
495882527734SSukumar Swaminathan 
495982527734SSukumar Swaminathan 
496082527734SSukumar Swaminathan /*ARGSUSED*/
496182527734SSukumar Swaminathan static void
496282527734SSukumar Swaminathan emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
496382527734SSukumar Swaminathan {
496482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4965*8f23e9faSHans Rosenfeld 	uint8_t status;
496682527734SSukumar Swaminathan 
4967a9800bebSGarrett D'Amore 	/* Save the event tag */
4968*8f23e9faSHans Rosenfeld 	if (hba->link_event_tag == cqe->un.link.event_tag) {
4969*8f23e9faSHans Rosenfeld 		HBASTATS.LinkMultiEvent++;
4970*8f23e9faSHans Rosenfeld 	} else if (hba->link_event_tag + 1 < cqe->un.link.event_tag) {
4971*8f23e9faSHans Rosenfeld 		HBASTATS.LinkMultiEvent++;
4972*8f23e9faSHans Rosenfeld 	}
4973a9800bebSGarrett D'Amore 	hba->link_event_tag = cqe->un.link.event_tag;
497482527734SSukumar Swaminathan 
497582527734SSukumar Swaminathan 	switch (cqe->event_code) {
4976*8f23e9faSHans Rosenfeld 	case ASYNC_EVENT_CODE_FCOE_LINK_STATE:
4977*8f23e9faSHans Rosenfeld 		HBASTATS.LinkEvent++;
4978*8f23e9faSHans Rosenfeld 
4979a9800bebSGarrett D'Amore 		switch (cqe->un.link.link_status) {
498082527734SSukumar Swaminathan 		case ASYNC_EVENT_PHYS_LINK_UP:
498182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4982*8f23e9faSHans Rosenfeld 			    "Link Async Event: PHYS_LINK_UP. val=%d "
4983*8f23e9faSHans Rosenfeld 			    "type=%x event=%x",
4984*8f23e9faSHans Rosenfeld 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
498582527734SSukumar Swaminathan 			break;
498682527734SSukumar Swaminathan 
4987*8f23e9faSHans Rosenfeld 		case ASYNC_EVENT_LOGICAL_LINK_UP:
4988a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4989*8f23e9faSHans Rosenfeld 			    "Link Async Event: LOGICAL_LINK_UP. val=%d "
4990*8f23e9faSHans Rosenfeld 			    "type=%x event=%x",
4991*8f23e9faSHans Rosenfeld 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
4992a9800bebSGarrett D'Amore 
4993*8f23e9faSHans Rosenfeld 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
499482527734SSukumar Swaminathan 			break;
499582527734SSukumar Swaminathan 
4996*8f23e9faSHans Rosenfeld 		case ASYNC_EVENT_PHYS_LINK_DOWN:
4997a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4998*8f23e9faSHans Rosenfeld 			    "Link Async Event: PHYS_LINK_DOWN. val=%d "
4999*8f23e9faSHans Rosenfeld 			    "type=%x event=%x",
5000*8f23e9faSHans Rosenfeld 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
500182527734SSukumar Swaminathan 
5002*8f23e9faSHans Rosenfeld 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5003*8f23e9faSHans Rosenfeld 			break;
5004a9800bebSGarrett D'Amore 
5005*8f23e9faSHans Rosenfeld 		case ASYNC_EVENT_LOGICAL_LINK_DOWN:
5006*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5007*8f23e9faSHans Rosenfeld 			    "Link Async Event: LOGICAL_LINK_DOWN. val=%d "
5008*8f23e9faSHans Rosenfeld 			    "type=%x event=%x",
5009*8f23e9faSHans Rosenfeld 			    cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
5010*8f23e9faSHans Rosenfeld 
5011*8f23e9faSHans Rosenfeld 			emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5012*8f23e9faSHans Rosenfeld 			break;
5013*8f23e9faSHans Rosenfeld 		default:
5014*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5015*8f23e9faSHans Rosenfeld 			    "Link Async Event: Unknown link status=%d event=%x",
5016*8f23e9faSHans Rosenfeld 			    cqe->un.link.link_status, HBASTATS.LinkEvent);
501782527734SSukumar Swaminathan 			break;
501882527734SSukumar Swaminathan 		}
501982527734SSukumar Swaminathan 		break;
502082527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_FCOE_FIP:
5021a9800bebSGarrett D'Amore 		switch (cqe->un.fcoe.evt_type) {
502282527734SSukumar Swaminathan 		case ASYNC_EVENT_NEW_FCF_DISC:
502382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5024*8f23e9faSHans Rosenfeld 			    "FIP Async Event: FCF_FOUND %d:%d",
5025a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5026a9800bebSGarrett D'Amore 
5027a9800bebSGarrett D'Amore 			(void) emlxs_fcf_found_notify(port,
5028a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
502982527734SSukumar Swaminathan 			break;
503082527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_TABLE_FULL:
5031a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5032*8f23e9faSHans Rosenfeld 			    "FIP Async Event: FCFTAB_FULL %d:%d",
5033a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5034a9800bebSGarrett D'Amore 
5035a9800bebSGarrett D'Amore 			(void) emlxs_fcf_full_notify(port);
503682527734SSukumar Swaminathan 			break;
503782527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_DEAD:
503882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5039*8f23e9faSHans Rosenfeld 			    "FIP Async Event: FCF_LOST %d:%d",
5040a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5041a9800bebSGarrett D'Amore 
5042a9800bebSGarrett D'Amore 			(void) emlxs_fcf_lost_notify(port,
5043a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
504482527734SSukumar Swaminathan 			break;
504582527734SSukumar Swaminathan 		case ASYNC_EVENT_VIRT_LINK_CLEAR:
504682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5047*8f23e9faSHans Rosenfeld 			    "FIP Async Event: CVL %d",
5048a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
5049a9800bebSGarrett D'Amore 
5050a9800bebSGarrett D'Amore 			(void) emlxs_fcf_cvl_notify(port,
5051*8f23e9faSHans Rosenfeld 			    emlxs_sli4_vpi_to_index(hba,
5052*8f23e9faSHans Rosenfeld 			    cqe->un.fcoe.ref_index));
5053a9800bebSGarrett D'Amore 			break;
5054a9800bebSGarrett D'Amore 
5055a9800bebSGarrett D'Amore 		case ASYNC_EVENT_FCF_MODIFIED:
5056a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5057*8f23e9faSHans Rosenfeld 			    "FIP Async Event: FCF_CHANGED %d",
5058a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
5059a9800bebSGarrett D'Amore 
5060a9800bebSGarrett D'Amore 			(void) emlxs_fcf_changed_notify(port,
5061a9800bebSGarrett D'Amore 			    cqe->un.fcoe.ref_index);
506282527734SSukumar Swaminathan 			break;
5063*8f23e9faSHans Rosenfeld 		default:
5064*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5065*8f23e9faSHans Rosenfeld 			    "FIP Async Event: Unknown event type=%d",
5066*8f23e9faSHans Rosenfeld 			    cqe->un.fcoe.evt_type);
5067*8f23e9faSHans Rosenfeld 			break;
506882527734SSukumar Swaminathan 		}
506982527734SSukumar Swaminathan 		break;
507082527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_DCBX:
507182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5072*8f23e9faSHans Rosenfeld 		    "DCBX Async Event: type=%d. Not supported.",
5073*8f23e9faSHans Rosenfeld 		    cqe->event_type);
507482527734SSukumar Swaminathan 		break;
5075a9800bebSGarrett D'Amore 	case ASYNC_EVENT_CODE_GRP_5:
5076a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5077*8f23e9faSHans Rosenfeld 		    "Group 5 Async Event: type=%d.", cqe->event_type);
5078a9800bebSGarrett D'Amore 		if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) {
5079a9800bebSGarrett D'Amore 			hba->qos_linkspeed = cqe->un.qos.qos_link_speed;
5080a9800bebSGarrett D'Amore 		}
5081a9800bebSGarrett D'Amore 		break;
5082*8f23e9faSHans Rosenfeld 	case ASYNC_EVENT_CODE_FC_EVENT:
5083*8f23e9faSHans Rosenfeld 		switch (cqe->event_type) {
5084*8f23e9faSHans Rosenfeld 		case ASYNC_EVENT_FC_LINK_ATT:
5085*8f23e9faSHans Rosenfeld 			HBASTATS.LinkEvent++;
5086*8f23e9faSHans Rosenfeld 
5087*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5088*8f23e9faSHans Rosenfeld 			    "FC Async Event: Link Attention. event=%x",
5089*8f23e9faSHans Rosenfeld 			    HBASTATS.LinkEvent);
5090*8f23e9faSHans Rosenfeld 
5091*8f23e9faSHans Rosenfeld 			emlxs_sli4_handle_fc_link_att(hba, cqe);
5092*8f23e9faSHans Rosenfeld 			break;
5093*8f23e9faSHans Rosenfeld 		case ASYNC_EVENT_FC_SHARED_LINK_ATT:
5094*8f23e9faSHans Rosenfeld 			HBASTATS.LinkEvent++;
5095*8f23e9faSHans Rosenfeld 
5096*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5097*8f23e9faSHans Rosenfeld 			    "FC Async Event: Shared Link Attention. event=%x",
5098*8f23e9faSHans Rosenfeld 			    HBASTATS.LinkEvent);
5099*8f23e9faSHans Rosenfeld 
5100*8f23e9faSHans Rosenfeld 			emlxs_sli4_handle_fc_link_att(hba, cqe);
5101*8f23e9faSHans Rosenfeld 			break;
5102*8f23e9faSHans Rosenfeld 		default:
5103*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5104*8f23e9faSHans Rosenfeld 			    "FC Async Event: Unknown event. type=%d event=%x",
5105*8f23e9faSHans Rosenfeld 			    cqe->event_type, HBASTATS.LinkEvent);
5106*8f23e9faSHans Rosenfeld 		}
5107*8f23e9faSHans Rosenfeld 		break;
5108*8f23e9faSHans Rosenfeld 	case ASYNC_EVENT_CODE_PORT:
5109*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5110*8f23e9faSHans Rosenfeld 		    "SLI Port Async Event: type=%d", cqe->event_type);
5111*8f23e9faSHans Rosenfeld 		if (cqe->event_type == ASYNC_EVENT_MISCONFIG_PORT) {
5112*8f23e9faSHans Rosenfeld 			*((uint32_t *)cqe->un.port.link_status) =
5113*8f23e9faSHans Rosenfeld 			    BE_SWAP32(*((uint32_t *)cqe->un.port.link_status));
5114*8f23e9faSHans Rosenfeld 			status =
5115*8f23e9faSHans Rosenfeld 			    cqe->un.port.link_status[hba->sli.sli4.link_number];
5116*8f23e9faSHans Rosenfeld 
5117*8f23e9faSHans Rosenfeld 			switch (status) {
5118*8f23e9faSHans Rosenfeld 				case 0 :
5119*8f23e9faSHans Rosenfeld 				break;
5120*8f23e9faSHans Rosenfeld 
5121*8f23e9faSHans Rosenfeld 				case 1 :
5122*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5123*8f23e9faSHans Rosenfeld 				    "SLI Port Async Event: Physical media not "
5124*8f23e9faSHans Rosenfeld 				    "detected");
5125*8f23e9faSHans Rosenfeld 				cmn_err(CE_WARN,
5126*8f23e9faSHans Rosenfeld 				    "^%s%d: Optics faulted/incorrectly "
5127*8f23e9faSHans Rosenfeld 				    "installed/not installed - Reseat optics, "
5128*8f23e9faSHans Rosenfeld 				    "if issue not resolved, replace.",
5129*8f23e9faSHans Rosenfeld 				    DRIVER_NAME, hba->ddiinst);
5130*8f23e9faSHans Rosenfeld 				break;
5131*8f23e9faSHans Rosenfeld 
5132*8f23e9faSHans Rosenfeld 				case 2 :
5133*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5134*8f23e9faSHans Rosenfeld 				    "SLI Port Async Event: Wrong physical "
5135*8f23e9faSHans Rosenfeld 				    "media detected");
5136*8f23e9faSHans Rosenfeld 				cmn_err(CE_WARN,
5137*8f23e9faSHans Rosenfeld 				    "^%s%d: Optics of two types installed - "
5138*8f23e9faSHans Rosenfeld 				    "Remove one optic or install matching"
5139*8f23e9faSHans Rosenfeld 				    "pair of optics.",
5140*8f23e9faSHans Rosenfeld 				    DRIVER_NAME, hba->ddiinst);
5141*8f23e9faSHans Rosenfeld 				break;
5142*8f23e9faSHans Rosenfeld 
5143*8f23e9faSHans Rosenfeld 				case 3 :
5144*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5145*8f23e9faSHans Rosenfeld 				    "SLI Port Async Event: Unsupported "
5146*8f23e9faSHans Rosenfeld 				    "physical media detected");
5147*8f23e9faSHans Rosenfeld 				cmn_err(CE_WARN,
5148*8f23e9faSHans Rosenfeld 				    "^%s%d:  Incompatible optics - Replace "
5149*8f23e9faSHans Rosenfeld 				    "with compatible optics for card to "
5150*8f23e9faSHans Rosenfeld 				    "function.",
5151*8f23e9faSHans Rosenfeld 				    DRIVER_NAME, hba->ddiinst);
5152*8f23e9faSHans Rosenfeld 				break;
5153*8f23e9faSHans Rosenfeld 
5154*8f23e9faSHans Rosenfeld 				default :
5155*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5156*8f23e9faSHans Rosenfeld 				    "SLI Port Async Event: Physical media "
5157*8f23e9faSHans Rosenfeld 				    "error, status=%x", status);
5158*8f23e9faSHans Rosenfeld 				cmn_err(CE_WARN,
5159*8f23e9faSHans Rosenfeld 				    "^%s%d: Misconfigured port: status=0x%x - "
5160*8f23e9faSHans Rosenfeld 				    "Check optics on card.",
5161*8f23e9faSHans Rosenfeld 				    DRIVER_NAME, hba->ddiinst, status);
5162*8f23e9faSHans Rosenfeld 				break;
5163*8f23e9faSHans Rosenfeld 			}
5164*8f23e9faSHans Rosenfeld 		}
5165*8f23e9faSHans Rosenfeld 		break;
5166*8f23e9faSHans Rosenfeld 	case ASYNC_EVENT_CODE_VF:
5167*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5168*8f23e9faSHans Rosenfeld 		    "VF Async Event: type=%d",
5169*8f23e9faSHans Rosenfeld 		    cqe->event_type);
5170*8f23e9faSHans Rosenfeld 		break;
5171*8f23e9faSHans Rosenfeld 	case ASYNC_EVENT_CODE_MR:
5172*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5173*8f23e9faSHans Rosenfeld 		    "MR Async Event: type=%d",
5174*8f23e9faSHans Rosenfeld 		    cqe->event_type);
5175*8f23e9faSHans Rosenfeld 		break;
517682527734SSukumar Swaminathan 	default:
517782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5178*8f23e9faSHans Rosenfeld 		    "Unknown Async Event: code=%d type=%d.",
5179*8f23e9faSHans Rosenfeld 		    cqe->event_code, cqe->event_type);
518082527734SSukumar Swaminathan 		break;
518182527734SSukumar Swaminathan 	}
518282527734SSukumar Swaminathan 
518382527734SSukumar Swaminathan } /* emlxs_sli4_process_async_event() */
518482527734SSukumar Swaminathan 
518582527734SSukumar Swaminathan 
518682527734SSukumar Swaminathan /*ARGSUSED*/
518782527734SSukumar Swaminathan static void
518882527734SSukumar Swaminathan emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
518982527734SSukumar Swaminathan {
519082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
519182527734SSukumar Swaminathan 	MAILBOX4 *mb;
519282527734SSukumar Swaminathan 	MATCHMAP *mbox_bp;
519382527734SSukumar Swaminathan 	MATCHMAP *mbox_nonembed;
5194a9800bebSGarrett D'Amore 	MAILBOXQ *mbq = NULL;
519582527734SSukumar Swaminathan 	uint32_t size;
519682527734SSukumar Swaminathan 	uint32_t *iptr;
519782527734SSukumar Swaminathan 	int rc;
5198b3660a96SSukumar Swaminathan 	off_t offset;
519982527734SSukumar Swaminathan 
520082527734SSukumar Swaminathan 	if (cqe->consumed && !cqe->completed) {
520182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5202a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Entry consumed but not completed");
520382527734SSukumar Swaminathan 		return;
520482527734SSukumar Swaminathan 	}
520582527734SSukumar Swaminathan 
5206a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_PORT_LOCK);
520782527734SSukumar Swaminathan 	switch (hba->mbox_queue_flag) {
520882527734SSukumar Swaminathan 	case 0:
520982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5210a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. No mailbox active.");
5211a9800bebSGarrett D'Amore 
5212a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
521382527734SSukumar Swaminathan 		return;
521482527734SSukumar Swaminathan 
521582527734SSukumar Swaminathan 	case MBX_POLL:
521682527734SSukumar Swaminathan 
521782527734SSukumar Swaminathan 		/* Mark mailbox complete, this should wake up any polling */
521882527734SSukumar Swaminathan 		/* threads. This can happen if interrupts are enabled while */
521982527734SSukumar Swaminathan 		/* a polled mailbox command is outstanding. If we don't set */
522082527734SSukumar Swaminathan 		/* MBQ_COMPLETED here, the polling thread may wait until */
522182527734SSukumar Swaminathan 		/* timeout error occurs */
522282527734SSukumar Swaminathan 
522382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
522482527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
522582527734SSukumar Swaminathan 		if (mbq) {
5226a9800bebSGarrett D'Amore 			port = (emlxs_port_t *)mbq->port;
522782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5228a9800bebSGarrett D'Amore 			    "CQ ENTRY: Mbox event. Completing Polled command.");
522982527734SSukumar Swaminathan 			mbq->flag |= MBQ_COMPLETED;
523082527734SSukumar Swaminathan 		}
523182527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
523282527734SSukumar Swaminathan 
5233a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
523482527734SSukumar Swaminathan 		return;
523582527734SSukumar Swaminathan 
523682527734SSukumar Swaminathan 	case MBX_SLEEP:
523782527734SSukumar Swaminathan 	case MBX_NOWAIT:
5238a9800bebSGarrett D'Amore 		/* Check mbox_timer, it acts as a service flag too */
5239a9800bebSGarrett D'Amore 		/* The first to service the mbox queue will clear the timer */
5240a9800bebSGarrett D'Amore 		if (hba->mbox_timer) {
5241a9800bebSGarrett D'Amore 			hba->mbox_timer = 0;
5242a9800bebSGarrett D'Amore 
5243a9800bebSGarrett D'Amore 			mutex_enter(&EMLXS_MBOX_LOCK);
5244a9800bebSGarrett D'Amore 			mbq = (MAILBOXQ *)hba->mbox_mbq;
5245a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_MBOX_LOCK);
5246a9800bebSGarrett D'Amore 		}
5247a9800bebSGarrett D'Amore 
5248a9800bebSGarrett D'Amore 		if (!mbq) {
5249a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5250a9800bebSGarrett D'Amore 			    "Mailbox event. No service required.");
5251a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_PORT_LOCK);
5252a9800bebSGarrett D'Amore 			return;
5253a9800bebSGarrett D'Amore 		}
5254a9800bebSGarrett D'Amore 
525582527734SSukumar Swaminathan 		mb = (MAILBOX4 *)mbq;
5256a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
525782527734SSukumar Swaminathan 		break;
525882527734SSukumar Swaminathan 
525982527734SSukumar Swaminathan 	default:
526082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
5261a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
5262a9800bebSGarrett D'Amore 		    hba->mbox_queue_flag);
5263a9800bebSGarrett D'Amore 
5264a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_PORT_LOCK);
526582527734SSukumar Swaminathan 		return;
526682527734SSukumar Swaminathan 	}
526782527734SSukumar Swaminathan 
5268a9800bebSGarrett D'Amore 	/* Set port context */
5269a9800bebSGarrett D'Amore 	port = (emlxs_port_t *)mbq->port;
5270a9800bebSGarrett D'Amore 
5271b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
5272b3660a96SSukumar Swaminathan 	    hba->sli.sli4.mq.addr.virt) -
5273b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
5274b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
5275b3660a96SSukumar Swaminathan 
527682527734SSukumar Swaminathan 	/* Now that we are the owner, DMA Sync entire MQ if needed */
5277b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
527882527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORDEV);
527982527734SSukumar Swaminathan 
528082527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
528182527734SSukumar Swaminathan 	    MAILBOX_CMD_SLI4_BSIZE);
528282527734SSukumar Swaminathan 
5283a9800bebSGarrett D'Amore 	if (mb->mbxCommand != MBX_HEARTBEAT) {
5284a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5285a9800bebSGarrett D'Amore 		    "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
5286a9800bebSGarrett D'Amore 		    mb->mbxStatus, mb->mbxCommand);
5287a9800bebSGarrett D'Amore 
5288a9800bebSGarrett D'Amore 		emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe,
5289a9800bebSGarrett D'Amore 		    12, 0);
5290a9800bebSGarrett D'Amore 	}
529182527734SSukumar Swaminathan 
529282527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_SLI_CONFIG) {
529382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
529482527734SSukumar Swaminathan 		    "Mbox sge_cnt: %d length: %d embed: %d",
529582527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.sge_cnt,
529682527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.payload_length,
529782527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.embedded);
529882527734SSukumar Swaminathan 	}
529982527734SSukumar Swaminathan 
530082527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
530182527734SSukumar Swaminathan 	if (mbq->bp) {
530282527734SSukumar Swaminathan 		mbox_bp = (MATCHMAP *)mbq->bp;
530382527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
530482527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
5305b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5306b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle)
5307b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
5308b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5309b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
5310*8f23e9faSHans Rosenfeld 			    "sli4_process_mbox_event: hdl=%p",
5311b3660a96SSukumar Swaminathan 			    mbox_bp->dma_handle);
5312b3660a96SSukumar Swaminathan 
5313b3660a96SSukumar Swaminathan 			mb->mbxStatus = MBXERR_DMA_ERROR;
5314b3660a96SSukumar Swaminathan }
5315b3660a96SSukumar Swaminathan #endif
531682527734SSukumar Swaminathan 	}
531782527734SSukumar Swaminathan 
531882527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
531982527734SSukumar Swaminathan 	if (mbq->nonembed) {
532082527734SSukumar Swaminathan 		mbox_nonembed = (MATCHMAP *)mbq->nonembed;
532182527734SSukumar Swaminathan 		size = mbox_nonembed->size;
532282527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
532382527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
532482527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
532582527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
532682527734SSukumar Swaminathan 
5327b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5328b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
5329b3660a96SSukumar Swaminathan 		    mbox_nonembed->dma_handle) != DDI_FM_OK) {
5330b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5331b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
5332*8f23e9faSHans Rosenfeld 			    "sli4_process_mbox_event: hdl=%p",
5333b3660a96SSukumar Swaminathan 			    mbox_nonembed->dma_handle);
5334b3660a96SSukumar Swaminathan 
5335b3660a96SSukumar Swaminathan 			mb->mbxStatus = MBXERR_DMA_ERROR;
5336b3660a96SSukumar Swaminathan 		}
5337b3660a96SSukumar Swaminathan #endif
5338*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
533982527734SSukumar Swaminathan 	}
534082527734SSukumar Swaminathan 
534182527734SSukumar Swaminathan 	/* Mailbox has been completely received at this point */
534282527734SSukumar Swaminathan 
534382527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_HEARTBEAT) {
534482527734SSukumar Swaminathan 		hba->heartbeat_active = 0;
534582527734SSukumar Swaminathan 		goto done;
534682527734SSukumar Swaminathan 	}
534782527734SSukumar Swaminathan 
534882527734SSukumar Swaminathan 	if (hba->mbox_queue_flag == MBX_SLEEP) {
534982527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
535082527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
535182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
535282527734SSukumar Swaminathan 			    "Received.  %s: status=%x Sleep.",
535382527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
535482527734SSukumar Swaminathan 			    mb->mbxStatus);
535582527734SSukumar Swaminathan 		}
535682527734SSukumar Swaminathan 	} else {
535782527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
535882527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
535982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
536082527734SSukumar Swaminathan 			    "Completed. %s: status=%x",
536182527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
536282527734SSukumar Swaminathan 			    mb->mbxStatus);
536382527734SSukumar Swaminathan 		}
536482527734SSukumar Swaminathan 	}
536582527734SSukumar Swaminathan 
536682527734SSukumar Swaminathan 	/* Filter out passthru mailbox */
536782527734SSukumar Swaminathan 	if (mbq->flag & MBQ_PASSTHRU) {
536882527734SSukumar Swaminathan 		goto done;
536982527734SSukumar Swaminathan 	}
537082527734SSukumar Swaminathan 
537182527734SSukumar Swaminathan 	if (mb->mbxStatus) {
537282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
537382527734SSukumar Swaminathan 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
537482527734SSukumar Swaminathan 		    (uint32_t)mb->mbxStatus);
537582527734SSukumar Swaminathan 	}
537682527734SSukumar Swaminathan 
537782527734SSukumar Swaminathan 	if (mbq->mbox_cmpl) {
537882527734SSukumar Swaminathan 		rc = (mbq->mbox_cmpl)(hba, mbq);
537982527734SSukumar Swaminathan 
538082527734SSukumar Swaminathan 		/* If mbox was retried, return immediately */
538182527734SSukumar Swaminathan 		if (rc) {
538282527734SSukumar Swaminathan 			return;
538382527734SSukumar Swaminathan 		}
538482527734SSukumar Swaminathan 	}
538582527734SSukumar Swaminathan 
538682527734SSukumar Swaminathan done:
538782527734SSukumar Swaminathan 
538882527734SSukumar Swaminathan 	/* Clean up the mailbox area */
538982527734SSukumar Swaminathan 	emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
539082527734SSukumar Swaminathan 
539182527734SSukumar Swaminathan 	/* Attempt to send pending mailboxes */
539282527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
539382527734SSukumar Swaminathan 	if (mbq) {
539482527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
539582527734SSukumar Swaminathan 		rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
539682527734SSukumar Swaminathan 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5397a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
539882527734SSukumar Swaminathan 		}
539982527734SSukumar Swaminathan 	}
540082527734SSukumar Swaminathan 	return;
540182527734SSukumar Swaminathan 
540282527734SSukumar Swaminathan } /* emlxs_sli4_process_mbox_event() */
540382527734SSukumar Swaminathan 
540482527734SSukumar Swaminathan 
5405bce54adfSSukumar Swaminathan /*ARGSUSED*/
540682527734SSukumar Swaminathan static void
540782527734SSukumar Swaminathan emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
540882527734SSukumar Swaminathan {
5409*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
541082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5411*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
541282527734SSukumar Swaminathan 	IOCBQ *iocbq;
541382527734SSukumar Swaminathan 	IOCB *iocb;
5414a9800bebSGarrett D'Amore 	uint32_t *iptr;
5415a9800bebSGarrett D'Amore 	fc_packet_t *pkt;
541682527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
541782527734SSukumar Swaminathan 
541882527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
541982527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
542082527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
542182527734SSukumar Swaminathan 
5422*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
542382527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5424*8f23e9faSHans Rosenfeld 	    "CQE to IOCB: cmd:%x tag:%x xri:%d", wqe->Command,
542582527734SSukumar Swaminathan 	    wqe->RequestTag, wqe->XRITag);
5426*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
542782527734SSukumar Swaminathan 
542882527734SSukumar Swaminathan 	iocb->ULPSTATUS = cqe->Status;
542982527734SSukumar Swaminathan 	iocb->un.ulpWord[4] = cqe->Parameter;
543082527734SSukumar Swaminathan 	iocb->ULPIOTAG = cqe->RequestTag;
543182527734SSukumar Swaminathan 	iocb->ULPCONTEXT = wqe->XRITag;
543282527734SSukumar Swaminathan 
543382527734SSukumar Swaminathan 	switch (wqe->Command) {
543482527734SSukumar Swaminathan 
543582527734SSukumar Swaminathan 	case CMD_FCP_ICMND64_CR:
543682527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
543782527734SSukumar Swaminathan 		break;
543882527734SSukumar Swaminathan 
543982527734SSukumar Swaminathan 	case CMD_FCP_IREAD64_CR:
544082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
5441*8f23e9faSHans Rosenfeld 		iocb->ULPPU = PARM_XFER_CHECK;
544282527734SSukumar Swaminathan 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
544382527734SSukumar Swaminathan 			iocb->un.fcpi64.fcpi_parm =
544482527734SSukumar Swaminathan 			    wqe->un.FcpCmd.TotalTransferCount -
544582527734SSukumar Swaminathan 			    cqe->CmdSpecific;
544682527734SSukumar Swaminathan 		}
544782527734SSukumar Swaminathan 		break;
544882527734SSukumar Swaminathan 
544982527734SSukumar Swaminathan 	case CMD_FCP_IWRITE64_CR:
545082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
5451*8f23e9faSHans Rosenfeld 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
5452*8f23e9faSHans Rosenfeld 			if (wqe->un.FcpCmd.TotalTransferCount >
5453*8f23e9faSHans Rosenfeld 			    cqe->CmdSpecific) {
5454*8f23e9faSHans Rosenfeld 				iocb->un.fcpi64.fcpi_parm =
5455*8f23e9faSHans Rosenfeld 				    wqe->un.FcpCmd.TotalTransferCount -
5456*8f23e9faSHans Rosenfeld 				    cqe->CmdSpecific;
5457*8f23e9faSHans Rosenfeld 			} else {
5458*8f23e9faSHans Rosenfeld 				iocb->un.fcpi64.fcpi_parm = 0;
5459*8f23e9faSHans Rosenfeld 			}
5460*8f23e9faSHans Rosenfeld 		}
546182527734SSukumar Swaminathan 		break;
546282527734SSukumar Swaminathan 
546382527734SSukumar Swaminathan 	case CMD_ELS_REQUEST64_CR:
546482527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
546582527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
546682527734SSukumar Swaminathan 		if (iocb->ULPSTATUS == 0) {
546782527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
546882527734SSukumar Swaminathan 		}
5469a9800bebSGarrett D'Amore 		if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
5470a9800bebSGarrett D'Amore 			/* For LS_RJT, the driver populates the rsp buffer */
5471a9800bebSGarrett D'Amore 			pkt = PRIV2PKT(sbp);
5472a9800bebSGarrett D'Amore 			iptr = (uint32_t *)pkt->pkt_resp;
5473a9800bebSGarrett D'Amore 			*iptr++ = ELS_CMD_LS_RJT;
5474a9800bebSGarrett D'Amore 			*iptr = cqe->Parameter;
5475a9800bebSGarrett D'Amore 		}
547682527734SSukumar Swaminathan 		break;
547782527734SSukumar Swaminathan 
547882527734SSukumar Swaminathan 	case CMD_GEN_REQUEST64_CR:
547982527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
548082527734SSukumar Swaminathan 		iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
548182527734SSukumar Swaminathan 		break;
548282527734SSukumar Swaminathan 
548382527734SSukumar Swaminathan 	case CMD_XMIT_SEQUENCE64_CR:
548482527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
548582527734SSukumar Swaminathan 		break;
548682527734SSukumar Swaminathan 
5487*8f23e9faSHans Rosenfeld 	case CMD_ABORT_XRI_CX:
5488*8f23e9faSHans Rosenfeld 		iocb->ULPCONTEXT = wqe->AbortTag;
5489*8f23e9faSHans Rosenfeld 		break;
5490*8f23e9faSHans Rosenfeld 
5491*8f23e9faSHans Rosenfeld 	case CMD_FCP_TRECEIVE64_CX:
5492*8f23e9faSHans Rosenfeld 		/* free memory for XRDY */
5493*8f23e9faSHans Rosenfeld 		if (iocbq->bp) {
5494*8f23e9faSHans Rosenfeld 			emlxs_mem_buf_free(hba, iocbq->bp);
5495*8f23e9faSHans Rosenfeld 			iocbq->bp = 0;
5496*8f23e9faSHans Rosenfeld 		}
5497*8f23e9faSHans Rosenfeld 
5498*8f23e9faSHans Rosenfeld 		/*FALLTHROUGH*/
5499*8f23e9faSHans Rosenfeld 
5500*8f23e9faSHans Rosenfeld 	case CMD_FCP_TSEND64_CX:
5501*8f23e9faSHans Rosenfeld 	case CMD_FCP_TRSP64_CX:
550282527734SSukumar Swaminathan 	default:
550382527734SSukumar Swaminathan 		iocb->ULPCOMMAND = wqe->Command;
550482527734SSukumar Swaminathan 
550582527734SSukumar Swaminathan 	}
550682527734SSukumar Swaminathan } /* emlxs_CQE_to_IOCB() */
550782527734SSukumar Swaminathan 
550882527734SSukumar Swaminathan 
550982527734SSukumar Swaminathan /*ARGSUSED*/
551082527734SSukumar Swaminathan static void
551182527734SSukumar Swaminathan emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
551282527734SSukumar Swaminathan {
5513bce54adfSSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
551482527734SSukumar Swaminathan 	CHANNEL *cp;
551582527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
551682527734SSukumar Swaminathan 	IOCBQ *iocbq;
5517a9800bebSGarrett D'Amore 	uint16_t i;
5518*8f23e9faSHans Rosenfeld 	uint32_t trigger = 0;
551982527734SSukumar Swaminathan 	CQE_CmplWQ_t cqe;
552082527734SSukumar Swaminathan 
552182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
552282527734SSukumar Swaminathan 	for (i = 0; i < hba->max_iotag; i++) {
552382527734SSukumar Swaminathan 		sbp = hba->fc_table[i];
552482527734SSukumar Swaminathan 		if (sbp == NULL || sbp == STALE_PACKET) {
552582527734SSukumar Swaminathan 			continue;
552682527734SSukumar Swaminathan 		}
5527a9800bebSGarrett D'Amore 		hba->fc_table[i] = STALE_PACKET;
552882527734SSukumar Swaminathan 		hba->io_count--;
5529a9800bebSGarrett D'Amore 		sbp->iotag = 0;
553082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
553182527734SSukumar Swaminathan 
553282527734SSukumar Swaminathan 		cp = sbp->channel;
553382527734SSukumar Swaminathan 		bzero(&cqe, sizeof (CQE_CmplWQ_t));
553482527734SSukumar Swaminathan 		cqe.RequestTag = i;
553582527734SSukumar Swaminathan 		cqe.Status = IOSTAT_LOCAL_REJECT;
553682527734SSukumar Swaminathan 		cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
553782527734SSukumar Swaminathan 
553882527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
553982527734SSukumar Swaminathan 
554082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
554182527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
554282527734SSukumar Swaminathan 		if (sbp->fct_cmd) {
554382527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
554482527734SSukumar Swaminathan 			    EMLXS_FCT_IOCB_COMPLETE);
554582527734SSukumar Swaminathan 		}
554682527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
554782527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
554882527734SSukumar Swaminathan 
5549*8f23e9faSHans Rosenfeld 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5550*8f23e9faSHans Rosenfeld 			atomic_dec_32(&hba->io_active);
5551*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
5552*8f23e9faSHans Rosenfeld 			if (sbp->node) {
5553*8f23e9faSHans Rosenfeld 				atomic_dec_32(&sbp->node->io_active);
5554*8f23e9faSHans Rosenfeld 			}
5555*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
5556*8f23e9faSHans Rosenfeld 		}
555782527734SSukumar Swaminathan 
555882527734SSukumar Swaminathan 		/* Copy entry to sbp's iocbq */
555982527734SSukumar Swaminathan 		iocbq = &sbp->iocbq;
556082527734SSukumar Swaminathan 		emlxs_CQE_to_IOCB(hba, &cqe, sbp);
556182527734SSukumar Swaminathan 
556282527734SSukumar Swaminathan 		iocbq->next = NULL;
556382527734SSukumar Swaminathan 
556482527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
5565*8f23e9faSHans Rosenfeld 		emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
556682527734SSukumar Swaminathan 
556782527734SSukumar Swaminathan 		if (!(sbp->pkt_flags &
556882527734SSukumar Swaminathan 		    (PACKET_POLLED | PACKET_ALLOCATED))) {
556982527734SSukumar Swaminathan 			/* Add the IOCB to the channel list */
557082527734SSukumar Swaminathan 			mutex_enter(&cp->rsp_lock);
557182527734SSukumar Swaminathan 			if (cp->rsp_head == NULL) {
557282527734SSukumar Swaminathan 				cp->rsp_head = iocbq;
557382527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
557482527734SSukumar Swaminathan 			} else {
557582527734SSukumar Swaminathan 				cp->rsp_tail->next = iocbq;
557682527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
557782527734SSukumar Swaminathan 			}
557882527734SSukumar Swaminathan 			mutex_exit(&cp->rsp_lock);
557982527734SSukumar Swaminathan 			trigger = 1;
558082527734SSukumar Swaminathan 		} else {
558182527734SSukumar Swaminathan 			emlxs_proc_channel_event(hba, cp, iocbq);
558282527734SSukumar Swaminathan 		}
558382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_FCTAB_LOCK);
558482527734SSukumar Swaminathan 	}
558582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
558682527734SSukumar Swaminathan 
558782527734SSukumar Swaminathan 	if (trigger) {
558882527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
558982527734SSukumar Swaminathan 			cp = &hba->chan[i];
559082527734SSukumar Swaminathan 			if (cp->rsp_head != NULL) {
559182527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
559282527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
559382527734SSukumar Swaminathan 			}
559482527734SSukumar Swaminathan 		}
559582527734SSukumar Swaminathan 	}
559682527734SSukumar Swaminathan 
559782527734SSukumar Swaminathan } /* emlxs_sli4_hba_flush_chipq() */
559882527734SSukumar Swaminathan 
559982527734SSukumar Swaminathan 
560082527734SSukumar Swaminathan /*ARGSUSED*/
560182527734SSukumar Swaminathan static void
560282527734SSukumar Swaminathan emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
560382527734SSukumar Swaminathan     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
560482527734SSukumar Swaminathan {
560582527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
560682527734SSukumar Swaminathan 	CHANNEL *cp;
560782527734SSukumar Swaminathan 	uint16_t request_tag;
560882527734SSukumar Swaminathan 
560982527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
561082527734SSukumar Swaminathan 
561182527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
561282527734SSukumar Swaminathan 	cp = cq->channelp;
561382527734SSukumar Swaminathan 
561482527734SSukumar Swaminathan 	cp->hbaCmplCmd++;
561582527734SSukumar Swaminathan 
561682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5617*8f23e9faSHans Rosenfeld 	    "CQ ENTRY: OOR Cmpl: iotag=%d", request_tag);
561882527734SSukumar Swaminathan 
5619*8f23e9faSHans Rosenfeld 	emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 4, 0);
5620a9800bebSGarrett D'Amore 
562182527734SSukumar Swaminathan } /* emlxs_sli4_process_oor_wqe_cmpl() */
562282527734SSukumar Swaminathan 
562382527734SSukumar Swaminathan 
562482527734SSukumar Swaminathan /*ARGSUSED*/
562582527734SSukumar Swaminathan static void
562682527734SSukumar Swaminathan emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
562782527734SSukumar Swaminathan {
562882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
562982527734SSukumar Swaminathan 	CHANNEL *cp;
563082527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
563182527734SSukumar Swaminathan 	IOCBQ *iocbq;
563282527734SSukumar Swaminathan 	uint16_t request_tag;
563382527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
5634*8f23e9faSHans Rosenfeld #ifdef FCT_IO_TRACE
563582527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd;
563682527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
5637*8f23e9faSHans Rosenfeld #endif /* FCT_IO_TRACE */
563882527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
563982527734SSukumar Swaminathan 
564082527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
564182527734SSukumar Swaminathan 
564282527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
564382527734SSukumar Swaminathan 	cp = cq->channelp;
564482527734SSukumar Swaminathan 
5645a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
564682527734SSukumar Swaminathan 	sbp = hba->fc_table[request_tag];
5647*8f23e9faSHans Rosenfeld 
5648*8f23e9faSHans Rosenfeld 	if (!sbp) {
5649*8f23e9faSHans Rosenfeld 		cp->hbaCmplCmd++;
5650*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_FCTAB_LOCK);
5651*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5652*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: NULL sbp. iotag=%d. Dropping...",
5653*8f23e9faSHans Rosenfeld 		    request_tag);
5654*8f23e9faSHans Rosenfeld 		return;
5655*8f23e9faSHans Rosenfeld 	}
565682527734SSukumar Swaminathan 
565782527734SSukumar Swaminathan 	if (sbp == STALE_PACKET) {
565882527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
5659a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
566082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5661*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: Stale sbp. iotag=%d. Dropping...", request_tag);
566282527734SSukumar Swaminathan 		return;
566382527734SSukumar Swaminathan 	}
566482527734SSukumar Swaminathan 
5665*8f23e9faSHans Rosenfeld 	if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5666*8f23e9faSHans Rosenfeld 		atomic_add_32(&hba->io_active, -1);
5667*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
5668*8f23e9faSHans Rosenfeld 		if (sbp->node) {
5669*8f23e9faSHans Rosenfeld 			atomic_add_32(&sbp->node->io_active, -1);
5670*8f23e9faSHans Rosenfeld 		}
5671*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
5672*8f23e9faSHans Rosenfeld 	}
5673*8f23e9faSHans Rosenfeld 
5674*8f23e9faSHans Rosenfeld 	if (!(sbp->xrip)) {
567582527734SSukumar Swaminathan 		cp->hbaCmplCmd++;
5676a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
567782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5678*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: NULL sbp xrip %p. iotag=%d. Dropping...",
567982527734SSukumar Swaminathan 		    sbp, request_tag);
568082527734SSukumar Swaminathan 		return;
568182527734SSukumar Swaminathan 	}
568282527734SSukumar Swaminathan 
5683*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
568482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
568582527734SSukumar Swaminathan 	    "CQ ENTRY: process wqe compl");
5686*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
568782527734SSukumar Swaminathan 	cp->hbaCmplCmd_sbp++;
568882527734SSukumar Swaminathan 
568982527734SSukumar Swaminathan 	/* Copy entry to sbp's iocbq */
569082527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
569182527734SSukumar Swaminathan 	emlxs_CQE_to_IOCB(hba, cqe, sbp);
569282527734SSukumar Swaminathan 
569382527734SSukumar Swaminathan 	iocbq->next = NULL;
569482527734SSukumar Swaminathan 
569582527734SSukumar Swaminathan 	if (cqe->XB) {
569682527734SSukumar Swaminathan 		/* Mark exchange as ABORT in progress */
5697a9800bebSGarrett D'Amore 		sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO;
5698*8f23e9faSHans Rosenfeld 		sbp->xrip->flag |= EMLXS_XRI_BUSY;
569982527734SSukumar Swaminathan 
570082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5701*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: XRI BUSY: iotag=%d xri=%d", request_tag,
5702a9800bebSGarrett D'Amore 		    sbp->xrip->XRI);
570382527734SSukumar Swaminathan 
5704*8f23e9faSHans Rosenfeld 		emlxs_sli4_free_xri(port, sbp, 0, 0);
570582527734SSukumar Swaminathan 	} else {
570682527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
5707*8f23e9faSHans Rosenfeld 		emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0);
5708a9800bebSGarrett D'Amore 	}
5709a9800bebSGarrett D'Amore 
5710a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_FCTAB_LOCK);
5711a9800bebSGarrett D'Amore 
5712a9800bebSGarrett D'Amore #ifdef SFCT_SUPPORT
5713*8f23e9faSHans Rosenfeld #ifdef FCT_IO_TRACE
5714a9800bebSGarrett D'Amore 	fct_cmd = sbp->fct_cmd;
5715a9800bebSGarrett D'Amore 	if (fct_cmd) {
5716a9800bebSGarrett D'Amore 		cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
5717a9800bebSGarrett D'Amore 		mutex_enter(&cmd_sbp->fct_mtx);
5718a9800bebSGarrett D'Amore 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
5719a9800bebSGarrett D'Amore 		mutex_exit(&cmd_sbp->fct_mtx);
572082527734SSukumar Swaminathan 	}
5721*8f23e9faSHans Rosenfeld #endif /* FCT_IO_TRACE */
5722a9800bebSGarrett D'Amore #endif /* SFCT_SUPPORT */
572382527734SSukumar Swaminathan 
572482527734SSukumar Swaminathan 	/*
572582527734SSukumar Swaminathan 	 * If this is NOT a polled command completion
572682527734SSukumar Swaminathan 	 * or a driver allocated pkt, then defer pkt
572782527734SSukumar Swaminathan 	 * completion.
572882527734SSukumar Swaminathan 	 */
572982527734SSukumar Swaminathan 	if (!(sbp->pkt_flags &
573082527734SSukumar Swaminathan 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
573182527734SSukumar Swaminathan 		/* Add the IOCB to the channel list */
573282527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
573382527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
573482527734SSukumar Swaminathan 			cp->rsp_head = iocbq;
573582527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
573682527734SSukumar Swaminathan 		} else {
573782527734SSukumar Swaminathan 			cp->rsp_tail->next = iocbq;
573882527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
573982527734SSukumar Swaminathan 		}
574082527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
574182527734SSukumar Swaminathan 
574282527734SSukumar Swaminathan 		/* Delay triggering thread till end of ISR */
574382527734SSukumar Swaminathan 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
574482527734SSukumar Swaminathan 	} else {
574582527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
574682527734SSukumar Swaminathan 	}
574782527734SSukumar Swaminathan 
574882527734SSukumar Swaminathan } /* emlxs_sli4_process_wqe_cmpl() */
574982527734SSukumar Swaminathan 
575082527734SSukumar Swaminathan 
575182527734SSukumar Swaminathan /*ARGSUSED*/
575282527734SSukumar Swaminathan static void
575382527734SSukumar Swaminathan emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
575482527734SSukumar Swaminathan     CQE_RelWQ_t *cqe)
575582527734SSukumar Swaminathan {
575682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
575782527734SSukumar Swaminathan 	WQ_DESC_t *wq;
575882527734SSukumar Swaminathan 	CHANNEL *cp;
575982527734SSukumar Swaminathan 	uint32_t i;
5760*8f23e9faSHans Rosenfeld 	uint16_t wqi;
5761*8f23e9faSHans Rosenfeld 
5762*8f23e9faSHans Rosenfeld 	wqi = emlxs_sli4_wqid_to_index(hba, (uint16_t)cqe->WQid);
5763*8f23e9faSHans Rosenfeld 
5764*8f23e9faSHans Rosenfeld 	/* Verify WQ index */
5765*8f23e9faSHans Rosenfeld 	if (wqi == 0xffff) {
5766*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5767*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: Invalid WQid:%d. Dropping...",
5768*8f23e9faSHans Rosenfeld 		    cqe->WQid);
5769*8f23e9faSHans Rosenfeld 		return;
5770*8f23e9faSHans Rosenfeld 	}
577182527734SSukumar Swaminathan 
5772*8f23e9faSHans Rosenfeld 	wq = &hba->sli.sli4.wq[wqi];
577382527734SSukumar Swaminathan 
5774*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
577582527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
577682527734SSukumar Swaminathan 	    "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
577782527734SSukumar Swaminathan 	    cqe->WQindex);
5778*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
577982527734SSukumar Swaminathan 
578082527734SSukumar Swaminathan 	wq->port_index = cqe->WQindex;
578182527734SSukumar Swaminathan 
578282527734SSukumar Swaminathan 	/* Cmd ring may be available. Try sending more iocbs */
578382527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
578482527734SSukumar Swaminathan 		cp = &hba->chan[i];
578582527734SSukumar Swaminathan 		if (wq == (WQ_DESC_t *)cp->iopath) {
578682527734SSukumar Swaminathan 			emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
578782527734SSukumar Swaminathan 		}
578882527734SSukumar Swaminathan 	}
578982527734SSukumar Swaminathan 
579082527734SSukumar Swaminathan } /* emlxs_sli4_process_release_wqe() */
579182527734SSukumar Swaminathan 
579282527734SSukumar Swaminathan 
579382527734SSukumar Swaminathan /*ARGSUSED*/
579482527734SSukumar Swaminathan emlxs_iocbq_t *
579582527734SSukumar Swaminathan emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
579682527734SSukumar Swaminathan {
579782527734SSukumar Swaminathan 	emlxs_queue_t *q;
579882527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq;
579982527734SSukumar Swaminathan 	emlxs_iocbq_t *prev;
580082527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr2;
580182527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
580282527734SSukumar Swaminathan 
580382527734SSukumar Swaminathan 	switch (fchdr->type) {
580482527734SSukumar Swaminathan 	case 1: /* ELS */
580582527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
580682527734SSukumar Swaminathan 		break;
580782527734SSukumar Swaminathan 	case 0x20: /* CT */
580882527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
580982527734SSukumar Swaminathan 		break;
581082527734SSukumar Swaminathan 	default:
581182527734SSukumar Swaminathan 		return (NULL);
581282527734SSukumar Swaminathan 	}
581382527734SSukumar Swaminathan 
581482527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
581582527734SSukumar Swaminathan 
581682527734SSukumar Swaminathan 	q = &rxq->active;
581782527734SSukumar Swaminathan 	iocbq  = (emlxs_iocbq_t *)q->q_first;
581882527734SSukumar Swaminathan 	prev = NULL;
581982527734SSukumar Swaminathan 
582082527734SSukumar Swaminathan 	while (iocbq) {
582182527734SSukumar Swaminathan 
582282527734SSukumar Swaminathan 		fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
582382527734SSukumar Swaminathan 
582482527734SSukumar Swaminathan 		if ((fchdr2->s_id == fchdr->s_id) &&
582582527734SSukumar Swaminathan 		    (fchdr2->ox_id == fchdr->ox_id) &&
582682527734SSukumar Swaminathan 		    (fchdr2->seq_id == fchdr->seq_id)) {
582782527734SSukumar Swaminathan 			/* Remove iocbq */
582882527734SSukumar Swaminathan 			if (prev) {
582982527734SSukumar Swaminathan 				prev->next = iocbq->next;
583082527734SSukumar Swaminathan 			}
583182527734SSukumar Swaminathan 			if (q->q_first == (uint8_t *)iocbq) {
583282527734SSukumar Swaminathan 				q->q_first = (uint8_t *)iocbq->next;
583382527734SSukumar Swaminathan 			}
583482527734SSukumar Swaminathan 			if (q->q_last == (uint8_t *)iocbq) {
583582527734SSukumar Swaminathan 				q->q_last = (uint8_t *)prev;
583682527734SSukumar Swaminathan 			}
583782527734SSukumar Swaminathan 			q->q_cnt--;
583882527734SSukumar Swaminathan 
583982527734SSukumar Swaminathan 			break;
584082527734SSukumar Swaminathan 		}
584182527734SSukumar Swaminathan 
584282527734SSukumar Swaminathan 		prev  = iocbq;
584382527734SSukumar Swaminathan 		iocbq = iocbq->next;
584482527734SSukumar Swaminathan 	}
584582527734SSukumar Swaminathan 
584682527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
584782527734SSukumar Swaminathan 
584882527734SSukumar Swaminathan 	return (iocbq);
584982527734SSukumar Swaminathan 
585082527734SSukumar Swaminathan } /* emlxs_sli4_rxq_get() */
585182527734SSukumar Swaminathan 
585282527734SSukumar Swaminathan 
585382527734SSukumar Swaminathan /*ARGSUSED*/
585482527734SSukumar Swaminathan void
585582527734SSukumar Swaminathan emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
585682527734SSukumar Swaminathan {
585782527734SSukumar Swaminathan 	emlxs_queue_t *q;
585882527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr;
585982527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
586082527734SSukumar Swaminathan 
586182527734SSukumar Swaminathan 	fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
586282527734SSukumar Swaminathan 
586382527734SSukumar Swaminathan 	switch (fchdr->type) {
586482527734SSukumar Swaminathan 	case 1: /* ELS */
586582527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
586682527734SSukumar Swaminathan 		break;
586782527734SSukumar Swaminathan 	case 0x20: /* CT */
586882527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
586982527734SSukumar Swaminathan 		break;
587082527734SSukumar Swaminathan 	default:
587182527734SSukumar Swaminathan 		return;
587282527734SSukumar Swaminathan 	}
587382527734SSukumar Swaminathan 
587482527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
587582527734SSukumar Swaminathan 
587682527734SSukumar Swaminathan 	q = &rxq->active;
587782527734SSukumar Swaminathan 
587882527734SSukumar Swaminathan 	if (q->q_last) {
587982527734SSukumar Swaminathan 		((emlxs_iocbq_t *)q->q_last)->next = iocbq;
588082527734SSukumar Swaminathan 		q->q_cnt++;
588182527734SSukumar Swaminathan 	} else {
588282527734SSukumar Swaminathan 		q->q_first = (uint8_t *)iocbq;
588382527734SSukumar Swaminathan 		q->q_cnt = 1;
588482527734SSukumar Swaminathan 	}
588582527734SSukumar Swaminathan 
588682527734SSukumar Swaminathan 	q->q_last = (uint8_t *)iocbq;
588782527734SSukumar Swaminathan 	iocbq->next = NULL;
588882527734SSukumar Swaminathan 
588982527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
589082527734SSukumar Swaminathan 
589182527734SSukumar Swaminathan 	return;
589282527734SSukumar Swaminathan 
589382527734SSukumar Swaminathan } /* emlxs_sli4_rxq_put() */
589482527734SSukumar Swaminathan 
589582527734SSukumar Swaminathan 
589682527734SSukumar Swaminathan static void
5897a9800bebSGarrett D'Amore emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid)
589882527734SSukumar Swaminathan {
5899a9800bebSGarrett D'Amore 	emlxs_hba_t *hba = HBA;
590082527734SSukumar Swaminathan 	emlxs_rqdbu_t rqdb;
590182527734SSukumar Swaminathan 
590282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
590382527734SSukumar Swaminathan 	    "RQ POST: rqid=%d count=1", rqid);
590482527734SSukumar Swaminathan 
590582527734SSukumar Swaminathan 	/* Ring the RQ doorbell once to repost the RQ buffer */
590682527734SSukumar Swaminathan 	rqdb.word = 0;
590782527734SSukumar Swaminathan 	rqdb.db.Qid = rqid;
590882527734SSukumar Swaminathan 	rqdb.db.NumPosted = 1;
590982527734SSukumar Swaminathan 
5910*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_rqdb(hba, rqdb.word);
591182527734SSukumar Swaminathan 
591282527734SSukumar Swaminathan } /* emlxs_sli4_rq_post() */
591382527734SSukumar Swaminathan 
591482527734SSukumar Swaminathan 
591582527734SSukumar Swaminathan /*ARGSUSED*/
591682527734SSukumar Swaminathan static void
591782527734SSukumar Swaminathan emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
591882527734SSukumar Swaminathan     CQE_UnsolRcv_t *cqe)
591982527734SSukumar Swaminathan {
592082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
592182527734SSukumar Swaminathan 	emlxs_port_t *vport;
592282527734SSukumar Swaminathan 	RQ_DESC_t *hdr_rq;
592382527734SSukumar Swaminathan 	RQ_DESC_t *data_rq;
5924b3660a96SSukumar Swaminathan 	MBUF_INFO *hdr_mp;
5925b3660a96SSukumar Swaminathan 	MBUF_INFO *data_mp;
592682527734SSukumar Swaminathan 	MATCHMAP *seq_mp;
592782527734SSukumar Swaminathan 	uint32_t *data;
592882527734SSukumar Swaminathan 	fc_frame_hdr_t fchdr;
5929*8f23e9faSHans Rosenfeld 	uint16_t hdr_rqi;
593082527734SSukumar Swaminathan 	uint32_t host_index;
593182527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq = NULL;
593282527734SSukumar Swaminathan 	emlxs_iocb_t *iocb;
5933*8f23e9faSHans Rosenfeld 	emlxs_node_t *node = NULL;
593482527734SSukumar Swaminathan 	uint32_t i;
593582527734SSukumar Swaminathan 	uint32_t seq_len;
593682527734SSukumar Swaminathan 	uint32_t seq_cnt;
593782527734SSukumar Swaminathan 	uint32_t buf_type;
593882527734SSukumar Swaminathan 	char label[32];
593982527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
594082527734SSukumar Swaminathan 	CHANNEL *cp;
5941a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
5942a9800bebSGarrett D'Amore 	RPIobj_t *rpip = NULL;
594382527734SSukumar Swaminathan 	uint32_t	cmd;
594482527734SSukumar Swaminathan 	uint32_t posted = 0;
594582527734SSukumar Swaminathan 	uint32_t abort = 1;
5946b3660a96SSukumar Swaminathan 	off_t offset;
5947*8f23e9faSHans Rosenfeld 	uint32_t status;
5948*8f23e9faSHans Rosenfeld 	uint32_t data_size;
5949*8f23e9faSHans Rosenfeld 	uint16_t rqid;
5950*8f23e9faSHans Rosenfeld 	uint32_t hdr_size;
5951*8f23e9faSHans Rosenfeld 	fc_packet_t *pkt;
5952*8f23e9faSHans Rosenfeld 	emlxs_buf_t *sbp;
595382527734SSukumar Swaminathan 
5954*8f23e9faSHans Rosenfeld 	if (cqe->Code == CQE_TYPE_UNSOL_RCV_V1) {
5955*8f23e9faSHans Rosenfeld 		CQE_UnsolRcvV1_t *cqeV1 = (CQE_UnsolRcvV1_t *)cqe;
595682527734SSukumar Swaminathan 
5957*8f23e9faSHans Rosenfeld 		status	  = cqeV1->Status;
5958*8f23e9faSHans Rosenfeld 		data_size = cqeV1->data_size;
5959*8f23e9faSHans Rosenfeld 		rqid	  = cqeV1->RQid;
5960*8f23e9faSHans Rosenfeld 		hdr_size  = cqeV1->hdr_size;
5961*8f23e9faSHans Rosenfeld 	} else {
5962*8f23e9faSHans Rosenfeld 		status	  = cqe->Status;
5963*8f23e9faSHans Rosenfeld 		data_size = cqe->data_size;
5964*8f23e9faSHans Rosenfeld 		rqid	  = cqe->RQid;
5965*8f23e9faSHans Rosenfeld 		hdr_size  = cqe->hdr_size;
5966*8f23e9faSHans Rosenfeld 	}
596782527734SSukumar Swaminathan 
596882527734SSukumar Swaminathan 	/* Validate the CQE */
596982527734SSukumar Swaminathan 
597082527734SSukumar Swaminathan 	/* Check status */
5971*8f23e9faSHans Rosenfeld 	switch (status) {
597282527734SSukumar Swaminathan 	case RQ_STATUS_SUCCESS: /* 0x10 */
597382527734SSukumar Swaminathan 		break;
597482527734SSukumar Swaminathan 
597582527734SSukumar Swaminathan 	case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
597682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
597782527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload truncated.");
597882527734SSukumar Swaminathan 		break;
597982527734SSukumar Swaminathan 
598082527734SSukumar Swaminathan 	case RQ_STATUS_NEED_BUFFER: /* 0x12 */
598182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
598282527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
598382527734SSukumar Swaminathan 		return;
598482527734SSukumar Swaminathan 
598582527734SSukumar Swaminathan 	case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
598682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
598782527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
598882527734SSukumar Swaminathan 		return;
598982527734SSukumar Swaminathan 
599082527734SSukumar Swaminathan 	default:
599182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
599282527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
5993*8f23e9faSHans Rosenfeld 		    status);
599482527734SSukumar Swaminathan 		break;
599582527734SSukumar Swaminathan 	}
599682527734SSukumar Swaminathan 
599782527734SSukumar Swaminathan 	/* Make sure there is a frame header */
5998*8f23e9faSHans Rosenfeld 	if (hdr_size < sizeof (fc_frame_hdr_t)) {
599982527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
600082527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
600182527734SSukumar Swaminathan 		return;
600282527734SSukumar Swaminathan 	}
600382527734SSukumar Swaminathan 
6004*8f23e9faSHans Rosenfeld 	hdr_rqi = emlxs_sli4_rqid_to_index(hba, rqid);
6005*8f23e9faSHans Rosenfeld 
6006*8f23e9faSHans Rosenfeld 	/* Verify RQ index */
6007*8f23e9faSHans Rosenfeld 	if (hdr_rqi == 0xffff) {
6008*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6009*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: Unsol Rcv: Invalid RQID:%d. Dropping...",
6010*8f23e9faSHans Rosenfeld 		    rqid);
6011*8f23e9faSHans Rosenfeld 		return;
6012*8f23e9faSHans Rosenfeld 	}
6013*8f23e9faSHans Rosenfeld 
6014*8f23e9faSHans Rosenfeld 	hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
6015*8f23e9faSHans Rosenfeld 	data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
6016*8f23e9faSHans Rosenfeld 
6017*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6018*8f23e9faSHans Rosenfeld 	    "CQ ENTRY: Unsol Rcv:%x rqid=%d,%d index=%d status=%x "
6019*8f23e9faSHans Rosenfeld 	    "hdr_size=%d data_size=%d",
6020*8f23e9faSHans Rosenfeld 	    cqe->Code, rqid, hdr_rqi, hdr_rq->host_index, status, hdr_size,
6021*8f23e9faSHans Rosenfeld 	    data_size);
6022*8f23e9faSHans Rosenfeld 
6023*8f23e9faSHans Rosenfeld 	hdr_rq->num_proc++;
6024*8f23e9faSHans Rosenfeld 
602582527734SSukumar Swaminathan 	/* Update host index */
602682527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
602782527734SSukumar Swaminathan 	host_index = hdr_rq->host_index;
602882527734SSukumar Swaminathan 	hdr_rq->host_index++;
6029*8f23e9faSHans Rosenfeld 
603082527734SSukumar Swaminathan 	if (hdr_rq->host_index >= hdr_rq->max_index) {
603182527734SSukumar Swaminathan 		hdr_rq->host_index = 0;
603282527734SSukumar Swaminathan 	}
603382527734SSukumar Swaminathan 	data_rq->host_index = hdr_rq->host_index;
603482527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
603582527734SSukumar Swaminathan 
603682527734SSukumar Swaminathan 	/* Get the next header rqb */
6037b3660a96SSukumar Swaminathan 	hdr_mp  = &hdr_rq->rqb[host_index];
603882527734SSukumar Swaminathan 
6039b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) -
6040b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt));
6041b3660a96SSukumar Swaminathan 
6042b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset,
604382527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
604482527734SSukumar Swaminathan 
604582527734SSukumar Swaminathan 	LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
604682527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t));
604782527734SSukumar Swaminathan 
604882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6049a9800bebSGarrett D'Amore 	    "RQ HDR[%d]: rctl:%x type:%x "
605082527734SSukumar Swaminathan 	    "sid:%x did:%x oxid:%x rxid:%x",
605182527734SSukumar Swaminathan 	    host_index, fchdr.r_ctl, fchdr.type,
605282527734SSukumar Swaminathan 	    fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
605382527734SSukumar Swaminathan 
605482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
605582527734SSukumar Swaminathan 	    "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
605682527734SSukumar Swaminathan 	    host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
605782527734SSukumar Swaminathan 	    fchdr.df_ctl, fchdr.ro);
605882527734SSukumar Swaminathan 
605982527734SSukumar Swaminathan 	/* Verify fc header type */
606082527734SSukumar Swaminathan 	switch (fchdr.type) {
606182527734SSukumar Swaminathan 	case 0: /* BLS */
606282527734SSukumar Swaminathan 		if (fchdr.r_ctl != 0x81) {
606382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6064a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unexpected FC rctl (0x%x) "
606582527734SSukumar Swaminathan 			    "received. Dropping...",
606682527734SSukumar Swaminathan 			    fchdr.r_ctl);
606782527734SSukumar Swaminathan 
606882527734SSukumar Swaminathan 			goto done;
606982527734SSukumar Swaminathan 		}
607082527734SSukumar Swaminathan 
607182527734SSukumar Swaminathan 		/* Make sure there is no payload */
6072*8f23e9faSHans Rosenfeld 		if (data_size != 0) {
607382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
607482527734SSukumar Swaminathan 			    "RQ ENTRY: ABTS payload provided. Dropping...");
607582527734SSukumar Swaminathan 
607682527734SSukumar Swaminathan 			goto done;
607782527734SSukumar Swaminathan 		}
607882527734SSukumar Swaminathan 
607982527734SSukumar Swaminathan 		buf_type = 0xFFFFFFFF;
6080*8f23e9faSHans Rosenfeld 		(void) strlcpy(label, "ABTS", sizeof (label));
608182527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
608282527734SSukumar Swaminathan 		break;
608382527734SSukumar Swaminathan 
608482527734SSukumar Swaminathan 	case 0x01: /* ELS */
608582527734SSukumar Swaminathan 		/* Make sure there is a payload */
6086*8f23e9faSHans Rosenfeld 		if (data_size == 0) {
608782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6088a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unsol Rcv: No ELS payload provided. "
608982527734SSukumar Swaminathan 			    "Dropping...");
609082527734SSukumar Swaminathan 
609182527734SSukumar Swaminathan 			goto done;
609282527734SSukumar Swaminathan 		}
609382527734SSukumar Swaminathan 
609482527734SSukumar Swaminathan 		buf_type = MEM_ELSBUF;
6095*8f23e9faSHans Rosenfeld 		(void) strlcpy(label, "Unsol ELS", sizeof (label));
609682527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
609782527734SSukumar Swaminathan 		break;
609882527734SSukumar Swaminathan 
609982527734SSukumar Swaminathan 	case 0x20: /* CT */
610082527734SSukumar Swaminathan 		/* Make sure there is a payload */
6101*8f23e9faSHans Rosenfeld 		if (data_size == 0) {
610282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6103a9800bebSGarrett D'Amore 			    "RQ ENTRY: Unsol Rcv: No CT payload provided. "
610482527734SSukumar Swaminathan 			    "Dropping...");
610582527734SSukumar Swaminathan 
610682527734SSukumar Swaminathan 			goto done;
610782527734SSukumar Swaminathan 		}
610882527734SSukumar Swaminathan 
610982527734SSukumar Swaminathan 		buf_type = MEM_CTBUF;
6110*8f23e9faSHans Rosenfeld 		(void) strlcpy(label, "Unsol CT", sizeof (label));
611182527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_ct];
611282527734SSukumar Swaminathan 		break;
611382527734SSukumar Swaminathan 
6114*8f23e9faSHans Rosenfeld 	case 0x08: /* FCT */
6115*8f23e9faSHans Rosenfeld 		/* Make sure there is a payload */
6116*8f23e9faSHans Rosenfeld 		if (data_size == 0) {
6117*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6118*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: Unsol Rcv: No FCP payload provided. "
6119*8f23e9faSHans Rosenfeld 			    "Dropping...");
6120*8f23e9faSHans Rosenfeld 
6121*8f23e9faSHans Rosenfeld 			goto done;
6122*8f23e9faSHans Rosenfeld 		}
6123*8f23e9faSHans Rosenfeld 
6124*8f23e9faSHans Rosenfeld 		buf_type = MEM_FCTBUF;
6125*8f23e9faSHans Rosenfeld 		(void) strlcpy(label, "Unsol FCT", sizeof (label));
6126*8f23e9faSHans Rosenfeld 		cp = &hba->chan[hba->CHANNEL_FCT];
6127*8f23e9faSHans Rosenfeld 		break;
6128*8f23e9faSHans Rosenfeld 
612982527734SSukumar Swaminathan 	default:
613082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
613182527734SSukumar Swaminathan 		    "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
613282527734SSukumar Swaminathan 		    fchdr.type);
613382527734SSukumar Swaminathan 
613482527734SSukumar Swaminathan 		goto done;
613582527734SSukumar Swaminathan 	}
613682527734SSukumar Swaminathan 	/* Fc Header is valid */
613782527734SSukumar Swaminathan 
613882527734SSukumar Swaminathan 	/* Check if this is an active sequence */
613982527734SSukumar Swaminathan 	iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
614082527734SSukumar Swaminathan 
614182527734SSukumar Swaminathan 	if (!iocbq) {
614282527734SSukumar Swaminathan 		if (fchdr.type != 0) {
614382527734SSukumar Swaminathan 			if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
614482527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6145a9800bebSGarrett D'Amore 				    "RQ ENTRY: %s: First of sequence not"
614682527734SSukumar Swaminathan 				    " set.  Dropping...",
614782527734SSukumar Swaminathan 				    label);
614882527734SSukumar Swaminathan 
614982527734SSukumar Swaminathan 				goto done;
615082527734SSukumar Swaminathan 			}
615182527734SSukumar Swaminathan 		}
615282527734SSukumar Swaminathan 
6153*8f23e9faSHans Rosenfeld 		if ((fchdr.type != 0) && (fchdr.seq_cnt != 0)) {
615482527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6155a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Sequence count not zero (%d).  "
615682527734SSukumar Swaminathan 			    "Dropping...",
615782527734SSukumar Swaminathan 			    label, fchdr.seq_cnt);
615882527734SSukumar Swaminathan 
615982527734SSukumar Swaminathan 			goto done;
616082527734SSukumar Swaminathan 		}
616182527734SSukumar Swaminathan 
6162*8f23e9faSHans Rosenfeld 		/* Find vport */
616382527734SSukumar Swaminathan 		for (i = 0; i < MAX_VPORTS; i++) {
616482527734SSukumar Swaminathan 			vport = &VPORT(i);
616582527734SSukumar Swaminathan 
616682527734SSukumar Swaminathan 			if (vport->did == fchdr.d_id) {
616782527734SSukumar Swaminathan 				port = vport;
616882527734SSukumar Swaminathan 				break;
616982527734SSukumar Swaminathan 			}
617082527734SSukumar Swaminathan 		}
617182527734SSukumar Swaminathan 
6172*8f23e9faSHans Rosenfeld 		if (i == MAX_VPORTS) {
6173*8f23e9faSHans Rosenfeld 			/* Allow unsol FLOGI & PLOGI for P2P */
6174*8f23e9faSHans Rosenfeld 			if ((fchdr.type != 1 /* ELS*/) ||
6175*8f23e9faSHans Rosenfeld 			    ((fchdr.d_id != FABRIC_DID) &&
6176*8f23e9faSHans Rosenfeld 			    !(hba->flag & FC_PT_TO_PT))) {
6177*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6178*8f23e9faSHans Rosenfeld 				    "RQ ENTRY: %s: Invalid did=%x. Dropping...",
6179*8f23e9faSHans Rosenfeld 				    label, fchdr.d_id);
6180*8f23e9faSHans Rosenfeld 
6181*8f23e9faSHans Rosenfeld 				goto done;
6182*8f23e9faSHans Rosenfeld 			}
6183*8f23e9faSHans Rosenfeld 		}
6184*8f23e9faSHans Rosenfeld 
618582527734SSukumar Swaminathan 		/* Allocate an IOCBQ */
6186*8f23e9faSHans Rosenfeld 		iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba, MEM_IOCB);
618782527734SSukumar Swaminathan 
618882527734SSukumar Swaminathan 		if (!iocbq) {
618982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6190a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of IOCB "
619182527734SSukumar Swaminathan 			    "resources.  Dropping...",
619282527734SSukumar Swaminathan 			    label);
619382527734SSukumar Swaminathan 
619482527734SSukumar Swaminathan 			goto done;
619582527734SSukumar Swaminathan 		}
619682527734SSukumar Swaminathan 
619782527734SSukumar Swaminathan 		seq_mp = NULL;
619882527734SSukumar Swaminathan 		if (fchdr.type != 0) {
619982527734SSukumar Swaminathan 			/* Allocate a buffer */
6200*8f23e9faSHans Rosenfeld 			seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type);
620182527734SSukumar Swaminathan 
620282527734SSukumar Swaminathan 			if (!seq_mp) {
620382527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6204a9800bebSGarrett D'Amore 				    "RQ ENTRY: %s: Out of buffer "
620582527734SSukumar Swaminathan 				    "resources.  Dropping...",
620682527734SSukumar Swaminathan 				    label);
620782527734SSukumar Swaminathan 
620882527734SSukumar Swaminathan 				goto done;
620982527734SSukumar Swaminathan 			}
621082527734SSukumar Swaminathan 
621182527734SSukumar Swaminathan 			iocbq->bp = (uint8_t *)seq_mp;
621282527734SSukumar Swaminathan 		}
621382527734SSukumar Swaminathan 
6214*8f23e9faSHans Rosenfeld 		node = (void *)emlxs_node_find_did(port, fchdr.s_id, 1);
621582527734SSukumar Swaminathan 		if (node == NULL) {
621682527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
621782527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Node not found. sid=%x",
621882527734SSukumar Swaminathan 			    label, fchdr.s_id);
621982527734SSukumar Swaminathan 		}
622082527734SSukumar Swaminathan 
622182527734SSukumar Swaminathan 		/* Initialize the iocbq */
622282527734SSukumar Swaminathan 		iocbq->port = port;
622382527734SSukumar Swaminathan 		iocbq->channel = cp;
622482527734SSukumar Swaminathan 		iocbq->node = node;
622582527734SSukumar Swaminathan 
622682527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
622782527734SSukumar Swaminathan 		iocb->RXSEQCNT = 0;
622882527734SSukumar Swaminathan 		iocb->RXSEQLEN = 0;
622982527734SSukumar Swaminathan 
623082527734SSukumar Swaminathan 		seq_len = 0;
623182527734SSukumar Swaminathan 		seq_cnt = 0;
623282527734SSukumar Swaminathan 
623382527734SSukumar Swaminathan 	} else {
623482527734SSukumar Swaminathan 
623582527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
623682527734SSukumar Swaminathan 		port = iocbq->port;
623782527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
623882527734SSukumar Swaminathan 
623982527734SSukumar Swaminathan 		seq_mp = (MATCHMAP *)iocbq->bp;
624082527734SSukumar Swaminathan 		seq_len = iocb->RXSEQLEN;
624182527734SSukumar Swaminathan 		seq_cnt = iocb->RXSEQCNT;
624282527734SSukumar Swaminathan 
624382527734SSukumar Swaminathan 		/* Check sequence order */
624482527734SSukumar Swaminathan 		if (fchdr.seq_cnt != seq_cnt) {
624582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6246a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of order frame received "
624782527734SSukumar Swaminathan 			    "(%d != %d).  Dropping...",
624882527734SSukumar Swaminathan 			    label, fchdr.seq_cnt, seq_cnt);
624982527734SSukumar Swaminathan 
625082527734SSukumar Swaminathan 			goto done;
625182527734SSukumar Swaminathan 		}
625282527734SSukumar Swaminathan 	}
625382527734SSukumar Swaminathan 
625482527734SSukumar Swaminathan 	/* We now have an iocbq */
625582527734SSukumar Swaminathan 
6256*8f23e9faSHans Rosenfeld 	if (!port->vpip->vfip) {
6257a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6258a9800bebSGarrett D'Amore 		    "RQ ENTRY: %s: No fabric connection. "
6259a9800bebSGarrett D'Amore 		    "Dropping...",
6260a9800bebSGarrett D'Amore 		    label);
6261a9800bebSGarrett D'Amore 
6262a9800bebSGarrett D'Amore 		goto done;
6263a9800bebSGarrett D'Amore 	}
6264a9800bebSGarrett D'Amore 
626582527734SSukumar Swaminathan 	/* Save the frame data to our seq buffer */
6266*8f23e9faSHans Rosenfeld 	if (data_size && seq_mp) {
626782527734SSukumar Swaminathan 		/* Get the next data rqb */
6268b3660a96SSukumar Swaminathan 		data_mp = &data_rq->rqb[host_index];
6269b3660a96SSukumar Swaminathan 
6270b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
6271b3660a96SSukumar Swaminathan 		    data_mp->virt) -
6272b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
6273b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
627482527734SSukumar Swaminathan 
6275b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset,
6276*8f23e9faSHans Rosenfeld 		    data_size, DDI_DMA_SYNC_FORKERNEL);
627782527734SSukumar Swaminathan 
627882527734SSukumar Swaminathan 		data = (uint32_t *)data_mp->virt;
627982527734SSukumar Swaminathan 
628082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
628182527734SSukumar Swaminathan 		    "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
628282527734SSukumar Swaminathan 		    host_index, data[0], data[1], data[2], data[3],
628382527734SSukumar Swaminathan 		    data[4], data[5]);
628482527734SSukumar Swaminathan 
628582527734SSukumar Swaminathan 		/* Check sequence length */
6286*8f23e9faSHans Rosenfeld 		if ((seq_len + data_size) > seq_mp->size) {
628782527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6288a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Sequence buffer overflow. "
628982527734SSukumar Swaminathan 			    "(%d > %d). Dropping...",
6290*8f23e9faSHans Rosenfeld 			    label, (seq_len + data_size), seq_mp->size);
629182527734SSukumar Swaminathan 
629282527734SSukumar Swaminathan 			goto done;
629382527734SSukumar Swaminathan 		}
629482527734SSukumar Swaminathan 
629582527734SSukumar Swaminathan 		/* Copy data to local receive buffer */
629682527734SSukumar Swaminathan 		bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
6297*8f23e9faSHans Rosenfeld 		    seq_len), data_size);
629882527734SSukumar Swaminathan 
6299*8f23e9faSHans Rosenfeld 		seq_len += data_size;
630082527734SSukumar Swaminathan 	}
630182527734SSukumar Swaminathan 
630282527734SSukumar Swaminathan 	/* If this is not the last frame of sequence, queue it. */
630382527734SSukumar Swaminathan 	if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
630482527734SSukumar Swaminathan 		/* Save sequence header */
630582527734SSukumar Swaminathan 		if (seq_cnt == 0) {
630682527734SSukumar Swaminathan 			bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
630782527734SSukumar Swaminathan 			    sizeof (fc_frame_hdr_t));
630882527734SSukumar Swaminathan 		}
630982527734SSukumar Swaminathan 
631082527734SSukumar Swaminathan 		/* Update sequence info in iocb */
631182527734SSukumar Swaminathan 		iocb->RXSEQCNT = seq_cnt + 1;
631282527734SSukumar Swaminathan 		iocb->RXSEQLEN = seq_len;
631382527734SSukumar Swaminathan 
631482527734SSukumar Swaminathan 		/* Queue iocbq for next frame */
631582527734SSukumar Swaminathan 		emlxs_sli4_rxq_put(hba, iocbq);
631682527734SSukumar Swaminathan 
631782527734SSukumar Swaminathan 		/* Don't free resources */
631882527734SSukumar Swaminathan 		iocbq = NULL;
631982527734SSukumar Swaminathan 
632082527734SSukumar Swaminathan 		/* No need to abort */
632182527734SSukumar Swaminathan 		abort = 0;
632282527734SSukumar Swaminathan 
632382527734SSukumar Swaminathan 		goto done;
632482527734SSukumar Swaminathan 	}
632582527734SSukumar Swaminathan 
6326a9800bebSGarrett D'Amore 	emlxs_sli4_rq_post(port, hdr_rq->qid);
632782527734SSukumar Swaminathan 	posted = 1;
632882527734SSukumar Swaminathan 
632982527734SSukumar Swaminathan 	/* End of sequence found. Process request now. */
633082527734SSukumar Swaminathan 
633182527734SSukumar Swaminathan 	if (seq_cnt > 0) {
633282527734SSukumar Swaminathan 		/* Retrieve first frame of sequence */
633382527734SSukumar Swaminathan 		bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
633482527734SSukumar Swaminathan 		    sizeof (fc_frame_hdr_t));
633582527734SSukumar Swaminathan 
633682527734SSukumar Swaminathan 		bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
633782527734SSukumar Swaminathan 	}
633882527734SSukumar Swaminathan 
633982527734SSukumar Swaminathan 	/* Build rcv iocb and process it */
634082527734SSukumar Swaminathan 	switch (fchdr.type) {
634182527734SSukumar Swaminathan 	case 0: /* BLS */
634282527734SSukumar Swaminathan 
634382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6344*8f23e9faSHans Rosenfeld 		    "RQ ENTRY: %s: oxid:%x rxid %x sid:%x. Sending BLS ACC...",
6345*8f23e9faSHans Rosenfeld 		    label, fchdr.ox_id, fchdr.rx_id, fchdr.s_id);
634682527734SSukumar Swaminathan 
6347*8f23e9faSHans Rosenfeld 		/* Try to send abort response */
6348*8f23e9faSHans Rosenfeld 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
6349*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6350*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Unable to alloc pkt. Dropping...",
6351*8f23e9faSHans Rosenfeld 			    label);
6352*8f23e9faSHans Rosenfeld 			goto done;
6353*8f23e9faSHans Rosenfeld 		}
635482527734SSukumar Swaminathan 
6355*8f23e9faSHans Rosenfeld 		/* Setup sbp / iocb for driver initiated cmd */
6356*8f23e9faSHans Rosenfeld 		sbp = PKT2PRIV(pkt);
6357*8f23e9faSHans Rosenfeld 
6358*8f23e9faSHans Rosenfeld 		/* Free the temporary iocbq */
6359*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
6360*8f23e9faSHans Rosenfeld 
6361*8f23e9faSHans Rosenfeld 		iocbq = (emlxs_iocbq_t *)&sbp->iocbq;
6362*8f23e9faSHans Rosenfeld 		iocbq->port = port;
6363*8f23e9faSHans Rosenfeld 		iocbq->channel = cp;
6364*8f23e9faSHans Rosenfeld 		iocbq->node = node;
6365*8f23e9faSHans Rosenfeld 
6366*8f23e9faSHans Rosenfeld 		sbp->pkt_flags &= ~PACKET_ULP_OWNED;
6367*8f23e9faSHans Rosenfeld 
6368*8f23e9faSHans Rosenfeld 		if (node) {
6369*8f23e9faSHans Rosenfeld 			sbp->node = node;
6370*8f23e9faSHans Rosenfeld 			sbp->did  = node->nlp_DID;
637182527734SSukumar Swaminathan 		}
6372*8f23e9faSHans Rosenfeld 
6373*8f23e9faSHans Rosenfeld 		iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
637482527734SSukumar Swaminathan 
637582527734SSukumar Swaminathan 		/* BLS ACC Response */
637682527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
637782527734SSukumar Swaminathan 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
637882527734SSukumar Swaminathan 
6379*8f23e9faSHans Rosenfeld 		iocbq->iocb.ULPCOMMAND = CMD_XMIT_BLS_RSP64_CX;
638082527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_BLS_RSP64_CX;
638182527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
638282527734SSukumar Swaminathan 
638382527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload0 = 0x80;
638482527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
638582527734SSukumar Swaminathan 
638682527734SSukumar Swaminathan 		wqe->un.BlsRsp.OXId = fchdr.ox_id;
638782527734SSukumar Swaminathan 		wqe->un.BlsRsp.RXId = fchdr.rx_id;
638882527734SSukumar Swaminathan 
638982527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntLow = 0;
639082527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
639182527734SSukumar Swaminathan 
6392*8f23e9faSHans Rosenfeld 		wqe->un.BlsRsp.XO = ((fchdr.f_ctl & F_CTL_XCHG_CONTEXT)? 1:0);
639382527734SSukumar Swaminathan 		wqe->un.BlsRsp.AR = 0;
639482527734SSukumar Swaminathan 
6395*8f23e9faSHans Rosenfeld 		rpip = EMLXS_NODE_TO_RPI(port, node);
639682527734SSukumar Swaminathan 
6397*8f23e9faSHans Rosenfeld 		if (rpip) {
6398*8f23e9faSHans Rosenfeld 			wqe->ContextType = WQE_RPI_CONTEXT;
6399*8f23e9faSHans Rosenfeld 			wqe->ContextTag = rpip->RPI;
6400*8f23e9faSHans Rosenfeld 		} else {
6401*8f23e9faSHans Rosenfeld 			wqe->ContextType = WQE_VPI_CONTEXT;
6402*8f23e9faSHans Rosenfeld 			wqe->ContextTag = port->vpip->VPI;
640382527734SSukumar Swaminathan 
6404*8f23e9faSHans Rosenfeld 			rpip = emlxs_rpi_reserve_notify(port, fchdr.s_id, 0);
640582527734SSukumar Swaminathan 
6406*8f23e9faSHans Rosenfeld 			if (!rpip) {
6407*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6408*8f23e9faSHans Rosenfeld 				    "RQ ENTRY: %s: Unable to alloc "
6409*8f23e9faSHans Rosenfeld 				    "reserved RPI. Dropping...",
6410*8f23e9faSHans Rosenfeld 				    label);
6411a9800bebSGarrett D'Amore 
6412*8f23e9faSHans Rosenfeld 				goto done;
6413*8f23e9faSHans Rosenfeld 			}
6414a9800bebSGarrett D'Amore 
6415*8f23e9faSHans Rosenfeld 			/* Store the reserved rpi */
6416*8f23e9faSHans Rosenfeld 			wqe->CmdSpecific = rpip->RPI;
641782527734SSukumar Swaminathan 
6418*8f23e9faSHans Rosenfeld 			wqe->un.BlsRsp.RemoteId = fchdr.s_id;
6419*8f23e9faSHans Rosenfeld 			wqe->un.BlsRsp.LocalId = fchdr.d_id;
642082527734SSukumar Swaminathan 		}
642182527734SSukumar Swaminathan 
6422*8f23e9faSHans Rosenfeld 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6423*8f23e9faSHans Rosenfeld 			wqe->CCPE = 1;
6424*8f23e9faSHans Rosenfeld 			wqe->CCP = fchdr.rsvd;
642582527734SSukumar Swaminathan 		}
642682527734SSukumar Swaminathan 
6427*8f23e9faSHans Rosenfeld 		/* Allocate an exchange for this command */
6428*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
6429*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_SOL_BLS_TYPE);
643082527734SSukumar Swaminathan 
6431a9800bebSGarrett D'Amore 		if (!xrip) {
643282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6433*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Unable to alloc XRI. Dropping...",
643482527734SSukumar Swaminathan 			    label);
643582527734SSukumar Swaminathan 			goto done;
643682527734SSukumar Swaminathan 		}
643782527734SSukumar Swaminathan 
6438*8f23e9faSHans Rosenfeld 		wqe->XRITag = xrip->XRI;
6439*8f23e9faSHans Rosenfeld 		wqe->Class = CLASS3;
6440*8f23e9faSHans Rosenfeld 		wqe->RequestTag = xrip->iotag;
6441*8f23e9faSHans Rosenfeld 		wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
6442*8f23e9faSHans Rosenfeld 
6443*8f23e9faSHans Rosenfeld 		sbp->ticks = hba->timer_tics + 30;
6444*8f23e9faSHans Rosenfeld 
6445*8f23e9faSHans Rosenfeld 		emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
6446*8f23e9faSHans Rosenfeld 
6447*8f23e9faSHans Rosenfeld 		/* The temporary iocbq has been freed already */
6448*8f23e9faSHans Rosenfeld 		iocbq = NULL;
6449*8f23e9faSHans Rosenfeld 
6450*8f23e9faSHans Rosenfeld 		break;
6451*8f23e9faSHans Rosenfeld 
6452*8f23e9faSHans Rosenfeld 	case 1: /* ELS */
6453*8f23e9faSHans Rosenfeld 		cmd = *((uint32_t *)seq_mp->virt);
6454*8f23e9faSHans Rosenfeld 		cmd &= ELS_CMD_MASK;
6455*8f23e9faSHans Rosenfeld 
6456*8f23e9faSHans Rosenfeld 		if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED)) {
6457*8f23e9faSHans Rosenfeld 			uint32_t dropit = 1;
6458*8f23e9faSHans Rosenfeld 
6459*8f23e9faSHans Rosenfeld 			/* Allow for P2P handshaking */
6460*8f23e9faSHans Rosenfeld 			switch (cmd) {
6461*8f23e9faSHans Rosenfeld 			case ELS_CMD_FLOGI:
6462*8f23e9faSHans Rosenfeld 				dropit = 0;
6463*8f23e9faSHans Rosenfeld 				break;
6464*8f23e9faSHans Rosenfeld 
6465*8f23e9faSHans Rosenfeld 			case ELS_CMD_PLOGI:
6466*8f23e9faSHans Rosenfeld 			case ELS_CMD_PRLI:
6467*8f23e9faSHans Rosenfeld 				if (hba->flag & FC_PT_TO_PT) {
6468*8f23e9faSHans Rosenfeld 					dropit = 0;
6469*8f23e9faSHans Rosenfeld 				}
6470*8f23e9faSHans Rosenfeld 				break;
6471*8f23e9faSHans Rosenfeld 			}
6472*8f23e9faSHans Rosenfeld 
6473*8f23e9faSHans Rosenfeld 			if (dropit) {
6474*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
6475*8f23e9faSHans Rosenfeld 				    &emlxs_sli_detail_msg,
6476*8f23e9faSHans Rosenfeld 				    "RQ ENTRY: %s: Port not yet enabled. "
6477*8f23e9faSHans Rosenfeld 				    "Dropping...",
6478*8f23e9faSHans Rosenfeld 				    label);
6479*8f23e9faSHans Rosenfeld 				goto done;
6480*8f23e9faSHans Rosenfeld 			}
6481*8f23e9faSHans Rosenfeld 		}
6482*8f23e9faSHans Rosenfeld 
6483*8f23e9faSHans Rosenfeld 		rpip = NULL;
6484*8f23e9faSHans Rosenfeld 
6485*8f23e9faSHans Rosenfeld 		if (cmd != ELS_CMD_LOGO) {
6486*8f23e9faSHans Rosenfeld 			rpip = EMLXS_NODE_TO_RPI(port, node);
6487*8f23e9faSHans Rosenfeld 		}
6488*8f23e9faSHans Rosenfeld 
6489*8f23e9faSHans Rosenfeld 		if (!rpip) {
6490*8f23e9faSHans Rosenfeld 			/* Use the fabric rpi */
6491*8f23e9faSHans Rosenfeld 			rpip = port->vpip->fabric_rpip;
6492*8f23e9faSHans Rosenfeld 		}
6493*8f23e9faSHans Rosenfeld 
6494*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6495*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_UNSOL_ELS_TYPE, fchdr.ox_id);
6496*8f23e9faSHans Rosenfeld 
6497*8f23e9faSHans Rosenfeld 		if (!xrip) {
6498*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6499*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Out of exchange "
6500*8f23e9faSHans Rosenfeld 			    "resources.  Dropping...",
6501*8f23e9faSHans Rosenfeld 			    label);
6502*8f23e9faSHans Rosenfeld 
6503*8f23e9faSHans Rosenfeld 			goto done;
6504*8f23e9faSHans Rosenfeld 		}
650582527734SSukumar Swaminathan 
650682527734SSukumar Swaminathan 		/* Build CMD_RCV_ELS64_CX */
650782527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
650882527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
650982527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
651082527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
651182527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
651282527734SSukumar Swaminathan 
651382527734SSukumar Swaminathan 		iocb->un.rcvels64.remoteID = fchdr.s_id;
651482527734SSukumar Swaminathan 		iocb->un.rcvels64.parmRo = fchdr.d_id;
651582527734SSukumar Swaminathan 
651682527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
6517a9800bebSGarrett D'Amore 		iocb->ULPCONTEXT = xrip->XRI;
651882527734SSukumar Swaminathan 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
651982527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
652082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
652182527734SSukumar Swaminathan 
6522*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6523*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
6524*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
6525*8f23e9faSHans Rosenfeld 
6526*8f23e9faSHans Rosenfeld 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6527*8f23e9faSHans Rosenfeld 			iocb->unsli3.ext_rcv.ccpe = 1;
6528*8f23e9faSHans Rosenfeld 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6529*8f23e9faSHans Rosenfeld 		}
6530*8f23e9faSHans Rosenfeld 
6531*8f23e9faSHans Rosenfeld 		if (port->mode == MODE_INITIATOR) {
6532*8f23e9faSHans Rosenfeld 			(void) emlxs_els_handle_unsol_req(port, iocbq->channel,
6533*8f23e9faSHans Rosenfeld 			    iocbq, seq_mp, seq_len);
6534*8f23e9faSHans Rosenfeld 		}
6535*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
6536*8f23e9faSHans Rosenfeld 		else if (port->mode == MODE_TARGET) {
6537*8f23e9faSHans Rosenfeld 			(void) emlxs_fct_handle_unsol_els(port, iocbq->channel,
6538*8f23e9faSHans Rosenfeld 			    iocbq, seq_mp, seq_len);
6539*8f23e9faSHans Rosenfeld 		}
6540*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
6541*8f23e9faSHans Rosenfeld 		break;
6542*8f23e9faSHans Rosenfeld 
6543*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
6544*8f23e9faSHans Rosenfeld 	case 8: /* FCT */
6545*8f23e9faSHans Rosenfeld 		if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
6546*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6547*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Port not yet enabled. "
6548*8f23e9faSHans Rosenfeld 			    "Dropping...",
6549*8f23e9faSHans Rosenfeld 			    label);
6550*8f23e9faSHans Rosenfeld 
6551*8f23e9faSHans Rosenfeld 			goto done;
6552*8f23e9faSHans Rosenfeld 		}
6553*8f23e9faSHans Rosenfeld 
6554*8f23e9faSHans Rosenfeld 		rpip = EMLXS_NODE_TO_RPI(port, node);
6555*8f23e9faSHans Rosenfeld 
6556*8f23e9faSHans Rosenfeld 		if (!rpip) {
6557*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6558*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Port not logged in. "
6559*8f23e9faSHans Rosenfeld 			    "Dropping...",
6560*8f23e9faSHans Rosenfeld 			    label);
6561*8f23e9faSHans Rosenfeld 
6562*8f23e9faSHans Rosenfeld 			goto done;
6563*8f23e9faSHans Rosenfeld 		}
6564*8f23e9faSHans Rosenfeld 
6565*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6566*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_UNSOL_FCP_TYPE, fchdr.ox_id);
6567*8f23e9faSHans Rosenfeld 
6568*8f23e9faSHans Rosenfeld 		if (!xrip) {
6569*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6570*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: Out of exchange "
6571*8f23e9faSHans Rosenfeld 			    "resources.  Dropping...",
6572*8f23e9faSHans Rosenfeld 			    label);
6573*8f23e9faSHans Rosenfeld 
6574*8f23e9faSHans Rosenfeld 			goto done;
6575*8f23e9faSHans Rosenfeld 		}
6576*8f23e9faSHans Rosenfeld 
6577*8f23e9faSHans Rosenfeld 		/* Build CMD_RCV_SEQUENCE64_CX */
6578*8f23e9faSHans Rosenfeld 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
6579*8f23e9faSHans Rosenfeld 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
6580*8f23e9faSHans Rosenfeld 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
6581*8f23e9faSHans Rosenfeld 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
6582*8f23e9faSHans Rosenfeld 		iocb->ULPBDECOUNT = 1;
6583*8f23e9faSHans Rosenfeld 
6584*8f23e9faSHans Rosenfeld 		iocb->ULPPU = 0x3;
6585*8f23e9faSHans Rosenfeld 		iocb->ULPCONTEXT = xrip->XRI;
6586*8f23e9faSHans Rosenfeld 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
6587*8f23e9faSHans Rosenfeld 		iocb->ULPCLASS = CLASS3;
6588*8f23e9faSHans Rosenfeld 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
6589*8f23e9faSHans Rosenfeld 
659082527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6591a9800bebSGarrett D'Amore 		iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
6592*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
659382527734SSukumar Swaminathan 
659482527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
659582527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
659682527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
659782527734SSukumar Swaminathan 		}
659882527734SSukumar Swaminathan 
6599*8f23e9faSHans Rosenfeld 		/* pass xrip to FCT in the iocbq */
6600*8f23e9faSHans Rosenfeld 		iocbq->sbp = xrip;
660182527734SSukumar Swaminathan 
6602*8f23e9faSHans Rosenfeld #define	EMLXS_FIX_CISCO_BUG1
6603*8f23e9faSHans Rosenfeld #ifdef EMLXS_FIX_CISCO_BUG1
6604*8f23e9faSHans Rosenfeld {
6605*8f23e9faSHans Rosenfeld uint8_t *ptr;
6606*8f23e9faSHans Rosenfeld ptr = ((uint8_t *)seq_mp->virt);
6607*8f23e9faSHans Rosenfeld if (((*ptr+12) != 0xa0) && (*(ptr+20) == 0x8) && (*(ptr+21) == 0x8)) {
6608*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6609*8f23e9faSHans Rosenfeld 	    "RQ ENTRY: Bad CDB fixed");
6610*8f23e9faSHans Rosenfeld 	*ptr++ = 0;
6611*8f23e9faSHans Rosenfeld 	*ptr = 0;
6612*8f23e9faSHans Rosenfeld }
6613*8f23e9faSHans Rosenfeld }
6614*8f23e9faSHans Rosenfeld #endif
6615*8f23e9faSHans Rosenfeld 		(void) emlxs_fct_handle_unsol_req(port, cp, iocbq,
6616*8f23e9faSHans Rosenfeld 			seq_mp, seq_len);
661782527734SSukumar Swaminathan 		break;
6618*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
661982527734SSukumar Swaminathan 
662082527734SSukumar Swaminathan 	case 0x20: /* CT */
6621*8f23e9faSHans Rosenfeld 		if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED) &&
6622*8f23e9faSHans Rosenfeld 		    !(hba->flag & FC_LOOPBACK_MODE)) {
6623a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6624a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Port not yet enabled. "
6625a9800bebSGarrett D'Amore 			    "Dropping...",
6626a9800bebSGarrett D'Amore 			    label);
6627a9800bebSGarrett D'Amore 
6628a9800bebSGarrett D'Amore 			goto done;
6629a9800bebSGarrett D'Amore 		}
663082527734SSukumar Swaminathan 
663182527734SSukumar Swaminathan 		if (!node) {
663282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6633a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Node not found (did=%x).  "
663482527734SSukumar Swaminathan 			    "Dropping...",
663582527734SSukumar Swaminathan 			    label, fchdr.d_id);
663682527734SSukumar Swaminathan 
663782527734SSukumar Swaminathan 			goto done;
663882527734SSukumar Swaminathan 		}
663982527734SSukumar Swaminathan 
6640a9800bebSGarrett D'Amore 		rpip = EMLXS_NODE_TO_RPI(port, node);
664182527734SSukumar Swaminathan 
6642a9800bebSGarrett D'Amore 		if (!rpip) {
664382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6644*8f23e9faSHans Rosenfeld 			    "RQ ENTRY: %s: RPI not found (did=%x rpi=%d).  "
664582527734SSukumar Swaminathan 			    "Dropping...",
664682527734SSukumar Swaminathan 			    label, fchdr.d_id, node->nlp_Rpi);
664782527734SSukumar Swaminathan 
664882527734SSukumar Swaminathan 			goto done;
664982527734SSukumar Swaminathan 		}
665082527734SSukumar Swaminathan 
6651*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_reserve_xri(port, rpip,
6652*8f23e9faSHans Rosenfeld 		    EMLXS_XRI_UNSOL_CT_TYPE, fchdr.ox_id);
665382527734SSukumar Swaminathan 
6654a9800bebSGarrett D'Amore 		if (!xrip) {
665582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6656a9800bebSGarrett D'Amore 			    "RQ ENTRY: %s: Out of exchange "
665782527734SSukumar Swaminathan 			    "resources.  Dropping...",
665882527734SSukumar Swaminathan 			    label);
665982527734SSukumar Swaminathan 
666082527734SSukumar Swaminathan 			goto done;
666182527734SSukumar Swaminathan 		}
666282527734SSukumar Swaminathan 
666382527734SSukumar Swaminathan 		/* Build CMD_RCV_SEQ64_CX */
666482527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
666582527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
666682527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
666782527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
666882527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
666982527734SSukumar Swaminathan 
667082527734SSukumar Swaminathan 		iocb->un.rcvseq64.xrsqRo = 0;
667182527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
667282527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
667382527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
667482527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
667582527734SSukumar Swaminathan 
667682527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
6677a9800bebSGarrett D'Amore 		iocb->ULPCONTEXT = xrip->XRI;
6678a9800bebSGarrett D'Amore 		iocb->ULPIOTAG = rpip->RPI;
667982527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
668082527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
668182527734SSukumar Swaminathan 
668282527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
6683*8f23e9faSHans Rosenfeld 		iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
668482527734SSukumar Swaminathan 
668582527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
668682527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
668782527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
668882527734SSukumar Swaminathan 		}
668982527734SSukumar Swaminathan 
669082527734SSukumar Swaminathan 		(void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
669182527734SSukumar Swaminathan 		    iocbq, seq_mp, seq_len);
669282527734SSukumar Swaminathan 
669382527734SSukumar Swaminathan 		break;
669482527734SSukumar Swaminathan 	}
669582527734SSukumar Swaminathan 
669682527734SSukumar Swaminathan 	/* Sequence handled, no need to abort */
669782527734SSukumar Swaminathan 	abort = 0;
669882527734SSukumar Swaminathan 
669982527734SSukumar Swaminathan done:
670082527734SSukumar Swaminathan 
670182527734SSukumar Swaminathan 	if (!posted) {
6702a9800bebSGarrett D'Amore 		emlxs_sli4_rq_post(port, hdr_rq->qid);
670382527734SSukumar Swaminathan 	}
670482527734SSukumar Swaminathan 
670582527734SSukumar Swaminathan 	if (abort) {
670682527734SSukumar Swaminathan 		/* Send ABTS for this exchange */
670782527734SSukumar Swaminathan 		/* !!! Currently, we have no implementation for this !!! */
670882527734SSukumar Swaminathan 		abort = 0;
670982527734SSukumar Swaminathan 	}
671082527734SSukumar Swaminathan 
671182527734SSukumar Swaminathan 	/* Return memory resources to pools */
671282527734SSukumar Swaminathan 	if (iocbq) {
671382527734SSukumar Swaminathan 		if (iocbq->bp) {
6714a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, buf_type, (void *)iocbq->bp);
6715*8f23e9faSHans Rosenfeld 			iocbq->bp = 0;
671682527734SSukumar Swaminathan 		}
671782527734SSukumar Swaminathan 
6718a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
671982527734SSukumar Swaminathan 	}
672082527734SSukumar Swaminathan 
6721b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
6722b3660a96SSukumar Swaminathan 	if (emlxs_fm_check_dma_handle(hba,
6723b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.dma_handle)
6724b3660a96SSukumar Swaminathan 	    != DDI_FM_OK) {
6725b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
6726b3660a96SSukumar Swaminathan 		    &emlxs_invalid_dma_handle_msg,
6727*8f23e9faSHans Rosenfeld 		    "sli4_process_unsol_rcv: hdl=%p",
6728b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.dma_handle);
6729b3660a96SSukumar Swaminathan 
6730b3660a96SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_restart_thread,
6731a9800bebSGarrett D'Amore 		    0, 0);
6732b3660a96SSukumar Swaminathan 	}
6733b3660a96SSukumar Swaminathan #endif
673482527734SSukumar Swaminathan 	return;
673582527734SSukumar Swaminathan 
673682527734SSukumar Swaminathan } /* emlxs_sli4_process_unsol_rcv() */
673782527734SSukumar Swaminathan 
673882527734SSukumar Swaminathan 
673982527734SSukumar Swaminathan /*ARGSUSED*/
674082527734SSukumar Swaminathan static void
674182527734SSukumar Swaminathan emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
674282527734SSukumar Swaminathan     CQE_XRI_Abort_t *cqe)
674382527734SSukumar Swaminathan {
674482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6745a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
6746a9800bebSGarrett D'Amore 
6747a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
674882527734SSukumar Swaminathan 
6749*8f23e9faSHans Rosenfeld 	xrip = emlxs_sli4_find_xri(port, cqe->XRI);
6750a9800bebSGarrett D'Amore 	if (xrip == NULL) {
6751*8f23e9faSHans Rosenfeld 		/* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, */
6752*8f23e9faSHans Rosenfeld 		/*    "CQ ENTRY: process xri aborted ignored");  */
6753a9800bebSGarrett D'Amore 
6754a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
675582527734SSukumar Swaminathan 		return;
675682527734SSukumar Swaminathan 	}
675782527734SSukumar Swaminathan 
675882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6759*8f23e9faSHans Rosenfeld 	    "CQ ENTRY: XRI Aborted: xri=%d IA=%d EO=%d BR=%d",
676082527734SSukumar Swaminathan 	    cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
676182527734SSukumar Swaminathan 
6762*8f23e9faSHans Rosenfeld 	if (!(xrip->flag & EMLXS_XRI_BUSY)) {
676382527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6764*8f23e9faSHans Rosenfeld 		    "CQ ENTRY: XRI Aborted: xri=%d flag=%x. Bad state.",
6765*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->flag);
6766a9800bebSGarrett D'Amore 
6767a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
676882527734SSukumar Swaminathan 		return;
676982527734SSukumar Swaminathan 	}
677082527734SSukumar Swaminathan 
677182527734SSukumar Swaminathan 	/* Exchange is no longer busy on-chip, free it */
6772*8f23e9faSHans Rosenfeld 	emlxs_sli4_free_xri(port, 0, xrip, 0);
6773a9800bebSGarrett D'Amore 
6774a9800bebSGarrett D'Amore 	mutex_exit(&EMLXS_FCTAB_LOCK);
6775a9800bebSGarrett D'Amore 
6776a9800bebSGarrett D'Amore 	return;
677782527734SSukumar Swaminathan 
677882527734SSukumar Swaminathan } /* emlxs_sli4_process_xri_aborted () */
677982527734SSukumar Swaminathan 
678082527734SSukumar Swaminathan 
678182527734SSukumar Swaminathan /*ARGSUSED*/
678282527734SSukumar Swaminathan static void
678382527734SSukumar Swaminathan emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
678482527734SSukumar Swaminathan {
678582527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
678682527734SSukumar Swaminathan 	CQE_u *cqe;
678782527734SSukumar Swaminathan 	CQE_u cq_entry;
678882527734SSukumar Swaminathan 	uint32_t cqdb;
678982527734SSukumar Swaminathan 	int num_entries = 0;
6790b3660a96SSukumar Swaminathan 	off_t offset;
679182527734SSukumar Swaminathan 
679282527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
679382527734SSukumar Swaminathan 
679482527734SSukumar Swaminathan 	cqe = (CQE_u *)cq->addr.virt;
679582527734SSukumar Swaminathan 	cqe += cq->host_index;
679682527734SSukumar Swaminathan 
6797b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
6798b3660a96SSukumar Swaminathan 	    cq->addr.virt) -
6799b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
6800b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
6801b3660a96SSukumar Swaminathan 
6802b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset,
680382527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
680482527734SSukumar Swaminathan 
680582527734SSukumar Swaminathan 	for (;;) {
680682527734SSukumar Swaminathan 		cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
6807*8f23e9faSHans Rosenfeld 		if (!(cq_entry.word[3] & CQE_VALID)) {
680882527734SSukumar Swaminathan 			break;
6809*8f23e9faSHans Rosenfeld 		}
681082527734SSukumar Swaminathan 
681182527734SSukumar Swaminathan 		cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
681282527734SSukumar Swaminathan 		cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
681382527734SSukumar Swaminathan 		cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
681482527734SSukumar Swaminathan 
6815*8f23e9faSHans Rosenfeld #ifdef	DEBUG_CQE
6816*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 6, 0);
6817*8f23e9faSHans Rosenfeld #endif /* DEBUG_CQE */
681882527734SSukumar Swaminathan 		num_entries++;
681982527734SSukumar Swaminathan 		cqe->word[3] = 0;
682082527734SSukumar Swaminathan 
682182527734SSukumar Swaminathan 		cq->host_index++;
682282527734SSukumar Swaminathan 		if (cq->host_index >= cq->max_index) {
682382527734SSukumar Swaminathan 			cq->host_index = 0;
682482527734SSukumar Swaminathan 			cqe = (CQE_u *)cq->addr.virt;
682582527734SSukumar Swaminathan 		} else {
682682527734SSukumar Swaminathan 			cqe++;
682782527734SSukumar Swaminathan 		}
682882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
682982527734SSukumar Swaminathan 
683082527734SSukumar Swaminathan 		/* Now handle specific cq type */
683182527734SSukumar Swaminathan 		if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
683282527734SSukumar Swaminathan 			if (cq_entry.cqAsyncEntry.async_evt) {
683382527734SSukumar Swaminathan 				emlxs_sli4_process_async_event(hba,
683482527734SSukumar Swaminathan 				    (CQE_ASYNC_t *)&cq_entry);
683582527734SSukumar Swaminathan 			} else {
683682527734SSukumar Swaminathan 				emlxs_sli4_process_mbox_event(hba,
683782527734SSukumar Swaminathan 				    (CQE_MBOX_t *)&cq_entry);
683882527734SSukumar Swaminathan 			}
683982527734SSukumar Swaminathan 		} else { /* EMLXS_CQ_TYPE_GROUP2 */
684082527734SSukumar Swaminathan 			switch (cq_entry.cqCmplEntry.Code) {
684182527734SSukumar Swaminathan 			case CQE_TYPE_WQ_COMPLETION:
684282527734SSukumar Swaminathan 				if (cq_entry.cqCmplEntry.RequestTag <
684382527734SSukumar Swaminathan 				    hba->max_iotag) {
684482527734SSukumar Swaminathan 					emlxs_sli4_process_wqe_cmpl(hba, cq,
684582527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
684682527734SSukumar Swaminathan 				} else {
684782527734SSukumar Swaminathan 					emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
684882527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
684982527734SSukumar Swaminathan 				}
685082527734SSukumar Swaminathan 				break;
685182527734SSukumar Swaminathan 			case CQE_TYPE_RELEASE_WQE:
685282527734SSukumar Swaminathan 				emlxs_sli4_process_release_wqe(hba, cq,
685382527734SSukumar Swaminathan 				    (CQE_RelWQ_t *)&cq_entry);
685482527734SSukumar Swaminathan 				break;
685582527734SSukumar Swaminathan 			case CQE_TYPE_UNSOL_RCV:
6856*8f23e9faSHans Rosenfeld 			case CQE_TYPE_UNSOL_RCV_V1:
685782527734SSukumar Swaminathan 				emlxs_sli4_process_unsol_rcv(hba, cq,
685882527734SSukumar Swaminathan 				    (CQE_UnsolRcv_t *)&cq_entry);
685982527734SSukumar Swaminathan 				break;
686082527734SSukumar Swaminathan 			case CQE_TYPE_XRI_ABORTED:
686182527734SSukumar Swaminathan 				emlxs_sli4_process_xri_aborted(hba, cq,
686282527734SSukumar Swaminathan 				    (CQE_XRI_Abort_t *)&cq_entry);
686382527734SSukumar Swaminathan 				break;
686482527734SSukumar Swaminathan 			default:
686582527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
686682527734SSukumar Swaminathan 				    "Invalid CQ entry %d: %08x %08x %08x %08x",
686782527734SSukumar Swaminathan 				    cq_entry.cqCmplEntry.Code, cq_entry.word[0],
686882527734SSukumar Swaminathan 				    cq_entry.word[1], cq_entry.word[2],
686982527734SSukumar Swaminathan 				    cq_entry.word[3]);
687082527734SSukumar Swaminathan 				break;
687182527734SSukumar Swaminathan 			}
687282527734SSukumar Swaminathan 		}
687382527734SSukumar Swaminathan 
687482527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
687582527734SSukumar Swaminathan 	}
687682527734SSukumar Swaminathan 
6877*8f23e9faSHans Rosenfeld 	/* Number of times this routine gets called for this CQ */
6878*8f23e9faSHans Rosenfeld 	cq->isr_count++;
6879*8f23e9faSHans Rosenfeld 
6880*8f23e9faSHans Rosenfeld 	/* num_entries is the number of CQEs we process in this specific CQ */
6881*8f23e9faSHans Rosenfeld 	cq->num_proc += num_entries;
6882*8f23e9faSHans Rosenfeld 	if (cq->max_proc < num_entries)
6883*8f23e9faSHans Rosenfeld 		cq->max_proc = num_entries;
6884*8f23e9faSHans Rosenfeld 
688582527734SSukumar Swaminathan 	cqdb = cq->qid;
688682527734SSukumar Swaminathan 	cqdb |= CQ_DB_REARM;
688782527734SSukumar Swaminathan 	if (num_entries != 0) {
688882527734SSukumar Swaminathan 		cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
688982527734SSukumar Swaminathan 	}
689082527734SSukumar Swaminathan 
6891*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
689282527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6893*8f23e9faSHans Rosenfeld 	    "CQE: CLEAR cqdb=%08x: pops=%d", cqdb, num_entries);
6894*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
689582527734SSukumar Swaminathan 
6896*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_cqdb(hba, cqdb);
689782527734SSukumar Swaminathan 
689882527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
689982527734SSukumar Swaminathan 
690082527734SSukumar Swaminathan } /* emlxs_sli4_process_cq() */
690182527734SSukumar Swaminathan 
690282527734SSukumar Swaminathan 
690382527734SSukumar Swaminathan /*ARGSUSED*/
690482527734SSukumar Swaminathan static void
690582527734SSukumar Swaminathan emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
690682527734SSukumar Swaminathan {
690782527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
690882527734SSukumar Swaminathan 	uint32_t eqdb;
690982527734SSukumar Swaminathan 	uint32_t *ptr;
691082527734SSukumar Swaminathan 	CHANNEL *cp;
691182527734SSukumar Swaminathan 	EQE_u eqe;
691282527734SSukumar Swaminathan 	uint32_t i;
6913*8f23e9faSHans Rosenfeld 	uint16_t cqi;
691482527734SSukumar Swaminathan 	int num_entries = 0;
6915b3660a96SSukumar Swaminathan 	off_t offset;
691682527734SSukumar Swaminathan 
691782527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
691882527734SSukumar Swaminathan 
6919*8f23e9faSHans Rosenfeld 	hba->intr_busy_cnt ++;
6920*8f23e9faSHans Rosenfeld 
692182527734SSukumar Swaminathan 	ptr = eq->addr.virt;
692282527734SSukumar Swaminathan 	ptr += eq->host_index;
692382527734SSukumar Swaminathan 
6924b3660a96SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)
6925b3660a96SSukumar Swaminathan 	    eq->addr.virt) -
6926b3660a96SSukumar Swaminathan 	    (uint64_t)((unsigned long)
6927b3660a96SSukumar Swaminathan 	    hba->sli.sli4.slim2.virt));
6928b3660a96SSukumar Swaminathan 
6929b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
693082527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
693182527734SSukumar Swaminathan 
693282527734SSukumar Swaminathan 	for (;;) {
693382527734SSukumar Swaminathan 		eqe.word = *ptr;
693482527734SSukumar Swaminathan 		eqe.word = BE_SWAP32(eqe.word);
693582527734SSukumar Swaminathan 
6936*8f23e9faSHans Rosenfeld 		if (!(eqe.word & EQE_VALID)) {
693782527734SSukumar Swaminathan 			break;
6938*8f23e9faSHans Rosenfeld 		}
693982527734SSukumar Swaminathan 
6940*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
694182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6942*8f23e9faSHans Rosenfeld 		    "EQE00: %08x", eqe.word);
6943*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
694482527734SSukumar Swaminathan 
694582527734SSukumar Swaminathan 		*ptr = 0;
694682527734SSukumar Swaminathan 		num_entries++;
694782527734SSukumar Swaminathan 		eq->host_index++;
694882527734SSukumar Swaminathan 		if (eq->host_index >= eq->max_index) {
694982527734SSukumar Swaminathan 			eq->host_index = 0;
695082527734SSukumar Swaminathan 			ptr = eq->addr.virt;
695182527734SSukumar Swaminathan 		} else {
695282527734SSukumar Swaminathan 			ptr++;
695382527734SSukumar Swaminathan 		}
695482527734SSukumar Swaminathan 
6955*8f23e9faSHans Rosenfeld 		cqi = emlxs_sli4_cqid_to_index(hba, eqe.entry.CQId);
6956*8f23e9faSHans Rosenfeld 
6957*8f23e9faSHans Rosenfeld 		/* Verify CQ index */
6958*8f23e9faSHans Rosenfeld 		if (cqi == 0xffff) {
6959*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6960*8f23e9faSHans Rosenfeld 			    "EQE: Invalid CQid: %d. Dropping...",
6961*8f23e9faSHans Rosenfeld 			    eqe.entry.CQId);
6962*8f23e9faSHans Rosenfeld 			continue;
6963*8f23e9faSHans Rosenfeld 		}
696482527734SSukumar Swaminathan 
6965*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
696682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6967*8f23e9faSHans Rosenfeld 		    "EQE: CQIndex:%x cqid:%x", cqi, eqe.entry.CQId);
6968*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
6969*8f23e9faSHans Rosenfeld 
6970*8f23e9faSHans Rosenfeld 		emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[cqi]);
6971*8f23e9faSHans Rosenfeld 	}
697282527734SSukumar Swaminathan 
6973*8f23e9faSHans Rosenfeld 	/* Number of times the ISR for this EQ gets called */
6974*8f23e9faSHans Rosenfeld 	eq->isr_count++;
6975*8f23e9faSHans Rosenfeld 
6976*8f23e9faSHans Rosenfeld 	/* num_entries is the number of EQEs we process in this specific ISR */
6977*8f23e9faSHans Rosenfeld 	eq->num_proc += num_entries;
6978*8f23e9faSHans Rosenfeld 	if (eq->max_proc < num_entries) {
6979*8f23e9faSHans Rosenfeld 		eq->max_proc = num_entries;
698082527734SSukumar Swaminathan 	}
698182527734SSukumar Swaminathan 
698282527734SSukumar Swaminathan 	eqdb = eq->qid;
698382527734SSukumar Swaminathan 	eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
698482527734SSukumar Swaminathan 
6985*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
698682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6987*8f23e9faSHans Rosenfeld 	    "EQE: CLEAR eqdb=%08x pops=%d", eqdb, num_entries);
6988*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
698982527734SSukumar Swaminathan 
699082527734SSukumar Swaminathan 	if (num_entries != 0) {
699182527734SSukumar Swaminathan 		eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
699282527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
699382527734SSukumar Swaminathan 			cp = &hba->chan[i];
699482527734SSukumar Swaminathan 			if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
699582527734SSukumar Swaminathan 				cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
699682527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
699782527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
699882527734SSukumar Swaminathan 			}
699982527734SSukumar Swaminathan 		}
700082527734SSukumar Swaminathan 	}
700182527734SSukumar Swaminathan 
7002*8f23e9faSHans Rosenfeld 	emlxs_sli4_write_cqdb(hba, eqdb);
700382527734SSukumar Swaminathan 
700482527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
700582527734SSukumar Swaminathan 
7006*8f23e9faSHans Rosenfeld 	hba->intr_busy_cnt --;
7007*8f23e9faSHans Rosenfeld 
700882527734SSukumar Swaminathan } /* emlxs_sli4_process_eq() */
700982527734SSukumar Swaminathan 
701082527734SSukumar Swaminathan 
701182527734SSukumar Swaminathan #ifdef MSI_SUPPORT
701282527734SSukumar Swaminathan /*ARGSUSED*/
701382527734SSukumar Swaminathan static uint32_t
701482527734SSukumar Swaminathan emlxs_sli4_msi_intr(char *arg1, char *arg2)
701582527734SSukumar Swaminathan {
701682527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
7017*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
701882527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
7019*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
702082527734SSukumar Swaminathan 	uint16_t msgid;
702182527734SSukumar Swaminathan 	int rc;
702282527734SSukumar Swaminathan 
7023*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
702482527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
702582527734SSukumar Swaminathan 	    "msiINTR arg1:%p arg2:%p", arg1, arg2);
7026*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
702782527734SSukumar Swaminathan 
702882527734SSukumar Swaminathan 	/* Check for legacy interrupt handling */
702982527734SSukumar Swaminathan 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
703082527734SSukumar Swaminathan 		rc = emlxs_sli4_intx_intr(arg1);
703182527734SSukumar Swaminathan 		return (rc);
703282527734SSukumar Swaminathan 	}
703382527734SSukumar Swaminathan 
703482527734SSukumar Swaminathan 	/* Get MSI message id */
703582527734SSukumar Swaminathan 	msgid = (uint16_t)((unsigned long)arg2);
703682527734SSukumar Swaminathan 
703782527734SSukumar Swaminathan 	/* Validate the message id */
703882527734SSukumar Swaminathan 	if (msgid >= hba->intr_count) {
703982527734SSukumar Swaminathan 		msgid = 0;
704082527734SSukumar Swaminathan 	}
704182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
704282527734SSukumar Swaminathan 
7043bce54adfSSukumar Swaminathan 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
704482527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
704582527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
704682527734SSukumar Swaminathan 	}
704782527734SSukumar Swaminathan 
704882527734SSukumar Swaminathan 	/* The eq[] index == the MSI vector number */
704982527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
705082527734SSukumar Swaminathan 
705182527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
705282527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
705382527734SSukumar Swaminathan 
705482527734SSukumar Swaminathan } /* emlxs_sli4_msi_intr() */
705582527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
705682527734SSukumar Swaminathan 
705782527734SSukumar Swaminathan 
705882527734SSukumar Swaminathan /*ARGSUSED*/
705982527734SSukumar Swaminathan static int
706082527734SSukumar Swaminathan emlxs_sli4_intx_intr(char *arg)
706182527734SSukumar Swaminathan {
706282527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
7063*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
706482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
7065*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
706682527734SSukumar Swaminathan 
7067*8f23e9faSHans Rosenfeld #ifdef DEBUG_FASTPATH
706882527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
706982527734SSukumar Swaminathan 	    "intxINTR arg:%p", arg);
7070*8f23e9faSHans Rosenfeld #endif /* DEBUG_FASTPATH */
707182527734SSukumar Swaminathan 
707282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
707382527734SSukumar Swaminathan 
7074bce54adfSSukumar Swaminathan 	if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
707582527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
707682527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
707782527734SSukumar Swaminathan 	}
707882527734SSukumar Swaminathan 
707982527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
708082527734SSukumar Swaminathan 
708182527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
708282527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
708382527734SSukumar Swaminathan } /* emlxs_sli4_intx_intr() */
708482527734SSukumar Swaminathan 
708582527734SSukumar Swaminathan 
708682527734SSukumar Swaminathan static void
708782527734SSukumar Swaminathan emlxs_sli4_hba_kill(emlxs_hba_t *hba)
708882527734SSukumar Swaminathan {
708982527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
709082527734SSukumar Swaminathan 	uint32_t j;
709182527734SSukumar Swaminathan 
709282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
709382527734SSukumar Swaminathan 	if (hba->flag & FC_INTERLOCKED) {
709482527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
709582527734SSukumar Swaminathan 
709682527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
709782527734SSukumar Swaminathan 
709882527734SSukumar Swaminathan 		return;
709982527734SSukumar Swaminathan 	}
710082527734SSukumar Swaminathan 
710182527734SSukumar Swaminathan 	j = 0;
710282527734SSukumar Swaminathan 	while (j++ < 10000) {
7103*8f23e9faSHans Rosenfeld 		if ((hba->mbox_queue_flag == 0) &&
7104*8f23e9faSHans Rosenfeld 		    (hba->intr_busy_cnt == 0)) {
710582527734SSukumar Swaminathan 			break;
710682527734SSukumar Swaminathan 		}
710782527734SSukumar Swaminathan 
710882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
7109*8f23e9faSHans Rosenfeld 		BUSYWAIT_US(100);
711082527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
711182527734SSukumar Swaminathan 	}
711282527734SSukumar Swaminathan 
7113*8f23e9faSHans Rosenfeld 	if ((hba->mbox_queue_flag != 0) || (hba->intr_busy_cnt > 0)) {
711482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
7115*8f23e9faSHans Rosenfeld 		    "Board kill failed. Adapter busy, %d, %d.",
7116*8f23e9faSHans Rosenfeld 		    hba->mbox_queue_flag, hba->intr_busy_cnt);
711782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
711882527734SSukumar Swaminathan 		return;
711982527734SSukumar Swaminathan 	}
712082527734SSukumar Swaminathan 
712182527734SSukumar Swaminathan 	hba->flag |= FC_INTERLOCKED;
712282527734SSukumar Swaminathan 
712382527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
712482527734SSukumar Swaminathan 
712582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
712682527734SSukumar Swaminathan 
712782527734SSukumar Swaminathan } /* emlxs_sli4_hba_kill() */
712882527734SSukumar Swaminathan 
712982527734SSukumar Swaminathan 
7130*8f23e9faSHans Rosenfeld extern void
7131*8f23e9faSHans Rosenfeld emlxs_sli4_hba_reset_all(emlxs_hba_t *hba, uint32_t flag)
7132*8f23e9faSHans Rosenfeld {
7133*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
7134*8f23e9faSHans Rosenfeld 	uint32_t value;
7135*8f23e9faSHans Rosenfeld 
7136*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_PORT_LOCK);
7137*8f23e9faSHans Rosenfeld 
7138*8f23e9faSHans Rosenfeld 	if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) != SLI_INTF_IF_TYPE_2) {
7139*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7140*8f23e9faSHans Rosenfeld 		    "Reset All failed. Invalid Operation.");
7141*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
7142*8f23e9faSHans Rosenfeld 		return;
7143*8f23e9faSHans Rosenfeld 	}
7144*8f23e9faSHans Rosenfeld 
7145*8f23e9faSHans Rosenfeld 	/* Issue a Firmware Reset All Request */
7146*8f23e9faSHans Rosenfeld 	if (flag) {
7147*8f23e9faSHans Rosenfeld 		value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL | SLI_PHYDEV_DD;
7148*8f23e9faSHans Rosenfeld 	} else {
7149*8f23e9faSHans Rosenfeld 		value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL;
7150*8f23e9faSHans Rosenfeld 	}
7151*8f23e9faSHans Rosenfeld 
7152*8f23e9faSHans Rosenfeld 	ddi_put32(hba->sli.sli4.bar0_acc_handle,
7153*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.PHYSDEV_reg_addr, value);
7154*8f23e9faSHans Rosenfeld 
7155*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_PORT_LOCK);
7156*8f23e9faSHans Rosenfeld 
7157*8f23e9faSHans Rosenfeld } /* emlxs_sli4_hba_reset_all() */
7158*8f23e9faSHans Rosenfeld 
7159*8f23e9faSHans Rosenfeld 
716082527734SSukumar Swaminathan static void
716182527734SSukumar Swaminathan emlxs_sli4_enable_intr(emlxs_hba_t *hba)
716282527734SSukumar Swaminathan {
716382527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
716482527734SSukumar Swaminathan 	int i;
716582527734SSukumar Swaminathan 	int num_cq;
716682527734SSukumar Swaminathan 	uint32_t data;
716782527734SSukumar Swaminathan 
716882527734SSukumar Swaminathan 	hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
716982527734SSukumar Swaminathan 
717082527734SSukumar Swaminathan 	num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
717182527734SSukumar Swaminathan 	    EMLXS_CQ_OFFSET_WQ;
717282527734SSukumar Swaminathan 
717382527734SSukumar Swaminathan 	/* ARM EQ / CQs */
717482527734SSukumar Swaminathan 	for (i = 0; i < num_cq; i++) {
717582527734SSukumar Swaminathan 		data = hba->sli.sli4.cq[i].qid;
717682527734SSukumar Swaminathan 		data |= CQ_DB_REARM;
7177*8f23e9faSHans Rosenfeld 		emlxs_sli4_write_cqdb(hba, data);
717882527734SSukumar Swaminathan 	}
717982527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
718082527734SSukumar Swaminathan 		data = hba->sli.sli4.eq[i].qid;
718182527734SSukumar Swaminathan 		data |= (EQ_DB_REARM | EQ_DB_EVENT);
7182*8f23e9faSHans Rosenfeld 		emlxs_sli4_write_cqdb(hba, data);
718382527734SSukumar Swaminathan 	}
718482527734SSukumar Swaminathan } /* emlxs_sli4_enable_intr() */
718582527734SSukumar Swaminathan 
718682527734SSukumar Swaminathan 
718782527734SSukumar Swaminathan static void
718882527734SSukumar Swaminathan emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
718982527734SSukumar Swaminathan {
719082527734SSukumar Swaminathan 	if (att) {
719182527734SSukumar Swaminathan 		return;
719282527734SSukumar Swaminathan 	}
719382527734SSukumar Swaminathan 
719482527734SSukumar Swaminathan 	hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
719582527734SSukumar Swaminathan 
719682527734SSukumar Swaminathan 	/* Short of reset, we cannot disable interrupts */
719782527734SSukumar Swaminathan } /* emlxs_sli4_disable_intr() */
719882527734SSukumar Swaminathan 
719982527734SSukumar Swaminathan 
720082527734SSukumar Swaminathan static void
720182527734SSukumar Swaminathan emlxs_sli4_resource_free(emlxs_hba_t *hba)
720282527734SSukumar Swaminathan {
720382527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
720482527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
720582527734SSukumar Swaminathan 	uint32_t	i;
720682527734SSukumar Swaminathan 
7207*8f23e9faSHans Rosenfeld 	buf_info = &hba->sli.sli4.slim2;
7208*8f23e9faSHans Rosenfeld 	if (buf_info->virt == 0) {
7209*8f23e9faSHans Rosenfeld 		/* Already free */
7210*8f23e9faSHans Rosenfeld 		return;
7211*8f23e9faSHans Rosenfeld 	}
7212*8f23e9faSHans Rosenfeld 
7213a9800bebSGarrett D'Amore 	emlxs_fcf_fini(hba);
721482527734SSukumar Swaminathan 
721582527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.HeaderTmplate;
721682527734SSukumar Swaminathan 	if (buf_info->virt) {
721782527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
721882527734SSukumar Swaminathan 	}
721982527734SSukumar Swaminathan 
722082527734SSukumar Swaminathan 	if (hba->sli.sli4.XRIp) {
722182527734SSukumar Swaminathan 		if ((hba->sli.sli4.XRIinuse_f !=
722282527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
722382527734SSukumar Swaminathan 		    (hba->sli.sli4.XRIinuse_b !=
722482527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
7225a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7226*8f23e9faSHans Rosenfeld 			    "XRIs in use during free!: %p %p != %p\n",
722782527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_f,
722882527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_b,
722982527734SSukumar Swaminathan 			    &hba->sli.sli4.XRIinuse_f);
723082527734SSukumar Swaminathan 		}
723182527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.XRIp,
723282527734SSukumar Swaminathan 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
723382527734SSukumar Swaminathan 		hba->sli.sli4.XRIp = NULL;
7234b3660a96SSukumar Swaminathan 
7235b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_f =
7236b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7237b3660a96SSukumar Swaminathan 		hba->sli.sli4.XRIfree_b =
7238b3660a96SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
723982527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count = 0;
724082527734SSukumar Swaminathan 	}
724182527734SSukumar Swaminathan 
7242*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->intr_count; i++) {
7243b3660a96SSukumar Swaminathan 		mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
724482527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7245*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].qid = 0xffff;
724682527734SSukumar Swaminathan 	}
724782527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQS; i++) {
724882527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7249*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].qid = 0xffff;
725082527734SSukumar Swaminathan 	}
725182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQS; i++) {
725282527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
7253*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].qid = 0xffff;
725482527734SSukumar Swaminathan 	}
7255*8f23e9faSHans Rosenfeld 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
7256b3660a96SSukumar Swaminathan 		mutex_destroy(&hba->sli.sli4.rxq[i].lock);
7257b3660a96SSukumar Swaminathan 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
7258*8f23e9faSHans Rosenfeld 	}
7259*8f23e9faSHans Rosenfeld 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7260*8f23e9faSHans Rosenfeld 		mutex_destroy(&hba->sli.sli4.rq[i].lock);
726182527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7262*8f23e9faSHans Rosenfeld 		hba->sli.sli4.rq[i].qid = 0xffff;
726382527734SSukumar Swaminathan 	}
726482527734SSukumar Swaminathan 
726582527734SSukumar Swaminathan 	/* Free the MQ */
7266b3660a96SSukumar Swaminathan 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7267b3660a96SSukumar Swaminathan 
7268b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.slim2;
7269b3660a96SSukumar Swaminathan 	if (buf_info->virt) {
727082527734SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
727182527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
7272b3660a96SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
727382527734SSukumar Swaminathan 	}
727482527734SSukumar Swaminathan 
727582527734SSukumar Swaminathan } /* emlxs_sli4_resource_free() */
727682527734SSukumar Swaminathan 
727782527734SSukumar Swaminathan 
727882527734SSukumar Swaminathan static int
727982527734SSukumar Swaminathan emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
728082527734SSukumar Swaminathan {
728182527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
728282527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
728382527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
728482527734SSukumar Swaminathan 	int		num_eq;
728582527734SSukumar Swaminathan 	int		num_wq;
7286a9800bebSGarrett D'Amore 	uint16_t	i;
728782527734SSukumar Swaminathan 	uint32_t	j;
728882527734SSukumar Swaminathan 	uint32_t	k;
7289*8f23e9faSHans Rosenfeld 	uint16_t	cq_depth;
7290*8f23e9faSHans Rosenfeld 	uint32_t	cq_size;
729182527734SSukumar Swaminathan 	uint32_t	word;
7292a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
729382527734SSukumar Swaminathan 	RQE_t		*rqe;
7294b3660a96SSukumar Swaminathan 	MBUF_INFO	*rqb;
7295b3660a96SSukumar Swaminathan 	uint64_t	phys;
7296b3660a96SSukumar Swaminathan 	uint64_t	tmp_phys;
7297b3660a96SSukumar Swaminathan 	char		*virt;
7298b3660a96SSukumar Swaminathan 	char		*tmp_virt;
7299b3660a96SSukumar Swaminathan 	void		*data_handle;
7300b3660a96SSukumar Swaminathan 	void		*dma_handle;
7301b3660a96SSukumar Swaminathan 	int32_t		size;
7302b3660a96SSukumar Swaminathan 	off_t		offset;
7303b3660a96SSukumar Swaminathan 	uint32_t	count = 0;
7304*8f23e9faSHans Rosenfeld 	uint32_t	hddr_size = 0;
7305*8f23e9faSHans Rosenfeld 	uint32_t	align;
7306*8f23e9faSHans Rosenfeld 	uint32_t	iotag;
7307*8f23e9faSHans Rosenfeld 
7308*8f23e9faSHans Rosenfeld 	buf_info = &hba->sli.sli4.slim2;
7309*8f23e9faSHans Rosenfeld 	if (buf_info->virt) {
7310*8f23e9faSHans Rosenfeld 		/* Already allocated */
7311*8f23e9faSHans Rosenfeld 		return (0);
7312*8f23e9faSHans Rosenfeld 	}
731382527734SSukumar Swaminathan 
7314a9800bebSGarrett D'Amore 	emlxs_fcf_init(hba);
731582527734SSukumar Swaminathan 
7316*8f23e9faSHans Rosenfeld 	switch (hba->sli.sli4.param.CQV) {
7317*8f23e9faSHans Rosenfeld 	case 0:
7318*8f23e9faSHans Rosenfeld 		cq_depth = CQ_DEPTH;
7319*8f23e9faSHans Rosenfeld 		break;
7320*8f23e9faSHans Rosenfeld 	case 2:
7321*8f23e9faSHans Rosenfeld 	default:
7322*8f23e9faSHans Rosenfeld 		cq_depth = CQ_DEPTH_V2;
7323*8f23e9faSHans Rosenfeld 		break;
7324*8f23e9faSHans Rosenfeld 	}
7325*8f23e9faSHans Rosenfeld 	cq_size = (cq_depth * CQE_SIZE);
7326*8f23e9faSHans Rosenfeld 
7327b3660a96SSukumar Swaminathan 	/* EQs - 1 per Interrupt vector */
7328b3660a96SSukumar Swaminathan 	num_eq = hba->intr_count;
7329*8f23e9faSHans Rosenfeld 
7330b3660a96SSukumar Swaminathan 	/* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
7331b3660a96SSukumar Swaminathan 	num_wq = cfg[CFG_NUM_WQ].current * num_eq;
733282527734SSukumar Swaminathan 
7333b3660a96SSukumar Swaminathan 	/* Calculate total dmable memory we need */
7334*8f23e9faSHans Rosenfeld 	/* WARNING: make sure each section is aligned on 4K boundary */
7335*8f23e9faSHans Rosenfeld 
7336b3660a96SSukumar Swaminathan 	/* EQ */
7337b3660a96SSukumar Swaminathan 	count += num_eq * 4096;
7338*8f23e9faSHans Rosenfeld 
7339b3660a96SSukumar Swaminathan 	/* CQ */
7340*8f23e9faSHans Rosenfeld 	count += (num_wq + EMLXS_CQ_OFFSET_WQ) * cq_size;
7341*8f23e9faSHans Rosenfeld 
7342b3660a96SSukumar Swaminathan 	/* WQ */
7343b3660a96SSukumar Swaminathan 	count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES);
7344*8f23e9faSHans Rosenfeld 
7345b3660a96SSukumar Swaminathan 	/* MQ */
7346b3660a96SSukumar Swaminathan 	count +=  EMLXS_MAX_MQS * 4096;
7347*8f23e9faSHans Rosenfeld 
7348b3660a96SSukumar Swaminathan 	/* RQ */
7349b3660a96SSukumar Swaminathan 	count +=  EMLXS_MAX_RQS * 4096;
7350*8f23e9faSHans Rosenfeld 
7351b3660a96SSukumar Swaminathan 	/* RQB/E */
7352b3660a96SSukumar Swaminathan 	count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
7353*8f23e9faSHans Rosenfeld 	count += (4096 - (count%4096)); /* Ensure 4K alignment */
7354*8f23e9faSHans Rosenfeld 
7355b3660a96SSukumar Swaminathan 	/* SGL */
7356*8f23e9faSHans Rosenfeld 	count += hba->sli.sli4.XRIExtSize * hba->sli.sli4.mem_sgl_size;
7357*8f23e9faSHans Rosenfeld 	count += (4096 - (count%4096)); /* Ensure 4K alignment */
7358*8f23e9faSHans Rosenfeld 
7359*8f23e9faSHans Rosenfeld 	/* RPI Header Templates */
7360*8f23e9faSHans Rosenfeld 	if (hba->sli.sli4.param.HDRR) {
7361*8f23e9faSHans Rosenfeld 		/* Bytes per extent */
7362*8f23e9faSHans Rosenfeld 		j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
7363*8f23e9faSHans Rosenfeld 
7364*8f23e9faSHans Rosenfeld 		/* Pages required per extent (page == 4096 bytes) */
7365*8f23e9faSHans Rosenfeld 		k = (j/4096) + ((j%4096)? 1:0);
7366*8f23e9faSHans Rosenfeld 
7367*8f23e9faSHans Rosenfeld 		/* Total size */
7368*8f23e9faSHans Rosenfeld 		hddr_size = (k * hba->sli.sli4.RPIExtCount * 4096);
7369*8f23e9faSHans Rosenfeld 
7370*8f23e9faSHans Rosenfeld 		count += hddr_size;
7371*8f23e9faSHans Rosenfeld 	}
7372b3660a96SSukumar Swaminathan 
7373b3660a96SSukumar Swaminathan 	/* Allocate slim2 for SLI4 */
7374b3660a96SSukumar Swaminathan 	buf_info = &hba->sli.sli4.slim2;
7375b3660a96SSukumar Swaminathan 	buf_info->size = count;
7376b3660a96SSukumar Swaminathan 	buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7377b3660a96SSukumar Swaminathan 	buf_info->align = ddi_ptob(hba->dip, 1L);
7378b3660a96SSukumar Swaminathan 
7379b3660a96SSukumar Swaminathan 	(void) emlxs_mem_alloc(hba, buf_info);
738082527734SSukumar Swaminathan 
7381b3660a96SSukumar Swaminathan 	if (buf_info->virt == NULL) {
7382b3660a96SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
7383b3660a96SSukumar Swaminathan 		    &emlxs_init_failed_msg,
7384b3660a96SSukumar Swaminathan 		    "Unable to allocate internal memory for SLI4: %d",
7385b3660a96SSukumar Swaminathan 		    count);
7386b3660a96SSukumar Swaminathan 		goto failed;
738782527734SSukumar Swaminathan 	}
7388b3660a96SSukumar Swaminathan 	bzero(buf_info->virt, buf_info->size);
7389b3660a96SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
7390b3660a96SSukumar Swaminathan 	    buf_info->size, DDI_DMA_SYNC_FORDEV);
739182527734SSukumar Swaminathan 
7392b3660a96SSukumar Swaminathan 	/* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
7393b3660a96SSukumar Swaminathan 	data_handle = buf_info->data_handle;
7394b3660a96SSukumar Swaminathan 	dma_handle = buf_info->dma_handle;
7395b3660a96SSukumar Swaminathan 	phys = buf_info->phys;
7396b3660a96SSukumar Swaminathan 	virt = (char *)buf_info->virt;
739782527734SSukumar Swaminathan 
739882527734SSukumar Swaminathan 	/* Allocate space for queues */
7399*8f23e9faSHans Rosenfeld 
7400*8f23e9faSHans Rosenfeld 	/* EQ */
7401b3660a96SSukumar Swaminathan 	size = 4096;
740282527734SSukumar Swaminathan 	for (i = 0; i < num_eq; i++) {
7403*8f23e9faSHans Rosenfeld 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7404*8f23e9faSHans Rosenfeld 
740582527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.eq[i].addr;
7406*8f23e9faSHans Rosenfeld 		buf_info->size = size;
7407*8f23e9faSHans Rosenfeld 		buf_info->flags =
7408*8f23e9faSHans Rosenfeld 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7409*8f23e9faSHans Rosenfeld 		buf_info->align = ddi_ptob(hba->dip, 1L);
7410*8f23e9faSHans Rosenfeld 		buf_info->phys = phys;
7411*8f23e9faSHans Rosenfeld 		buf_info->virt = (void *)virt;
7412*8f23e9faSHans Rosenfeld 		buf_info->data_handle = data_handle;
7413*8f23e9faSHans Rosenfeld 		buf_info->dma_handle = dma_handle;
741482527734SSukumar Swaminathan 
7415*8f23e9faSHans Rosenfeld 		phys += size;
7416*8f23e9faSHans Rosenfeld 		virt += size;
741782527734SSukumar Swaminathan 
7418*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
7419*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].qid = 0xffff;
742082527734SSukumar Swaminathan 
7421*8f23e9faSHans Rosenfeld 		mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, NULL,
742282527734SSukumar Swaminathan 		    MUTEX_DRIVER, NULL);
742382527734SSukumar Swaminathan 	}
7424b3660a96SSukumar Swaminathan 
7425*8f23e9faSHans Rosenfeld 
7426*8f23e9faSHans Rosenfeld 	/* CQ */
742782527734SSukumar Swaminathan 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7428*8f23e9faSHans Rosenfeld 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7429*8f23e9faSHans Rosenfeld 
743082527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.cq[i].addr;
7431*8f23e9faSHans Rosenfeld 		buf_info->size = cq_size;
7432*8f23e9faSHans Rosenfeld 		buf_info->flags =
7433*8f23e9faSHans Rosenfeld 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7434*8f23e9faSHans Rosenfeld 		buf_info->align = ddi_ptob(hba->dip, 1L);
7435*8f23e9faSHans Rosenfeld 		buf_info->phys = phys;
7436*8f23e9faSHans Rosenfeld 		buf_info->virt = (void *)virt;
7437*8f23e9faSHans Rosenfeld 		buf_info->data_handle = data_handle;
7438*8f23e9faSHans Rosenfeld 		buf_info->dma_handle = dma_handle;
743982527734SSukumar Swaminathan 
7440*8f23e9faSHans Rosenfeld 		phys += cq_size;
7441*8f23e9faSHans Rosenfeld 		virt += cq_size;
744282527734SSukumar Swaminathan 
7443*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].max_index = cq_depth;
7444*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].qid = 0xffff;
744582527734SSukumar Swaminathan 	}
7446b3660a96SSukumar Swaminathan 
7447*8f23e9faSHans Rosenfeld 
7448*8f23e9faSHans Rosenfeld 	/* WQ */
7449b3660a96SSukumar Swaminathan 	size = 4096 * EMLXS_NUM_WQ_PAGES;
745082527734SSukumar Swaminathan 	for (i = 0; i < num_wq; i++) {
7451*8f23e9faSHans Rosenfeld 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
745282527734SSukumar Swaminathan 
7453*8f23e9faSHans Rosenfeld 		buf_info = &hba->sli.sli4.wq[i].addr;
7454b3660a96SSukumar Swaminathan 		buf_info->size = size;
7455b3660a96SSukumar Swaminathan 		buf_info->flags =
7456b3660a96SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7457b3660a96SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
7458b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
7459a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
7460b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
7461b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
7462b3660a96SSukumar Swaminathan 
7463b3660a96SSukumar Swaminathan 		phys += size;
7464b3660a96SSukumar Swaminathan 		virt += size;
7465b3660a96SSukumar Swaminathan 
7466*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
7467*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
7468*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].qid = 0xFFFF;
7469b3660a96SSukumar Swaminathan 	}
7470b3660a96SSukumar Swaminathan 
7471*8f23e9faSHans Rosenfeld 
7472*8f23e9faSHans Rosenfeld 	/* MQ */
7473*8f23e9faSHans Rosenfeld 	size = 4096;
7474*8f23e9faSHans Rosenfeld 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7475*8f23e9faSHans Rosenfeld 
7476*8f23e9faSHans Rosenfeld 	buf_info = &hba->sli.sli4.mq.addr;
7477*8f23e9faSHans Rosenfeld 	buf_info->size = size;
7478*8f23e9faSHans Rosenfeld 	buf_info->flags =
7479*8f23e9faSHans Rosenfeld 	    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7480*8f23e9faSHans Rosenfeld 	buf_info->align = ddi_ptob(hba->dip, 1L);
7481*8f23e9faSHans Rosenfeld 	buf_info->phys = phys;
7482*8f23e9faSHans Rosenfeld 	buf_info->virt = (void *)virt;
7483*8f23e9faSHans Rosenfeld 	buf_info->data_handle = data_handle;
7484*8f23e9faSHans Rosenfeld 	buf_info->dma_handle = dma_handle;
7485*8f23e9faSHans Rosenfeld 
7486*8f23e9faSHans Rosenfeld 	phys += size;
7487*8f23e9faSHans Rosenfeld 	virt += size;
7488*8f23e9faSHans Rosenfeld 
7489*8f23e9faSHans Rosenfeld 	hba->sli.sli4.mq.max_index = MQ_DEPTH;
7490*8f23e9faSHans Rosenfeld 
7491*8f23e9faSHans Rosenfeld 
7492*8f23e9faSHans Rosenfeld 	/* RXQ */
749382527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
749482527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
749582527734SSukumar Swaminathan 
7496*8f23e9faSHans Rosenfeld 		mutex_init(&hba->sli.sli4.rxq[i].lock, NULL, MUTEX_DRIVER,
7497*8f23e9faSHans Rosenfeld 		    NULL);
749882527734SSukumar Swaminathan 	}
749982527734SSukumar Swaminathan 
7500*8f23e9faSHans Rosenfeld 
7501*8f23e9faSHans Rosenfeld 	/* RQ */
7502b3660a96SSukumar Swaminathan 	size = 4096;
750382527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
750482527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7505*8f23e9faSHans Rosenfeld 
7506*8f23e9faSHans Rosenfeld 		buf_info = &hba->sli.sli4.rq[i].addr;
7507b3660a96SSukumar Swaminathan 		buf_info->size = size;
750882527734SSukumar Swaminathan 		buf_info->flags =
750982527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
751082527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
7511b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
7512a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
7513b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
7514b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
751582527734SSukumar Swaminathan 
7516b3660a96SSukumar Swaminathan 		phys += size;
7517b3660a96SSukumar Swaminathan 		virt += size;
751882527734SSukumar Swaminathan 
751982527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
7520*8f23e9faSHans Rosenfeld 		hba->sli.sli4.rq[i].qid = 0xFFFF;
752182527734SSukumar Swaminathan 
7522*8f23e9faSHans Rosenfeld 		mutex_init(&hba->sli.sli4.rq[i].lock, NULL, MUTEX_DRIVER, NULL);
7523b3660a96SSukumar Swaminathan 	}
752482527734SSukumar Swaminathan 
7525*8f23e9faSHans Rosenfeld 
7526*8f23e9faSHans Rosenfeld 	/* RQB/E */
7527*8f23e9faSHans Rosenfeld 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7528b3660a96SSukumar Swaminathan 		size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE;
7529b3660a96SSukumar Swaminathan 		tmp_phys = phys;
7530b3660a96SSukumar Swaminathan 		tmp_virt = virt;
753182527734SSukumar Swaminathan 
753282527734SSukumar Swaminathan 		/* Initialize the RQEs */
753382527734SSukumar Swaminathan 		rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
753482527734SSukumar Swaminathan 		for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
7535b3660a96SSukumar Swaminathan 			phys = tmp_phys;
7536b3660a96SSukumar Swaminathan 			virt = tmp_virt;
753782527734SSukumar Swaminathan 			for (k = 0; k < RQB_COUNT; k++) {
7538b3660a96SSukumar Swaminathan 				word = PADDR_HI(phys);
753982527734SSukumar Swaminathan 				rqe->AddrHi = BE_SWAP32(word);
754082527734SSukumar Swaminathan 
7541b3660a96SSukumar Swaminathan 				word = PADDR_LO(phys);
754282527734SSukumar Swaminathan 				rqe->AddrLo = BE_SWAP32(word);
754382527734SSukumar Swaminathan 
7544b3660a96SSukumar Swaminathan 				rqb = &hba->sli.sli4.rq[i].
7545b3660a96SSukumar Swaminathan 				    rqb[k + (j * RQB_COUNT)];
7546b3660a96SSukumar Swaminathan 				rqb->size = size;
7547b3660a96SSukumar Swaminathan 				rqb->flags = FC_MBUF_DMA |
7548b3660a96SSukumar Swaminathan 				    FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7549b3660a96SSukumar Swaminathan 				rqb->align = ddi_ptob(hba->dip, 1L);
7550b3660a96SSukumar Swaminathan 				rqb->phys = phys;
7551a9800bebSGarrett D'Amore 				rqb->virt = (void *)virt;
7552b3660a96SSukumar Swaminathan 				rqb->data_handle = data_handle;
7553b3660a96SSukumar Swaminathan 				rqb->dma_handle = dma_handle;
7554b3660a96SSukumar Swaminathan 
7555b3660a96SSukumar Swaminathan 				phys += size;
7556b3660a96SSukumar Swaminathan 				virt += size;
7557*8f23e9faSHans Rosenfeld #ifdef DEBUG_RQE
755882527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7559*8f23e9faSHans Rosenfeld 				    "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p iotag=%d",
756082527734SSukumar Swaminathan 				    i, j, k, mp, mp->tag);
7561*8f23e9faSHans Rosenfeld #endif /* DEBUG_RQE */
756282527734SSukumar Swaminathan 
756382527734SSukumar Swaminathan 				rqe++;
756482527734SSukumar Swaminathan 			}
756582527734SSukumar Swaminathan 		}
756682527734SSukumar Swaminathan 
7567b3660a96SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)
7568b3660a96SSukumar Swaminathan 		    hba->sli.sli4.rq[i].addr.virt) -
7569b3660a96SSukumar Swaminathan 		    (uint64_t)((unsigned long)
7570b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.virt));
7571b3660a96SSukumar Swaminathan 
757282527734SSukumar Swaminathan 		/* Sync the RQ buffer list */
7573b3660a96SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset,
757482527734SSukumar Swaminathan 		    hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
7575b3660a96SSukumar Swaminathan 	}
757682527734SSukumar Swaminathan 
7577*8f23e9faSHans Rosenfeld 	/* 4K Alignment */
7578*8f23e9faSHans Rosenfeld 	align = (4096 - (phys%4096));
7579*8f23e9faSHans Rosenfeld 	phys += align;
7580*8f23e9faSHans Rosenfeld 	virt += align;
7581b3660a96SSukumar Swaminathan 
7582*8f23e9faSHans Rosenfeld 	/* SGL */
7583*8f23e9faSHans Rosenfeld 	/* Initialize double linked lists */
7584*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIinuse_f =
7585*8f23e9faSHans Rosenfeld 	    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7586*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIinuse_b =
7587*8f23e9faSHans Rosenfeld 	    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7588*8f23e9faSHans Rosenfeld 	hba->sli.sli4.xria_count = 0;
7589*8f23e9faSHans Rosenfeld 
7590*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIfree_f =
7591*8f23e9faSHans Rosenfeld 	    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7592*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIfree_b =
7593*8f23e9faSHans Rosenfeld 	    (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7594*8f23e9faSHans Rosenfeld 	hba->sli.sli4.xria_count = 0;
7595*8f23e9faSHans Rosenfeld 
7596*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
7597*8f23e9faSHans Rosenfeld 	    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
7598b3660a96SSukumar Swaminathan 
7599*8f23e9faSHans Rosenfeld 	xrip = hba->sli.sli4.XRIp;
7600*8f23e9faSHans Rosenfeld 	size = hba->sli.sli4.mem_sgl_size;
7601*8f23e9faSHans Rosenfeld 	iotag = 1;
7602*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->sli.sli4.XRICount; i++) {
7603*8f23e9faSHans Rosenfeld 		xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
7604*8f23e9faSHans Rosenfeld 
7605*8f23e9faSHans Rosenfeld 		/* We don't use XRI==0, since it also represents an */
7606*8f23e9faSHans Rosenfeld 		/* uninitialized exchange */
7607*8f23e9faSHans Rosenfeld 		if (xrip->XRI == 0) {
7608a9800bebSGarrett D'Amore 			xrip++;
7609*8f23e9faSHans Rosenfeld 			continue;
7610b3660a96SSukumar Swaminathan 		}
7611*8f23e9faSHans Rosenfeld 
7612*8f23e9faSHans Rosenfeld 		xrip->iotag = iotag++;
7613*8f23e9faSHans Rosenfeld 		xrip->sge_count =
7614*8f23e9faSHans Rosenfeld 		    (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
7615*8f23e9faSHans Rosenfeld 
7616*8f23e9faSHans Rosenfeld 		/* Add xrip to end of free list */
7617*8f23e9faSHans Rosenfeld 		xrip->_b = hba->sli.sli4.XRIfree_b;
7618*8f23e9faSHans Rosenfeld 		hba->sli.sli4.XRIfree_b->_f = xrip;
7619*8f23e9faSHans Rosenfeld 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7620*8f23e9faSHans Rosenfeld 		hba->sli.sli4.XRIfree_b = xrip;
7621*8f23e9faSHans Rosenfeld 		hba->sli.sli4.xrif_count++;
7622*8f23e9faSHans Rosenfeld 
7623*8f23e9faSHans Rosenfeld 		/* Allocate SGL for this xrip */
7624*8f23e9faSHans Rosenfeld 		buf_info = &xrip->SGList;
7625*8f23e9faSHans Rosenfeld 		buf_info->size = size;
7626*8f23e9faSHans Rosenfeld 		buf_info->flags =
7627*8f23e9faSHans Rosenfeld 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7628*8f23e9faSHans Rosenfeld 		buf_info->align = size;
7629*8f23e9faSHans Rosenfeld 		buf_info->phys = phys;
7630*8f23e9faSHans Rosenfeld 		buf_info->virt = (void *)virt;
7631*8f23e9faSHans Rosenfeld 		buf_info->data_handle = data_handle;
7632*8f23e9faSHans Rosenfeld 		buf_info->dma_handle = dma_handle;
7633*8f23e9faSHans Rosenfeld 
7634*8f23e9faSHans Rosenfeld 		phys += size;
7635*8f23e9faSHans Rosenfeld 		virt += size;
7636*8f23e9faSHans Rosenfeld 
7637*8f23e9faSHans Rosenfeld 		xrip++;
763882527734SSukumar Swaminathan 	}
763982527734SSukumar Swaminathan 
7640*8f23e9faSHans Rosenfeld 	/* 4K Alignment */
7641*8f23e9faSHans Rosenfeld 	align = (4096 - (phys%4096));
7642*8f23e9faSHans Rosenfeld 	phys += align;
7643*8f23e9faSHans Rosenfeld 	virt += align;
7644*8f23e9faSHans Rosenfeld 
7645*8f23e9faSHans Rosenfeld 	/* RPI Header Templates */
7646*8f23e9faSHans Rosenfeld 	if (hba->sli.sli4.param.HDRR) {
7647*8f23e9faSHans Rosenfeld 		buf_info = &hba->sli.sli4.HeaderTmplate;
7648b3660a96SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
7649*8f23e9faSHans Rosenfeld 		buf_info->size = hddr_size;
7650b3660a96SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
765182527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
7652b3660a96SSukumar Swaminathan 		buf_info->phys = phys;
7653a9800bebSGarrett D'Amore 		buf_info->virt = (void *)virt;
7654b3660a96SSukumar Swaminathan 		buf_info->data_handle = data_handle;
7655b3660a96SSukumar Swaminathan 		buf_info->dma_handle = dma_handle;
7656b3660a96SSukumar Swaminathan 	}
765782527734SSukumar Swaminathan 
7658b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
7659b3660a96SSukumar Swaminathan 	if (hba->sli.sli4.slim2.dma_handle) {
7660b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
7661b3660a96SSukumar Swaminathan 		    hba->sli.sli4.slim2.dma_handle)
7662b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
7663b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
7664b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
7665*8f23e9faSHans Rosenfeld 			    "sli4_resource_alloc: hdl=%p",
7666b3660a96SSukumar Swaminathan 			    hba->sli.sli4.slim2.dma_handle);
766782527734SSukumar Swaminathan 			goto failed;
766882527734SSukumar Swaminathan 		}
766982527734SSukumar Swaminathan 	}
7670*8f23e9faSHans Rosenfeld #endif /* FMA_SUPPORT */
767182527734SSukumar Swaminathan 
767282527734SSukumar Swaminathan 	return (0);
767382527734SSukumar Swaminathan 
767482527734SSukumar Swaminathan failed:
767582527734SSukumar Swaminathan 
767682527734SSukumar Swaminathan 	(void) emlxs_sli4_resource_free(hba);
767782527734SSukumar Swaminathan 	return (ENOMEM);
767882527734SSukumar Swaminathan 
767982527734SSukumar Swaminathan } /* emlxs_sli4_resource_alloc */
768082527734SSukumar Swaminathan 
768182527734SSukumar Swaminathan 
7682*8f23e9faSHans Rosenfeld extern void
7683*8f23e9faSHans Rosenfeld emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba)
768482527734SSukumar Swaminathan {
7685*8f23e9faSHans Rosenfeld 	uint32_t i;
7686*8f23e9faSHans Rosenfeld 	uint32_t num_wq;
7687*8f23e9faSHans Rosenfeld 	emlxs_config_t	*cfg = &CFG;
7688*8f23e9faSHans Rosenfeld 	clock_t		time;
7689*8f23e9faSHans Rosenfeld 
7690*8f23e9faSHans Rosenfeld 	/* EQ */
7691*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->intr_count; i++) {
7692*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].num_proc = 0;
7693*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].max_proc = 0;
7694*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].isr_count = 0;
7695*8f23e9faSHans Rosenfeld 	}
7696*8f23e9faSHans Rosenfeld 	num_wq = cfg[CFG_NUM_WQ].current * hba->intr_count;
7697*8f23e9faSHans Rosenfeld 	/* CQ */
7698*8f23e9faSHans Rosenfeld 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7699*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].num_proc = 0;
7700*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].max_proc = 0;
7701*8f23e9faSHans Rosenfeld 		hba->sli.sli4.cq[i].isr_count = 0;
7702*8f23e9faSHans Rosenfeld 	}
7703*8f23e9faSHans Rosenfeld 	/* WQ */
7704*8f23e9faSHans Rosenfeld 	for (i = 0; i < num_wq; i++) {
7705*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].num_proc = 0;
7706*8f23e9faSHans Rosenfeld 		hba->sli.sli4.wq[i].num_busy = 0;
7707*8f23e9faSHans Rosenfeld 	}
7708*8f23e9faSHans Rosenfeld 	/* RQ */
7709*8f23e9faSHans Rosenfeld 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
7710*8f23e9faSHans Rosenfeld 		hba->sli.sli4.rq[i].num_proc = 0;
7711*8f23e9faSHans Rosenfeld 	}
7712*8f23e9faSHans Rosenfeld 	(void) drv_getparm(LBOLT, &time);
7713*8f23e9faSHans Rosenfeld 	hba->sli.sli4.que_stat_timer = (uint32_t)time;
7714*8f23e9faSHans Rosenfeld 
7715*8f23e9faSHans Rosenfeld } /* emlxs_sli4_zero_queue_stat */
7716*8f23e9faSHans Rosenfeld 
7717*8f23e9faSHans Rosenfeld 
7718*8f23e9faSHans Rosenfeld extern XRIobj_t *
7719*8f23e9faSHans Rosenfeld emlxs_sli4_reserve_xri(emlxs_port_t *port,  RPIobj_t *rpip, uint32_t type,
7720*8f23e9faSHans Rosenfeld     uint16_t rx_id)
7721*8f23e9faSHans Rosenfeld {
7722*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
7723a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
7724a9800bebSGarrett D'Amore 	uint16_t	iotag;
772582527734SSukumar Swaminathan 
7726a9800bebSGarrett D'Amore 	mutex_enter(&EMLXS_FCTAB_LOCK);
772782527734SSukumar Swaminathan 
7728a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIfree_f;
772982527734SSukumar Swaminathan 
7730a9800bebSGarrett D'Amore 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
7731a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
773282527734SSukumar Swaminathan 
7733a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7734*8f23e9faSHans Rosenfeld 		    "Unable to reserve XRI. type=%d",
7735*8f23e9faSHans Rosenfeld 		    type);
773682527734SSukumar Swaminathan 
7737a9800bebSGarrett D'Amore 		return (NULL);
7738a9800bebSGarrett D'Amore 	}
773982527734SSukumar Swaminathan 
7740a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
774182527734SSukumar Swaminathan 
7742a9800bebSGarrett D'Amore 	if ((!iotag) ||
7743a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
7744a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
7745a9800bebSGarrett D'Amore 		/*
7746a9800bebSGarrett D'Amore 		 * No more command slots available, retry later
7747a9800bebSGarrett D'Amore 		 */
7748a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7749*8f23e9faSHans Rosenfeld 		    "Adapter Busy. Unable to reserve iotag. type=%d",
7750*8f23e9faSHans Rosenfeld 		    type);
775182527734SSukumar Swaminathan 
7752a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
7753a9800bebSGarrett D'Amore 		return (NULL);
775482527734SSukumar Swaminathan 	}
775582527734SSukumar Swaminathan 
7756a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_ALLOCATED;
7757*8f23e9faSHans Rosenfeld 	xrip->type = type;
7758a9800bebSGarrett D'Amore 	xrip->flag = EMLXS_XRI_RESERVED;
7759a9800bebSGarrett D'Amore 	xrip->sbp = NULL;
776082527734SSukumar Swaminathan 
7761*8f23e9faSHans Rosenfeld 	xrip->rpip = rpip;
7762*8f23e9faSHans Rosenfeld 	xrip->rx_id = rx_id;
7763*8f23e9faSHans Rosenfeld 	rpip->xri_count++;
776482527734SSukumar Swaminathan 
7765a9800bebSGarrett D'Amore 	/* Take it off free list */
7766a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
7767a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
7768a9800bebSGarrett D'Amore 	xrip->_f = NULL;
7769a9800bebSGarrett D'Amore 	xrip->_b = NULL;
7770a9800bebSGarrett D'Amore 	hba->sli.sli4.xrif_count--;
777182527734SSukumar Swaminathan 
777282527734SSukumar Swaminathan 	/* Add it to end of inuse list */
7773a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIinuse_b;
7774a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b->_f = xrip;
7775a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7776a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b = xrip;
777782527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
777882527734SSukumar Swaminathan 
777982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
7780a9800bebSGarrett D'Amore 	return (xrip);
778182527734SSukumar Swaminathan 
778282527734SSukumar Swaminathan } /* emlxs_sli4_reserve_xri() */
778382527734SSukumar Swaminathan 
778482527734SSukumar Swaminathan 
778582527734SSukumar Swaminathan extern uint32_t
7786*8f23e9faSHans Rosenfeld emlxs_sli4_unreserve_xri(emlxs_port_t *port, uint16_t xri, uint32_t lock)
778782527734SSukumar Swaminathan {
7788*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
7789a9800bebSGarrett D'Amore 	XRIobj_t *xrip;
779082527734SSukumar Swaminathan 
7791a9800bebSGarrett D'Amore 	if (lock) {
7792a9800bebSGarrett D'Amore 		mutex_enter(&EMLXS_FCTAB_LOCK);
7793a9800bebSGarrett D'Amore 	}
779482527734SSukumar Swaminathan 
7795*8f23e9faSHans Rosenfeld 	xrip = emlxs_sli4_find_xri(port, xri);
7796a9800bebSGarrett D'Amore 
7797a9800bebSGarrett D'Amore 	if (!xrip || xrip->state == XRI_STATE_FREE) {
7798a9800bebSGarrett D'Amore 		if (lock) {
7799a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
7800a9800bebSGarrett D'Amore 		}
780182527734SSukumar Swaminathan 
780282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7803*8f23e9faSHans Rosenfeld 		    "sli4_unreserve_xri:%d already freed.", xri);
780482527734SSukumar Swaminathan 		return (0);
780582527734SSukumar Swaminathan 	}
780682527734SSukumar Swaminathan 
7807*8f23e9faSHans Rosenfeld 	/* Flush this unsolicited ct command */
7808*8f23e9faSHans Rosenfeld 	if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
7809*8f23e9faSHans Rosenfeld 		(void) emlxs_flush_ct_event(port, xrip->rx_id);
7810*8f23e9faSHans Rosenfeld 	}
7811*8f23e9faSHans Rosenfeld 
7812a9800bebSGarrett D'Amore 	if (!(xrip->flag & EMLXS_XRI_RESERVED)) {
7813a9800bebSGarrett D'Amore 		if (lock) {
7814a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
7815a9800bebSGarrett D'Amore 		}
7816a9800bebSGarrett D'Amore 
781782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7818*8f23e9faSHans Rosenfeld 		    "sli4_unreserve_xri:%d in use. type=%d",
7819*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip->type);
782082527734SSukumar Swaminathan 		return (1);
782182527734SSukumar Swaminathan 	}
782282527734SSukumar Swaminathan 
7823a9800bebSGarrett D'Amore 	if (xrip->iotag &&
7824a9800bebSGarrett D'Amore 	    (hba->fc_table[xrip->iotag] != NULL) &&
7825a9800bebSGarrett D'Amore 	    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
7826a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7827*8f23e9faSHans Rosenfeld 		    "sli4_unreserve_xri:%d  sbp dropped:%p type=%d",
7828*8f23e9faSHans Rosenfeld 		    xrip->XRI, hba->fc_table[xrip->iotag], xrip->type);
7829a9800bebSGarrett D'Amore 
7830a9800bebSGarrett D'Amore 		hba->fc_table[xrip->iotag] = NULL;
783182527734SSukumar Swaminathan 		hba->io_count--;
783282527734SSukumar Swaminathan 	}
783382527734SSukumar Swaminathan 
7834*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7835*8f23e9faSHans Rosenfeld 	    "sli4_unreserve_xri:%d unreserved. type=%d",
7836*8f23e9faSHans Rosenfeld 	    xrip->XRI, xrip->type);
7837*8f23e9faSHans Rosenfeld 
7838a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_FREE;
7839*8f23e9faSHans Rosenfeld 	xrip->type = 0;
784082527734SSukumar Swaminathan 
7841a9800bebSGarrett D'Amore 	if (xrip->rpip) {
7842a9800bebSGarrett D'Amore 		xrip->rpip->xri_count--;
7843a9800bebSGarrett D'Amore 		xrip->rpip = NULL;
784482527734SSukumar Swaminathan 	}
784582527734SSukumar Swaminathan 
7846*8f23e9faSHans Rosenfeld 	if (xrip->reserved_rpip) {
7847*8f23e9faSHans Rosenfeld 		xrip->reserved_rpip->xri_count--;
7848*8f23e9faSHans Rosenfeld 		xrip->reserved_rpip = NULL;
7849*8f23e9faSHans Rosenfeld 	}
7850*8f23e9faSHans Rosenfeld 
785182527734SSukumar Swaminathan 	/* Take it off inuse list */
7852a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
7853a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
7854a9800bebSGarrett D'Amore 	xrip->_f = NULL;
7855a9800bebSGarrett D'Amore 	xrip->_b = NULL;
785682527734SSukumar Swaminathan 	hba->sli.sli4.xria_count--;
785782527734SSukumar Swaminathan 
785882527734SSukumar Swaminathan 	/* Add it to end of free list */
7859a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIfree_b;
7860a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIfree_b->_f = xrip;
7861a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7862a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIfree_b = xrip;
786382527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count++;
786482527734SSukumar Swaminathan 
7865a9800bebSGarrett D'Amore 	if (lock) {
7866a9800bebSGarrett D'Amore 		mutex_exit(&EMLXS_FCTAB_LOCK);
7867a9800bebSGarrett D'Amore 	}
786882527734SSukumar Swaminathan 
786982527734SSukumar Swaminathan 	return (0);
787082527734SSukumar Swaminathan 
787182527734SSukumar Swaminathan } /* emlxs_sli4_unreserve_xri() */
787282527734SSukumar Swaminathan 
787382527734SSukumar Swaminathan 
7874*8f23e9faSHans Rosenfeld XRIobj_t *
7875*8f23e9faSHans Rosenfeld emlxs_sli4_register_xri(emlxs_port_t *port, emlxs_buf_t *sbp, uint16_t xri,
7876*8f23e9faSHans Rosenfeld     uint32_t did)
787782527734SSukumar Swaminathan {
7878*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
787982527734SSukumar Swaminathan 	uint16_t	iotag;
7880a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
7881*8f23e9faSHans Rosenfeld 	emlxs_node_t	*node;
7882*8f23e9faSHans Rosenfeld 	RPIobj_t	*rpip;
788382527734SSukumar Swaminathan 
788482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
788582527734SSukumar Swaminathan 
7886*8f23e9faSHans Rosenfeld 	xrip = sbp->xrip;
7887a9800bebSGarrett D'Amore 	if (!xrip) {
7888*8f23e9faSHans Rosenfeld 		xrip = emlxs_sli4_find_xri(port, xri);
788982527734SSukumar Swaminathan 
7890*8f23e9faSHans Rosenfeld 		if (!xrip) {
7891*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7892*8f23e9faSHans Rosenfeld 			    "sli4_register_xri:%d XRI not found.", xri);
789382527734SSukumar Swaminathan 
7894*8f23e9faSHans Rosenfeld 			mutex_exit(&EMLXS_FCTAB_LOCK);
7895*8f23e9faSHans Rosenfeld 			return (NULL);
7896*8f23e9faSHans Rosenfeld 		}
789782527734SSukumar Swaminathan 	}
789882527734SSukumar Swaminathan 
7899a9800bebSGarrett D'Amore 	if ((xrip->state == XRI_STATE_FREE) ||
7900a9800bebSGarrett D'Amore 	    !(xrip->flag & EMLXS_XRI_RESERVED)) {
790182527734SSukumar Swaminathan 
790282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7903*8f23e9faSHans Rosenfeld 		    "sli4_register_xri:%d Invalid XRI. xrip=%p "
7904a9800bebSGarrett D'Amore 		    "state=%x flag=%x",
7905*8f23e9faSHans Rosenfeld 		    xrip->XRI, xrip, xrip->state, xrip->flag);
790682527734SSukumar Swaminathan 
790782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
790882527734SSukumar Swaminathan 		return (NULL);
790982527734SSukumar Swaminathan 	}
791082527734SSukumar Swaminathan 
7911a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
791282527734SSukumar Swaminathan 
791382527734SSukumar Swaminathan 	if ((!iotag) ||
7914a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
7915a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
791682527734SSukumar Swaminathan 
791782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7918*8f23e9faSHans Rosenfeld 		    "sli4_register_xri:%d Invalid fc_table entry. "
7919*8f23e9faSHans Rosenfeld 		    "iotag=%d entry=%p",
7920*8f23e9faSHans Rosenfeld 		    xrip->XRI, iotag, hba->fc_table[iotag]);
792182527734SSukumar Swaminathan 
792282527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
792382527734SSukumar Swaminathan 		return (NULL);
792482527734SSukumar Swaminathan 	}
792582527734SSukumar Swaminathan 
792682527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
792782527734SSukumar Swaminathan 	hba->io_count++;
792882527734SSukumar Swaminathan 
792982527734SSukumar Swaminathan 	sbp->iotag = iotag;
7930a9800bebSGarrett D'Amore 	sbp->xrip = xrip;
793182527734SSukumar Swaminathan 
7932a9800bebSGarrett D'Amore 	xrip->flag &= ~EMLXS_XRI_RESERVED;
7933a9800bebSGarrett D'Amore 	xrip->sbp = sbp;
793482527734SSukumar Swaminathan 
7935*8f23e9faSHans Rosenfeld 	/* If we did not have a registered RPI when we reserved */
7936*8f23e9faSHans Rosenfeld 	/* this exchange, check again now. */
7937*8f23e9faSHans Rosenfeld 	if (xrip->rpip && (xrip->rpip->RPI == FABRIC_RPI)) {
7938*8f23e9faSHans Rosenfeld 		node = emlxs_node_find_did(port, did, 1);
7939*8f23e9faSHans Rosenfeld 		rpip = EMLXS_NODE_TO_RPI(port, node);
7940*8f23e9faSHans Rosenfeld 
7941*8f23e9faSHans Rosenfeld 		if (rpip && (rpip->RPI != FABRIC_RPI)) {
7942*8f23e9faSHans Rosenfeld 			/* Move the XRI to the new RPI */
7943*8f23e9faSHans Rosenfeld 			xrip->rpip->xri_count--;
7944*8f23e9faSHans Rosenfeld 			xrip->rpip = rpip;
7945*8f23e9faSHans Rosenfeld 			rpip->xri_count++;
7946*8f23e9faSHans Rosenfeld 		}
7947*8f23e9faSHans Rosenfeld 	}
7948*8f23e9faSHans Rosenfeld 
794982527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
795082527734SSukumar Swaminathan 
7951a9800bebSGarrett D'Amore 	return (xrip);
795282527734SSukumar Swaminathan 
795382527734SSukumar Swaminathan } /* emlxs_sli4_register_xri() */
795482527734SSukumar Swaminathan 
795582527734SSukumar Swaminathan 
795682527734SSukumar Swaminathan /* Performs both reserve and register functions for XRI */
795782527734SSukumar Swaminathan static XRIobj_t *
7958*8f23e9faSHans Rosenfeld emlxs_sli4_alloc_xri(emlxs_port_t *port, emlxs_buf_t *sbp, RPIobj_t *rpip,
7959*8f23e9faSHans Rosenfeld     uint32_t type)
796082527734SSukumar Swaminathan {
7961*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
7962a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
796382527734SSukumar Swaminathan 	uint16_t	iotag;
796482527734SSukumar Swaminathan 
796582527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
796682527734SSukumar Swaminathan 
7967a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIfree_f;
796882527734SSukumar Swaminathan 
7969a9800bebSGarrett D'Amore 	if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
797082527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
797182527734SSukumar Swaminathan 
797282527734SSukumar Swaminathan 		return (NULL);
797382527734SSukumar Swaminathan 	}
797482527734SSukumar Swaminathan 
797582527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
7976a9800bebSGarrett D'Amore 	iotag = xrip->iotag;
797782527734SSukumar Swaminathan 
797882527734SSukumar Swaminathan 	if ((!iotag) ||
7979a9800bebSGarrett D'Amore 	    ((hba->fc_table[iotag] != NULL) &&
7980a9800bebSGarrett D'Amore 	    (hba->fc_table[iotag] != STALE_PACKET))) {
798182527734SSukumar Swaminathan 		/*
798282527734SSukumar Swaminathan 		 * No more command slots available, retry later
798382527734SSukumar Swaminathan 		 */
798482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7985*8f23e9faSHans Rosenfeld 		    "Adapter Busy. Unable to alloc iotag:(0x%x)(%p) type=%d",
7986*8f23e9faSHans Rosenfeld 		    iotag, hba->fc_table[iotag], type);
798782527734SSukumar Swaminathan 
798882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
798982527734SSukumar Swaminathan 		return (NULL);
799082527734SSukumar Swaminathan 	}
799182527734SSukumar Swaminathan 
799282527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
799382527734SSukumar Swaminathan 	hba->io_count++;
799482527734SSukumar Swaminathan 
799582527734SSukumar Swaminathan 	sbp->iotag = iotag;
7996a9800bebSGarrett D'Amore 	sbp->xrip = xrip;
799782527734SSukumar Swaminathan 
7998a9800bebSGarrett D'Amore 	xrip->state = XRI_STATE_ALLOCATED;
7999*8f23e9faSHans Rosenfeld 	xrip->type = type;
8000a9800bebSGarrett D'Amore 	xrip->flag = 0;
8001a9800bebSGarrett D'Amore 	xrip->sbp = sbp;
800282527734SSukumar Swaminathan 
8003*8f23e9faSHans Rosenfeld 	xrip->rpip = rpip;
8004*8f23e9faSHans Rosenfeld 	rpip->xri_count++;
800582527734SSukumar Swaminathan 
800682527734SSukumar Swaminathan 	/* Take it off free list */
8007a9800bebSGarrett D'Amore 	(xrip->_b)->_f = xrip->_f;
8008a9800bebSGarrett D'Amore 	(xrip->_f)->_b = xrip->_b;
8009a9800bebSGarrett D'Amore 	xrip->_f = NULL;
8010a9800bebSGarrett D'Amore 	xrip->_b = NULL;
801182527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count--;
801282527734SSukumar Swaminathan 
801382527734SSukumar Swaminathan 	/* Add it to end of inuse list */
8014a9800bebSGarrett D'Amore 	xrip->_b = hba->sli.sli4.XRIinuse_b;
8015a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b->_f = xrip;
8016a9800bebSGarrett D'Amore 	xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
8017a9800bebSGarrett D'Amore 	hba->sli.sli4.XRIinuse_b = xrip;
801882527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
801982527734SSukumar Swaminathan 
802082527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
802182527734SSukumar Swaminathan 
8022a9800bebSGarrett D'Amore 	return (xrip);
802382527734SSukumar Swaminathan 
802482527734SSukumar Swaminathan } /* emlxs_sli4_alloc_xri() */
802582527734SSukumar Swaminathan 
802682527734SSukumar Swaminathan 
8027a9800bebSGarrett D'Amore /* EMLXS_FCTAB_LOCK must be held to enter */
802882527734SSukumar Swaminathan extern XRIobj_t *
8029*8f23e9faSHans Rosenfeld emlxs_sli4_find_xri(emlxs_port_t *port, uint16_t xri)
803082527734SSukumar Swaminathan {
8031*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
8032a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
803382527734SSukumar Swaminathan 
8034a9800bebSGarrett D'Amore 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
8035a9800bebSGarrett D'Amore 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
8036a9800bebSGarrett D'Amore 		if ((xrip->state >= XRI_STATE_ALLOCATED) &&
8037a9800bebSGarrett D'Amore 		    (xrip->XRI == xri)) {
8038a9800bebSGarrett D'Amore 			return (xrip);
803982527734SSukumar Swaminathan 		}
8040a9800bebSGarrett D'Amore 		xrip = xrip->_f;
804182527734SSukumar Swaminathan 	}
804282527734SSukumar Swaminathan 
8043a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8044a9800bebSGarrett D'Amore 	    "Unable to find XRI x%x", xri);
804582527734SSukumar Swaminathan 
8046a9800bebSGarrett D'Amore 	return (NULL);
804782527734SSukumar Swaminathan 
8048a9800bebSGarrett D'Amore } /* emlxs_sli4_find_xri() */
804982527734SSukumar Swaminathan 
805082527734SSukumar Swaminathan 
805182527734SSukumar Swaminathan 
805282527734SSukumar Swaminathan 
805382527734SSukumar Swaminathan extern void
8054*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(emlxs_port_t *port, emlxs_buf_t *sbp, XRIobj_t *xrip,
8055a9800bebSGarrett D'Amore     uint8_t lock)
805682527734SSukumar Swaminathan {
8057*8f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
805882527734SSukumar Swaminathan 
8059a9800bebSGarrett D'Amore 	if (lock) {
8060a9800bebSGarrett D'Amore 		mutex_enter(&EMLXS_FCTAB_LOCK);
806182527734SSukumar Swaminathan 	}
806282527734SSukumar Swaminathan 
8063a9800bebSGarrett D'Amore 	if (xrip) {
8064a9800bebSGarrett D'Amore 		if (xrip->state == XRI_STATE_FREE) {
8065a9800bebSGarrett D'Amore 			if (lock) {
8066a9800bebSGarrett D'Amore 				mutex_exit(&EMLXS_FCTAB_LOCK);
8067a9800bebSGarrett D'Amore 			}
806882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8069*8f23e9faSHans Rosenfeld 			    "Free XRI:%x, Already freed. type=%d",
8070*8f23e9faSHans Rosenfeld 			    xrip->XRI, xrip->type);
807182527734SSukumar Swaminathan 			return;
807282527734SSukumar Swaminathan 		}
807382527734SSukumar Swaminathan 
8074*8f23e9faSHans Rosenfeld 		if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
8075*8f23e9faSHans Rosenfeld 			(void) emlxs_flush_ct_event(port, xrip->rx_id);
8076*8f23e9faSHans Rosenfeld 		}
8077*8f23e9faSHans Rosenfeld 
8078a9800bebSGarrett D'Amore 		if (xrip->iotag &&
8079a9800bebSGarrett D'Amore 		    (hba->fc_table[xrip->iotag] != NULL) &&
8080a9800bebSGarrett D'Amore 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
8081a9800bebSGarrett D'Amore 			hba->fc_table[xrip->iotag] = NULL;
808282527734SSukumar Swaminathan 			hba->io_count--;
808382527734SSukumar Swaminathan 		}
808482527734SSukumar Swaminathan 
8085a9800bebSGarrett D'Amore 		xrip->state = XRI_STATE_FREE;
8086*8f23e9faSHans Rosenfeld 		xrip->type  = 0;
8087a9800bebSGarrett D'Amore 		xrip->flag  = 0;
808882527734SSukumar Swaminathan 
8089a9800bebSGarrett D'Amore 		if (xrip->rpip) {
8090a9800bebSGarrett D'Amore 			xrip->rpip->xri_count--;
8091a9800bebSGarrett D'Amore 			xrip->rpip = NULL;
809282527734SSukumar Swaminathan 		}
809382527734SSukumar Swaminathan 
8094*8f23e9faSHans Rosenfeld 		if (xrip->reserved_rpip) {
8095*8f23e9faSHans Rosenfeld 			xrip->reserved_rpip->xri_count--;
8096*8f23e9faSHans Rosenfeld 			xrip->reserved_rpip = NULL;
8097*8f23e9faSHans Rosenfeld 		}
8098*8f23e9faSHans Rosenfeld 
809982527734SSukumar Swaminathan 		/* Take it off inuse list */
8100a9800bebSGarrett D'Amore 		(xrip->_b)->_f = xrip->_f;
8101a9800bebSGarrett D'Amore 		(xrip->_f)->_b = xrip->_b;
8102a9800bebSGarrett D'Amore 		xrip->_f = NULL;
8103a9800bebSGarrett D'Amore 		xrip->_b = NULL;
810482527734SSukumar Swaminathan 		hba->sli.sli4.xria_count--;
810582527734SSukumar Swaminathan 
810682527734SSukumar Swaminathan 		/* Add it to end of free list */
8107a9800bebSGarrett D'Amore 		xrip->_b = hba->sli.sli4.XRIfree_b;
8108a9800bebSGarrett D'Amore 		hba->sli.sli4.XRIfree_b->_f = xrip;
8109a9800bebSGarrett D'Amore 		xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
8110a9800bebSGarrett D'Amore 		hba->sli.sli4.XRIfree_b = xrip;
811182527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count++;
811282527734SSukumar Swaminathan 	}
811382527734SSukumar Swaminathan 
811482527734SSukumar Swaminathan 	if (sbp) {
8115a9800bebSGarrett D'Amore 		if (!(sbp->pkt_flags & PACKET_VALID) ||
8116a9800bebSGarrett D'Amore 		    (sbp->pkt_flags &
8117a9800bebSGarrett D'Amore 		    (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
8118a9800bebSGarrett D'Amore 			if (lock) {
8119a9800bebSGarrett D'Amore 				mutex_exit(&EMLXS_FCTAB_LOCK);
8120a9800bebSGarrett D'Amore 			}
8121a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8122*8f23e9faSHans Rosenfeld 			    "Free XRI: sbp invalid. sbp=%p flags=%x xri=%d",
8123a9800bebSGarrett D'Amore 			    sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0));
8124a9800bebSGarrett D'Amore 			return;
8125a9800bebSGarrett D'Amore 		}
812682527734SSukumar Swaminathan 
8127a9800bebSGarrett D'Amore 		if (xrip && (xrip->iotag != sbp->iotag)) {
8128a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8129*8f23e9faSHans Rosenfeld 			    "sbp/iotag mismatch %p iotag:%d %d", sbp,
8130a9800bebSGarrett D'Amore 			    sbp->iotag, xrip->iotag);
813182527734SSukumar Swaminathan 		}
813282527734SSukumar Swaminathan 
813382527734SSukumar Swaminathan 		if (sbp->iotag) {
8134a9800bebSGarrett D'Amore 			if (sbp == hba->fc_table[sbp->iotag]) {
813582527734SSukumar Swaminathan 				hba->fc_table[sbp->iotag] = NULL;
813682527734SSukumar Swaminathan 				hba->io_count--;
8137*8f23e9faSHans Rosenfeld 
8138*8f23e9faSHans Rosenfeld 				if (sbp->xrip) {
8139*8f23e9faSHans Rosenfeld 					/* Exchange is still reserved */
8140*8f23e9faSHans Rosenfeld 					sbp->xrip->flag |= EMLXS_XRI_RESERVED;
8141*8f23e9faSHans Rosenfeld 				}
814282527734SSukumar Swaminathan 			}
814382527734SSukumar Swaminathan 			sbp->iotag = 0;
814482527734SSukumar Swaminathan 		}
814582527734SSukumar Swaminathan 
8146*8f23e9faSHans Rosenfeld 		if (xrip) {
8147*8f23e9faSHans Rosenfeld 			sbp->xrip = 0;
8148*8f23e9faSHans Rosenfeld 		}
8149*8f23e9faSHans Rosenfeld 
8150a9800bebSGarrett D'Amore 		if (lock) {
8151a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
8152a9800bebSGarrett D'Amore 		}
815382527734SSukumar Swaminathan 
815482527734SSukumar Swaminathan 		/* Clean up the sbp */
815582527734SSukumar Swaminathan 		mutex_enter(&sbp->mtx);
815682527734SSukumar Swaminathan 
815782527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
815882527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
815982527734SSukumar Swaminathan 			hba->channel_tx_count--;
816082527734SSukumar Swaminathan 		}
816182527734SSukumar Swaminathan 
816282527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
816382527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
816482527734SSukumar Swaminathan 		}
816582527734SSukumar Swaminathan 
816682527734SSukumar Swaminathan 		mutex_exit(&sbp->mtx);
816782527734SSukumar Swaminathan 	} else {
8168a9800bebSGarrett D'Amore 		if (lock) {
8169a9800bebSGarrett D'Amore 			mutex_exit(&EMLXS_FCTAB_LOCK);
8170a9800bebSGarrett D'Amore 		}
817182527734SSukumar Swaminathan 	}
817282527734SSukumar Swaminathan 
817382527734SSukumar Swaminathan } /* emlxs_sli4_free_xri() */
817482527734SSukumar Swaminathan 
817582527734SSukumar Swaminathan 
817682527734SSukumar Swaminathan static int
817782527734SSukumar Swaminathan emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
817882527734SSukumar Swaminathan {
817982527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
818082527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
8181a9800bebSGarrett D'Amore 	XRIobj_t	*xrip;
818282527734SSukumar Swaminathan 	MATCHMAP	*mp;
818382527734SSukumar Swaminathan 	mbox_req_hdr_t 	*hdr_req;
8184*8f23e9faSHans Rosenfeld 	uint32_t	i;
8185*8f23e9faSHans Rosenfeld 	uint32_t	cnt;
8186*8f23e9faSHans Rosenfeld 	uint32_t	xri_cnt;
8187*8f23e9faSHans Rosenfeld 	uint32_t	j;
818882527734SSukumar Swaminathan 	uint32_t	size;
818982527734SSukumar Swaminathan 	IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
819082527734SSukumar Swaminathan 
819182527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
819282527734SSukumar Swaminathan 	mbq->bp = NULL;
819382527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
819482527734SSukumar Swaminathan 
819582527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
819682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
819782527734SSukumar Swaminathan 		    "Unable to POST_SGL. Mailbox cmd=%x  ",
819882527734SSukumar Swaminathan 		    mb->mbxCommand);
819982527734SSukumar Swaminathan 		return (EIO);
820082527734SSukumar Swaminathan 	}
8201a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
820282527734SSukumar Swaminathan 
820382527734SSukumar Swaminathan 	/*
820482527734SSukumar Swaminathan 	 * Signifies a non embedded command
820582527734SSukumar Swaminathan 	 */
820682527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
820782527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
820882527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
820982527734SSukumar Swaminathan 
821082527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
821182527734SSukumar Swaminathan 	post_sgl =
821282527734SSukumar Swaminathan 	    (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
821382527734SSukumar Swaminathan 
8214a9800bebSGarrett D'Amore 	xrip = hba->sli.sli4.XRIp;
821582527734SSukumar Swaminathan 
8216*8f23e9faSHans Rosenfeld 	/* For each extent */
8217*8f23e9faSHans Rosenfeld 	for (j = 0; j < hba->sli.sli4.XRIExtCount; j++) {
8218*8f23e9faSHans Rosenfeld 		cnt = hba->sli.sli4.XRIExtSize;
8219*8f23e9faSHans Rosenfeld 		while (cnt) {
8220*8f23e9faSHans Rosenfeld 			if (xrip->XRI == 0) {
8221*8f23e9faSHans Rosenfeld 				cnt--;
8222*8f23e9faSHans Rosenfeld 				xrip++;
8223*8f23e9faSHans Rosenfeld 				continue;
8224*8f23e9faSHans Rosenfeld 			}
8225*8f23e9faSHans Rosenfeld 
8226*8f23e9faSHans Rosenfeld 			bzero((void *) hdr_req, mp->size);
8227*8f23e9faSHans Rosenfeld 			size = mp->size - IOCTL_HEADER_SZ;
8228*8f23e9faSHans Rosenfeld 
8229*8f23e9faSHans Rosenfeld 			mb->un.varSLIConfig.be.payload_length =
8230*8f23e9faSHans Rosenfeld 			    mp->size;
8231*8f23e9faSHans Rosenfeld 			mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8232*8f23e9faSHans Rosenfeld 			    IOCTL_SUBSYSTEM_FCOE;
8233*8f23e9faSHans Rosenfeld 			mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8234*8f23e9faSHans Rosenfeld 			    FCOE_OPCODE_CFG_POST_SGL_PAGES;
8235*8f23e9faSHans Rosenfeld 			mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8236*8f23e9faSHans Rosenfeld 			mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
8237*8f23e9faSHans Rosenfeld 
8238*8f23e9faSHans Rosenfeld 			hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
8239*8f23e9faSHans Rosenfeld 			hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
8240*8f23e9faSHans Rosenfeld 			hdr_req->timeout = 0;
8241*8f23e9faSHans Rosenfeld 			hdr_req->req_length = size;
8242*8f23e9faSHans Rosenfeld 
8243*8f23e9faSHans Rosenfeld 			post_sgl->params.request.xri_count = 0;
8244*8f23e9faSHans Rosenfeld 			post_sgl->params.request.xri_start = xrip->XRI;
8245*8f23e9faSHans Rosenfeld 
8246*8f23e9faSHans Rosenfeld 			xri_cnt = (size -
8247*8f23e9faSHans Rosenfeld 			    sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
8248*8f23e9faSHans Rosenfeld 			    sizeof (FCOE_SGL_PAGES);
8249*8f23e9faSHans Rosenfeld 
8250*8f23e9faSHans Rosenfeld 			for (i = 0; (i < xri_cnt) && cnt; i++) {
8251*8f23e9faSHans Rosenfeld 				post_sgl->params.request.xri_count++;
8252*8f23e9faSHans Rosenfeld 				post_sgl->params.request.pages[i].\
8253*8f23e9faSHans Rosenfeld 				    sgl_page0.addrLow =
8254*8f23e9faSHans Rosenfeld 				    PADDR_LO(xrip->SGList.phys);
8255*8f23e9faSHans Rosenfeld 				post_sgl->params.request.pages[i].\
8256*8f23e9faSHans Rosenfeld 				    sgl_page0.addrHigh =
8257*8f23e9faSHans Rosenfeld 				    PADDR_HI(xrip->SGList.phys);
8258*8f23e9faSHans Rosenfeld 
8259*8f23e9faSHans Rosenfeld 				cnt--;
8260*8f23e9faSHans Rosenfeld 				xrip++;
8261*8f23e9faSHans Rosenfeld 			}
8262*8f23e9faSHans Rosenfeld 
8263*8f23e9faSHans Rosenfeld 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8264*8f23e9faSHans Rosenfeld 			    MBX_SUCCESS) {
8265*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8266*8f23e9faSHans Rosenfeld 				    "Unable to POST_SGL. Mailbox cmd=%x "
8267*8f23e9faSHans Rosenfeld 				    "status=%x XRI cnt:%d start:%d",
8268*8f23e9faSHans Rosenfeld 				    mb->mbxCommand, mb->mbxStatus,
8269*8f23e9faSHans Rosenfeld 				    post_sgl->params.request.xri_count,
8270*8f23e9faSHans Rosenfeld 				    post_sgl->params.request.xri_start);
8271*8f23e9faSHans Rosenfeld 				emlxs_mem_buf_free(hba, mp);
8272*8f23e9faSHans Rosenfeld 				mbq->nonembed = NULL;
8273*8f23e9faSHans Rosenfeld 				return (EIO);
827482527734SSukumar Swaminathan 			}
827582527734SSukumar Swaminathan 		}
827682527734SSukumar Swaminathan 	}
8277*8f23e9faSHans Rosenfeld 
8278a9800bebSGarrett D'Amore 	emlxs_mem_buf_free(hba, mp);
8279a9800bebSGarrett D'Amore 	mbq->nonembed = NULL;
828082527734SSukumar Swaminathan 	return (0);
828182527734SSukumar Swaminathan 
828282527734SSukumar Swaminathan } /* emlxs_sli4_post_sgl_pages() */
828382527734SSukumar Swaminathan 
828482527734SSukumar Swaminathan 
828582527734SSukumar Swaminathan static int
828682527734SSukumar Swaminathan emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
828782527734SSukumar Swaminathan {
828882527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
828982527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
8290*8f23e9faSHans Rosenfeld 	uint32_t 	j;
8291*8f23e9faSHans Rosenfeld 	uint32_t 	k;
829282527734SSukumar Swaminathan 	uint64_t	addr;
829382527734SSukumar Swaminathan 	IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
8294*8f23e9faSHans Rosenfeld 	uint16_t	num_pages;
829582527734SSukumar Swaminathan 
8296*8f23e9faSHans Rosenfeld 	if (!(hba->sli.sli4.param.HDRR)) {
8297*8f23e9faSHans Rosenfeld 		return (0);
8298*8f23e9faSHans Rosenfeld 	}
829982527734SSukumar Swaminathan 
8300*8f23e9faSHans Rosenfeld 	/* Bytes per extent */
8301*8f23e9faSHans Rosenfeld 	j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
8302*8f23e9faSHans Rosenfeld 
8303*8f23e9faSHans Rosenfeld 	/* Pages required per extent (page == 4096 bytes) */
8304*8f23e9faSHans Rosenfeld 	num_pages = (j/4096) + ((j%4096)? 1:0);
830582527734SSukumar Swaminathan 
830682527734SSukumar Swaminathan 	addr = hba->sli.sli4.HeaderTmplate.phys;
830782527734SSukumar Swaminathan 
8308*8f23e9faSHans Rosenfeld 	/* For each extent */
8309*8f23e9faSHans Rosenfeld 	for (j = 0; j < hba->sli.sli4.RPIExtCount; j++) {
8310*8f23e9faSHans Rosenfeld 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
8311*8f23e9faSHans Rosenfeld 		mbq->bp = NULL;
8312*8f23e9faSHans Rosenfeld 		mbq->mbox_cmpl = NULL;
8313*8f23e9faSHans Rosenfeld 
8314*8f23e9faSHans Rosenfeld 		/*
8315*8f23e9faSHans Rosenfeld 		 * Signifies an embedded command
8316*8f23e9faSHans Rosenfeld 		 */
8317*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.embedded = 1;
8318*8f23e9faSHans Rosenfeld 
8319*8f23e9faSHans Rosenfeld 		mb->mbxCommand = MBX_SLI_CONFIG;
8320*8f23e9faSHans Rosenfeld 		mb->mbxOwner = OWN_HOST;
8321*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.payload_length =
8322*8f23e9faSHans Rosenfeld 		    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
8323*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8324*8f23e9faSHans Rosenfeld 		    IOCTL_SUBSYSTEM_FCOE;
8325*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8326*8f23e9faSHans Rosenfeld 		    FCOE_OPCODE_POST_HDR_TEMPLATES;
8327*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8328*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
8329*8f23e9faSHans Rosenfeld 		    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
8330*8f23e9faSHans Rosenfeld 
8331*8f23e9faSHans Rosenfeld 		post_hdr =
8332*8f23e9faSHans Rosenfeld 		    (IOCTL_FCOE_POST_HDR_TEMPLATES *)
8333*8f23e9faSHans Rosenfeld 		    &mb->un.varSLIConfig.payload;
8334*8f23e9faSHans Rosenfeld 		post_hdr->params.request.num_pages = num_pages;
8335*8f23e9faSHans Rosenfeld 		post_hdr->params.request.rpi_offset = hba->sli.sli4.RPIBase[j];
8336*8f23e9faSHans Rosenfeld 
8337*8f23e9faSHans Rosenfeld 		for (k = 0; k < num_pages; k++) {
8338*8f23e9faSHans Rosenfeld 			post_hdr->params.request.pages[k].addrLow =
8339*8f23e9faSHans Rosenfeld 			    PADDR_LO(addr);
8340*8f23e9faSHans Rosenfeld 			post_hdr->params.request.pages[k].addrHigh =
8341*8f23e9faSHans Rosenfeld 			    PADDR_HI(addr);
8342*8f23e9faSHans Rosenfeld 			addr += 4096;
8343*8f23e9faSHans Rosenfeld 		}
8344*8f23e9faSHans Rosenfeld 
8345*8f23e9faSHans Rosenfeld 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8346*8f23e9faSHans Rosenfeld 		    MBX_SUCCESS) {
8347*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8348*8f23e9faSHans Rosenfeld 			    "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x "
8349*8f23e9faSHans Rosenfeld 			    "status=%x ",
8350*8f23e9faSHans Rosenfeld 			    mb->mbxCommand, mb->mbxStatus);
8351*8f23e9faSHans Rosenfeld 			return (EIO);
8352*8f23e9faSHans Rosenfeld 		}
8353*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0);
835482527734SSukumar Swaminathan 	}
8355*8f23e9faSHans Rosenfeld 
835682527734SSukumar Swaminathan 	return (0);
835782527734SSukumar Swaminathan 
835882527734SSukumar Swaminathan } /* emlxs_sli4_post_hdr_tmplates() */
835982527734SSukumar Swaminathan 
836082527734SSukumar Swaminathan 
836182527734SSukumar Swaminathan static int
836282527734SSukumar Swaminathan emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
836382527734SSukumar Swaminathan {
836482527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
836582527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
836682527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
836782527734SSukumar Swaminathan 	IOCTL_COMMON_EQ_CREATE *eq;
836882527734SSukumar Swaminathan 	IOCTL_COMMON_CQ_CREATE *cq;
836982527734SSukumar Swaminathan 	IOCTL_FCOE_WQ_CREATE *wq;
837082527734SSukumar Swaminathan 	IOCTL_FCOE_RQ_CREATE *rq;
837182527734SSukumar Swaminathan 	IOCTL_COMMON_MQ_CREATE *mq;
8372*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_MQ_CREATE_EXT *mq_ext;
837382527734SSukumar Swaminathan 	emlxs_rqdbu_t	rqdb;
8374a9800bebSGarrett D'Amore 	uint16_t i, j;
8375a9800bebSGarrett D'Amore 	uint16_t num_cq, total_cq;
8376a9800bebSGarrett D'Amore 	uint16_t num_wq, total_wq;
837782527734SSukumar Swaminathan 
837882527734SSukumar Swaminathan 	/*
837982527734SSukumar Swaminathan 	 * The first CQ is reserved for ASYNC events,
838082527734SSukumar Swaminathan 	 * the second is reserved for unsol rcv, the rest
838182527734SSukumar Swaminathan 	 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
838282527734SSukumar Swaminathan 	 */
838382527734SSukumar Swaminathan 
838482527734SSukumar Swaminathan 	total_cq = 0;
838582527734SSukumar Swaminathan 	total_wq = 0;
838682527734SSukumar Swaminathan 
838782527734SSukumar Swaminathan 	/* Create EQ's */
838882527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
838982527734SSukumar Swaminathan 		emlxs_mb_eq_create(hba, mbq, i);
839082527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
839182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
839282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
839382527734SSukumar Swaminathan 			    "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
839482527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
839582527734SSukumar Swaminathan 			return (EIO);
839682527734SSukumar Swaminathan 		}
839782527734SSukumar Swaminathan 		eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
839882527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
839982527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].lastwq = total_wq;
8400*8f23e9faSHans Rosenfeld 		hba->sli.sli4.eq[i].msix_vector = i;
840182527734SSukumar Swaminathan 
8402*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
840382527734SSukumar Swaminathan 		num_wq = cfg[CFG_NUM_WQ].current;
840482527734SSukumar Swaminathan 		num_cq = num_wq;
840582527734SSukumar Swaminathan 		if (i == 0) {
840682527734SSukumar Swaminathan 			/* One for RQ handling, one for mbox/event handling */
840782527734SSukumar Swaminathan 			num_cq += EMLXS_CQ_OFFSET_WQ;
840882527734SSukumar Swaminathan 		}
840982527734SSukumar Swaminathan 
8410*8f23e9faSHans Rosenfeld 		/* Create CQ's */
841182527734SSukumar Swaminathan 		for (j = 0; j < num_cq; j++) {
841282527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
841382527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
841482527734SSukumar Swaminathan 
841582527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].eqid =
841682527734SSukumar Swaminathan 			    hba->sli.sli4.eq[i].qid;
841782527734SSukumar Swaminathan 
841882527734SSukumar Swaminathan 			emlxs_mb_cq_create(hba, mbq, total_cq);
841982527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
842082527734SSukumar Swaminathan 			    MBX_SUCCESS) {
842182527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
842282527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
842382527734SSukumar Swaminathan 				    "CQ %d: Mailbox cmd=%x status=%x ",
842482527734SSukumar Swaminathan 				    total_cq, mb->mbxCommand, mb->mbxStatus);
842582527734SSukumar Swaminathan 				return (EIO);
842682527734SSukumar Swaminathan 			}
842782527734SSukumar Swaminathan 			cq = (IOCTL_COMMON_CQ_CREATE *)
842882527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
842982527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].qid =
843082527734SSukumar Swaminathan 			    cq->params.response.CQId;
843182527734SSukumar Swaminathan 
843282527734SSukumar Swaminathan 			switch (total_cq) {
843382527734SSukumar Swaminathan 			case EMLXS_CQ_MBOX:
843482527734SSukumar Swaminathan 				/* First CQ is for async event handling */
843582527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
843682527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP1;
843782527734SSukumar Swaminathan 				break;
843882527734SSukumar Swaminathan 
843982527734SSukumar Swaminathan 			case EMLXS_CQ_RCV:
844082527734SSukumar Swaminathan 				/* Second CQ is for unsol receive handling */
844182527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
844282527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
844382527734SSukumar Swaminathan 				break;
844482527734SSukumar Swaminathan 
844582527734SSukumar Swaminathan 			default:
844682527734SSukumar Swaminathan 				/* Setup CQ to channel mapping */
844782527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
844882527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
844982527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].channelp =
845082527734SSukumar Swaminathan 				    &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
845182527734SSukumar Swaminathan 				break;
845282527734SSukumar Swaminathan 			}
8453*8f23e9faSHans Rosenfeld 			emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb,
8454*8f23e9faSHans Rosenfeld 			    18, 0);
845582527734SSukumar Swaminathan 			total_cq++;
845682527734SSukumar Swaminathan 		}
845782527734SSukumar Swaminathan 
8458*8f23e9faSHans Rosenfeld 		/* Create WQ's */
845982527734SSukumar Swaminathan 		for (j = 0; j < num_wq; j++) {
846082527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
846182527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
846282527734SSukumar Swaminathan 
846382527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
846482527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
846582527734SSukumar Swaminathan 
846682527734SSukumar Swaminathan 			emlxs_mb_wq_create(hba, mbq, total_wq);
846782527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
846882527734SSukumar Swaminathan 			    MBX_SUCCESS) {
846982527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
847082527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
847182527734SSukumar Swaminathan 				    "WQ %d: Mailbox cmd=%x status=%x ",
847282527734SSukumar Swaminathan 				    total_wq, mb->mbxCommand, mb->mbxStatus);
847382527734SSukumar Swaminathan 				return (EIO);
847482527734SSukumar Swaminathan 			}
847582527734SSukumar Swaminathan 			wq = (IOCTL_FCOE_WQ_CREATE *)
847682527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
847782527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].qid =
847882527734SSukumar Swaminathan 			    wq->params.response.WQId;
847982527734SSukumar Swaminathan 
848082527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
848182527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
8482*8f23e9faSHans Rosenfeld 			emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb,
8483*8f23e9faSHans Rosenfeld 			    18, 0);
848482527734SSukumar Swaminathan 			total_wq++;
848582527734SSukumar Swaminathan 		}
8486a9800bebSGarrett D'Amore 		hba->last_msiid = i;
848782527734SSukumar Swaminathan 	}
848882527734SSukumar Swaminathan 
848982527734SSukumar Swaminathan 	/* We assume 1 RQ pair will handle ALL incoming data */
849082527734SSukumar Swaminathan 	/* Create RQs */
849182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
849282527734SSukumar Swaminathan 		/* Personalize the RQ */
849382527734SSukumar Swaminathan 		switch (i) {
849482527734SSukumar Swaminathan 		case 0:
849582527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
849682527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
849782527734SSukumar Swaminathan 			break;
849882527734SSukumar Swaminathan 		case 1:
849982527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
850082527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
850182527734SSukumar Swaminathan 			break;
850282527734SSukumar Swaminathan 		default:
850382527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid = 0xffff;
850482527734SSukumar Swaminathan 		}
850582527734SSukumar Swaminathan 
850682527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
850782527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
850882527734SSukumar Swaminathan 
850982527734SSukumar Swaminathan 		emlxs_mb_rq_create(hba, mbq, i);
851082527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
851182527734SSukumar Swaminathan 		    MBX_SUCCESS) {
851282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
851382527734SSukumar Swaminathan 			    "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
851482527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
851582527734SSukumar Swaminathan 			return (EIO);
851682527734SSukumar Swaminathan 		}
8517*8f23e9faSHans Rosenfeld 
851882527734SSukumar Swaminathan 		rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
851982527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
8520*8f23e9faSHans Rosenfeld 		emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0);
852182527734SSukumar Swaminathan 
852282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
852382527734SSukumar Swaminathan 		    "RQ CREATE: rq[%d].qid=%d cqid=%d",
852482527734SSukumar Swaminathan 		    i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
852582527734SSukumar Swaminathan 
852682527734SSukumar Swaminathan 		/* Initialize the host_index */
852782527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].host_index = 0;
852882527734SSukumar Swaminathan 
852982527734SSukumar Swaminathan 		/* If Data queue was just created, */
853082527734SSukumar Swaminathan 		/* then post buffers using the header qid */
853182527734SSukumar Swaminathan 		if ((i & 0x1)) {
853282527734SSukumar Swaminathan 			/* Ring the RQ doorbell to post buffers */
853382527734SSukumar Swaminathan 			rqdb.word = 0;
853482527734SSukumar Swaminathan 			rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
853582527734SSukumar Swaminathan 			rqdb.db.NumPosted = RQB_COUNT;
853682527734SSukumar Swaminathan 
8537*8f23e9faSHans Rosenfeld 			emlxs_sli4_write_rqdb(hba, rqdb.word);
853882527734SSukumar Swaminathan 
853982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
854082527734SSukumar Swaminathan 			    "RQ CREATE: Doorbell rang: qid=%d count=%d",
854182527734SSukumar Swaminathan 			    hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
854282527734SSukumar Swaminathan 		}
854382527734SSukumar Swaminathan 	}
854482527734SSukumar Swaminathan 
854582527734SSukumar Swaminathan 	/* Create MQ */
854682527734SSukumar Swaminathan 
854782527734SSukumar Swaminathan 	/* Personalize the MQ */
854882527734SSukumar Swaminathan 	hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
854982527734SSukumar Swaminathan 
855082527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
855182527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
855282527734SSukumar Swaminathan 
8553*8f23e9faSHans Rosenfeld 	emlxs_mb_mq_create_ext(hba, mbq);
855482527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
855582527734SSukumar Swaminathan 	    MBX_SUCCESS) {
855682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8557*8f23e9faSHans Rosenfeld 		    "Unable to Create MQ_EXT %d: Mailbox cmd=%x status=%x ",
855882527734SSukumar Swaminathan 		    i, mb->mbxCommand, mb->mbxStatus);
855982527734SSukumar Swaminathan 
8560a9800bebSGarrett D'Amore 		/* Reuse mbq from previous mbox */
8561a9800bebSGarrett D'Amore 		bzero(mbq, sizeof (MAILBOXQ));
856282527734SSukumar Swaminathan 
8563a9800bebSGarrett D'Amore 		emlxs_mb_mq_create(hba, mbq);
8564a9800bebSGarrett D'Amore 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8565a9800bebSGarrett D'Amore 		    MBX_SUCCESS) {
8566a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8567a9800bebSGarrett D'Amore 			    "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
8568a9800bebSGarrett D'Amore 			    i, mb->mbxCommand, mb->mbxStatus);
8569a9800bebSGarrett D'Amore 			return (EIO);
8570a9800bebSGarrett D'Amore 		}
857182527734SSukumar Swaminathan 
8572a9800bebSGarrett D'Amore 		mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
8573a9800bebSGarrett D'Amore 		hba->sli.sli4.mq.qid = mq->params.response.MQId;
857482527734SSukumar Swaminathan 		return (0);
857582527734SSukumar Swaminathan 	}
857682527734SSukumar Swaminathan 
8577*8f23e9faSHans Rosenfeld 	mq_ext = (IOCTL_COMMON_MQ_CREATE_EXT *)&mb->un.varSLIConfig.payload;
8578*8f23e9faSHans Rosenfeld 	hba->sli.sli4.mq.qid = mq_ext->params.response.MQId;
857982527734SSukumar Swaminathan 	return (0);
858082527734SSukumar Swaminathan 
8581a9800bebSGarrett D'Amore } /* emlxs_sli4_create_queues() */
858282527734SSukumar Swaminathan 
858382527734SSukumar Swaminathan 
858482527734SSukumar Swaminathan extern void
858582527734SSukumar Swaminathan emlxs_sli4_timer(emlxs_hba_t *hba)
858682527734SSukumar Swaminathan {
858782527734SSukumar Swaminathan 	/* Perform SLI4 level timer checks */
858882527734SSukumar Swaminathan 
8589a9800bebSGarrett D'Amore 	emlxs_fcf_timer_notify(hba);
8590a9800bebSGarrett D'Amore 
859182527734SSukumar Swaminathan 	emlxs_sli4_timer_check_mbox(hba);
859282527734SSukumar Swaminathan 
859382527734SSukumar Swaminathan 	return;
859482527734SSukumar Swaminathan 
859582527734SSukumar Swaminathan } /* emlxs_sli4_timer() */
859682527734SSukumar Swaminathan 
859782527734SSukumar Swaminathan 
859882527734SSukumar Swaminathan static void
859982527734SSukumar Swaminathan emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
860082527734SSukumar Swaminathan {
860182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
860282527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
860382527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
860482527734SSukumar Swaminathan 
860582527734SSukumar Swaminathan 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
860682527734SSukumar Swaminathan 		return;
860782527734SSukumar Swaminathan 	}
860882527734SSukumar Swaminathan 
860982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
861082527734SSukumar Swaminathan 
861182527734SSukumar Swaminathan 	/* Return if timer hasn't expired */
861282527734SSukumar Swaminathan 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
861382527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
861482527734SSukumar Swaminathan 		return;
861582527734SSukumar Swaminathan 	}
8616a9800bebSGarrett D'Amore 
8617a9800bebSGarrett D'Amore 	/* The first to service the mbox queue will clear the timer */
861882527734SSukumar Swaminathan 	hba->mbox_timer = 0;
861982527734SSukumar Swaminathan 
862082527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
862182527734SSukumar Swaminathan 		if (hba->mbox_mbq) {
862282527734SSukumar Swaminathan 			mb = (MAILBOX *)hba->mbox_mbq;
862382527734SSukumar Swaminathan 		}
862482527734SSukumar Swaminathan 	}
862582527734SSukumar Swaminathan 
862682527734SSukumar Swaminathan 	if (mb) {
862782527734SSukumar Swaminathan 		switch (hba->mbox_queue_flag) {
862882527734SSukumar Swaminathan 		case MBX_NOWAIT:
862982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
863082527734SSukumar Swaminathan 			    "%s: Nowait.",
863182527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
863282527734SSukumar Swaminathan 			break;
863382527734SSukumar Swaminathan 
863482527734SSukumar Swaminathan 		case MBX_SLEEP:
863582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
863682527734SSukumar Swaminathan 			    "%s: mb=%p Sleep.",
863782527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
863882527734SSukumar Swaminathan 			    mb);
863982527734SSukumar Swaminathan 			break;
864082527734SSukumar Swaminathan 
864182527734SSukumar Swaminathan 		case MBX_POLL:
864282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
864382527734SSukumar Swaminathan 			    "%s: mb=%p Polled.",
864482527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
864582527734SSukumar Swaminathan 			    mb);
864682527734SSukumar Swaminathan 			break;
864782527734SSukumar Swaminathan 
864882527734SSukumar Swaminathan 		default:
864982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
865082527734SSukumar Swaminathan 			    "%s: mb=%p (%d).",
865182527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
865282527734SSukumar Swaminathan 			    mb, hba->mbox_queue_flag);
865382527734SSukumar Swaminathan 			break;
865482527734SSukumar Swaminathan 		}
865582527734SSukumar Swaminathan 	} else {
865682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
865782527734SSukumar Swaminathan 	}
865882527734SSukumar Swaminathan 
865982527734SSukumar Swaminathan 	hba->flag |= FC_MBOX_TIMEOUT;
866082527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
866182527734SSukumar Swaminathan 
866282527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
866382527734SSukumar Swaminathan 
866482527734SSukumar Swaminathan 	/* Perform mailbox cleanup */
866582527734SSukumar Swaminathan 	/* This will wake any sleeping or polling threads */
866682527734SSukumar Swaminathan 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
866782527734SSukumar Swaminathan 
866882527734SSukumar Swaminathan 	/* Trigger adapter shutdown */
8669a9800bebSGarrett D'Amore 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
867082527734SSukumar Swaminathan 
867182527734SSukumar Swaminathan 	return;
867282527734SSukumar Swaminathan 
867382527734SSukumar Swaminathan } /* emlxs_sli4_timer_check_mbox() */
867482527734SSukumar Swaminathan 
867582527734SSukumar Swaminathan 
867682527734SSukumar Swaminathan extern void
8677a9800bebSGarrett D'Amore emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
867882527734SSukumar Swaminathan {
867982527734SSukumar Swaminathan 	void *msg;
868082527734SSukumar Swaminathan 
8681*8f23e9faSHans Rosenfeld 	if (!port || !str || !iptr || !cnt) {
8682*8f23e9faSHans Rosenfeld 		return;
8683*8f23e9faSHans Rosenfeld 	}
8684*8f23e9faSHans Rosenfeld 
868582527734SSukumar Swaminathan 	if (err) {
868682527734SSukumar Swaminathan 		msg = &emlxs_sli_err_msg;
868782527734SSukumar Swaminathan 	} else {
868882527734SSukumar Swaminathan 		msg = &emlxs_sli_detail_msg;
868982527734SSukumar Swaminathan 	}
869082527734SSukumar Swaminathan 
869182527734SSukumar Swaminathan 	if (cnt) {
869282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8693*8f23e9faSHans Rosenfeld 		    "%s00: %08x %08x %08x %08x %08x %08x", str, *iptr,
869482527734SSukumar Swaminathan 		    *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
869582527734SSukumar Swaminathan 	}
869682527734SSukumar Swaminathan 	if (cnt > 6) {
869782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
8698*8f23e9faSHans Rosenfeld 		    "%s06: %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
869982527734SSukumar Swaminathan 		    *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
870082527734SSukumar Swaminathan 	}
870182527734SSukumar Swaminathan 	if (cnt > 12) {
870282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
870382527734SSukumar Swaminathan 		    "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
870482527734SSukumar Swaminathan 		    *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
870582527734SSukumar Swaminathan 	}
870682527734SSukumar Swaminathan 	if (cnt > 18) {
870782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
870882527734SSukumar Swaminathan 		    "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
870982527734SSukumar Swaminathan 		    *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
871082527734SSukumar Swaminathan 	}
871182527734SSukumar Swaminathan 	if (cnt > 24) {
871282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
871382527734SSukumar Swaminathan 		    "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
871482527734SSukumar Swaminathan 		    *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
871582527734SSukumar Swaminathan 	}
871682527734SSukumar Swaminathan 	if (cnt > 30) {
871782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
871882527734SSukumar Swaminathan 		    "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
871982527734SSukumar Swaminathan 		    *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
872082527734SSukumar Swaminathan 	}
872182527734SSukumar Swaminathan 	if (cnt > 36) {
872282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
872382527734SSukumar Swaminathan 		    "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
872482527734SSukumar Swaminathan 		    *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
872582527734SSukumar Swaminathan 	}
872682527734SSukumar Swaminathan 
872782527734SSukumar Swaminathan } /* emlxs_data_dump() */
872882527734SSukumar Swaminathan 
872982527734SSukumar Swaminathan 
873082527734SSukumar Swaminathan extern void
873182527734SSukumar Swaminathan emlxs_ue_dump(emlxs_hba_t *hba, char *str)
873282527734SSukumar Swaminathan {
873382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
8734*8f23e9faSHans Rosenfeld 	uint32_t status;
873582527734SSukumar Swaminathan 	uint32_t ue_h;
873682527734SSukumar Swaminathan 	uint32_t ue_l;
873782527734SSukumar Swaminathan 	uint32_t on1;
873882527734SSukumar Swaminathan 	uint32_t on2;
873982527734SSukumar Swaminathan 
8740*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8741*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
8742*8f23e9faSHans Rosenfeld 		ue_l = ddi_get32(hba->pci_acc_handle,
8743*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
8744*8f23e9faSHans Rosenfeld 		ue_h = ddi_get32(hba->pci_acc_handle,
8745*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
874682527734SSukumar Swaminathan 
8747*8f23e9faSHans Rosenfeld 		on1 = ddi_get32(hba->pci_acc_handle,
8748*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
8749*8f23e9faSHans Rosenfeld 		on2 = ddi_get32(hba->pci_acc_handle,
8750*8f23e9faSHans Rosenfeld 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
8751*8f23e9faSHans Rosenfeld 
8752*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8753*8f23e9faSHans Rosenfeld 		    "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
8754*8f23e9faSHans Rosenfeld 		    ue_l, ue_h, on1, on2);
8755*8f23e9faSHans Rosenfeld 		break;
8756*8f23e9faSHans Rosenfeld 
8757*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
8758*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8759*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.STATUS_reg_addr);
8760*8f23e9faSHans Rosenfeld 
8761*8f23e9faSHans Rosenfeld 		ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8762*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
8763*8f23e9faSHans Rosenfeld 		ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8764*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
8765*8f23e9faSHans Rosenfeld 
8766*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8767*8f23e9faSHans Rosenfeld 		    "%s: status:%08x err1:%08x err2:%08x", str,
8768*8f23e9faSHans Rosenfeld 		    status, ue_l, ue_h);
8769*8f23e9faSHans Rosenfeld 
8770*8f23e9faSHans Rosenfeld 		break;
8771*8f23e9faSHans Rosenfeld 	}
877282527734SSukumar Swaminathan 
877382527734SSukumar Swaminathan #ifdef FMA_SUPPORT
877482527734SSukumar Swaminathan 	/* Access handle validation */
877582527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
877682527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
877782527734SSukumar Swaminathan 
877882527734SSukumar Swaminathan } /* emlxs_ue_dump() */
877982527734SSukumar Swaminathan 
878082527734SSukumar Swaminathan 
8781a9800bebSGarrett D'Amore static void
878282527734SSukumar Swaminathan emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
878382527734SSukumar Swaminathan {
878482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
8785*8f23e9faSHans Rosenfeld 	uint32_t status;
878682527734SSukumar Swaminathan 	uint32_t ue_h;
878782527734SSukumar Swaminathan 	uint32_t ue_l;
8788*8f23e9faSHans Rosenfeld 	uint32_t error = 0;
878982527734SSukumar Swaminathan 
879082527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
879182527734SSukumar Swaminathan 		return;
879282527734SSukumar Swaminathan 	}
879382527734SSukumar Swaminathan 
8794*8f23e9faSHans Rosenfeld 	switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8795*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_0:
8796*8f23e9faSHans Rosenfeld 		ue_l = ddi_get32(hba->pci_acc_handle,
8797*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR1_reg_addr);
8798*8f23e9faSHans Rosenfeld 		ue_h = ddi_get32(hba->pci_acc_handle,
8799*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.ERR2_reg_addr);
8800*8f23e9faSHans Rosenfeld 
8801*8f23e9faSHans Rosenfeld 		if ((~hba->sli.sli4.ue_mask_lo & ue_l) ||
8802*8f23e9faSHans Rosenfeld 		    (~hba->sli.sli4.ue_mask_hi & ue_h) ||
8803*8f23e9faSHans Rosenfeld 		    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8804*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
8805*8f23e9faSHans Rosenfeld 			    "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
8806*8f23e9faSHans Rosenfeld 			    "maskHigh:%08x flag:%08x",
8807*8f23e9faSHans Rosenfeld 			    ue_l, ue_h, hba->sli.sli4.ue_mask_lo,
8808*8f23e9faSHans Rosenfeld 			    hba->sli.sli4.ue_mask_hi, hba->sli.sli4.flag);
8809*8f23e9faSHans Rosenfeld 
8810*8f23e9faSHans Rosenfeld 			error = 2;
8811*8f23e9faSHans Rosenfeld 		}
8812*8f23e9faSHans Rosenfeld 		break;
8813*8f23e9faSHans Rosenfeld 
8814*8f23e9faSHans Rosenfeld 	case SLI_INTF_IF_TYPE_2:
8815*8f23e9faSHans Rosenfeld 		status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8816*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.STATUS_reg_addr);
8817*8f23e9faSHans Rosenfeld 
8818*8f23e9faSHans Rosenfeld 		if ((status & SLI_STATUS_ERROR) ||
8819*8f23e9faSHans Rosenfeld 		    (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8820*8f23e9faSHans Rosenfeld 			ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8821*8f23e9faSHans Rosenfeld 			    hba->sli.sli4.ERR1_reg_addr);
8822*8f23e9faSHans Rosenfeld 			ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8823*8f23e9faSHans Rosenfeld 			    hba->sli.sli4.ERR2_reg_addr);
8824*8f23e9faSHans Rosenfeld 
8825*8f23e9faSHans Rosenfeld 			error = (status & SLI_STATUS_RESET_NEEDED)? 1:2;
882682527734SSukumar Swaminathan 
8827*8f23e9faSHans Rosenfeld 			if (error == 1) {
8828*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8829*8f23e9faSHans Rosenfeld 				    "Host Error: status:%08x err1:%08x "
8830*8f23e9faSHans Rosenfeld 				    "err2:%08x flag:%08x",
8831*8f23e9faSHans Rosenfeld 				    status, ue_l, ue_h, hba->sli.sli4.flag);
8832*8f23e9faSHans Rosenfeld 			} else {
8833*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
8834*8f23e9faSHans Rosenfeld 				    &emlxs_hardware_error_msg,
8835*8f23e9faSHans Rosenfeld 				    "Host Error: status:%08x err1:%08x "
8836*8f23e9faSHans Rosenfeld 				    "err2:%08x flag:%08x",
8837*8f23e9faSHans Rosenfeld 				    status, ue_l, ue_h, hba->sli.sli4.flag);
8838*8f23e9faSHans Rosenfeld 			}
8839*8f23e9faSHans Rosenfeld 		}
8840*8f23e9faSHans Rosenfeld 		break;
8841*8f23e9faSHans Rosenfeld 	}
884282527734SSukumar Swaminathan 
8843*8f23e9faSHans Rosenfeld 	if (error == 2) {
884482527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
884582527734SSukumar Swaminathan 
884682527734SSukumar Swaminathan 		emlxs_sli4_hba_flush_chipq(hba);
884782527734SSukumar Swaminathan 
8848a9800bebSGarrett D'Amore 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
8849*8f23e9faSHans Rosenfeld 
8850*8f23e9faSHans Rosenfeld 	} else if (error == 1) {
8851*8f23e9faSHans Rosenfeld 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
8852*8f23e9faSHans Rosenfeld 
8853*8f23e9faSHans Rosenfeld 		emlxs_sli4_hba_flush_chipq(hba);
8854*8f23e9faSHans Rosenfeld 
8855*8f23e9faSHans Rosenfeld 		emlxs_thread_spawn(hba, emlxs_restart_thread, 0, 0);
885682527734SSukumar Swaminathan 	}
885782527734SSukumar Swaminathan 
8858*8f23e9faSHans Rosenfeld #ifdef FMA_SUPPORT
8859*8f23e9faSHans Rosenfeld 	/* Access handle validation */
8860*8f23e9faSHans Rosenfeld 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
8861*8f23e9faSHans Rosenfeld #endif  /* FMA_SUPPORT */
8862*8f23e9faSHans Rosenfeld 
886382527734SSukumar Swaminathan } /* emlxs_sli4_poll_erratt() */
886482527734SSukumar Swaminathan 
8865a9800bebSGarrett D'Amore 
8866*8f23e9faSHans Rosenfeld static uint32_t
8867a9800bebSGarrett D'Amore emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
8868a9800bebSGarrett D'Amore     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
886982527734SSukumar Swaminathan {
887082527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
8871a9800bebSGarrett D'Amore 	NODELIST	*node;
8872a9800bebSGarrett D'Amore 	RPIobj_t	*rpip;
8873a9800bebSGarrett D'Amore 	uint32_t	rval;
8874a9800bebSGarrett D'Amore 
8875a9800bebSGarrett D'Amore 	/* Check for invalid node ids to register */
8876a9800bebSGarrett D'Amore 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8877a9800bebSGarrett D'Amore 		return (1);
8878a9800bebSGarrett D'Amore 	}
8879a9800bebSGarrett D'Amore 
8880a9800bebSGarrett D'Amore 	if (did & 0xff000000) {
8881a9800bebSGarrett D'Amore 		return (1);
8882a9800bebSGarrett D'Amore 	}
8883a9800bebSGarrett D'Amore 
8884*8f23e9faSHans Rosenfeld 	/* We don't register our own did */
8885*8f23e9faSHans Rosenfeld 	if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8886a9800bebSGarrett D'Amore 		return (1);
8887a9800bebSGarrett D'Amore 	}
8888a9800bebSGarrett D'Amore 
8889*8f23e9faSHans Rosenfeld 	if (did != FABRIC_DID) {
8890*8f23e9faSHans Rosenfeld 		if ((rval = emlxs_mb_check_sparm(hba, param))) {
8891*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8892*8f23e9faSHans Rosenfeld 			    "Invalid service parameters. did=%06x rval=%d", did,
8893*8f23e9faSHans Rosenfeld 			    rval);
8894*8f23e9faSHans Rosenfeld 
8895*8f23e9faSHans Rosenfeld 			return (1);
8896*8f23e9faSHans Rosenfeld 		}
8897*8f23e9faSHans Rosenfeld 	}
8898*8f23e9faSHans Rosenfeld 
8899a9800bebSGarrett D'Amore 	/* Check if the node limit has been reached */
8900a9800bebSGarrett D'Amore 	if (port->node_count >= hba->max_nodes) {
8901a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8902a9800bebSGarrett D'Amore 		    "Limit reached. did=%06x count=%d", did,
8903a9800bebSGarrett D'Amore 		    port->node_count);
8904a9800bebSGarrett D'Amore 
8905a9800bebSGarrett D'Amore 		return (1);
8906a9800bebSGarrett D'Amore 	}
8907a9800bebSGarrett D'Amore 
8908*8f23e9faSHans Rosenfeld 	node = emlxs_node_find_did(port, did, 1);
8909a9800bebSGarrett D'Amore 	rpip = EMLXS_NODE_TO_RPI(port, node);
8910a9800bebSGarrett D'Amore 
8911a9800bebSGarrett D'Amore 	rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp,
8912a9800bebSGarrett D'Amore 	    (void *)ubp, (void *)iocbq);
8913a9800bebSGarrett D'Amore 
8914a9800bebSGarrett D'Amore 	return (rval);
8915a9800bebSGarrett D'Amore 
8916a9800bebSGarrett D'Amore } /* emlxs_sli4_reg_did() */
8917a9800bebSGarrett D'Amore 
8918a9800bebSGarrett D'Amore 
8919*8f23e9faSHans Rosenfeld static uint32_t
8920a9800bebSGarrett D'Amore emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node,
8921a9800bebSGarrett D'Amore     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
8922a9800bebSGarrett D'Amore {
8923a9800bebSGarrett D'Amore 	RPIobj_t	*rpip;
8924a9800bebSGarrett D'Amore 	uint32_t	rval;
8925a9800bebSGarrett D'Amore 
8926a9800bebSGarrett D'Amore 	if (!node) {
8927a9800bebSGarrett D'Amore 		/* Unreg all nodes */
8928a9800bebSGarrett D'Amore 		(void) emlxs_sli4_unreg_all_nodes(port);
8929a9800bebSGarrett D'Amore 		return (1);
8930a9800bebSGarrett D'Amore 	}
8931a9800bebSGarrett D'Amore 
8932a9800bebSGarrett D'Amore 	/* Check for base node */
8933a9800bebSGarrett D'Amore 	if (node == &port->node_base) {
8934a9800bebSGarrett D'Amore 		/* Just flush base node */
8935a9800bebSGarrett D'Amore 		(void) emlxs_tx_node_flush(port, &port->node_base,
8936a9800bebSGarrett D'Amore 		    0, 0, 0);
8937a9800bebSGarrett D'Amore 
8938a9800bebSGarrett D'Amore 		(void) emlxs_chipq_node_flush(port, 0,
8939a9800bebSGarrett D'Amore 		    &port->node_base, 0);
8940a9800bebSGarrett D'Amore 
8941a9800bebSGarrett D'Amore 		port->did = 0;
8942a9800bebSGarrett D'Amore 
8943a9800bebSGarrett D'Amore 		/* Return now */
8944a9800bebSGarrett D'Amore 		return (1);
8945a9800bebSGarrett D'Amore 	}
8946a9800bebSGarrett D'Amore 
8947a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8948a9800bebSGarrett D'Amore 	    "unreg_node:%p did=%x rpi=%d",
8949a9800bebSGarrett D'Amore 	    node, node->nlp_DID, node->nlp_Rpi);
8950a9800bebSGarrett D'Amore 
8951a9800bebSGarrett D'Amore 	rpip = EMLXS_NODE_TO_RPI(port, node);
8952a9800bebSGarrett D'Amore 
8953a9800bebSGarrett D'Amore 	if (!rpip) {
8954*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8955a9800bebSGarrett D'Amore 		    "unreg_node:%p did=%x rpi=%d. RPI not found.",
8956a9800bebSGarrett D'Amore 		    node, node->nlp_DID, node->nlp_Rpi);
8957a9800bebSGarrett D'Amore 
8958a9800bebSGarrett D'Amore 		emlxs_node_rm(port, node);
8959a9800bebSGarrett D'Amore 		return (1);
8960a9800bebSGarrett D'Amore 	}
8961a9800bebSGarrett D'Amore 
8962a9800bebSGarrett D'Amore 	rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp,
8963a9800bebSGarrett D'Amore 	    (void *)iocbq);
8964a9800bebSGarrett D'Amore 
8965a9800bebSGarrett D'Amore 	return (rval);
8966a9800bebSGarrett D'Amore 
8967a9800bebSGarrett D'Amore } /* emlxs_sli4_unreg_node() */
8968a9800bebSGarrett D'Amore 
8969a9800bebSGarrett D'Amore 
8970a9800bebSGarrett D'Amore extern uint32_t
8971a9800bebSGarrett D'Amore emlxs_sli4_unreg_all_nodes(emlxs_port_t *port)
8972a9800bebSGarrett D'Amore {
897382527734SSukumar Swaminathan 	NODELIST	*nlp;
897482527734SSukumar Swaminathan 	int		i;
8975a9800bebSGarrett D'Amore 	uint32_t 	found;
897682527734SSukumar Swaminathan 
8977a9800bebSGarrett D'Amore 	/* Set the node tags */
8978a9800bebSGarrett D'Amore 	/* We will process all nodes with this tag */
8979a9800bebSGarrett D'Amore 	rw_enter(&port->node_rwlock, RW_READER);
8980a9800bebSGarrett D'Amore 	found = 0;
898182527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
898282527734SSukumar Swaminathan 		nlp = port->node_table[i];
898382527734SSukumar Swaminathan 		while (nlp != NULL) {
8984a9800bebSGarrett D'Amore 			found = 1;
8985a9800bebSGarrett D'Amore 			nlp->nlp_tag = 1;
8986a9800bebSGarrett D'Amore 			nlp = nlp->nlp_list_next;
898782527734SSukumar Swaminathan 		}
898882527734SSukumar Swaminathan 	}
898982527734SSukumar Swaminathan 	rw_exit(&port->node_rwlock);
899082527734SSukumar Swaminathan 
8991a9800bebSGarrett D'Amore 	if (!found) {
8992a9800bebSGarrett D'Amore 		return (0);
8993a9800bebSGarrett D'Amore 	}
8994a9800bebSGarrett D'Amore 
8995a9800bebSGarrett D'Amore 	for (;;) {
8996a9800bebSGarrett D'Amore 		rw_enter(&port->node_rwlock, RW_READER);
8997a9800bebSGarrett D'Amore 		found = 0;
8998a9800bebSGarrett D'Amore 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
8999a9800bebSGarrett D'Amore 			nlp = port->node_table[i];
9000a9800bebSGarrett D'Amore 			while (nlp != NULL) {
9001a9800bebSGarrett D'Amore 				if (!nlp->nlp_tag) {
9002a9800bebSGarrett D'Amore 					nlp = nlp->nlp_list_next;
9003a9800bebSGarrett D'Amore 					continue;
9004a9800bebSGarrett D'Amore 				}
9005a9800bebSGarrett D'Amore 				nlp->nlp_tag = 0;
9006a9800bebSGarrett D'Amore 				found = 1;
9007a9800bebSGarrett D'Amore 				break;
9008a9800bebSGarrett D'Amore 			}
9009a9800bebSGarrett D'Amore 
9010a9800bebSGarrett D'Amore 			if (found) {
9011a9800bebSGarrett D'Amore 				break;
9012a9800bebSGarrett D'Amore 			}
9013a9800bebSGarrett D'Amore 		}
9014a9800bebSGarrett D'Amore 		rw_exit(&port->node_rwlock);
9015a9800bebSGarrett D'Amore 
9016a9800bebSGarrett D'Amore 		if (!found) {
9017a9800bebSGarrett D'Amore 			break;
9018a9800bebSGarrett D'Amore 		}
9019a9800bebSGarrett D'Amore 
9020a9800bebSGarrett D'Amore 		(void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0);
9021a9800bebSGarrett D'Amore 	}
9022a9800bebSGarrett D'Amore 
902382527734SSukumar Swaminathan 	return (0);
9024a9800bebSGarrett D'Amore 
9025a9800bebSGarrett D'Amore } /* emlxs_sli4_unreg_all_nodes() */
9026*8f23e9faSHans Rosenfeld 
9027*8f23e9faSHans Rosenfeld 
9028*8f23e9faSHans Rosenfeld static void
9029*8f23e9faSHans Rosenfeld emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9030*8f23e9faSHans Rosenfeld {
9031*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
9032*8f23e9faSHans Rosenfeld 
9033*8f23e9faSHans Rosenfeld 	/* Handle link down */
9034*8f23e9faSHans Rosenfeld 	if ((cqe->un.link.link_status == ASYNC_EVENT_LOGICAL_LINK_DOWN) ||
9035*8f23e9faSHans Rosenfeld 	    (cqe->un.link.link_status == ASYNC_EVENT_PHYS_LINK_DOWN)) {
9036*8f23e9faSHans Rosenfeld 		(void) emlxs_fcf_linkdown_notify(port);
9037*8f23e9faSHans Rosenfeld 
9038*8f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
9039*8f23e9faSHans Rosenfeld 		hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9040*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
9041*8f23e9faSHans Rosenfeld 		return;
9042*8f23e9faSHans Rosenfeld 	}
9043*8f23e9faSHans Rosenfeld 
9044*8f23e9faSHans Rosenfeld 	/* Link is up */
9045*8f23e9faSHans Rosenfeld 
9046*8f23e9faSHans Rosenfeld 	/* Set linkspeed */
9047*8f23e9faSHans Rosenfeld 	switch (cqe->un.link.port_speed) {
9048*8f23e9faSHans Rosenfeld 	case PHY_1GHZ_LINK:
9049*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_1GHZ_LINK;
9050*8f23e9faSHans Rosenfeld 		break;
9051*8f23e9faSHans Rosenfeld 	case PHY_10GHZ_LINK:
9052*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_10GHZ_LINK;
9053*8f23e9faSHans Rosenfeld 		break;
9054*8f23e9faSHans Rosenfeld 	default:
9055*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9056*8f23e9faSHans Rosenfeld 		    "sli4_handle_fcoe_link_event: Unknown link speed=%x.",
9057*8f23e9faSHans Rosenfeld 		    cqe->un.link.port_speed);
9058*8f23e9faSHans Rosenfeld 		hba->linkspeed = 0;
9059*8f23e9faSHans Rosenfeld 		break;
9060*8f23e9faSHans Rosenfeld 	}
9061*8f23e9faSHans Rosenfeld 
9062*8f23e9faSHans Rosenfeld 	/* Set qos_linkspeed */
9063*8f23e9faSHans Rosenfeld 	hba->qos_linkspeed = cqe->un.link.qos_link_speed;
9064*8f23e9faSHans Rosenfeld 
9065*8f23e9faSHans Rosenfeld 	/* Set topology */
9066*8f23e9faSHans Rosenfeld 	hba->topology = TOPOLOGY_PT_PT;
9067*8f23e9faSHans Rosenfeld 
9068*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_PORT_LOCK);
9069*8f23e9faSHans Rosenfeld 	hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9070*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_PORT_LOCK);
9071*8f23e9faSHans Rosenfeld 
9072*8f23e9faSHans Rosenfeld 	(void) emlxs_fcf_linkup_notify(port);
9073*8f23e9faSHans Rosenfeld 
9074*8f23e9faSHans Rosenfeld 	return;
9075*8f23e9faSHans Rosenfeld 
9076*8f23e9faSHans Rosenfeld } /* emlxs_sli4_handle_fcoe_link_event()  */
9077*8f23e9faSHans Rosenfeld 
9078*8f23e9faSHans Rosenfeld 
9079*8f23e9faSHans Rosenfeld static void
9080*8f23e9faSHans Rosenfeld emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9081*8f23e9faSHans Rosenfeld {
9082*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
9083*8f23e9faSHans Rosenfeld 
9084*8f23e9faSHans Rosenfeld 	/* Handle link down */
9085*8f23e9faSHans Rosenfeld 	if (cqe->un.fc.att_type == ATT_TYPE_LINK_DOWN) {
9086*8f23e9faSHans Rosenfeld 		(void) emlxs_fcf_linkdown_notify(port);
9087*8f23e9faSHans Rosenfeld 
9088*8f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
9089*8f23e9faSHans Rosenfeld 		hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9090*8f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
9091*8f23e9faSHans Rosenfeld 		return;
9092*8f23e9faSHans Rosenfeld 	}
9093*8f23e9faSHans Rosenfeld 
9094*8f23e9faSHans Rosenfeld 	/* Link is up */
9095*8f23e9faSHans Rosenfeld 
9096*8f23e9faSHans Rosenfeld 	/* Set linkspeed */
9097*8f23e9faSHans Rosenfeld 	switch (cqe->un.fc.port_speed) {
9098*8f23e9faSHans Rosenfeld 	case 1:
9099*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_1GHZ_LINK;
9100*8f23e9faSHans Rosenfeld 		break;
9101*8f23e9faSHans Rosenfeld 	case 2:
9102*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_2GHZ_LINK;
9103*8f23e9faSHans Rosenfeld 		break;
9104*8f23e9faSHans Rosenfeld 	case 4:
9105*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_4GHZ_LINK;
9106*8f23e9faSHans Rosenfeld 		break;
9107*8f23e9faSHans Rosenfeld 	case 8:
9108*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_8GHZ_LINK;
9109*8f23e9faSHans Rosenfeld 		break;
9110*8f23e9faSHans Rosenfeld 	case 10:
9111*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_10GHZ_LINK;
9112*8f23e9faSHans Rosenfeld 		break;
9113*8f23e9faSHans Rosenfeld 	case 16:
9114*8f23e9faSHans Rosenfeld 		hba->linkspeed = LA_16GHZ_LINK;
9115*8f23e9faSHans Rosenfeld 		break;
9116*8f23e9faSHans Rosenfeld 	default:
9117*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9118*8f23e9faSHans Rosenfeld 		    "sli4_handle_fc_link_att: Unknown link speed=%x.",
9119*8f23e9faSHans Rosenfeld 		    cqe->un.fc.port_speed);
9120*8f23e9faSHans Rosenfeld 		hba->linkspeed = 0;
9121*8f23e9faSHans Rosenfeld 		break;
9122*8f23e9faSHans Rosenfeld 	}
9123*8f23e9faSHans Rosenfeld 
9124*8f23e9faSHans Rosenfeld 	/* Set qos_linkspeed */
9125*8f23e9faSHans Rosenfeld 	hba->qos_linkspeed = cqe->un.fc.link_speed;
9126*8f23e9faSHans Rosenfeld 
9127*8f23e9faSHans Rosenfeld 	/* Set topology */
9128*8f23e9faSHans Rosenfeld 	hba->topology = cqe->un.fc.topology;
9129*8f23e9faSHans Rosenfeld 
9130*8f23e9faSHans Rosenfeld 	mutex_enter(&EMLXS_PORT_LOCK);
9131*8f23e9faSHans Rosenfeld 	hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9132*8f23e9faSHans Rosenfeld 	mutex_exit(&EMLXS_PORT_LOCK);
9133*8f23e9faSHans Rosenfeld 
9134*8f23e9faSHans Rosenfeld 	(void) emlxs_fcf_linkup_notify(port);
9135*8f23e9faSHans Rosenfeld 
9136*8f23e9faSHans Rosenfeld 	return;
9137*8f23e9faSHans Rosenfeld 
9138*8f23e9faSHans Rosenfeld } /* emlxs_sli4_handle_fc_link_att() */
9139*8f23e9faSHans Rosenfeld 
9140*8f23e9faSHans Rosenfeld 
9141*8f23e9faSHans Rosenfeld static int
9142*8f23e9faSHans Rosenfeld emlxs_sli4_init_extents(emlxs_hba_t *hba, MAILBOXQ *mbq)
9143*8f23e9faSHans Rosenfeld {
9144*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
9145*8f23e9faSHans Rosenfeld 	MAILBOX4 *mb4;
9146*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_EXTENTS *ep;
9147*8f23e9faSHans Rosenfeld 	uint32_t i;
9148*8f23e9faSHans Rosenfeld 	uint32_t ExtentCnt;
9149*8f23e9faSHans Rosenfeld 
9150*8f23e9faSHans Rosenfeld 	if (!(hba->sli.sli4.param.EXT)) {
9151*8f23e9faSHans Rosenfeld 		return (0);
9152*8f23e9faSHans Rosenfeld 	}
9153*8f23e9faSHans Rosenfeld 
9154*8f23e9faSHans Rosenfeld 	mb4 = (MAILBOX4 *) mbq;
9155*8f23e9faSHans Rosenfeld 
9156*8f23e9faSHans Rosenfeld 	/* Discover XRI Extents */
9157*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9158*8f23e9faSHans Rosenfeld 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_XRI);
9159*8f23e9faSHans Rosenfeld 
9160*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9161*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9162*8f23e9faSHans Rosenfeld 		    "Unable to discover XRI extents.  Mailbox cmd=%x status=%x",
9163*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9164*8f23e9faSHans Rosenfeld 
9165*8f23e9faSHans Rosenfeld 		return (EIO);
9166*8f23e9faSHans Rosenfeld 	}
9167*8f23e9faSHans Rosenfeld 
9168*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9169*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIExtSize = ep->params.response.ExtentSize;
9170*8f23e9faSHans Rosenfeld 	ExtentCnt = ep->params.response.ExtentCnt;
9171*8f23e9faSHans Rosenfeld 
9172*8f23e9faSHans Rosenfeld 	/* Allocate XRI Extents */
9173*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9174*8f23e9faSHans Rosenfeld 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_XRI, ExtentCnt);
9175*8f23e9faSHans Rosenfeld 
9176*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9177*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9178*8f23e9faSHans Rosenfeld 		    "Unable to allocate XRI extents.  Mailbox cmd=%x status=%x",
9179*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9180*8f23e9faSHans Rosenfeld 
9181*8f23e9faSHans Rosenfeld 		return (EIO);
9182*8f23e9faSHans Rosenfeld 	}
9183*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9184*8f23e9faSHans Rosenfeld 
9185*8f23e9faSHans Rosenfeld 	bcopy((uint8_t *)ep->params.response.RscId,
9186*8f23e9faSHans Rosenfeld 	    (uint8_t *)hba->sli.sli4.XRIBase,
9187*8f23e9faSHans Rosenfeld 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9188*8f23e9faSHans Rosenfeld 
9189*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRIExtCount = ep->params.response.ExtentCnt;
9190*8f23e9faSHans Rosenfeld 	hba->sli.sli4.XRICount = hba->sli.sli4.XRIExtCount *
9191*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.XRIExtSize;
9192*8f23e9faSHans Rosenfeld 
9193*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9194*8f23e9faSHans Rosenfeld 	    "XRI Ext: size=%d cnt=%d/%d",
9195*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.XRIExtSize,
9196*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.XRIExtCount, ExtentCnt);
9197*8f23e9faSHans Rosenfeld 
9198*8f23e9faSHans Rosenfeld 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9199*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9200*8f23e9faSHans Rosenfeld 		    "XRI Ext%d: %d, %d, %d, %d", i,
9201*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.XRIBase[i],
9202*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.XRIBase[i+1],
9203*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.XRIBase[i+2],
9204*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.XRIBase[i+3]);
9205*8f23e9faSHans Rosenfeld 	}
9206*8f23e9faSHans Rosenfeld 
9207*8f23e9faSHans Rosenfeld 
9208*8f23e9faSHans Rosenfeld 	/* Discover RPI Extents */
9209*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9210*8f23e9faSHans Rosenfeld 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_RPI);
9211*8f23e9faSHans Rosenfeld 
9212*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9213*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9214*8f23e9faSHans Rosenfeld 		    "Unable to discover RPI extents.  Mailbox cmd=%x status=%x",
9215*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9216*8f23e9faSHans Rosenfeld 
9217*8f23e9faSHans Rosenfeld 		return (EIO);
9218*8f23e9faSHans Rosenfeld 	}
9219*8f23e9faSHans Rosenfeld 
9220*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9221*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPIExtSize = ep->params.response.ExtentSize;
9222*8f23e9faSHans Rosenfeld 	ExtentCnt = ep->params.response.ExtentCnt;
9223*8f23e9faSHans Rosenfeld 
9224*8f23e9faSHans Rosenfeld 	/* Allocate RPI Extents */
9225*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9226*8f23e9faSHans Rosenfeld 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_RPI, ExtentCnt);
9227*8f23e9faSHans Rosenfeld 
9228*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9229*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9230*8f23e9faSHans Rosenfeld 		    "Unable to allocate RPI extents.  Mailbox cmd=%x status=%x",
9231*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9232*8f23e9faSHans Rosenfeld 
9233*8f23e9faSHans Rosenfeld 		return (EIO);
9234*8f23e9faSHans Rosenfeld 	}
9235*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9236*8f23e9faSHans Rosenfeld 
9237*8f23e9faSHans Rosenfeld 	bcopy((uint8_t *)ep->params.response.RscId,
9238*8f23e9faSHans Rosenfeld 	    (uint8_t *)hba->sli.sli4.RPIBase,
9239*8f23e9faSHans Rosenfeld 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9240*8f23e9faSHans Rosenfeld 
9241*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPIExtCount = ep->params.response.ExtentCnt;
9242*8f23e9faSHans Rosenfeld 	hba->sli.sli4.RPICount = hba->sli.sli4.RPIExtCount *
9243*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.RPIExtSize;
9244*8f23e9faSHans Rosenfeld 
9245*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9246*8f23e9faSHans Rosenfeld 	    "RPI Ext: size=%d cnt=%d/%d",
9247*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.RPIExtSize,
9248*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.RPIExtCount, ExtentCnt);
9249*8f23e9faSHans Rosenfeld 
9250*8f23e9faSHans Rosenfeld 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9251*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9252*8f23e9faSHans Rosenfeld 		    "RPI Ext%d: %d, %d, %d, %d", i,
9253*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RPIBase[i],
9254*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RPIBase[i+1],
9255*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RPIBase[i+2],
9256*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.RPIBase[i+3]);
9257*8f23e9faSHans Rosenfeld 	}
9258*8f23e9faSHans Rosenfeld 
9259*8f23e9faSHans Rosenfeld 
9260*8f23e9faSHans Rosenfeld 	/* Discover VPI Extents */
9261*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9262*8f23e9faSHans Rosenfeld 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VPI);
9263*8f23e9faSHans Rosenfeld 
9264*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9265*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9266*8f23e9faSHans Rosenfeld 		    "Unable to discover VPI extents.  Mailbox cmd=%x status=%x",
9267*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9268*8f23e9faSHans Rosenfeld 
9269*8f23e9faSHans Rosenfeld 		return (EIO);
9270*8f23e9faSHans Rosenfeld 	}
9271*8f23e9faSHans Rosenfeld 
9272*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9273*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPIExtSize = ep->params.response.ExtentSize;
9274*8f23e9faSHans Rosenfeld 	ExtentCnt = ep->params.response.ExtentCnt;
9275*8f23e9faSHans Rosenfeld 
9276*8f23e9faSHans Rosenfeld 	/* Allocate VPI Extents */
9277*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9278*8f23e9faSHans Rosenfeld 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VPI, ExtentCnt);
9279*8f23e9faSHans Rosenfeld 
9280*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9281*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9282*8f23e9faSHans Rosenfeld 		    "Unable to allocate VPI extents.  Mailbox cmd=%x status=%x",
9283*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9284*8f23e9faSHans Rosenfeld 
9285*8f23e9faSHans Rosenfeld 		return (EIO);
9286*8f23e9faSHans Rosenfeld 	}
9287*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9288*8f23e9faSHans Rosenfeld 
9289*8f23e9faSHans Rosenfeld 	bcopy((uint8_t *)ep->params.response.RscId,
9290*8f23e9faSHans Rosenfeld 	    (uint8_t *)hba->sli.sli4.VPIBase,
9291*8f23e9faSHans Rosenfeld 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9292*8f23e9faSHans Rosenfeld 
9293*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPIExtCount = ep->params.response.ExtentCnt;
9294*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VPICount = hba->sli.sli4.VPIExtCount *
9295*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VPIExtSize;
9296*8f23e9faSHans Rosenfeld 
9297*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9298*8f23e9faSHans Rosenfeld 	    "VPI Ext: size=%d cnt=%d/%d",
9299*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VPIExtSize,
9300*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VPIExtCount, ExtentCnt);
9301*8f23e9faSHans Rosenfeld 
9302*8f23e9faSHans Rosenfeld 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9303*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9304*8f23e9faSHans Rosenfeld 		    "VPI Ext%d: %d, %d, %d, %d", i,
9305*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VPIBase[i],
9306*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VPIBase[i+1],
9307*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VPIBase[i+2],
9308*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VPIBase[i+3]);
9309*8f23e9faSHans Rosenfeld 	}
9310*8f23e9faSHans Rosenfeld 
9311*8f23e9faSHans Rosenfeld 	/* Discover VFI Extents */
9312*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9313*8f23e9faSHans Rosenfeld 	emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VFI);
9314*8f23e9faSHans Rosenfeld 
9315*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9316*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9317*8f23e9faSHans Rosenfeld 		    "Unable to discover VFI extents.  Mailbox cmd=%x status=%x",
9318*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9319*8f23e9faSHans Rosenfeld 
9320*8f23e9faSHans Rosenfeld 		return (EIO);
9321*8f23e9faSHans Rosenfeld 	}
9322*8f23e9faSHans Rosenfeld 
9323*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9324*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFIExtSize = ep->params.response.ExtentSize;
9325*8f23e9faSHans Rosenfeld 	ExtentCnt = ep->params.response.ExtentCnt;
9326*8f23e9faSHans Rosenfeld 
9327*8f23e9faSHans Rosenfeld 	/* Allocate VFI Extents */
9328*8f23e9faSHans Rosenfeld 	bzero(mbq, sizeof (MAILBOXQ));
9329*8f23e9faSHans Rosenfeld 	emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VFI, ExtentCnt);
9330*8f23e9faSHans Rosenfeld 
9331*8f23e9faSHans Rosenfeld 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9332*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9333*8f23e9faSHans Rosenfeld 		    "Unable to allocate VFI extents.  Mailbox cmd=%x status=%x",
9334*8f23e9faSHans Rosenfeld 		    mb4->mbxCommand, mb4->mbxStatus);
9335*8f23e9faSHans Rosenfeld 
9336*8f23e9faSHans Rosenfeld 		return (EIO);
9337*8f23e9faSHans Rosenfeld 	}
9338*8f23e9faSHans Rosenfeld 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9339*8f23e9faSHans Rosenfeld 
9340*8f23e9faSHans Rosenfeld 	bcopy((uint8_t *)ep->params.response.RscId,
9341*8f23e9faSHans Rosenfeld 	    (uint8_t *)hba->sli.sli4.VFIBase,
9342*8f23e9faSHans Rosenfeld 	    (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9343*8f23e9faSHans Rosenfeld 
9344*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFIExtCount = ep->params.response.ExtentCnt;
9345*8f23e9faSHans Rosenfeld 	hba->sli.sli4.VFICount = hba->sli.sli4.VFIExtCount *
9346*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VFIExtSize;
9347*8f23e9faSHans Rosenfeld 
9348*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9349*8f23e9faSHans Rosenfeld 	    "VFI Ext: size=%d cnt=%d/%d",
9350*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VFIExtSize,
9351*8f23e9faSHans Rosenfeld 	    hba->sli.sli4.VFIExtCount, ExtentCnt);
9352*8f23e9faSHans Rosenfeld 
9353*8f23e9faSHans Rosenfeld 	for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9354*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9355*8f23e9faSHans Rosenfeld 		    "VFI Ext%d: %d, %d, %d, %d", i,
9356*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VFIBase[i],
9357*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VFIBase[i+1],
9358*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VFIBase[i+2],
9359*8f23e9faSHans Rosenfeld 		    hba->sli.sli4.VFIBase[i+3]);
9360*8f23e9faSHans Rosenfeld 	}
9361*8f23e9faSHans Rosenfeld 
9362*8f23e9faSHans Rosenfeld 	return (0);
9363*8f23e9faSHans Rosenfeld 
9364*8f23e9faSHans Rosenfeld } /* emlxs_sli4_init_extents() */
9365*8f23e9faSHans Rosenfeld 
9366*8f23e9faSHans Rosenfeld 
9367*8f23e9faSHans Rosenfeld extern uint32_t
9368*8f23e9faSHans Rosenfeld emlxs_sli4_index_to_rpi(emlxs_hba_t *hba, uint32_t index)
9369*8f23e9faSHans Rosenfeld {
9370*8f23e9faSHans Rosenfeld 	uint32_t i;
9371*8f23e9faSHans Rosenfeld 	uint32_t j;
9372*8f23e9faSHans Rosenfeld 	uint32_t rpi;
9373*8f23e9faSHans Rosenfeld 
9374*8f23e9faSHans Rosenfeld 	i = index / hba->sli.sli4.RPIExtSize;
9375*8f23e9faSHans Rosenfeld 	j = index % hba->sli.sli4.RPIExtSize;
9376*8f23e9faSHans Rosenfeld 	rpi = hba->sli.sli4.RPIBase[i] + j;
9377*8f23e9faSHans Rosenfeld 
9378*8f23e9faSHans Rosenfeld 	return (rpi);
9379*8f23e9faSHans Rosenfeld 
9380*8f23e9faSHans Rosenfeld } /* emlxs_sli4_index_to_rpi */
9381*8f23e9faSHans Rosenfeld 
9382*8f23e9faSHans Rosenfeld 
9383*8f23e9faSHans Rosenfeld extern uint32_t
9384*8f23e9faSHans Rosenfeld emlxs_sli4_rpi_to_index(emlxs_hba_t *hba, uint32_t rpi)
9385*8f23e9faSHans Rosenfeld {
9386*8f23e9faSHans Rosenfeld 	uint32_t i;
9387*8f23e9faSHans Rosenfeld 	uint32_t lo;
9388*8f23e9faSHans Rosenfeld 	uint32_t hi;
9389*8f23e9faSHans Rosenfeld 	uint32_t index = hba->sli.sli4.RPICount;
9390*8f23e9faSHans Rosenfeld 
9391*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->sli.sli4.RPIExtCount; i++) {
9392*8f23e9faSHans Rosenfeld 		lo = hba->sli.sli4.RPIBase[i];
9393*8f23e9faSHans Rosenfeld 		hi = lo + hba->sli.sli4.RPIExtSize;
9394*8f23e9faSHans Rosenfeld 
9395*8f23e9faSHans Rosenfeld 		if ((rpi < hi) && (rpi >= lo)) {
9396*8f23e9faSHans Rosenfeld 			index = (i * hba->sli.sli4.RPIExtSize) + (rpi - lo);
9397*8f23e9faSHans Rosenfeld 			break;
9398*8f23e9faSHans Rosenfeld 		}
9399*8f23e9faSHans Rosenfeld 	}
9400*8f23e9faSHans Rosenfeld 
9401*8f23e9faSHans Rosenfeld 	return (index);
9402*8f23e9faSHans Rosenfeld 
9403*8f23e9faSHans Rosenfeld } /* emlxs_sli4_rpi_to_index */
9404*8f23e9faSHans Rosenfeld 
9405*8f23e9faSHans Rosenfeld 
9406*8f23e9faSHans Rosenfeld extern uint32_t
9407*8f23e9faSHans Rosenfeld emlxs_sli4_index_to_xri(emlxs_hba_t *hba, uint32_t index)
9408*8f23e9faSHans Rosenfeld {
9409*8f23e9faSHans Rosenfeld 	uint32_t i;
9410*8f23e9faSHans Rosenfeld 	uint32_t j;
9411*8f23e9faSHans Rosenfeld 	uint32_t xri;
9412*8f23e9faSHans Rosenfeld 
9413*8f23e9faSHans Rosenfeld 	i = index / hba->sli.sli4.XRIExtSize;
9414*8f23e9faSHans Rosenfeld 	j = index % hba->sli.sli4.XRIExtSize;
9415*8f23e9faSHans Rosenfeld 	xri = hba->sli.sli4.XRIBase[i] + j;
9416*8f23e9faSHans Rosenfeld 
9417*8f23e9faSHans Rosenfeld 	return (xri);
9418*8f23e9faSHans Rosenfeld 
9419*8f23e9faSHans Rosenfeld } /* emlxs_sli4_index_to_xri */
9420*8f23e9faSHans Rosenfeld 
9421*8f23e9faSHans Rosenfeld 
9422*8f23e9faSHans Rosenfeld 
9423*8f23e9faSHans Rosenfeld 
9424*8f23e9faSHans Rosenfeld extern uint32_t
9425*8f23e9faSHans Rosenfeld emlxs_sli4_index_to_vpi(emlxs_hba_t *hba, uint32_t index)
9426*8f23e9faSHans Rosenfeld {
9427*8f23e9faSHans Rosenfeld 	uint32_t i;
9428*8f23e9faSHans Rosenfeld 	uint32_t j;
9429*8f23e9faSHans Rosenfeld 	uint32_t vpi;
9430*8f23e9faSHans Rosenfeld 
9431*8f23e9faSHans Rosenfeld 	i = index / hba->sli.sli4.VPIExtSize;
9432*8f23e9faSHans Rosenfeld 	j = index % hba->sli.sli4.VPIExtSize;
9433*8f23e9faSHans Rosenfeld 	vpi = hba->sli.sli4.VPIBase[i] + j;
9434*8f23e9faSHans Rosenfeld 
9435*8f23e9faSHans Rosenfeld 	return (vpi);
9436*8f23e9faSHans Rosenfeld 
9437*8f23e9faSHans Rosenfeld } /* emlxs_sli4_index_to_vpi */
9438*8f23e9faSHans Rosenfeld 
9439*8f23e9faSHans Rosenfeld 
9440*8f23e9faSHans Rosenfeld extern uint32_t
9441*8f23e9faSHans Rosenfeld emlxs_sli4_vpi_to_index(emlxs_hba_t *hba, uint32_t vpi)
9442*8f23e9faSHans Rosenfeld {
9443*8f23e9faSHans Rosenfeld 	uint32_t i;
9444*8f23e9faSHans Rosenfeld 	uint32_t lo;
9445*8f23e9faSHans Rosenfeld 	uint32_t hi;
9446*8f23e9faSHans Rosenfeld 	uint32_t index = hba->sli.sli4.VPICount;
9447*8f23e9faSHans Rosenfeld 
9448*8f23e9faSHans Rosenfeld 	for (i = 0; i < hba->sli.sli4.VPIExtCount; i++) {
9449*8f23e9faSHans Rosenfeld 		lo = hba->sli.sli4.VPIBase[i];
9450*8f23e9faSHans Rosenfeld 		hi = lo + hba->sli.sli4.VPIExtSize;
9451*8f23e9faSHans Rosenfeld 
9452*8f23e9faSHans Rosenfeld 		if ((vpi < hi) && (vpi >= lo)) {
9453*8f23e9faSHans Rosenfeld 			index = (i * hba->sli.sli4.VPIExtSize) + (vpi - lo);
9454*8f23e9faSHans Rosenfeld 			break;
9455*8f23e9faSHans Rosenfeld 		}
9456*8f23e9faSHans Rosenfeld 	}
9457*8f23e9faSHans Rosenfeld 
9458*8f23e9faSHans Rosenfeld 	return (index);
9459*8f23e9faSHans Rosenfeld 
9460*8f23e9faSHans Rosenfeld } /* emlxs_sli4_vpi_to_index */
9461*8f23e9faSHans Rosenfeld 
9462*8f23e9faSHans Rosenfeld 
9463*8f23e9faSHans Rosenfeld 
9464*8f23e9faSHans Rosenfeld 
9465*8f23e9faSHans Rosenfeld extern uint32_t
9466*8f23e9faSHans Rosenfeld emlxs_sli4_index_to_vfi(emlxs_hba_t *hba, uint32_t index)
9467*8f23e9faSHans Rosenfeld {
9468*8f23e9faSHans Rosenfeld 	uint32_t i;
9469*8f23e9faSHans Rosenfeld 	uint32_t j;
9470*8f23e9faSHans Rosenfeld 	uint32_t vfi;
9471*8f23e9faSHans Rosenfeld 
9472*8f23e9faSHans Rosenfeld 	i = index / hba->sli.sli4.VFIExtSize;
9473*8f23e9faSHans Rosenfeld 	j = index % hba->sli.sli4.VFIExtSize;
9474*8f23e9faSHans Rosenfeld 	vfi = hba->sli.sli4.VFIBase[i] + j;
9475*8f23e9faSHans Rosenfeld 
9476*8f23e9faSHans Rosenfeld 	return (vfi);
9477*8f23e9faSHans Rosenfeld 
9478*8f23e9faSHans Rosenfeld } /* emlxs_sli4_index_to_vfi */
9479*8f23e9faSHans Rosenfeld 
9480*8f23e9faSHans Rosenfeld 
9481*8f23e9faSHans Rosenfeld static uint16_t
9482*8f23e9faSHans Rosenfeld emlxs_sli4_rqid_to_index(emlxs_hba_t *hba, uint16_t rqid)
9483*8f23e9faSHans Rosenfeld {
9484*8f23e9faSHans Rosenfeld 	uint16_t i;
9485*8f23e9faSHans Rosenfeld 
9486*8f23e9faSHans Rosenfeld 	if (rqid < 0xffff) {
9487*8f23e9faSHans Rosenfeld 		for (i = 0; i < EMLXS_MAX_RQS; i++) {
9488*8f23e9faSHans Rosenfeld 			if (hba->sli.sli4.rq[i].qid == rqid) {
9489*8f23e9faSHans Rosenfeld 				return (i);
9490*8f23e9faSHans Rosenfeld 			}
9491*8f23e9faSHans Rosenfeld 		}
9492*8f23e9faSHans Rosenfeld 	}
9493*8f23e9faSHans Rosenfeld 
9494*8f23e9faSHans Rosenfeld 	return (0xffff);
9495*8f23e9faSHans Rosenfeld 
9496*8f23e9faSHans Rosenfeld } /* emlxs_sli4_rqid_to_index */
9497*8f23e9faSHans Rosenfeld 
9498*8f23e9faSHans Rosenfeld 
9499*8f23e9faSHans Rosenfeld static uint16_t
9500*8f23e9faSHans Rosenfeld emlxs_sli4_wqid_to_index(emlxs_hba_t *hba, uint16_t wqid)
9501*8f23e9faSHans Rosenfeld {
9502*8f23e9faSHans Rosenfeld 	uint16_t i;
9503*8f23e9faSHans Rosenfeld 
9504*8f23e9faSHans Rosenfeld 	if (wqid < 0xffff) {
9505*8f23e9faSHans Rosenfeld 		for (i = 0; i < EMLXS_MAX_WQS; i++) {
9506*8f23e9faSHans Rosenfeld 			if (hba->sli.sli4.wq[i].qid == wqid) {
9507*8f23e9faSHans Rosenfeld 				return (i);
9508*8f23e9faSHans Rosenfeld 			}
9509*8f23e9faSHans Rosenfeld 		}
9510*8f23e9faSHans Rosenfeld 	}
9511*8f23e9faSHans Rosenfeld 
9512*8f23e9faSHans Rosenfeld 	return (0xffff);
9513*8f23e9faSHans Rosenfeld 
9514*8f23e9faSHans Rosenfeld } /* emlxs_sli4_wqid_to_index */
9515*8f23e9faSHans Rosenfeld 
9516*8f23e9faSHans Rosenfeld 
9517*8f23e9faSHans Rosenfeld static uint16_t
9518*8f23e9faSHans Rosenfeld emlxs_sli4_cqid_to_index(emlxs_hba_t *hba, uint16_t cqid)
9519*8f23e9faSHans Rosenfeld {
9520*8f23e9faSHans Rosenfeld 	uint16_t i;
9521*8f23e9faSHans Rosenfeld 
9522*8f23e9faSHans Rosenfeld 	if (cqid < 0xffff) {
9523*8f23e9faSHans Rosenfeld 		for (i = 0; i < EMLXS_MAX_CQS; i++) {
9524*8f23e9faSHans Rosenfeld 			if (hba->sli.sli4.cq[i].qid == cqid) {
9525*8f23e9faSHans Rosenfeld 				return (i);
9526*8f23e9faSHans Rosenfeld 			}
9527*8f23e9faSHans Rosenfeld 		}
9528*8f23e9faSHans Rosenfeld 	}
9529*8f23e9faSHans Rosenfeld 
9530*8f23e9faSHans Rosenfeld 	return (0xffff);
9531*8f23e9faSHans Rosenfeld 
9532*8f23e9faSHans Rosenfeld } /* emlxs_sli4_cqid_to_index */
9533