1*82527734SSukumar Swaminathan /*
2*82527734SSukumar Swaminathan  * CDDL HEADER START
3*82527734SSukumar Swaminathan  *
4*82527734SSukumar Swaminathan  * The contents of this file are subject to the terms of the
5*82527734SSukumar Swaminathan  * Common Development and Distribution License (the "License").
6*82527734SSukumar Swaminathan  * You may not use this file except in compliance with the License.
7*82527734SSukumar Swaminathan  *
8*82527734SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*82527734SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
10*82527734SSukumar Swaminathan  * See the License for the specific language governing permissions
11*82527734SSukumar Swaminathan  * and limitations under the License.
12*82527734SSukumar Swaminathan  *
13*82527734SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
14*82527734SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*82527734SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
16*82527734SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
17*82527734SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
18*82527734SSukumar Swaminathan  *
19*82527734SSukumar Swaminathan  * CDDL HEADER END
20*82527734SSukumar Swaminathan  */
21*82527734SSukumar Swaminathan 
22*82527734SSukumar Swaminathan /*
23*82527734SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25*82527734SSukumar Swaminathan  */
26*82527734SSukumar Swaminathan 
27*82527734SSukumar Swaminathan 
28*82527734SSukumar Swaminathan #include <emlxs.h>
29*82527734SSukumar Swaminathan 
30*82527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31*82527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI4_C);
32*82527734SSukumar Swaminathan 
33*82527734SSukumar Swaminathan static int		emlxs_sli4_create_queues(emlxs_hba_t *hba,
34*82527734SSukumar Swaminathan 				MAILBOXQ *mbq);
35*82527734SSukumar Swaminathan static int		emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
36*82527734SSukumar Swaminathan 				MAILBOXQ *mbq);
37*82527734SSukumar Swaminathan static int		emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
38*82527734SSukumar Swaminathan 				MAILBOXQ *mbq);
39*82527734SSukumar Swaminathan static int		emlxs_fcf_bind(emlxs_hba_t *hba);
40*82527734SSukumar Swaminathan 
41*82527734SSukumar Swaminathan static int		emlxs_fcf_unbind(emlxs_hba_t *hba, uint32_t index);
42*82527734SSukumar Swaminathan 
43*82527734SSukumar Swaminathan static int		emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
44*82527734SSukumar Swaminathan 
45*82527734SSukumar Swaminathan extern void		emlxs_parse_prog_types(emlxs_hba_t *hba, char *types);
46*82527734SSukumar Swaminathan 
47*82527734SSukumar Swaminathan extern int32_t		emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd,
48*82527734SSukumar Swaminathan 				uint32_t size);
49*82527734SSukumar Swaminathan extern void		emlxs_decode_label(char *label, char *buffer, int bige);
50*82527734SSukumar Swaminathan 
51*82527734SSukumar Swaminathan extern void		emlxs_build_prog_types(emlxs_hba_t *hba,
52*82527734SSukumar Swaminathan 				char *prog_types);
53*82527734SSukumar Swaminathan 
54*82527734SSukumar Swaminathan extern int		emlxs_pci_model_count;
55*82527734SSukumar Swaminathan 
56*82527734SSukumar Swaminathan extern emlxs_model_t	emlxs_pci_model[];
57*82527734SSukumar Swaminathan 
58*82527734SSukumar Swaminathan static int		emlxs_sli4_map_hdw(emlxs_hba_t *hba);
59*82527734SSukumar Swaminathan 
60*82527734SSukumar Swaminathan static void		emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
61*82527734SSukumar Swaminathan 
62*82527734SSukumar Swaminathan static int32_t		emlxs_sli4_online(emlxs_hba_t *hba);
63*82527734SSukumar Swaminathan 
64*82527734SSukumar Swaminathan static void		emlxs_sli4_offline(emlxs_hba_t *hba);
65*82527734SSukumar Swaminathan 
66*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
67*82527734SSukumar Swaminathan 				uint32_t skip_post, uint32_t quiesce);
68*82527734SSukumar Swaminathan static void		emlxs_sli4_hba_kill(emlxs_hba_t *hba);
69*82527734SSukumar Swaminathan 
70*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_hba_init(emlxs_hba_t *hba);
71*82527734SSukumar Swaminathan 
72*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_bde_setup(emlxs_port_t *port,
73*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
74*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_fct_bde_setup(emlxs_port_t *port,
75*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
76*82527734SSukumar Swaminathan static void		emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
77*82527734SSukumar Swaminathan 				CHANNEL *rp, IOCBQ *iocb_cmd);
78*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
79*82527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
80*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
81*82527734SSukumar Swaminathan 				MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
82*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
83*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
84*82527734SSukumar Swaminathan 				emlxs_buf_t *cmd_sbp, int channel);
85*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
86*82527734SSukumar Swaminathan 
87*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
88*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp, int ring);
89*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
90*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
91*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
92*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
93*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
94*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp);
95*82527734SSukumar Swaminathan static void		emlxs_sli4_poll_intr(emlxs_hba_t *hba,
96*82527734SSukumar Swaminathan 				uint32_t att_bit);
97*82527734SSukumar Swaminathan static int32_t		emlxs_sli4_intx_intr(char *arg);
98*82527734SSukumar Swaminathan 
99*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
100*82527734SSukumar Swaminathan static uint32_t		emlxs_sli4_msi_intr(char *arg1, char *arg2);
101*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
102*82527734SSukumar Swaminathan 
103*82527734SSukumar Swaminathan static void		emlxs_sli4_resource_free(emlxs_hba_t *hba);
104*82527734SSukumar Swaminathan 
105*82527734SSukumar Swaminathan static int		emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
106*82527734SSukumar Swaminathan 
107*82527734SSukumar Swaminathan static void		emlxs_sli4_destroy_queues(emlxs_hba_t *hba);
108*82527734SSukumar Swaminathan 
109*82527734SSukumar Swaminathan static XRIobj_t		*emlxs_sli4_alloc_xri(emlxs_hba_t *hba,
110*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp, RPIobj_t *rp);
111*82527734SSukumar Swaminathan static void		emlxs_sli4_free_vpi(emlxs_hba_t *hba, emlxs_port_t *pp);
112*82527734SSukumar Swaminathan 
113*82527734SSukumar Swaminathan static void		emlxs_sli4_enable_intr(emlxs_hba_t *hba);
114*82527734SSukumar Swaminathan 
115*82527734SSukumar Swaminathan static void		emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
116*82527734SSukumar Swaminathan 
117*82527734SSukumar Swaminathan extern void		emlxs_sli4_timer(emlxs_hba_t *hba);
118*82527734SSukumar Swaminathan 
119*82527734SSukumar Swaminathan static void		emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
120*82527734SSukumar Swaminathan 
121*82527734SSukumar Swaminathan extern void		emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
122*82527734SSukumar Swaminathan 
123*82527734SSukumar Swaminathan static XRIobj_t 	*emlxs_sli4_register_xri(emlxs_hba_t *hba,
124*82527734SSukumar Swaminathan 				emlxs_buf_t *sbp, uint16_t xri);
125*82527734SSukumar Swaminathan 
126*82527734SSukumar Swaminathan static XRIobj_t 	*emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp);
127*82527734SSukumar Swaminathan 
128*82527734SSukumar Swaminathan static int		emlxs_check_hdw_ready(emlxs_hba_t *);
129*82527734SSukumar Swaminathan 
130*82527734SSukumar Swaminathan /* Define SLI4 API functions */
131*82527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli4_api = {
132*82527734SSukumar Swaminathan 	emlxs_sli4_map_hdw,
133*82527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw,
134*82527734SSukumar Swaminathan 	emlxs_sli4_online,
135*82527734SSukumar Swaminathan 	emlxs_sli4_offline,
136*82527734SSukumar Swaminathan 	emlxs_sli4_hba_reset,
137*82527734SSukumar Swaminathan 	emlxs_sli4_hba_kill,
138*82527734SSukumar Swaminathan 	emlxs_sli4_issue_iocb_cmd,
139*82527734SSukumar Swaminathan 	emlxs_sli4_issue_mbox_cmd,
140*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
141*82527734SSukumar Swaminathan 	emlxs_sli4_prep_fct_iocb,
142*82527734SSukumar Swaminathan #else
143*82527734SSukumar Swaminathan 	NULL,
144*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
145*82527734SSukumar Swaminathan 	emlxs_sli4_prep_fcp_iocb,
146*82527734SSukumar Swaminathan 	emlxs_sli4_prep_ip_iocb,
147*82527734SSukumar Swaminathan 	emlxs_sli4_prep_els_iocb,
148*82527734SSukumar Swaminathan 	emlxs_sli4_prep_ct_iocb,
149*82527734SSukumar Swaminathan 	emlxs_sli4_poll_intr,
150*82527734SSukumar Swaminathan 	emlxs_sli4_intx_intr,
151*82527734SSukumar Swaminathan 	emlxs_sli4_msi_intr,
152*82527734SSukumar Swaminathan 	emlxs_sli4_disable_intr,
153*82527734SSukumar Swaminathan 	emlxs_sli4_timer,
154*82527734SSukumar Swaminathan 	emlxs_sli4_poll_erratt
155*82527734SSukumar Swaminathan };
156*82527734SSukumar Swaminathan 
157*82527734SSukumar Swaminathan 
158*82527734SSukumar Swaminathan /* ************************************************************************** */
159*82527734SSukumar Swaminathan 
160*82527734SSukumar Swaminathan 
161*82527734SSukumar Swaminathan /*
162*82527734SSukumar Swaminathan  * emlxs_sli4_online()
163*82527734SSukumar Swaminathan  *
164*82527734SSukumar Swaminathan  * This routine will start initialization of the SLI4 HBA.
165*82527734SSukumar Swaminathan  */
166*82527734SSukumar Swaminathan static int32_t
167*82527734SSukumar Swaminathan emlxs_sli4_online(emlxs_hba_t *hba)
168*82527734SSukumar Swaminathan {
169*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
170*82527734SSukumar Swaminathan 	emlxs_config_t *cfg;
171*82527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
172*82527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
173*82527734SSukumar Swaminathan 	MAILBOX4 *mb  = NULL;
174*82527734SSukumar Swaminathan 	MATCHMAP *mp  = NULL;
175*82527734SSukumar Swaminathan 	MATCHMAP *mp1 = NULL;
176*82527734SSukumar Swaminathan 	uint32_t i;
177*82527734SSukumar Swaminathan 	uint32_t j;
178*82527734SSukumar Swaminathan 	uint32_t rval = 0;
179*82527734SSukumar Swaminathan 	uint8_t *vpd_data;
180*82527734SSukumar Swaminathan 	uint32_t sli_mode;
181*82527734SSukumar Swaminathan 	uint8_t *outptr;
182*82527734SSukumar Swaminathan 	uint32_t status;
183*82527734SSukumar Swaminathan 	uint32_t fw_check;
184*82527734SSukumar Swaminathan 	emlxs_firmware_t hba_fw;
185*82527734SSukumar Swaminathan 	emlxs_firmware_t *fw;
186*82527734SSukumar Swaminathan 
187*82527734SSukumar Swaminathan 	cfg = &CFG;
188*82527734SSukumar Swaminathan 	vpd = &VPD;
189*82527734SSukumar Swaminathan 
190*82527734SSukumar Swaminathan 	sli_mode = EMLXS_HBA_SLI4_MODE;
191*82527734SSukumar Swaminathan 	hba->sli_mode = sli_mode;
192*82527734SSukumar Swaminathan 
193*82527734SSukumar Swaminathan 	/* Set the fw_check flag */
194*82527734SSukumar Swaminathan 	fw_check = cfg[CFG_FW_CHECK].current;
195*82527734SSukumar Swaminathan 
196*82527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
197*82527734SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
198*82527734SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
199*82527734SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
200*82527734SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
201*82527734SSukumar Swaminathan 
202*82527734SSukumar Swaminathan 	/* Target mode not supported */
203*82527734SSukumar Swaminathan 	if (hba->tgt_mode) {
204*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
205*82527734SSukumar Swaminathan 		    "Target mode not supported in SLI4.");
206*82527734SSukumar Swaminathan 
207*82527734SSukumar Swaminathan 		return (ENOMEM);
208*82527734SSukumar Swaminathan 	}
209*82527734SSukumar Swaminathan 
210*82527734SSukumar Swaminathan 	/* Networking not supported */
211*82527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
212*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
213*82527734SSukumar Swaminathan 		    "Networking not supported in SLI4, turning it off");
214*82527734SSukumar Swaminathan 		cfg[CFG_NETWORK_ON].current = 0;
215*82527734SSukumar Swaminathan 	}
216*82527734SSukumar Swaminathan 
217*82527734SSukumar Swaminathan 	hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
218*82527734SSukumar Swaminathan 	if (hba->chan_count > MAX_CHANNEL) {
219*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
220*82527734SSukumar Swaminathan 		    "Max channels exceeded, dropping num-wq from %d to 1",
221*82527734SSukumar Swaminathan 		    cfg[CFG_NUM_WQ].current);
222*82527734SSukumar Swaminathan 		cfg[CFG_NUM_WQ].current = 1;
223*82527734SSukumar Swaminathan 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
224*82527734SSukumar Swaminathan 	}
225*82527734SSukumar Swaminathan 	hba->channel_fcp = 0; /* First channel */
226*82527734SSukumar Swaminathan 
227*82527734SSukumar Swaminathan 	/* Default channel for everything else is the last channel */
228*82527734SSukumar Swaminathan 	hba->channel_ip = hba->chan_count - 1;
229*82527734SSukumar Swaminathan 	hba->channel_els = hba->chan_count - 1;
230*82527734SSukumar Swaminathan 	hba->channel_ct = hba->chan_count - 1;
231*82527734SSukumar Swaminathan 
232*82527734SSukumar Swaminathan 	hba->fc_iotag = 1;
233*82527734SSukumar Swaminathan 	hba->io_count = 0;
234*82527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
235*82527734SSukumar Swaminathan 
236*82527734SSukumar Swaminathan 	/* Initialize the local dump region buffer */
237*82527734SSukumar Swaminathan 	bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
238*82527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
239*82527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
240*82527734SSukumar Swaminathan 	    | FC_MBUF_DMA32;
241*82527734SSukumar Swaminathan 	hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
242*82527734SSukumar Swaminathan 
243*82527734SSukumar Swaminathan 	(void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
244*82527734SSukumar Swaminathan 
245*82527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt == NULL) {
246*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
247*82527734SSukumar Swaminathan 		    "Unable to allocate dump region buffer.");
248*82527734SSukumar Swaminathan 
249*82527734SSukumar Swaminathan 		return (ENOMEM);
250*82527734SSukumar Swaminathan 	}
251*82527734SSukumar Swaminathan 
252*82527734SSukumar Swaminathan 	/*
253*82527734SSukumar Swaminathan 	 * Get a buffer which will be used repeatedly for mailbox commands
254*82527734SSukumar Swaminathan 	 */
255*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
256*82527734SSukumar Swaminathan 
257*82527734SSukumar Swaminathan 	mb = (MAILBOX4 *)mbq;
258*82527734SSukumar Swaminathan 
259*82527734SSukumar Swaminathan reset:
260*82527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
261*82527734SSukumar Swaminathan 	if (emlxs_sli4_hba_init(hba)) {
262*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
263*82527734SSukumar Swaminathan 		    "Unable to init hba.");
264*82527734SSukumar Swaminathan 
265*82527734SSukumar Swaminathan 		rval = EIO;
266*82527734SSukumar Swaminathan 		goto failed1;
267*82527734SSukumar Swaminathan 	}
268*82527734SSukumar Swaminathan 
269*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
270*82527734SSukumar Swaminathan 	/* Access handle validation */
271*82527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
272*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
273*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar1_acc_handle)
274*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
275*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli4.bar2_acc_handle)
276*82527734SSukumar Swaminathan 	    != DDI_FM_OK)) {
277*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
278*82527734SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
279*82527734SSukumar Swaminathan 
280*82527734SSukumar Swaminathan 		rval = EIO;
281*82527734SSukumar Swaminathan 		goto failed1;
282*82527734SSukumar Swaminathan 	}
283*82527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
284*82527734SSukumar Swaminathan 
285*82527734SSukumar Swaminathan 	/*
286*82527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
287*82527734SSukumar Swaminathan 	 */
288*82527734SSukumar Swaminathan 	vpd->opFwRev = 0;
289*82527734SSukumar Swaminathan 	vpd->postKernRev = 0;
290*82527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
291*82527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
292*82527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
293*82527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
294*82527734SSukumar Swaminathan 
295*82527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
296*82527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
297*82527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
298*82527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
299*82527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
300*82527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
301*82527734SSukumar Swaminathan 
302*82527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
303*82527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
304*82527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
305*82527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
306*82527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
307*82527734SSukumar Swaminathan 
308*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
309*82527734SSukumar Swaminathan 
310*82527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
311*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
312*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
313*82527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
314*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
315*82527734SSukumar Swaminathan 
316*82527734SSukumar Swaminathan 		rval = EIO;
317*82527734SSukumar Swaminathan 		goto failed1;
318*82527734SSukumar Swaminathan 
319*82527734SSukumar Swaminathan 	}
320*82527734SSukumar Swaminathan 
321*82527734SSukumar Swaminathan emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0);
322*82527734SSukumar Swaminathan 	if (mb->un.varRdRev4.sliLevel != 4) {
323*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
324*82527734SSukumar Swaminathan 		    "Invalid read rev Version for SLI4: 0x%x",
325*82527734SSukumar Swaminathan 		    mb->un.varRdRev4.sliLevel);
326*82527734SSukumar Swaminathan 
327*82527734SSukumar Swaminathan 		rval = EIO;
328*82527734SSukumar Swaminathan 		goto failed1;
329*82527734SSukumar Swaminathan 	}
330*82527734SSukumar Swaminathan 
331*82527734SSukumar Swaminathan 	switch (mb->un.varRdRev4.dcbxMode) {
332*82527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CIN:	/* Mapped to nonFIP mode */
333*82527734SSukumar Swaminathan 		hba->flag &= ~FC_FIP_SUPPORTED;
334*82527734SSukumar Swaminathan 		break;
335*82527734SSukumar Swaminathan 
336*82527734SSukumar Swaminathan 	case EMLXS_DCBX_MODE_CEE:	/* Mapped to FIP mode */
337*82527734SSukumar Swaminathan 		hba->flag |= FC_FIP_SUPPORTED;
338*82527734SSukumar Swaminathan 		break;
339*82527734SSukumar Swaminathan 
340*82527734SSukumar Swaminathan 	default:
341*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
342*82527734SSukumar Swaminathan 		    "Invalid read rev dcbx mode for SLI4: 0x%x",
343*82527734SSukumar Swaminathan 		    mb->un.varRdRev4.dcbxMode);
344*82527734SSukumar Swaminathan 
345*82527734SSukumar Swaminathan 		rval = EIO;
346*82527734SSukumar Swaminathan 		goto failed1;
347*82527734SSukumar Swaminathan 	}
348*82527734SSukumar Swaminathan 
349*82527734SSukumar Swaminathan 
350*82527734SSukumar Swaminathan 	/* Save information as VPD data */
351*82527734SSukumar Swaminathan 	vpd->rBit = 1;
352*82527734SSukumar Swaminathan 
353*82527734SSukumar Swaminathan 	vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
354*82527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
355*82527734SSukumar Swaminathan 
356*82527734SSukumar Swaminathan 	vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
357*82527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
358*82527734SSukumar Swaminathan 
359*82527734SSukumar Swaminathan 	vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
360*82527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
361*82527734SSukumar Swaminathan 
362*82527734SSukumar Swaminathan 	vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
363*82527734SSukumar Swaminathan 	vpd->fcphLow = mb->un.varRdRev4.fcphLow;
364*82527734SSukumar Swaminathan 	vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
365*82527734SSukumar Swaminathan 	vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
366*82527734SSukumar Swaminathan 
367*82527734SSukumar Swaminathan 	/* Decode FW labels */
368*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0);
369*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0);
370*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0);
371*82527734SSukumar Swaminathan 
372*82527734SSukumar Swaminathan 	if (hba->model_info.chip == EMLXS_TIGERSHARK_CHIP) {
373*82527734SSukumar Swaminathan 		(void) strcpy(vpd->sli4FwLabel, "be2.ufi");
374*82527734SSukumar Swaminathan 	} else {
375*82527734SSukumar Swaminathan 		(void) strcpy(vpd->sli4FwLabel, "sli4.fw");
376*82527734SSukumar Swaminathan 	}
377*82527734SSukumar Swaminathan 
378*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
379*82527734SSukumar Swaminathan 	    "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
380*82527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
381*82527734SSukumar Swaminathan 	    vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
382*82527734SSukumar Swaminathan 	    mb->un.varRdRev4.dcbxMode);
383*82527734SSukumar Swaminathan 
384*82527734SSukumar Swaminathan 	/* No key information is needed for SLI4 products */
385*82527734SSukumar Swaminathan 
386*82527734SSukumar Swaminathan 	/* Get adapter VPD information */
387*82527734SSukumar Swaminathan 	vpd->port_index = (uint32_t)-1;
388*82527734SSukumar Swaminathan 
389*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
390*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
391*82527734SSukumar Swaminathan 
392*82527734SSukumar Swaminathan 	emlxs_mb_dump_vpd(hba, mbq, 0);
393*82527734SSukumar Swaminathan 	vpd_data = hba->sli.sli4.dump_region.virt;
394*82527734SSukumar Swaminathan 
395*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
396*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
397*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
398*82527734SSukumar Swaminathan 		    "No VPD found. status=%x", mb->mbxStatus);
399*82527734SSukumar Swaminathan 	} else {
400*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
401*82527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
402*82527734SSukumar Swaminathan 		    "VPD dumped. rsp_cnt=%d status=%x",
403*82527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
404*82527734SSukumar Swaminathan 
405*82527734SSukumar Swaminathan 		if (mb->un.varDmp4.rsp_cnt) {
406*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
407*82527734SSukumar Swaminathan 			    0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
408*82527734SSukumar Swaminathan 
409*82527734SSukumar Swaminathan 		}
410*82527734SSukumar Swaminathan 	}
411*82527734SSukumar Swaminathan 
412*82527734SSukumar Swaminathan 	if (vpd_data[0]) {
413*82527734SSukumar Swaminathan 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
414*82527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt);
415*82527734SSukumar Swaminathan 
416*82527734SSukumar Swaminathan 		/*
417*82527734SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
418*82527734SSukumar Swaminathan 		 * match the current default HBA model info,
419*82527734SSukumar Swaminathan 		 * replace the default data with an entry that
420*82527734SSukumar Swaminathan 		 * does match.
421*82527734SSukumar Swaminathan 		 *
422*82527734SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
423*82527734SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
424*82527734SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
425*82527734SSukumar Swaminathan 		 */
426*82527734SSukumar Swaminathan 
427*82527734SSukumar Swaminathan 		rval = 0;
428*82527734SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
429*82527734SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
430*82527734SSukumar Swaminathan 
431*82527734SSukumar Swaminathan 			/* First scan for a V2 match */
432*82527734SSukumar Swaminathan 
433*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
434*82527734SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
435*82527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
436*82527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
437*82527734SSukumar Swaminathan 					    &hba->model_info,
438*82527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
439*82527734SSukumar Swaminathan 					rval = 1;
440*82527734SSukumar Swaminathan 					break;
441*82527734SSukumar Swaminathan 				}
442*82527734SSukumar Swaminathan 			}
443*82527734SSukumar Swaminathan 		}
444*82527734SSukumar Swaminathan 
445*82527734SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
446*82527734SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
447*82527734SSukumar Swaminathan 
448*82527734SSukumar Swaminathan 			/* Next scan for a PN match */
449*82527734SSukumar Swaminathan 
450*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
451*82527734SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
452*82527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
453*82527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
454*82527734SSukumar Swaminathan 					    &hba->model_info,
455*82527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
456*82527734SSukumar Swaminathan 					break;
457*82527734SSukumar Swaminathan 				}
458*82527734SSukumar Swaminathan 			}
459*82527734SSukumar Swaminathan 		}
460*82527734SSukumar Swaminathan 
461*82527734SSukumar Swaminathan 		/*
462*82527734SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
463*82527734SSukumar Swaminathan 		 * VPD data, if any.
464*82527734SSukumar Swaminathan 		 */
465*82527734SSukumar Swaminathan 
466*82527734SSukumar Swaminathan 		/*
467*82527734SSukumar Swaminathan 		 * Replace the default model description with vpd data
468*82527734SSukumar Swaminathan 		 */
469*82527734SSukumar Swaminathan 		if (vpd->model_desc[0] != 0) {
470*82527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model_desc,
471*82527734SSukumar Swaminathan 			    vpd->model_desc);
472*82527734SSukumar Swaminathan 		}
473*82527734SSukumar Swaminathan 
474*82527734SSukumar Swaminathan 		/* Replace the default model with vpd data */
475*82527734SSukumar Swaminathan 		if (vpd->model[0] != 0) {
476*82527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model, vpd->model);
477*82527734SSukumar Swaminathan 		}
478*82527734SSukumar Swaminathan 
479*82527734SSukumar Swaminathan 		/* Replace the default program types with vpd data */
480*82527734SSukumar Swaminathan 		if (vpd->prog_types[0] != 0) {
481*82527734SSukumar Swaminathan 			emlxs_parse_prog_types(hba, vpd->prog_types);
482*82527734SSukumar Swaminathan 		}
483*82527734SSukumar Swaminathan 	}
484*82527734SSukumar Swaminathan 
485*82527734SSukumar Swaminathan 	/*
486*82527734SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
487*82527734SSukumar Swaminathan 	 * lets double check if adapter is not supported
488*82527734SSukumar Swaminathan 	 */
489*82527734SSukumar Swaminathan 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
490*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
491*82527734SSukumar Swaminathan 		    "Unsupported adapter found.  "
492*82527734SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
493*82527734SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
494*82527734SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
495*82527734SSukumar Swaminathan 
496*82527734SSukumar Swaminathan 		rval = EIO;
497*82527734SSukumar Swaminathan 		goto failed1;
498*82527734SSukumar Swaminathan 	}
499*82527734SSukumar Swaminathan 
500*82527734SSukumar Swaminathan 	(void) strcpy(vpd->boot_version, vpd->sli4FwName);
501*82527734SSukumar Swaminathan 
502*82527734SSukumar Swaminathan 	/* Get fcode version property */
503*82527734SSukumar Swaminathan 	emlxs_get_fcode_version(hba);
504*82527734SSukumar Swaminathan 
505*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
506*82527734SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
507*82527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
508*82527734SSukumar Swaminathan 
509*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
510*82527734SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
511*82527734SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
512*82527734SSukumar Swaminathan 
513*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
514*82527734SSukumar Swaminathan 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
515*82527734SSukumar Swaminathan 
516*82527734SSukumar Swaminathan 	/*
517*82527734SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
518*82527734SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
519*82527734SSukumar Swaminathan 	 */
520*82527734SSukumar Swaminathan 	if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
521*82527734SSukumar Swaminathan 	    hba->model_info.fwid) || ((fw_check == 2) &&
522*82527734SSukumar Swaminathan 	    hba->model_info.fwid)) {
523*82527734SSukumar Swaminathan 
524*82527734SSukumar Swaminathan 		/* Find firmware image indicated by adapter model */
525*82527734SSukumar Swaminathan 		fw = NULL;
526*82527734SSukumar Swaminathan 		for (i = 0; i < emlxs_fw_count; i++) {
527*82527734SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
528*82527734SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
529*82527734SSukumar Swaminathan 				break;
530*82527734SSukumar Swaminathan 			}
531*82527734SSukumar Swaminathan 		}
532*82527734SSukumar Swaminathan 
533*82527734SSukumar Swaminathan 		/*
534*82527734SSukumar Swaminathan 		 * If the image was found, then verify current firmware
535*82527734SSukumar Swaminathan 		 * versions of adapter
536*82527734SSukumar Swaminathan 		 */
537*82527734SSukumar Swaminathan 		if (fw) {
538*82527734SSukumar Swaminathan 
539*82527734SSukumar Swaminathan 			/* Obtain current firmware version info */
540*82527734SSukumar Swaminathan 			if (hba->model_info.chip == EMLXS_TIGERSHARK_CHIP) {
541*82527734SSukumar Swaminathan 				(void) emlxs_sli4_read_fw_version(hba, &hba_fw);
542*82527734SSukumar Swaminathan 			} else {
543*82527734SSukumar Swaminathan 				hba_fw.kern = vpd->postKernRev;
544*82527734SSukumar Swaminathan 				hba_fw.stub = vpd->opFwRev;
545*82527734SSukumar Swaminathan 				hba_fw.sli1 = vpd->sli1FwRev;
546*82527734SSukumar Swaminathan 				hba_fw.sli2 = vpd->sli2FwRev;
547*82527734SSukumar Swaminathan 				hba_fw.sli3 = vpd->sli3FwRev;
548*82527734SSukumar Swaminathan 				hba_fw.sli4 = vpd->sli4FwRev;
549*82527734SSukumar Swaminathan 			}
550*82527734SSukumar Swaminathan 
551*82527734SSukumar Swaminathan 			if ((fw->kern && (hba_fw.kern != fw->kern)) ||
552*82527734SSukumar Swaminathan 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
553*82527734SSukumar Swaminathan 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
554*82527734SSukumar Swaminathan 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
555*82527734SSukumar Swaminathan 			    (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
556*82527734SSukumar Swaminathan 			    (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
557*82527734SSukumar Swaminathan 
558*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
559*82527734SSukumar Swaminathan 				    "Firmware update needed. "
560*82527734SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
561*82527734SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
562*82527734SSukumar Swaminathan 
563*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
564*82527734SSukumar Swaminathan 				/*
565*82527734SSukumar Swaminathan 				 * Load the firmware image now
566*82527734SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
567*82527734SSukumar Swaminathan 				 * firmware image will already be defined
568*82527734SSukumar Swaminathan 				 * in the emlxs_fw_table
569*82527734SSukumar Swaminathan 				 */
570*82527734SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
571*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
572*82527734SSukumar Swaminathan 
573*82527734SSukumar Swaminathan 				if (fw->image && fw->size) {
574*82527734SSukumar Swaminathan 					if (emlxs_fw_download(hba,
575*82527734SSukumar Swaminathan 					    (char *)fw->image, fw->size, 0)) {
576*82527734SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
577*82527734SSukumar Swaminathan 						    &emlxs_init_msg,
578*82527734SSukumar Swaminathan 						    "Firmware update failed.");
579*82527734SSukumar Swaminathan 					}
580*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
581*82527734SSukumar Swaminathan 					/*
582*82527734SSukumar Swaminathan 					 * Unload the firmware image from
583*82527734SSukumar Swaminathan 					 * kernel memory
584*82527734SSukumar Swaminathan 					 */
585*82527734SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
586*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
587*82527734SSukumar Swaminathan 
588*82527734SSukumar Swaminathan 					fw_check = 0;
589*82527734SSukumar Swaminathan 
590*82527734SSukumar Swaminathan 					goto reset;
591*82527734SSukumar Swaminathan 				}
592*82527734SSukumar Swaminathan 
593*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
594*82527734SSukumar Swaminathan 				    "Firmware image unavailable.");
595*82527734SSukumar Swaminathan 			} else {
596*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
597*82527734SSukumar Swaminathan 				    "Firmware update not needed.");
598*82527734SSukumar Swaminathan 			}
599*82527734SSukumar Swaminathan 		} else {
600*82527734SSukumar Swaminathan 			/*
601*82527734SSukumar Swaminathan 			 * This means either the adapter database is not
602*82527734SSukumar Swaminathan 			 * correct or a firmware image is missing from the
603*82527734SSukumar Swaminathan 			 * compile
604*82527734SSukumar Swaminathan 			 */
605*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
606*82527734SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
607*82527734SSukumar Swaminathan 			    hba->model_info.id, hba->model_info.fwid);
608*82527734SSukumar Swaminathan 		}
609*82527734SSukumar Swaminathan 	}
610*82527734SSukumar Swaminathan 
611*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
612*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
613*82527734SSukumar Swaminathan 
614*82527734SSukumar Swaminathan 	emlxs_mb_dump_fcoe(hba, mbq, 0);
615*82527734SSukumar Swaminathan 
616*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
617*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
618*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
619*82527734SSukumar Swaminathan 		    "No FCOE info found. status=%x", mb->mbxStatus);
620*82527734SSukumar Swaminathan 	} else {
621*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
622*82527734SSukumar Swaminathan 		    &emlxs_init_debug_msg,
623*82527734SSukumar Swaminathan 		    "FCOE info dumped. rsp_cnt=%d status=%x",
624*82527734SSukumar Swaminathan 		    mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
625*82527734SSukumar Swaminathan 		(void) emlxs_parse_fcoe(hba,
626*82527734SSukumar Swaminathan 		    (uint8_t *)hba->sli.sli4.dump_region.virt, 0);
627*82527734SSukumar Swaminathan 	}
628*82527734SSukumar Swaminathan 
629*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
630*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
631*82527734SSukumar Swaminathan 
632*82527734SSukumar Swaminathan 	emlxs_mb_request_features(hba, mbq);
633*82527734SSukumar Swaminathan 
634*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
635*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
636*82527734SSukumar Swaminathan 		    "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
637*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
638*82527734SSukumar Swaminathan 
639*82527734SSukumar Swaminathan 		rval = EIO;
640*82527734SSukumar Swaminathan 		goto failed1;
641*82527734SSukumar Swaminathan 	}
642*82527734SSukumar Swaminathan emlxs_data_dump(hba, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
643*82527734SSukumar Swaminathan 
644*82527734SSukumar Swaminathan 	/* Make sure we get the features we requested */
645*82527734SSukumar Swaminathan 	if (mb->un.varReqFeatures.featuresRequested !=
646*82527734SSukumar Swaminathan 	    mb->un.varReqFeatures.featuresEnabled) {
647*82527734SSukumar Swaminathan 
648*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
649*82527734SSukumar Swaminathan 		    "Unable to get REQUESTed_FEATURES. want:x%x  got:x%x",
650*82527734SSukumar Swaminathan 		    mb->un.varReqFeatures.featuresRequested,
651*82527734SSukumar Swaminathan 		    mb->un.varReqFeatures.featuresEnabled);
652*82527734SSukumar Swaminathan 
653*82527734SSukumar Swaminathan 		rval = EIO;
654*82527734SSukumar Swaminathan 		goto failed1;
655*82527734SSukumar Swaminathan 	}
656*82527734SSukumar Swaminathan 
657*82527734SSukumar Swaminathan 	if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
658*82527734SSukumar Swaminathan 		hba->flag |= FC_NPIV_ENABLED;
659*82527734SSukumar Swaminathan 	}
660*82527734SSukumar Swaminathan 
661*82527734SSukumar Swaminathan 	/* Check enable-npiv driver parameter for now */
662*82527734SSukumar Swaminathan 	if (cfg[CFG_NPIV_ENABLE].current) {
663*82527734SSukumar Swaminathan 		hba->flag |= FC_NPIV_ENABLED;
664*82527734SSukumar Swaminathan 	}
665*82527734SSukumar Swaminathan 
666*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
667*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
668*82527734SSukumar Swaminathan 
669*82527734SSukumar Swaminathan 	emlxs_mb_read_config(hba, mbq);
670*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
671*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
672*82527734SSukumar Swaminathan 		    "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
673*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
674*82527734SSukumar Swaminathan 
675*82527734SSukumar Swaminathan 		rval = EIO;
676*82527734SSukumar Swaminathan 		goto failed1;
677*82527734SSukumar Swaminathan 	}
678*82527734SSukumar Swaminathan emlxs_data_dump(hba, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
679*82527734SSukumar Swaminathan 
680*82527734SSukumar Swaminathan 	hba->sli.sli4.XRICount = (mb->un.varRdConfig4.XRICount);
681*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIBase = (mb->un.varRdConfig4.XRIBase);
682*82527734SSukumar Swaminathan 	hba->sli.sli4.RPICount = (mb->un.varRdConfig4.RPICount);
683*82527734SSukumar Swaminathan 	hba->sli.sli4.RPIBase = (mb->un.varRdConfig4.RPIBase);
684*82527734SSukumar Swaminathan 	hba->sli.sli4.VPICount = (mb->un.varRdConfig4.VPICount);
685*82527734SSukumar Swaminathan 	hba->sli.sli4.VPIBase = (mb->un.varRdConfig4.VPIBase);
686*82527734SSukumar Swaminathan 	hba->sli.sli4.VFICount = (mb->un.varRdConfig4.VFICount);
687*82527734SSukumar Swaminathan 	hba->sli.sli4.VFIBase = (mb->un.varRdConfig4.VFIBase);
688*82527734SSukumar Swaminathan 	hba->sli.sli4.FCFICount = (mb->un.varRdConfig4.FCFICount);
689*82527734SSukumar Swaminathan 
690*82527734SSukumar Swaminathan 	if (hba->sli.sli4.VPICount) {
691*82527734SSukumar Swaminathan 		hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
692*82527734SSukumar Swaminathan 	}
693*82527734SSukumar Swaminathan 	hba->vpi_base = mb->un.varRdConfig4.VPIBase;
694*82527734SSukumar Swaminathan 
695*82527734SSukumar Swaminathan 	/* Set the max node count */
696*82527734SSukumar Swaminathan 	if (cfg[CFG_NUM_NODES].current > 0) {
697*82527734SSukumar Swaminathan 		hba->max_nodes =
698*82527734SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
699*82527734SSukumar Swaminathan 		    hba->sli.sli4.RPICount);
700*82527734SSukumar Swaminathan 	} else {
701*82527734SSukumar Swaminathan 		hba->max_nodes = hba->sli.sli4.RPICount;
702*82527734SSukumar Swaminathan 	}
703*82527734SSukumar Swaminathan 
704*82527734SSukumar Swaminathan 	/* Set the io throttle */
705*82527734SSukumar Swaminathan 	hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
706*82527734SSukumar Swaminathan 	hba->max_iotag = hba->sli.sli4.XRICount;
707*82527734SSukumar Swaminathan 
708*82527734SSukumar Swaminathan 	/* Save the link speed capabilities */
709*82527734SSukumar Swaminathan 	vpd->link_speed = mb->un.varRdConfig4.lmt;
710*82527734SSukumar Swaminathan 	emlxs_process_link_speed(hba);
711*82527734SSukumar Swaminathan 
712*82527734SSukumar Swaminathan 	/*
713*82527734SSukumar Swaminathan 	 * Allocate some memory for buffers
714*82527734SSukumar Swaminathan 	 */
715*82527734SSukumar Swaminathan 	if (emlxs_mem_alloc_buffer(hba) == 0) {
716*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
717*82527734SSukumar Swaminathan 		    "Unable to allocate memory buffers.");
718*82527734SSukumar Swaminathan 
719*82527734SSukumar Swaminathan 		rval = ENOMEM;
720*82527734SSukumar Swaminathan 		goto failed1;
721*82527734SSukumar Swaminathan 	}
722*82527734SSukumar Swaminathan 
723*82527734SSukumar Swaminathan 	/*
724*82527734SSukumar Swaminathan 	 * OutOfRange (oor) iotags are used for abort or close
725*82527734SSukumar Swaminathan 	 * XRI commands or any WQE that does not require a SGL
726*82527734SSukumar Swaminathan 	 */
727*82527734SSukumar Swaminathan 	hba->fc_oor_iotag = hba->max_iotag;
728*82527734SSukumar Swaminathan 
729*82527734SSukumar Swaminathan 	if (emlxs_sli4_resource_alloc(hba)) {
730*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
731*82527734SSukumar Swaminathan 		    "Unable to allocate resources.");
732*82527734SSukumar Swaminathan 
733*82527734SSukumar Swaminathan 		rval = ENOMEM;
734*82527734SSukumar Swaminathan 		goto failed2;
735*82527734SSukumar Swaminathan 	}
736*82527734SSukumar Swaminathan emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
737*82527734SSukumar Swaminathan 
738*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
739*82527734SSukumar Swaminathan 	if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
740*82527734SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports = hba->vpi_max;
741*82527734SSukumar Swaminathan 	}
742*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
743*82527734SSukumar Swaminathan 
744*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
745*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
746*82527734SSukumar Swaminathan 
747*82527734SSukumar Swaminathan 	if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
748*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
749*82527734SSukumar Swaminathan 		    "Unable to post sgl pages.");
750*82527734SSukumar Swaminathan 
751*82527734SSukumar Swaminathan 		rval = EIO;
752*82527734SSukumar Swaminathan 		goto failed3;
753*82527734SSukumar Swaminathan 	}
754*82527734SSukumar Swaminathan 
755*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
756*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
757*82527734SSukumar Swaminathan 
758*82527734SSukumar Swaminathan 	if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
759*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
760*82527734SSukumar Swaminathan 		    "Unable to post header templates.");
761*82527734SSukumar Swaminathan 
762*82527734SSukumar Swaminathan 		rval = EIO;
763*82527734SSukumar Swaminathan 		goto failed3;
764*82527734SSukumar Swaminathan 	}
765*82527734SSukumar Swaminathan 
766*82527734SSukumar Swaminathan 	/*
767*82527734SSukumar Swaminathan 	 * Add our interrupt routine to kernel's interrupt chain & enable it
768*82527734SSukumar Swaminathan 	 * If MSI is enabled this will cause Solaris to program the MSI address
769*82527734SSukumar Swaminathan 	 * and data registers in PCI config space
770*82527734SSukumar Swaminathan 	 */
771*82527734SSukumar Swaminathan 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
772*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
773*82527734SSukumar Swaminathan 		    "Unable to add interrupt(s).");
774*82527734SSukumar Swaminathan 
775*82527734SSukumar Swaminathan 		rval = EIO;
776*82527734SSukumar Swaminathan 		goto failed3;
777*82527734SSukumar Swaminathan 	}
778*82527734SSukumar Swaminathan 
779*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
780*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
781*82527734SSukumar Swaminathan 
782*82527734SSukumar Swaminathan 	/* This MUST be done after EMLXS_INTR_ADD */
783*82527734SSukumar Swaminathan 	if (emlxs_sli4_create_queues(hba, mbq)) {
784*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
785*82527734SSukumar Swaminathan 		    "Unable to create queues.");
786*82527734SSukumar Swaminathan 
787*82527734SSukumar Swaminathan 		rval = EIO;
788*82527734SSukumar Swaminathan 		goto failed3;
789*82527734SSukumar Swaminathan 	}
790*82527734SSukumar Swaminathan 
791*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
792*82527734SSukumar Swaminathan 
793*82527734SSukumar Swaminathan 	/* Get and save the current firmware version (based on sli_mode) */
794*82527734SSukumar Swaminathan 	emlxs_decode_firmware_rev(hba, vpd);
795*82527734SSukumar Swaminathan 
796*82527734SSukumar Swaminathan 	/*
797*82527734SSukumar Swaminathan 	 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
798*82527734SSukumar Swaminathan 	 */
799*82527734SSukumar Swaminathan 	if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) ||
800*82527734SSukumar Swaminathan 	    ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0)) {
801*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
802*82527734SSukumar Swaminathan 		    "Unable to allocate diag buffers.");
803*82527734SSukumar Swaminathan 
804*82527734SSukumar Swaminathan 		rval = ENOMEM;
805*82527734SSukumar Swaminathan 		goto failed3;
806*82527734SSukumar Swaminathan 	}
807*82527734SSukumar Swaminathan 
808*82527734SSukumar Swaminathan 	bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
809*82527734SSukumar Swaminathan 	    MEM_ELSBUF_SIZE);
810*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
811*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
812*82527734SSukumar Swaminathan 
813*82527734SSukumar Swaminathan 	bzero(mp1->virt, MEM_ELSBUF_SIZE);
814*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
815*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
816*82527734SSukumar Swaminathan 
817*82527734SSukumar Swaminathan 
818*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
819*82527734SSukumar Swaminathan 	mp = NULL;
820*82527734SSukumar Swaminathan 
821*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
822*82527734SSukumar Swaminathan 
823*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
824*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
825*82527734SSukumar Swaminathan 
826*82527734SSukumar Swaminathan 	/*
827*82527734SSukumar Swaminathan 	 * We need to get login parameters for NID
828*82527734SSukumar Swaminathan 	 */
829*82527734SSukumar Swaminathan 	(void) emlxs_mb_read_sparam(hba, mbq);
830*82527734SSukumar Swaminathan 	mp = (MATCHMAP *)(mbq->bp);
831*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
832*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
833*82527734SSukumar Swaminathan 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
834*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
835*82527734SSukumar Swaminathan 
836*82527734SSukumar Swaminathan 		rval = EIO;
837*82527734SSukumar Swaminathan 		goto failed3;
838*82527734SSukumar Swaminathan 	}
839*82527734SSukumar Swaminathan 
840*82527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
841*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
842*82527734SSukumar Swaminathan 	mp = NULL;
843*82527734SSukumar Swaminathan 
844*82527734SSukumar Swaminathan 	/* If no serial number in VPD data, then use the WWPN */
845*82527734SSukumar Swaminathan 	if (vpd->serial_num[0] == 0) {
846*82527734SSukumar Swaminathan 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
847*82527734SSukumar Swaminathan 		for (i = 0; i < 12; i++) {
848*82527734SSukumar Swaminathan 			status = *outptr++;
849*82527734SSukumar Swaminathan 			j = ((status & 0xf0) >> 4);
850*82527734SSukumar Swaminathan 			if (j <= 9) {
851*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
852*82527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
853*82527734SSukumar Swaminathan 			} else {
854*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
855*82527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
856*82527734SSukumar Swaminathan 			}
857*82527734SSukumar Swaminathan 
858*82527734SSukumar Swaminathan 			i++;
859*82527734SSukumar Swaminathan 			j = (status & 0xf);
860*82527734SSukumar Swaminathan 			if (j <= 9) {
861*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
862*82527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
863*82527734SSukumar Swaminathan 			} else {
864*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
865*82527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
866*82527734SSukumar Swaminathan 			}
867*82527734SSukumar Swaminathan 		}
868*82527734SSukumar Swaminathan 
869*82527734SSukumar Swaminathan 		/*
870*82527734SSukumar Swaminathan 		 * Set port number and port index to zero
871*82527734SSukumar Swaminathan 		 * The WWN's are unique to each port and therefore port_num
872*82527734SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
873*82527734SSukumar Swaminathan 		 * in fca_bind_port()
874*82527734SSukumar Swaminathan 		 */
875*82527734SSukumar Swaminathan 		vpd->port_num[0] = 0;
876*82527734SSukumar Swaminathan 		vpd->port_index = 0;
877*82527734SSukumar Swaminathan 	}
878*82527734SSukumar Swaminathan 
879*82527734SSukumar Swaminathan 	/* Make attempt to set a port index */
880*82527734SSukumar Swaminathan 	if (vpd->port_index == -1) {
881*82527734SSukumar Swaminathan 		dev_info_t *p_dip;
882*82527734SSukumar Swaminathan 		dev_info_t *c_dip;
883*82527734SSukumar Swaminathan 
884*82527734SSukumar Swaminathan 		p_dip = ddi_get_parent(hba->dip);
885*82527734SSukumar Swaminathan 		c_dip = ddi_get_child(p_dip);
886*82527734SSukumar Swaminathan 
887*82527734SSukumar Swaminathan 		vpd->port_index = 0;
888*82527734SSukumar Swaminathan 		while (c_dip && (hba->dip != c_dip)) {
889*82527734SSukumar Swaminathan 			c_dip = ddi_get_next_sibling(c_dip);
890*82527734SSukumar Swaminathan 
891*82527734SSukumar Swaminathan 			if (strcmp(ddi_get_name(c_dip), "ethernet")) {
892*82527734SSukumar Swaminathan 				vpd->port_index++;
893*82527734SSukumar Swaminathan 			}
894*82527734SSukumar Swaminathan 		}
895*82527734SSukumar Swaminathan 	}
896*82527734SSukumar Swaminathan 
897*82527734SSukumar Swaminathan 	if (vpd->port_num[0] == 0) {
898*82527734SSukumar Swaminathan 		if (hba->model_info.channels > 1) {
899*82527734SSukumar Swaminathan 			(void) sprintf(vpd->port_num, "%d", vpd->port_index);
900*82527734SSukumar Swaminathan 		}
901*82527734SSukumar Swaminathan 	}
902*82527734SSukumar Swaminathan 
903*82527734SSukumar Swaminathan 	if (vpd->id[0] == 0) {
904*82527734SSukumar Swaminathan 		(void) sprintf(vpd->id, "%s %d",
905*82527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
906*82527734SSukumar Swaminathan 
907*82527734SSukumar Swaminathan 	}
908*82527734SSukumar Swaminathan 
909*82527734SSukumar Swaminathan 	if (vpd->manufacturer[0] == 0) {
910*82527734SSukumar Swaminathan 		(void) strcpy(vpd->manufacturer, hba->model_info.manufacturer);
911*82527734SSukumar Swaminathan 	}
912*82527734SSukumar Swaminathan 
913*82527734SSukumar Swaminathan 	if (vpd->part_num[0] == 0) {
914*82527734SSukumar Swaminathan 		(void) strcpy(vpd->part_num, hba->model_info.model);
915*82527734SSukumar Swaminathan 	}
916*82527734SSukumar Swaminathan 
917*82527734SSukumar Swaminathan 	if (vpd->model_desc[0] == 0) {
918*82527734SSukumar Swaminathan 		(void) sprintf(vpd->model_desc, "%s %d",
919*82527734SSukumar Swaminathan 		    hba->model_info.model_desc, vpd->port_index);
920*82527734SSukumar Swaminathan 	}
921*82527734SSukumar Swaminathan 
922*82527734SSukumar Swaminathan 	if (vpd->model[0] == 0) {
923*82527734SSukumar Swaminathan 		(void) strcpy(vpd->model, hba->model_info.model);
924*82527734SSukumar Swaminathan 	}
925*82527734SSukumar Swaminathan 
926*82527734SSukumar Swaminathan 	if (vpd->prog_types[0] == 0) {
927*82527734SSukumar Swaminathan 		emlxs_build_prog_types(hba, vpd->prog_types);
928*82527734SSukumar Swaminathan 	}
929*82527734SSukumar Swaminathan 
930*82527734SSukumar Swaminathan 	/* Create the symbolic names */
931*82527734SSukumar Swaminathan 	(void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s",
932*82527734SSukumar Swaminathan 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
933*82527734SSukumar Swaminathan 	    (char *)utsname.nodename);
934*82527734SSukumar Swaminathan 
935*82527734SSukumar Swaminathan 	(void) sprintf(hba->spn,
936*82527734SSukumar Swaminathan 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
937*82527734SSukumar Swaminathan 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
938*82527734SSukumar Swaminathan 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
939*82527734SSukumar Swaminathan 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
940*82527734SSukumar Swaminathan 
941*82527734SSukumar Swaminathan 
942*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
943*82527734SSukumar Swaminathan 	emlxs_sli4_enable_intr(hba);
944*82527734SSukumar Swaminathan 
945*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
946*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
947*82527734SSukumar Swaminathan 
948*82527734SSukumar Swaminathan 	/*
949*82527734SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command
950*82527734SSukumar Swaminathan 	 * At this point, the interrupt will be generated by the HW
951*82527734SSukumar Swaminathan 	 * Do this only if persist-linkdown is not set
952*82527734SSukumar Swaminathan 	 */
953*82527734SSukumar Swaminathan 	if (cfg[CFG_PERSIST_LINKDOWN].current == 0) {
954*82527734SSukumar Swaminathan 		emlxs_mb_init_link(hba, mbq,
955*82527734SSukumar Swaminathan 		    cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
956*82527734SSukumar Swaminathan 
957*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0)
958*82527734SSukumar Swaminathan 		    != MBX_SUCCESS) {
959*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
960*82527734SSukumar Swaminathan 			    "Unable to initialize link. " \
961*82527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
962*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
963*82527734SSukumar Swaminathan 
964*82527734SSukumar Swaminathan 			rval = EIO;
965*82527734SSukumar Swaminathan 			goto failed3;
966*82527734SSukumar Swaminathan 		}
967*82527734SSukumar Swaminathan 
968*82527734SSukumar Swaminathan 		/* Wait for link to come up */
969*82527734SSukumar Swaminathan 		i = cfg[CFG_LINKUP_DELAY].current;
970*82527734SSukumar Swaminathan 		while (i && (hba->state < FC_LINK_UP)) {
971*82527734SSukumar Swaminathan 			/* Check for hardware error */
972*82527734SSukumar Swaminathan 			if (hba->state == FC_ERROR) {
973*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
974*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
975*82527734SSukumar Swaminathan 				    "Adapter error.", mb->mbxCommand,
976*82527734SSukumar Swaminathan 				    mb->mbxStatus);
977*82527734SSukumar Swaminathan 
978*82527734SSukumar Swaminathan 				rval = EIO;
979*82527734SSukumar Swaminathan 				goto failed3;
980*82527734SSukumar Swaminathan 			}
981*82527734SSukumar Swaminathan 
982*82527734SSukumar Swaminathan 			DELAYMS(1000);
983*82527734SSukumar Swaminathan 			i--;
984*82527734SSukumar Swaminathan 		}
985*82527734SSukumar Swaminathan 	}
986*82527734SSukumar Swaminathan 
987*82527734SSukumar Swaminathan 	/*
988*82527734SSukumar Swaminathan 	 * The leadvile driver will now handle the FLOGI at the driver level
989*82527734SSukumar Swaminathan 	 */
990*82527734SSukumar Swaminathan 
991*82527734SSukumar Swaminathan 	return (0);
992*82527734SSukumar Swaminathan 
993*82527734SSukumar Swaminathan failed3:
994*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
995*82527734SSukumar Swaminathan 
996*82527734SSukumar Swaminathan 	if (mp) {
997*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
998*82527734SSukumar Swaminathan 		mp = NULL;
999*82527734SSukumar Swaminathan 	}
1000*82527734SSukumar Swaminathan 
1001*82527734SSukumar Swaminathan 	if (mp1) {
1002*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
1003*82527734SSukumar Swaminathan 		mp1 = NULL;
1004*82527734SSukumar Swaminathan 	}
1005*82527734SSukumar Swaminathan 
1006*82527734SSukumar Swaminathan 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
1007*82527734SSukumar Swaminathan 		(void) EMLXS_INTR_REMOVE(hba);
1008*82527734SSukumar Swaminathan 	}
1009*82527734SSukumar Swaminathan 
1010*82527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
1011*82527734SSukumar Swaminathan 
1012*82527734SSukumar Swaminathan failed2:
1013*82527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1014*82527734SSukumar Swaminathan 
1015*82527734SSukumar Swaminathan failed1:
1016*82527734SSukumar Swaminathan 	if (mbq) {
1017*82527734SSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1018*82527734SSukumar Swaminathan 		mbq = NULL;
1019*82527734SSukumar Swaminathan 		mb = NULL;
1020*82527734SSukumar Swaminathan 	}
1021*82527734SSukumar Swaminathan 
1022*82527734SSukumar Swaminathan 	if (hba->sli.sli4.dump_region.virt) {
1023*82527734SSukumar Swaminathan 		(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1024*82527734SSukumar Swaminathan 	}
1025*82527734SSukumar Swaminathan 
1026*82527734SSukumar Swaminathan 	if (rval == 0) {
1027*82527734SSukumar Swaminathan 		rval = EIO;
1028*82527734SSukumar Swaminathan 	}
1029*82527734SSukumar Swaminathan 
1030*82527734SSukumar Swaminathan 	return (rval);
1031*82527734SSukumar Swaminathan 
1032*82527734SSukumar Swaminathan } /* emlxs_sli4_online() */
1033*82527734SSukumar Swaminathan 
1034*82527734SSukumar Swaminathan 
1035*82527734SSukumar Swaminathan static void
1036*82527734SSukumar Swaminathan emlxs_sli4_offline(emlxs_hba_t *hba)
1037*82527734SSukumar Swaminathan {
1038*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
1039*82527734SSukumar Swaminathan 	MAILBOXQ mboxq;
1040*82527734SSukumar Swaminathan 
1041*82527734SSukumar Swaminathan 	/* Reverse emlxs_sli4_online */
1042*82527734SSukumar Swaminathan 
1043*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
1044*82527734SSukumar Swaminathan 	if (!(hba->flag & FC_INTERLOCKED)) {
1045*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
1046*82527734SSukumar Swaminathan 
1047*82527734SSukumar Swaminathan 		/* This is the only way to disable interupts */
1048*82527734SSukumar Swaminathan 		bzero((void *)&mboxq, sizeof (MAILBOXQ));
1049*82527734SSukumar Swaminathan 		emlxs_mb_resetport(hba, &mboxq);
1050*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
1051*82527734SSukumar Swaminathan 		    MBX_WAIT, 0) != MBX_SUCCESS) {
1052*82527734SSukumar Swaminathan 			/* Timeout occurred */
1053*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1054*82527734SSukumar Swaminathan 			    "Timeout: Offline RESET");
1055*82527734SSukumar Swaminathan 		}
1056*82527734SSukumar Swaminathan 		(void) emlxs_check_hdw_ready(hba);
1057*82527734SSukumar Swaminathan 	} else {
1058*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
1059*82527734SSukumar Swaminathan 	}
1060*82527734SSukumar Swaminathan 
1061*82527734SSukumar Swaminathan 
1062*82527734SSukumar Swaminathan 	/* Shutdown the adapter interface */
1063*82527734SSukumar Swaminathan 	emlxs_sli4_hba_kill(hba);
1064*82527734SSukumar Swaminathan 
1065*82527734SSukumar Swaminathan 	/* Free SLI shared memory */
1066*82527734SSukumar Swaminathan 	emlxs_sli4_resource_free(hba);
1067*82527734SSukumar Swaminathan 
1068*82527734SSukumar Swaminathan 	/* Free driver shared memory */
1069*82527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1070*82527734SSukumar Swaminathan 
1071*82527734SSukumar Swaminathan 	/* Free the host dump region buffer */
1072*82527734SSukumar Swaminathan 	(void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1073*82527734SSukumar Swaminathan 
1074*82527734SSukumar Swaminathan } /* emlxs_sli4_offline() */
1075*82527734SSukumar Swaminathan 
1076*82527734SSukumar Swaminathan 
1077*82527734SSukumar Swaminathan /*ARGSUSED*/
1078*82527734SSukumar Swaminathan static int
1079*82527734SSukumar Swaminathan emlxs_sli4_map_hdw(emlxs_hba_t *hba)
1080*82527734SSukumar Swaminathan {
1081*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
1082*82527734SSukumar Swaminathan 	dev_info_t		*dip;
1083*82527734SSukumar Swaminathan 	ddi_device_acc_attr_t	dev_attr;
1084*82527734SSukumar Swaminathan 	int			status;
1085*82527734SSukumar Swaminathan 
1086*82527734SSukumar Swaminathan 	dip = (dev_info_t *)hba->dip;
1087*82527734SSukumar Swaminathan 	dev_attr = emlxs_dev_acc_attr;
1088*82527734SSukumar Swaminathan 
1089*82527734SSukumar Swaminathan 	/*
1090*82527734SSukumar Swaminathan 	 * Map in Hardware BAR pages that will be used for
1091*82527734SSukumar Swaminathan 	 * communication with HBA.
1092*82527734SSukumar Swaminathan 	 */
1093*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bar1_acc_handle == 0) {
1094*82527734SSukumar Swaminathan 		status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
1095*82527734SSukumar Swaminathan 		    (caddr_t *)&hba->sli.sli4.bar1_addr,
1096*82527734SSukumar Swaminathan 		    0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
1097*82527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
1098*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
1099*82527734SSukumar Swaminathan 			    &emlxs_attach_failed_msg,
1100*82527734SSukumar Swaminathan 			    "(PCI) ddi_regs_map_setup BAR1 failed. "
1101*82527734SSukumar Swaminathan 			    "stat=%d mem=%p attr=%p hdl=%p",
1102*82527734SSukumar Swaminathan 			    status, &hba->sli.sli4.bar1_addr, &dev_attr,
1103*82527734SSukumar Swaminathan 			    &hba->sli.sli4.bar1_acc_handle);
1104*82527734SSukumar Swaminathan 			goto failed;
1105*82527734SSukumar Swaminathan 		}
1106*82527734SSukumar Swaminathan 	}
1107*82527734SSukumar Swaminathan 
1108*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bar2_acc_handle == 0) {
1109*82527734SSukumar Swaminathan 		status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
1110*82527734SSukumar Swaminathan 		    (caddr_t *)&hba->sli.sli4.bar2_addr,
1111*82527734SSukumar Swaminathan 		    0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
1112*82527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
1113*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
1114*82527734SSukumar Swaminathan 			    &emlxs_attach_failed_msg,
1115*82527734SSukumar Swaminathan 			    "ddi_regs_map_setup BAR2 failed. status=%x",
1116*82527734SSukumar Swaminathan 			    status);
1117*82527734SSukumar Swaminathan 			goto failed;
1118*82527734SSukumar Swaminathan 		}
1119*82527734SSukumar Swaminathan 	}
1120*82527734SSukumar Swaminathan 
1121*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt == 0) {
1122*82527734SSukumar Swaminathan 		MBUF_INFO	*buf_info;
1123*82527734SSukumar Swaminathan 		MBUF_INFO	bufinfo;
1124*82527734SSukumar Swaminathan 
1125*82527734SSukumar Swaminathan 		buf_info = &bufinfo;
1126*82527734SSukumar Swaminathan 
1127*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1128*82527734SSukumar Swaminathan 		buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
1129*82527734SSukumar Swaminathan 		buf_info->flags =
1130*82527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1131*82527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(dip, 1L);
1132*82527734SSukumar Swaminathan 
1133*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
1134*82527734SSukumar Swaminathan 
1135*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
1136*82527734SSukumar Swaminathan 			goto failed;
1137*82527734SSukumar Swaminathan 		}
1138*82527734SSukumar Swaminathan 
1139*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.virt = (uint8_t *)buf_info->virt;
1140*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
1141*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
1142*82527734SSukumar Swaminathan 		    MBOX_EXTENSION_SIZE;
1143*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
1144*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
1145*82527734SSukumar Swaminathan 		bzero((char *)hba->sli.sli4.bootstrapmb.virt,
1146*82527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE);
1147*82527734SSukumar Swaminathan 	}
1148*82527734SSukumar Swaminathan 
1149*82527734SSukumar Swaminathan 	/* offset from beginning of register space */
1150*82527734SSukumar Swaminathan 	hba->sli.sli4.MPUEPSemaphore_reg_addr =
1151*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar1_addr + CSR_MPU_EP_SEMAPHORE_OFFSET);
1152*82527734SSukumar Swaminathan 	hba->sli.sli4.MBDB_reg_addr =
1153*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
1154*82527734SSukumar Swaminathan 	hba->sli.sli4.CQDB_reg_addr =
1155*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
1156*82527734SSukumar Swaminathan 	hba->sli.sli4.MQDB_reg_addr =
1157*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
1158*82527734SSukumar Swaminathan 	hba->sli.sli4.WQDB_reg_addr =
1159*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
1160*82527734SSukumar Swaminathan 	hba->sli.sli4.RQDB_reg_addr =
1161*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
1162*82527734SSukumar Swaminathan 	hba->chan_count = MAX_CHANNEL;
1163*82527734SSukumar Swaminathan 
1164*82527734SSukumar Swaminathan 	return (0);
1165*82527734SSukumar Swaminathan 
1166*82527734SSukumar Swaminathan failed:
1167*82527734SSukumar Swaminathan 
1168*82527734SSukumar Swaminathan 	emlxs_sli4_unmap_hdw(hba);
1169*82527734SSukumar Swaminathan 	return (ENOMEM);
1170*82527734SSukumar Swaminathan 
1171*82527734SSukumar Swaminathan 
1172*82527734SSukumar Swaminathan } /* emlxs_sli4_map_hdw() */
1173*82527734SSukumar Swaminathan 
1174*82527734SSukumar Swaminathan 
1175*82527734SSukumar Swaminathan /*ARGSUSED*/
1176*82527734SSukumar Swaminathan static void
1177*82527734SSukumar Swaminathan emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
1178*82527734SSukumar Swaminathan {
1179*82527734SSukumar Swaminathan 	MBUF_INFO	bufinfo;
1180*82527734SSukumar Swaminathan 	MBUF_INFO	*buf_info = &bufinfo;
1181*82527734SSukumar Swaminathan 
1182*82527734SSukumar Swaminathan 	/*
1183*82527734SSukumar Swaminathan 	 * Free map for Hardware BAR pages that were used for
1184*82527734SSukumar Swaminathan 	 * communication with HBA.
1185*82527734SSukumar Swaminathan 	 */
1186*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bar1_acc_handle) {
1187*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
1188*82527734SSukumar Swaminathan 		hba->sli.sli4.bar1_acc_handle = 0;
1189*82527734SSukumar Swaminathan 	}
1190*82527734SSukumar Swaminathan 
1191*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bar2_acc_handle) {
1192*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
1193*82527734SSukumar Swaminathan 		hba->sli.sli4.bar2_acc_handle = 0;
1194*82527734SSukumar Swaminathan 	}
1195*82527734SSukumar Swaminathan 	if (hba->sli.sli4.bootstrapmb.virt) {
1196*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1197*82527734SSukumar Swaminathan 
1198*82527734SSukumar Swaminathan 		if (hba->sli.sli4.bootstrapmb.phys) {
1199*82527734SSukumar Swaminathan 			buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
1200*82527734SSukumar Swaminathan 			buf_info->data_handle =
1201*82527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.data_handle;
1202*82527734SSukumar Swaminathan 			buf_info->dma_handle =
1203*82527734SSukumar Swaminathan 			    hba->sli.sli4.bootstrapmb.dma_handle;
1204*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
1205*82527734SSukumar Swaminathan 		}
1206*82527734SSukumar Swaminathan 
1207*82527734SSukumar Swaminathan 		buf_info->virt = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
1208*82527734SSukumar Swaminathan 		buf_info->size = hba->sli.sli4.bootstrapmb.size;
1209*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
1210*82527734SSukumar Swaminathan 
1211*82527734SSukumar Swaminathan 		hba->sli.sli4.bootstrapmb.virt = 0;
1212*82527734SSukumar Swaminathan 	}
1213*82527734SSukumar Swaminathan 
1214*82527734SSukumar Swaminathan 	return;
1215*82527734SSukumar Swaminathan 
1216*82527734SSukumar Swaminathan } /* emlxs_sli4_unmap_hdw() */
1217*82527734SSukumar Swaminathan 
1218*82527734SSukumar Swaminathan 
1219*82527734SSukumar Swaminathan static int
1220*82527734SSukumar Swaminathan emlxs_check_hdw_ready(emlxs_hba_t *hba)
1221*82527734SSukumar Swaminathan {
1222*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1223*82527734SSukumar Swaminathan 	uint32_t status;
1224*82527734SSukumar Swaminathan 	uint32_t i = 0;
1225*82527734SSukumar Swaminathan 
1226*82527734SSukumar Swaminathan 	/* Wait for reset completion */
1227*82527734SSukumar Swaminathan 	while (i < 30) {
1228*82527734SSukumar Swaminathan 		/* Check Semaphore register to see what the ARM state is */
1229*82527734SSukumar Swaminathan 		status = READ_BAR1_REG(hba, FC_SEMA_REG(hba));
1230*82527734SSukumar Swaminathan 
1231*82527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
1232*82527734SSukumar Swaminathan 		if (status & ARM_POST_FATAL) {
1233*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1234*82527734SSukumar Swaminathan 			    "SEMA Error: status=0x%x", status);
1235*82527734SSukumar Swaminathan 
1236*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1237*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1238*82527734SSukumar Swaminathan 			/* Access handle validation */
1239*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
1240*82527734SSukumar Swaminathan 			    hba->sli.sli4.bar1_acc_handle);
1241*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1242*82527734SSukumar Swaminathan 			return (1);
1243*82527734SSukumar Swaminathan 		}
1244*82527734SSukumar Swaminathan 		if ((status & ARM_POST_MASK) == ARM_POST_READY) {
1245*82527734SSukumar Swaminathan 			/* ARM Ready !! */
1246*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1247*82527734SSukumar Swaminathan 			    "ARM Ready: status=0x%x", status);
1248*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1249*82527734SSukumar Swaminathan 			/* Access handle validation */
1250*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
1251*82527734SSukumar Swaminathan 			    hba->sli.sli4.bar1_acc_handle);
1252*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1253*82527734SSukumar Swaminathan 			return (0);
1254*82527734SSukumar Swaminathan 		}
1255*82527734SSukumar Swaminathan 
1256*82527734SSukumar Swaminathan 		DELAYMS(1000);
1257*82527734SSukumar Swaminathan 		i++;
1258*82527734SSukumar Swaminathan 	}
1259*82527734SSukumar Swaminathan 
1260*82527734SSukumar Swaminathan 	/* Timeout occurred */
1261*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1262*82527734SSukumar Swaminathan 	    "Timeout waiting for READY: status=0x%x", status);
1263*82527734SSukumar Swaminathan 
1264*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1265*82527734SSukumar Swaminathan 
1266*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1267*82527734SSukumar Swaminathan 	/* Access handle validation */
1268*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
1269*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1270*82527734SSukumar Swaminathan 
1271*82527734SSukumar Swaminathan 	/* Log a dump event - not supported */
1272*82527734SSukumar Swaminathan 
1273*82527734SSukumar Swaminathan 	return (2);
1274*82527734SSukumar Swaminathan 
1275*82527734SSukumar Swaminathan } /* emlxs_check_hdw_ready() */
1276*82527734SSukumar Swaminathan 
1277*82527734SSukumar Swaminathan 
1278*82527734SSukumar Swaminathan static uint32_t
1279*82527734SSukumar Swaminathan emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
1280*82527734SSukumar Swaminathan {
1281*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1282*82527734SSukumar Swaminathan 	uint32_t status;
1283*82527734SSukumar Swaminathan 
1284*82527734SSukumar Swaminathan 	/* Wait for reset completion, tmo is in 10ms ticks */
1285*82527734SSukumar Swaminathan 	while (tmo) {
1286*82527734SSukumar Swaminathan 		/* Check Semaphore register to see what the ARM state is */
1287*82527734SSukumar Swaminathan 		status = READ_BAR2_REG(hba, FC_MBDB_REG(hba));
1288*82527734SSukumar Swaminathan 
1289*82527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
1290*82527734SSukumar Swaminathan 		if (status & BMBX_READY) {
1291*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1292*82527734SSukumar Swaminathan 			    "BMBX Ready: status=0x%x", status);
1293*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1294*82527734SSukumar Swaminathan 			/* Access handle validation */
1295*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
1296*82527734SSukumar Swaminathan 			    hba->sli.sli4.bar2_acc_handle);
1297*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1298*82527734SSukumar Swaminathan 			return (tmo);
1299*82527734SSukumar Swaminathan 		}
1300*82527734SSukumar Swaminathan 
1301*82527734SSukumar Swaminathan 		DELAYMS(10);
1302*82527734SSukumar Swaminathan 		tmo--;
1303*82527734SSukumar Swaminathan 	}
1304*82527734SSukumar Swaminathan 
1305*82527734SSukumar Swaminathan 	/* Timeout occurred */
1306*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1307*82527734SSukumar Swaminathan 	    "Timeout waiting for BMailbox: status=0x%x", status);
1308*82527734SSukumar Swaminathan 
1309*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1310*82527734SSukumar Swaminathan 
1311*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1312*82527734SSukumar Swaminathan 	/* Access handle validation */
1313*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
1314*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
1315*82527734SSukumar Swaminathan 
1316*82527734SSukumar Swaminathan 	/* Log a dump event - not supported */
1317*82527734SSukumar Swaminathan 
1318*82527734SSukumar Swaminathan 	return (0);
1319*82527734SSukumar Swaminathan 
1320*82527734SSukumar Swaminathan } /* emlxs_check_bootstrap_ready() */
1321*82527734SSukumar Swaminathan 
1322*82527734SSukumar Swaminathan 
1323*82527734SSukumar Swaminathan static uint32_t
1324*82527734SSukumar Swaminathan emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
1325*82527734SSukumar Swaminathan {
1326*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1327*82527734SSukumar Swaminathan 	uint32_t *iptr;
1328*82527734SSukumar Swaminathan 	uint32_t addr30;
1329*82527734SSukumar Swaminathan 
1330*82527734SSukumar Swaminathan 	/*
1331*82527734SSukumar Swaminathan 	 * This routine assumes the bootstrap mbox is loaded
1332*82527734SSukumar Swaminathan 	 * with the mailbox command to be executed.
1333*82527734SSukumar Swaminathan 	 *
1334*82527734SSukumar Swaminathan 	 * First, load the high 30 bits of bootstrap mailbox
1335*82527734SSukumar Swaminathan 	 */
1336*82527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
1337*82527734SSukumar Swaminathan 	addr30 |= BMBX_ADDR_HI;
1338*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
1339*82527734SSukumar Swaminathan 
1340*82527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
1341*82527734SSukumar Swaminathan 	if (tmo == 0) {
1342*82527734SSukumar Swaminathan 		return (0);
1343*82527734SSukumar Swaminathan 	}
1344*82527734SSukumar Swaminathan 
1345*82527734SSukumar Swaminathan 	/* Load the low 30 bits of bootstrap mailbox */
1346*82527734SSukumar Swaminathan 	addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
1347*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MBDB_REG(hba), addr30);
1348*82527734SSukumar Swaminathan 
1349*82527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, tmo);
1350*82527734SSukumar Swaminathan 	if (tmo == 0) {
1351*82527734SSukumar Swaminathan 		return (0);
1352*82527734SSukumar Swaminathan 	}
1353*82527734SSukumar Swaminathan 
1354*82527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
1355*82527734SSukumar Swaminathan 
1356*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
1357*82527734SSukumar Swaminathan 	    "BootstrapMB: %p Completed %08x %08x %08x",
1358*82527734SSukumar Swaminathan 	    hba->sli.sli4.bootstrapmb.virt,
1359*82527734SSukumar Swaminathan 	    *iptr, *(iptr+1), *(iptr+2));
1360*82527734SSukumar Swaminathan 
1361*82527734SSukumar Swaminathan 	return (tmo);
1362*82527734SSukumar Swaminathan 
1363*82527734SSukumar Swaminathan } /* emlxs_issue_bootstrap_mb() */
1364*82527734SSukumar Swaminathan 
1365*82527734SSukumar Swaminathan 
1366*82527734SSukumar Swaminathan static int
1367*82527734SSukumar Swaminathan emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
1368*82527734SSukumar Swaminathan {
1369*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
1370*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1371*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */
1372*82527734SSukumar Swaminathan 	uint32_t *iptr;
1373*82527734SSukumar Swaminathan 	uint32_t tmo;
1374*82527734SSukumar Swaminathan 
1375*82527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
1376*82527734SSukumar Swaminathan 		return (1);
1377*82527734SSukumar Swaminathan 	}
1378*82527734SSukumar Swaminathan 
1379*82527734SSukumar Swaminathan 	if (hba->flag & FC_BOOTSTRAPMB_INIT) {
1380*82527734SSukumar Swaminathan 		return (0);  /* Already initialized */
1381*82527734SSukumar Swaminathan 	}
1382*82527734SSukumar Swaminathan 
1383*82527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
1384*82527734SSukumar Swaminathan 	tmo = emlxs_check_bootstrap_ready(hba, 3000);
1385*82527734SSukumar Swaminathan 	if (tmo == 0) {
1386*82527734SSukumar Swaminathan 		return (1);
1387*82527734SSukumar Swaminathan 	}
1388*82527734SSukumar Swaminathan 
1389*82527734SSukumar Swaminathan 	/* Special words to initialize bootstrap mbox MUST be little endian */
1390*82527734SSukumar Swaminathan 	iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
1391*82527734SSukumar Swaminathan 	*iptr++ = LE_SWAP32(MQE_SPECIAL_WORD0);
1392*82527734SSukumar Swaminathan 	*iptr = LE_SWAP32(MQE_SPECIAL_WORD1);
1393*82527734SSukumar Swaminathan 
1394*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
1395*82527734SSukumar Swaminathan 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
1396*82527734SSukumar Swaminathan 
1397*82527734SSukumar Swaminathan emlxs_data_dump(hba, "EndianIN", (uint32_t *)iptr, 6, 0);
1398*82527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
1399*82527734SSukumar Swaminathan 		return (1);
1400*82527734SSukumar Swaminathan 	}
1401*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
1402*82527734SSukumar Swaminathan 	    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
1403*82527734SSukumar Swaminathan emlxs_data_dump(hba, "EndianOUT", (uint32_t *)iptr, 6, 0);
1404*82527734SSukumar Swaminathan 
1405*82527734SSukumar Swaminathan 	hba->flag |= FC_BOOTSTRAPMB_INIT;
1406*82527734SSukumar Swaminathan 	return (0);
1407*82527734SSukumar Swaminathan 
1408*82527734SSukumar Swaminathan } /* emlxs_init_bootstrap_mb() */
1409*82527734SSukumar Swaminathan 
1410*82527734SSukumar Swaminathan 
1411*82527734SSukumar Swaminathan static uint32_t
1412*82527734SSukumar Swaminathan emlxs_sli4_hba_init(emlxs_hba_t *hba)
1413*82527734SSukumar Swaminathan {
1414*82527734SSukumar Swaminathan 	int rc;
1415*82527734SSukumar Swaminathan 	uint32_t i;
1416*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
1417*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
1418*82527734SSukumar Swaminathan 	CHANNEL *cp;
1419*82527734SSukumar Swaminathan 
1420*82527734SSukumar Swaminathan 	/* Restart the adapter */
1421*82527734SSukumar Swaminathan 	if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
1422*82527734SSukumar Swaminathan 		return (1);
1423*82527734SSukumar Swaminathan 	}
1424*82527734SSukumar Swaminathan 
1425*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
1426*82527734SSukumar Swaminathan 		cp = &hba->chan[i];
1427*82527734SSukumar Swaminathan 		cp->iopath = (void *)&hba->sli.sli4.wq[i];
1428*82527734SSukumar Swaminathan 	}
1429*82527734SSukumar Swaminathan 
1430*82527734SSukumar Swaminathan 	/* Initialize all the port objects */
1431*82527734SSukumar Swaminathan 	hba->vpi_base = 0;
1432*82527734SSukumar Swaminathan 	hba->vpi_max  = 0;
1433*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
1434*82527734SSukumar Swaminathan 		vport = &VPORT(i);
1435*82527734SSukumar Swaminathan 		vport->hba = hba;
1436*82527734SSukumar Swaminathan 		vport->vpi = i;
1437*82527734SSukumar Swaminathan 	}
1438*82527734SSukumar Swaminathan 
1439*82527734SSukumar Swaminathan 	/* Set the max node count */
1440*82527734SSukumar Swaminathan 	if (hba->max_nodes == 0) {
1441*82527734SSukumar Swaminathan 		if (cfg[CFG_NUM_NODES].current > 0) {
1442*82527734SSukumar Swaminathan 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
1443*82527734SSukumar Swaminathan 		} else {
1444*82527734SSukumar Swaminathan 			hba->max_nodes = 4096;
1445*82527734SSukumar Swaminathan 		}
1446*82527734SSukumar Swaminathan 	}
1447*82527734SSukumar Swaminathan 
1448*82527734SSukumar Swaminathan 	rc = emlxs_init_bootstrap_mb(hba);
1449*82527734SSukumar Swaminathan 	if (rc) {
1450*82527734SSukumar Swaminathan 		return (rc);
1451*82527734SSukumar Swaminathan 	}
1452*82527734SSukumar Swaminathan 
1453*82527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
1454*82527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
1455*82527734SSukumar Swaminathan 	hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
1456*82527734SSukumar Swaminathan 
1457*82527734SSukumar Swaminathan 	return (0);
1458*82527734SSukumar Swaminathan 
1459*82527734SSukumar Swaminathan } /* emlxs_sli4_hba_init() */
1460*82527734SSukumar Swaminathan 
1461*82527734SSukumar Swaminathan 
1462*82527734SSukumar Swaminathan /*ARGSUSED*/
1463*82527734SSukumar Swaminathan static uint32_t
1464*82527734SSukumar Swaminathan emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
1465*82527734SSukumar Swaminathan 		uint32_t quiesce)
1466*82527734SSukumar Swaminathan {
1467*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1468*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
1469*82527734SSukumar Swaminathan 	CHANNEL *cp;
1470*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
1471*82527734SSukumar Swaminathan 	MAILBOXQ mboxq;
1472*82527734SSukumar Swaminathan 	uint32_t i;
1473*82527734SSukumar Swaminathan 	uint32_t rc;
1474*82527734SSukumar Swaminathan 	uint32_t channelno;
1475*82527734SSukumar Swaminathan 
1476*82527734SSukumar Swaminathan 	if (!cfg[CFG_RESET_ENABLE].current) {
1477*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1478*82527734SSukumar Swaminathan 		    "Adapter reset disabled.");
1479*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
1480*82527734SSukumar Swaminathan 
1481*82527734SSukumar Swaminathan 		return (1);
1482*82527734SSukumar Swaminathan 	}
1483*82527734SSukumar Swaminathan 
1484*82527734SSukumar Swaminathan 	if (quiesce == 0) {
1485*82527734SSukumar Swaminathan 		emlxs_sli4_hba_kill(hba);
1486*82527734SSukumar Swaminathan 
1487*82527734SSukumar Swaminathan 		/*
1488*82527734SSukumar Swaminathan 		 * Initalize Hardware that will be used to bring
1489*82527734SSukumar Swaminathan 		 * SLI4 online.
1490*82527734SSukumar Swaminathan 		 */
1491*82527734SSukumar Swaminathan 		rc = emlxs_init_bootstrap_mb(hba);
1492*82527734SSukumar Swaminathan 		if (rc) {
1493*82527734SSukumar Swaminathan 			return (rc);
1494*82527734SSukumar Swaminathan 		}
1495*82527734SSukumar Swaminathan 	}
1496*82527734SSukumar Swaminathan 
1497*82527734SSukumar Swaminathan 	bzero((void *)&mboxq, sizeof (MAILBOXQ));
1498*82527734SSukumar Swaminathan 	emlxs_mb_resetport(hba, &mboxq);
1499*82527734SSukumar Swaminathan 
1500*82527734SSukumar Swaminathan 	if (quiesce == 0) {
1501*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
1502*82527734SSukumar Swaminathan 		    MBX_POLL, 0) != MBX_SUCCESS) {
1503*82527734SSukumar Swaminathan 			/* Timeout occurred */
1504*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1505*82527734SSukumar Swaminathan 			    "Timeout: RESET");
1506*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1507*82527734SSukumar Swaminathan 			/* Log a dump event - not supported */
1508*82527734SSukumar Swaminathan 			return (1);
1509*82527734SSukumar Swaminathan 		}
1510*82527734SSukumar Swaminathan 	} else {
1511*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
1512*82527734SSukumar Swaminathan 		    MBX_POLL, 0) != MBX_SUCCESS) {
1513*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1514*82527734SSukumar Swaminathan 			/* Log a dump event - not supported */
1515*82527734SSukumar Swaminathan 			return (1);
1516*82527734SSukumar Swaminathan 		}
1517*82527734SSukumar Swaminathan 	}
1518*82527734SSukumar Swaminathan emlxs_data_dump(hba, "resetPort", (uint32_t *)&mboxq, 12, 0);
1519*82527734SSukumar Swaminathan 
1520*82527734SSukumar Swaminathan 	/* Reset the hba structure */
1521*82527734SSukumar Swaminathan 	hba->flag &= FC_RESET_MASK;
1522*82527734SSukumar Swaminathan 
1523*82527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
1524*82527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
1525*82527734SSukumar Swaminathan 		cp->hba = hba;
1526*82527734SSukumar Swaminathan 		cp->channelno = channelno;
1527*82527734SSukumar Swaminathan 	}
1528*82527734SSukumar Swaminathan 
1529*82527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
1530*82527734SSukumar Swaminathan 	hba->io_count = 0;
1531*82527734SSukumar Swaminathan 	hba->iodone_count = 0;
1532*82527734SSukumar Swaminathan 	hba->topology = 0;
1533*82527734SSukumar Swaminathan 	hba->linkspeed = 0;
1534*82527734SSukumar Swaminathan 	hba->heartbeat_active = 0;
1535*82527734SSukumar Swaminathan 	hba->discovery_timer = 0;
1536*82527734SSukumar Swaminathan 	hba->linkup_timer = 0;
1537*82527734SSukumar Swaminathan 	hba->loopback_tics = 0;
1538*82527734SSukumar Swaminathan 
1539*82527734SSukumar Swaminathan 	/* Reset the port objects */
1540*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
1541*82527734SSukumar Swaminathan 		vport = &VPORT(i);
1542*82527734SSukumar Swaminathan 
1543*82527734SSukumar Swaminathan 		vport->flag &= EMLXS_PORT_RESET_MASK;
1544*82527734SSukumar Swaminathan 		vport->did = 0;
1545*82527734SSukumar Swaminathan 		vport->prev_did = 0;
1546*82527734SSukumar Swaminathan 		vport->lip_type = 0;
1547*82527734SSukumar Swaminathan 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
1548*82527734SSukumar Swaminathan 
1549*82527734SSukumar Swaminathan 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
1550*82527734SSukumar Swaminathan 		vport->node_base.nlp_Rpi = 0;
1551*82527734SSukumar Swaminathan 		vport->node_base.nlp_DID = 0xffffff;
1552*82527734SSukumar Swaminathan 		vport->node_base.nlp_list_next = NULL;
1553*82527734SSukumar Swaminathan 		vport->node_base.nlp_list_prev = NULL;
1554*82527734SSukumar Swaminathan 		vport->node_base.nlp_active = 1;
1555*82527734SSukumar Swaminathan 		vport->node_count = 0;
1556*82527734SSukumar Swaminathan 
1557*82527734SSukumar Swaminathan 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
1558*82527734SSukumar Swaminathan 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
1559*82527734SSukumar Swaminathan 		}
1560*82527734SSukumar Swaminathan 	}
1561*82527734SSukumar Swaminathan 
1562*82527734SSukumar Swaminathan 	if (emlxs_check_hdw_ready(hba)) {
1563*82527734SSukumar Swaminathan 		return (1);
1564*82527734SSukumar Swaminathan 	}
1565*82527734SSukumar Swaminathan 
1566*82527734SSukumar Swaminathan 	return (0);
1567*82527734SSukumar Swaminathan 
1568*82527734SSukumar Swaminathan } /* emlxs_sli4_hba_reset */
1569*82527734SSukumar Swaminathan 
1570*82527734SSukumar Swaminathan 
1571*82527734SSukumar Swaminathan #define	SGL_CMD		0
1572*82527734SSukumar Swaminathan #define	SGL_RESP	1
1573*82527734SSukumar Swaminathan #define	SGL_DATA	2
1574*82527734SSukumar Swaminathan #define	SGL_LAST	0x80
1575*82527734SSukumar Swaminathan 
1576*82527734SSukumar Swaminathan /*ARGSUSED*/
1577*82527734SSukumar Swaminathan ULP_SGE64 *
1578*82527734SSukumar Swaminathan emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt,
1579*82527734SSukumar Swaminathan     uint32_t sgl_type, uint32_t *pcnt)
1580*82527734SSukumar Swaminathan {
1581*82527734SSukumar Swaminathan #ifdef DEBUG_SGE
1582*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
1583*82527734SSukumar Swaminathan #endif
1584*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp;
1585*82527734SSukumar Swaminathan 	uint_t i;
1586*82527734SSukumar Swaminathan 	uint_t last;
1587*82527734SSukumar Swaminathan 	int32_t	size;
1588*82527734SSukumar Swaminathan 	int32_t	sge_size;
1589*82527734SSukumar Swaminathan 	uint64_t sge_addr;
1590*82527734SSukumar Swaminathan 	int32_t	len;
1591*82527734SSukumar Swaminathan 	uint32_t cnt;
1592*82527734SSukumar Swaminathan 	uint_t cookie_cnt;
1593*82527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
1594*82527734SSukumar Swaminathan 
1595*82527734SSukumar Swaminathan 	last = sgl_type & SGL_LAST;
1596*82527734SSukumar Swaminathan 	sgl_type &= ~SGL_LAST;
1597*82527734SSukumar Swaminathan 
1598*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
1599*82527734SSukumar Swaminathan 	switch (sgl_type) {
1600*82527734SSukumar Swaminathan 	case SGL_CMD:
1601*82527734SSukumar Swaminathan 		cp = pkt->pkt_cmd_cookie;
1602*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
1603*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
1604*82527734SSukumar Swaminathan 		break;
1605*82527734SSukumar Swaminathan 
1606*82527734SSukumar Swaminathan 	case SGL_RESP:
1607*82527734SSukumar Swaminathan 		cp = pkt->pkt_resp_cookie;
1608*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
1609*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
1610*82527734SSukumar Swaminathan 		break;
1611*82527734SSukumar Swaminathan 
1612*82527734SSukumar Swaminathan 
1613*82527734SSukumar Swaminathan 	case SGL_DATA:
1614*82527734SSukumar Swaminathan 		cp = pkt->pkt_data_cookie;
1615*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_data_cookie_cnt;
1616*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
1617*82527734SSukumar Swaminathan 		break;
1618*82527734SSukumar Swaminathan 	}
1619*82527734SSukumar Swaminathan 
1620*82527734SSukumar Swaminathan #else
1621*82527734SSukumar Swaminathan 	switch (sgl_type) {
1622*82527734SSukumar Swaminathan 	case SGL_CMD:
1623*82527734SSukumar Swaminathan 		cp = &pkt->pkt_cmd_cookie;
1624*82527734SSukumar Swaminathan 		cookie_cnt = 1;
1625*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
1626*82527734SSukumar Swaminathan 		break;
1627*82527734SSukumar Swaminathan 
1628*82527734SSukumar Swaminathan 	case SGL_RESP:
1629*82527734SSukumar Swaminathan 		cp = &pkt->pkt_resp_cookie;
1630*82527734SSukumar Swaminathan 		cookie_cnt = 1;
1631*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
1632*82527734SSukumar Swaminathan 		break;
1633*82527734SSukumar Swaminathan 
1634*82527734SSukumar Swaminathan 
1635*82527734SSukumar Swaminathan 	case SGL_DATA:
1636*82527734SSukumar Swaminathan 		cp = &pkt->pkt_data_cookie;
1637*82527734SSukumar Swaminathan 		cookie_cnt = 1;
1638*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
1639*82527734SSukumar Swaminathan 		break;
1640*82527734SSukumar Swaminathan 	}
1641*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
1642*82527734SSukumar Swaminathan 
1643*82527734SSukumar Swaminathan 	stage_sge.offset = 0;
1644*82527734SSukumar Swaminathan 	stage_sge.reserved = 0;
1645*82527734SSukumar Swaminathan 	stage_sge.last = 0;
1646*82527734SSukumar Swaminathan 	cnt = 0;
1647*82527734SSukumar Swaminathan 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
1648*82527734SSukumar Swaminathan 
1649*82527734SSukumar Swaminathan 
1650*82527734SSukumar Swaminathan 		sge_size = cp->dmac_size;
1651*82527734SSukumar Swaminathan 		sge_addr = cp->dmac_laddress;
1652*82527734SSukumar Swaminathan 		while (sge_size && size) {
1653*82527734SSukumar Swaminathan 			if (cnt) {
1654*82527734SSukumar Swaminathan 				/* Copy staged SGE before we build next one */
1655*82527734SSukumar Swaminathan 				BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
1656*82527734SSukumar Swaminathan 				    (uint8_t *)sge, sizeof (ULP_SGE64));
1657*82527734SSukumar Swaminathan 				sge++;
1658*82527734SSukumar Swaminathan 			}
1659*82527734SSukumar Swaminathan 			len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
1660*82527734SSukumar Swaminathan 			len = MIN(size, len);
1661*82527734SSukumar Swaminathan 
1662*82527734SSukumar Swaminathan 			stage_sge.addrHigh =
1663*82527734SSukumar Swaminathan 			    PADDR_HI(sge_addr);
1664*82527734SSukumar Swaminathan 			stage_sge.addrLow =
1665*82527734SSukumar Swaminathan 			    PADDR_LO(sge_addr);
1666*82527734SSukumar Swaminathan 			stage_sge.length = len;
1667*82527734SSukumar Swaminathan 			if (sgl_type == SGL_DATA) {
1668*82527734SSukumar Swaminathan 				stage_sge.offset = cnt;
1669*82527734SSukumar Swaminathan 			}
1670*82527734SSukumar Swaminathan #ifdef DEBUG_SGE
1671*82527734SSukumar Swaminathan 			emlxs_data_dump(hba, "SGE", (uint32_t *)&stage_sge,
1672*82527734SSukumar Swaminathan 			    4, 0);
1673*82527734SSukumar Swaminathan #endif
1674*82527734SSukumar Swaminathan 			sge_addr += len;
1675*82527734SSukumar Swaminathan 			sge_size -= len;
1676*82527734SSukumar Swaminathan 
1677*82527734SSukumar Swaminathan 			cnt += len;
1678*82527734SSukumar Swaminathan 			size -= len;
1679*82527734SSukumar Swaminathan 		}
1680*82527734SSukumar Swaminathan 	}
1681*82527734SSukumar Swaminathan 
1682*82527734SSukumar Swaminathan 	if (last) {
1683*82527734SSukumar Swaminathan 		stage_sge.last = 1;
1684*82527734SSukumar Swaminathan 	}
1685*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
1686*82527734SSukumar Swaminathan 	    sizeof (ULP_SGE64));
1687*82527734SSukumar Swaminathan 	sge++;
1688*82527734SSukumar Swaminathan 
1689*82527734SSukumar Swaminathan 	*pcnt = cnt;
1690*82527734SSukumar Swaminathan 	return (sge);
1691*82527734SSukumar Swaminathan 
1692*82527734SSukumar Swaminathan } /* emlxs_pkt_to_sgl */
1693*82527734SSukumar Swaminathan 
1694*82527734SSukumar Swaminathan 
1695*82527734SSukumar Swaminathan /*ARGSUSED*/
1696*82527734SSukumar Swaminathan uint32_t
1697*82527734SSukumar Swaminathan emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
1698*82527734SSukumar Swaminathan {
1699*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
1700*82527734SSukumar Swaminathan 	XRIobj_t *xp;
1701*82527734SSukumar Swaminathan 	ULP_SGE64 *sge;
1702*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
1703*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
1704*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
1705*82527734SSukumar Swaminathan 	uint32_t cmd_cnt;
1706*82527734SSukumar Swaminathan 	uint32_t resp_cnt;
1707*82527734SSukumar Swaminathan 	uint32_t cnt;
1708*82527734SSukumar Swaminathan 
1709*82527734SSukumar Swaminathan 	iocbq = (IOCBQ *) &sbp->iocbq;
1710*82527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
1711*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
1712*82527734SSukumar Swaminathan 	xp = sbp->xp;
1713*82527734SSukumar Swaminathan 	sge = xp->SGList.virt;
1714*82527734SSukumar Swaminathan 
1715*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
1716*82527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
1717*82527734SSukumar Swaminathan #else
1718*82527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
1719*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
1720*82527734SSukumar Swaminathan 
1721*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
1722*82527734SSukumar Swaminathan 	if (iocbq->flag & IOCB_FCP_CMD) {
1723*82527734SSukumar Swaminathan 
1724*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
1725*82527734SSukumar Swaminathan 			return (1);
1726*82527734SSukumar Swaminathan 		}
1727*82527734SSukumar Swaminathan 
1728*82527734SSukumar Swaminathan 		/* CMD payload */
1729*82527734SSukumar Swaminathan 		sge = emlxs_pkt_to_sgl(port, sge, pkt, SGL_CMD, &cmd_cnt);
1730*82527734SSukumar Swaminathan 
1731*82527734SSukumar Swaminathan 		/* DATA payload */
1732*82527734SSukumar Swaminathan 		if (pkt->pkt_datalen != 0) {
1733*82527734SSukumar Swaminathan 			/* RSP payload */
1734*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1735*82527734SSukumar Swaminathan 			    SGL_RESP, &resp_cnt);
1736*82527734SSukumar Swaminathan 
1737*82527734SSukumar Swaminathan 			/* Data portion */
1738*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1739*82527734SSukumar Swaminathan 			    SGL_DATA | SGL_LAST, &cnt);
1740*82527734SSukumar Swaminathan 		} else {
1741*82527734SSukumar Swaminathan 			/* RSP payload */
1742*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1743*82527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
1744*82527734SSukumar Swaminathan 		}
1745*82527734SSukumar Swaminathan 
1746*82527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrHigh =
1747*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
1748*82527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.addrLow =
1749*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
1750*82527734SSukumar Swaminathan 		wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
1751*82527734SSukumar Swaminathan 		wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
1752*82527734SSukumar Swaminathan 
1753*82527734SSukumar Swaminathan 	} else {
1754*82527734SSukumar Swaminathan 
1755*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
1756*82527734SSukumar Swaminathan 			/* CMD payload */
1757*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1758*82527734SSukumar Swaminathan 			    SGL_CMD | SGL_LAST, &cmd_cnt);
1759*82527734SSukumar Swaminathan 		} else {
1760*82527734SSukumar Swaminathan 			/* CMD payload */
1761*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1762*82527734SSukumar Swaminathan 			    SGL_CMD, &cmd_cnt);
1763*82527734SSukumar Swaminathan 
1764*82527734SSukumar Swaminathan 			/* RSP payload */
1765*82527734SSukumar Swaminathan 			sge = emlxs_pkt_to_sgl(port, sge, pkt,
1766*82527734SSukumar Swaminathan 			    SGL_RESP | SGL_LAST, &resp_cnt);
1767*82527734SSukumar Swaminathan 			wqe->un.GenReq.PayloadLength = cmd_cnt;
1768*82527734SSukumar Swaminathan 		}
1769*82527734SSukumar Swaminathan 
1770*82527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrHigh =
1771*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
1772*82527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.addrLow =
1773*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
1774*82527734SSukumar Swaminathan 		wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
1775*82527734SSukumar Swaminathan 	}
1776*82527734SSukumar Swaminathan 	return (0);
1777*82527734SSukumar Swaminathan } /* emlxs_sli4_bde_setup */
1778*82527734SSukumar Swaminathan 
1779*82527734SSukumar Swaminathan 
1780*82527734SSukumar Swaminathan /*ARGSUSED*/
1781*82527734SSukumar Swaminathan static uint32_t
1782*82527734SSukumar Swaminathan emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
1783*82527734SSukumar Swaminathan {
1784*82527734SSukumar Swaminathan 	return (0);
1785*82527734SSukumar Swaminathan 
1786*82527734SSukumar Swaminathan } /* emlxs_sli4_fct_bde_setup */
1787*82527734SSukumar Swaminathan 
1788*82527734SSukumar Swaminathan 
1789*82527734SSukumar Swaminathan static void
1790*82527734SSukumar Swaminathan emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
1791*82527734SSukumar Swaminathan {
1792*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1793*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
1794*82527734SSukumar Swaminathan 	uint32_t channelno;
1795*82527734SSukumar Swaminathan 	int32_t throttle;
1796*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
1797*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqeslot;
1798*82527734SSukumar Swaminathan 	WQ_DESC_t *wq;
1799*82527734SSukumar Swaminathan 	uint32_t flag;
1800*82527734SSukumar Swaminathan 	uint32_t wqdb;
1801*82527734SSukumar Swaminathan 	uint32_t next_wqe;
1802*82527734SSukumar Swaminathan 
1803*82527734SSukumar Swaminathan 
1804*82527734SSukumar Swaminathan 	channelno = cp->channelno;
1805*82527734SSukumar Swaminathan 	wq = (WQ_DESC_t *)cp->iopath;
1806*82527734SSukumar Swaminathan 
1807*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
1808*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1809*82527734SSukumar Swaminathan 	    "ISSUE WQE channel: %x  %p", channelno, wq);
1810*82527734SSukumar Swaminathan #endif
1811*82527734SSukumar Swaminathan 
1812*82527734SSukumar Swaminathan 	throttle = 0;
1813*82527734SSukumar Swaminathan 
1814*82527734SSukumar Swaminathan 	/* Check if FCP ring and adapter is not ready */
1815*82527734SSukumar Swaminathan 	/* We may use any ring for FCP_CMD */
1816*82527734SSukumar Swaminathan 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
1817*82527734SSukumar Swaminathan 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
1818*82527734SSukumar Swaminathan 		    !(((emlxs_port_t *)iocbq->port)->tgt_mode)) {
1819*82527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
1820*82527734SSukumar Swaminathan 			return;
1821*82527734SSukumar Swaminathan 		}
1822*82527734SSukumar Swaminathan 	}
1823*82527734SSukumar Swaminathan 
1824*82527734SSukumar Swaminathan 	/* Attempt to acquire CMD_RING lock */
1825*82527734SSukumar Swaminathan 	if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) {
1826*82527734SSukumar Swaminathan 		/* Queue it for later */
1827*82527734SSukumar Swaminathan 		if (iocbq) {
1828*82527734SSukumar Swaminathan 			if ((hba->io_count -
1829*82527734SSukumar Swaminathan 			    hba->channel_tx_count) > 10) {
1830*82527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
1831*82527734SSukumar Swaminathan 				return;
1832*82527734SSukumar Swaminathan 			} else {
1833*82527734SSukumar Swaminathan 
1834*82527734SSukumar Swaminathan 				mutex_enter(&EMLXS_CMD_RING_LOCK(channelno));
1835*82527734SSukumar Swaminathan 			}
1836*82527734SSukumar Swaminathan 		} else {
1837*82527734SSukumar Swaminathan 			return;
1838*82527734SSukumar Swaminathan 		}
1839*82527734SSukumar Swaminathan 	}
1840*82527734SSukumar Swaminathan 	/* CMD_RING_LOCK acquired */
1841*82527734SSukumar Swaminathan 
1842*82527734SSukumar Swaminathan 	/* Throttle check only applies to non special iocb */
1843*82527734SSukumar Swaminathan 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
1844*82527734SSukumar Swaminathan 		/* Check if HBA is full */
1845*82527734SSukumar Swaminathan 		throttle = hba->io_throttle - hba->io_active;
1846*82527734SSukumar Swaminathan 		if (throttle <= 0) {
1847*82527734SSukumar Swaminathan 			/* Hitting adapter throttle limit */
1848*82527734SSukumar Swaminathan 			/* Queue it for later */
1849*82527734SSukumar Swaminathan 			if (iocbq) {
1850*82527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
1851*82527734SSukumar Swaminathan 			}
1852*82527734SSukumar Swaminathan 
1853*82527734SSukumar Swaminathan 			goto busy;
1854*82527734SSukumar Swaminathan 		}
1855*82527734SSukumar Swaminathan 	}
1856*82527734SSukumar Swaminathan 
1857*82527734SSukumar Swaminathan 	/* Check to see if we have room for this WQE */
1858*82527734SSukumar Swaminathan 	next_wqe = wq->host_index + 1;
1859*82527734SSukumar Swaminathan 	if (next_wqe >= wq->max_index) {
1860*82527734SSukumar Swaminathan 		next_wqe = 0;
1861*82527734SSukumar Swaminathan 	}
1862*82527734SSukumar Swaminathan 
1863*82527734SSukumar Swaminathan 	if (next_wqe == wq->port_index) {
1864*82527734SSukumar Swaminathan 		/* Queue it for later */
1865*82527734SSukumar Swaminathan 		if (iocbq) {
1866*82527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
1867*82527734SSukumar Swaminathan 		}
1868*82527734SSukumar Swaminathan 		goto busy;
1869*82527734SSukumar Swaminathan 	}
1870*82527734SSukumar Swaminathan 
1871*82527734SSukumar Swaminathan 	/*
1872*82527734SSukumar Swaminathan 	 * We have a command ring slot available
1873*82527734SSukumar Swaminathan 	 * Make sure we have an iocb to send
1874*82527734SSukumar Swaminathan 	 */
1875*82527734SSukumar Swaminathan 	if (iocbq) {
1876*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
1877*82527734SSukumar Swaminathan 
1878*82527734SSukumar Swaminathan 		/* Check if the ring already has iocb's waiting */
1879*82527734SSukumar Swaminathan 		if (cp->nodeq.q_first != NULL) {
1880*82527734SSukumar Swaminathan 			/* Put the current iocbq on the tx queue */
1881*82527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 0);
1882*82527734SSukumar Swaminathan 
1883*82527734SSukumar Swaminathan 			/*
1884*82527734SSukumar Swaminathan 			 * Attempt to replace it with the next iocbq
1885*82527734SSukumar Swaminathan 			 * in the tx queue
1886*82527734SSukumar Swaminathan 			 */
1887*82527734SSukumar Swaminathan 			iocbq = emlxs_tx_get(cp, 0);
1888*82527734SSukumar Swaminathan 		}
1889*82527734SSukumar Swaminathan 
1890*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
1891*82527734SSukumar Swaminathan 	} else {
1892*82527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
1893*82527734SSukumar Swaminathan 	}
1894*82527734SSukumar Swaminathan 
1895*82527734SSukumar Swaminathan sendit:
1896*82527734SSukumar Swaminathan 	/* Process each iocbq */
1897*82527734SSukumar Swaminathan 	while (iocbq) {
1898*82527734SSukumar Swaminathan 
1899*82527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
1900*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
1901*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1902*82527734SSukumar Swaminathan 		    "ISSUE QID %d WQE iotag: %x xri: %x", wq->qid,
1903*82527734SSukumar Swaminathan 		    wqe->RequestTag, wqe->XRITag);
1904*82527734SSukumar Swaminathan #endif
1905*82527734SSukumar Swaminathan 
1906*82527734SSukumar Swaminathan 		sbp = iocbq->sbp;
1907*82527734SSukumar Swaminathan 		if (sbp) {
1908*82527734SSukumar Swaminathan 			/* If exchange removed after wqe was prep'ed, drop it */
1909*82527734SSukumar Swaminathan 			if (!(sbp->xp)) {
1910*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
1911*82527734SSukumar Swaminathan 				    "Xmit WQE iotag: %x xri: %x aborted",
1912*82527734SSukumar Swaminathan 				    wqe->RequestTag, wqe->XRITag);
1913*82527734SSukumar Swaminathan 
1914*82527734SSukumar Swaminathan 				/* Get next iocb from the tx queue */
1915*82527734SSukumar Swaminathan 				iocbq = emlxs_tx_get(cp, 1);
1916*82527734SSukumar Swaminathan 				continue;
1917*82527734SSukumar Swaminathan 			}
1918*82527734SSukumar Swaminathan 
1919*82527734SSukumar Swaminathan 			if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
1920*82527734SSukumar Swaminathan 
1921*82527734SSukumar Swaminathan 				/* Perform delay */
1922*82527734SSukumar Swaminathan 				if ((channelno == hba->channel_els) &&
1923*82527734SSukumar Swaminathan 				    !(iocbq->flag & IOCB_FCP_CMD)) {
1924*82527734SSukumar Swaminathan 					drv_usecwait(100000);
1925*82527734SSukumar Swaminathan 				} else {
1926*82527734SSukumar Swaminathan 					drv_usecwait(20000);
1927*82527734SSukumar Swaminathan 				}
1928*82527734SSukumar Swaminathan 			}
1929*82527734SSukumar Swaminathan 		}
1930*82527734SSukumar Swaminathan 
1931*82527734SSukumar Swaminathan 		/*
1932*82527734SSukumar Swaminathan 		 * At this point, we have a command ring slot available
1933*82527734SSukumar Swaminathan 		 * and an iocb to send
1934*82527734SSukumar Swaminathan 		 */
1935*82527734SSukumar Swaminathan 		wq->release_depth--;
1936*82527734SSukumar Swaminathan 		if (wq->release_depth == 0) {
1937*82527734SSukumar Swaminathan 			wq->release_depth = WQE_RELEASE_DEPTH;
1938*82527734SSukumar Swaminathan 			wqe->WQEC = 1;
1939*82527734SSukumar Swaminathan 		}
1940*82527734SSukumar Swaminathan 
1941*82527734SSukumar Swaminathan 
1942*82527734SSukumar Swaminathan 		HBASTATS.IocbIssued[channelno]++;
1943*82527734SSukumar Swaminathan 
1944*82527734SSukumar Swaminathan 		/* Check for ULP pkt request */
1945*82527734SSukumar Swaminathan 		if (sbp) {
1946*82527734SSukumar Swaminathan 			mutex_enter(&sbp->mtx);
1947*82527734SSukumar Swaminathan 
1948*82527734SSukumar Swaminathan 			if (sbp->node == NULL) {
1949*82527734SSukumar Swaminathan 				/* Set node to base node by default */
1950*82527734SSukumar Swaminathan 				iocbq->node = (void *)&port->node_base;
1951*82527734SSukumar Swaminathan 				sbp->node = (void *)&port->node_base;
1952*82527734SSukumar Swaminathan 			}
1953*82527734SSukumar Swaminathan 
1954*82527734SSukumar Swaminathan 			sbp->pkt_flags |= PACKET_IN_CHIPQ;
1955*82527734SSukumar Swaminathan 			mutex_exit(&sbp->mtx);
1956*82527734SSukumar Swaminathan 
1957*82527734SSukumar Swaminathan 			atomic_add_32(&hba->io_active, 1);
1958*82527734SSukumar Swaminathan 			sbp->xp->state |= RESOURCE_XRI_PENDING_IO;
1959*82527734SSukumar Swaminathan 		}
1960*82527734SSukumar Swaminathan 
1961*82527734SSukumar Swaminathan 
1962*82527734SSukumar Swaminathan 		/* Free the local iocb if there is no sbp tracking it */
1963*82527734SSukumar Swaminathan 		if (sbp) {
1964*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
1965*82527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
1966*82527734SSukumar Swaminathan 			if (sbp->fct_cmd) {
1967*82527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
1968*82527734SSukumar Swaminathan 				    EMLXS_FCT_IOCB_ISSUED);
1969*82527734SSukumar Swaminathan 				emlxs_fct_io_trace(port, sbp->fct_cmd,
1970*82527734SSukumar Swaminathan 				    icmd->ULPCOMMAND);
1971*82527734SSukumar Swaminathan 			}
1972*82527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
1973*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
1974*82527734SSukumar Swaminathan 			cp->hbaSendCmd_sbp++;
1975*82527734SSukumar Swaminathan 			iocbq->channel = cp;
1976*82527734SSukumar Swaminathan 		} else {
1977*82527734SSukumar Swaminathan 			cp->hbaSendCmd++;
1978*82527734SSukumar Swaminathan 		}
1979*82527734SSukumar Swaminathan 
1980*82527734SSukumar Swaminathan 		flag = iocbq->flag;
1981*82527734SSukumar Swaminathan 
1982*82527734SSukumar Swaminathan 		/* Send the iocb */
1983*82527734SSukumar Swaminathan 		wqeslot = (emlxs_wqe_t *)wq->addr.virt;
1984*82527734SSukumar Swaminathan 		wqeslot += wq->host_index;
1985*82527734SSukumar Swaminathan 
1986*82527734SSukumar Swaminathan 		wqe->CQId = wq->cqid;
1987*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
1988*82527734SSukumar Swaminathan 		    sizeof (emlxs_wqe_t));
1989*82527734SSukumar Swaminathan #ifdef DEBUG_WQE
1990*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "WQE", (uint32_t *)wqe, 18, 0);
1991*82527734SSukumar Swaminathan #endif
1992*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(wq->addr.dma_handle, 0,
1993*82527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
1994*82527734SSukumar Swaminathan 
1995*82527734SSukumar Swaminathan 		/* Ring the WQ Doorbell */
1996*82527734SSukumar Swaminathan 		wqdb = wq->qid;
1997*82527734SSukumar Swaminathan 		wqdb |= ((1 << 24) | (wq->host_index << 16));
1998*82527734SSukumar Swaminathan 
1999*82527734SSukumar Swaminathan 
2000*82527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_WQDB_REG(hba), wqdb);
2001*82527734SSukumar Swaminathan 		wq->host_index = next_wqe;
2002*82527734SSukumar Swaminathan 
2003*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
2004*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2005*82527734SSukumar Swaminathan 		    "WQ RING: %08x", wqdb);
2006*82527734SSukumar Swaminathan #endif
2007*82527734SSukumar Swaminathan 
2008*82527734SSukumar Swaminathan 		/*
2009*82527734SSukumar Swaminathan 		 * After this, the sbp / iocb / wqe should not be
2010*82527734SSukumar Swaminathan 		 * accessed in the xmit path.
2011*82527734SSukumar Swaminathan 		 */
2012*82527734SSukumar Swaminathan 
2013*82527734SSukumar Swaminathan 		if (!sbp) {
2014*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq);
2015*82527734SSukumar Swaminathan 		}
2016*82527734SSukumar Swaminathan 
2017*82527734SSukumar Swaminathan 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
2018*82527734SSukumar Swaminathan 			/* Check if HBA is full */
2019*82527734SSukumar Swaminathan 			throttle = hba->io_throttle - hba->io_active;
2020*82527734SSukumar Swaminathan 			if (throttle <= 0) {
2021*82527734SSukumar Swaminathan 				goto busy;
2022*82527734SSukumar Swaminathan 			}
2023*82527734SSukumar Swaminathan 		}
2024*82527734SSukumar Swaminathan 
2025*82527734SSukumar Swaminathan 		/* Check to see if we have room for another WQE */
2026*82527734SSukumar Swaminathan 		next_wqe++;
2027*82527734SSukumar Swaminathan 		if (next_wqe >= wq->max_index) {
2028*82527734SSukumar Swaminathan 			next_wqe = 0;
2029*82527734SSukumar Swaminathan 		}
2030*82527734SSukumar Swaminathan 
2031*82527734SSukumar Swaminathan 		if (next_wqe == wq->port_index) {
2032*82527734SSukumar Swaminathan 			/* Queue it for later */
2033*82527734SSukumar Swaminathan 			goto busy;
2034*82527734SSukumar Swaminathan 		}
2035*82527734SSukumar Swaminathan 
2036*82527734SSukumar Swaminathan 
2037*82527734SSukumar Swaminathan 		/* Get the next iocb from the tx queue if there is one */
2038*82527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
2039*82527734SSukumar Swaminathan 	}
2040*82527734SSukumar Swaminathan 
2041*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
2042*82527734SSukumar Swaminathan 
2043*82527734SSukumar Swaminathan 	return;
2044*82527734SSukumar Swaminathan 
2045*82527734SSukumar Swaminathan busy:
2046*82527734SSukumar Swaminathan 	if (throttle <= 0) {
2047*82527734SSukumar Swaminathan 		HBASTATS.IocbThrottled++;
2048*82527734SSukumar Swaminathan 	} else {
2049*82527734SSukumar Swaminathan 		HBASTATS.IocbRingFull[channelno]++;
2050*82527734SSukumar Swaminathan 	}
2051*82527734SSukumar Swaminathan 
2052*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
2053*82527734SSukumar Swaminathan 
2054*82527734SSukumar Swaminathan 	return;
2055*82527734SSukumar Swaminathan 
2056*82527734SSukumar Swaminathan } /* emlxs_sli4_issue_iocb_cmd() */
2057*82527734SSukumar Swaminathan 
2058*82527734SSukumar Swaminathan 
2059*82527734SSukumar Swaminathan /*ARGSUSED*/
2060*82527734SSukumar Swaminathan static uint32_t
2061*82527734SSukumar Swaminathan emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo)
2062*82527734SSukumar Swaminathan {
2063*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
2064*82527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
2065*82527734SSukumar Swaminathan 	MAILBOX4	*mb4;
2066*82527734SSukumar Swaminathan 	MATCHMAP	*mp;
2067*82527734SSukumar Swaminathan 	uint32_t	*iptr;
2068*82527734SSukumar Swaminathan 	uint32_t	mqdb;
2069*82527734SSukumar Swaminathan 
2070*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
2071*82527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
2072*82527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
2073*82527734SSukumar Swaminathan 	hba->mbox_mqe = (uint32_t *)mqe;
2074*82527734SSukumar Swaminathan 
2075*82527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2076*82527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
2077*82527734SSukumar Swaminathan 		/*
2078*82527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
2079*82527734SSukumar Swaminathan 		 * into the mailbox area.
2080*82527734SSukumar Swaminathan 		 */
2081*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
2082*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2083*82527734SSukumar Swaminathan 
2084*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
2085*82527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
2086*82527734SSukumar Swaminathan 
2087*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX CMD", (uint32_t *)mqe, 18, 0);
2088*82527734SSukumar Swaminathan 	} else {
2089*82527734SSukumar Swaminathan 		/* SLI_CONFIG and non-embedded */
2090*82527734SSukumar Swaminathan 
2091*82527734SSukumar Swaminathan 		/*
2092*82527734SSukumar Swaminathan 		 * If this is not embedded, the MQ area
2093*82527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
2094*82527734SSukumar Swaminathan 		 * non-embedded mailbox command.
2095*82527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
2096*82527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
2097*82527734SSukumar Swaminathan 		 */
2098*82527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
2099*82527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
2100*82527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
2101*82527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
2102*82527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
2103*82527734SSukumar Swaminathan 		*iptr = mp->size;
2104*82527734SSukumar Swaminathan 
2105*82527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2106*82527734SSukumar Swaminathan 
2107*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2108*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
2109*82527734SSukumar Swaminathan 
2110*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
2111*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2112*82527734SSukumar Swaminathan 
2113*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
2114*82527734SSukumar Swaminathan 		    4096, DDI_DMA_SYNC_FORDEV);
2115*82527734SSukumar Swaminathan 
2116*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX EXT", (uint32_t *)mqe, 12, 0);
2117*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2118*82527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
2119*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
2120*82527734SSukumar Swaminathan 	}
2121*82527734SSukumar Swaminathan 
2122*82527734SSukumar Swaminathan 	/* Ring the MQ Doorbell */
2123*82527734SSukumar Swaminathan 	mqdb = hba->sli.sli4.mq.qid;
2124*82527734SSukumar Swaminathan 	mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
2125*82527734SSukumar Swaminathan 
2126*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2127*82527734SSukumar Swaminathan 	    "MQ RING: %08x", mqdb);
2128*82527734SSukumar Swaminathan 
2129*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_MQDB_REG(hba), mqdb);
2130*82527734SSukumar Swaminathan 	return (MBX_SUCCESS);
2131*82527734SSukumar Swaminathan 
2132*82527734SSukumar Swaminathan } /* emlxs_sli4_issue_mq() */
2133*82527734SSukumar Swaminathan 
2134*82527734SSukumar Swaminathan 
2135*82527734SSukumar Swaminathan /*ARGSUSED*/
2136*82527734SSukumar Swaminathan static uint32_t
2137*82527734SSukumar Swaminathan emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
2138*82527734SSukumar Swaminathan {
2139*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
2140*82527734SSukumar Swaminathan 	MAILBOXQ	*mbq;
2141*82527734SSukumar Swaminathan 	MAILBOX4	*mb4;
2142*82527734SSukumar Swaminathan 	MATCHMAP	*mp;
2143*82527734SSukumar Swaminathan 	uint32_t	*iptr;
2144*82527734SSukumar Swaminathan 
2145*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)mb;
2146*82527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mb;
2147*82527734SSukumar Swaminathan 	mp = (MATCHMAP *) mbq->nonembed;
2148*82527734SSukumar Swaminathan 	hba->mbox_mqe = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2149*82527734SSukumar Swaminathan 
2150*82527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2151*82527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
2152*82527734SSukumar Swaminathan 		/*
2153*82527734SSukumar Swaminathan 		 * If this is an embedded mbox, everything should fit
2154*82527734SSukumar Swaminathan 		 * into the bootstrap mailbox area.
2155*82527734SSukumar Swaminathan 		 */
2156*82527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2157*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
2158*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2159*82527734SSukumar Swaminathan 
2160*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2161*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
2162*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX CMD", iptr, 18, 0);
2163*82527734SSukumar Swaminathan 	} else {
2164*82527734SSukumar Swaminathan 		/*
2165*82527734SSukumar Swaminathan 		 * If this is not embedded, the bootstrap mailbox area
2166*82527734SSukumar Swaminathan 		 * MUST contain a SGE pointer to a larger area for the
2167*82527734SSukumar Swaminathan 		 * non-embedded mailbox command.
2168*82527734SSukumar Swaminathan 		 * mp will point to the actual mailbox command which
2169*82527734SSukumar Swaminathan 		 * should be copied into the non-embedded area.
2170*82527734SSukumar Swaminathan 		 */
2171*82527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.sge_cnt = 1;
2172*82527734SSukumar Swaminathan 		mb4->un.varSLIConfig.be.payload_length = mp->size;
2173*82527734SSukumar Swaminathan 		iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
2174*82527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_LO(mp->phys);
2175*82527734SSukumar Swaminathan 		*iptr++ = (uint32_t)PADDR_HI(mp->phys);
2176*82527734SSukumar Swaminathan 		*iptr = mp->size;
2177*82527734SSukumar Swaminathan 
2178*82527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2179*82527734SSukumar Swaminathan 
2180*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2181*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
2182*82527734SSukumar Swaminathan 
2183*82527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2184*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
2185*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2186*82527734SSukumar Swaminathan 
2187*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2188*82527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
2189*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORDEV);
2190*82527734SSukumar Swaminathan 
2191*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX EXT", iptr, 12, 0);
2192*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2193*82527734SSukumar Swaminathan 		    "Extension Addr %p %p", mp->phys,
2194*82527734SSukumar Swaminathan 		    (uint32_t *)((uint8_t *)mp->virt));
2195*82527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2196*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
2197*82527734SSukumar Swaminathan 	}
2198*82527734SSukumar Swaminathan 
2199*82527734SSukumar Swaminathan 
2200*82527734SSukumar Swaminathan 	/* NOTE: tmo is in 10ms ticks */
2201*82527734SSukumar Swaminathan 	if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
2202*82527734SSukumar Swaminathan 		return (MBX_TIMEOUT);
2203*82527734SSukumar Swaminathan 	}
2204*82527734SSukumar Swaminathan 
2205*82527734SSukumar Swaminathan 	if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
2206*82527734SSukumar Swaminathan 	    (mb4->un.varSLIConfig.be.embedded)) {
2207*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2208*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
2209*82527734SSukumar Swaminathan 
2210*82527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2211*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
2212*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2213*82527734SSukumar Swaminathan 
2214*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX CMPL", iptr, 18, 0);
2215*82527734SSukumar Swaminathan 
2216*82527734SSukumar Swaminathan 	} else {
2217*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2218*82527734SSukumar Swaminathan 		    EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
2219*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
2220*82527734SSukumar Swaminathan 
2221*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2222*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
2223*82527734SSukumar Swaminathan 
2224*82527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(mp->virt, mp->size);
2225*82527734SSukumar Swaminathan 
2226*82527734SSukumar Swaminathan 		iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2227*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
2228*82527734SSukumar Swaminathan 		    MAILBOX_CMD_SLI4_BSIZE);
2229*82527734SSukumar Swaminathan 
2230*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "MBOX CMPL", iptr, 12, 0);
2231*82527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mp->virt);
2232*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0);
2233*82527734SSukumar Swaminathan 	}
2234*82527734SSukumar Swaminathan 
2235*82527734SSukumar Swaminathan 	return (MBX_SUCCESS);
2236*82527734SSukumar Swaminathan 
2237*82527734SSukumar Swaminathan } /* emlxs_sli4_issue_bootstrap() */
2238*82527734SSukumar Swaminathan 
2239*82527734SSukumar Swaminathan 
2240*82527734SSukumar Swaminathan /*ARGSUSED*/
2241*82527734SSukumar Swaminathan static uint32_t
2242*82527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
2243*82527734SSukumar Swaminathan     uint32_t tmo)
2244*82527734SSukumar Swaminathan {
2245*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
2246*82527734SSukumar Swaminathan 	MAILBOX4	*mb4;
2247*82527734SSukumar Swaminathan 	MAILBOX		*mb;
2248*82527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
2249*82527734SSukumar Swaminathan 	MATCHMAP	*mp;
2250*82527734SSukumar Swaminathan 	uint32_t	*iptr;
2251*82527734SSukumar Swaminathan 	uint32_t	rc;
2252*82527734SSukumar Swaminathan 	uint32_t	i;
2253*82527734SSukumar Swaminathan 	uint32_t	tmo_local;
2254*82527734SSukumar Swaminathan 
2255*82527734SSukumar Swaminathan 	mb4 = (MAILBOX4 *)mbq;
2256*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
2257*82527734SSukumar Swaminathan 
2258*82527734SSukumar Swaminathan 
2259*82527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
2260*82527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
2261*82527734SSukumar Swaminathan 
2262*82527734SSukumar Swaminathan 	/* Check for minimum timeouts */
2263*82527734SSukumar Swaminathan 	switch (mb->mbxCommand) {
2264*82527734SSukumar Swaminathan 	/* Mailbox commands that erase/write flash */
2265*82527734SSukumar Swaminathan 	case MBX_DOWN_LOAD:
2266*82527734SSukumar Swaminathan 	case MBX_UPDATE_CFG:
2267*82527734SSukumar Swaminathan 	case MBX_LOAD_AREA:
2268*82527734SSukumar Swaminathan 	case MBX_LOAD_EXP_ROM:
2269*82527734SSukumar Swaminathan 	case MBX_WRITE_NV:
2270*82527734SSukumar Swaminathan 	case MBX_FLASH_WR_ULA:
2271*82527734SSukumar Swaminathan 	case MBX_DEL_LD_ENTRY:
2272*82527734SSukumar Swaminathan 	case MBX_LOAD_SM:
2273*82527734SSukumar Swaminathan 		if (tmo < 300) {
2274*82527734SSukumar Swaminathan 			tmo = 300;
2275*82527734SSukumar Swaminathan 		}
2276*82527734SSukumar Swaminathan 		break;
2277*82527734SSukumar Swaminathan 
2278*82527734SSukumar Swaminathan 	default:
2279*82527734SSukumar Swaminathan 		if (tmo < 30) {
2280*82527734SSukumar Swaminathan 			tmo = 30;
2281*82527734SSukumar Swaminathan 		}
2282*82527734SSukumar Swaminathan 		break;
2283*82527734SSukumar Swaminathan 	}
2284*82527734SSukumar Swaminathan 
2285*82527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
2286*82527734SSukumar Swaminathan 	tmo_local = tmo * 100;
2287*82527734SSukumar Swaminathan 
2288*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
2289*82527734SSukumar Swaminathan 
2290*82527734SSukumar Swaminathan 	/* Adjust wait flag */
2291*82527734SSukumar Swaminathan 	if (flag != MBX_NOWAIT) {
2292*82527734SSukumar Swaminathan 		if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
2293*82527734SSukumar Swaminathan 			flag = MBX_SLEEP;
2294*82527734SSukumar Swaminathan 		} else {
2295*82527734SSukumar Swaminathan 			flag = MBX_POLL;
2296*82527734SSukumar Swaminathan 		}
2297*82527734SSukumar Swaminathan 	} else {
2298*82527734SSukumar Swaminathan 		/* Must have interrupts enabled to perform MBX_NOWAIT */
2299*82527734SSukumar Swaminathan 		if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
2300*82527734SSukumar Swaminathan 
2301*82527734SSukumar Swaminathan 			mb->mbxStatus = MBX_HARDWARE_ERROR;
2302*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
2303*82527734SSukumar Swaminathan 
2304*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2305*82527734SSukumar Swaminathan 			    "Mailbox Queue missing %s failed",
2306*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
2307*82527734SSukumar Swaminathan 
2308*82527734SSukumar Swaminathan 			return (MBX_HARDWARE_ERROR);
2309*82527734SSukumar Swaminathan 		}
2310*82527734SSukumar Swaminathan 	}
2311*82527734SSukumar Swaminathan 
2312*82527734SSukumar Swaminathan 	/* Check for hardware error */
2313*82527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
2314*82527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
2315*82527734SSukumar Swaminathan 
2316*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
2317*82527734SSukumar Swaminathan 
2318*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2319*82527734SSukumar Swaminathan 		    "Hardware error reported. %s failed. status=%x mb=%p",
2320*82527734SSukumar Swaminathan 		    emlxs_mb_cmd_xlate(mb->mbxCommand),  mb->mbxStatus, mb);
2321*82527734SSukumar Swaminathan 
2322*82527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
2323*82527734SSukumar Swaminathan 	}
2324*82527734SSukumar Swaminathan 
2325*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
2326*82527734SSukumar Swaminathan 		/* If we are not polling, then queue it for later */
2327*82527734SSukumar Swaminathan 		if (flag == MBX_NOWAIT) {
2328*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2329*82527734SSukumar Swaminathan 			    "Busy.      %s: mb=%p NoWait.",
2330*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2331*82527734SSukumar Swaminathan 
2332*82527734SSukumar Swaminathan 			emlxs_mb_put(hba, mbq);
2333*82527734SSukumar Swaminathan 
2334*82527734SSukumar Swaminathan 			HBASTATS.MboxBusy++;
2335*82527734SSukumar Swaminathan 
2336*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
2337*82527734SSukumar Swaminathan 
2338*82527734SSukumar Swaminathan 			return (MBX_BUSY);
2339*82527734SSukumar Swaminathan 		}
2340*82527734SSukumar Swaminathan 
2341*82527734SSukumar Swaminathan 		while (hba->mbox_queue_flag) {
2342*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
2343*82527734SSukumar Swaminathan 
2344*82527734SSukumar Swaminathan 			if (tmo_local-- == 0) {
2345*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2346*82527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
2347*82527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
2348*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2349*82527734SSukumar Swaminathan 				    tmo);
2350*82527734SSukumar Swaminathan 
2351*82527734SSukumar Swaminathan 				/* Non-lethalStatus mailbox timeout */
2352*82527734SSukumar Swaminathan 				/* Does not indicate a hardware error */
2353*82527734SSukumar Swaminathan 				mb->mbxStatus = MBX_TIMEOUT;
2354*82527734SSukumar Swaminathan 				return (MBX_TIMEOUT);
2355*82527734SSukumar Swaminathan 			}
2356*82527734SSukumar Swaminathan 
2357*82527734SSukumar Swaminathan 			DELAYMS(10);
2358*82527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
2359*82527734SSukumar Swaminathan 		}
2360*82527734SSukumar Swaminathan 	}
2361*82527734SSukumar Swaminathan 
2362*82527734SSukumar Swaminathan 	/* Initialize mailbox area */
2363*82527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
2364*82527734SSukumar Swaminathan 
2365*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
2366*82527734SSukumar Swaminathan 	switch (flag) {
2367*82527734SSukumar Swaminathan 
2368*82527734SSukumar Swaminathan 	case MBX_NOWAIT:
2369*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_HEARTBEAT) {
2370*82527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
2371*82527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2372*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2373*82527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
2374*82527734SSukumar Swaminathan 				    "Sending.   %s: mb=%p NoWait. embedded %d",
2375*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2376*82527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2377*82527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
2378*82527734SSukumar Swaminathan 			}
2379*82527734SSukumar Swaminathan 		}
2380*82527734SSukumar Swaminathan 
2381*82527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
2382*82527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
2383*82527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
2384*82527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
2385*82527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
2386*82527734SSukumar Swaminathan 		}
2387*82527734SSukumar Swaminathan 
2388*82527734SSukumar Swaminathan 		if (mbq->bp) {
2389*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2390*82527734SSukumar Swaminathan 			    "BDE virt %p phys %p size x%x",
2391*82527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->virt,
2392*82527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->phys,
2393*82527734SSukumar Swaminathan 			    ((MATCHMAP *)mbq->bp)->size);
2394*82527734SSukumar Swaminathan 			emlxs_data_dump(hba, "DATA",
2395*82527734SSukumar Swaminathan 			    (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
2396*82527734SSukumar Swaminathan 		}
2397*82527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_mq(hba, (MAILBOX4 *)iptr, mb, tmo_local);
2398*82527734SSukumar Swaminathan 		break;
2399*82527734SSukumar Swaminathan 
2400*82527734SSukumar Swaminathan 	case MBX_POLL:
2401*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
2402*82527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2403*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2404*82527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Poll. embedded %d",
2405*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2406*82527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2407*82527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
2408*82527734SSukumar Swaminathan 		}
2409*82527734SSukumar Swaminathan 
2410*82527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
2411*82527734SSukumar Swaminathan 
2412*82527734SSukumar Swaminathan 		/* Clean up the mailbox area */
2413*82527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
2414*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2415*82527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
2416*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
2417*82527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2418*82527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
2419*82527734SSukumar Swaminathan 
2420*82527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
2421*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
2422*82527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
2423*82527734SSukumar Swaminathan 
2424*82527734SSukumar Swaminathan 		} else {
2425*82527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
2426*82527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2427*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2428*82527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
2429*82527734SSukumar Swaminathan 				    "Completed.   %s: mb=%p status=%x Poll. " \
2430*82527734SSukumar Swaminathan 				    "embedded %d",
2431*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
2432*82527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2433*82527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
2434*82527734SSukumar Swaminathan 			}
2435*82527734SSukumar Swaminathan 
2436*82527734SSukumar Swaminathan 			/* Process the result */
2437*82527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
2438*82527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
2439*82527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
2440*82527734SSukumar Swaminathan 				}
2441*82527734SSukumar Swaminathan 			}
2442*82527734SSukumar Swaminathan 
2443*82527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
2444*82527734SSukumar Swaminathan 		}
2445*82527734SSukumar Swaminathan 
2446*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
2447*82527734SSukumar Swaminathan 		if (mp) {
2448*82527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2449*82527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2450*82527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2451*82527734SSukumar Swaminathan 			}
2452*82527734SSukumar Swaminathan 		}
2453*82527734SSukumar Swaminathan 		rc = mb->mbxStatus;
2454*82527734SSukumar Swaminathan 
2455*82527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
2456*82527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)emlxs_mb_get(hba);
2457*82527734SSukumar Swaminathan 		if (mbq) {
2458*82527734SSukumar Swaminathan 			/* Attempt to send pending mailboxes */
2459*82527734SSukumar Swaminathan 			i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
2460*82527734SSukumar Swaminathan 			if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
2461*82527734SSukumar Swaminathan 				(void) emlxs_mem_put(hba, MEM_MBOX,
2462*82527734SSukumar Swaminathan 				    (uint8_t *)mbq);
2463*82527734SSukumar Swaminathan 			}
2464*82527734SSukumar Swaminathan 		}
2465*82527734SSukumar Swaminathan 		break;
2466*82527734SSukumar Swaminathan 
2467*82527734SSukumar Swaminathan 	case MBX_SLEEP:
2468*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
2469*82527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2470*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2471*82527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Sleep. embedded %d",
2472*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2473*82527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2474*82527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
2475*82527734SSukumar Swaminathan 		}
2476*82527734SSukumar Swaminathan 
2477*82527734SSukumar Swaminathan 		iptr = hba->sli.sli4.mq.addr.virt;
2478*82527734SSukumar Swaminathan 		iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
2479*82527734SSukumar Swaminathan 		hba->sli.sli4.mq.host_index++;
2480*82527734SSukumar Swaminathan 		if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
2481*82527734SSukumar Swaminathan 			hba->sli.sli4.mq.host_index = 0;
2482*82527734SSukumar Swaminathan 		}
2483*82527734SSukumar Swaminathan 
2484*82527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_mq(hba, (MAILBOX4 *)iptr, mb, tmo_local);
2485*82527734SSukumar Swaminathan 
2486*82527734SSukumar Swaminathan 		if (rc != MBX_SUCCESS) {
2487*82527734SSukumar Swaminathan 			break;
2488*82527734SSukumar Swaminathan 		}
2489*82527734SSukumar Swaminathan 
2490*82527734SSukumar Swaminathan 		/* Wait for completion */
2491*82527734SSukumar Swaminathan 		/* The driver clock is timing the mailbox. */
2492*82527734SSukumar Swaminathan 
2493*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
2494*82527734SSukumar Swaminathan 		while (!(mbq->flag & MBQ_COMPLETED)) {
2495*82527734SSukumar Swaminathan 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
2496*82527734SSukumar Swaminathan 		}
2497*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
2498*82527734SSukumar Swaminathan 
2499*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
2500*82527734SSukumar Swaminathan 		if (mp) {
2501*82527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2502*82527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2503*82527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2504*82527734SSukumar Swaminathan 			}
2505*82527734SSukumar Swaminathan 		}
2506*82527734SSukumar Swaminathan 		rc = mb->mbxStatus;
2507*82527734SSukumar Swaminathan 
2508*82527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
2509*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2510*82527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
2511*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
2512*82527734SSukumar Swaminathan 			    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2513*82527734SSukumar Swaminathan 			    (mb4->un.varSLIConfig.be.embedded)));
2514*82527734SSukumar Swaminathan 		} else {
2515*82527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD
2516*82527734SSukumar Swaminathan 			    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
2517*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2518*82527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
2519*82527734SSukumar Swaminathan 				    "Completed.   %s: mb=%p status=%x Sleep. " \
2520*82527734SSukumar Swaminathan 				    "embedded %d",
2521*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
2522*82527734SSukumar Swaminathan 				    ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
2523*82527734SSukumar Swaminathan 				    (mb4->un.varSLIConfig.be.embedded)));
2524*82527734SSukumar Swaminathan 			}
2525*82527734SSukumar Swaminathan 		}
2526*82527734SSukumar Swaminathan 		break;
2527*82527734SSukumar Swaminathan 	}
2528*82527734SSukumar Swaminathan 
2529*82527734SSukumar Swaminathan 	return (rc);
2530*82527734SSukumar Swaminathan 
2531*82527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd() */
2532*82527734SSukumar Swaminathan 
2533*82527734SSukumar Swaminathan 
2534*82527734SSukumar Swaminathan 
2535*82527734SSukumar Swaminathan /*ARGSUSED*/
2536*82527734SSukumar Swaminathan static uint32_t
2537*82527734SSukumar Swaminathan emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
2538*82527734SSukumar Swaminathan     uint32_t tmo)
2539*82527734SSukumar Swaminathan {
2540*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
2541*82527734SSukumar Swaminathan 	MAILBOX		*mb;
2542*82527734SSukumar Swaminathan 	mbox_rsp_hdr_t	*hdr_rsp;
2543*82527734SSukumar Swaminathan 	MATCHMAP	*mp;
2544*82527734SSukumar Swaminathan 	uint32_t	rc;
2545*82527734SSukumar Swaminathan 	uint32_t	tmo_local;
2546*82527734SSukumar Swaminathan 
2547*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
2548*82527734SSukumar Swaminathan 
2549*82527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
2550*82527734SSukumar Swaminathan 	rc = MBX_SUCCESS;
2551*82527734SSukumar Swaminathan 
2552*82527734SSukumar Swaminathan 	if (tmo < 30) {
2553*82527734SSukumar Swaminathan 		tmo = 30;
2554*82527734SSukumar Swaminathan 	}
2555*82527734SSukumar Swaminathan 
2556*82527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
2557*82527734SSukumar Swaminathan 	tmo_local = tmo * 100;
2558*82527734SSukumar Swaminathan 
2559*82527734SSukumar Swaminathan 	flag = MBX_POLL;
2560*82527734SSukumar Swaminathan 
2561*82527734SSukumar Swaminathan 	/* Check for hardware error */
2562*82527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
2563*82527734SSukumar Swaminathan 		mb->mbxStatus = MBX_HARDWARE_ERROR;
2564*82527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
2565*82527734SSukumar Swaminathan 	}
2566*82527734SSukumar Swaminathan 
2567*82527734SSukumar Swaminathan 	/* Initialize mailbox area */
2568*82527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
2569*82527734SSukumar Swaminathan 
2570*82527734SSukumar Swaminathan 	switch (flag) {
2571*82527734SSukumar Swaminathan 
2572*82527734SSukumar Swaminathan 	case MBX_POLL:
2573*82527734SSukumar Swaminathan 
2574*82527734SSukumar Swaminathan 		rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
2575*82527734SSukumar Swaminathan 
2576*82527734SSukumar Swaminathan 		/* Clean up the mailbox area */
2577*82527734SSukumar Swaminathan 		if (rc == MBX_TIMEOUT) {
2578*82527734SSukumar Swaminathan 			hba->flag |= FC_MBOX_TIMEOUT;
2579*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
2580*82527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
2581*82527734SSukumar Swaminathan 
2582*82527734SSukumar Swaminathan 		} else {
2583*82527734SSukumar Swaminathan 			/* Process the result */
2584*82527734SSukumar Swaminathan 			if (!(mbq->flag & MBQ_PASSTHRU)) {
2585*82527734SSukumar Swaminathan 				if (mbq->mbox_cmpl) {
2586*82527734SSukumar Swaminathan 					(void) (mbq->mbox_cmpl)(hba, mbq);
2587*82527734SSukumar Swaminathan 				}
2588*82527734SSukumar Swaminathan 			}
2589*82527734SSukumar Swaminathan 
2590*82527734SSukumar Swaminathan 			emlxs_mb_fini(hba, NULL, mb->mbxStatus);
2591*82527734SSukumar Swaminathan 		}
2592*82527734SSukumar Swaminathan 
2593*82527734SSukumar Swaminathan 		mp = (MATCHMAP *)mbq->nonembed;
2594*82527734SSukumar Swaminathan 		if (mp) {
2595*82527734SSukumar Swaminathan 			hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2596*82527734SSukumar Swaminathan 			if (hdr_rsp->status) {
2597*82527734SSukumar Swaminathan 				mb->mbxStatus = MBX_NONEMBED_ERROR;
2598*82527734SSukumar Swaminathan 			}
2599*82527734SSukumar Swaminathan 		}
2600*82527734SSukumar Swaminathan 		rc = mb->mbxStatus;
2601*82527734SSukumar Swaminathan 
2602*82527734SSukumar Swaminathan 		break;
2603*82527734SSukumar Swaminathan 	}
2604*82527734SSukumar Swaminathan 
2605*82527734SSukumar Swaminathan 	return (rc);
2606*82527734SSukumar Swaminathan 
2607*82527734SSukumar Swaminathan } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
2608*82527734SSukumar Swaminathan 
2609*82527734SSukumar Swaminathan 
2610*82527734SSukumar Swaminathan 
2611*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
2612*82527734SSukumar Swaminathan /*ARGSUSED*/
2613*82527734SSukumar Swaminathan static uint32_t
2614*82527734SSukumar Swaminathan emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
2615*82527734SSukumar Swaminathan {
2616*82527734SSukumar Swaminathan 	return (IOERR_NO_RESOURCES);
2617*82527734SSukumar Swaminathan 
2618*82527734SSukumar Swaminathan } /* emlxs_sli4_prep_fct_iocb() */
2619*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2620*82527734SSukumar Swaminathan 
2621*82527734SSukumar Swaminathan 
2622*82527734SSukumar Swaminathan /*ARGSUSED*/
2623*82527734SSukumar Swaminathan extern uint32_t
2624*82527734SSukumar Swaminathan emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
2625*82527734SSukumar Swaminathan {
2626*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
2627*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
2628*82527734SSukumar Swaminathan 	CHANNEL *cp;
2629*82527734SSukumar Swaminathan 	RPIobj_t *rp;
2630*82527734SSukumar Swaminathan 	XRIobj_t *xp;
2631*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
2632*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
2633*82527734SSukumar Swaminathan 	NODELIST *node;
2634*82527734SSukumar Swaminathan 	uint16_t iotag;
2635*82527734SSukumar Swaminathan 	uint32_t did;
2636*82527734SSukumar Swaminathan 
2637*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2638*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2639*82527734SSukumar Swaminathan 	cp = &hba->chan[channel];
2640*82527734SSukumar Swaminathan 
2641*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
2642*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
2643*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
2644*82527734SSukumar Swaminathan 
2645*82527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
2646*82527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
2647*82527734SSukumar Swaminathan 
2648*82527734SSukumar Swaminathan 	/* Find target node object */
2649*82527734SSukumar Swaminathan 	node = (NODELIST *)iocbq->node;
2650*82527734SSukumar Swaminathan 	rp = EMLXS_NODE_TO_RPI(hba, node);
2651*82527734SSukumar Swaminathan 
2652*82527734SSukumar Swaminathan 	if (!rp) {
2653*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2654*82527734SSukumar Swaminathan 		    "Unable to find rpi. did=0x%x", did);
2655*82527734SSukumar Swaminathan 
2656*82527734SSukumar Swaminathan 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2657*82527734SSukumar Swaminathan 		    IOERR_INVALID_RPI, 0);
2658*82527734SSukumar Swaminathan 		return (0xff);
2659*82527734SSukumar Swaminathan 	}
2660*82527734SSukumar Swaminathan 
2661*82527734SSukumar Swaminathan 	sbp->channel = cp;
2662*82527734SSukumar Swaminathan 	/* Next allocate an Exchange for this command */
2663*82527734SSukumar Swaminathan 	xp = emlxs_sli4_alloc_xri(hba, sbp, rp);
2664*82527734SSukumar Swaminathan 
2665*82527734SSukumar Swaminathan 	if (!xp) {
2666*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2667*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
2668*82527734SSukumar Swaminathan 
2669*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
2670*82527734SSukumar Swaminathan 	}
2671*82527734SSukumar Swaminathan 	sbp->bmp = NULL;
2672*82527734SSukumar Swaminathan 	iotag = sbp->iotag;
2673*82527734SSukumar Swaminathan 
2674*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
2675*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,  /* DEBUG */
2676*82527734SSukumar Swaminathan 	    "Prep FCP iotag: %x xri: %x", iotag, xp->XRI);
2677*82527734SSukumar Swaminathan #endif
2678*82527734SSukumar Swaminathan 
2679*82527734SSukumar Swaminathan 	/* Indicate this is a FCP cmd */
2680*82527734SSukumar Swaminathan 	iocbq->flag |= IOCB_FCP_CMD;
2681*82527734SSukumar Swaminathan 
2682*82527734SSukumar Swaminathan 	if (emlxs_sli4_bde_setup(port, sbp)) {
2683*82527734SSukumar Swaminathan 		emlxs_sli4_free_xri(hba, sbp, xp);
2684*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2685*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
2686*82527734SSukumar Swaminathan 
2687*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
2688*82527734SSukumar Swaminathan 	}
2689*82527734SSukumar Swaminathan 
2690*82527734SSukumar Swaminathan 
2691*82527734SSukumar Swaminathan 	/* DEBUG */
2692*82527734SSukumar Swaminathan #ifdef DEBUG_FCP
2693*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2694*82527734SSukumar Swaminathan 	    "SGLaddr virt %p phys %p size %d", xp->SGList.virt,
2695*82527734SSukumar Swaminathan 	    xp->SGList.phys, pkt->pkt_datalen);
2696*82527734SSukumar Swaminathan 	emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 20, 0);
2697*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2698*82527734SSukumar Swaminathan 	    "CMD virt %p len %d:%d:%d",
2699*82527734SSukumar Swaminathan 	    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
2700*82527734SSukumar Swaminathan 	emlxs_data_dump(hba, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
2701*82527734SSukumar Swaminathan #endif
2702*82527734SSukumar Swaminathan 
2703*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0,
2704*82527734SSukumar Swaminathan 	    xp->SGList.size, DDI_DMA_SYNC_FORDEV);
2705*82527734SSukumar Swaminathan 
2706*82527734SSukumar Swaminathan 	/* if device is FCP-2 device, set the following bit */
2707*82527734SSukumar Swaminathan 	/* that says to run the FC-TAPE protocol. */
2708*82527734SSukumar Swaminathan 	if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
2709*82527734SSukumar Swaminathan 		wqe->ERP = 1;
2710*82527734SSukumar Swaminathan 	}
2711*82527734SSukumar Swaminathan 
2712*82527734SSukumar Swaminathan 	if (pkt->pkt_datalen == 0) {
2713*82527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_ICMND64_CR;
2714*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
2715*82527734SSukumar Swaminathan 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
2716*82527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_IREAD64_CR;
2717*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
2718*82527734SSukumar Swaminathan 		wqe->PU = PARM_READ_CHECK;
2719*82527734SSukumar Swaminathan 	} else {
2720*82527734SSukumar Swaminathan 		wqe->Command = CMD_FCP_IWRITE64_CR;
2721*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
2722*82527734SSukumar Swaminathan 	}
2723*82527734SSukumar Swaminathan 	wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
2724*82527734SSukumar Swaminathan 
2725*82527734SSukumar Swaminathan 	wqe->ContextTag = rp->RPI;
2726*82527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
2727*82527734SSukumar Swaminathan 	wqe->XRITag = xp->XRI;
2728*82527734SSukumar Swaminathan 	wqe->Timer =
2729*82527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
2730*82527734SSukumar Swaminathan 
2731*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
2732*82527734SSukumar Swaminathan 		wqe->CCPE = 1;
2733*82527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
2734*82527734SSukumar Swaminathan 	}
2735*82527734SSukumar Swaminathan 
2736*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
2737*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
2738*82527734SSukumar Swaminathan 		wqe->Class = CLASS2;
2739*82527734SSukumar Swaminathan 		break;
2740*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
2741*82527734SSukumar Swaminathan 	default:
2742*82527734SSukumar Swaminathan 		wqe->Class = CLASS3;
2743*82527734SSukumar Swaminathan 		break;
2744*82527734SSukumar Swaminathan 	}
2745*82527734SSukumar Swaminathan 	sbp->class = wqe->Class;
2746*82527734SSukumar Swaminathan 	wqe->RequestTag = iotag;
2747*82527734SSukumar Swaminathan 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
2748*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
2749*82527734SSukumar Swaminathan } /* emlxs_sli4_prep_fcp_iocb() */
2750*82527734SSukumar Swaminathan 
2751*82527734SSukumar Swaminathan 
2752*82527734SSukumar Swaminathan /*ARGSUSED*/
2753*82527734SSukumar Swaminathan static uint32_t
2754*82527734SSukumar Swaminathan emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
2755*82527734SSukumar Swaminathan {
2756*82527734SSukumar Swaminathan 	return (FC_TRAN_BUSY);
2757*82527734SSukumar Swaminathan 
2758*82527734SSukumar Swaminathan } /* emlxs_sli4_prep_ip_iocb() */
2759*82527734SSukumar Swaminathan 
2760*82527734SSukumar Swaminathan 
2761*82527734SSukumar Swaminathan /*ARGSUSED*/
2762*82527734SSukumar Swaminathan static uint32_t
2763*82527734SSukumar Swaminathan emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
2764*82527734SSukumar Swaminathan {
2765*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
2766*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
2767*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
2768*82527734SSukumar Swaminathan 	IOCB *iocb;
2769*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
2770*82527734SSukumar Swaminathan 	FCFIobj_t *fp;
2771*82527734SSukumar Swaminathan 	RPIobj_t *rp = NULL;
2772*82527734SSukumar Swaminathan 	XRIobj_t *xp;
2773*82527734SSukumar Swaminathan 	CHANNEL *cp;
2774*82527734SSukumar Swaminathan 	uint32_t did;
2775*82527734SSukumar Swaminathan 	uint32_t cmd;
2776*82527734SSukumar Swaminathan 	ULP_SGE64 stage_sge;
2777*82527734SSukumar Swaminathan 	ULP_SGE64 *sge;
2778*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
2779*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_resp;
2780*82527734SSukumar Swaminathan 	emlxs_node_t *node;
2781*82527734SSukumar Swaminathan 
2782*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2783*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
2784*82527734SSukumar Swaminathan 
2785*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
2786*82527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
2787*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
2788*82527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
2789*82527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
2790*82527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_els];
2791*82527734SSukumar Swaminathan 
2792*82527734SSukumar Swaminathan 	/* Initalize iocbq */
2793*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
2794*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
2795*82527734SSukumar Swaminathan 
2796*82527734SSukumar Swaminathan 	sbp->channel = cp;
2797*82527734SSukumar Swaminathan 	sbp->bmp = NULL;
2798*82527734SSukumar Swaminathan 
2799*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
2800*82527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
2801*82527734SSukumar Swaminathan 	cp_resp = pkt->pkt_resp_cookie;
2802*82527734SSukumar Swaminathan #else
2803*82527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
2804*82527734SSukumar Swaminathan 	cp_resp = &pkt->pkt_resp_cookie;
2805*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2806*82527734SSukumar Swaminathan 
2807*82527734SSukumar Swaminathan 	/* CMD payload */
2808*82527734SSukumar Swaminathan 	sge = &stage_sge;
2809*82527734SSukumar Swaminathan 	sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
2810*82527734SSukumar Swaminathan 	sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
2811*82527734SSukumar Swaminathan 	sge->length = pkt->pkt_cmdlen;
2812*82527734SSukumar Swaminathan 	sge->offset = 0;
2813*82527734SSukumar Swaminathan 
2814*82527734SSukumar Swaminathan 	/* Initalize iocb */
2815*82527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2816*82527734SSukumar Swaminathan 		/* ELS Response */
2817*82527734SSukumar Swaminathan 
2818*82527734SSukumar Swaminathan 		xp = emlxs_sli4_register_xri(hba, sbp, pkt->pkt_cmd_fhdr.rx_id);
2819*82527734SSukumar Swaminathan 
2820*82527734SSukumar Swaminathan 		if (!xp) {
2821*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2822*82527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
2823*82527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
2824*82527734SSukumar Swaminathan 
2825*82527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2826*82527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
2827*82527734SSukumar Swaminathan 			return (0xff);
2828*82527734SSukumar Swaminathan 		}
2829*82527734SSukumar Swaminathan 
2830*82527734SSukumar Swaminathan 		rp = xp->RPIp;
2831*82527734SSukumar Swaminathan 
2832*82527734SSukumar Swaminathan 		if (!rp) {
2833*82527734SSukumar Swaminathan 			/* This means that we had a node registered */
2834*82527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
2835*82527734SSukumar Swaminathan 			/* has since been unregistered. */
2836*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
2837*82527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
2838*82527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
2839*82527734SSukumar Swaminathan 
2840*82527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
2841*82527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
2842*82527734SSukumar Swaminathan 			return (0xff);
2843*82527734SSukumar Swaminathan 		}
2844*82527734SSukumar Swaminathan 
2845*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2846*82527734SSukumar Swaminathan 		    "Prep ELS XRI: xri=%x iotag=%x oxid=%x rpi=%x",
2847*82527734SSukumar Swaminathan 		    xp->XRI, xp->iotag, xp->rx_id, rp->RPI);
2848*82527734SSukumar Swaminathan 
2849*82527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_ELS_RSP64_CX;
2850*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
2851*82527734SSukumar Swaminathan 
2852*82527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
2853*82527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
2854*82527734SSukumar Swaminathan 		wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
2855*82527734SSukumar Swaminathan 
2856*82527734SSukumar Swaminathan 		wqe->un.ElsRsp.RemoteId = did;
2857*82527734SSukumar Swaminathan 		wqe->PU = 0x3;
2858*82527734SSukumar Swaminathan 
2859*82527734SSukumar Swaminathan 		sge->last = 1;
2860*82527734SSukumar Swaminathan 		/* Now sge is fully staged */
2861*82527734SSukumar Swaminathan 
2862*82527734SSukumar Swaminathan 		sge = xp->SGList.virt;
2863*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2864*82527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
2865*82527734SSukumar Swaminathan 
2866*82527734SSukumar Swaminathan 		wqe->ContextTag = port->vpi + hba->vpi_base;
2867*82527734SSukumar Swaminathan 		wqe->ContextType = WQE_VPI_CONTEXT;
2868*82527734SSukumar Swaminathan 		wqe->OXId = xp->rx_id;
2869*82527734SSukumar Swaminathan 
2870*82527734SSukumar Swaminathan 	} else {
2871*82527734SSukumar Swaminathan 		/* ELS Request */
2872*82527734SSukumar Swaminathan 
2873*82527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
2874*82527734SSukumar Swaminathan 		rp = EMLXS_NODE_TO_RPI(hba, node);
2875*82527734SSukumar Swaminathan 
2876*82527734SSukumar Swaminathan 		if (!rp) {
2877*82527734SSukumar Swaminathan 			fp = hba->sli.sli4.FCFIp;
2878*82527734SSukumar Swaminathan 			rp = &fp->scratch_rpi;
2879*82527734SSukumar Swaminathan 		}
2880*82527734SSukumar Swaminathan 
2881*82527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
2882*82527734SSukumar Swaminathan 		xp = emlxs_sli4_alloc_xri(hba, sbp, rp);
2883*82527734SSukumar Swaminathan 
2884*82527734SSukumar Swaminathan 		if (!xp) {
2885*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
2886*82527734SSukumar Swaminathan 			    "Adapter Busy. Unable to allocate exchange. " \
2887*82527734SSukumar Swaminathan 			    "did=0x%x", did);
2888*82527734SSukumar Swaminathan 
2889*82527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
2890*82527734SSukumar Swaminathan 		}
2891*82527734SSukumar Swaminathan 
2892*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2893*82527734SSukumar Swaminathan 		    "Prep ELS XRI: xri=%x iotag=%x rpi=%x", xp->XRI,
2894*82527734SSukumar Swaminathan 		    xp->iotag, rp->RPI);
2895*82527734SSukumar Swaminathan 
2896*82527734SSukumar Swaminathan 		wqe->Command = CMD_ELS_REQUEST64_CR;
2897*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_ELS;
2898*82527734SSukumar Swaminathan 
2899*82527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
2900*82527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
2901*82527734SSukumar Swaminathan 		wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
2902*82527734SSukumar Swaminathan 
2903*82527734SSukumar Swaminathan 		/* setup for rsp */
2904*82527734SSukumar Swaminathan 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
2905*82527734SSukumar Swaminathan 		iocb->ULPPU = 1;	/* Wd4 is relative offset */
2906*82527734SSukumar Swaminathan 
2907*82527734SSukumar Swaminathan 		sge->last = 0;
2908*82527734SSukumar Swaminathan 
2909*82527734SSukumar Swaminathan 		sge = xp->SGList.virt;
2910*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2911*82527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
2912*82527734SSukumar Swaminathan 
2913*82527734SSukumar Swaminathan 		wqe->un.ElsCmd.PayloadLength =
2914*82527734SSukumar Swaminathan 		    pkt->pkt_cmdlen; /* Byte offset of rsp data */
2915*82527734SSukumar Swaminathan 
2916*82527734SSukumar Swaminathan 		/* RSP payload */
2917*82527734SSukumar Swaminathan 		sge = &stage_sge;
2918*82527734SSukumar Swaminathan 		sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
2919*82527734SSukumar Swaminathan 		sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
2920*82527734SSukumar Swaminathan 		sge->length = pkt->pkt_rsplen;
2921*82527734SSukumar Swaminathan 		sge->offset = pkt->pkt_cmdlen;
2922*82527734SSukumar Swaminathan 		sge->last = 1;
2923*82527734SSukumar Swaminathan 		/* Now sge is fully staged */
2924*82527734SSukumar Swaminathan 
2925*82527734SSukumar Swaminathan 		sge = xp->SGList.virt;
2926*82527734SSukumar Swaminathan 		sge++;
2927*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2928*82527734SSukumar Swaminathan 		    sizeof (ULP_SGE64));
2929*82527734SSukumar Swaminathan #ifdef DEBUG_ELS
2930*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2931*82527734SSukumar Swaminathan 		    "SGLaddr virt %p phys %p",
2932*82527734SSukumar Swaminathan 		    xp->SGList.virt, xp->SGList.phys);
2933*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2934*82527734SSukumar Swaminathan 		    "PAYLOAD virt %p phys %p",
2935*82527734SSukumar Swaminathan 		    pkt->pkt_cmd, cp_cmd->dmac_laddress);
2936*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 12, 0);
2937*82527734SSukumar Swaminathan #endif
2938*82527734SSukumar Swaminathan 
2939*82527734SSukumar Swaminathan 		cmd = *((uint32_t *)pkt->pkt_cmd);
2940*82527734SSukumar Swaminathan 		cmd &= ELS_CMD_MASK;
2941*82527734SSukumar Swaminathan 
2942*82527734SSukumar Swaminathan 		switch (cmd) {
2943*82527734SSukumar Swaminathan 		case ELS_CMD_FLOGI:
2944*82527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
2945*82527734SSukumar Swaminathan 			wqe->ContextTag = fp->FCFI;
2946*82527734SSukumar Swaminathan 			wqe->ContextType = WQE_FCFI_CONTEXT;
2947*82527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
2948*82527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
2949*82527734SSukumar Swaminathan 				wqe->ELSId |= WQE_ELSID_FLOGI;
2950*82527734SSukumar Swaminathan 			}
2951*82527734SSukumar Swaminathan 			break;
2952*82527734SSukumar Swaminathan 		case ELS_CMD_FDISC:
2953*82527734SSukumar Swaminathan 			wqe->un.ElsCmd.SP = 1;
2954*82527734SSukumar Swaminathan 			wqe->ContextTag = port->vpi + hba->vpi_base;
2955*82527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
2956*82527734SSukumar Swaminathan 			if (hba->flag & FC_FIP_SUPPORTED) {
2957*82527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
2958*82527734SSukumar Swaminathan 				wqe->ELSId |= WQE_ELSID_FDISC;
2959*82527734SSukumar Swaminathan 			}
2960*82527734SSukumar Swaminathan 			break;
2961*82527734SSukumar Swaminathan 		case ELS_CMD_LOGO:
2962*82527734SSukumar Swaminathan 			wqe->ContextTag = port->vpi + hba->vpi_base;
2963*82527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
2964*82527734SSukumar Swaminathan 			if ((hba->flag & FC_FIP_SUPPORTED) &&
2965*82527734SSukumar Swaminathan 			    (did == FABRIC_DID)) {
2966*82527734SSukumar Swaminathan 				wqe->CmdType |= WQE_TYPE_MASK_FIP;
2967*82527734SSukumar Swaminathan 				wqe->ELSId |= WQE_ELSID_LOGO;
2968*82527734SSukumar Swaminathan 			}
2969*82527734SSukumar Swaminathan 			break;
2970*82527734SSukumar Swaminathan 
2971*82527734SSukumar Swaminathan 		case ELS_CMD_SCR:
2972*82527734SSukumar Swaminathan 		case ELS_CMD_PLOGI:
2973*82527734SSukumar Swaminathan 		case ELS_CMD_PRLI:
2974*82527734SSukumar Swaminathan 		default:
2975*82527734SSukumar Swaminathan 			wqe->ContextTag = port->vpi + hba->vpi_base;
2976*82527734SSukumar Swaminathan 			wqe->ContextType = WQE_VPI_CONTEXT;
2977*82527734SSukumar Swaminathan 			break;
2978*82527734SSukumar Swaminathan 		}
2979*82527734SSukumar Swaminathan 		wqe->un.ElsCmd.RemoteId = did;
2980*82527734SSukumar Swaminathan 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
2981*82527734SSukumar Swaminathan 	}
2982*82527734SSukumar Swaminathan 
2983*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0,
2984*82527734SSukumar Swaminathan 	    xp->SGList.size, DDI_DMA_SYNC_FORDEV);
2985*82527734SSukumar Swaminathan 
2986*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
2987*82527734SSukumar Swaminathan 		wqe->CCPE = 1;
2988*82527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
2989*82527734SSukumar Swaminathan 	}
2990*82527734SSukumar Swaminathan 
2991*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
2992*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
2993*82527734SSukumar Swaminathan 		wqe->Class = CLASS2;
2994*82527734SSukumar Swaminathan 		break;
2995*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
2996*82527734SSukumar Swaminathan 	default:
2997*82527734SSukumar Swaminathan 		wqe->Class = CLASS3;
2998*82527734SSukumar Swaminathan 		break;
2999*82527734SSukumar Swaminathan 	}
3000*82527734SSukumar Swaminathan 	sbp->class = wqe->Class;
3001*82527734SSukumar Swaminathan 	wqe->XRITag = xp->XRI;
3002*82527734SSukumar Swaminathan 	wqe->RequestTag = xp->iotag;
3003*82527734SSukumar Swaminathan 	wqe->CQId = 0x3ff;
3004*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3005*82527734SSukumar Swaminathan 
3006*82527734SSukumar Swaminathan } /* emlxs_sli4_prep_els_iocb() */
3007*82527734SSukumar Swaminathan 
3008*82527734SSukumar Swaminathan 
3009*82527734SSukumar Swaminathan /*ARGSUSED*/
3010*82527734SSukumar Swaminathan static uint32_t
3011*82527734SSukumar Swaminathan emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3012*82527734SSukumar Swaminathan {
3013*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3014*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
3015*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3016*82527734SSukumar Swaminathan 	IOCB *iocb;
3017*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
3018*82527734SSukumar Swaminathan 	NODELIST *node = NULL;
3019*82527734SSukumar Swaminathan 	CHANNEL *cp;
3020*82527734SSukumar Swaminathan 	RPIobj_t *rp;
3021*82527734SSukumar Swaminathan 	XRIobj_t *xp;
3022*82527734SSukumar Swaminathan 	uint32_t did;
3023*82527734SSukumar Swaminathan 
3024*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3025*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3026*82527734SSukumar Swaminathan 
3027*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3028*82527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
3029*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3030*82527734SSukumar Swaminathan 	bzero((void *)wqe, sizeof (emlxs_wqe_t));
3031*82527734SSukumar Swaminathan 	bzero((void *)iocb, sizeof (IOCB));
3032*82527734SSukumar Swaminathan 
3033*82527734SSukumar Swaminathan 	cp = &hba->chan[hba->channel_ct];
3034*82527734SSukumar Swaminathan 
3035*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
3036*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
3037*82527734SSukumar Swaminathan 
3038*82527734SSukumar Swaminathan 	sbp->bmp = NULL;
3039*82527734SSukumar Swaminathan 	sbp->channel = cp;
3040*82527734SSukumar Swaminathan 
3041*82527734SSukumar Swaminathan 	/* Initalize wqe */
3042*82527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
3043*82527734SSukumar Swaminathan 		/* CT Response */
3044*82527734SSukumar Swaminathan 
3045*82527734SSukumar Swaminathan 		xp = emlxs_sli4_register_xri(hba, sbp, pkt->pkt_cmd_fhdr.rx_id);
3046*82527734SSukumar Swaminathan 
3047*82527734SSukumar Swaminathan 		if (!xp) {
3048*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3049*82527734SSukumar Swaminathan 			    "Unable to find XRI. rxid=%x",
3050*82527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
3051*82527734SSukumar Swaminathan 
3052*82527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3053*82527734SSukumar Swaminathan 			    IOERR_NO_XRI, 0);
3054*82527734SSukumar Swaminathan 			return (0xff);
3055*82527734SSukumar Swaminathan 		}
3056*82527734SSukumar Swaminathan 
3057*82527734SSukumar Swaminathan 		rp = xp->RPIp;
3058*82527734SSukumar Swaminathan 
3059*82527734SSukumar Swaminathan 		if (!rp) {
3060*82527734SSukumar Swaminathan 			/* This means that we had a node registered */
3061*82527734SSukumar Swaminathan 			/* when the unsol request came in but the node */
3062*82527734SSukumar Swaminathan 			/* has since been unregistered. */
3063*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3064*82527734SSukumar Swaminathan 			    "Unable to find RPI. rxid=%x",
3065*82527734SSukumar Swaminathan 			    pkt->pkt_cmd_fhdr.rx_id);
3066*82527734SSukumar Swaminathan 
3067*82527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3068*82527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
3069*82527734SSukumar Swaminathan 			return (0xff);
3070*82527734SSukumar Swaminathan 		}
3071*82527734SSukumar Swaminathan 
3072*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3073*82527734SSukumar Swaminathan 		    "Prep CT XRI: xri=%x iotag=%x oxid=%x", xp->XRI,
3074*82527734SSukumar Swaminathan 		    xp->iotag, xp->rx_id);
3075*82527734SSukumar Swaminathan 
3076*82527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
3077*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3078*82527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
3079*82527734SSukumar Swaminathan 
3080*82527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
3081*82527734SSukumar Swaminathan 		}
3082*82527734SSukumar Swaminathan 
3083*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
3084*82527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_SEQUENCE64_CR;
3085*82527734SSukumar Swaminathan 		wqe->un.XmitSeq.la = 1;
3086*82527734SSukumar Swaminathan 
3087*82527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
3088*82527734SSukumar Swaminathan 			wqe->un.XmitSeq.ls = 1;
3089*82527734SSukumar Swaminathan 		}
3090*82527734SSukumar Swaminathan 
3091*82527734SSukumar Swaminathan 		if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
3092*82527734SSukumar Swaminathan 			wqe->un.XmitSeq.si = 1;
3093*82527734SSukumar Swaminathan 		}
3094*82527734SSukumar Swaminathan 
3095*82527734SSukumar Swaminathan 		wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
3096*82527734SSukumar Swaminathan 		wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3097*82527734SSukumar Swaminathan 		wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
3098*82527734SSukumar Swaminathan 		wqe->OXId = xp->rx_id;
3099*82527734SSukumar Swaminathan 		wqe->XC = 1;
3100*82527734SSukumar Swaminathan 		wqe->CmdSpecific[0] = wqe->un.GenReq.Payload.tus.f.bdeSize;
3101*82527734SSukumar Swaminathan 
3102*82527734SSukumar Swaminathan 	} else {
3103*82527734SSukumar Swaminathan 		/* CT Request */
3104*82527734SSukumar Swaminathan 
3105*82527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
3106*82527734SSukumar Swaminathan 		rp = EMLXS_NODE_TO_RPI(hba, node);
3107*82527734SSukumar Swaminathan 
3108*82527734SSukumar Swaminathan 		if (!rp) {
3109*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
3110*82527734SSukumar Swaminathan 			    "Unable to find rpi. did=0x%x", did);
3111*82527734SSukumar Swaminathan 
3112*82527734SSukumar Swaminathan 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3113*82527734SSukumar Swaminathan 			    IOERR_INVALID_RPI, 0);
3114*82527734SSukumar Swaminathan 			return (0xff);
3115*82527734SSukumar Swaminathan 		}
3116*82527734SSukumar Swaminathan 
3117*82527734SSukumar Swaminathan 		/* Next allocate an Exchange for this command */
3118*82527734SSukumar Swaminathan 		xp = emlxs_sli4_alloc_xri(hba, sbp, rp);
3119*82527734SSukumar Swaminathan 
3120*82527734SSukumar Swaminathan 		if (!xp) {
3121*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3122*82527734SSukumar Swaminathan 			    "Adapter Busy. Unable to allocate exchange. " \
3123*82527734SSukumar Swaminathan 			    "did=0x%x", did);
3124*82527734SSukumar Swaminathan 
3125*82527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
3126*82527734SSukumar Swaminathan 		}
3127*82527734SSukumar Swaminathan 
3128*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3129*82527734SSukumar Swaminathan 		    "Prep CT XRI: %x iotag %x", xp->XRI, xp->iotag);
3130*82527734SSukumar Swaminathan 
3131*82527734SSukumar Swaminathan 		if (emlxs_sli4_bde_setup(port, sbp)) {
3132*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3133*82527734SSukumar Swaminathan 			    "Adapter Busy. Unable to setup SGE. did=0x%x", did);
3134*82527734SSukumar Swaminathan 
3135*82527734SSukumar Swaminathan 			emlxs_sli4_free_xri(hba, sbp, xp);
3136*82527734SSukumar Swaminathan 			return (FC_TRAN_BUSY);
3137*82527734SSukumar Swaminathan 		}
3138*82527734SSukumar Swaminathan 
3139*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
3140*82527734SSukumar Swaminathan 		wqe->Command = CMD_GEN_REQUEST64_CR;
3141*82527734SSukumar Swaminathan 		wqe->un.GenReq.la = 1;
3142*82527734SSukumar Swaminathan 		wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
3143*82527734SSukumar Swaminathan 		wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3144*82527734SSukumar Swaminathan 		wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
3145*82527734SSukumar Swaminathan 		wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3146*82527734SSukumar Swaminathan 
3147*82527734SSukumar Swaminathan #ifdef DEBUG_CT
3148*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3149*82527734SSukumar Swaminathan 		    "SGLaddr virt %p phys %p", xp->SGList.virt,
3150*82527734SSukumar Swaminathan 		    xp->SGList.phys);
3151*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 12, 0);
3152*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3153*82527734SSukumar Swaminathan 		    "CMD virt %p len %d:%d",
3154*82527734SSukumar Swaminathan 		    pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
3155*82527734SSukumar Swaminathan 		emlxs_data_dump(hba, "DATA", (uint32_t *)pkt->pkt_cmd, 20, 0);
3156*82527734SSukumar Swaminathan #endif /* DEBUG_CT */
3157*82527734SSukumar Swaminathan 	}
3158*82527734SSukumar Swaminathan 
3159*82527734SSukumar Swaminathan 	/* Setup for rsp */
3160*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3161*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
3162*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
3163*82527734SSukumar Swaminathan 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
3164*82527734SSukumar Swaminathan 
3165*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0,
3166*82527734SSukumar Swaminathan 	    xp->SGList.size, DDI_DMA_SYNC_FORDEV);
3167*82527734SSukumar Swaminathan 
3168*82527734SSukumar Swaminathan 	wqe->ContextTag = rp->RPI;
3169*82527734SSukumar Swaminathan 	wqe->ContextType = WQE_RPI_CONTEXT;
3170*82527734SSukumar Swaminathan 	wqe->XRITag = xp->XRI;
3171*82527734SSukumar Swaminathan 
3172*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
3173*82527734SSukumar Swaminathan 		wqe->CCPE = 1;
3174*82527734SSukumar Swaminathan 		wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
3175*82527734SSukumar Swaminathan 	}
3176*82527734SSukumar Swaminathan 
3177*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3178*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
3179*82527734SSukumar Swaminathan 		wqe->Class = CLASS2;
3180*82527734SSukumar Swaminathan 		break;
3181*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
3182*82527734SSukumar Swaminathan 	default:
3183*82527734SSukumar Swaminathan 		wqe->Class = CLASS3;
3184*82527734SSukumar Swaminathan 		break;
3185*82527734SSukumar Swaminathan 	}
3186*82527734SSukumar Swaminathan 	sbp->class = wqe->Class;
3187*82527734SSukumar Swaminathan 	wqe->RequestTag = xp->iotag;
3188*82527734SSukumar Swaminathan 	wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
3189*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3190*82527734SSukumar Swaminathan 
3191*82527734SSukumar Swaminathan } /* emlxs_sli4_prep_ct_iocb() */
3192*82527734SSukumar Swaminathan 
3193*82527734SSukumar Swaminathan 
3194*82527734SSukumar Swaminathan /*ARGSUSED*/
3195*82527734SSukumar Swaminathan static int
3196*82527734SSukumar Swaminathan emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
3197*82527734SSukumar Swaminathan {
3198*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3199*82527734SSukumar Swaminathan 	uint32_t *ptr;
3200*82527734SSukumar Swaminathan 	int num_entries = 0;
3201*82527734SSukumar Swaminathan 	EQE_u eqe;
3202*82527734SSukumar Swaminathan 	uint32_t host_index, shost_index;
3203*82527734SSukumar Swaminathan 	int rc = 0;
3204*82527734SSukumar Swaminathan 
3205*82527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
3206*82527734SSukumar Swaminathan 	ptr = eq->addr.virt;
3207*82527734SSukumar Swaminathan 	ptr += eq->host_index;
3208*82527734SSukumar Swaminathan 	host_index = eq->host_index;
3209*82527734SSukumar Swaminathan 
3210*82527734SSukumar Swaminathan 	shost_index = host_index;
3211*82527734SSukumar Swaminathan 
3212*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, 0,
3213*82527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
3214*82527734SSukumar Swaminathan 
3215*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3216*82527734SSukumar Swaminathan 
3217*82527734SSukumar Swaminathan 	for (;;) {
3218*82527734SSukumar Swaminathan 		eqe.word = *ptr;
3219*82527734SSukumar Swaminathan 		eqe.word = BE_SWAP32(eqe.word);
3220*82527734SSukumar Swaminathan 
3221*82527734SSukumar Swaminathan 		if (eqe.word & EQE_VALID) {
3222*82527734SSukumar Swaminathan 			rc = 1;
3223*82527734SSukumar Swaminathan 			break;
3224*82527734SSukumar Swaminathan 		}
3225*82527734SSukumar Swaminathan 
3226*82527734SSukumar Swaminathan 		*ptr = 0;
3227*82527734SSukumar Swaminathan 		num_entries++;
3228*82527734SSukumar Swaminathan 		host_index++;
3229*82527734SSukumar Swaminathan 		if (host_index >= eq->max_index) {
3230*82527734SSukumar Swaminathan 			host_index = 0;
3231*82527734SSukumar Swaminathan 			ptr = eq->addr.virt;
3232*82527734SSukumar Swaminathan 		} else {
3233*82527734SSukumar Swaminathan 			ptr++;
3234*82527734SSukumar Swaminathan 		}
3235*82527734SSukumar Swaminathan 
3236*82527734SSukumar Swaminathan 		if (host_index == shost_index) {
3237*82527734SSukumar Swaminathan 			/* We donot need to loop forever */
3238*82527734SSukumar Swaminathan 			break;
3239*82527734SSukumar Swaminathan 		}
3240*82527734SSukumar Swaminathan 	}
3241*82527734SSukumar Swaminathan 
3242*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3243*82527734SSukumar Swaminathan 
3244*82527734SSukumar Swaminathan 	return (rc);
3245*82527734SSukumar Swaminathan 
3246*82527734SSukumar Swaminathan } /* emlxs_sli4_poll_eq */
3247*82527734SSukumar Swaminathan 
3248*82527734SSukumar Swaminathan 
3249*82527734SSukumar Swaminathan /*ARGSUSED*/
3250*82527734SSukumar Swaminathan static void
3251*82527734SSukumar Swaminathan emlxs_sli4_poll_intr(emlxs_hba_t *hba, uint32_t att_bit)
3252*82527734SSukumar Swaminathan {
3253*82527734SSukumar Swaminathan 	int rc = 0;
3254*82527734SSukumar Swaminathan 	int i;
3255*82527734SSukumar Swaminathan 	char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
3256*82527734SSukumar Swaminathan 	char arg2;
3257*82527734SSukumar Swaminathan 
3258*82527734SSukumar Swaminathan 	/*
3259*82527734SSukumar Swaminathan 	 * Poll the eqe to see if the valid bit is set or not
3260*82527734SSukumar Swaminathan 	 */
3261*82527734SSukumar Swaminathan 
3262*82527734SSukumar Swaminathan 	for (;;) {
3263*82527734SSukumar Swaminathan 		if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
3264*82527734SSukumar Swaminathan 			/* only poll eqe0 */
3265*82527734SSukumar Swaminathan 			rc = emlxs_sli4_poll_eq(hba,
3266*82527734SSukumar Swaminathan 			    &hba->sli.sli4.eq[0]);
3267*82527734SSukumar Swaminathan 			if (rc == 1) {
3268*82527734SSukumar Swaminathan 				(void) bcopy((char *)&arg[0],
3269*82527734SSukumar Swaminathan 				    (char *)&arg2, sizeof (char));
3270*82527734SSukumar Swaminathan 				break;
3271*82527734SSukumar Swaminathan 			}
3272*82527734SSukumar Swaminathan 		} else {
3273*82527734SSukumar Swaminathan 			/* poll every msi vector */
3274*82527734SSukumar Swaminathan 			for (i = 0; i < hba->intr_count; i++) {
3275*82527734SSukumar Swaminathan 				rc = emlxs_sli4_poll_eq(hba,
3276*82527734SSukumar Swaminathan 				    &hba->sli.sli4.eq[i]);
3277*82527734SSukumar Swaminathan 
3278*82527734SSukumar Swaminathan 				if (rc == 1) {
3279*82527734SSukumar Swaminathan 					break;
3280*82527734SSukumar Swaminathan 				}
3281*82527734SSukumar Swaminathan 			}
3282*82527734SSukumar Swaminathan 			if ((i != hba->intr_count) && (rc == 1)) {
3283*82527734SSukumar Swaminathan 				(void) bcopy((char *)&arg[i],
3284*82527734SSukumar Swaminathan 				    (char *)&arg2, sizeof (char));
3285*82527734SSukumar Swaminathan 				break;
3286*82527734SSukumar Swaminathan 			}
3287*82527734SSukumar Swaminathan 		}
3288*82527734SSukumar Swaminathan 	}
3289*82527734SSukumar Swaminathan 
3290*82527734SSukumar Swaminathan 	/* process it here */
3291*82527734SSukumar Swaminathan 	rc = emlxs_sli4_msi_intr((char *)hba, (char *)&arg2);
3292*82527734SSukumar Swaminathan 
3293*82527734SSukumar Swaminathan 	return;
3294*82527734SSukumar Swaminathan 
3295*82527734SSukumar Swaminathan } /* emlxs_sli4_poll_intr() */
3296*82527734SSukumar Swaminathan 
3297*82527734SSukumar Swaminathan 
3298*82527734SSukumar Swaminathan /*ARGSUSED*/
3299*82527734SSukumar Swaminathan static void
3300*82527734SSukumar Swaminathan emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
3301*82527734SSukumar Swaminathan {
3302*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3303*82527734SSukumar Swaminathan 	CQE_ASYNC_FCOE_t *fcoe;
3304*82527734SSukumar Swaminathan 
3305*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3306*82527734SSukumar Swaminathan 	    "CQ ENTRY: process async event %d stat %d tag %d",
3307*82527734SSukumar Swaminathan 	    cqe->event_code, cqe->link_status, cqe->event_tag);
3308*82527734SSukumar Swaminathan 
3309*82527734SSukumar Swaminathan 	hba->link_event_tag = cqe->event_tag;
3310*82527734SSukumar Swaminathan 	switch (cqe->event_code) {
3311*82527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_LINK_STATE:
3312*82527734SSukumar Swaminathan 		switch (cqe->link_status) {
3313*82527734SSukumar Swaminathan 		case ASYNC_EVENT_PHYS_LINK_UP:
3314*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3315*82527734SSukumar Swaminathan 			    "Physical link up received");
3316*82527734SSukumar Swaminathan 			break;
3317*82527734SSukumar Swaminathan 
3318*82527734SSukumar Swaminathan 		case ASYNC_EVENT_PHYS_LINK_DOWN:
3319*82527734SSukumar Swaminathan 		case ASYNC_EVENT_LOGICAL_LINK_DOWN:
3320*82527734SSukumar Swaminathan 			if (hba->state > FC_LINK_DOWN) {
3321*82527734SSukumar Swaminathan 				(void) emlxs_fcf_unbind(hba,
3322*82527734SSukumar Swaminathan 				    MAX_FCFCONNECTLIST_ENTRIES);
3323*82527734SSukumar Swaminathan 			}
3324*82527734SSukumar Swaminathan 			/* Log the link event */
3325*82527734SSukumar Swaminathan 			emlxs_log_link_event(port);
3326*82527734SSukumar Swaminathan 			break;
3327*82527734SSukumar Swaminathan 
3328*82527734SSukumar Swaminathan 		case ASYNC_EVENT_LOGICAL_LINK_UP:
3329*82527734SSukumar Swaminathan 			/* If link not already up then declare it up now */
3330*82527734SSukumar Swaminathan 			if (hba->state < FC_LINK_UP) {
3331*82527734SSukumar Swaminathan 				if (cqe->port_speed == PHY_1GHZ_LINK) {
3332*82527734SSukumar Swaminathan 					hba->linkspeed = LA_1GHZ_LINK;
3333*82527734SSukumar Swaminathan 				} else {
3334*82527734SSukumar Swaminathan 					hba->linkspeed = LA_10GHZ_LINK;
3335*82527734SSukumar Swaminathan 				}
3336*82527734SSukumar Swaminathan 				hba->topology = TOPOLOGY_PT_PT;
3337*82527734SSukumar Swaminathan 
3338*82527734SSukumar Swaminathan 				/*
3339*82527734SSukumar Swaminathan 				 * This link is not really up till we have
3340*82527734SSukumar Swaminathan 				 * a valid FCF.
3341*82527734SSukumar Swaminathan 				 */
3342*82527734SSukumar Swaminathan 				(void) emlxs_fcf_bind(hba);
3343*82527734SSukumar Swaminathan 			}
3344*82527734SSukumar Swaminathan 			/* Log the link event */
3345*82527734SSukumar Swaminathan 			emlxs_log_link_event(port);
3346*82527734SSukumar Swaminathan 			break;
3347*82527734SSukumar Swaminathan 		}
3348*82527734SSukumar Swaminathan 		break;
3349*82527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_FCOE_FIP:
3350*82527734SSukumar Swaminathan 		fcoe = (CQE_ASYNC_FCOE_t *)cqe;
3351*82527734SSukumar Swaminathan 		switch (fcoe->evt_type) {
3352*82527734SSukumar Swaminathan 		case ASYNC_EVENT_NEW_FCF_DISC:
3353*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3354*82527734SSukumar Swaminathan 			    "FCOE Async Event New FCF %d:%d: received ",
3355*82527734SSukumar Swaminathan 			    fcoe->ref_index, fcoe->fcf_count);
3356*82527734SSukumar Swaminathan 			(void) emlxs_fcf_bind(hba);
3357*82527734SSukumar Swaminathan 			break;
3358*82527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_TABLE_FULL:
3359*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
3360*82527734SSukumar Swaminathan 			    "FCOE Async Event FCF Table Full %d:%d: received ",
3361*82527734SSukumar Swaminathan 			    fcoe->ref_index, fcoe->fcf_count);
3362*82527734SSukumar Swaminathan 			break;
3363*82527734SSukumar Swaminathan 		case ASYNC_EVENT_FCF_DEAD:
3364*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3365*82527734SSukumar Swaminathan 			    "FCOE Async Event FCF Disappeared %d:%d: received ",
3366*82527734SSukumar Swaminathan 			    fcoe->ref_index, fcoe->fcf_count);
3367*82527734SSukumar Swaminathan 			(void) emlxs_reset_link(hba, 1, 0);
3368*82527734SSukumar Swaminathan 			break;
3369*82527734SSukumar Swaminathan 		case ASYNC_EVENT_VIRT_LINK_CLEAR:
3370*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3371*82527734SSukumar Swaminathan 			    "FCOE Async Event VLINK CLEAR %d: received ",
3372*82527734SSukumar Swaminathan 			    fcoe->ref_index);
3373*82527734SSukumar Swaminathan 			if (fcoe->ref_index == 0) {
3374*82527734SSukumar Swaminathan 				/*
3375*82527734SSukumar Swaminathan 				 * Bounce the link to force rediscovery for
3376*82527734SSukumar Swaminathan 				 * VPI 0.  We are ignoring this event for
3377*82527734SSukumar Swaminathan 				 * all other VPIs for now.
3378*82527734SSukumar Swaminathan 				 */
3379*82527734SSukumar Swaminathan 				(void) emlxs_reset_link(hba, 1, 0);
3380*82527734SSukumar Swaminathan 			}
3381*82527734SSukumar Swaminathan 			break;
3382*82527734SSukumar Swaminathan 		}
3383*82527734SSukumar Swaminathan 		break;
3384*82527734SSukumar Swaminathan 	case ASYNC_EVENT_CODE_DCBX:
3385*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3386*82527734SSukumar Swaminathan 		    "DCBX Async Event Code %d: Not supported ",
3387*82527734SSukumar Swaminathan 		    cqe->event_code);
3388*82527734SSukumar Swaminathan 		break;
3389*82527734SSukumar Swaminathan 	default:
3390*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3391*82527734SSukumar Swaminathan 		    "Unknown Async Event Code %d", cqe->event_code);
3392*82527734SSukumar Swaminathan 		break;
3393*82527734SSukumar Swaminathan 	}
3394*82527734SSukumar Swaminathan 
3395*82527734SSukumar Swaminathan } /* emlxs_sli4_process_async_event() */
3396*82527734SSukumar Swaminathan 
3397*82527734SSukumar Swaminathan 
3398*82527734SSukumar Swaminathan /*ARGSUSED*/
3399*82527734SSukumar Swaminathan static void
3400*82527734SSukumar Swaminathan emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
3401*82527734SSukumar Swaminathan {
3402*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3403*82527734SSukumar Swaminathan 	MAILBOX4 *mb;
3404*82527734SSukumar Swaminathan 	MATCHMAP *mbox_bp;
3405*82527734SSukumar Swaminathan 	MATCHMAP *mbox_nonembed;
3406*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
3407*82527734SSukumar Swaminathan 	uint32_t size;
3408*82527734SSukumar Swaminathan 	uint32_t *iptr;
3409*82527734SSukumar Swaminathan 	int rc;
3410*82527734SSukumar Swaminathan 
3411*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3412*82527734SSukumar Swaminathan 	    "CQ ENTRY: process mbox event");
3413*82527734SSukumar Swaminathan 
3414*82527734SSukumar Swaminathan 	if (cqe->consumed && !cqe->completed) {
3415*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3416*82527734SSukumar Swaminathan 		    "CQ ENTRY: Entry comsumed but not completed");
3417*82527734SSukumar Swaminathan 		return;
3418*82527734SSukumar Swaminathan 	}
3419*82527734SSukumar Swaminathan 
3420*82527734SSukumar Swaminathan 	switch (hba->mbox_queue_flag) {
3421*82527734SSukumar Swaminathan 	case 0:
3422*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
3423*82527734SSukumar Swaminathan 		    "No mailbox active.");
3424*82527734SSukumar Swaminathan 		return;
3425*82527734SSukumar Swaminathan 
3426*82527734SSukumar Swaminathan 	case MBX_POLL:
3427*82527734SSukumar Swaminathan 
3428*82527734SSukumar Swaminathan 		/* Mark mailbox complete, this should wake up any polling */
3429*82527734SSukumar Swaminathan 		/* threads. This can happen if interrupts are enabled while */
3430*82527734SSukumar Swaminathan 		/* a polled mailbox command is outstanding. If we don't set */
3431*82527734SSukumar Swaminathan 		/* MBQ_COMPLETED here, the polling thread may wait until */
3432*82527734SSukumar Swaminathan 		/* timeout error occurs */
3433*82527734SSukumar Swaminathan 
3434*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
3435*82527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
3436*82527734SSukumar Swaminathan 		if (mbq) {
3437*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3438*82527734SSukumar Swaminathan 			    "Mailbox event. Completing Polled command.");
3439*82527734SSukumar Swaminathan 			mbq->flag |= MBQ_COMPLETED;
3440*82527734SSukumar Swaminathan 		}
3441*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
3442*82527734SSukumar Swaminathan 
3443*82527734SSukumar Swaminathan 		return;
3444*82527734SSukumar Swaminathan 
3445*82527734SSukumar Swaminathan 	case MBX_SLEEP:
3446*82527734SSukumar Swaminathan 	case MBX_NOWAIT:
3447*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
3448*82527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
3449*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
3450*82527734SSukumar Swaminathan 		mb = (MAILBOX4 *)mbq;
3451*82527734SSukumar Swaminathan 		break;
3452*82527734SSukumar Swaminathan 
3453*82527734SSukumar Swaminathan 	default:
3454*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
3455*82527734SSukumar Swaminathan 		    "Invalid Mailbox flag (%x).");
3456*82527734SSukumar Swaminathan 		return;
3457*82527734SSukumar Swaminathan 	}
3458*82527734SSukumar Swaminathan 
3459*82527734SSukumar Swaminathan 	/* Now that we are the owner, DMA Sync entire MQ if needed */
3460*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
3461*82527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORDEV);
3462*82527734SSukumar Swaminathan 
3463*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
3464*82527734SSukumar Swaminathan 	    MAILBOX_CMD_SLI4_BSIZE);
3465*82527734SSukumar Swaminathan 
3466*82527734SSukumar Swaminathan 	emlxs_data_dump(hba, "MBOX CMP", (uint32_t *)hba->mbox_mqe, 12, 0);
3467*82527734SSukumar Swaminathan 
3468*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3469*82527734SSukumar Swaminathan 	    "Mbox cmpl: %x cmd: %x", mb->mbxStatus, mb->mbxCommand);
3470*82527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_SLI_CONFIG) {
3471*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3472*82527734SSukumar Swaminathan 		    "Mbox sge_cnt: %d length: %d embed: %d",
3473*82527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.sge_cnt,
3474*82527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.payload_length,
3475*82527734SSukumar Swaminathan 		    mb->un.varSLIConfig.be.embedded);
3476*82527734SSukumar Swaminathan 	}
3477*82527734SSukumar Swaminathan 
3478*82527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
3479*82527734SSukumar Swaminathan 	if (mbq->bp) {
3480*82527734SSukumar Swaminathan 		mbox_bp = (MATCHMAP *)mbq->bp;
3481*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
3482*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
3483*82527734SSukumar Swaminathan 	}
3484*82527734SSukumar Swaminathan 
3485*82527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
3486*82527734SSukumar Swaminathan 	if (mbq->nonembed) {
3487*82527734SSukumar Swaminathan 		mbox_nonembed = (MATCHMAP *)mbq->nonembed;
3488*82527734SSukumar Swaminathan 		size = mbox_nonembed->size;
3489*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
3490*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
3491*82527734SSukumar Swaminathan 		iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
3492*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
3493*82527734SSukumar Swaminathan 
3494*82527734SSukumar Swaminathan emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0);
3495*82527734SSukumar Swaminathan 	}
3496*82527734SSukumar Swaminathan 
3497*82527734SSukumar Swaminathan 	/* Mailbox has been completely received at this point */
3498*82527734SSukumar Swaminathan 
3499*82527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_HEARTBEAT) {
3500*82527734SSukumar Swaminathan 		hba->heartbeat_active = 0;
3501*82527734SSukumar Swaminathan 		goto done;
3502*82527734SSukumar Swaminathan 	}
3503*82527734SSukumar Swaminathan 
3504*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag == MBX_SLEEP) {
3505*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
3506*82527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3507*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3508*82527734SSukumar Swaminathan 			    "Received.  %s: status=%x Sleep.",
3509*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
3510*82527734SSukumar Swaminathan 			    mb->mbxStatus);
3511*82527734SSukumar Swaminathan 		}
3512*82527734SSukumar Swaminathan 	} else {
3513*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD
3514*82527734SSukumar Swaminathan 		    /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3515*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3516*82527734SSukumar Swaminathan 			    "Completed. %s: status=%x",
3517*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
3518*82527734SSukumar Swaminathan 			    mb->mbxStatus);
3519*82527734SSukumar Swaminathan 		}
3520*82527734SSukumar Swaminathan 	}
3521*82527734SSukumar Swaminathan 
3522*82527734SSukumar Swaminathan 	/* Filter out passthru mailbox */
3523*82527734SSukumar Swaminathan 	if (mbq->flag & MBQ_PASSTHRU) {
3524*82527734SSukumar Swaminathan 		goto done;
3525*82527734SSukumar Swaminathan 	}
3526*82527734SSukumar Swaminathan 
3527*82527734SSukumar Swaminathan 	if (mb->mbxStatus) {
3528*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3529*82527734SSukumar Swaminathan 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
3530*82527734SSukumar Swaminathan 		    (uint32_t)mb->mbxStatus);
3531*82527734SSukumar Swaminathan 	}
3532*82527734SSukumar Swaminathan 
3533*82527734SSukumar Swaminathan 	if (mbq->mbox_cmpl) {
3534*82527734SSukumar Swaminathan 		rc = (mbq->mbox_cmpl)(hba, mbq);
3535*82527734SSukumar Swaminathan 
3536*82527734SSukumar Swaminathan 		/* If mbox was retried, return immediately */
3537*82527734SSukumar Swaminathan 		if (rc) {
3538*82527734SSukumar Swaminathan 			return;
3539*82527734SSukumar Swaminathan 		}
3540*82527734SSukumar Swaminathan 	}
3541*82527734SSukumar Swaminathan 
3542*82527734SSukumar Swaminathan done:
3543*82527734SSukumar Swaminathan 
3544*82527734SSukumar Swaminathan 	/* Clean up the mailbox area */
3545*82527734SSukumar Swaminathan 	emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
3546*82527734SSukumar Swaminathan 
3547*82527734SSukumar Swaminathan 	/* Attempt to send pending mailboxes */
3548*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
3549*82527734SSukumar Swaminathan 	if (mbq) {
3550*82527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
3551*82527734SSukumar Swaminathan 		rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
3552*82527734SSukumar Swaminathan 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
3553*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3554*82527734SSukumar Swaminathan 		}
3555*82527734SSukumar Swaminathan 	}
3556*82527734SSukumar Swaminathan 	return;
3557*82527734SSukumar Swaminathan 
3558*82527734SSukumar Swaminathan } /* emlxs_sli4_process_mbox_event() */
3559*82527734SSukumar Swaminathan 
3560*82527734SSukumar Swaminathan 
3561*82527734SSukumar Swaminathan static void
3562*82527734SSukumar Swaminathan emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
3563*82527734SSukumar Swaminathan {
3564*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3565*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3566*82527734SSukumar Swaminathan 	IOCB *iocb;
3567*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
3568*82527734SSukumar Swaminathan 
3569*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3570*82527734SSukumar Swaminathan 	wqe = &iocbq->wqe;
3571*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3572*82527734SSukumar Swaminathan 
3573*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
3574*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3575*82527734SSukumar Swaminathan 	    "CQE to IOCB: cmd:x%x tag:x%x xri:x%x", wqe->Command,
3576*82527734SSukumar Swaminathan 	    wqe->RequestTag, wqe->XRITag);
3577*82527734SSukumar Swaminathan #endif
3578*82527734SSukumar Swaminathan 
3579*82527734SSukumar Swaminathan 	iocb->ULPSTATUS = cqe->Status;
3580*82527734SSukumar Swaminathan 	iocb->un.ulpWord[4] = cqe->Parameter;
3581*82527734SSukumar Swaminathan 	iocb->ULPIOTAG = cqe->RequestTag;
3582*82527734SSukumar Swaminathan 	iocb->ULPCONTEXT = wqe->XRITag;
3583*82527734SSukumar Swaminathan 
3584*82527734SSukumar Swaminathan 	switch (wqe->Command) {
3585*82527734SSukumar Swaminathan 
3586*82527734SSukumar Swaminathan 	case CMD_FCP_ICMND64_CR:
3587*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
3588*82527734SSukumar Swaminathan 		break;
3589*82527734SSukumar Swaminathan 
3590*82527734SSukumar Swaminathan 	case CMD_FCP_IREAD64_CR:
3591*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
3592*82527734SSukumar Swaminathan 		iocb->ULPPU = PARM_READ_CHECK;
3593*82527734SSukumar Swaminathan 		if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
3594*82527734SSukumar Swaminathan 			iocb->un.fcpi64.fcpi_parm =
3595*82527734SSukumar Swaminathan 			    wqe->un.FcpCmd.TotalTransferCount -
3596*82527734SSukumar Swaminathan 			    cqe->CmdSpecific;
3597*82527734SSukumar Swaminathan 		}
3598*82527734SSukumar Swaminathan 		break;
3599*82527734SSukumar Swaminathan 
3600*82527734SSukumar Swaminathan 	case CMD_FCP_IWRITE64_CR:
3601*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
3602*82527734SSukumar Swaminathan 		break;
3603*82527734SSukumar Swaminathan 
3604*82527734SSukumar Swaminathan 	case CMD_ELS_REQUEST64_CR:
3605*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
3606*82527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
3607*82527734SSukumar Swaminathan 		if (iocb->ULPSTATUS == 0) {
3608*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
3609*82527734SSukumar Swaminathan 		}
3610*82527734SSukumar Swaminathan 		break;
3611*82527734SSukumar Swaminathan 
3612*82527734SSukumar Swaminathan 	case CMD_GEN_REQUEST64_CR:
3613*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
3614*82527734SSukumar Swaminathan 		iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
3615*82527734SSukumar Swaminathan 		break;
3616*82527734SSukumar Swaminathan 
3617*82527734SSukumar Swaminathan 	case CMD_XMIT_SEQUENCE64_CR:
3618*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
3619*82527734SSukumar Swaminathan 		break;
3620*82527734SSukumar Swaminathan 
3621*82527734SSukumar Swaminathan 	default:
3622*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = wqe->Command;
3623*82527734SSukumar Swaminathan 
3624*82527734SSukumar Swaminathan 	}
3625*82527734SSukumar Swaminathan 
3626*82527734SSukumar Swaminathan } /* emlxs_CQE_to_IOCB() */
3627*82527734SSukumar Swaminathan 
3628*82527734SSukumar Swaminathan 
3629*82527734SSukumar Swaminathan /*ARGSUSED*/
3630*82527734SSukumar Swaminathan static void
3631*82527734SSukumar Swaminathan emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
3632*82527734SSukumar Swaminathan {
3633*82527734SSukumar Swaminathan 	CHANNEL *cp;
3634*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
3635*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3636*82527734SSukumar Swaminathan 	uint32_t i;
3637*82527734SSukumar Swaminathan 	uint32_t trigger;
3638*82527734SSukumar Swaminathan 	CQE_CmplWQ_t cqe;
3639*82527734SSukumar Swaminathan 
3640*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
3641*82527734SSukumar Swaminathan 	for (i = 0; i < hba->max_iotag; i++) {
3642*82527734SSukumar Swaminathan 		sbp = hba->fc_table[i];
3643*82527734SSukumar Swaminathan 		if (sbp == NULL || sbp == STALE_PACKET) {
3644*82527734SSukumar Swaminathan 			continue;
3645*82527734SSukumar Swaminathan 		}
3646*82527734SSukumar Swaminathan 		hba->fc_table[i] = NULL;
3647*82527734SSukumar Swaminathan 		hba->io_count--;
3648*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
3649*82527734SSukumar Swaminathan 
3650*82527734SSukumar Swaminathan 		cp = sbp->channel;
3651*82527734SSukumar Swaminathan 		bzero(&cqe, sizeof (CQE_CmplWQ_t));
3652*82527734SSukumar Swaminathan 		cqe.RequestTag = i;
3653*82527734SSukumar Swaminathan 		cqe.Status = IOSTAT_LOCAL_REJECT;
3654*82527734SSukumar Swaminathan 		cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
3655*82527734SSukumar Swaminathan 
3656*82527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
3657*82527734SSukumar Swaminathan 
3658*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
3659*82527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
3660*82527734SSukumar Swaminathan 		if (sbp->fct_cmd) {
3661*82527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
3662*82527734SSukumar Swaminathan 			    EMLXS_FCT_IOCB_COMPLETE);
3663*82527734SSukumar Swaminathan 		}
3664*82527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
3665*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3666*82527734SSukumar Swaminathan 
3667*82527734SSukumar Swaminathan 		atomic_add_32(&hba->io_active, -1);
3668*82527734SSukumar Swaminathan 
3669*82527734SSukumar Swaminathan 		/* Copy entry to sbp's iocbq */
3670*82527734SSukumar Swaminathan 		iocbq = &sbp->iocbq;
3671*82527734SSukumar Swaminathan 		emlxs_CQE_to_IOCB(hba, &cqe, sbp);
3672*82527734SSukumar Swaminathan 
3673*82527734SSukumar Swaminathan 		iocbq->next = NULL;
3674*82527734SSukumar Swaminathan 
3675*82527734SSukumar Swaminathan 		sbp->xp->state &= ~RESOURCE_XRI_PENDING_IO;
3676*82527734SSukumar Swaminathan 
3677*82527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
3678*82527734SSukumar Swaminathan 		emlxs_sli4_free_xri(hba, sbp, sbp->xp);
3679*82527734SSukumar Swaminathan 
3680*82527734SSukumar Swaminathan 		if (!(sbp->pkt_flags &
3681*82527734SSukumar Swaminathan 		    (PACKET_POLLED | PACKET_ALLOCATED))) {
3682*82527734SSukumar Swaminathan 			/* Add the IOCB to the channel list */
3683*82527734SSukumar Swaminathan 			mutex_enter(&cp->rsp_lock);
3684*82527734SSukumar Swaminathan 			if (cp->rsp_head == NULL) {
3685*82527734SSukumar Swaminathan 				cp->rsp_head = iocbq;
3686*82527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
3687*82527734SSukumar Swaminathan 			} else {
3688*82527734SSukumar Swaminathan 				cp->rsp_tail->next = iocbq;
3689*82527734SSukumar Swaminathan 				cp->rsp_tail = iocbq;
3690*82527734SSukumar Swaminathan 			}
3691*82527734SSukumar Swaminathan 			mutex_exit(&cp->rsp_lock);
3692*82527734SSukumar Swaminathan 			trigger = 1;
3693*82527734SSukumar Swaminathan 		} else {
3694*82527734SSukumar Swaminathan 			emlxs_proc_channel_event(hba, cp, iocbq);
3695*82527734SSukumar Swaminathan 		}
3696*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_FCTAB_LOCK);
3697*82527734SSukumar Swaminathan 	}
3698*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
3699*82527734SSukumar Swaminathan 
3700*82527734SSukumar Swaminathan 	if (trigger) {
3701*82527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
3702*82527734SSukumar Swaminathan 			cp = &hba->chan[i];
3703*82527734SSukumar Swaminathan 			if (cp->rsp_head != NULL) {
3704*82527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
3705*82527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
3706*82527734SSukumar Swaminathan 			}
3707*82527734SSukumar Swaminathan 		}
3708*82527734SSukumar Swaminathan 	}
3709*82527734SSukumar Swaminathan 
3710*82527734SSukumar Swaminathan } /* emlxs_sli4_hba_flush_chipq() */
3711*82527734SSukumar Swaminathan 
3712*82527734SSukumar Swaminathan 
3713*82527734SSukumar Swaminathan /*ARGSUSED*/
3714*82527734SSukumar Swaminathan static void
3715*82527734SSukumar Swaminathan emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
3716*82527734SSukumar Swaminathan     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
3717*82527734SSukumar Swaminathan {
3718*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3719*82527734SSukumar Swaminathan 	CHANNEL *cp;
3720*82527734SSukumar Swaminathan 	uint16_t request_tag;
3721*82527734SSukumar Swaminathan 
3722*82527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
3723*82527734SSukumar Swaminathan 
3724*82527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
3725*82527734SSukumar Swaminathan 	cp = cq->channelp;
3726*82527734SSukumar Swaminathan 
3727*82527734SSukumar Swaminathan 	cp->hbaCmplCmd++;
3728*82527734SSukumar Swaminathan 
3729*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3730*82527734SSukumar Swaminathan 	    "CQ ENTRY: OOR Cmpl: tag=%x", request_tag);
3731*82527734SSukumar Swaminathan 
3732*82527734SSukumar Swaminathan } /* emlxs_sli4_process_oor_wqe_cmpl() */
3733*82527734SSukumar Swaminathan 
3734*82527734SSukumar Swaminathan 
3735*82527734SSukumar Swaminathan /*ARGSUSED*/
3736*82527734SSukumar Swaminathan static void
3737*82527734SSukumar Swaminathan emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
3738*82527734SSukumar Swaminathan {
3739*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3740*82527734SSukumar Swaminathan 	CHANNEL *cp;
3741*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
3742*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3743*82527734SSukumar Swaminathan 	uint16_t request_tag;
3744*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
3745*82527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd;
3746*82527734SSukumar Swaminathan 	emlxs_buf_t *cmd_sbp;
3747*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3748*82527734SSukumar Swaminathan 
3749*82527734SSukumar Swaminathan 	request_tag = cqe->RequestTag;
3750*82527734SSukumar Swaminathan 
3751*82527734SSukumar Swaminathan 	/* 1 to 1 mapping between CQ and channel */
3752*82527734SSukumar Swaminathan 	cp = cq->channelp;
3753*82527734SSukumar Swaminathan 
3754*82527734SSukumar Swaminathan 	sbp = hba->fc_table[request_tag];
3755*82527734SSukumar Swaminathan 	atomic_add_32(&hba->io_active, -1);
3756*82527734SSukumar Swaminathan 
3757*82527734SSukumar Swaminathan 	if (sbp == STALE_PACKET) {
3758*82527734SSukumar Swaminathan 		cp->hbaCmplCmd_sbp++;
3759*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3760*82527734SSukumar Swaminathan 		    "CQ ENTRY: Stale sbp. tag=%x. Dropping...", request_tag);
3761*82527734SSukumar Swaminathan 		return;
3762*82527734SSukumar Swaminathan 	}
3763*82527734SSukumar Swaminathan 
3764*82527734SSukumar Swaminathan 	if (!sbp || !(sbp->xp)) {
3765*82527734SSukumar Swaminathan 		cp->hbaCmplCmd++;
3766*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3767*82527734SSukumar Swaminathan 		    "CQ ENTRY: NULL sbp %p. tag=%x. Dropping...",
3768*82527734SSukumar Swaminathan 		    sbp, request_tag);
3769*82527734SSukumar Swaminathan 		return;
3770*82527734SSukumar Swaminathan 	}
3771*82527734SSukumar Swaminathan 
3772*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
3773*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3774*82527734SSukumar Swaminathan 	    "CQ ENTRY: process wqe compl");
3775*82527734SSukumar Swaminathan #endif
3776*82527734SSukumar Swaminathan 
3777*82527734SSukumar Swaminathan 	cp->hbaCmplCmd_sbp++;
3778*82527734SSukumar Swaminathan 
3779*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
3780*82527734SSukumar Swaminathan 	fct_cmd = sbp->fct_cmd;
3781*82527734SSukumar Swaminathan 	if (fct_cmd) {
3782*82527734SSukumar Swaminathan 		cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3783*82527734SSukumar Swaminathan 		mutex_enter(&cmd_sbp->fct_mtx);
3784*82527734SSukumar Swaminathan 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
3785*82527734SSukumar Swaminathan 		mutex_exit(&cmd_sbp->fct_mtx);
3786*82527734SSukumar Swaminathan 	}
3787*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3788*82527734SSukumar Swaminathan 
3789*82527734SSukumar Swaminathan 	/* Copy entry to sbp's iocbq */
3790*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3791*82527734SSukumar Swaminathan 	emlxs_CQE_to_IOCB(hba, cqe, sbp);
3792*82527734SSukumar Swaminathan 
3793*82527734SSukumar Swaminathan 	iocbq->next = NULL;
3794*82527734SSukumar Swaminathan 
3795*82527734SSukumar Swaminathan 	sbp->xp->state &= ~RESOURCE_XRI_PENDING_IO;
3796*82527734SSukumar Swaminathan 	if (cqe->XB) {
3797*82527734SSukumar Swaminathan 		/* Mark exchange as ABORT in progress */
3798*82527734SSukumar Swaminathan 		sbp->xp->state |= RESOURCE_XRI_ABORT_INP;
3799*82527734SSukumar Swaminathan 
3800*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3801*82527734SSukumar Swaminathan 		    "CQ ENTRY: ABORT INP: tag=%x xri=%x", request_tag,
3802*82527734SSukumar Swaminathan 		    sbp->xp->XRI);
3803*82527734SSukumar Swaminathan 
3804*82527734SSukumar Swaminathan 		emlxs_sli4_free_xri(hba, sbp, 0);
3805*82527734SSukumar Swaminathan 	} else {
3806*82527734SSukumar Swaminathan 		/* Exchange is no longer busy on-chip, free it */
3807*82527734SSukumar Swaminathan 		emlxs_sli4_free_xri(hba, sbp, sbp->xp);
3808*82527734SSukumar Swaminathan 	}
3809*82527734SSukumar Swaminathan 
3810*82527734SSukumar Swaminathan 	/*
3811*82527734SSukumar Swaminathan 	 * If this is NOT a polled command completion
3812*82527734SSukumar Swaminathan 	 * or a driver allocated pkt, then defer pkt
3813*82527734SSukumar Swaminathan 	 * completion.
3814*82527734SSukumar Swaminathan 	 */
3815*82527734SSukumar Swaminathan 	if (!(sbp->pkt_flags &
3816*82527734SSukumar Swaminathan 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
3817*82527734SSukumar Swaminathan 		/* Add the IOCB to the channel list */
3818*82527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
3819*82527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
3820*82527734SSukumar Swaminathan 			cp->rsp_head = iocbq;
3821*82527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
3822*82527734SSukumar Swaminathan 		} else {
3823*82527734SSukumar Swaminathan 			cp->rsp_tail->next = iocbq;
3824*82527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
3825*82527734SSukumar Swaminathan 		}
3826*82527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
3827*82527734SSukumar Swaminathan 
3828*82527734SSukumar Swaminathan 		/* Delay triggering thread till end of ISR */
3829*82527734SSukumar Swaminathan 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
3830*82527734SSukumar Swaminathan 	} else {
3831*82527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
3832*82527734SSukumar Swaminathan 	}
3833*82527734SSukumar Swaminathan 
3834*82527734SSukumar Swaminathan } /* emlxs_sli4_process_wqe_cmpl() */
3835*82527734SSukumar Swaminathan 
3836*82527734SSukumar Swaminathan 
3837*82527734SSukumar Swaminathan /*ARGSUSED*/
3838*82527734SSukumar Swaminathan static void
3839*82527734SSukumar Swaminathan emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
3840*82527734SSukumar Swaminathan     CQE_RelWQ_t *cqe)
3841*82527734SSukumar Swaminathan {
3842*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3843*82527734SSukumar Swaminathan 	WQ_DESC_t *wq;
3844*82527734SSukumar Swaminathan 	CHANNEL *cp;
3845*82527734SSukumar Swaminathan 	uint32_t i;
3846*82527734SSukumar Swaminathan 
3847*82527734SSukumar Swaminathan 	i = cqe->WQid;
3848*82527734SSukumar Swaminathan 	wq = &hba->sli.sli4.wq[hba->sli.sli4.wq_map[i]];
3849*82527734SSukumar Swaminathan 
3850*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
3851*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3852*82527734SSukumar Swaminathan 	    "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
3853*82527734SSukumar Swaminathan 	    cqe->WQindex);
3854*82527734SSukumar Swaminathan #endif
3855*82527734SSukumar Swaminathan 
3856*82527734SSukumar Swaminathan 	wq->port_index = cqe->WQindex;
3857*82527734SSukumar Swaminathan 
3858*82527734SSukumar Swaminathan 	/* Cmd ring may be available. Try sending more iocbs */
3859*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
3860*82527734SSukumar Swaminathan 		cp = &hba->chan[i];
3861*82527734SSukumar Swaminathan 		if (wq == (WQ_DESC_t *)cp->iopath) {
3862*82527734SSukumar Swaminathan 			emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
3863*82527734SSukumar Swaminathan 		}
3864*82527734SSukumar Swaminathan 	}
3865*82527734SSukumar Swaminathan 
3866*82527734SSukumar Swaminathan } /* emlxs_sli4_process_release_wqe() */
3867*82527734SSukumar Swaminathan 
3868*82527734SSukumar Swaminathan 
3869*82527734SSukumar Swaminathan /*ARGSUSED*/
3870*82527734SSukumar Swaminathan emlxs_iocbq_t *
3871*82527734SSukumar Swaminathan emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
3872*82527734SSukumar Swaminathan {
3873*82527734SSukumar Swaminathan 	emlxs_queue_t *q;
3874*82527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq;
3875*82527734SSukumar Swaminathan 	emlxs_iocbq_t *prev;
3876*82527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr2;
3877*82527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
3878*82527734SSukumar Swaminathan 
3879*82527734SSukumar Swaminathan 	switch (fchdr->type) {
3880*82527734SSukumar Swaminathan 	case 1: /* ELS */
3881*82527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
3882*82527734SSukumar Swaminathan 		break;
3883*82527734SSukumar Swaminathan 	case 0x20: /* CT */
3884*82527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
3885*82527734SSukumar Swaminathan 		break;
3886*82527734SSukumar Swaminathan 	default:
3887*82527734SSukumar Swaminathan 		return (NULL);
3888*82527734SSukumar Swaminathan 	}
3889*82527734SSukumar Swaminathan 
3890*82527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
3891*82527734SSukumar Swaminathan 
3892*82527734SSukumar Swaminathan 	q = &rxq->active;
3893*82527734SSukumar Swaminathan 	iocbq  = (emlxs_iocbq_t *)q->q_first;
3894*82527734SSukumar Swaminathan 	prev = NULL;
3895*82527734SSukumar Swaminathan 
3896*82527734SSukumar Swaminathan 	while (iocbq) {
3897*82527734SSukumar Swaminathan 
3898*82527734SSukumar Swaminathan 		fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
3899*82527734SSukumar Swaminathan 
3900*82527734SSukumar Swaminathan 		if ((fchdr2->s_id == fchdr->s_id) &&
3901*82527734SSukumar Swaminathan 		    (fchdr2->ox_id == fchdr->ox_id) &&
3902*82527734SSukumar Swaminathan 		    (fchdr2->seq_id == fchdr->seq_id)) {
3903*82527734SSukumar Swaminathan 			/* Remove iocbq */
3904*82527734SSukumar Swaminathan 			if (prev) {
3905*82527734SSukumar Swaminathan 				prev->next = iocbq->next;
3906*82527734SSukumar Swaminathan 			}
3907*82527734SSukumar Swaminathan 			if (q->q_first == (uint8_t *)iocbq) {
3908*82527734SSukumar Swaminathan 				q->q_first = (uint8_t *)iocbq->next;
3909*82527734SSukumar Swaminathan 			}
3910*82527734SSukumar Swaminathan 			if (q->q_last == (uint8_t *)iocbq) {
3911*82527734SSukumar Swaminathan 				q->q_last = (uint8_t *)prev;
3912*82527734SSukumar Swaminathan 			}
3913*82527734SSukumar Swaminathan 			q->q_cnt--;
3914*82527734SSukumar Swaminathan 
3915*82527734SSukumar Swaminathan 			break;
3916*82527734SSukumar Swaminathan 		}
3917*82527734SSukumar Swaminathan 
3918*82527734SSukumar Swaminathan 		prev  = iocbq;
3919*82527734SSukumar Swaminathan 		iocbq = iocbq->next;
3920*82527734SSukumar Swaminathan 	}
3921*82527734SSukumar Swaminathan 
3922*82527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
3923*82527734SSukumar Swaminathan 
3924*82527734SSukumar Swaminathan 	return (iocbq);
3925*82527734SSukumar Swaminathan 
3926*82527734SSukumar Swaminathan } /* emlxs_sli4_rxq_get() */
3927*82527734SSukumar Swaminathan 
3928*82527734SSukumar Swaminathan 
3929*82527734SSukumar Swaminathan /*ARGSUSED*/
3930*82527734SSukumar Swaminathan void
3931*82527734SSukumar Swaminathan emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
3932*82527734SSukumar Swaminathan {
3933*82527734SSukumar Swaminathan 	emlxs_queue_t *q;
3934*82527734SSukumar Swaminathan 	fc_frame_hdr_t *fchdr;
3935*82527734SSukumar Swaminathan 	RXQ_DESC_t *rxq;
3936*82527734SSukumar Swaminathan 
3937*82527734SSukumar Swaminathan 	fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
3938*82527734SSukumar Swaminathan 
3939*82527734SSukumar Swaminathan 	switch (fchdr->type) {
3940*82527734SSukumar Swaminathan 	case 1: /* ELS */
3941*82527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
3942*82527734SSukumar Swaminathan 		break;
3943*82527734SSukumar Swaminathan 	case 0x20: /* CT */
3944*82527734SSukumar Swaminathan 		rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
3945*82527734SSukumar Swaminathan 		break;
3946*82527734SSukumar Swaminathan 	default:
3947*82527734SSukumar Swaminathan 		return;
3948*82527734SSukumar Swaminathan 	}
3949*82527734SSukumar Swaminathan 
3950*82527734SSukumar Swaminathan 	mutex_enter(&rxq->lock);
3951*82527734SSukumar Swaminathan 
3952*82527734SSukumar Swaminathan 	q = &rxq->active;
3953*82527734SSukumar Swaminathan 
3954*82527734SSukumar Swaminathan 	if (q->q_last) {
3955*82527734SSukumar Swaminathan 		((emlxs_iocbq_t *)q->q_last)->next = iocbq;
3956*82527734SSukumar Swaminathan 		q->q_cnt++;
3957*82527734SSukumar Swaminathan 	} else {
3958*82527734SSukumar Swaminathan 		q->q_first = (uint8_t *)iocbq;
3959*82527734SSukumar Swaminathan 		q->q_cnt = 1;
3960*82527734SSukumar Swaminathan 	}
3961*82527734SSukumar Swaminathan 
3962*82527734SSukumar Swaminathan 	q->q_last = (uint8_t *)iocbq;
3963*82527734SSukumar Swaminathan 	iocbq->next = NULL;
3964*82527734SSukumar Swaminathan 
3965*82527734SSukumar Swaminathan 	mutex_exit(&rxq->lock);
3966*82527734SSukumar Swaminathan 
3967*82527734SSukumar Swaminathan 	return;
3968*82527734SSukumar Swaminathan 
3969*82527734SSukumar Swaminathan } /* emlxs_sli4_rxq_put() */
3970*82527734SSukumar Swaminathan 
3971*82527734SSukumar Swaminathan 
3972*82527734SSukumar Swaminathan static void
3973*82527734SSukumar Swaminathan emlxs_sli4_rq_post(emlxs_hba_t *hba, uint16_t rqid)
3974*82527734SSukumar Swaminathan {
3975*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3976*82527734SSukumar Swaminathan 	emlxs_rqdbu_t rqdb;
3977*82527734SSukumar Swaminathan 
3978*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3979*82527734SSukumar Swaminathan 	    "RQ POST: rqid=%d count=1", rqid);
3980*82527734SSukumar Swaminathan 
3981*82527734SSukumar Swaminathan 	/* Ring the RQ doorbell once to repost the RQ buffer */
3982*82527734SSukumar Swaminathan 	rqdb.word = 0;
3983*82527734SSukumar Swaminathan 	rqdb.db.Qid = rqid;
3984*82527734SSukumar Swaminathan 	rqdb.db.NumPosted = 1;
3985*82527734SSukumar Swaminathan 
3986*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
3987*82527734SSukumar Swaminathan 
3988*82527734SSukumar Swaminathan } /* emlxs_sli4_rq_post() */
3989*82527734SSukumar Swaminathan 
3990*82527734SSukumar Swaminathan 
3991*82527734SSukumar Swaminathan /*ARGSUSED*/
3992*82527734SSukumar Swaminathan static void
3993*82527734SSukumar Swaminathan emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
3994*82527734SSukumar Swaminathan     CQE_UnsolRcv_t *cqe)
3995*82527734SSukumar Swaminathan {
3996*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3997*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
3998*82527734SSukumar Swaminathan 	RQ_DESC_t *hdr_rq;
3999*82527734SSukumar Swaminathan 	RQ_DESC_t *data_rq;
4000*82527734SSukumar Swaminathan 	MATCHMAP *hdr_mp;
4001*82527734SSukumar Swaminathan 	MATCHMAP *data_mp;
4002*82527734SSukumar Swaminathan 	MATCHMAP *seq_mp;
4003*82527734SSukumar Swaminathan 	uint32_t *data;
4004*82527734SSukumar Swaminathan 	fc_frame_hdr_t fchdr;
4005*82527734SSukumar Swaminathan 	uint32_t hdr_rqi;
4006*82527734SSukumar Swaminathan 	uint32_t host_index;
4007*82527734SSukumar Swaminathan 	emlxs_iocbq_t *iocbq = NULL;
4008*82527734SSukumar Swaminathan 	emlxs_iocb_t *iocb;
4009*82527734SSukumar Swaminathan 	emlxs_node_t *node;
4010*82527734SSukumar Swaminathan 	uint32_t i;
4011*82527734SSukumar Swaminathan 	uint32_t seq_len;
4012*82527734SSukumar Swaminathan 	uint32_t seq_cnt;
4013*82527734SSukumar Swaminathan 	uint32_t buf_type;
4014*82527734SSukumar Swaminathan 	char label[32];
4015*82527734SSukumar Swaminathan 	emlxs_wqe_t *wqe;
4016*82527734SSukumar Swaminathan 	CHANNEL *cp;
4017*82527734SSukumar Swaminathan 	uint16_t iotag;
4018*82527734SSukumar Swaminathan 	XRIobj_t *xp;
4019*82527734SSukumar Swaminathan 	RPIobj_t *rp = NULL;
4020*82527734SSukumar Swaminathan 	FCFIobj_t *fp;
4021*82527734SSukumar Swaminathan 	uint32_t	cmd;
4022*82527734SSukumar Swaminathan 	uint32_t posted = 0;
4023*82527734SSukumar Swaminathan 	uint32_t abort = 1;
4024*82527734SSukumar Swaminathan 
4025*82527734SSukumar Swaminathan 	hdr_rqi = hba->sli.sli4.rq_map[cqe->RQid];
4026*82527734SSukumar Swaminathan 	hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
4027*82527734SSukumar Swaminathan 	data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
4028*82527734SSukumar Swaminathan 
4029*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4030*82527734SSukumar Swaminathan 	    "CQ ENTRY: Unsol Rcv: RQid=%d,%d index=%d status=%x " \
4031*82527734SSukumar Swaminathan 	    "hdr_size=%d data_size=%d",
4032*82527734SSukumar Swaminathan 	    cqe->RQid, hdr_rqi, hdr_rq->host_index, cqe->Status, cqe->hdr_size,
4033*82527734SSukumar Swaminathan 	    cqe->data_size);
4034*82527734SSukumar Swaminathan 
4035*82527734SSukumar Swaminathan 	/* Validate the CQE */
4036*82527734SSukumar Swaminathan 
4037*82527734SSukumar Swaminathan 	/* Check status */
4038*82527734SSukumar Swaminathan 	switch (cqe->Status) {
4039*82527734SSukumar Swaminathan 	case RQ_STATUS_SUCCESS: /* 0x10 */
4040*82527734SSukumar Swaminathan 		break;
4041*82527734SSukumar Swaminathan 
4042*82527734SSukumar Swaminathan 	case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
4043*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4044*82527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload truncated.");
4045*82527734SSukumar Swaminathan 		break;
4046*82527734SSukumar Swaminathan 
4047*82527734SSukumar Swaminathan 	case RQ_STATUS_NEED_BUFFER: /* 0x12 */
4048*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4049*82527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
4050*82527734SSukumar Swaminathan 		return;
4051*82527734SSukumar Swaminathan 
4052*82527734SSukumar Swaminathan 	case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
4053*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4054*82527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
4055*82527734SSukumar Swaminathan 		return;
4056*82527734SSukumar Swaminathan 
4057*82527734SSukumar Swaminathan 	default:
4058*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4059*82527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
4060*82527734SSukumar Swaminathan 		    cqe->Status);
4061*82527734SSukumar Swaminathan 		break;
4062*82527734SSukumar Swaminathan 	}
4063*82527734SSukumar Swaminathan 
4064*82527734SSukumar Swaminathan 	/* Make sure there is a frame header */
4065*82527734SSukumar Swaminathan 	if (cqe->hdr_size < sizeof (fc_frame_hdr_t)) {
4066*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4067*82527734SSukumar Swaminathan 		    "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
4068*82527734SSukumar Swaminathan 		return;
4069*82527734SSukumar Swaminathan 	}
4070*82527734SSukumar Swaminathan 
4071*82527734SSukumar Swaminathan 	/* Update host index */
4072*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
4073*82527734SSukumar Swaminathan 	host_index = hdr_rq->host_index;
4074*82527734SSukumar Swaminathan 	hdr_rq->host_index++;
4075*82527734SSukumar Swaminathan 	if (hdr_rq->host_index >= hdr_rq->max_index) {
4076*82527734SSukumar Swaminathan 		hdr_rq->host_index = 0;
4077*82527734SSukumar Swaminathan 	}
4078*82527734SSukumar Swaminathan 	data_rq->host_index = hdr_rq->host_index;
4079*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
4080*82527734SSukumar Swaminathan 
4081*82527734SSukumar Swaminathan 	/* Get the next header rqb */
4082*82527734SSukumar Swaminathan 	hdr_mp  = hdr_rq->rqb[host_index];
4083*82527734SSukumar Swaminathan 
4084*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, 0,
4085*82527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
4086*82527734SSukumar Swaminathan 
4087*82527734SSukumar Swaminathan 	LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
4088*82527734SSukumar Swaminathan 	    sizeof (fc_frame_hdr_t));
4089*82527734SSukumar Swaminathan 
4090*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4091*82527734SSukumar Swaminathan 	    "RQ HDR[%d]: rctl:%x type:%x " \
4092*82527734SSukumar Swaminathan 	    "sid:%x did:%x oxid:%x rxid:%x",
4093*82527734SSukumar Swaminathan 	    host_index, fchdr.r_ctl, fchdr.type,
4094*82527734SSukumar Swaminathan 	    fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
4095*82527734SSukumar Swaminathan 
4096*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4097*82527734SSukumar Swaminathan 	    "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
4098*82527734SSukumar Swaminathan 	    host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
4099*82527734SSukumar Swaminathan 	    fchdr.df_ctl, fchdr.ro);
4100*82527734SSukumar Swaminathan 
4101*82527734SSukumar Swaminathan 	/* Verify fc header type */
4102*82527734SSukumar Swaminathan 	switch (fchdr.type) {
4103*82527734SSukumar Swaminathan 	case 0: /* BLS */
4104*82527734SSukumar Swaminathan 		if (fchdr.r_ctl != 0x81) {
4105*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4106*82527734SSukumar Swaminathan 			    "RQ ENTRY: Unexpected FC rctl (0x%x) " \
4107*82527734SSukumar Swaminathan 			    "received. Dropping...",
4108*82527734SSukumar Swaminathan 			    fchdr.r_ctl);
4109*82527734SSukumar Swaminathan 
4110*82527734SSukumar Swaminathan 			goto done;
4111*82527734SSukumar Swaminathan 		}
4112*82527734SSukumar Swaminathan 
4113*82527734SSukumar Swaminathan 		/* Make sure there is no payload */
4114*82527734SSukumar Swaminathan 		if (cqe->data_size != 0) {
4115*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4116*82527734SSukumar Swaminathan 			    "RQ ENTRY: ABTS payload provided. Dropping...");
4117*82527734SSukumar Swaminathan 
4118*82527734SSukumar Swaminathan 			goto done;
4119*82527734SSukumar Swaminathan 		}
4120*82527734SSukumar Swaminathan 
4121*82527734SSukumar Swaminathan 		buf_type = 0xFFFFFFFF;
4122*82527734SSukumar Swaminathan 		(void) strcpy(label, "ABTS");
4123*82527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
4124*82527734SSukumar Swaminathan 		break;
4125*82527734SSukumar Swaminathan 
4126*82527734SSukumar Swaminathan 	case 0x01: /* ELS */
4127*82527734SSukumar Swaminathan 		/* Make sure there is a payload */
4128*82527734SSukumar Swaminathan 		if (cqe->data_size == 0) {
4129*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4130*82527734SSukumar Swaminathan 			    "RQ ENTRY: Unsol Rcv: No ELS payload provided. " \
4131*82527734SSukumar Swaminathan 			    "Dropping...");
4132*82527734SSukumar Swaminathan 
4133*82527734SSukumar Swaminathan 			goto done;
4134*82527734SSukumar Swaminathan 		}
4135*82527734SSukumar Swaminathan 
4136*82527734SSukumar Swaminathan 		buf_type = MEM_ELSBUF;
4137*82527734SSukumar Swaminathan 		(void) strcpy(label, "Unsol ELS");
4138*82527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_els];
4139*82527734SSukumar Swaminathan 		break;
4140*82527734SSukumar Swaminathan 
4141*82527734SSukumar Swaminathan 	case 0x20: /* CT */
4142*82527734SSukumar Swaminathan 		/* Make sure there is a payload */
4143*82527734SSukumar Swaminathan 		if (cqe->data_size == 0) {
4144*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4145*82527734SSukumar Swaminathan 			    "RQ ENTRY: Unsol Rcv: No CT payload provided. " \
4146*82527734SSukumar Swaminathan 			    "Dropping...");
4147*82527734SSukumar Swaminathan 
4148*82527734SSukumar Swaminathan 			goto done;
4149*82527734SSukumar Swaminathan 		}
4150*82527734SSukumar Swaminathan 
4151*82527734SSukumar Swaminathan 		buf_type = MEM_CTBUF;
4152*82527734SSukumar Swaminathan 		(void) strcpy(label, "Unsol CT");
4153*82527734SSukumar Swaminathan 		cp = &hba->chan[hba->channel_ct];
4154*82527734SSukumar Swaminathan 		break;
4155*82527734SSukumar Swaminathan 
4156*82527734SSukumar Swaminathan 	default:
4157*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4158*82527734SSukumar Swaminathan 		    "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
4159*82527734SSukumar Swaminathan 		    fchdr.type);
4160*82527734SSukumar Swaminathan 
4161*82527734SSukumar Swaminathan 		goto done;
4162*82527734SSukumar Swaminathan 	}
4163*82527734SSukumar Swaminathan 	/* Fc Header is valid */
4164*82527734SSukumar Swaminathan 
4165*82527734SSukumar Swaminathan 	/* Check if this is an active sequence */
4166*82527734SSukumar Swaminathan 	iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
4167*82527734SSukumar Swaminathan 
4168*82527734SSukumar Swaminathan 	if (!iocbq) {
4169*82527734SSukumar Swaminathan 		if (fchdr.type != 0) {
4170*82527734SSukumar Swaminathan 			if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
4171*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4172*82527734SSukumar Swaminathan 				    "RQ ENTRY: %s: First of sequence not" \
4173*82527734SSukumar Swaminathan 				    " set.  Dropping...",
4174*82527734SSukumar Swaminathan 				    label);
4175*82527734SSukumar Swaminathan 
4176*82527734SSukumar Swaminathan 				goto done;
4177*82527734SSukumar Swaminathan 			}
4178*82527734SSukumar Swaminathan 		}
4179*82527734SSukumar Swaminathan 
4180*82527734SSukumar Swaminathan 		if (fchdr.seq_cnt != 0) {
4181*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4182*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Sequence count not zero (%d).  " \
4183*82527734SSukumar Swaminathan 			    "Dropping...",
4184*82527734SSukumar Swaminathan 			    label, fchdr.seq_cnt);
4185*82527734SSukumar Swaminathan 
4186*82527734SSukumar Swaminathan 			goto done;
4187*82527734SSukumar Swaminathan 		}
4188*82527734SSukumar Swaminathan 
4189*82527734SSukumar Swaminathan 		/* Find vport (defaults to physical port) */
4190*82527734SSukumar Swaminathan 		for (i = 0; i < MAX_VPORTS; i++) {
4191*82527734SSukumar Swaminathan 			vport = &VPORT(i);
4192*82527734SSukumar Swaminathan 
4193*82527734SSukumar Swaminathan 			if (vport->did == fchdr.d_id) {
4194*82527734SSukumar Swaminathan 				port = vport;
4195*82527734SSukumar Swaminathan 				break;
4196*82527734SSukumar Swaminathan 			}
4197*82527734SSukumar Swaminathan 		}
4198*82527734SSukumar Swaminathan 
4199*82527734SSukumar Swaminathan 		/* Allocate an IOCBQ */
4200*82527734SSukumar Swaminathan 		iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba,
4201*82527734SSukumar Swaminathan 		    MEM_IOCB, 1);
4202*82527734SSukumar Swaminathan 
4203*82527734SSukumar Swaminathan 		if (!iocbq) {
4204*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4205*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Out of IOCB " \
4206*82527734SSukumar Swaminathan 			    "resources.  Dropping...",
4207*82527734SSukumar Swaminathan 			    label);
4208*82527734SSukumar Swaminathan 
4209*82527734SSukumar Swaminathan 			goto done;
4210*82527734SSukumar Swaminathan 		}
4211*82527734SSukumar Swaminathan 
4212*82527734SSukumar Swaminathan 		seq_mp = NULL;
4213*82527734SSukumar Swaminathan 		if (fchdr.type != 0) {
4214*82527734SSukumar Swaminathan 			/* Allocate a buffer */
4215*82527734SSukumar Swaminathan 			seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type, 1);
4216*82527734SSukumar Swaminathan 
4217*82527734SSukumar Swaminathan 			if (!seq_mp) {
4218*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4219*82527734SSukumar Swaminathan 				    "RQ ENTRY: %s: Out of buffer " \
4220*82527734SSukumar Swaminathan 				    "resources.  Dropping...",
4221*82527734SSukumar Swaminathan 				    label);
4222*82527734SSukumar Swaminathan 
4223*82527734SSukumar Swaminathan 				goto done;
4224*82527734SSukumar Swaminathan 			}
4225*82527734SSukumar Swaminathan 
4226*82527734SSukumar Swaminathan 			iocbq->bp = (uint8_t *)seq_mp;
4227*82527734SSukumar Swaminathan 		}
4228*82527734SSukumar Swaminathan 
4229*82527734SSukumar Swaminathan 		node = (void *)emlxs_node_find_did(port, fchdr.s_id);
4230*82527734SSukumar Swaminathan 		if (node == NULL) {
4231*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4232*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Node not found. sid=%x",
4233*82527734SSukumar Swaminathan 			    label, fchdr.s_id);
4234*82527734SSukumar Swaminathan 		}
4235*82527734SSukumar Swaminathan 
4236*82527734SSukumar Swaminathan 		/* Initialize the iocbq */
4237*82527734SSukumar Swaminathan 		iocbq->port = port;
4238*82527734SSukumar Swaminathan 		iocbq->channel = cp;
4239*82527734SSukumar Swaminathan 		iocbq->node = node;
4240*82527734SSukumar Swaminathan 
4241*82527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
4242*82527734SSukumar Swaminathan 		iocb->RXSEQCNT = 0;
4243*82527734SSukumar Swaminathan 		iocb->RXSEQLEN = 0;
4244*82527734SSukumar Swaminathan 
4245*82527734SSukumar Swaminathan 		seq_len = 0;
4246*82527734SSukumar Swaminathan 		seq_cnt = 0;
4247*82527734SSukumar Swaminathan 
4248*82527734SSukumar Swaminathan 	} else {
4249*82527734SSukumar Swaminathan 
4250*82527734SSukumar Swaminathan 		iocb = &iocbq->iocb;
4251*82527734SSukumar Swaminathan 		port = iocbq->port;
4252*82527734SSukumar Swaminathan 		node = (emlxs_node_t *)iocbq->node;
4253*82527734SSukumar Swaminathan 
4254*82527734SSukumar Swaminathan 		seq_mp = (MATCHMAP *)iocbq->bp;
4255*82527734SSukumar Swaminathan 		seq_len = iocb->RXSEQLEN;
4256*82527734SSukumar Swaminathan 		seq_cnt = iocb->RXSEQCNT;
4257*82527734SSukumar Swaminathan 
4258*82527734SSukumar Swaminathan 		/* Check sequence order */
4259*82527734SSukumar Swaminathan 		if (fchdr.seq_cnt != seq_cnt) {
4260*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4261*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Out of order frame received " \
4262*82527734SSukumar Swaminathan 			    "(%d != %d).  Dropping...",
4263*82527734SSukumar Swaminathan 			    label, fchdr.seq_cnt, seq_cnt);
4264*82527734SSukumar Swaminathan 
4265*82527734SSukumar Swaminathan 			goto done;
4266*82527734SSukumar Swaminathan 		}
4267*82527734SSukumar Swaminathan 	}
4268*82527734SSukumar Swaminathan 
4269*82527734SSukumar Swaminathan 	/* We now have an iocbq */
4270*82527734SSukumar Swaminathan 
4271*82527734SSukumar Swaminathan 	/* Save the frame data to our seq buffer */
4272*82527734SSukumar Swaminathan 	if (cqe->data_size && seq_mp) {
4273*82527734SSukumar Swaminathan 		/* Get the next data rqb */
4274*82527734SSukumar Swaminathan 		data_mp = data_rq->rqb[host_index];
4275*82527734SSukumar Swaminathan 
4276*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(data_mp->dma_handle, 0,
4277*82527734SSukumar Swaminathan 		    cqe->data_size, DDI_DMA_SYNC_FORKERNEL);
4278*82527734SSukumar Swaminathan 
4279*82527734SSukumar Swaminathan 		data = (uint32_t *)data_mp->virt;
4280*82527734SSukumar Swaminathan 
4281*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4282*82527734SSukumar Swaminathan 		    "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
4283*82527734SSukumar Swaminathan 		    host_index, data[0], data[1], data[2], data[3],
4284*82527734SSukumar Swaminathan 		    data[4], data[5]);
4285*82527734SSukumar Swaminathan 
4286*82527734SSukumar Swaminathan 		/* Check sequence length */
4287*82527734SSukumar Swaminathan 		if ((seq_len + cqe->data_size) > seq_mp->size) {
4288*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4289*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Sequence buffer overflow. " \
4290*82527734SSukumar Swaminathan 			    "(%d > %d). Dropping...",
4291*82527734SSukumar Swaminathan 			    label, (seq_len + cqe->data_size), seq_mp->size);
4292*82527734SSukumar Swaminathan 
4293*82527734SSukumar Swaminathan 			goto done;
4294*82527734SSukumar Swaminathan 		}
4295*82527734SSukumar Swaminathan 
4296*82527734SSukumar Swaminathan 		/* Copy data to local receive buffer */
4297*82527734SSukumar Swaminathan 		bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
4298*82527734SSukumar Swaminathan 		    seq_len), cqe->data_size);
4299*82527734SSukumar Swaminathan 
4300*82527734SSukumar Swaminathan 		seq_len += cqe->data_size;
4301*82527734SSukumar Swaminathan 	}
4302*82527734SSukumar Swaminathan 
4303*82527734SSukumar Swaminathan 	/* If this is not the last frame of sequence, queue it. */
4304*82527734SSukumar Swaminathan 	if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
4305*82527734SSukumar Swaminathan 		/* Save sequence header */
4306*82527734SSukumar Swaminathan 		if (seq_cnt == 0) {
4307*82527734SSukumar Swaminathan 			bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
4308*82527734SSukumar Swaminathan 			    sizeof (fc_frame_hdr_t));
4309*82527734SSukumar Swaminathan 		}
4310*82527734SSukumar Swaminathan 
4311*82527734SSukumar Swaminathan 		/* Update sequence info in iocb */
4312*82527734SSukumar Swaminathan 		iocb->RXSEQCNT = seq_cnt + 1;
4313*82527734SSukumar Swaminathan 		iocb->RXSEQLEN = seq_len;
4314*82527734SSukumar Swaminathan 
4315*82527734SSukumar Swaminathan 		/* Queue iocbq for next frame */
4316*82527734SSukumar Swaminathan 		emlxs_sli4_rxq_put(hba, iocbq);
4317*82527734SSukumar Swaminathan 
4318*82527734SSukumar Swaminathan 		/* Don't free resources */
4319*82527734SSukumar Swaminathan 		iocbq = NULL;
4320*82527734SSukumar Swaminathan 
4321*82527734SSukumar Swaminathan 		/* No need to abort */
4322*82527734SSukumar Swaminathan 		abort = 0;
4323*82527734SSukumar Swaminathan 
4324*82527734SSukumar Swaminathan 		goto done;
4325*82527734SSukumar Swaminathan 	}
4326*82527734SSukumar Swaminathan 
4327*82527734SSukumar Swaminathan 	emlxs_sli4_rq_post(hba, hdr_rq->qid);
4328*82527734SSukumar Swaminathan 	posted = 1;
4329*82527734SSukumar Swaminathan 
4330*82527734SSukumar Swaminathan 	/* End of sequence found. Process request now. */
4331*82527734SSukumar Swaminathan 
4332*82527734SSukumar Swaminathan 	if (seq_cnt > 0) {
4333*82527734SSukumar Swaminathan 		/* Retrieve first frame of sequence */
4334*82527734SSukumar Swaminathan 		bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
4335*82527734SSukumar Swaminathan 		    sizeof (fc_frame_hdr_t));
4336*82527734SSukumar Swaminathan 
4337*82527734SSukumar Swaminathan 		bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
4338*82527734SSukumar Swaminathan 	}
4339*82527734SSukumar Swaminathan 
4340*82527734SSukumar Swaminathan 	/* Build rcv iocb and process it */
4341*82527734SSukumar Swaminathan 	switch (fchdr.type) {
4342*82527734SSukumar Swaminathan 	case 0: /* BLS */
4343*82527734SSukumar Swaminathan 
4344*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4345*82527734SSukumar Swaminathan 		    "RQ ENTRY: %s: xid:%x sid:%x. Sending BLS ACC...",
4346*82527734SSukumar Swaminathan 		    label, fchdr.ox_id, fchdr.s_id);
4347*82527734SSukumar Swaminathan 
4348*82527734SSukumar Swaminathan 		iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
4349*82527734SSukumar Swaminathan 
4350*82527734SSukumar Swaminathan 		/* Set up an iotag using special Abort iotags */
4351*82527734SSukumar Swaminathan 		if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) {
4352*82527734SSukumar Swaminathan 			hba->fc_oor_iotag = hba->max_iotag;
4353*82527734SSukumar Swaminathan 		}
4354*82527734SSukumar Swaminathan 		iotag = hba->fc_oor_iotag++;
4355*82527734SSukumar Swaminathan 
4356*82527734SSukumar Swaminathan 		/* BLS ACC Response */
4357*82527734SSukumar Swaminathan 		wqe = &iocbq->wqe;
4358*82527734SSukumar Swaminathan 		bzero((void *)wqe, sizeof (emlxs_wqe_t));
4359*82527734SSukumar Swaminathan 
4360*82527734SSukumar Swaminathan 		wqe->Command = CMD_XMIT_BLS_RSP64_CX;
4361*82527734SSukumar Swaminathan 		wqe->CmdType = WQE_TYPE_GEN;
4362*82527734SSukumar Swaminathan 
4363*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload0 = 0x80;
4364*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
4365*82527734SSukumar Swaminathan 
4366*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.OXId = fchdr.ox_id;
4367*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.RXId = fchdr.rx_id;
4368*82527734SSukumar Swaminathan 
4369*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntLow = 0;
4370*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
4371*82527734SSukumar Swaminathan 
4372*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.XO = 0;
4373*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.AR = 0;
4374*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.PT = 1;
4375*82527734SSukumar Swaminathan 		wqe->un.BlsRsp.RemoteId = fchdr.s_id;
4376*82527734SSukumar Swaminathan 
4377*82527734SSukumar Swaminathan 		wqe->PU = 0x3;
4378*82527734SSukumar Swaminathan 		wqe->ContextTag = port->vpi + hba->vpi_base;
4379*82527734SSukumar Swaminathan 		wqe->ContextType = WQE_VPI_CONTEXT;
4380*82527734SSukumar Swaminathan 		wqe->OXId = (volatile uint16_t) fchdr.ox_id;
4381*82527734SSukumar Swaminathan 		wqe->XRITag = 0xffff;
4382*82527734SSukumar Swaminathan 
4383*82527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4384*82527734SSukumar Swaminathan 			wqe->CCPE = 1;
4385*82527734SSukumar Swaminathan 			wqe->CCP = fchdr.rsvd;
4386*82527734SSukumar Swaminathan 		}
4387*82527734SSukumar Swaminathan 
4388*82527734SSukumar Swaminathan 		wqe->Class = CLASS3;
4389*82527734SSukumar Swaminathan 		wqe->RequestTag = iotag;
4390*82527734SSukumar Swaminathan 		wqe->CQId = 0x3ff;
4391*82527734SSukumar Swaminathan 
4392*82527734SSukumar Swaminathan 		emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
4393*82527734SSukumar Swaminathan 
4394*82527734SSukumar Swaminathan 		break;
4395*82527734SSukumar Swaminathan 
4396*82527734SSukumar Swaminathan 	case 1: /* ELS */
4397*82527734SSukumar Swaminathan 		cmd = *((uint32_t *)seq_mp->virt);
4398*82527734SSukumar Swaminathan 		cmd &= ELS_CMD_MASK;
4399*82527734SSukumar Swaminathan 		rp = NULL;
4400*82527734SSukumar Swaminathan 
4401*82527734SSukumar Swaminathan 		if (cmd != ELS_CMD_LOGO) {
4402*82527734SSukumar Swaminathan 			rp = EMLXS_NODE_TO_RPI(hba, node);
4403*82527734SSukumar Swaminathan 		}
4404*82527734SSukumar Swaminathan 
4405*82527734SSukumar Swaminathan 		if (!rp) {
4406*82527734SSukumar Swaminathan 			fp = hba->sli.sli4.FCFIp;
4407*82527734SSukumar Swaminathan 			rp = &fp->scratch_rpi;
4408*82527734SSukumar Swaminathan 		}
4409*82527734SSukumar Swaminathan 
4410*82527734SSukumar Swaminathan 		xp = emlxs_sli4_reserve_xri(hba, rp);
4411*82527734SSukumar Swaminathan 
4412*82527734SSukumar Swaminathan 		if (!xp) {
4413*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4414*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Out of exchange " \
4415*82527734SSukumar Swaminathan 			    "resources.  Dropping...",
4416*82527734SSukumar Swaminathan 			    label);
4417*82527734SSukumar Swaminathan 
4418*82527734SSukumar Swaminathan 			goto done;
4419*82527734SSukumar Swaminathan 		}
4420*82527734SSukumar Swaminathan 
4421*82527734SSukumar Swaminathan 		xp->rx_id = fchdr.ox_id;
4422*82527734SSukumar Swaminathan 
4423*82527734SSukumar Swaminathan 		/* Build CMD_RCV_ELS64_CX */
4424*82527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
4425*82527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
4426*82527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
4427*82527734SSukumar Swaminathan 		iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
4428*82527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
4429*82527734SSukumar Swaminathan 
4430*82527734SSukumar Swaminathan 		iocb->un.rcvels64.remoteID = fchdr.s_id;
4431*82527734SSukumar Swaminathan 		iocb->un.rcvels64.parmRo = fchdr.d_id;
4432*82527734SSukumar Swaminathan 
4433*82527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
4434*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = xp->XRI;
4435*82527734SSukumar Swaminathan 		iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
4436*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
4437*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
4438*82527734SSukumar Swaminathan 
4439*82527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4440*82527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.vpi = port->vpi + hba->vpi_base;
4441*82527734SSukumar Swaminathan 
4442*82527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4443*82527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
4444*82527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
4445*82527734SSukumar Swaminathan 		}
4446*82527734SSukumar Swaminathan 
4447*82527734SSukumar Swaminathan 		(void) emlxs_els_handle_unsol_req(port, iocbq->channel,
4448*82527734SSukumar Swaminathan 		    iocbq, seq_mp, seq_len);
4449*82527734SSukumar Swaminathan 
4450*82527734SSukumar Swaminathan 		break;
4451*82527734SSukumar Swaminathan 
4452*82527734SSukumar Swaminathan 	case 0x20: /* CT */
4453*82527734SSukumar Swaminathan 
4454*82527734SSukumar Swaminathan 		if (!node) {
4455*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4456*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Node not found (did=%x).  " \
4457*82527734SSukumar Swaminathan 			    "Dropping...",
4458*82527734SSukumar Swaminathan 			    label, fchdr.d_id);
4459*82527734SSukumar Swaminathan 
4460*82527734SSukumar Swaminathan 			goto done;
4461*82527734SSukumar Swaminathan 		}
4462*82527734SSukumar Swaminathan 
4463*82527734SSukumar Swaminathan 		rp = EMLXS_NODE_TO_RPI(hba, node);
4464*82527734SSukumar Swaminathan 
4465*82527734SSukumar Swaminathan 		if (!rp) {
4466*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4467*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: RPI not found (did=%x rpi=%x).  " \
4468*82527734SSukumar Swaminathan 			    "Dropping...",
4469*82527734SSukumar Swaminathan 			    label, fchdr.d_id, node->nlp_Rpi);
4470*82527734SSukumar Swaminathan 
4471*82527734SSukumar Swaminathan 			goto done;
4472*82527734SSukumar Swaminathan 		}
4473*82527734SSukumar Swaminathan 
4474*82527734SSukumar Swaminathan 		xp = emlxs_sli4_reserve_xri(hba, rp);
4475*82527734SSukumar Swaminathan 
4476*82527734SSukumar Swaminathan 		if (!xp) {
4477*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4478*82527734SSukumar Swaminathan 			    "RQ ENTRY: %s: Out of exchange " \
4479*82527734SSukumar Swaminathan 			    "resources.  Dropping...",
4480*82527734SSukumar Swaminathan 			    label);
4481*82527734SSukumar Swaminathan 
4482*82527734SSukumar Swaminathan 			goto done;
4483*82527734SSukumar Swaminathan 		}
4484*82527734SSukumar Swaminathan 
4485*82527734SSukumar Swaminathan 		xp->rx_id = fchdr.ox_id;
4486*82527734SSukumar Swaminathan 
4487*82527734SSukumar Swaminathan 		/* Build CMD_RCV_SEQ64_CX */
4488*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
4489*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
4490*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
4491*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
4492*82527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 1;
4493*82527734SSukumar Swaminathan 
4494*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.xrsqRo = 0;
4495*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
4496*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
4497*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
4498*82527734SSukumar Swaminathan 		iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
4499*82527734SSukumar Swaminathan 
4500*82527734SSukumar Swaminathan 		iocb->ULPPU = 0x3;
4501*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = xp->XRI;
4502*82527734SSukumar Swaminathan 		iocb->ULPIOTAG = rp->RPI;
4503*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
4504*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
4505*82527734SSukumar Swaminathan 
4506*82527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.seq_len = seq_len;
4507*82527734SSukumar Swaminathan 		iocb->unsli3.ext_rcv.vpi = port->vpi + hba->vpi_base;
4508*82527734SSukumar Swaminathan 
4509*82527734SSukumar Swaminathan 		if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
4510*82527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccpe = 1;
4511*82527734SSukumar Swaminathan 			iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
4512*82527734SSukumar Swaminathan 		}
4513*82527734SSukumar Swaminathan 
4514*82527734SSukumar Swaminathan 		(void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
4515*82527734SSukumar Swaminathan 		    iocbq, seq_mp, seq_len);
4516*82527734SSukumar Swaminathan 
4517*82527734SSukumar Swaminathan 		break;
4518*82527734SSukumar Swaminathan 	}
4519*82527734SSukumar Swaminathan 
4520*82527734SSukumar Swaminathan 	/* Sequence handled, no need to abort */
4521*82527734SSukumar Swaminathan 	abort = 0;
4522*82527734SSukumar Swaminathan 
4523*82527734SSukumar Swaminathan done:
4524*82527734SSukumar Swaminathan 
4525*82527734SSukumar Swaminathan 	if (!posted) {
4526*82527734SSukumar Swaminathan 		emlxs_sli4_rq_post(hba, hdr_rq->qid);
4527*82527734SSukumar Swaminathan 	}
4528*82527734SSukumar Swaminathan 
4529*82527734SSukumar Swaminathan 	if (abort) {
4530*82527734SSukumar Swaminathan 		/* Send ABTS for this exchange */
4531*82527734SSukumar Swaminathan 		/* !!! Currently, we have no implementation for this !!! */
4532*82527734SSukumar Swaminathan 		abort = 0;
4533*82527734SSukumar Swaminathan 	}
4534*82527734SSukumar Swaminathan 
4535*82527734SSukumar Swaminathan 	/* Return memory resources to pools */
4536*82527734SSukumar Swaminathan 	if (iocbq) {
4537*82527734SSukumar Swaminathan 		if (iocbq->bp) {
4538*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, buf_type,
4539*82527734SSukumar Swaminathan 			    (uint8_t *)iocbq->bp);
4540*82527734SSukumar Swaminathan 		}
4541*82527734SSukumar Swaminathan 
4542*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq);
4543*82527734SSukumar Swaminathan 	}
4544*82527734SSukumar Swaminathan 
4545*82527734SSukumar Swaminathan 	return;
4546*82527734SSukumar Swaminathan 
4547*82527734SSukumar Swaminathan } /* emlxs_sli4_process_unsol_rcv() */
4548*82527734SSukumar Swaminathan 
4549*82527734SSukumar Swaminathan 
4550*82527734SSukumar Swaminathan /*ARGSUSED*/
4551*82527734SSukumar Swaminathan static void
4552*82527734SSukumar Swaminathan emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
4553*82527734SSukumar Swaminathan     CQE_XRI_Abort_t *cqe)
4554*82527734SSukumar Swaminathan {
4555*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4556*82527734SSukumar Swaminathan 	XRIobj_t *xp;
4557*82527734SSukumar Swaminathan 
4558*82527734SSukumar Swaminathan 	xp = emlxs_sli4_find_xri(hba, cqe->XRI);
4559*82527734SSukumar Swaminathan 	if (xp == NULL) {
4560*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4561*82527734SSukumar Swaminathan 		    "CQ ENTRY: process xri aborted ignored");
4562*82527734SSukumar Swaminathan 		return;
4563*82527734SSukumar Swaminathan 	}
4564*82527734SSukumar Swaminathan 
4565*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4566*82527734SSukumar Swaminathan 	    "CQ ENTRY: process xri x%x aborted: IA %d EO %d BR %d",
4567*82527734SSukumar Swaminathan 	    cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
4568*82527734SSukumar Swaminathan 
4569*82527734SSukumar Swaminathan 	if (!(xp->state & RESOURCE_XRI_ABORT_INP)) {
4570*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4571*82527734SSukumar Swaminathan 		    "XRI Aborted: Bad state: x%x xri x%x",
4572*82527734SSukumar Swaminathan 		    xp->state, xp->XRI);
4573*82527734SSukumar Swaminathan 		return;
4574*82527734SSukumar Swaminathan 	}
4575*82527734SSukumar Swaminathan 
4576*82527734SSukumar Swaminathan 	/* Exchange is no longer busy on-chip, free it */
4577*82527734SSukumar Swaminathan 	emlxs_sli4_free_xri(hba, 0, xp);
4578*82527734SSukumar Swaminathan 
4579*82527734SSukumar Swaminathan } /* emlxs_sli4_process_xri_aborted () */
4580*82527734SSukumar Swaminathan 
4581*82527734SSukumar Swaminathan 
4582*82527734SSukumar Swaminathan /*ARGSUSED*/
4583*82527734SSukumar Swaminathan static void
4584*82527734SSukumar Swaminathan emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
4585*82527734SSukumar Swaminathan {
4586*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4587*82527734SSukumar Swaminathan 	CQE_u *cqe;
4588*82527734SSukumar Swaminathan 	CQE_u cq_entry;
4589*82527734SSukumar Swaminathan 	uint32_t cqdb;
4590*82527734SSukumar Swaminathan 	int num_entries = 0;
4591*82527734SSukumar Swaminathan 
4592*82527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
4593*82527734SSukumar Swaminathan 
4594*82527734SSukumar Swaminathan 	cqe = (CQE_u *)cq->addr.virt;
4595*82527734SSukumar Swaminathan 	cqe += cq->host_index;
4596*82527734SSukumar Swaminathan 
4597*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(cq->addr.dma_handle, 0,
4598*82527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
4599*82527734SSukumar Swaminathan 
4600*82527734SSukumar Swaminathan 	for (;;) {
4601*82527734SSukumar Swaminathan 		cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
4602*82527734SSukumar Swaminathan 		if (!(cq_entry.word[3] & CQE_VALID))
4603*82527734SSukumar Swaminathan 			break;
4604*82527734SSukumar Swaminathan 
4605*82527734SSukumar Swaminathan 		cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
4606*82527734SSukumar Swaminathan 		cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
4607*82527734SSukumar Swaminathan 		cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
4608*82527734SSukumar Swaminathan 
4609*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4610*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4611*82527734SSukumar Swaminathan 		    "CQ ENTRY: %08x %08x %08x %08x", cq_entry.word[0],
4612*82527734SSukumar Swaminathan 		    cq_entry.word[1], cq_entry.word[2], cq_entry.word[3]);
4613*82527734SSukumar Swaminathan #endif
4614*82527734SSukumar Swaminathan 
4615*82527734SSukumar Swaminathan 		num_entries++;
4616*82527734SSukumar Swaminathan 		cqe->word[3] = 0;
4617*82527734SSukumar Swaminathan 
4618*82527734SSukumar Swaminathan 		cq->host_index++;
4619*82527734SSukumar Swaminathan 		if (cq->host_index >= cq->max_index) {
4620*82527734SSukumar Swaminathan 			cq->host_index = 0;
4621*82527734SSukumar Swaminathan 			cqe = (CQE_u *)cq->addr.virt;
4622*82527734SSukumar Swaminathan 		} else {
4623*82527734SSukumar Swaminathan 			cqe++;
4624*82527734SSukumar Swaminathan 		}
4625*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4626*82527734SSukumar Swaminathan 
4627*82527734SSukumar Swaminathan 		/* Now handle specific cq type */
4628*82527734SSukumar Swaminathan 		if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
4629*82527734SSukumar Swaminathan 			if (cq_entry.cqAsyncEntry.async_evt) {
4630*82527734SSukumar Swaminathan 				emlxs_sli4_process_async_event(hba,
4631*82527734SSukumar Swaminathan 				    (CQE_ASYNC_t *)&cq_entry);
4632*82527734SSukumar Swaminathan 			} else {
4633*82527734SSukumar Swaminathan 				emlxs_sli4_process_mbox_event(hba,
4634*82527734SSukumar Swaminathan 				    (CQE_MBOX_t *)&cq_entry);
4635*82527734SSukumar Swaminathan 			}
4636*82527734SSukumar Swaminathan 		} else { /* EMLXS_CQ_TYPE_GROUP2 */
4637*82527734SSukumar Swaminathan 			switch (cq_entry.cqCmplEntry.Code) {
4638*82527734SSukumar Swaminathan 			case CQE_TYPE_WQ_COMPLETION:
4639*82527734SSukumar Swaminathan 				if (cq_entry.cqCmplEntry.RequestTag <
4640*82527734SSukumar Swaminathan 				    hba->max_iotag) {
4641*82527734SSukumar Swaminathan 					emlxs_sli4_process_wqe_cmpl(hba, cq,
4642*82527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
4643*82527734SSukumar Swaminathan 				} else {
4644*82527734SSukumar Swaminathan 					emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
4645*82527734SSukumar Swaminathan 					    (CQE_CmplWQ_t *)&cq_entry);
4646*82527734SSukumar Swaminathan 				}
4647*82527734SSukumar Swaminathan 				break;
4648*82527734SSukumar Swaminathan 			case CQE_TYPE_RELEASE_WQE:
4649*82527734SSukumar Swaminathan 				emlxs_sli4_process_release_wqe(hba, cq,
4650*82527734SSukumar Swaminathan 				    (CQE_RelWQ_t *)&cq_entry);
4651*82527734SSukumar Swaminathan 				break;
4652*82527734SSukumar Swaminathan 			case CQE_TYPE_UNSOL_RCV:
4653*82527734SSukumar Swaminathan 				emlxs_sli4_process_unsol_rcv(hba, cq,
4654*82527734SSukumar Swaminathan 				    (CQE_UnsolRcv_t *)&cq_entry);
4655*82527734SSukumar Swaminathan 				break;
4656*82527734SSukumar Swaminathan 			case CQE_TYPE_XRI_ABORTED:
4657*82527734SSukumar Swaminathan 				emlxs_sli4_process_xri_aborted(hba, cq,
4658*82527734SSukumar Swaminathan 				    (CQE_XRI_Abort_t *)&cq_entry);
4659*82527734SSukumar Swaminathan 				break;
4660*82527734SSukumar Swaminathan 			default:
4661*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4662*82527734SSukumar Swaminathan 				    "Invalid CQ entry %d: %08x %08x %08x %08x",
4663*82527734SSukumar Swaminathan 				    cq_entry.cqCmplEntry.Code, cq_entry.word[0],
4664*82527734SSukumar Swaminathan 				    cq_entry.word[1], cq_entry.word[2],
4665*82527734SSukumar Swaminathan 				    cq_entry.word[3]);
4666*82527734SSukumar Swaminathan 				break;
4667*82527734SSukumar Swaminathan 			}
4668*82527734SSukumar Swaminathan 		}
4669*82527734SSukumar Swaminathan 
4670*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
4671*82527734SSukumar Swaminathan 	}
4672*82527734SSukumar Swaminathan 
4673*82527734SSukumar Swaminathan 	cqdb = cq->qid;
4674*82527734SSukumar Swaminathan 	cqdb |= CQ_DB_REARM;
4675*82527734SSukumar Swaminathan 	if (num_entries != 0) {
4676*82527734SSukumar Swaminathan 		cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
4677*82527734SSukumar Swaminathan 	}
4678*82527734SSukumar Swaminathan 
4679*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4680*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4681*82527734SSukumar Swaminathan 	    "CQ CLEAR: %08x: pops:x%x", cqdb, num_entries);
4682*82527734SSukumar Swaminathan #endif
4683*82527734SSukumar Swaminathan 
4684*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), cqdb);
4685*82527734SSukumar Swaminathan 
4686*82527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
4687*82527734SSukumar Swaminathan 
4688*82527734SSukumar Swaminathan } /* emlxs_sli4_process_cq() */
4689*82527734SSukumar Swaminathan 
4690*82527734SSukumar Swaminathan 
4691*82527734SSukumar Swaminathan /*ARGSUSED*/
4692*82527734SSukumar Swaminathan static void
4693*82527734SSukumar Swaminathan emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
4694*82527734SSukumar Swaminathan {
4695*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4696*82527734SSukumar Swaminathan 	uint32_t eqdb;
4697*82527734SSukumar Swaminathan 	uint32_t *ptr;
4698*82527734SSukumar Swaminathan 	CHANNEL *cp;
4699*82527734SSukumar Swaminathan 	EQE_u eqe;
4700*82527734SSukumar Swaminathan 	uint32_t i;
4701*82527734SSukumar Swaminathan 	uint32_t value;
4702*82527734SSukumar Swaminathan 	int num_entries = 0;
4703*82527734SSukumar Swaminathan 
4704*82527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when entering this routine */
4705*82527734SSukumar Swaminathan 
4706*82527734SSukumar Swaminathan 	ptr = eq->addr.virt;
4707*82527734SSukumar Swaminathan 	ptr += eq->host_index;
4708*82527734SSukumar Swaminathan 
4709*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(eq->addr.dma_handle, 0,
4710*82527734SSukumar Swaminathan 	    4096, DDI_DMA_SYNC_FORKERNEL);
4711*82527734SSukumar Swaminathan 
4712*82527734SSukumar Swaminathan 	for (;;) {
4713*82527734SSukumar Swaminathan 		eqe.word = *ptr;
4714*82527734SSukumar Swaminathan 		eqe.word = BE_SWAP32(eqe.word);
4715*82527734SSukumar Swaminathan 
4716*82527734SSukumar Swaminathan 		if (!(eqe.word & EQE_VALID))
4717*82527734SSukumar Swaminathan 			break;
4718*82527734SSukumar Swaminathan 
4719*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4720*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4721*82527734SSukumar Swaminathan 		    "EQ ENTRY: %08x", eqe.word);
4722*82527734SSukumar Swaminathan #endif
4723*82527734SSukumar Swaminathan 
4724*82527734SSukumar Swaminathan 		*ptr = 0;
4725*82527734SSukumar Swaminathan 		num_entries++;
4726*82527734SSukumar Swaminathan 		eq->host_index++;
4727*82527734SSukumar Swaminathan 		if (eq->host_index >= eq->max_index) {
4728*82527734SSukumar Swaminathan 			eq->host_index = 0;
4729*82527734SSukumar Swaminathan 			ptr = eq->addr.virt;
4730*82527734SSukumar Swaminathan 		} else {
4731*82527734SSukumar Swaminathan 			ptr++;
4732*82527734SSukumar Swaminathan 		}
4733*82527734SSukumar Swaminathan 
4734*82527734SSukumar Swaminathan 		value = hba->sli.sli4.cq_map[eqe.entry.CQId];
4735*82527734SSukumar Swaminathan 
4736*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4737*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4738*82527734SSukumar Swaminathan 		    "EQ ENTRY:  CQIndex:x%x: cqid:x%x", value, eqe.entry.CQId);
4739*82527734SSukumar Swaminathan #endif
4740*82527734SSukumar Swaminathan 
4741*82527734SSukumar Swaminathan 		emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[value]);
4742*82527734SSukumar Swaminathan 	}
4743*82527734SSukumar Swaminathan 
4744*82527734SSukumar Swaminathan 	eqdb = eq->qid;
4745*82527734SSukumar Swaminathan 	eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
4746*82527734SSukumar Swaminathan 
4747*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4748*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4749*82527734SSukumar Swaminathan 	    "EQ CLEAR: %08x: pops:x%x", eqdb, num_entries);
4750*82527734SSukumar Swaminathan #endif
4751*82527734SSukumar Swaminathan 
4752*82527734SSukumar Swaminathan 	if (num_entries != 0) {
4753*82527734SSukumar Swaminathan 		eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
4754*82527734SSukumar Swaminathan 		for (i = 0; i < hba->chan_count; i++) {
4755*82527734SSukumar Swaminathan 			cp = &hba->chan[i];
4756*82527734SSukumar Swaminathan 			if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
4757*82527734SSukumar Swaminathan 				cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
4758*82527734SSukumar Swaminathan 				emlxs_thread_trigger2(&cp->intr_thread,
4759*82527734SSukumar Swaminathan 				    emlxs_proc_channel, cp);
4760*82527734SSukumar Swaminathan 			}
4761*82527734SSukumar Swaminathan 		}
4762*82527734SSukumar Swaminathan 	}
4763*82527734SSukumar Swaminathan 
4764*82527734SSukumar Swaminathan 	WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), eqdb);
4765*82527734SSukumar Swaminathan 
4766*82527734SSukumar Swaminathan 	/* EMLXS_PORT_LOCK must be held when exiting this routine */
4767*82527734SSukumar Swaminathan 
4768*82527734SSukumar Swaminathan } /* emlxs_sli4_process_eq() */
4769*82527734SSukumar Swaminathan 
4770*82527734SSukumar Swaminathan 
4771*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
4772*82527734SSukumar Swaminathan /*ARGSUSED*/
4773*82527734SSukumar Swaminathan static uint32_t
4774*82527734SSukumar Swaminathan emlxs_sli4_msi_intr(char *arg1, char *arg2)
4775*82527734SSukumar Swaminathan {
4776*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
4777*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4778*82527734SSukumar Swaminathan 	uint16_t msgid;
4779*82527734SSukumar Swaminathan 	int rc;
4780*82527734SSukumar Swaminathan 
4781*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4782*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4783*82527734SSukumar Swaminathan 	    "msiINTR arg1:%p arg2:%p", arg1, arg2);
4784*82527734SSukumar Swaminathan #endif
4785*82527734SSukumar Swaminathan 
4786*82527734SSukumar Swaminathan 	/* Check for legacy interrupt handling */
4787*82527734SSukumar Swaminathan 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
4788*82527734SSukumar Swaminathan 		rc = emlxs_sli4_intx_intr(arg1);
4789*82527734SSukumar Swaminathan 		return (rc);
4790*82527734SSukumar Swaminathan 	}
4791*82527734SSukumar Swaminathan 
4792*82527734SSukumar Swaminathan 	/* Get MSI message id */
4793*82527734SSukumar Swaminathan 	msgid = (uint16_t)((unsigned long)arg2);
4794*82527734SSukumar Swaminathan 
4795*82527734SSukumar Swaminathan 	/* Validate the message id */
4796*82527734SSukumar Swaminathan 	if (msgid >= hba->intr_count) {
4797*82527734SSukumar Swaminathan 		msgid = 0;
4798*82527734SSukumar Swaminathan 	}
4799*82527734SSukumar Swaminathan 
4800*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_INTR_LOCK(msgid));
4801*82527734SSukumar Swaminathan 
4802*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4803*82527734SSukumar Swaminathan 
4804*82527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
4805*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4806*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_INTR_LOCK(msgid));
4807*82527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
4808*82527734SSukumar Swaminathan 	}
4809*82527734SSukumar Swaminathan 
4810*82527734SSukumar Swaminathan 	/* The eq[] index == the MSI vector number */
4811*82527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
4812*82527734SSukumar Swaminathan 
4813*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4814*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_INTR_LOCK(msgid));
4815*82527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
4816*82527734SSukumar Swaminathan 
4817*82527734SSukumar Swaminathan } /* emlxs_sli4_msi_intr() */
4818*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
4819*82527734SSukumar Swaminathan 
4820*82527734SSukumar Swaminathan 
4821*82527734SSukumar Swaminathan /*ARGSUSED*/
4822*82527734SSukumar Swaminathan static int
4823*82527734SSukumar Swaminathan emlxs_sli4_intx_intr(char *arg)
4824*82527734SSukumar Swaminathan {
4825*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
4826*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4827*82527734SSukumar Swaminathan 
4828*82527734SSukumar Swaminathan #ifdef SLI4_FASTPATH_DEBUG
4829*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4830*82527734SSukumar Swaminathan 	    "intxINTR arg:%p", arg);
4831*82527734SSukumar Swaminathan #endif
4832*82527734SSukumar Swaminathan 
4833*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4834*82527734SSukumar Swaminathan 
4835*82527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
4836*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4837*82527734SSukumar Swaminathan 		return (DDI_INTR_UNCLAIMED);
4838*82527734SSukumar Swaminathan 	}
4839*82527734SSukumar Swaminathan 
4840*82527734SSukumar Swaminathan 	emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
4841*82527734SSukumar Swaminathan 
4842*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4843*82527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
4844*82527734SSukumar Swaminathan } /* emlxs_sli4_intx_intr() */
4845*82527734SSukumar Swaminathan 
4846*82527734SSukumar Swaminathan 
4847*82527734SSukumar Swaminathan static void
4848*82527734SSukumar Swaminathan emlxs_sli4_hba_kill(emlxs_hba_t *hba)
4849*82527734SSukumar Swaminathan {
4850*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4851*82527734SSukumar Swaminathan 	uint32_t j;
4852*82527734SSukumar Swaminathan 
4853*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4854*82527734SSukumar Swaminathan 	if (hba->flag & FC_INTERLOCKED) {
4855*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
4856*82527734SSukumar Swaminathan 
4857*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4858*82527734SSukumar Swaminathan 
4859*82527734SSukumar Swaminathan 		return;
4860*82527734SSukumar Swaminathan 	}
4861*82527734SSukumar Swaminathan 
4862*82527734SSukumar Swaminathan 	j = 0;
4863*82527734SSukumar Swaminathan 	while (j++ < 10000) {
4864*82527734SSukumar Swaminathan 		if (hba->mbox_queue_flag == 0) {
4865*82527734SSukumar Swaminathan 			break;
4866*82527734SSukumar Swaminathan 		}
4867*82527734SSukumar Swaminathan 
4868*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4869*82527734SSukumar Swaminathan 		DELAYUS(100);
4870*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
4871*82527734SSukumar Swaminathan 	}
4872*82527734SSukumar Swaminathan 
4873*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag != 0) {
4874*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
4875*82527734SSukumar Swaminathan 		    "Board kill failed. Mailbox busy.");
4876*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4877*82527734SSukumar Swaminathan 		return;
4878*82527734SSukumar Swaminathan 	}
4879*82527734SSukumar Swaminathan 
4880*82527734SSukumar Swaminathan 	hba->flag |= FC_INTERLOCKED;
4881*82527734SSukumar Swaminathan 
4882*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
4883*82527734SSukumar Swaminathan 
4884*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4885*82527734SSukumar Swaminathan 
4886*82527734SSukumar Swaminathan } /* emlxs_sli4_hba_kill() */
4887*82527734SSukumar Swaminathan 
4888*82527734SSukumar Swaminathan 
4889*82527734SSukumar Swaminathan static void
4890*82527734SSukumar Swaminathan emlxs_sli4_enable_intr(emlxs_hba_t *hba)
4891*82527734SSukumar Swaminathan {
4892*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
4893*82527734SSukumar Swaminathan 	int i;
4894*82527734SSukumar Swaminathan 	int num_cq;
4895*82527734SSukumar Swaminathan 	uint32_t data;
4896*82527734SSukumar Swaminathan 
4897*82527734SSukumar Swaminathan 	hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
4898*82527734SSukumar Swaminathan 
4899*82527734SSukumar Swaminathan 	num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
4900*82527734SSukumar Swaminathan 	    EMLXS_CQ_OFFSET_WQ;
4901*82527734SSukumar Swaminathan 
4902*82527734SSukumar Swaminathan 	/* ARM EQ / CQs */
4903*82527734SSukumar Swaminathan 	for (i = 0; i < num_cq; i++) {
4904*82527734SSukumar Swaminathan 		data = hba->sli.sli4.cq[i].qid;
4905*82527734SSukumar Swaminathan 		data |= CQ_DB_REARM;
4906*82527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
4907*82527734SSukumar Swaminathan 	}
4908*82527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
4909*82527734SSukumar Swaminathan 		data = hba->sli.sli4.eq[i].qid;
4910*82527734SSukumar Swaminathan 		data |= (EQ_DB_REARM | EQ_DB_EVENT);
4911*82527734SSukumar Swaminathan 		WRITE_BAR2_REG(hba, FC_CQDB_REG(hba), data);
4912*82527734SSukumar Swaminathan 	}
4913*82527734SSukumar Swaminathan } /* emlxs_sli4_enable_intr() */
4914*82527734SSukumar Swaminathan 
4915*82527734SSukumar Swaminathan 
4916*82527734SSukumar Swaminathan static void
4917*82527734SSukumar Swaminathan emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
4918*82527734SSukumar Swaminathan {
4919*82527734SSukumar Swaminathan 	if (att) {
4920*82527734SSukumar Swaminathan 		return;
4921*82527734SSukumar Swaminathan 	}
4922*82527734SSukumar Swaminathan 
4923*82527734SSukumar Swaminathan 	hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
4924*82527734SSukumar Swaminathan 
4925*82527734SSukumar Swaminathan 	/* Short of reset, we cannot disable interrupts */
4926*82527734SSukumar Swaminathan } /* emlxs_sli4_disable_intr() */
4927*82527734SSukumar Swaminathan 
4928*82527734SSukumar Swaminathan 
4929*82527734SSukumar Swaminathan static void
4930*82527734SSukumar Swaminathan emlxs_sli4_resource_free(emlxs_hba_t *hba)
4931*82527734SSukumar Swaminathan {
4932*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
4933*82527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
4934*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
4935*82527734SSukumar Swaminathan 	uint32_t	i;
4936*82527734SSukumar Swaminathan 
4937*82527734SSukumar Swaminathan 	if (hba->sli.sli4.FCFIp) {
4938*82527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.FCFIp,
4939*82527734SSukumar Swaminathan 		    (sizeof (FCFIobj_t) * hba->sli.sli4.FCFICount));
4940*82527734SSukumar Swaminathan 		hba->sli.sli4.FCFIp = NULL;
4941*82527734SSukumar Swaminathan 	}
4942*82527734SSukumar Swaminathan 	if (hba->sli.sli4.VFIp) {
4943*82527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.VFIp,
4944*82527734SSukumar Swaminathan 		    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount));
4945*82527734SSukumar Swaminathan 		hba->sli.sli4.VFIp = NULL;
4946*82527734SSukumar Swaminathan 	}
4947*82527734SSukumar Swaminathan 	if (hba->sli.sli4.RPIp) {
4948*82527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.RPIp,
4949*82527734SSukumar Swaminathan 		    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount));
4950*82527734SSukumar Swaminathan 		hba->sli.sli4.RPIp = NULL;
4951*82527734SSukumar Swaminathan 	}
4952*82527734SSukumar Swaminathan 
4953*82527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.HeaderTmplate;
4954*82527734SSukumar Swaminathan 	if (buf_info->virt) {
4955*82527734SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
4956*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
4957*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
4958*82527734SSukumar Swaminathan 	}
4959*82527734SSukumar Swaminathan 
4960*82527734SSukumar Swaminathan 	if (hba->sli.sli4.XRIp) {
4961*82527734SSukumar Swaminathan 		if ((hba->sli.sli4.XRIinuse_f !=
4962*82527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
4963*82527734SSukumar Swaminathan 		    (hba->sli.sli4.XRIinuse_b !=
4964*82527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
4965*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
4966*82527734SSukumar Swaminathan 			    "XRIs inuse during free!: %p %p != %p\n",
4967*82527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_f,
4968*82527734SSukumar Swaminathan 			    hba->sli.sli4.XRIinuse_b,
4969*82527734SSukumar Swaminathan 			    &hba->sli.sli4.XRIinuse_f);
4970*82527734SSukumar Swaminathan 		}
4971*82527734SSukumar Swaminathan 		xp = hba->sli.sli4.XRIp;
4972*82527734SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.XRICount; i++) {
4973*82527734SSukumar Swaminathan 			buf_info = &xp->SGList;
4974*82527734SSukumar Swaminathan 			if (buf_info->virt) {
4975*82527734SSukumar Swaminathan 				buf_info->flags = FC_MBUF_DMA;
4976*82527734SSukumar Swaminathan 				emlxs_mem_free(hba, buf_info);
4977*82527734SSukumar Swaminathan 				bzero(buf_info, sizeof (MBUF_INFO));
4978*82527734SSukumar Swaminathan 			}
4979*82527734SSukumar Swaminathan 			xp++;
4980*82527734SSukumar Swaminathan 		}
4981*82527734SSukumar Swaminathan 		kmem_free(hba->sli.sli4.XRIp,
4982*82527734SSukumar Swaminathan 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
4983*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIp = NULL;
4984*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIfree_tail = NULL;
4985*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIfree_list = NULL;
4986*82527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count = 0;
4987*82527734SSukumar Swaminathan 	}
4988*82527734SSukumar Swaminathan 
4989*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQS; i++) {
4990*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.eq[i].addr;
4991*82527734SSukumar Swaminathan 		if (buf_info->virt) {
4992*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
4993*82527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
4994*82527734SSukumar Swaminathan 			mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
4995*82527734SSukumar Swaminathan 		}
4996*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
4997*82527734SSukumar Swaminathan 	}
4998*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQS; i++) {
4999*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.cq[i].addr;
5000*82527734SSukumar Swaminathan 		if (buf_info->virt) {
5001*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
5002*82527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
5003*82527734SSukumar Swaminathan 		}
5004*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
5005*82527734SSukumar Swaminathan 	}
5006*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQS; i++) {
5007*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.wq[i].addr;
5008*82527734SSukumar Swaminathan 		if (buf_info->virt) {
5009*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
5010*82527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
5011*82527734SSukumar Swaminathan 		}
5012*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
5013*82527734SSukumar Swaminathan 	}
5014*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5015*82527734SSukumar Swaminathan 		/* Free the RQ */
5016*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.rq[i].addr;
5017*82527734SSukumar Swaminathan 		if (buf_info->virt) {
5018*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
5019*82527734SSukumar Swaminathan 			emlxs_mem_free(hba, buf_info);
5020*82527734SSukumar Swaminathan 
5021*82527734SSukumar Swaminathan 			/* Free the RQB pool */
5022*82527734SSukumar Swaminathan 			emlxs_mem_pool_free(hba, &hba->sli.sli4.rq[i].rqb_pool);
5023*82527734SSukumar Swaminathan 			mutex_destroy(&hba->sli.sli4.rq[i].lock);
5024*82527734SSukumar Swaminathan 
5025*82527734SSukumar Swaminathan 			/* Free the associated RXQ */
5026*82527734SSukumar Swaminathan 			mutex_destroy(&hba->sli.sli4.rxq[i].lock);
5027*82527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
5028*82527734SSukumar Swaminathan 		}
5029*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
5030*82527734SSukumar Swaminathan 	}
5031*82527734SSukumar Swaminathan 
5032*82527734SSukumar Swaminathan 	/* Free the MQ */
5033*82527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.mq.addr;
5034*82527734SSukumar Swaminathan 	if (buf_info->virt == NULL) {
5035*82527734SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
5036*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
5037*82527734SSukumar Swaminathan 	}
5038*82527734SSukumar Swaminathan 	bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5039*82527734SSukumar Swaminathan 
5040*82527734SSukumar Swaminathan 	/* Cleanup queue ordinal mapping */
5041*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
5042*82527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[i] = 0xffff;
5043*82527734SSukumar Swaminathan 	}
5044*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
5045*82527734SSukumar Swaminathan 		hba->sli.sli4.cq_map[i] = 0xffff;
5046*82527734SSukumar Swaminathan 	}
5047*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
5048*82527734SSukumar Swaminathan 		hba->sli.sli4.wq_map[i] = 0xffff;
5049*82527734SSukumar Swaminathan 	}
5050*82527734SSukumar Swaminathan 
5051*82527734SSukumar Swaminathan 	mutex_destroy(&hba->sli.sli4.id_lock);
5052*82527734SSukumar Swaminathan 
5053*82527734SSukumar Swaminathan } /* emlxs_sli4_resource_free() */
5054*82527734SSukumar Swaminathan 
5055*82527734SSukumar Swaminathan 
5056*82527734SSukumar Swaminathan static int
5057*82527734SSukumar Swaminathan emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
5058*82527734SSukumar Swaminathan {
5059*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5060*82527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
5061*82527734SSukumar Swaminathan 	MBUF_INFO	*buf_info;
5062*82527734SSukumar Swaminathan 	uint16_t	index;
5063*82527734SSukumar Swaminathan 	int		num_eq;
5064*82527734SSukumar Swaminathan 	int		num_wq;
5065*82527734SSukumar Swaminathan 	uint32_t	i;
5066*82527734SSukumar Swaminathan 	uint32_t	j;
5067*82527734SSukumar Swaminathan 	uint32_t	k;
5068*82527734SSukumar Swaminathan 	uint32_t	word;
5069*82527734SSukumar Swaminathan 	FCFIobj_t	*fp;
5070*82527734SSukumar Swaminathan 	VFIobj_t	*vp;
5071*82527734SSukumar Swaminathan 	RPIobj_t	*rp;
5072*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5073*82527734SSukumar Swaminathan 	char		buf[64];
5074*82527734SSukumar Swaminathan 	emlxs_memseg_t	*seg;
5075*82527734SSukumar Swaminathan 	MATCHMAP 	*mp;
5076*82527734SSukumar Swaminathan 	MATCHMAP 	**rqb;
5077*82527734SSukumar Swaminathan 	RQE_t		*rqe;
5078*82527734SSukumar Swaminathan 
5079*82527734SSukumar Swaminathan 	(void) sprintf(buf, "%s_id_lock mutex", DRIVER_NAME);
5080*82527734SSukumar Swaminathan 	mutex_init(&hba->sli.sli4.id_lock, buf, MUTEX_DRIVER, NULL);
5081*82527734SSukumar Swaminathan 
5082*82527734SSukumar Swaminathan 	if ((!hba->sli.sli4.FCFIp) && (hba->sli.sli4.FCFICount)) {
5083*82527734SSukumar Swaminathan 		hba->sli.sli4.FCFIp = (FCFIobj_t *)kmem_zalloc(
5084*82527734SSukumar Swaminathan 		    (sizeof (FCFIobj_t) * hba->sli.sli4.FCFICount), KM_SLEEP);
5085*82527734SSukumar Swaminathan 
5086*82527734SSukumar Swaminathan 		fp = hba->sli.sli4.FCFIp;
5087*82527734SSukumar Swaminathan 		index = 0;	/* Start FCFIs at 0 */
5088*82527734SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.FCFICount; i++) {
5089*82527734SSukumar Swaminathan 			fp->FCFI = index;
5090*82527734SSukumar Swaminathan 			fp->index = i;
5091*82527734SSukumar Swaminathan 			fp++;
5092*82527734SSukumar Swaminathan 			index++;
5093*82527734SSukumar Swaminathan 		}
5094*82527734SSukumar Swaminathan 	}
5095*82527734SSukumar Swaminathan 
5096*82527734SSukumar Swaminathan 	if ((!hba->sli.sli4.VFIp) && (hba->sli.sli4.VFICount)) {
5097*82527734SSukumar Swaminathan 		hba->sli.sli4.VFIp = (VFIobj_t *)kmem_zalloc(
5098*82527734SSukumar Swaminathan 		    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP);
5099*82527734SSukumar Swaminathan 
5100*82527734SSukumar Swaminathan 		vp = hba->sli.sli4.VFIp;
5101*82527734SSukumar Swaminathan 		index = hba->sli.sli4.VFIBase;
5102*82527734SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.VFICount; i++) {
5103*82527734SSukumar Swaminathan 			vp->VFI = index;
5104*82527734SSukumar Swaminathan 			vp->index = i;
5105*82527734SSukumar Swaminathan 			vp++;
5106*82527734SSukumar Swaminathan 			index++;
5107*82527734SSukumar Swaminathan 		}
5108*82527734SSukumar Swaminathan 	}
5109*82527734SSukumar Swaminathan 
5110*82527734SSukumar Swaminathan 	if ((!hba->sli.sli4.RPIp) && (hba->sli.sli4.RPICount)) {
5111*82527734SSukumar Swaminathan 		hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc(
5112*82527734SSukumar Swaminathan 		    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP);
5113*82527734SSukumar Swaminathan 
5114*82527734SSukumar Swaminathan 		rp = hba->sli.sli4.RPIp;
5115*82527734SSukumar Swaminathan 		index = hba->sli.sli4.RPIBase;
5116*82527734SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.RPICount; i++) {
5117*82527734SSukumar Swaminathan 			rp->RPI = index;
5118*82527734SSukumar Swaminathan 			rp->index = i; /* offset into HdrTmplate */
5119*82527734SSukumar Swaminathan 			rp++;
5120*82527734SSukumar Swaminathan 			index++;
5121*82527734SSukumar Swaminathan 		}
5122*82527734SSukumar Swaminathan 	}
5123*82527734SSukumar Swaminathan 
5124*82527734SSukumar Swaminathan 	if ((!hba->sli.sli4.XRIp) && (hba->sli.sli4.XRICount)) {
5125*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
5126*82527734SSukumar Swaminathan 		    (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
5127*82527734SSukumar Swaminathan 
5128*82527734SSukumar Swaminathan 		xp = hba->sli.sli4.XRIp;
5129*82527734SSukumar Swaminathan 		index = hba->sli.sli4.XRIBase;
5130*82527734SSukumar Swaminathan 		for (i = 0; i < hba->sli.sli4.XRICount; i++) {
5131*82527734SSukumar Swaminathan 			xp->sge_count =
5132*82527734SSukumar Swaminathan 			    (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
5133*82527734SSukumar Swaminathan 			xp->XRI = index;
5134*82527734SSukumar Swaminathan 			xp->iotag = i;
5135*82527734SSukumar Swaminathan 			if ((xp->XRI == 0) || (xp->iotag == 0)) {
5136*82527734SSukumar Swaminathan 				index++; /* Skip XRI 0 or IOTag 0 */
5137*82527734SSukumar Swaminathan 				xp++;
5138*82527734SSukumar Swaminathan 				continue;
5139*82527734SSukumar Swaminathan 			}
5140*82527734SSukumar Swaminathan 			/* Add xp to end of single linked free list */
5141*82527734SSukumar Swaminathan 			if (hba->sli.sli4.XRIfree_tail) {
5142*82527734SSukumar Swaminathan 				hba->sli.sli4.XRIfree_tail->_f = xp;
5143*82527734SSukumar Swaminathan 				hba->sli.sli4.XRIfree_tail = xp;
5144*82527734SSukumar Swaminathan 			} else {
5145*82527734SSukumar Swaminathan 				hba->sli.sli4.XRIfree_tail = xp;
5146*82527734SSukumar Swaminathan 			}
5147*82527734SSukumar Swaminathan 			if (hba->sli.sli4.XRIfree_list == NULL) {
5148*82527734SSukumar Swaminathan 				hba->sli.sli4.XRIfree_list = xp;
5149*82527734SSukumar Swaminathan 			}
5150*82527734SSukumar Swaminathan 			xp->_f = NULL;
5151*82527734SSukumar Swaminathan 			hba->sli.sli4.xrif_count++;
5152*82527734SSukumar Swaminathan 
5153*82527734SSukumar Swaminathan 			/* Allocate SGL for this xp */
5154*82527734SSukumar Swaminathan 			buf_info = &xp->SGList;
5155*82527734SSukumar Swaminathan 			buf_info->size = hba->sli.sli4.mem_sgl_size;
5156*82527734SSukumar Swaminathan 			buf_info->flags =
5157*82527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5158*82527734SSukumar Swaminathan 			buf_info->align = hba->sli.sli4.mem_sgl_size;
5159*82527734SSukumar Swaminathan 
5160*82527734SSukumar Swaminathan 			(void) emlxs_mem_alloc(hba, buf_info);
5161*82527734SSukumar Swaminathan 
5162*82527734SSukumar Swaminathan 			if (buf_info->virt == NULL) {
5163*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
5164*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
5165*82527734SSukumar Swaminathan 				    "Unable to allocate XRI SGL area: %d",
5166*82527734SSukumar Swaminathan 				    hba->sli.sli4.mem_sgl_size);
5167*82527734SSukumar Swaminathan 				goto failed;
5168*82527734SSukumar Swaminathan 			}
5169*82527734SSukumar Swaminathan 			bzero(buf_info->virt, hba->sli.sli4.mem_sgl_size);
5170*82527734SSukumar Swaminathan 			xp++;
5171*82527734SSukumar Swaminathan 			index++;
5172*82527734SSukumar Swaminathan 		}
5173*82527734SSukumar Swaminathan 		/* Initialize double linked list */
5174*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIinuse_f =
5175*82527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5176*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIinuse_b =
5177*82527734SSukumar Swaminathan 		    (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5178*82527734SSukumar Swaminathan 		hba->sli.sli4.xria_count = 0;
5179*82527734SSukumar Swaminathan 	}
5180*82527734SSukumar Swaminathan 
5181*82527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.HeaderTmplate;
5182*82527734SSukumar Swaminathan 	if ((buf_info->virt == NULL) && (hba->sli.sli4.RPICount)) {
5183*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
5184*82527734SSukumar Swaminathan 		buf_info->size = (sizeof (RPIHdrTmplate_t) *
5185*82527734SSukumar Swaminathan 		    hba->sli.sli4.RPICount);
5186*82527734SSukumar Swaminathan 		buf_info->flags =
5187*82527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_DMA32;
5188*82527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5189*82527734SSukumar Swaminathan 
5190*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
5191*82527734SSukumar Swaminathan 
5192*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5193*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
5194*82527734SSukumar Swaminathan 			    "Unable to allocate Header Tmplate area: %d",
5195*82527734SSukumar Swaminathan 			    (sizeof (RPIHdrTmplate_t) *
5196*82527734SSukumar Swaminathan 			    hba->sli.sli4.RPICount));
5197*82527734SSukumar Swaminathan 			goto failed;
5198*82527734SSukumar Swaminathan 		}
5199*82527734SSukumar Swaminathan 		bzero(buf_info->virt,
5200*82527734SSukumar Swaminathan 		    (sizeof (RPIHdrTmplate_t) * hba->sli.sli4.RPICount));
5201*82527734SSukumar Swaminathan 	}
5202*82527734SSukumar Swaminathan 
5203*82527734SSukumar Swaminathan 	/* Allocate space for queues */
5204*82527734SSukumar Swaminathan 	/* EQs - 1 per Interrupt vector */
5205*82527734SSukumar Swaminathan 	num_eq = hba->intr_count;
5206*82527734SSukumar Swaminathan 	for (i = 0; i < num_eq; i++) {
5207*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.eq[i].addr;
5208*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5209*82527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
5210*82527734SSukumar Swaminathan 			buf_info->size = 4096;
5211*82527734SSukumar Swaminathan 			buf_info->flags =
5212*82527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5213*82527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5214*82527734SSukumar Swaminathan 
5215*82527734SSukumar Swaminathan 			(void) emlxs_mem_alloc(hba, buf_info);
5216*82527734SSukumar Swaminathan 
5217*82527734SSukumar Swaminathan 			if (buf_info->virt == NULL) {
5218*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
5219*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
5220*82527734SSukumar Swaminathan 				    "Unable to allocate EQ %d area", i);
5221*82527734SSukumar Swaminathan 				goto failed;
5222*82527734SSukumar Swaminathan 			}
5223*82527734SSukumar Swaminathan 			bzero(buf_info->virt, 4096);
5224*82527734SSukumar Swaminathan 			hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
5225*82527734SSukumar Swaminathan 		}
5226*82527734SSukumar Swaminathan 
5227*82527734SSukumar Swaminathan 		(void) sprintf(buf, "%s_eq%d_lastwq_lock mutex",
5228*82527734SSukumar Swaminathan 		    DRIVER_NAME, i);
5229*82527734SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, buf,
5230*82527734SSukumar Swaminathan 		    MUTEX_DRIVER, NULL);
5231*82527734SSukumar Swaminathan 	}
5232*82527734SSukumar Swaminathan 	/* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
5233*82527734SSukumar Swaminathan 	num_wq = cfg[CFG_NUM_WQ].current * num_eq;
5234*82527734SSukumar Swaminathan 	for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
5235*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.cq[i].addr;
5236*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5237*82527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
5238*82527734SSukumar Swaminathan 			buf_info->size = 4096;
5239*82527734SSukumar Swaminathan 			buf_info->flags =
5240*82527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5241*82527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5242*82527734SSukumar Swaminathan 
5243*82527734SSukumar Swaminathan 			(void) emlxs_mem_alloc(hba, buf_info);
5244*82527734SSukumar Swaminathan 
5245*82527734SSukumar Swaminathan 			if (buf_info->virt == NULL) {
5246*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
5247*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
5248*82527734SSukumar Swaminathan 				    "Unable to allocate CQ %d area", i);
5249*82527734SSukumar Swaminathan 				goto failed;
5250*82527734SSukumar Swaminathan 			}
5251*82527734SSukumar Swaminathan 			bzero(buf_info->virt, 4096);
5252*82527734SSukumar Swaminathan 			hba->sli.sli4.cq[i].max_index = CQ_DEPTH;
5253*82527734SSukumar Swaminathan 		}
5254*82527734SSukumar Swaminathan 	}
5255*82527734SSukumar Swaminathan 	/* WQs - NUM_WQ config parameter * number of EQs */
5256*82527734SSukumar Swaminathan 	for (i = 0; i < num_wq; i++) {
5257*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.wq[i].addr;
5258*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5259*82527734SSukumar Swaminathan 			bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
5260*82527734SSukumar Swaminathan 			buf_info->size = (4096 * EMLXS_NUM_WQ_PAGES);
5261*82527734SSukumar Swaminathan 			buf_info->flags =
5262*82527734SSukumar Swaminathan 			    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5263*82527734SSukumar Swaminathan 			buf_info->align = ddi_ptob(hba->dip, 1L);
5264*82527734SSukumar Swaminathan 
5265*82527734SSukumar Swaminathan 			(void) emlxs_mem_alloc(hba, buf_info);
5266*82527734SSukumar Swaminathan 
5267*82527734SSukumar Swaminathan 			if (buf_info->virt == NULL) {
5268*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
5269*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
5270*82527734SSukumar Swaminathan 				    "Unable to allocate WQ %d area", i);
5271*82527734SSukumar Swaminathan 				goto failed;
5272*82527734SSukumar Swaminathan 			}
5273*82527734SSukumar Swaminathan 			bzero(buf_info->virt, (4096 * EMLXS_NUM_WQ_PAGES));
5274*82527734SSukumar Swaminathan 			hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
5275*82527734SSukumar Swaminathan 			hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
5276*82527734SSukumar Swaminathan 		}
5277*82527734SSukumar Swaminathan 	}
5278*82527734SSukumar Swaminathan 
5279*82527734SSukumar Swaminathan 	/* RXQs */
5280*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RXQS; i++) {
5281*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
5282*82527734SSukumar Swaminathan 
5283*82527734SSukumar Swaminathan 		(void) sprintf(buf, "%s_rxq%d_lock mutex", DRIVER_NAME, i);
5284*82527734SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.rxq[i].lock, buf, MUTEX_DRIVER, NULL);
5285*82527734SSukumar Swaminathan 	}
5286*82527734SSukumar Swaminathan 
5287*82527734SSukumar Swaminathan 	/* RQs */
5288*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
5289*82527734SSukumar Swaminathan 		buf_info = &hba->sli.sli4.rq[i].addr;
5290*82527734SSukumar Swaminathan 		if (buf_info->virt) {
5291*82527734SSukumar Swaminathan 			continue;
5292*82527734SSukumar Swaminathan 		}
5293*82527734SSukumar Swaminathan 
5294*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
5295*82527734SSukumar Swaminathan 		buf_info->size = 4096;
5296*82527734SSukumar Swaminathan 		buf_info->flags =
5297*82527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5298*82527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5299*82527734SSukumar Swaminathan 
5300*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
5301*82527734SSukumar Swaminathan 
5302*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5303*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5304*82527734SSukumar Swaminathan 			    &emlxs_init_failed_msg,
5305*82527734SSukumar Swaminathan 			    "Unable to allocate RQ %d area", i);
5306*82527734SSukumar Swaminathan 			goto failed;
5307*82527734SSukumar Swaminathan 		}
5308*82527734SSukumar Swaminathan 		bzero(buf_info->virt, 4096);
5309*82527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
5310*82527734SSukumar Swaminathan 
5311*82527734SSukumar Swaminathan 		/* RQBs */
5312*82527734SSukumar Swaminathan 		seg = &hba->sli.sli4.rq[i].rqb_pool;
5313*82527734SSukumar Swaminathan 		bzero(seg, sizeof (MEMSEG));
5314*82527734SSukumar Swaminathan 		seg->fc_numblks = RQB_COUNT;
5315*82527734SSukumar Swaminathan 		seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5316*82527734SSukumar Swaminathan 		seg->fc_memalign = 8;
5317*82527734SSukumar Swaminathan 		seg->fc_memtag = (i<<16);
5318*82527734SSukumar Swaminathan 
5319*82527734SSukumar Swaminathan 		if ((i & 0x1)) {
5320*82527734SSukumar Swaminathan 			/* Odd == Data pool */
5321*82527734SSukumar Swaminathan 			seg->fc_memsize = RQB_DATA_SIZE;
5322*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "RQB Data Pool");
5323*82527734SSukumar Swaminathan 
5324*82527734SSukumar Swaminathan 		} else {
5325*82527734SSukumar Swaminathan 			/* Even == Header pool */
5326*82527734SSukumar Swaminathan 			seg->fc_memsize = RQB_HEADER_SIZE;
5327*82527734SSukumar Swaminathan 			(void) strcpy(seg->fc_label, "RQB Header Pool");
5328*82527734SSukumar Swaminathan 		}
5329*82527734SSukumar Swaminathan 
5330*82527734SSukumar Swaminathan 		/* Allocate the pool */
5331*82527734SSukumar Swaminathan 		if (emlxs_mem_pool_alloc(hba, seg) == NULL) {
5332*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
5333*82527734SSukumar Swaminathan 			    "Unable to allocate RQ %d pool", i);
5334*82527734SSukumar Swaminathan 
5335*82527734SSukumar Swaminathan 			goto failed;
5336*82527734SSukumar Swaminathan 		}
5337*82527734SSukumar Swaminathan 
5338*82527734SSukumar Swaminathan 		/* Initialize the RQEs */
5339*82527734SSukumar Swaminathan 		rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
5340*82527734SSukumar Swaminathan 		rqb = hba->sli.sli4.rq[i].rqb;
5341*82527734SSukumar Swaminathan 
5342*82527734SSukumar Swaminathan 		for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
5343*82527734SSukumar Swaminathan 			mp  = (MATCHMAP*)seg->fc_memget_ptr;
5344*82527734SSukumar Swaminathan 			for (k = 0; k < RQB_COUNT; k++) {
5345*82527734SSukumar Swaminathan 				if (j == 0) {
5346*82527734SSukumar Swaminathan 					mp->tag = (seg->fc_memtag | k);
5347*82527734SSukumar Swaminathan 				}
5348*82527734SSukumar Swaminathan 
5349*82527734SSukumar Swaminathan 				word = PADDR_HI(mp->phys);
5350*82527734SSukumar Swaminathan 				rqe->AddrHi = BE_SWAP32(word);
5351*82527734SSukumar Swaminathan 
5352*82527734SSukumar Swaminathan 				word = PADDR_LO(mp->phys);
5353*82527734SSukumar Swaminathan 				rqe->AddrLo = BE_SWAP32(word);
5354*82527734SSukumar Swaminathan 
5355*82527734SSukumar Swaminathan 				*rqb = mp;
5356*82527734SSukumar Swaminathan 
5357*82527734SSukumar Swaminathan #ifdef RQ_DEBUG
5358*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5359*82527734SSukumar Swaminathan 				    "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p tag=%08x",
5360*82527734SSukumar Swaminathan 				    i, j, k, mp, mp->tag);
5361*82527734SSukumar Swaminathan #endif
5362*82527734SSukumar Swaminathan 
5363*82527734SSukumar Swaminathan 				mp = (MATCHMAP *)mp->fc_mptr;
5364*82527734SSukumar Swaminathan 				rqe++;
5365*82527734SSukumar Swaminathan 				rqb++;
5366*82527734SSukumar Swaminathan 			}
5367*82527734SSukumar Swaminathan 		}
5368*82527734SSukumar Swaminathan 
5369*82527734SSukumar Swaminathan 		/* Sync the RQ buffer list */
5370*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, 0,
5371*82527734SSukumar Swaminathan 		    hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
5372*82527734SSukumar Swaminathan 
5373*82527734SSukumar Swaminathan 		(void) sprintf(buf, "%s_rq%d_lock mutex", DRIVER_NAME, i);
5374*82527734SSukumar Swaminathan 		mutex_init(&hba->sli.sli4.rq[i].lock, buf, MUTEX_DRIVER, NULL);
5375*82527734SSukumar Swaminathan 	}
5376*82527734SSukumar Swaminathan 
5377*82527734SSukumar Swaminathan 	/* MQ */
5378*82527734SSukumar Swaminathan 	buf_info = &hba->sli.sli4.mq.addr;
5379*82527734SSukumar Swaminathan 	if (!buf_info->virt) {
5380*82527734SSukumar Swaminathan 		bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
5381*82527734SSukumar Swaminathan 		buf_info->size = 4096;
5382*82527734SSukumar Swaminathan 		buf_info->flags =
5383*82527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
5384*82527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(hba->dip, 1L);
5385*82527734SSukumar Swaminathan 
5386*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
5387*82527734SSukumar Swaminathan 
5388*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
5389*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
5390*82527734SSukumar Swaminathan 			    "Unable to allocate MQ area");
5391*82527734SSukumar Swaminathan 			goto failed;
5392*82527734SSukumar Swaminathan 		}
5393*82527734SSukumar Swaminathan 		bzero(buf_info->virt, 4096);
5394*82527734SSukumar Swaminathan 		hba->sli.sli4.mq.max_index = MQ_DEPTH;
5395*82527734SSukumar Swaminathan 	}
5396*82527734SSukumar Swaminathan 
5397*82527734SSukumar Swaminathan 	return (0);
5398*82527734SSukumar Swaminathan 
5399*82527734SSukumar Swaminathan failed:
5400*82527734SSukumar Swaminathan 
5401*82527734SSukumar Swaminathan 	(void) emlxs_sli4_resource_free(hba);
5402*82527734SSukumar Swaminathan 	return (ENOMEM);
5403*82527734SSukumar Swaminathan 
5404*82527734SSukumar Swaminathan } /* emlxs_sli4_resource_alloc */
5405*82527734SSukumar Swaminathan 
5406*82527734SSukumar Swaminathan 
5407*82527734SSukumar Swaminathan static FCFIobj_t *
5408*82527734SSukumar Swaminathan emlxs_sli4_alloc_fcfi(emlxs_hba_t *hba)
5409*82527734SSukumar Swaminathan {
5410*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
5411*82527734SSukumar Swaminathan 	uint32_t	i;
5412*82527734SSukumar Swaminathan 	FCFIobj_t	*fp;
5413*82527734SSukumar Swaminathan 
5414*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5415*82527734SSukumar Swaminathan 	fp = hba->sli.sli4.FCFIp;
5416*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.FCFICount; i++) {
5417*82527734SSukumar Swaminathan 		if (fp->state == RESOURCE_FREE) {
5418*82527734SSukumar Swaminathan 			fp->state = RESOURCE_ALLOCATED;
5419*82527734SSukumar Swaminathan 			mutex_exit(&hba->sli.sli4.id_lock);
5420*82527734SSukumar Swaminathan 			return (fp);
5421*82527734SSukumar Swaminathan 		}
5422*82527734SSukumar Swaminathan 		fp++;
5423*82527734SSukumar Swaminathan 	}
5424*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5425*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5426*82527734SSukumar Swaminathan 	    "Unable to Alloc FCFI");
5427*82527734SSukumar Swaminathan 	return (NULL);
5428*82527734SSukumar Swaminathan 
5429*82527734SSukumar Swaminathan } /* emlxs_sli4_alloc_fcfi() */
5430*82527734SSukumar Swaminathan 
5431*82527734SSukumar Swaminathan 
5432*82527734SSukumar Swaminathan static FCFIobj_t *
5433*82527734SSukumar Swaminathan emlxs_sli4_find_fcfi_fcfrec(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
5434*82527734SSukumar Swaminathan {
5435*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5436*82527734SSukumar Swaminathan 	uint32_t	i;
5437*82527734SSukumar Swaminathan 	FCFIobj_t	*fp;
5438*82527734SSukumar Swaminathan 
5439*82527734SSukumar Swaminathan 	/* Check for BOTH a matching FCF index and mac address */
5440*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5441*82527734SSukumar Swaminathan 	fp = hba->sli.sli4.FCFIp;
5442*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.FCFICount; i++) {
5443*82527734SSukumar Swaminathan 		if (fp->state & RESOURCE_ALLOCATED) {
5444*82527734SSukumar Swaminathan 			if ((fp->FCF_index == fcfrec->fcf_index) &&
5445*82527734SSukumar Swaminathan 			    (bcmp((char *)fcfrec->fcf_mac_address_hi,
5446*82527734SSukumar Swaminathan 			    fp->fcf_rec.fcf_mac_address_hi, 4) == 0) &&
5447*82527734SSukumar Swaminathan 			    (bcmp((char *)fcfrec->fcf_mac_address_low,
5448*82527734SSukumar Swaminathan 			    fp->fcf_rec.fcf_mac_address_low, 2) == 0)) {
5449*82527734SSukumar Swaminathan 				mutex_exit(&hba->sli.sli4.id_lock);
5450*82527734SSukumar Swaminathan 				return (fp);
5451*82527734SSukumar Swaminathan 			}
5452*82527734SSukumar Swaminathan 		}
5453*82527734SSukumar Swaminathan 		fp++;
5454*82527734SSukumar Swaminathan 	}
5455*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5456*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5457*82527734SSukumar Swaminathan 	    "Unable to Find FCF Index %d", fcfrec->fcf_index);
5458*82527734SSukumar Swaminathan 	return (0);
5459*82527734SSukumar Swaminathan 
5460*82527734SSukumar Swaminathan } /* emlxs_sli4_find_fcfi_fcfrec() */
5461*82527734SSukumar Swaminathan 
5462*82527734SSukumar Swaminathan 
5463*82527734SSukumar Swaminathan extern VFIobj_t *
5464*82527734SSukumar Swaminathan emlxs_sli4_alloc_vfi(emlxs_hba_t *hba, FCFIobj_t *fp)
5465*82527734SSukumar Swaminathan {
5466*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
5467*82527734SSukumar Swaminathan 	uint32_t	i;
5468*82527734SSukumar Swaminathan 	VFIobj_t	*vp;
5469*82527734SSukumar Swaminathan 
5470*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5471*82527734SSukumar Swaminathan 	vp = hba->sli.sli4.VFIp;
5472*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.VFICount; i++) {
5473*82527734SSukumar Swaminathan 		if (vp->state == RESOURCE_FREE) {
5474*82527734SSukumar Swaminathan 			vp->state = RESOURCE_ALLOCATED;
5475*82527734SSukumar Swaminathan 			vp->FCFIp = fp;
5476*82527734SSukumar Swaminathan 			fp->outstandingVFIs++;
5477*82527734SSukumar Swaminathan 			mutex_exit(&hba->sli.sli4.id_lock);
5478*82527734SSukumar Swaminathan 			return (vp);
5479*82527734SSukumar Swaminathan 		}
5480*82527734SSukumar Swaminathan 		vp++;
5481*82527734SSukumar Swaminathan 	}
5482*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5483*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5484*82527734SSukumar Swaminathan 	    "Unable to Alloc VFI");
5485*82527734SSukumar Swaminathan 	return (NULL);
5486*82527734SSukumar Swaminathan 
5487*82527734SSukumar Swaminathan } /* emlxs_sli4_alloc_vfi() */
5488*82527734SSukumar Swaminathan 
5489*82527734SSukumar Swaminathan 
5490*82527734SSukumar Swaminathan extern RPIobj_t *
5491*82527734SSukumar Swaminathan emlxs_sli4_alloc_rpi(emlxs_port_t *port)
5492*82527734SSukumar Swaminathan {
5493*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
5494*82527734SSukumar Swaminathan 	uint32_t	i;
5495*82527734SSukumar Swaminathan 	RPIobj_t	*rp;
5496*82527734SSukumar Swaminathan 
5497*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5498*82527734SSukumar Swaminathan 	rp = hba->sli.sli4.RPIp;
5499*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.RPICount; i++) {
5500*82527734SSukumar Swaminathan 		/* To be consistent with SLI3, the RPI assignment */
5501*82527734SSukumar Swaminathan 		/* starts with 1. ONLY one SLI4 HBA in the entire */
5502*82527734SSukumar Swaminathan 		/* system will be sacrificed by one RPI and that  */
5503*82527734SSukumar Swaminathan 		/* is the one having RPI base equal 0. */
5504*82527734SSukumar Swaminathan 		if ((rp->state == RESOURCE_FREE) && (rp->RPI != 0)) {
5505*82527734SSukumar Swaminathan 			rp->state = RESOURCE_ALLOCATED;
5506*82527734SSukumar Swaminathan 			rp->VPIp = port;
5507*82527734SSukumar Swaminathan 			port->outstandingRPIs++;
5508*82527734SSukumar Swaminathan 			mutex_exit(&hba->sli.sli4.id_lock);
5509*82527734SSukumar Swaminathan 			return (rp);
5510*82527734SSukumar Swaminathan 		}
5511*82527734SSukumar Swaminathan 		rp++;
5512*82527734SSukumar Swaminathan 	}
5513*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5514*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5515*82527734SSukumar Swaminathan 	    "Unable to Alloc RPI");
5516*82527734SSukumar Swaminathan 	return (NULL);
5517*82527734SSukumar Swaminathan 
5518*82527734SSukumar Swaminathan } /* emlxs_sli4_alloc_rpi() */
5519*82527734SSukumar Swaminathan 
5520*82527734SSukumar Swaminathan 
5521*82527734SSukumar Swaminathan extern RPIobj_t *
5522*82527734SSukumar Swaminathan emlxs_sli4_find_rpi(emlxs_hba_t *hba, uint16_t rpi)
5523*82527734SSukumar Swaminathan {
5524*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5525*82527734SSukumar Swaminathan 	RPIobj_t	*rp;
5526*82527734SSukumar Swaminathan 	int		index;
5527*82527734SSukumar Swaminathan 
5528*82527734SSukumar Swaminathan 	rp = hba->sli.sli4.RPIp;
5529*82527734SSukumar Swaminathan 	index = rpi - hba->sli.sli4.RPIBase;
5530*82527734SSukumar Swaminathan 	if ((rpi == 0xffff) || (index >= hba->sli.sli4.RPICount)) {
5531*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5532*82527734SSukumar Swaminathan 		    "RPI %d out of range: Count = %d",
5533*82527734SSukumar Swaminathan 		    index, hba->sli.sli4.RPICount);
5534*82527734SSukumar Swaminathan 		return (NULL);
5535*82527734SSukumar Swaminathan 	}
5536*82527734SSukumar Swaminathan 	rp += index;
5537*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5538*82527734SSukumar Swaminathan 	if ((index < 0) || !(rp->state & RESOURCE_ALLOCATED)) {
5539*82527734SSukumar Swaminathan 		mutex_exit(&hba->sli.sli4.id_lock);
5540*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5541*82527734SSukumar Swaminathan 		    "Unable to find RPI %d", index);
5542*82527734SSukumar Swaminathan 		return (NULL);
5543*82527734SSukumar Swaminathan 	}
5544*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5545*82527734SSukumar Swaminathan 	return (rp);
5546*82527734SSukumar Swaminathan 
5547*82527734SSukumar Swaminathan } /* emlxs_sli4_find_rpi() */
5548*82527734SSukumar Swaminathan 
5549*82527734SSukumar Swaminathan 
5550*82527734SSukumar Swaminathan static XRIobj_t *
5551*82527734SSukumar Swaminathan emlxs_sli4_reserve_xri(emlxs_hba_t *hba,  RPIobj_t *rp)
5552*82527734SSukumar Swaminathan {
5553*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5554*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5555*82527734SSukumar Swaminathan 	uint16_t	iotag;
5556*82527734SSukumar Swaminathan 
5557*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5558*82527734SSukumar Swaminathan 
5559*82527734SSukumar Swaminathan 	xp = hba->sli.sli4.XRIfree_list;
5560*82527734SSukumar Swaminathan 
5561*82527734SSukumar Swaminathan 	if (xp == NULL) {
5562*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5563*82527734SSukumar Swaminathan 
5564*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5565*82527734SSukumar Swaminathan 		    "Unable to reserve XRI");
5566*82527734SSukumar Swaminathan 
5567*82527734SSukumar Swaminathan 		return (NULL);
5568*82527734SSukumar Swaminathan 	}
5569*82527734SSukumar Swaminathan 
5570*82527734SSukumar Swaminathan 	iotag = xp->iotag;
5571*82527734SSukumar Swaminathan 
5572*82527734SSukumar Swaminathan 	if ((!iotag) ||
5573*82527734SSukumar Swaminathan 	    (hba->fc_table[iotag] != NULL &&
5574*82527734SSukumar Swaminathan 	    hba->fc_table[iotag] != STALE_PACKET)) {
5575*82527734SSukumar Swaminathan 		/*
5576*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
5577*82527734SSukumar Swaminathan 		 */
5578*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5579*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to reserve iotag");
5580*82527734SSukumar Swaminathan 
5581*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5582*82527734SSukumar Swaminathan 		return (NULL);
5583*82527734SSukumar Swaminathan 	}
5584*82527734SSukumar Swaminathan 
5585*82527734SSukumar Swaminathan 	xp->state = (RESOURCE_ALLOCATED | RESOURCE_XRI_RESERVED);
5586*82527734SSukumar Swaminathan 	xp->RPIp = rp;
5587*82527734SSukumar Swaminathan 	xp->sbp = NULL;
5588*82527734SSukumar Swaminathan 
5589*82527734SSukumar Swaminathan 	if (rp) {
5590*82527734SSukumar Swaminathan 		rp->outstandingXRIs++;
5591*82527734SSukumar Swaminathan 	}
5592*82527734SSukumar Swaminathan 
5593*82527734SSukumar Swaminathan 	/* Take it off free list */
5594*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIfree_list = xp->_f;
5595*82527734SSukumar Swaminathan 	xp->_f = NULL;
5596*82527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count--;
5597*82527734SSukumar Swaminathan 
5598*82527734SSukumar Swaminathan 	/* Add it to end of inuse list */
5599*82527734SSukumar Swaminathan 	xp->_b = hba->sli.sli4.XRIinuse_b;
5600*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIinuse_b->_f = xp;
5601*82527734SSukumar Swaminathan 	xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5602*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIinuse_b = xp;
5603*82527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
5604*82527734SSukumar Swaminathan 
5605*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5606*82527734SSukumar Swaminathan 	return (xp);
5607*82527734SSukumar Swaminathan 
5608*82527734SSukumar Swaminathan } /* emlxs_sli4_reserve_xri() */
5609*82527734SSukumar Swaminathan 
5610*82527734SSukumar Swaminathan 
5611*82527734SSukumar Swaminathan extern uint32_t
5612*82527734SSukumar Swaminathan emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri)
5613*82527734SSukumar Swaminathan {
5614*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5615*82527734SSukumar Swaminathan 	XRIobj_t *xp;
5616*82527734SSukumar Swaminathan 
5617*82527734SSukumar Swaminathan 	xp = emlxs_sli4_find_xri(hba, xri);
5618*82527734SSukumar Swaminathan 
5619*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5620*82527734SSukumar Swaminathan 
5621*82527734SSukumar Swaminathan 	if (!xp || xp->state == RESOURCE_FREE) {
5622*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5623*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5624*82527734SSukumar Swaminathan 		    "emlxs_sli4_unreserve_xri: xri=%x already freed.", xp->XRI);
5625*82527734SSukumar Swaminathan 		return (0);
5626*82527734SSukumar Swaminathan 	}
5627*82527734SSukumar Swaminathan 
5628*82527734SSukumar Swaminathan 	if (!(xp->state & RESOURCE_XRI_RESERVED)) {
5629*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5630*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5631*82527734SSukumar Swaminathan 		    "emlxs_sli4_unreserve_xri: xri=%x in use.", xp->XRI);
5632*82527734SSukumar Swaminathan 		return (1);
5633*82527734SSukumar Swaminathan 	}
5634*82527734SSukumar Swaminathan 
5635*82527734SSukumar Swaminathan 	if (hba->fc_table[xp->iotag]) {
5636*82527734SSukumar Swaminathan 		hba->fc_table[xp->iotag] = NULL;
5637*82527734SSukumar Swaminathan 		hba->io_count--;
5638*82527734SSukumar Swaminathan 	}
5639*82527734SSukumar Swaminathan 
5640*82527734SSukumar Swaminathan 	xp->state = RESOURCE_FREE;
5641*82527734SSukumar Swaminathan 
5642*82527734SSukumar Swaminathan 	if (xp->RPIp) {
5643*82527734SSukumar Swaminathan 		xp->RPIp->outstandingXRIs--;
5644*82527734SSukumar Swaminathan 		xp->RPIp = NULL;
5645*82527734SSukumar Swaminathan 	}
5646*82527734SSukumar Swaminathan 
5647*82527734SSukumar Swaminathan 	/* Take it off inuse list */
5648*82527734SSukumar Swaminathan 	(xp->_b)->_f = xp->_f;
5649*82527734SSukumar Swaminathan 	(xp->_f)->_b = xp->_b;
5650*82527734SSukumar Swaminathan 	xp->_f = NULL;
5651*82527734SSukumar Swaminathan 	xp->_b = NULL;
5652*82527734SSukumar Swaminathan 	hba->sli.sli4.xria_count--;
5653*82527734SSukumar Swaminathan 
5654*82527734SSukumar Swaminathan 	/* Add it to end of free list */
5655*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIfree_tail->_f = xp;
5656*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIfree_tail = xp;
5657*82527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count++;
5658*82527734SSukumar Swaminathan 
5659*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5660*82527734SSukumar Swaminathan 	    "emlxs_sli4_unreserve_xri: xri=%x unreserved.", xp->XRI);
5661*82527734SSukumar Swaminathan 
5662*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5663*82527734SSukumar Swaminathan 
5664*82527734SSukumar Swaminathan 	return (0);
5665*82527734SSukumar Swaminathan 
5666*82527734SSukumar Swaminathan } /* emlxs_sli4_unreserve_xri() */
5667*82527734SSukumar Swaminathan 
5668*82527734SSukumar Swaminathan 
5669*82527734SSukumar Swaminathan static XRIobj_t *
5670*82527734SSukumar Swaminathan emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri)
5671*82527734SSukumar Swaminathan {
5672*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5673*82527734SSukumar Swaminathan 	uint16_t	iotag;
5674*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5675*82527734SSukumar Swaminathan 
5676*82527734SSukumar Swaminathan 	xp = emlxs_sli4_find_xri(hba, xri);
5677*82527734SSukumar Swaminathan 
5678*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5679*82527734SSukumar Swaminathan 
5680*82527734SSukumar Swaminathan 	if (!xp) {
5681*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5682*82527734SSukumar Swaminathan 		    "emlxs_sli4_register_xri: XRI not found.");
5683*82527734SSukumar Swaminathan 
5684*82527734SSukumar Swaminathan 
5685*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5686*82527734SSukumar Swaminathan 		return (NULL);
5687*82527734SSukumar Swaminathan 	}
5688*82527734SSukumar Swaminathan 
5689*82527734SSukumar Swaminathan 	if (!(xp->state & RESOURCE_ALLOCATED) ||
5690*82527734SSukumar Swaminathan 	    !(xp->state & RESOURCE_XRI_RESERVED)) {
5691*82527734SSukumar Swaminathan 
5692*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5693*82527734SSukumar Swaminathan 		    "emlxs_sli4_register_xri: Invalid XRI. xp=%p state=%x",
5694*82527734SSukumar Swaminathan 		    xp, xp->state);
5695*82527734SSukumar Swaminathan 
5696*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5697*82527734SSukumar Swaminathan 		return (NULL);
5698*82527734SSukumar Swaminathan 	}
5699*82527734SSukumar Swaminathan 
5700*82527734SSukumar Swaminathan 	iotag = xp->iotag;
5701*82527734SSukumar Swaminathan 
5702*82527734SSukumar Swaminathan 	if ((!iotag) ||
5703*82527734SSukumar Swaminathan 	    (hba->fc_table[iotag] != NULL &&
5704*82527734SSukumar Swaminathan 	    hba->fc_table[iotag] != STALE_PACKET)) {
5705*82527734SSukumar Swaminathan 
5706*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5707*82527734SSukumar Swaminathan 		    "emlxs_sli4_register_xri: Invalid fc_table entry. " \
5708*82527734SSukumar Swaminathan 		    "iotag=%x entry=%p",
5709*82527734SSukumar Swaminathan 		    iotag, hba->fc_table[iotag]);
5710*82527734SSukumar Swaminathan 
5711*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5712*82527734SSukumar Swaminathan 		return (NULL);
5713*82527734SSukumar Swaminathan 	}
5714*82527734SSukumar Swaminathan 
5715*82527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
5716*82527734SSukumar Swaminathan 	hba->io_count++;
5717*82527734SSukumar Swaminathan 
5718*82527734SSukumar Swaminathan 	sbp->iotag = iotag;
5719*82527734SSukumar Swaminathan 	sbp->xp = xp;
5720*82527734SSukumar Swaminathan 
5721*82527734SSukumar Swaminathan 	xp->state &= ~RESOURCE_XRI_RESERVED;
5722*82527734SSukumar Swaminathan 	xp->sbp = sbp;
5723*82527734SSukumar Swaminathan 
5724*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5725*82527734SSukumar Swaminathan 
5726*82527734SSukumar Swaminathan 	return (xp);
5727*82527734SSukumar Swaminathan 
5728*82527734SSukumar Swaminathan } /* emlxs_sli4_register_xri() */
5729*82527734SSukumar Swaminathan 
5730*82527734SSukumar Swaminathan 
5731*82527734SSukumar Swaminathan /* Performs both reserve and register functions for XRI */
5732*82527734SSukumar Swaminathan static XRIobj_t *
5733*82527734SSukumar Swaminathan emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rp)
5734*82527734SSukumar Swaminathan {
5735*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5736*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5737*82527734SSukumar Swaminathan 	uint16_t	iotag;
5738*82527734SSukumar Swaminathan 
5739*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5740*82527734SSukumar Swaminathan 
5741*82527734SSukumar Swaminathan 	xp = hba->sli.sli4.XRIfree_list;
5742*82527734SSukumar Swaminathan 
5743*82527734SSukumar Swaminathan 	if (xp == NULL) {
5744*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5745*82527734SSukumar Swaminathan 
5746*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5747*82527734SSukumar Swaminathan 		    "Unable to allocate XRI");
5748*82527734SSukumar Swaminathan 
5749*82527734SSukumar Swaminathan 		return (NULL);
5750*82527734SSukumar Swaminathan 	}
5751*82527734SSukumar Swaminathan 
5752*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
5753*82527734SSukumar Swaminathan 	iotag = xp->iotag;
5754*82527734SSukumar Swaminathan 
5755*82527734SSukumar Swaminathan 	if ((!iotag) ||
5756*82527734SSukumar Swaminathan 	    (hba->fc_table[iotag] != NULL &&
5757*82527734SSukumar Swaminathan 	    hba->fc_table[iotag] != STALE_PACKET)) {
5758*82527734SSukumar Swaminathan 		/*
5759*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
5760*82527734SSukumar Swaminathan 		 */
5761*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
5762*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag");
5763*82527734SSukumar Swaminathan 
5764*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
5765*82527734SSukumar Swaminathan 		return (NULL);
5766*82527734SSukumar Swaminathan 	}
5767*82527734SSukumar Swaminathan 
5768*82527734SSukumar Swaminathan 	hba->fc_table[iotag] = sbp;
5769*82527734SSukumar Swaminathan 	hba->io_count++;
5770*82527734SSukumar Swaminathan 
5771*82527734SSukumar Swaminathan 	sbp->iotag = iotag;
5772*82527734SSukumar Swaminathan 	sbp->xp = xp;
5773*82527734SSukumar Swaminathan 
5774*82527734SSukumar Swaminathan 	xp->state = RESOURCE_ALLOCATED;
5775*82527734SSukumar Swaminathan 	xp->RPIp = rp;
5776*82527734SSukumar Swaminathan 	xp->sbp = sbp;
5777*82527734SSukumar Swaminathan 
5778*82527734SSukumar Swaminathan 	if (rp) {
5779*82527734SSukumar Swaminathan 		rp->outstandingXRIs++;
5780*82527734SSukumar Swaminathan 	}
5781*82527734SSukumar Swaminathan 
5782*82527734SSukumar Swaminathan 	/* Take it off free list */
5783*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIfree_list = xp->_f;
5784*82527734SSukumar Swaminathan 	xp->_f = NULL;
5785*82527734SSukumar Swaminathan 	hba->sli.sli4.xrif_count--;
5786*82527734SSukumar Swaminathan 
5787*82527734SSukumar Swaminathan 	/* Add it to end of inuse list */
5788*82527734SSukumar Swaminathan 	xp->_b = hba->sli.sli4.XRIinuse_b;
5789*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIinuse_b->_f = xp;
5790*82527734SSukumar Swaminathan 	xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
5791*82527734SSukumar Swaminathan 	hba->sli.sli4.XRIinuse_b = xp;
5792*82527734SSukumar Swaminathan 	hba->sli.sli4.xria_count++;
5793*82527734SSukumar Swaminathan 
5794*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5795*82527734SSukumar Swaminathan 
5796*82527734SSukumar Swaminathan 	return (xp);
5797*82527734SSukumar Swaminathan 
5798*82527734SSukumar Swaminathan } /* emlxs_sli4_alloc_xri() */
5799*82527734SSukumar Swaminathan 
5800*82527734SSukumar Swaminathan 
5801*82527734SSukumar Swaminathan extern XRIobj_t *
5802*82527734SSukumar Swaminathan emlxs_sli4_find_xri(emlxs_hba_t *hba, uint16_t xri)
5803*82527734SSukumar Swaminathan {
5804*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5805*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5806*82527734SSukumar Swaminathan 
5807*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5808*82527734SSukumar Swaminathan 	xp = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
5809*82527734SSukumar Swaminathan 	while (xp != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
5810*82527734SSukumar Swaminathan 		if ((xp->state & RESOURCE_ALLOCATED) &&
5811*82527734SSukumar Swaminathan 		    (xp->XRI == xri)) {
5812*82527734SSukumar Swaminathan 			break;
5813*82527734SSukumar Swaminathan 		}
5814*82527734SSukumar Swaminathan 		xp = xp->_f;
5815*82527734SSukumar Swaminathan 	}
5816*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
5817*82527734SSukumar Swaminathan 
5818*82527734SSukumar Swaminathan 	if (xp == (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
5819*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5820*82527734SSukumar Swaminathan 		    "Unable to find XRI x%x", xri);
5821*82527734SSukumar Swaminathan 		return (NULL);
5822*82527734SSukumar Swaminathan 	}
5823*82527734SSukumar Swaminathan 	return (xp);
5824*82527734SSukumar Swaminathan 
5825*82527734SSukumar Swaminathan } /* emlxs_sli4_find_xri() */
5826*82527734SSukumar Swaminathan 
5827*82527734SSukumar Swaminathan extern void
5828*82527734SSukumar Swaminathan emlxs_sli4_free_fcfi(emlxs_hba_t *hba, FCFIobj_t *fp)
5829*82527734SSukumar Swaminathan {
5830*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5831*82527734SSukumar Swaminathan 
5832*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5833*82527734SSukumar Swaminathan 	if (fp->state == RESOURCE_FREE) {
5834*82527734SSukumar Swaminathan 		mutex_exit(&hba->sli.sli4.id_lock);
5835*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5836*82527734SSukumar Swaminathan 		    "Free FCFI:%d idx:%d, Already freed",
5837*82527734SSukumar Swaminathan 		    fp->FCFI, fp->FCF_index);
5838*82527734SSukumar Swaminathan 		return;
5839*82527734SSukumar Swaminathan 	}
5840*82527734SSukumar Swaminathan 
5841*82527734SSukumar Swaminathan 	if (fp->outstandingVFIs) {
5842*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5843*82527734SSukumar Swaminathan 		    "Free FCFI:%d, %d outstanding VFIs", fp->FCFI,
5844*82527734SSukumar Swaminathan 		    fp->outstandingVFIs);
5845*82527734SSukumar Swaminathan 	}
5846*82527734SSukumar Swaminathan 	fp->state = RESOURCE_FREE;
5847*82527734SSukumar Swaminathan 	fp->FCF_index = 0;
5848*82527734SSukumar Swaminathan 	bzero(&fp->fcf_rec, sizeof (FCF_RECORD_t));
5849*82527734SSukumar Swaminathan 	fp->fcf_vfi = 0;
5850*82527734SSukumar Swaminathan 	fp->fcf_vpi = 0;
5851*82527734SSukumar Swaminathan 
5852*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5853*82527734SSukumar Swaminathan 
5854*82527734SSukumar Swaminathan } /* emlxs_sli4_free_fcfi() */
5855*82527734SSukumar Swaminathan 
5856*82527734SSukumar Swaminathan 
5857*82527734SSukumar Swaminathan extern void
5858*82527734SSukumar Swaminathan emlxs_sli4_free_vfi(emlxs_hba_t *hba, VFIobj_t *fp)
5859*82527734SSukumar Swaminathan {
5860*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5861*82527734SSukumar Swaminathan 
5862*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5863*82527734SSukumar Swaminathan 	if (fp->state == RESOURCE_FREE) {
5864*82527734SSukumar Swaminathan 		mutex_exit(&hba->sli.sli4.id_lock);
5865*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5866*82527734SSukumar Swaminathan 		    "Free VFI:%d, Already freed", fp->VFI);
5867*82527734SSukumar Swaminathan 		return;
5868*82527734SSukumar Swaminathan 	}
5869*82527734SSukumar Swaminathan 
5870*82527734SSukumar Swaminathan 	if (fp->outstandingVPIs) {
5871*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5872*82527734SSukumar Swaminathan 		    "Free VFI:%d, %d outstanding VPIs", fp->VFI,
5873*82527734SSukumar Swaminathan 		    fp->outstandingVPIs);
5874*82527734SSukumar Swaminathan 	}
5875*82527734SSukumar Swaminathan 	fp->state = RESOURCE_FREE;
5876*82527734SSukumar Swaminathan 	fp->FCFIp->outstandingVFIs--;
5877*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5878*82527734SSukumar Swaminathan 
5879*82527734SSukumar Swaminathan 	if ((fp->FCFIp->outstandingVFIs == 0) &&
5880*82527734SSukumar Swaminathan 	    (hba->state == FC_LINK_DOWN)) {
5881*82527734SSukumar Swaminathan 
5882*82527734SSukumar Swaminathan 		/* No more VPIs so unreg the VFI */
5883*82527734SSukumar Swaminathan 		(void) emlxs_mb_unreg_fcfi(hba, fp->FCFIp);
5884*82527734SSukumar Swaminathan 	}
5885*82527734SSukumar Swaminathan 	fp->FCFIp = NULL;
5886*82527734SSukumar Swaminathan 
5887*82527734SSukumar Swaminathan 
5888*82527734SSukumar Swaminathan } /* emlxs_sli4_free_vfi() */
5889*82527734SSukumar Swaminathan 
5890*82527734SSukumar Swaminathan 
5891*82527734SSukumar Swaminathan static void
5892*82527734SSukumar Swaminathan emlxs_sli4_free_vpi(emlxs_hba_t *hba, emlxs_port_t *pp)
5893*82527734SSukumar Swaminathan {
5894*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5895*82527734SSukumar Swaminathan 
5896*82527734SSukumar Swaminathan 	if (!(pp->flag & EMLXS_PORT_ENABLE)) {
5897*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5898*82527734SSukumar Swaminathan 		    "Free VPI:%d, Already freed", pp->vpi);
5899*82527734SSukumar Swaminathan 		return;
5900*82527734SSukumar Swaminathan 	}
5901*82527734SSukumar Swaminathan 
5902*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5903*82527734SSukumar Swaminathan 	if (pp->outstandingRPIs) {
5904*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5905*82527734SSukumar Swaminathan 		    "Free VPI:%d, %d outstanding RPIs", pp->vpi,
5906*82527734SSukumar Swaminathan 		    pp->outstandingRPIs);
5907*82527734SSukumar Swaminathan 	}
5908*82527734SSukumar Swaminathan 	pp->VFIp->outstandingVPIs--;
5909*82527734SSukumar Swaminathan 	if (pp->VFIp->outstandingVPIs == 0) {
5910*82527734SSukumar Swaminathan 		/* No more VPIs so unreg the VFI */
5911*82527734SSukumar Swaminathan 		(void) emlxs_mb_unreg_vfi(hba, pp->VFIp);
5912*82527734SSukumar Swaminathan 	}
5913*82527734SSukumar Swaminathan 
5914*82527734SSukumar Swaminathan 	pp->VFIp = NULL;
5915*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5916*82527734SSukumar Swaminathan 
5917*82527734SSukumar Swaminathan } /* emlxs_sli4_free_vpi() */
5918*82527734SSukumar Swaminathan 
5919*82527734SSukumar Swaminathan 
5920*82527734SSukumar Swaminathan static void
5921*82527734SSukumar Swaminathan emlxs_sli4_cmpl_io(emlxs_hba_t *hba, emlxs_buf_t *sbp)
5922*82527734SSukumar Swaminathan {
5923*82527734SSukumar Swaminathan 	CHANNEL *cp;
5924*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
5925*82527734SSukumar Swaminathan 	CQE_u cq_entry;
5926*82527734SSukumar Swaminathan 
5927*82527734SSukumar Swaminathan 	cp = sbp->channel;
5928*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
5929*82527734SSukumar Swaminathan 
5930*82527734SSukumar Swaminathan 	bzero((void *) &cq_entry, sizeof (CQE_u));
5931*82527734SSukumar Swaminathan 	cq_entry.cqCmplEntry.Status = IOSTAT_LOCAL_REJECT;
5932*82527734SSukumar Swaminathan 	cq_entry.cqCmplEntry.Parameter = IOERR_SEQUENCE_TIMEOUT;
5933*82527734SSukumar Swaminathan 	cq_entry.cqCmplEntry.RequestTag = sbp->iotag;
5934*82527734SSukumar Swaminathan 	emlxs_CQE_to_IOCB(hba, &cq_entry.cqCmplEntry, sbp);
5935*82527734SSukumar Swaminathan 
5936*82527734SSukumar Swaminathan 	/*
5937*82527734SSukumar Swaminathan 	 * If this is NOT a polled command completion
5938*82527734SSukumar Swaminathan 	 * or a driver allocated pkt, then defer pkt
5939*82527734SSukumar Swaminathan 	 * completion.
5940*82527734SSukumar Swaminathan 	 */
5941*82527734SSukumar Swaminathan 	if (!(sbp->pkt_flags &
5942*82527734SSukumar Swaminathan 	    (PACKET_POLLED | PACKET_ALLOCATED))) {
5943*82527734SSukumar Swaminathan 		/* Add the IOCB to the channel list */
5944*82527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
5945*82527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
5946*82527734SSukumar Swaminathan 			cp->rsp_head = iocbq;
5947*82527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
5948*82527734SSukumar Swaminathan 		} else {
5949*82527734SSukumar Swaminathan 			cp->rsp_tail->next = iocbq;
5950*82527734SSukumar Swaminathan 			cp->rsp_tail = iocbq;
5951*82527734SSukumar Swaminathan 		}
5952*82527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
5953*82527734SSukumar Swaminathan 
5954*82527734SSukumar Swaminathan 		/* Delay triggering thread till end of ISR */
5955*82527734SSukumar Swaminathan 		cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
5956*82527734SSukumar Swaminathan 	} else {
5957*82527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
5958*82527734SSukumar Swaminathan 	}
5959*82527734SSukumar Swaminathan } /* emlxs_sli4_cmpl_io() */
5960*82527734SSukumar Swaminathan 
5961*82527734SSukumar Swaminathan extern void
5962*82527734SSukumar Swaminathan emlxs_sli4_free_rpi(emlxs_hba_t *hba, RPIobj_t *rp)
5963*82527734SSukumar Swaminathan {
5964*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5965*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
5966*82527734SSukumar Swaminathan 	XRIobj_t	*next_xp;
5967*82527734SSukumar Swaminathan 
5968*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
5969*82527734SSukumar Swaminathan 	if (rp->state == RESOURCE_FREE) {
5970*82527734SSukumar Swaminathan 		mutex_exit(&hba->sli.sli4.id_lock);
5971*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5972*82527734SSukumar Swaminathan 		    "Free RPI:%d, Already freed", rp->RPI);
5973*82527734SSukumar Swaminathan 		return;
5974*82527734SSukumar Swaminathan 	}
5975*82527734SSukumar Swaminathan 	if (rp->outstandingXRIs) {
5976*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5977*82527734SSukumar Swaminathan 		    "Free RPI:%d, %d outstanding XRIs", rp->RPI,
5978*82527734SSukumar Swaminathan 		    rp->outstandingXRIs);
5979*82527734SSukumar Swaminathan 	}
5980*82527734SSukumar Swaminathan 	rp->state = RESOURCE_FREE;
5981*82527734SSukumar Swaminathan 	rp->VPIp = NULL;
5982*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
5983*82527734SSukumar Swaminathan 
5984*82527734SSukumar Swaminathan 	/* Break node/RPI binding */
5985*82527734SSukumar Swaminathan 	if (rp->node) {
5986*82527734SSukumar Swaminathan 		rw_enter(&port->node_rwlock, RW_WRITER);
5987*82527734SSukumar Swaminathan 		rp->node->RPIp = NULL;
5988*82527734SSukumar Swaminathan 		rp->node = NULL;
5989*82527734SSukumar Swaminathan 		rw_exit(&port->node_rwlock);
5990*82527734SSukumar Swaminathan 	}
5991*82527734SSukumar Swaminathan 
5992*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
5993*82527734SSukumar Swaminathan 	/* Remove all XRIs under this RPI */
5994*82527734SSukumar Swaminathan 	xp = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
5995*82527734SSukumar Swaminathan 	while (xp != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
5996*82527734SSukumar Swaminathan 		next_xp = xp->_f;
5997*82527734SSukumar Swaminathan 		if ((xp->state & RESOURCE_ALLOCATED) &&
5998*82527734SSukumar Swaminathan 		    (xp->RPIp == rp)) {
5999*82527734SSukumar Swaminathan 			xp->RPIp->outstandingXRIs--;
6000*82527734SSukumar Swaminathan 			xp->RPIp = NULL;
6001*82527734SSukumar Swaminathan 		}
6002*82527734SSukumar Swaminathan 		xp = next_xp;
6003*82527734SSukumar Swaminathan 	}
6004*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
6005*82527734SSukumar Swaminathan 
6006*82527734SSukumar Swaminathan } /* emlxs_sli4_free_rpi() */
6007*82527734SSukumar Swaminathan 
6008*82527734SSukumar Swaminathan 
6009*82527734SSukumar Swaminathan extern void
6010*82527734SSukumar Swaminathan emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xp)
6011*82527734SSukumar Swaminathan {
6012*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6013*82527734SSukumar Swaminathan 
6014*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
6015*82527734SSukumar Swaminathan 	if (xp) {
6016*82527734SSukumar Swaminathan 		if (xp->state == RESOURCE_FREE) {
6017*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_FCTAB_LOCK);
6018*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6019*82527734SSukumar Swaminathan 			    "Free XRI:%x, Already freed", xp->XRI);
6020*82527734SSukumar Swaminathan 			return;
6021*82527734SSukumar Swaminathan 		}
6022*82527734SSukumar Swaminathan 
6023*82527734SSukumar Swaminathan 		if (hba->fc_table[xp->iotag]) {
6024*82527734SSukumar Swaminathan 			hba->fc_table[xp->iotag] = NULL;
6025*82527734SSukumar Swaminathan 			hba->io_count--;
6026*82527734SSukumar Swaminathan 		}
6027*82527734SSukumar Swaminathan 
6028*82527734SSukumar Swaminathan 		xp->state = RESOURCE_FREE;
6029*82527734SSukumar Swaminathan 
6030*82527734SSukumar Swaminathan 		if (xp->RPIp) {
6031*82527734SSukumar Swaminathan 			xp->RPIp->outstandingXRIs--;
6032*82527734SSukumar Swaminathan 			xp->RPIp = NULL;
6033*82527734SSukumar Swaminathan 		}
6034*82527734SSukumar Swaminathan 
6035*82527734SSukumar Swaminathan 		/* Take it off inuse list */
6036*82527734SSukumar Swaminathan 		(xp->_b)->_f = xp->_f;
6037*82527734SSukumar Swaminathan 		(xp->_f)->_b = xp->_b;
6038*82527734SSukumar Swaminathan 		xp->_f = NULL;
6039*82527734SSukumar Swaminathan 		xp->_b = NULL;
6040*82527734SSukumar Swaminathan 		hba->sli.sli4.xria_count--;
6041*82527734SSukumar Swaminathan 
6042*82527734SSukumar Swaminathan 		/* Add it to end of free list */
6043*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIfree_tail->_f = xp;
6044*82527734SSukumar Swaminathan 		hba->sli.sli4.XRIfree_tail = xp;
6045*82527734SSukumar Swaminathan 		hba->sli.sli4.xrif_count++;
6046*82527734SSukumar Swaminathan 	}
6047*82527734SSukumar Swaminathan 
6048*82527734SSukumar Swaminathan 	if (sbp) {
6049*82527734SSukumar Swaminathan 		sbp->xp = 0;
6050*82527734SSukumar Swaminathan 
6051*82527734SSukumar Swaminathan 		if (xp && (xp->iotag != sbp->iotag)) {
6052*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6053*82527734SSukumar Swaminathan 			    "sbp / iotag mismatch %p iotag:%d %d", sbp,
6054*82527734SSukumar Swaminathan 			    sbp->iotag, xp->iotag);
6055*82527734SSukumar Swaminathan 		}
6056*82527734SSukumar Swaminathan 
6057*82527734SSukumar Swaminathan 		if (sbp->iotag) {
6058*82527734SSukumar Swaminathan 			if (hba->fc_table[sbp->iotag]) {
6059*82527734SSukumar Swaminathan 				hba->fc_table[sbp->iotag] = NULL;
6060*82527734SSukumar Swaminathan 				hba->io_count--;
6061*82527734SSukumar Swaminathan 			}
6062*82527734SSukumar Swaminathan 			sbp->iotag = 0;
6063*82527734SSukumar Swaminathan 		}
6064*82527734SSukumar Swaminathan 
6065*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
6066*82527734SSukumar Swaminathan 
6067*82527734SSukumar Swaminathan 		/* Clean up the sbp */
6068*82527734SSukumar Swaminathan 		mutex_enter(&sbp->mtx);
6069*82527734SSukumar Swaminathan 
6070*82527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_TXQ) {
6071*82527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_TXQ;
6072*82527734SSukumar Swaminathan 			hba->channel_tx_count--;
6073*82527734SSukumar Swaminathan 		}
6074*82527734SSukumar Swaminathan 
6075*82527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
6076*82527734SSukumar Swaminathan 			sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
6077*82527734SSukumar Swaminathan 		}
6078*82527734SSukumar Swaminathan 
6079*82527734SSukumar Swaminathan 		mutex_exit(&sbp->mtx);
6080*82527734SSukumar Swaminathan 	} else {
6081*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_FCTAB_LOCK);
6082*82527734SSukumar Swaminathan 	}
6083*82527734SSukumar Swaminathan 
6084*82527734SSukumar Swaminathan } /* emlxs_sli4_free_xri() */
6085*82527734SSukumar Swaminathan 
6086*82527734SSukumar Swaminathan 
6087*82527734SSukumar Swaminathan static int
6088*82527734SSukumar Swaminathan emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
6089*82527734SSukumar Swaminathan {
6090*82527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6091*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6092*82527734SSukumar Swaminathan 	XRIobj_t	*xp;
6093*82527734SSukumar Swaminathan 	MATCHMAP	*mp;
6094*82527734SSukumar Swaminathan 	mbox_req_hdr_t 	*hdr_req;
6095*82527734SSukumar Swaminathan 	uint32_t	i, cnt, xri_cnt;
6096*82527734SSukumar Swaminathan 	uint32_t	size;
6097*82527734SSukumar Swaminathan 	IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
6098*82527734SSukumar Swaminathan 
6099*82527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
6100*82527734SSukumar Swaminathan 	mbq->bp = NULL;
6101*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
6102*82527734SSukumar Swaminathan 
6103*82527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
6104*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6105*82527734SSukumar Swaminathan 		    "Unable to POST_SGL. Mailbox cmd=%x  ",
6106*82527734SSukumar Swaminathan 		    mb->mbxCommand);
6107*82527734SSukumar Swaminathan 		return (EIO);
6108*82527734SSukumar Swaminathan 	}
6109*82527734SSukumar Swaminathan 	mbq->nonembed = (uint8_t *)mp;
6110*82527734SSukumar Swaminathan 
6111*82527734SSukumar Swaminathan 	/*
6112*82527734SSukumar Swaminathan 	 * Signifies a non embedded command
6113*82527734SSukumar Swaminathan 	 */
6114*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
6115*82527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
6116*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
6117*82527734SSukumar Swaminathan 
6118*82527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
6119*82527734SSukumar Swaminathan 	post_sgl =
6120*82527734SSukumar Swaminathan 	    (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
6121*82527734SSukumar Swaminathan 
6122*82527734SSukumar Swaminathan 
6123*82527734SSukumar Swaminathan 	xp = hba->sli.sli4.XRIp;
6124*82527734SSukumar Swaminathan 	cnt = hba->sli.sli4.XRICount;
6125*82527734SSukumar Swaminathan 	while (cnt) {
6126*82527734SSukumar Swaminathan 		bzero((void *) hdr_req, mp->size);
6127*82527734SSukumar Swaminathan 		size = mp->size - IOCTL_HEADER_SZ;
6128*82527734SSukumar Swaminathan 
6129*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.payload_length =
6130*82527734SSukumar Swaminathan 		    mp->size;
6131*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
6132*82527734SSukumar Swaminathan 		    IOCTL_SUBSYSTEM_FCOE;
6133*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
6134*82527734SSukumar Swaminathan 		    FCOE_OPCODE_CFG_POST_SGL_PAGES;
6135*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
6136*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
6137*82527734SSukumar Swaminathan 
6138*82527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
6139*82527734SSukumar Swaminathan 		hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
6140*82527734SSukumar Swaminathan 		hdr_req->timeout = 0;
6141*82527734SSukumar Swaminathan 		hdr_req->req_length = size;
6142*82527734SSukumar Swaminathan 
6143*82527734SSukumar Swaminathan 		post_sgl->params.request.xri_count = 0;
6144*82527734SSukumar Swaminathan 		post_sgl->params.request.xri_start = xp->XRI;
6145*82527734SSukumar Swaminathan 		xri_cnt = (size - sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
6146*82527734SSukumar Swaminathan 		    sizeof (FCOE_SGL_PAGES);
6147*82527734SSukumar Swaminathan 		for (i = 0; i < xri_cnt; i++) {
6148*82527734SSukumar Swaminathan 
6149*82527734SSukumar Swaminathan 			post_sgl->params.request.xri_count++;
6150*82527734SSukumar Swaminathan 			post_sgl->params.request.pages[i].sgl_page0.addrLow =
6151*82527734SSukumar Swaminathan 			    PADDR_LO(xp->SGList.phys);
6152*82527734SSukumar Swaminathan 			post_sgl->params.request.pages[i].sgl_page0.addrHigh =
6153*82527734SSukumar Swaminathan 			    PADDR_HI(xp->SGList.phys);
6154*82527734SSukumar Swaminathan 			cnt--;
6155*82527734SSukumar Swaminathan 			xp++;
6156*82527734SSukumar Swaminathan 			if (cnt == 0) {
6157*82527734SSukumar Swaminathan 				break;
6158*82527734SSukumar Swaminathan 			}
6159*82527734SSukumar Swaminathan 		}
6160*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6161*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
6162*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6163*82527734SSukumar Swaminathan 			    "Unable to POST_SGL. Mailbox cmd=%x status=%x "
6164*82527734SSukumar Swaminathan 			    "XRI cnt:%d start:%d",
6165*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus,
6166*82527734SSukumar Swaminathan 			    post_sgl->params.request.xri_count,
6167*82527734SSukumar Swaminathan 			    post_sgl->params.request.xri_start);
6168*82527734SSukumar Swaminathan 			(void) emlxs_mem_buf_free(hba, mp);
6169*82527734SSukumar Swaminathan 			mbq->nonembed = (uint8_t *)NULL;
6170*82527734SSukumar Swaminathan 			return (EIO);
6171*82527734SSukumar Swaminathan 		}
6172*82527734SSukumar Swaminathan 	}
6173*82527734SSukumar Swaminathan 	(void) emlxs_mem_buf_free(hba, mp);
6174*82527734SSukumar Swaminathan 	mbq->nonembed = (uint8_t *)NULL;
6175*82527734SSukumar Swaminathan 	return (0);
6176*82527734SSukumar Swaminathan 
6177*82527734SSukumar Swaminathan } /* emlxs_sli4_post_sgl_pages() */
6178*82527734SSukumar Swaminathan 
6179*82527734SSukumar Swaminathan 
6180*82527734SSukumar Swaminathan static int
6181*82527734SSukumar Swaminathan emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
6182*82527734SSukumar Swaminathan {
6183*82527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6184*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6185*82527734SSukumar Swaminathan 	int		i, cnt;
6186*82527734SSukumar Swaminathan 	uint64_t	addr;
6187*82527734SSukumar Swaminathan 	IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
6188*82527734SSukumar Swaminathan 
6189*82527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
6190*82527734SSukumar Swaminathan 	mbq->bp = NULL;
6191*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
6192*82527734SSukumar Swaminathan 
6193*82527734SSukumar Swaminathan 	/*
6194*82527734SSukumar Swaminathan 	 * Signifies an embedded command
6195*82527734SSukumar Swaminathan 	 */
6196*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 1;
6197*82527734SSukumar Swaminathan 
6198*82527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
6199*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
6200*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.payload_length =
6201*82527734SSukumar Swaminathan 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
6202*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
6203*82527734SSukumar Swaminathan 	    IOCTL_SUBSYSTEM_FCOE;
6204*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
6205*82527734SSukumar Swaminathan 	    FCOE_OPCODE_POST_HDR_TEMPLATES;
6206*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
6207*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
6208*82527734SSukumar Swaminathan 	    sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
6209*82527734SSukumar Swaminathan 	post_hdr =
6210*82527734SSukumar Swaminathan 	    (IOCTL_FCOE_POST_HDR_TEMPLATES *)&mb->un.varSLIConfig.payload;
6211*82527734SSukumar Swaminathan 	addr = hba->sli.sli4.HeaderTmplate.phys;
6212*82527734SSukumar Swaminathan 	post_hdr->params.request.num_pages = 0;
6213*82527734SSukumar Swaminathan 	i = 0;
6214*82527734SSukumar Swaminathan 	cnt = hba->sli.sli4.HeaderTmplate.size;
6215*82527734SSukumar Swaminathan 	while (cnt > 0) {
6216*82527734SSukumar Swaminathan 		post_hdr->params.request.num_pages++;
6217*82527734SSukumar Swaminathan 		post_hdr->params.request.pages[i].addrLow = PADDR_LO(addr);
6218*82527734SSukumar Swaminathan 		post_hdr->params.request.pages[i].addrHigh = PADDR_HI(addr);
6219*82527734SSukumar Swaminathan 		i++;
6220*82527734SSukumar Swaminathan 		addr += 4096;
6221*82527734SSukumar Swaminathan 		cnt -= 4096;
6222*82527734SSukumar Swaminathan 	}
6223*82527734SSukumar Swaminathan 	post_hdr->params.request.starting_rpi_index = hba->sli.sli4.RPIBase;
6224*82527734SSukumar Swaminathan 
6225*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6226*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
6227*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6228*82527734SSukumar Swaminathan 		    "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x status=%x ",
6229*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
6230*82527734SSukumar Swaminathan 		return (EIO);
6231*82527734SSukumar Swaminathan 	}
6232*82527734SSukumar Swaminathan emlxs_data_dump(hba, "POST_HDR", (uint32_t *)mb, 18, 0);
6233*82527734SSukumar Swaminathan 	return (0);
6234*82527734SSukumar Swaminathan 
6235*82527734SSukumar Swaminathan } /* emlxs_sli4_post_hdr_tmplates() */
6236*82527734SSukumar Swaminathan 
6237*82527734SSukumar Swaminathan 
6238*82527734SSukumar Swaminathan static int
6239*82527734SSukumar Swaminathan emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
6240*82527734SSukumar Swaminathan {
6241*82527734SSukumar Swaminathan 	MAILBOX4	*mb = (MAILBOX4 *)mbq;
6242*82527734SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
6243*82527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
6244*82527734SSukumar Swaminathan 	IOCTL_COMMON_EQ_CREATE *eq;
6245*82527734SSukumar Swaminathan 	IOCTL_COMMON_CQ_CREATE *cq;
6246*82527734SSukumar Swaminathan 	IOCTL_FCOE_WQ_CREATE *wq;
6247*82527734SSukumar Swaminathan 	IOCTL_FCOE_RQ_CREATE *rq;
6248*82527734SSukumar Swaminathan 	IOCTL_COMMON_MQ_CREATE *mq;
6249*82527734SSukumar Swaminathan 	emlxs_rqdbu_t	rqdb;
6250*82527734SSukumar Swaminathan 	int i, j;
6251*82527734SSukumar Swaminathan 	int num_cq, total_cq;
6252*82527734SSukumar Swaminathan 	int num_wq, total_wq;
6253*82527734SSukumar Swaminathan 
6254*82527734SSukumar Swaminathan 	/*
6255*82527734SSukumar Swaminathan 	 * The first CQ is reserved for ASYNC events,
6256*82527734SSukumar Swaminathan 	 * the second is reserved for unsol rcv, the rest
6257*82527734SSukumar Swaminathan 	 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
6258*82527734SSukumar Swaminathan 	 */
6259*82527734SSukumar Swaminathan 
6260*82527734SSukumar Swaminathan 	/* First initialize queue ordinal mapping */
6261*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) {
6262*82527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[i] = 0xffff;
6263*82527734SSukumar Swaminathan 	}
6264*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_CQ_IDS; i++) {
6265*82527734SSukumar Swaminathan 		hba->sli.sli4.cq_map[i] = 0xffff;
6266*82527734SSukumar Swaminathan 	}
6267*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_WQ_IDS; i++) {
6268*82527734SSukumar Swaminathan 		hba->sli.sli4.wq_map[i] = 0xffff;
6269*82527734SSukumar Swaminathan 	}
6270*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQ_IDS; i++) {
6271*82527734SSukumar Swaminathan 		hba->sli.sli4.rq_map[i] = 0xffff;
6272*82527734SSukumar Swaminathan 	}
6273*82527734SSukumar Swaminathan 
6274*82527734SSukumar Swaminathan 	total_cq = 0;
6275*82527734SSukumar Swaminathan 	total_wq = 0;
6276*82527734SSukumar Swaminathan 
6277*82527734SSukumar Swaminathan 	/* Create EQ's */
6278*82527734SSukumar Swaminathan 	for (i = 0; i < hba->intr_count; i++) {
6279*82527734SSukumar Swaminathan 		emlxs_mb_eq_create(hba, mbq, i);
6280*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6281*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
6282*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6283*82527734SSukumar Swaminathan 			    "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
6284*82527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
6285*82527734SSukumar Swaminathan 			return (EIO);
6286*82527734SSukumar Swaminathan 		}
6287*82527734SSukumar Swaminathan 		eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
6288*82527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
6289*82527734SSukumar Swaminathan 		hba->sli.sli4.eq_map[eq->params.response.EQId] = i;
6290*82527734SSukumar Swaminathan 		hba->sli.sli4.eq[i].lastwq = total_wq;
6291*82527734SSukumar Swaminathan 
6292*82527734SSukumar Swaminathan emlxs_data_dump(hba, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
6293*82527734SSukumar Swaminathan 		num_wq = cfg[CFG_NUM_WQ].current;
6294*82527734SSukumar Swaminathan 		num_cq = num_wq;
6295*82527734SSukumar Swaminathan 		if (i == 0) {
6296*82527734SSukumar Swaminathan 			/* One for RQ handling, one for mbox/event handling */
6297*82527734SSukumar Swaminathan 			num_cq += EMLXS_CQ_OFFSET_WQ;
6298*82527734SSukumar Swaminathan 		}
6299*82527734SSukumar Swaminathan 
6300*82527734SSukumar Swaminathan 		for (j = 0; j < num_cq; j++) {
6301*82527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
6302*82527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
6303*82527734SSukumar Swaminathan 
6304*82527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].eqid =
6305*82527734SSukumar Swaminathan 			    hba->sli.sli4.eq[i].qid;
6306*82527734SSukumar Swaminathan 
6307*82527734SSukumar Swaminathan 			emlxs_mb_cq_create(hba, mbq, total_cq);
6308*82527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6309*82527734SSukumar Swaminathan 			    MBX_SUCCESS) {
6310*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
6311*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
6312*82527734SSukumar Swaminathan 				    "CQ %d: Mailbox cmd=%x status=%x ",
6313*82527734SSukumar Swaminathan 				    total_cq, mb->mbxCommand, mb->mbxStatus);
6314*82527734SSukumar Swaminathan 				return (EIO);
6315*82527734SSukumar Swaminathan 			}
6316*82527734SSukumar Swaminathan 			cq = (IOCTL_COMMON_CQ_CREATE *)
6317*82527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
6318*82527734SSukumar Swaminathan 			hba->sli.sli4.cq[total_cq].qid =
6319*82527734SSukumar Swaminathan 			    cq->params.response.CQId;
6320*82527734SSukumar Swaminathan 			hba->sli.sli4.cq_map[cq->params.response.CQId] =
6321*82527734SSukumar Swaminathan 			    total_cq;
6322*82527734SSukumar Swaminathan 
6323*82527734SSukumar Swaminathan 			switch (total_cq) {
6324*82527734SSukumar Swaminathan 			case EMLXS_CQ_MBOX:
6325*82527734SSukumar Swaminathan 				/* First CQ is for async event handling */
6326*82527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
6327*82527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP1;
6328*82527734SSukumar Swaminathan 				break;
6329*82527734SSukumar Swaminathan 
6330*82527734SSukumar Swaminathan 			case EMLXS_CQ_RCV:
6331*82527734SSukumar Swaminathan 				/* Second CQ is for unsol receive handling */
6332*82527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
6333*82527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
6334*82527734SSukumar Swaminathan 				break;
6335*82527734SSukumar Swaminathan 
6336*82527734SSukumar Swaminathan 			default:
6337*82527734SSukumar Swaminathan 				/* Setup CQ to channel mapping */
6338*82527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].type =
6339*82527734SSukumar Swaminathan 				    EMLXS_CQ_TYPE_GROUP2;
6340*82527734SSukumar Swaminathan 				hba->sli.sli4.cq[total_cq].channelp =
6341*82527734SSukumar Swaminathan 				    &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
6342*82527734SSukumar Swaminathan 				break;
6343*82527734SSukumar Swaminathan 			}
6344*82527734SSukumar Swaminathan emlxs_data_dump(hba, "CQX_CREATE", (uint32_t *)mb, 18, 0);
6345*82527734SSukumar Swaminathan 			total_cq++;
6346*82527734SSukumar Swaminathan 		}
6347*82527734SSukumar Swaminathan 
6348*82527734SSukumar Swaminathan 		for (j = 0; j < num_wq; j++) {
6349*82527734SSukumar Swaminathan 			/* Reuse mbq from previous mbox */
6350*82527734SSukumar Swaminathan 			bzero(mbq, sizeof (MAILBOXQ));
6351*82527734SSukumar Swaminathan 
6352*82527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
6353*82527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
6354*82527734SSukumar Swaminathan 
6355*82527734SSukumar Swaminathan 			emlxs_mb_wq_create(hba, mbq, total_wq);
6356*82527734SSukumar Swaminathan 			if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6357*82527734SSukumar Swaminathan 			    MBX_SUCCESS) {
6358*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
6359*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg, "Unable to Create "
6360*82527734SSukumar Swaminathan 				    "WQ %d: Mailbox cmd=%x status=%x ",
6361*82527734SSukumar Swaminathan 				    total_wq, mb->mbxCommand, mb->mbxStatus);
6362*82527734SSukumar Swaminathan 				return (EIO);
6363*82527734SSukumar Swaminathan 			}
6364*82527734SSukumar Swaminathan 			wq = (IOCTL_FCOE_WQ_CREATE *)
6365*82527734SSukumar Swaminathan 			    &mb->un.varSLIConfig.payload;
6366*82527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].qid =
6367*82527734SSukumar Swaminathan 			    wq->params.response.WQId;
6368*82527734SSukumar Swaminathan 			hba->sli.sli4.wq_map[wq->params.response.WQId] =
6369*82527734SSukumar Swaminathan 			    total_wq;
6370*82527734SSukumar Swaminathan 
6371*82527734SSukumar Swaminathan 			hba->sli.sli4.wq[total_wq].cqid =
6372*82527734SSukumar Swaminathan 			    hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
6373*82527734SSukumar Swaminathan emlxs_data_dump(hba, "WQ_CREATE", (uint32_t *)mb, 18, 0);
6374*82527734SSukumar Swaminathan 			total_wq++;
6375*82527734SSukumar Swaminathan 		}
6376*82527734SSukumar Swaminathan 	}
6377*82527734SSukumar Swaminathan 
6378*82527734SSukumar Swaminathan 	/* We assume 1 RQ pair will handle ALL incoming data */
6379*82527734SSukumar Swaminathan 	/* Create RQs */
6380*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_MAX_RQS; i++) {
6381*82527734SSukumar Swaminathan 		/* Personalize the RQ */
6382*82527734SSukumar Swaminathan 		switch (i) {
6383*82527734SSukumar Swaminathan 		case 0:
6384*82527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
6385*82527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
6386*82527734SSukumar Swaminathan 			break;
6387*82527734SSukumar Swaminathan 		case 1:
6388*82527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid =
6389*82527734SSukumar Swaminathan 			    hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
6390*82527734SSukumar Swaminathan 			break;
6391*82527734SSukumar Swaminathan 		default:
6392*82527734SSukumar Swaminathan 			hba->sli.sli4.rq[i].cqid = 0xffff;
6393*82527734SSukumar Swaminathan 		}
6394*82527734SSukumar Swaminathan 
6395*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
6396*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
6397*82527734SSukumar Swaminathan 
6398*82527734SSukumar Swaminathan 		emlxs_mb_rq_create(hba, mbq, i);
6399*82527734SSukumar Swaminathan 		if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6400*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
6401*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6402*82527734SSukumar Swaminathan 			    "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
6403*82527734SSukumar Swaminathan 			    i, mb->mbxCommand, mb->mbxStatus);
6404*82527734SSukumar Swaminathan 			return (EIO);
6405*82527734SSukumar Swaminathan 		}
6406*82527734SSukumar Swaminathan 		rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
6407*82527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
6408*82527734SSukumar Swaminathan 		hba->sli.sli4.rq_map[rq->params.response.RQId] = i;
6409*82527734SSukumar Swaminathan emlxs_data_dump(hba, "RQ CREATE", (uint32_t *)mb, 18, 0);
6410*82527734SSukumar Swaminathan 
6411*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6412*82527734SSukumar Swaminathan 		    "RQ CREATE: rq[%d].qid=%d cqid=%d",
6413*82527734SSukumar Swaminathan 		    i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
6414*82527734SSukumar Swaminathan 
6415*82527734SSukumar Swaminathan 		/* Initialize the host_index */
6416*82527734SSukumar Swaminathan 		hba->sli.sli4.rq[i].host_index = 0;
6417*82527734SSukumar Swaminathan 
6418*82527734SSukumar Swaminathan 		/* If Data queue was just created, */
6419*82527734SSukumar Swaminathan 		/* then post buffers using the header qid */
6420*82527734SSukumar Swaminathan 		if ((i & 0x1)) {
6421*82527734SSukumar Swaminathan 			/* Ring the RQ doorbell to post buffers */
6422*82527734SSukumar Swaminathan 			rqdb.word = 0;
6423*82527734SSukumar Swaminathan 			rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
6424*82527734SSukumar Swaminathan 			rqdb.db.NumPosted = RQB_COUNT;
6425*82527734SSukumar Swaminathan 
6426*82527734SSukumar Swaminathan 			WRITE_BAR2_REG(hba, FC_RQDB_REG(hba), rqdb.word);
6427*82527734SSukumar Swaminathan 
6428*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6429*82527734SSukumar Swaminathan 			    "RQ CREATE: Doorbell rang: qid=%d count=%d",
6430*82527734SSukumar Swaminathan 			    hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
6431*82527734SSukumar Swaminathan 		}
6432*82527734SSukumar Swaminathan 	}
6433*82527734SSukumar Swaminathan 
6434*82527734SSukumar Swaminathan 	/* Create MQ */
6435*82527734SSukumar Swaminathan 
6436*82527734SSukumar Swaminathan 	/* Personalize the MQ */
6437*82527734SSukumar Swaminathan 	hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
6438*82527734SSukumar Swaminathan 
6439*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
6440*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
6441*82527734SSukumar Swaminathan 
6442*82527734SSukumar Swaminathan 	emlxs_mb_mq_create(hba, mbq);
6443*82527734SSukumar Swaminathan 	if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
6444*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
6445*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6446*82527734SSukumar Swaminathan 		    "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
6447*82527734SSukumar Swaminathan 		    i, mb->mbxCommand, mb->mbxStatus);
6448*82527734SSukumar Swaminathan 		return (EIO);
6449*82527734SSukumar Swaminathan 	}
6450*82527734SSukumar Swaminathan 	mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
6451*82527734SSukumar Swaminathan 	hba->sli.sli4.mq.qid = mq->params.response.MQId;
6452*82527734SSukumar Swaminathan 	return (0);
6453*82527734SSukumar Swaminathan 
6454*82527734SSukumar Swaminathan } /* emlxs_sli4_create_queues() */
6455*82527734SSukumar Swaminathan 
6456*82527734SSukumar Swaminathan 
6457*82527734SSukumar Swaminathan static int
6458*82527734SSukumar Swaminathan emlxs_fcf_bind(emlxs_hba_t *hba)
6459*82527734SSukumar Swaminathan {
6460*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
6461*82527734SSukumar Swaminathan 	int rc;
6462*82527734SSukumar Swaminathan 
6463*82527734SSukumar Swaminathan 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
6464*82527734SSukumar Swaminathan 		return (0);
6465*82527734SSukumar Swaminathan 	}
6466*82527734SSukumar Swaminathan 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
6467*82527734SSukumar Swaminathan 		/*
6468*82527734SSukumar Swaminathan 		 * If the firmware donesn't support FIP, we must
6469*82527734SSukumar Swaminathan 		 * build the fcf table manually first.
6470*82527734SSukumar Swaminathan 		 */
6471*82527734SSukumar Swaminathan 		rc =  emlxs_mbext_add_fcf_table(hba, mbq, 0);
6472*82527734SSukumar Swaminathan 	} else {
6473*82527734SSukumar Swaminathan 		rc =  emlxs_mbext_read_fcf_table(hba, mbq, -1);
6474*82527734SSukumar Swaminathan 	}
6475*82527734SSukumar Swaminathan 
6476*82527734SSukumar Swaminathan 	if (rc == 0) {
6477*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6478*82527734SSukumar Swaminathan 		return (0);
6479*82527734SSukumar Swaminathan 	}
6480*82527734SSukumar Swaminathan 
6481*82527734SSukumar Swaminathan 	rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
6482*82527734SSukumar Swaminathan 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
6483*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6484*82527734SSukumar Swaminathan 	}
6485*82527734SSukumar Swaminathan 	return (1);
6486*82527734SSukumar Swaminathan 
6487*82527734SSukumar Swaminathan } /* emlxs_fcf_bind() */
6488*82527734SSukumar Swaminathan 
6489*82527734SSukumar Swaminathan 
6490*82527734SSukumar Swaminathan static int
6491*82527734SSukumar Swaminathan emlxs_fcf_unbind(emlxs_hba_t *hba, uint32_t index)
6492*82527734SSukumar Swaminathan {
6493*82527734SSukumar Swaminathan 	FCFIobj_t *fp;
6494*82527734SSukumar Swaminathan 	int i;
6495*82527734SSukumar Swaminathan 
6496*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
6497*82527734SSukumar Swaminathan 	/* Loop thru all FCFIs */
6498*82527734SSukumar Swaminathan 	fp = hba->sli.sli4.FCFIp;
6499*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.FCFICount; i++) {
6500*82527734SSukumar Swaminathan 		if ((index == MAX_FCFCONNECTLIST_ENTRIES) ||
6501*82527734SSukumar Swaminathan 		    (index == fp->FCF_index)) {
6502*82527734SSukumar Swaminathan 			if (fp->state & RESOURCE_ALLOCATED) {
6503*82527734SSukumar Swaminathan 				mutex_exit(&hba->sli.sli4.id_lock);
6504*82527734SSukumar Swaminathan 				if (hba->state > FC_LINK_DOWN) {
6505*82527734SSukumar Swaminathan 					fp->state &= ~RESOURCE_FCFI_DISC;
6506*82527734SSukumar Swaminathan 					/* Declare link down here */
6507*82527734SSukumar Swaminathan 					emlxs_linkdown(hba);
6508*82527734SSukumar Swaminathan 				}
6509*82527734SSukumar Swaminathan 				/* There should only be 1 FCF for now */
6510*82527734SSukumar Swaminathan 				return (1);
6511*82527734SSukumar Swaminathan 			}
6512*82527734SSukumar Swaminathan 		}
6513*82527734SSukumar Swaminathan 	}
6514*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
6515*82527734SSukumar Swaminathan 	return (0);
6516*82527734SSukumar Swaminathan 
6517*82527734SSukumar Swaminathan } /* emlxs_fcf_unbind() */
6518*82527734SSukumar Swaminathan 
6519*82527734SSukumar Swaminathan 
6520*82527734SSukumar Swaminathan /*ARGSUSED*/
6521*82527734SSukumar Swaminathan extern int
6522*82527734SSukumar Swaminathan emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
6523*82527734SSukumar Swaminathan {
6524*82527734SSukumar Swaminathan 	int i;
6525*82527734SSukumar Swaminathan 
6526*82527734SSukumar Swaminathan 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
6527*82527734SSukumar Swaminathan 		if (!hba->sli.sli4.cfgFCOE.length) {
6528*82527734SSukumar Swaminathan 			/* Nothing specified, so everything matches */
6529*82527734SSukumar Swaminathan 			/* For nonFIP only use index 0 */
6530*82527734SSukumar Swaminathan 			if (fcfrec->fcf_index == 0) {
6531*82527734SSukumar Swaminathan 				return (1);  /* success */
6532*82527734SSukumar Swaminathan 			}
6533*82527734SSukumar Swaminathan 			return (0);
6534*82527734SSukumar Swaminathan 		}
6535*82527734SSukumar Swaminathan 
6536*82527734SSukumar Swaminathan 		/* Just check FCMap for now */
6537*82527734SSukumar Swaminathan 		if (bcmp((char *)fcfrec->fc_map,
6538*82527734SSukumar Swaminathan 		    hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
6539*82527734SSukumar Swaminathan 			return (1);  /* success */
6540*82527734SSukumar Swaminathan 		}
6541*82527734SSukumar Swaminathan 		return (0);
6542*82527734SSukumar Swaminathan 	}
6543*82527734SSukumar Swaminathan 
6544*82527734SSukumar Swaminathan 	/* For FIP mode, the FCF record must match Config Region 23 */
6545*82527734SSukumar Swaminathan 
6546*82527734SSukumar Swaminathan 	if (!hba->sli.sli4.cfgFCF.length) {
6547*82527734SSukumar Swaminathan 		/* Nothing specified, so everything matches */
6548*82527734SSukumar Swaminathan 		return (1);  /* success */
6549*82527734SSukumar Swaminathan 	}
6550*82527734SSukumar Swaminathan 
6551*82527734SSukumar Swaminathan 	/* Just check FabricName for now */
6552*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_FCFCONNECTLIST_ENTRIES; i++) {
6553*82527734SSukumar Swaminathan 		if ((hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) &&
6554*82527734SSukumar Swaminathan 		    (bcmp((char *)fcfrec->fabric_name_identifier,
6555*82527734SSukumar Swaminathan 		    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0)) {
6556*82527734SSukumar Swaminathan 			return (1);  /* success */
6557*82527734SSukumar Swaminathan 		}
6558*82527734SSukumar Swaminathan 	}
6559*82527734SSukumar Swaminathan 	return (0);
6560*82527734SSukumar Swaminathan }
6561*82527734SSukumar Swaminathan 
6562*82527734SSukumar Swaminathan 
6563*82527734SSukumar Swaminathan extern FCFIobj_t *
6564*82527734SSukumar Swaminathan emlxs_sli4_assign_fcfi(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
6565*82527734SSukumar Swaminathan {
6566*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6567*82527734SSukumar Swaminathan 	FCFIobj_t *fcfp;
6568*82527734SSukumar Swaminathan 	int i;
6569*82527734SSukumar Swaminathan 
6570*82527734SSukumar Swaminathan 	fcfp = emlxs_sli4_find_fcfi_fcfrec(hba, fcfrec);
6571*82527734SSukumar Swaminathan 	if (!fcfp) {
6572*82527734SSukumar Swaminathan 		fcfp = emlxs_sli4_alloc_fcfi(hba);
6573*82527734SSukumar Swaminathan 		if (!fcfp) {
6574*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6575*82527734SSukumar Swaminathan 			    "Unable to alloc FCFI for fcf index %d",
6576*82527734SSukumar Swaminathan 			    fcfrec->fcf_index);
6577*82527734SSukumar Swaminathan 			return (0);
6578*82527734SSukumar Swaminathan 		}
6579*82527734SSukumar Swaminathan 		fcfp->FCF_index = fcfrec->fcf_index;
6580*82527734SSukumar Swaminathan 	}
6581*82527734SSukumar Swaminathan 
6582*82527734SSukumar Swaminathan 	bcopy((char *)fcfrec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t));
6583*82527734SSukumar Swaminathan 
6584*82527734SSukumar Swaminathan 	for (i = 0; i < 512; i++) {
6585*82527734SSukumar Swaminathan 		if (fcfrec->vlan_bitmap[i / 8] == (1 << (i % 8))) {
6586*82527734SSukumar Swaminathan 			fcfp->vlan_id = i;
6587*82527734SSukumar Swaminathan 			fcfp->state |= RESOURCE_FCFI_VLAN_ID;
6588*82527734SSukumar Swaminathan 			break;
6589*82527734SSukumar Swaminathan 		}
6590*82527734SSukumar Swaminathan 	}
6591*82527734SSukumar Swaminathan 
6592*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6593*82527734SSukumar Swaminathan 	    "FCFI %d: idx %x av %x val %x ste %x macp %x vid %x "
6594*82527734SSukumar Swaminathan 	    "addr: %02x:%02x:%02x:%02x:%02x:%02x",
6595*82527734SSukumar Swaminathan 	    fcfp->FCFI,
6596*82527734SSukumar Swaminathan 	    fcfrec->fcf_index,
6597*82527734SSukumar Swaminathan 	    fcfrec->fcf_available,
6598*82527734SSukumar Swaminathan 	    fcfrec->fcf_valid,
6599*82527734SSukumar Swaminathan 	    fcfrec->fcf_state,
6600*82527734SSukumar Swaminathan 	    fcfrec->mac_address_provider,
6601*82527734SSukumar Swaminathan 	    fcfp->vlan_id,
6602*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_hi[0],
6603*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_hi[1],
6604*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_hi[2],
6605*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_hi[3],
6606*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_low[0],
6607*82527734SSukumar Swaminathan 	    fcfrec->fcf_mac_address_low[1]);
6608*82527734SSukumar Swaminathan 
6609*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6610*82527734SSukumar Swaminathan 	    "fabric: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
6611*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[0],
6612*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[1],
6613*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[2],
6614*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[3],
6615*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[4],
6616*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[5],
6617*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[6],
6618*82527734SSukumar Swaminathan 	    fcfrec->fabric_name_identifier[7]);
6619*82527734SSukumar Swaminathan 
6620*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6621*82527734SSukumar Swaminathan 	    "switch: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
6622*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[0],
6623*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[1],
6624*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[2],
6625*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[3],
6626*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[4],
6627*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[5],
6628*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[6],
6629*82527734SSukumar Swaminathan 	    fcfrec->switch_name_identifier[7]);
6630*82527734SSukumar Swaminathan 
6631*82527734SSukumar Swaminathan 	return (fcfp);
6632*82527734SSukumar Swaminathan 
6633*82527734SSukumar Swaminathan } /* emlxs_sli4_assign_fcfi() */
6634*82527734SSukumar Swaminathan 
6635*82527734SSukumar Swaminathan 
6636*82527734SSukumar Swaminathan extern FCFIobj_t *
6637*82527734SSukumar Swaminathan emlxs_sli4_bind_fcfi(emlxs_hba_t *hba)
6638*82527734SSukumar Swaminathan {
6639*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6640*82527734SSukumar Swaminathan 	FCFIobj_t *fp;
6641*82527734SSukumar Swaminathan 	VFIobj_t *vfip;
6642*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
6643*82527734SSukumar Swaminathan 	int rc;
6644*82527734SSukumar Swaminathan 	uint32_t i;
6645*82527734SSukumar Swaminathan 
6646*82527734SSukumar Swaminathan 	mutex_enter(&hba->sli.sli4.id_lock);
6647*82527734SSukumar Swaminathan 	/* Loop thru all FCFIs */
6648*82527734SSukumar Swaminathan 	fp = hba->sli.sli4.FCFIp;
6649*82527734SSukumar Swaminathan 	for (i = 0; i < hba->sli.sli4.FCFICount; i++) {
6650*82527734SSukumar Swaminathan 		if (fp->state & RESOURCE_ALLOCATED) {
6651*82527734SSukumar Swaminathan 			/*
6652*82527734SSukumar Swaminathan 			 * Look for one thats valid, available
6653*82527734SSukumar Swaminathan 			 * and matches our FCF configuration info.
6654*82527734SSukumar Swaminathan 			 */
6655*82527734SSukumar Swaminathan 			if (fp->fcf_rec.fcf_valid &&
6656*82527734SSukumar Swaminathan 			    fp->fcf_rec.fcf_available &&
6657*82527734SSukumar Swaminathan 			    emlxs_sli4_check_fcf_config(hba, &fp->fcf_rec)) {
6658*82527734SSukumar Swaminathan 				/* Since we only support one FCF */
6659*82527734SSukumar Swaminathan 				break;
6660*82527734SSukumar Swaminathan 			}
6661*82527734SSukumar Swaminathan 		}
6662*82527734SSukumar Swaminathan 		fp++;
6663*82527734SSukumar Swaminathan 	}
6664*82527734SSukumar Swaminathan 	mutex_exit(&hba->sli.sli4.id_lock);
6665*82527734SSukumar Swaminathan 
6666*82527734SSukumar Swaminathan 	if (i == hba->sli.sli4.FCFICount) {
6667*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6668*82527734SSukumar Swaminathan 		    "Not a valid FCF");
6669*82527734SSukumar Swaminathan 		return (0);
6670*82527734SSukumar Swaminathan 	}
6671*82527734SSukumar Swaminathan 
6672*82527734SSukumar Swaminathan 	if (fp->state & RESOURCE_FCFI_REG) {
6673*82527734SSukumar Swaminathan 
6674*82527734SSukumar Swaminathan 		if (!fp->fcf_vfi) {
6675*82527734SSukumar Swaminathan 			vfip = emlxs_sli4_alloc_vfi(hba, fp);
6676*82527734SSukumar Swaminathan 			if (!vfip) {
6677*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
6678*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
6679*82527734SSukumar Swaminathan 				    "Fabric VFI alloc failure, fcf index %d",
6680*82527734SSukumar Swaminathan 				    fp->FCF_index);
6681*82527734SSukumar Swaminathan 				(void) emlxs_sli4_free_fcfi(hba, fp);
6682*82527734SSukumar Swaminathan 				return (0);
6683*82527734SSukumar Swaminathan 			}
6684*82527734SSukumar Swaminathan 			fp->fcf_vfi = vfip;
6685*82527734SSukumar Swaminathan 		}
6686*82527734SSukumar Swaminathan 
6687*82527734SSukumar Swaminathan 		if (!fp->fcf_vpi) {
6688*82527734SSukumar Swaminathan 			fp->fcf_vpi = port;
6689*82527734SSukumar Swaminathan 			port->VFIp = fp->fcf_vfi;
6690*82527734SSukumar Swaminathan 			port->VFIp->outstandingVPIs++;
6691*82527734SSukumar Swaminathan 		}
6692*82527734SSukumar Swaminathan 
6693*82527734SSukumar Swaminathan 		if (!(fp->state & RESOURCE_FCFI_DISC)) {
6694*82527734SSukumar Swaminathan 			fp->state |= RESOURCE_FCFI_DISC;
6695*82527734SSukumar Swaminathan 			emlxs_linkup(hba);
6696*82527734SSukumar Swaminathan 		}
6697*82527734SSukumar Swaminathan 		return (fp);
6698*82527734SSukumar Swaminathan 	}
6699*82527734SSukumar Swaminathan 
6700*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
6701*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6702*82527734SSukumar Swaminathan 		    "Unable to alloc mbox for fcf index %d",
6703*82527734SSukumar Swaminathan 		    fp->fcf_rec.fcf_index);
6704*82527734SSukumar Swaminathan 		return (0);
6705*82527734SSukumar Swaminathan 	}
6706*82527734SSukumar Swaminathan 	emlxs_mb_reg_fcfi(hba, mbq, fp);
6707*82527734SSukumar Swaminathan 
6708*82527734SSukumar Swaminathan 	rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
6709*82527734SSukumar Swaminathan 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
6710*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
6711*82527734SSukumar Swaminathan 		    "Unable to issue mbox for fcf index %d",
6712*82527734SSukumar Swaminathan 		    fp->fcf_rec.fcf_index);
6713*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6714*82527734SSukumar Swaminathan 	}
6715*82527734SSukumar Swaminathan 
6716*82527734SSukumar Swaminathan 	return (fp);
6717*82527734SSukumar Swaminathan 
6718*82527734SSukumar Swaminathan } /* emlxs_sli4_bind_fcfi() */
6719*82527734SSukumar Swaminathan 
6720*82527734SSukumar Swaminathan 
6721*82527734SSukumar Swaminathan extern void
6722*82527734SSukumar Swaminathan emlxs_sli4_timer(emlxs_hba_t *hba)
6723*82527734SSukumar Swaminathan {
6724*82527734SSukumar Swaminathan 	/* Perform SLI4 level timer checks */
6725*82527734SSukumar Swaminathan 
6726*82527734SSukumar Swaminathan 	emlxs_sli4_timer_check_mbox(hba);
6727*82527734SSukumar Swaminathan 
6728*82527734SSukumar Swaminathan 	return;
6729*82527734SSukumar Swaminathan 
6730*82527734SSukumar Swaminathan } /* emlxs_sli4_timer() */
6731*82527734SSukumar Swaminathan 
6732*82527734SSukumar Swaminathan 
6733*82527734SSukumar Swaminathan static void
6734*82527734SSukumar Swaminathan emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
6735*82527734SSukumar Swaminathan {
6736*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6737*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
6738*82527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
6739*82527734SSukumar Swaminathan 
6740*82527734SSukumar Swaminathan 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
6741*82527734SSukumar Swaminathan 		return;
6742*82527734SSukumar Swaminathan 	}
6743*82527734SSukumar Swaminathan 
6744*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
6745*82527734SSukumar Swaminathan 
6746*82527734SSukumar Swaminathan 	/* Return if timer hasn't expired */
6747*82527734SSukumar Swaminathan 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
6748*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
6749*82527734SSukumar Swaminathan 		return;
6750*82527734SSukumar Swaminathan 	}
6751*82527734SSukumar Swaminathan 	hba->mbox_timer = 0;
6752*82527734SSukumar Swaminathan 
6753*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
6754*82527734SSukumar Swaminathan 		if (hba->mbox_mbq) {
6755*82527734SSukumar Swaminathan 			mb = (MAILBOX *)hba->mbox_mbq;
6756*82527734SSukumar Swaminathan 		}
6757*82527734SSukumar Swaminathan 	}
6758*82527734SSukumar Swaminathan 
6759*82527734SSukumar Swaminathan 	if (mb) {
6760*82527734SSukumar Swaminathan 		switch (hba->mbox_queue_flag) {
6761*82527734SSukumar Swaminathan 		case MBX_NOWAIT:
6762*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6763*82527734SSukumar Swaminathan 			    "%s: Nowait.",
6764*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
6765*82527734SSukumar Swaminathan 			break;
6766*82527734SSukumar Swaminathan 
6767*82527734SSukumar Swaminathan 		case MBX_SLEEP:
6768*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6769*82527734SSukumar Swaminathan 			    "%s: mb=%p Sleep.",
6770*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6771*82527734SSukumar Swaminathan 			    mb);
6772*82527734SSukumar Swaminathan 			break;
6773*82527734SSukumar Swaminathan 
6774*82527734SSukumar Swaminathan 		case MBX_POLL:
6775*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6776*82527734SSukumar Swaminathan 			    "%s: mb=%p Polled.",
6777*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6778*82527734SSukumar Swaminathan 			    mb);
6779*82527734SSukumar Swaminathan 			break;
6780*82527734SSukumar Swaminathan 
6781*82527734SSukumar Swaminathan 		default:
6782*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6783*82527734SSukumar Swaminathan 			    "%s: mb=%p (%d).",
6784*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
6785*82527734SSukumar Swaminathan 			    mb, hba->mbox_queue_flag);
6786*82527734SSukumar Swaminathan 			break;
6787*82527734SSukumar Swaminathan 		}
6788*82527734SSukumar Swaminathan 	} else {
6789*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
6790*82527734SSukumar Swaminathan 	}
6791*82527734SSukumar Swaminathan 
6792*82527734SSukumar Swaminathan 	hba->flag |= FC_MBOX_TIMEOUT;
6793*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
6794*82527734SSukumar Swaminathan 
6795*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
6796*82527734SSukumar Swaminathan 
6797*82527734SSukumar Swaminathan 	/* Perform mailbox cleanup */
6798*82527734SSukumar Swaminathan 	/* This will wake any sleeping or polling threads */
6799*82527734SSukumar Swaminathan 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
6800*82527734SSukumar Swaminathan 
6801*82527734SSukumar Swaminathan 	/* Trigger adapter shutdown */
6802*82527734SSukumar Swaminathan 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
6803*82527734SSukumar Swaminathan 
6804*82527734SSukumar Swaminathan 	return;
6805*82527734SSukumar Swaminathan 
6806*82527734SSukumar Swaminathan } /* emlxs_sli4_timer_check_mbox() */
6807*82527734SSukumar Swaminathan 
6808*82527734SSukumar Swaminathan 
6809*82527734SSukumar Swaminathan extern void
6810*82527734SSukumar Swaminathan emlxs_data_dump(emlxs_hba_t *hba, char *str, uint32_t *iptr, int cnt, int err)
6811*82527734SSukumar Swaminathan {
6812*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
6813*82527734SSukumar Swaminathan 	void *msg;
6814*82527734SSukumar Swaminathan 
6815*82527734SSukumar Swaminathan 	if (err) {
6816*82527734SSukumar Swaminathan 		msg = &emlxs_sli_err_msg;
6817*82527734SSukumar Swaminathan 	} else {
6818*82527734SSukumar Swaminathan 		msg = &emlxs_sli_detail_msg;
6819*82527734SSukumar Swaminathan 	}
6820*82527734SSukumar Swaminathan 
6821*82527734SSukumar Swaminathan 	if (cnt) {
6822*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6823*82527734SSukumar Swaminathan 		    "%s00:  %08x %08x %08x %08x %08x %08x", str, *iptr,
6824*82527734SSukumar Swaminathan 		    *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
6825*82527734SSukumar Swaminathan 	}
6826*82527734SSukumar Swaminathan 	if (cnt > 6) {
6827*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6828*82527734SSukumar Swaminathan 		    "%s06:  %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
6829*82527734SSukumar Swaminathan 		    *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
6830*82527734SSukumar Swaminathan 	}
6831*82527734SSukumar Swaminathan 	if (cnt > 12) {
6832*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6833*82527734SSukumar Swaminathan 		    "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
6834*82527734SSukumar Swaminathan 		    *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
6835*82527734SSukumar Swaminathan 	}
6836*82527734SSukumar Swaminathan 	if (cnt > 18) {
6837*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6838*82527734SSukumar Swaminathan 		    "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
6839*82527734SSukumar Swaminathan 		    *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
6840*82527734SSukumar Swaminathan 	}
6841*82527734SSukumar Swaminathan 	if (cnt > 24) {
6842*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6843*82527734SSukumar Swaminathan 		    "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
6844*82527734SSukumar Swaminathan 		    *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
6845*82527734SSukumar Swaminathan 	}
6846*82527734SSukumar Swaminathan 	if (cnt > 30) {
6847*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6848*82527734SSukumar Swaminathan 		    "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
6849*82527734SSukumar Swaminathan 		    *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
6850*82527734SSukumar Swaminathan 	}
6851*82527734SSukumar Swaminathan 	if (cnt > 36) {
6852*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, msg,
6853*82527734SSukumar Swaminathan 		    "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
6854*82527734SSukumar Swaminathan 		    *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
6855*82527734SSukumar Swaminathan 	}
6856*82527734SSukumar Swaminathan 
6857*82527734SSukumar Swaminathan } /* emlxs_data_dump() */
6858*82527734SSukumar Swaminathan 
6859*82527734SSukumar Swaminathan 
6860*82527734SSukumar Swaminathan extern void
6861*82527734SSukumar Swaminathan emlxs_ue_dump(emlxs_hba_t *hba, char *str)
6862*82527734SSukumar Swaminathan {
6863*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6864*82527734SSukumar Swaminathan 	uint32_t ue_h;
6865*82527734SSukumar Swaminathan 	uint32_t ue_l;
6866*82527734SSukumar Swaminathan 	uint32_t on1;
6867*82527734SSukumar Swaminathan 	uint32_t on2;
6868*82527734SSukumar Swaminathan 
6869*82527734SSukumar Swaminathan 	ue_l = ddi_get32(hba->pci_acc_handle,
6870*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
6871*82527734SSukumar Swaminathan 	ue_h = ddi_get32(hba->pci_acc_handle,
6872*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
6873*82527734SSukumar Swaminathan 	on1 = ddi_get32(hba->pci_acc_handle,
6874*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
6875*82527734SSukumar Swaminathan 	on2 = ddi_get32(hba->pci_acc_handle,
6876*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
6877*82527734SSukumar Swaminathan 
6878*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6879*82527734SSukumar Swaminathan 	    "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
6880*82527734SSukumar Swaminathan 	    ue_l, ue_h, on1, on2);
6881*82527734SSukumar Swaminathan 
6882*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
6883*82527734SSukumar Swaminathan 	/* Access handle validation */
6884*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
6885*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6886*82527734SSukumar Swaminathan 
6887*82527734SSukumar Swaminathan } /* emlxs_ue_dump() */
6888*82527734SSukumar Swaminathan 
6889*82527734SSukumar Swaminathan 
6890*82527734SSukumar Swaminathan void
6891*82527734SSukumar Swaminathan emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
6892*82527734SSukumar Swaminathan {
6893*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6894*82527734SSukumar Swaminathan 	uint32_t ue_h;
6895*82527734SSukumar Swaminathan 	uint32_t ue_l;
6896*82527734SSukumar Swaminathan 	uint32_t on1;
6897*82527734SSukumar Swaminathan 	uint32_t on2;
6898*82527734SSukumar Swaminathan 
6899*82527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
6900*82527734SSukumar Swaminathan 		return;
6901*82527734SSukumar Swaminathan 	}
6902*82527734SSukumar Swaminathan 
6903*82527734SSukumar Swaminathan 	on1 = ddi_get32(hba->pci_acc_handle,
6904*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
6905*82527734SSukumar Swaminathan 	on2 = ddi_get32(hba->pci_acc_handle,
6906*82527734SSukumar Swaminathan 	    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
6907*82527734SSukumar Swaminathan 
6908*82527734SSukumar Swaminathan 	if (on1 != 0xffffffff || on2 != 0xffffffff) {
6909*82527734SSukumar Swaminathan 		ue_l = ddi_get32(hba->pci_acc_handle,
6910*82527734SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET));
6911*82527734SSukumar Swaminathan 		ue_h = ddi_get32(hba->pci_acc_handle,
6912*82527734SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET));
6913*82527734SSukumar Swaminathan 
6914*82527734SSukumar Swaminathan 		/* Unrecoverable error detected */
6915*82527734SSukumar Swaminathan 		/* Shut the HBA down */
6916*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
6917*82527734SSukumar Swaminathan 		    "Host Error: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x",
6918*82527734SSukumar Swaminathan 		    ue_l, ue_h, on1, on2);
6919*82527734SSukumar Swaminathan 
6920*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
6921*82527734SSukumar Swaminathan 
6922*82527734SSukumar Swaminathan 		emlxs_sli4_hba_flush_chipq(hba);
6923*82527734SSukumar Swaminathan 
6924*82527734SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
6925*82527734SSukumar Swaminathan 	}
6926*82527734SSukumar Swaminathan 
6927*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
6928*82527734SSukumar Swaminathan 	/* The PCI(e) driver generates PCI error when PCI read returns */
6929*82527734SSukumar Swaminathan 	/* 0xFFFFFFFF value. Since PCICFG_UE_STATUS_ONLINE0 and */
6930*82527734SSukumar Swaminathan 	/* PCICFG_UE_STATUS_ONLINE1 registers return 0xFFFFFFFF to */
6931*82527734SSukumar Swaminathan 	/* indicate that no internal component has an unrecoverable */
6932*82527734SSukumar Swaminathan 	/* error on HBA, no access handle check and just call below */
6933*82527734SSukumar Swaminathan 	/* function to clear the access handle error here. */
6934*82527734SSukumar Swaminathan 
6935*82527734SSukumar Swaminathan 	/* Some S10 versions do not define the ddi_fm_acc_err_clear function */
6936*82527734SSukumar Swaminathan 	if ((void *)&ddi_fm_acc_err_clear != NULL) {
6937*82527734SSukumar Swaminathan 		(void) ddi_fm_acc_err_clear(hba->pci_acc_handle,
6938*82527734SSukumar Swaminathan 		    DDI_FME_VERSION);
6939*82527734SSukumar Swaminathan 	}
6940*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6941*82527734SSukumar Swaminathan 
6942*82527734SSukumar Swaminathan } /* emlxs_sli4_poll_erratt() */
6943*82527734SSukumar Swaminathan 
6944*82527734SSukumar Swaminathan int
6945*82527734SSukumar Swaminathan emlxs_sli4_unreg_all_rpi_by_port(emlxs_port_t *port)
6946*82527734SSukumar Swaminathan {
6947*82527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
6948*82527734SSukumar Swaminathan 	NODELIST	*nlp;
6949*82527734SSukumar Swaminathan 	int		i;
6950*82527734SSukumar Swaminathan 
6951*82527734SSukumar Swaminathan 	rw_enter(&port->node_rwlock, RW_WRITER);
6952*82527734SSukumar Swaminathan 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6953*82527734SSukumar Swaminathan 		nlp = port->node_table[i];
6954*82527734SSukumar Swaminathan 		while (nlp != NULL) {
6955*82527734SSukumar Swaminathan 			if (nlp->nlp_Rpi != 0xffff) {
6956*82527734SSukumar Swaminathan 				rw_exit(&port->node_rwlock);
6957*82527734SSukumar Swaminathan 				(void) emlxs_mb_unreg_rpi(port,
6958*82527734SSukumar Swaminathan 				    nlp->nlp_Rpi, 0, 0, 0);
6959*82527734SSukumar Swaminathan 				rw_enter(&port->node_rwlock, RW_WRITER);
6960*82527734SSukumar Swaminathan 			} else {
6961*82527734SSukumar Swaminathan 				/* Just free nlp back to the pool */
6962*82527734SSukumar Swaminathan 				port->node_table[i] = nlp->nlp_list_next;
6963*82527734SSukumar Swaminathan 				(void) emlxs_mem_put(hba, MEM_NLP,
6964*82527734SSukumar Swaminathan 				    (uint8_t *)nlp);
6965*82527734SSukumar Swaminathan 			}
6966*82527734SSukumar Swaminathan 			nlp = port->node_table[i];
6967*82527734SSukumar Swaminathan 		}
6968*82527734SSukumar Swaminathan 	}
6969*82527734SSukumar Swaminathan 	rw_exit(&port->node_rwlock);
6970*82527734SSukumar Swaminathan 
6971*82527734SSukumar Swaminathan 	return (0);
6972*82527734SSukumar Swaminathan } /* emlxs_sli4_unreg_all_rpi_by_port() */
6973