1291a2b48SSukumar Swaminathan /*
2291a2b48SSukumar Swaminathan  * CDDL HEADER START
3291a2b48SSukumar Swaminathan  *
4291a2b48SSukumar Swaminathan  * The contents of this file are subject to the terms of the
5291a2b48SSukumar Swaminathan  * Common Development and Distribution License (the "License").
6291a2b48SSukumar Swaminathan  * You may not use this file except in compliance with the License.
7291a2b48SSukumar Swaminathan  *
8291a2b48SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9291a2b48SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
10291a2b48SSukumar Swaminathan  * See the License for the specific language governing permissions
11291a2b48SSukumar Swaminathan  * and limitations under the License.
12291a2b48SSukumar Swaminathan  *
13291a2b48SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
14291a2b48SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15291a2b48SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
16291a2b48SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
17291a2b48SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
18291a2b48SSukumar Swaminathan  *
19291a2b48SSukumar Swaminathan  * CDDL HEADER END
20291a2b48SSukumar Swaminathan  */
21291a2b48SSukumar Swaminathan 
22291a2b48SSukumar Swaminathan /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25291a2b48SSukumar Swaminathan  */
26291a2b48SSukumar Swaminathan 
27*82527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29291a2b48SSukumar Swaminathan 
30291a2b48SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31*82527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI3_C);
32291a2b48SSukumar Swaminathan 
33*82527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq);
34*82527734SSukumar Swaminathan static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba);
35*82527734SSukumar Swaminathan static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
36291a2b48SSukumar Swaminathan 	uint32_t ha_copy);
37*82527734SSukumar Swaminathan static int emlxs_sli3_mb_handle_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq);
38291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
39291a2b48SSukumar Swaminathan static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
40291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
41*82527734SSukumar Swaminathan 
42291a2b48SSukumar Swaminathan static uint32_t	emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
43291a2b48SSukumar Swaminathan 
44*82527734SSukumar Swaminathan static uint32_t emlxs_disable_traffic_cop = 1;
45291a2b48SSukumar Swaminathan 
46*82527734SSukumar Swaminathan static int			emlxs_sli3_map_hdw(emlxs_hba_t *hba);
47291a2b48SSukumar Swaminathan 
48*82527734SSukumar Swaminathan static void			emlxs_sli3_unmap_hdw(emlxs_hba_t *hba);
49291a2b48SSukumar Swaminathan 
50*82527734SSukumar Swaminathan static int32_t			emlxs_sli3_online(emlxs_hba_t *hba);
51291a2b48SSukumar Swaminathan 
52*82527734SSukumar Swaminathan static void			emlxs_sli3_offline(emlxs_hba_t *hba);
53291a2b48SSukumar Swaminathan 
54*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_reset(emlxs_hba_t *hba,
55*82527734SSukumar Swaminathan 					uint32_t restart, uint32_t skip_post,
56*82527734SSukumar Swaminathan 					uint32_t quiesce);
57291a2b48SSukumar Swaminathan 
58*82527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill(emlxs_hba_t *hba);
59*82527734SSukumar Swaminathan static void			emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba);
60*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_hba_init(emlxs_hba_t *hba);
61291a2b48SSukumar Swaminathan 
62*82527734SSukumar Swaminathan static uint32_t			emlxs_sli2_bde_setup(emlxs_port_t *port,
63*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
64*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_bde_setup(emlxs_port_t *port,
65*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
66*82527734SSukumar Swaminathan static uint32_t			emlxs_sli2_fct_bde_setup(emlxs_port_t *port,
67*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
68*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_fct_bde_setup(emlxs_port_t *port,
69*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
70291a2b48SSukumar Swaminathan 
71291a2b48SSukumar Swaminathan 
72*82527734SSukumar Swaminathan static void			emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba,
73*82527734SSukumar Swaminathan 					CHANNEL *rp, IOCBQ *iocb_cmd);
74291a2b48SSukumar Swaminathan 
75291a2b48SSukumar Swaminathan 
76*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba,
77*82527734SSukumar Swaminathan 					MAILBOXQ *mbq, int32_t flg,
78*82527734SSukumar Swaminathan 					uint32_t tmo);
79291a2b48SSukumar Swaminathan 
80291a2b48SSukumar Swaminathan 
81*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
82*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fct_iocb(emlxs_port_t *port,
83*82527734SSukumar Swaminathan 					emlxs_buf_t *cmd_sbp, int channel);
84291a2b48SSukumar Swaminathan 
85*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
86291a2b48SSukumar Swaminathan 
87*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port,
88*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp, int ring);
89291a2b48SSukumar Swaminathan 
90*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ip_iocb(emlxs_port_t *port,
91*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
92291a2b48SSukumar Swaminathan 
93*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_els_iocb(emlxs_port_t *port,
94*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
95291a2b48SSukumar Swaminathan 
96291a2b48SSukumar Swaminathan 
97*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_prep_ct_iocb(emlxs_port_t *port,
98*82527734SSukumar Swaminathan 					emlxs_buf_t *sbp);
99291a2b48SSukumar Swaminathan 
100291a2b48SSukumar Swaminathan 
101*82527734SSukumar Swaminathan static void			emlxs_sli3_poll_intr(emlxs_hba_t *hba,
102*82527734SSukumar Swaminathan 					uint32_t att_bit);
103291a2b48SSukumar Swaminathan 
104*82527734SSukumar Swaminathan static int32_t			emlxs_sli3_intx_intr(char *arg);
105*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
106*82527734SSukumar Swaminathan static uint32_t			emlxs_sli3_msi_intr(char *arg1, char *arg2);
107*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
108291a2b48SSukumar Swaminathan 
109*82527734SSukumar Swaminathan static void			emlxs_sli3_enable_intr(emlxs_hba_t *hba);
110*82527734SSukumar Swaminathan 
111*82527734SSukumar Swaminathan static void			emlxs_sli3_disable_intr(emlxs_hba_t *hba,
112*82527734SSukumar Swaminathan 					uint32_t att);
113*82527734SSukumar Swaminathan 
114*82527734SSukumar Swaminathan static uint32_t			emlxs_reset_ring(emlxs_hba_t *hba,
115*82527734SSukumar Swaminathan 					uint32_t ringno);
116*82527734SSukumar Swaminathan static void			emlxs_handle_ff_error(emlxs_hba_t *hba);
117*82527734SSukumar Swaminathan 
118*82527734SSukumar Swaminathan static uint32_t			emlxs_handle_mb_event(emlxs_hba_t *hba);
119*82527734SSukumar Swaminathan 
120*82527734SSukumar Swaminathan static void			emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba);
121*82527734SSukumar Swaminathan 
122*82527734SSukumar Swaminathan static uint32_t			emlxs_mb_config_port(emlxs_hba_t *hba,
123*82527734SSukumar Swaminathan 					MAILBOXQ *mbq, uint32_t sli_mode,
124*82527734SSukumar Swaminathan 					uint32_t hbainit);
125*82527734SSukumar Swaminathan static void			emlxs_enable_latt(emlxs_hba_t *hba);
126*82527734SSukumar Swaminathan 
127*82527734SSukumar Swaminathan static uint32_t			emlxs_check_attention(emlxs_hba_t *hba);
128*82527734SSukumar Swaminathan 
129*82527734SSukumar Swaminathan static uint32_t			emlxs_get_attention(emlxs_hba_t *hba,
130*82527734SSukumar Swaminathan 					uint32_t msgid);
131*82527734SSukumar Swaminathan static void			emlxs_proc_attention(emlxs_hba_t *hba,
132*82527734SSukumar Swaminathan 					uint32_t ha_copy);
133*82527734SSukumar Swaminathan /* static int			emlxs_handle_rcv_seq(emlxs_hba_t *hba, */
134*82527734SSukumar Swaminathan 					/* CHANNEL *cp, IOCBQ *iocbq); */
135*82527734SSukumar Swaminathan /* static void			emlxs_update_HBQ_index(emlxs_hba_t *hba, */
136*82527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
137*82527734SSukumar Swaminathan /* static void			emlxs_hbq_free_all(emlxs_hba_t *hba, */
138*82527734SSukumar Swaminathan 					/* uint32_t hbq_id); */
139*82527734SSukumar Swaminathan static uint32_t			emlxs_hbq_setup(emlxs_hba_t *hba,
140*82527734SSukumar Swaminathan 					uint32_t hbq_id);
141*82527734SSukumar Swaminathan extern void			emlxs_sli3_timer(emlxs_hba_t *hba);
142*82527734SSukumar Swaminathan 
143*82527734SSukumar Swaminathan extern void			emlxs_sli3_poll_erratt(emlxs_hba_t *hba);
144*82527734SSukumar Swaminathan 
145*82527734SSukumar Swaminathan 
146*82527734SSukumar Swaminathan /* Define SLI3 API functions */
147*82527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli3_api = {
148*82527734SSukumar Swaminathan 	emlxs_sli3_map_hdw,
149*82527734SSukumar Swaminathan 	emlxs_sli3_unmap_hdw,
150*82527734SSukumar Swaminathan 	emlxs_sli3_online,
151*82527734SSukumar Swaminathan 	emlxs_sli3_offline,
152*82527734SSukumar Swaminathan 	emlxs_sli3_hba_reset,
153*82527734SSukumar Swaminathan 	emlxs_sli3_hba_kill,
154*82527734SSukumar Swaminathan 	emlxs_sli3_issue_iocb_cmd,
155*82527734SSukumar Swaminathan 	emlxs_sli3_issue_mbox_cmd,
156*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
157*82527734SSukumar Swaminathan 	emlxs_sli3_prep_fct_iocb,
158*82527734SSukumar Swaminathan #else
159*82527734SSukumar Swaminathan 	NULL,
160*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
161*82527734SSukumar Swaminathan 	emlxs_sli3_prep_fcp_iocb,
162*82527734SSukumar Swaminathan 	emlxs_sli3_prep_ip_iocb,
163*82527734SSukumar Swaminathan 	emlxs_sli3_prep_els_iocb,
164*82527734SSukumar Swaminathan 	emlxs_sli3_prep_ct_iocb,
165*82527734SSukumar Swaminathan 	emlxs_sli3_poll_intr,
166*82527734SSukumar Swaminathan 	emlxs_sli3_intx_intr,
167*82527734SSukumar Swaminathan 	emlxs_sli3_msi_intr,
168*82527734SSukumar Swaminathan 	emlxs_sli3_disable_intr,
169*82527734SSukumar Swaminathan 	emlxs_sli3_timer,
170*82527734SSukumar Swaminathan 	emlxs_sli3_poll_erratt
171*82527734SSukumar Swaminathan };
172291a2b48SSukumar Swaminathan 
173291a2b48SSukumar Swaminathan 
174*82527734SSukumar Swaminathan /*
175*82527734SSukumar Swaminathan  * emlxs_sli3_online()
176*82527734SSukumar Swaminathan  *
177*82527734SSukumar Swaminathan  * This routine will start initialization of the SLI2/3 HBA.
178*82527734SSukumar Swaminathan  */
179*82527734SSukumar Swaminathan static int32_t
180*82527734SSukumar Swaminathan emlxs_sli3_online(emlxs_hba_t *hba)
181*82527734SSukumar Swaminathan {
182*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
183*82527734SSukumar Swaminathan 	emlxs_config_t *cfg;
184*82527734SSukumar Swaminathan 	emlxs_vpd_t *vpd;
185*82527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
186*82527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
187*82527734SSukumar Swaminathan 	RING *rp;
188*82527734SSukumar Swaminathan 	CHANNEL *cp;
189*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
190*82527734SSukumar Swaminathan 	MATCHMAP *mp1 = NULL;
191*82527734SSukumar Swaminathan 	uint8_t *inptr;
192*82527734SSukumar Swaminathan 	uint8_t *outptr;
193*82527734SSukumar Swaminathan 	uint32_t status;
194*82527734SSukumar Swaminathan 	uint32_t i;
195*82527734SSukumar Swaminathan 	uint32_t j;
196*82527734SSukumar Swaminathan 	uint32_t read_rev_reset;
197*82527734SSukumar Swaminathan 	uint32_t key = 0;
198*82527734SSukumar Swaminathan 	uint32_t fw_check;
199*82527734SSukumar Swaminathan 	uint32_t rval = 0;
200*82527734SSukumar Swaminathan 	uint32_t offset;
201*82527734SSukumar Swaminathan 	uint8_t vpd_data[DMP_VPD_SIZE];
202*82527734SSukumar Swaminathan 	uint32_t MaxRbusSize;
203*82527734SSukumar Swaminathan 	uint32_t MaxIbusSize;
204*82527734SSukumar Swaminathan 	uint32_t sli_mode;
205*82527734SSukumar Swaminathan 	uint32_t sli_mode_mask;
206291a2b48SSukumar Swaminathan 
207*82527734SSukumar Swaminathan 	cfg = &CFG;
208*82527734SSukumar Swaminathan 	vpd = &VPD;
209*82527734SSukumar Swaminathan 	MaxRbusSize = 0;
210*82527734SSukumar Swaminathan 	MaxIbusSize = 0;
211*82527734SSukumar Swaminathan 	read_rev_reset = 0;
212*82527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
213291a2b48SSukumar Swaminathan 
214*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
215*82527734SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
216*82527734SSukumar Swaminathan 	}
217291a2b48SSukumar Swaminathan 
218*82527734SSukumar Swaminathan 	/* Initialize sli mode based on configuration parameter */
219*82527734SSukumar Swaminathan 	switch (cfg[CFG_SLI_MODE].current) {
220*82527734SSukumar Swaminathan 	case 2:	/* SLI2 mode */
221*82527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
222*82527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
223*82527734SSukumar Swaminathan 		break;
224291a2b48SSukumar Swaminathan 
225*82527734SSukumar Swaminathan 	case 3:	/* SLI3 mode */
226*82527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI3_MODE;
227*82527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI3_MASK;
228*82527734SSukumar Swaminathan 		break;
229291a2b48SSukumar Swaminathan 
230*82527734SSukumar Swaminathan 	case 0:	/* Best available */
231*82527734SSukumar Swaminathan 	case 1:	/* Best available */
232*82527734SSukumar Swaminathan 	default:
233*82527734SSukumar Swaminathan 		if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) {
234*82527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
235*82527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
236*82527734SSukumar Swaminathan 		} else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) {
237*82527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
238*82527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
239*82527734SSukumar Swaminathan 		}
240*82527734SSukumar Swaminathan 	}
241*82527734SSukumar Swaminathan 	/* SBUS adapters only available in SLI2 */
242*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
243*82527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
244*82527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
245291a2b48SSukumar Swaminathan 	}
246291a2b48SSukumar Swaminathan 
247*82527734SSukumar Swaminathan 	/* Set the fw_check flag */
248*82527734SSukumar Swaminathan 	fw_check = cfg[CFG_FW_CHECK].current;
249291a2b48SSukumar Swaminathan 
250*82527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
251*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
252*82527734SSukumar Swaminathan 	hba->fc_edtov = FF_DEF_EDTOV;
253*82527734SSukumar Swaminathan 	hba->fc_ratov = FF_DEF_RATOV;
254*82527734SSukumar Swaminathan 	hba->fc_altov = FF_DEF_ALTOV;
255*82527734SSukumar Swaminathan 	hba->fc_arbtov = FF_DEF_ARBTOV;
256291a2b48SSukumar Swaminathan 
257291a2b48SSukumar Swaminathan 	/*
258*82527734SSukumar Swaminathan 	 * Get a buffer which will be used repeatedly for mailbox commands
259291a2b48SSukumar Swaminathan 	 */
260*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
261291a2b48SSukumar Swaminathan 
262*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
263*82527734SSukumar Swaminathan reset:
264291a2b48SSukumar Swaminathan 
265*82527734SSukumar Swaminathan 	/* Reset & Initialize the adapter */
266*82527734SSukumar Swaminathan 	if (emlxs_sli3_hba_init(hba)) {
267*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
268*82527734SSukumar Swaminathan 		    "Unable to init hba.");
269291a2b48SSukumar Swaminathan 
270*82527734SSukumar Swaminathan 		rval = EIO;
271*82527734SSukumar Swaminathan 		goto failed;
272*82527734SSukumar Swaminathan 	}
273291a2b48SSukumar Swaminathan 
274*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
275*82527734SSukumar Swaminathan 	/* Access handle validation */
276*82527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
277*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
278*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
279*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
280*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
281*82527734SSukumar Swaminathan 	    != DDI_FM_OK)) {
282*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
283*82527734SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
284*82527734SSukumar Swaminathan 
285*82527734SSukumar Swaminathan 		rval = EIO;
286*82527734SSukumar Swaminathan 		goto failed;
287291a2b48SSukumar Swaminathan 	}
288*82527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
289291a2b48SSukumar Swaminathan 
290*82527734SSukumar Swaminathan 	/* Check for the LP9802 (This is a special case) */
291*82527734SSukumar Swaminathan 	/* We need to check for dual channel adapter */
292*82527734SSukumar Swaminathan 	if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) {
293*82527734SSukumar Swaminathan 		/* Try to determine if this is a DC adapter */
294*82527734SSukumar Swaminathan 		if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) {
295*82527734SSukumar Swaminathan 			if (MaxRbusSize == REDUCED_SRAM_CFG) {
296*82527734SSukumar Swaminathan 				/* LP9802DC */
297*82527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
298*82527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802DC) {
299*82527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
300*82527734SSukumar Swaminathan 						    &hba->model_info,
301*82527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
302*82527734SSukumar Swaminathan 						break;
303*82527734SSukumar Swaminathan 					}
304*82527734SSukumar Swaminathan 				}
305*82527734SSukumar Swaminathan 			} else if (hba->model_info.id != LP9802) {
306*82527734SSukumar Swaminathan 				/* LP9802 */
307*82527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
308*82527734SSukumar Swaminathan 					if (emlxs_pci_model[i].id == LP9802) {
309*82527734SSukumar Swaminathan 						bcopy(&emlxs_pci_model[i],
310*82527734SSukumar Swaminathan 						    &hba->model_info,
311*82527734SSukumar Swaminathan 						    sizeof (emlxs_model_t));
312*82527734SSukumar Swaminathan 						break;
313*82527734SSukumar Swaminathan 					}
314*82527734SSukumar Swaminathan 				}
315*82527734SSukumar Swaminathan 			}
316*82527734SSukumar Swaminathan 		}
317*82527734SSukumar Swaminathan 	}
318291a2b48SSukumar Swaminathan 
319291a2b48SSukumar Swaminathan 	/*
320*82527734SSukumar Swaminathan 	 * Setup and issue mailbox READ REV command
321291a2b48SSukumar Swaminathan 	 */
322*82527734SSukumar Swaminathan 	vpd->opFwRev = 0;
323*82527734SSukumar Swaminathan 	vpd->postKernRev = 0;
324*82527734SSukumar Swaminathan 	vpd->sli1FwRev = 0;
325*82527734SSukumar Swaminathan 	vpd->sli2FwRev = 0;
326*82527734SSukumar Swaminathan 	vpd->sli3FwRev = 0;
327*82527734SSukumar Swaminathan 	vpd->sli4FwRev = 0;
328*82527734SSukumar Swaminathan 
329*82527734SSukumar Swaminathan 	vpd->postKernName[0] = 0;
330*82527734SSukumar Swaminathan 	vpd->opFwName[0] = 0;
331*82527734SSukumar Swaminathan 	vpd->sli1FwName[0] = 0;
332*82527734SSukumar Swaminathan 	vpd->sli2FwName[0] = 0;
333*82527734SSukumar Swaminathan 	vpd->sli3FwName[0] = 0;
334*82527734SSukumar Swaminathan 	vpd->sli4FwName[0] = 0;
335*82527734SSukumar Swaminathan 
336*82527734SSukumar Swaminathan 	vpd->opFwLabel[0] = 0;
337*82527734SSukumar Swaminathan 	vpd->sli1FwLabel[0] = 0;
338*82527734SSukumar Swaminathan 	vpd->sli2FwLabel[0] = 0;
339*82527734SSukumar Swaminathan 	vpd->sli3FwLabel[0] = 0;
340*82527734SSukumar Swaminathan 	vpd->sli4FwLabel[0] = 0;
341*82527734SSukumar Swaminathan 
342*82527734SSukumar Swaminathan 	/* Sanity check */
343*82527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
344*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
345*82527734SSukumar Swaminathan 		    "Adapter / SLI mode mismatch mask:x%x",
346*82527734SSukumar Swaminathan 		    hba->model_info.sli_mask);
347*82527734SSukumar Swaminathan 
348*82527734SSukumar Swaminathan 		rval = EIO;
349*82527734SSukumar Swaminathan 		goto failed;
350291a2b48SSukumar Swaminathan 	}
351291a2b48SSukumar Swaminathan 
352*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
353*82527734SSukumar Swaminathan 	emlxs_mb_read_rev(hba, mbq, 0);
354*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
355*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
356*82527734SSukumar Swaminathan 		    "Unable to read rev. Mailbox cmd=%x status=%x",
357*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
358291a2b48SSukumar Swaminathan 
359*82527734SSukumar Swaminathan 		rval = EIO;
360*82527734SSukumar Swaminathan 		goto failed;
361291a2b48SSukumar Swaminathan 	}
362291a2b48SSukumar Swaminathan 
363*82527734SSukumar Swaminathan 	if (mb->un.varRdRev.rr == 0) {
364*82527734SSukumar Swaminathan 		/* Old firmware */
365*82527734SSukumar Swaminathan 		if (read_rev_reset == 0) {
366*82527734SSukumar Swaminathan 			read_rev_reset = 1;
367291a2b48SSukumar Swaminathan 
368*82527734SSukumar Swaminathan 			goto reset;
369*82527734SSukumar Swaminathan 		} else {
370*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
371*82527734SSukumar Swaminathan 			    "Outdated firmware detected.");
372*82527734SSukumar Swaminathan 		}
373291a2b48SSukumar Swaminathan 
374*82527734SSukumar Swaminathan 		vpd->rBit = 0;
375*82527734SSukumar Swaminathan 	} else {
376*82527734SSukumar Swaminathan 		if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) {
377*82527734SSukumar Swaminathan 			if (read_rev_reset == 0) {
378*82527734SSukumar Swaminathan 				read_rev_reset = 1;
379291a2b48SSukumar Swaminathan 
380*82527734SSukumar Swaminathan 				goto reset;
381*82527734SSukumar Swaminathan 			} else {
382*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
383*82527734SSukumar Swaminathan 				    "Non-operational firmware detected. "
384*82527734SSukumar Swaminathan 				    "type=%x",
385*82527734SSukumar Swaminathan 				    mb->un.varRdRev.un.b.ProgType);
386*82527734SSukumar Swaminathan 			}
387*82527734SSukumar Swaminathan 		}
388291a2b48SSukumar Swaminathan 
389*82527734SSukumar Swaminathan 		vpd->rBit = 1;
390*82527734SSukumar Swaminathan 		vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1;
391*82527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel,
392*82527734SSukumar Swaminathan 		    16);
393*82527734SSukumar Swaminathan 		vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2;
394*82527734SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel,
395*82527734SSukumar Swaminathan 		    16);
396291a2b48SSukumar Swaminathan 
397*82527734SSukumar Swaminathan 		/*
398*82527734SSukumar Swaminathan 		 * Lets try to read the SLI3 version
399*82527734SSukumar Swaminathan 		 * Setup and issue mailbox READ REV(v3) command
400*82527734SSukumar Swaminathan 		 */
401*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
402*82527734SSukumar Swaminathan 
403*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
404*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
405*82527734SSukumar Swaminathan 
406*82527734SSukumar Swaminathan 		emlxs_mb_read_rev(hba, mbq, 1);
407*82527734SSukumar Swaminathan 
408*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
409*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
410*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
411*82527734SSukumar Swaminathan 			    "Unable to read rev (v3). Mailbox cmd=%x status=%x",
412*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
413*82527734SSukumar Swaminathan 
414*82527734SSukumar Swaminathan 			rval = EIO;
415*82527734SSukumar Swaminathan 			goto failed;
416*82527734SSukumar Swaminathan 		}
417*82527734SSukumar Swaminathan 
418*82527734SSukumar Swaminathan 		if (mb->un.varRdRev.rf3) {
419*82527734SSukumar Swaminathan 			/*
420*82527734SSukumar Swaminathan 			 * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1;
421*82527734SSukumar Swaminathan 			 * Not needed
422*82527734SSukumar Swaminathan 			 */
423*82527734SSukumar Swaminathan 			vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2;
424*82527734SSukumar Swaminathan 			bcopy((char *)mb->un.varRdRev.sliFwName2,
425*82527734SSukumar Swaminathan 			    vpd->sli3FwLabel, 16);
426*82527734SSukumar Swaminathan 		}
427291a2b48SSukumar Swaminathan 	}
428291a2b48SSukumar Swaminathan 
429*82527734SSukumar Swaminathan 
430*82527734SSukumar Swaminathan 	if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) {
431*82527734SSukumar Swaminathan 		if (vpd->sli2FwRev) {
432*82527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
433*82527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
434*82527734SSukumar Swaminathan 		} else {
435*82527734SSukumar Swaminathan 			sli_mode = 0;
436*82527734SSukumar Swaminathan 			sli_mode_mask = 0;
437*82527734SSukumar Swaminathan 		}
438291a2b48SSukumar Swaminathan 	}
439291a2b48SSukumar Swaminathan 
440*82527734SSukumar Swaminathan 	else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) {
441*82527734SSukumar Swaminathan 		if (vpd->sli3FwRev) {
442*82527734SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
443*82527734SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
444291a2b48SSukumar Swaminathan 		} else {
445*82527734SSukumar Swaminathan 			sli_mode = 0;
446*82527734SSukumar Swaminathan 			sli_mode_mask = 0;
447291a2b48SSukumar Swaminathan 		}
448291a2b48SSukumar Swaminathan 	}
449291a2b48SSukumar Swaminathan 
450*82527734SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & sli_mode_mask)) {
451*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
452*82527734SSukumar Swaminathan 		    "Firmware not available. sli-mode=%d",
453*82527734SSukumar Swaminathan 		    cfg[CFG_SLI_MODE].current);
454291a2b48SSukumar Swaminathan 
455*82527734SSukumar Swaminathan 		rval = EIO;
456*82527734SSukumar Swaminathan 		goto failed;
457*82527734SSukumar Swaminathan 	}
458291a2b48SSukumar Swaminathan 
459*82527734SSukumar Swaminathan 	/* Save information as VPD data */
460*82527734SSukumar Swaminathan 	vpd->postKernRev = mb->un.varRdRev.postKernRev;
461*82527734SSukumar Swaminathan 	vpd->opFwRev = mb->un.varRdRev.opFwRev;
462*82527734SSukumar Swaminathan 	bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16);
463*82527734SSukumar Swaminathan 	vpd->biuRev = mb->un.varRdRev.biuRev;
464*82527734SSukumar Swaminathan 	vpd->smRev = mb->un.varRdRev.smRev;
465*82527734SSukumar Swaminathan 	vpd->smFwRev = mb->un.varRdRev.un.smFwRev;
466*82527734SSukumar Swaminathan 	vpd->endecRev = mb->un.varRdRev.endecRev;
467*82527734SSukumar Swaminathan 	vpd->fcphHigh = mb->un.varRdRev.fcphHigh;
468*82527734SSukumar Swaminathan 	vpd->fcphLow = mb->un.varRdRev.fcphLow;
469*82527734SSukumar Swaminathan 	vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh;
470*82527734SSukumar Swaminathan 	vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow;
471*82527734SSukumar Swaminathan 
472*82527734SSukumar Swaminathan 	/* Decode FW names */
473*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->postKernRev, vpd->postKernName);
474*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->opFwRev, vpd->opFwName);
475*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName);
476*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName);
477*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName);
478*82527734SSukumar Swaminathan 	emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName);
479*82527734SSukumar Swaminathan 
480*82527734SSukumar Swaminathan 	/* Decode FW labels */
481*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1);
482*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1);
483*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1);
484*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1);
485*82527734SSukumar Swaminathan 	emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1);
486*82527734SSukumar Swaminathan 
487*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
488*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
489*82527734SSukumar Swaminathan 
490*82527734SSukumar Swaminathan 	key = emlxs_get_key(hba, mbq);
491*82527734SSukumar Swaminathan 
492*82527734SSukumar Swaminathan 	/* Get adapter VPD information */
493*82527734SSukumar Swaminathan 	offset = 0;
494*82527734SSukumar Swaminathan 	bzero(vpd_data, sizeof (vpd_data));
495*82527734SSukumar Swaminathan 	vpd->port_index = (uint32_t)-1;
496291a2b48SSukumar Swaminathan 
497*82527734SSukumar Swaminathan 	while (offset < DMP_VPD_SIZE) {
498*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
499*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
500291a2b48SSukumar Swaminathan 
501*82527734SSukumar Swaminathan 		emlxs_mb_dump_vpd(hba, mbq, offset);
502*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
503*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
504*82527734SSukumar Swaminathan 			/*
505*82527734SSukumar Swaminathan 			 * Let it go through even if failed.
506*82527734SSukumar Swaminathan 			 * Not all adapter's have VPD info and thus will
507*82527734SSukumar Swaminathan 			 * fail here. This is not a problem
508*82527734SSukumar Swaminathan 			 */
509291a2b48SSukumar Swaminathan 
510*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
511*82527734SSukumar Swaminathan 			    "No VPD found. offset=%x status=%x", offset,
512*82527734SSukumar Swaminathan 			    mb->mbxStatus);
513*82527734SSukumar Swaminathan 			break;
514*82527734SSukumar Swaminathan 		} else {
515*82527734SSukumar Swaminathan 			if (mb->un.varDmp.ra == 1) {
516*82527734SSukumar Swaminathan 				uint32_t *lp1, *lp2;
517*82527734SSukumar Swaminathan 				uint32_t bsize;
518*82527734SSukumar Swaminathan 				uint32_t wsize;
519291a2b48SSukumar Swaminathan 
520*82527734SSukumar Swaminathan 				/*
521*82527734SSukumar Swaminathan 				 * mb->un.varDmp.word_cnt is actually byte
522*82527734SSukumar Swaminathan 				 * count for the dump reply
523*82527734SSukumar Swaminathan 				 */
524*82527734SSukumar Swaminathan 				bsize = mb->un.varDmp.word_cnt;
525291a2b48SSukumar Swaminathan 
526*82527734SSukumar Swaminathan 				/* Stop if no data was received */
527*82527734SSukumar Swaminathan 				if (bsize == 0) {
528*82527734SSukumar Swaminathan 					break;
529*82527734SSukumar Swaminathan 				}
530291a2b48SSukumar Swaminathan 
531*82527734SSukumar Swaminathan 				/* Check limit on byte size */
532*82527734SSukumar Swaminathan 				bsize = (bsize >
533*82527734SSukumar Swaminathan 				    (sizeof (vpd_data) - offset)) ?
534*82527734SSukumar Swaminathan 				    (sizeof (vpd_data) - offset) : bsize;
535291a2b48SSukumar Swaminathan 
536*82527734SSukumar Swaminathan 				/*
537*82527734SSukumar Swaminathan 				 * Convert size from bytes to words with
538*82527734SSukumar Swaminathan 				 * minimum of 1 word
539*82527734SSukumar Swaminathan 				 */
540*82527734SSukumar Swaminathan 				wsize = (bsize > 4) ? (bsize >> 2) : 1;
541291a2b48SSukumar Swaminathan 
542*82527734SSukumar Swaminathan 				/*
543*82527734SSukumar Swaminathan 				 * Transfer data into vpd_data buffer one
544*82527734SSukumar Swaminathan 				 * word at a time
545*82527734SSukumar Swaminathan 				 */
546*82527734SSukumar Swaminathan 				lp1 = (uint32_t *)&mb->un.varDmp.resp_offset;
547*82527734SSukumar Swaminathan 				lp2 = (uint32_t *)&vpd_data[offset];
548291a2b48SSukumar Swaminathan 
549*82527734SSukumar Swaminathan 				for (i = 0; i < wsize; i++) {
550*82527734SSukumar Swaminathan 					status = *lp1++;
551*82527734SSukumar Swaminathan 					*lp2++ = BE_SWAP32(status);
552*82527734SSukumar Swaminathan 				}
553291a2b48SSukumar Swaminathan 
554*82527734SSukumar Swaminathan 				/* Increment total byte count saved */
555*82527734SSukumar Swaminathan 				offset += (wsize << 2);
556291a2b48SSukumar Swaminathan 
557*82527734SSukumar Swaminathan 				/*
558*82527734SSukumar Swaminathan 				 * Stop if less than a full transfer was
559*82527734SSukumar Swaminathan 				 * received
560*82527734SSukumar Swaminathan 				 */
561*82527734SSukumar Swaminathan 				if (wsize < DMP_VPD_DUMP_WCOUNT) {
562*82527734SSukumar Swaminathan 					break;
563*82527734SSukumar Swaminathan 				}
564291a2b48SSukumar Swaminathan 
565*82527734SSukumar Swaminathan 			} else {
566*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
567*82527734SSukumar Swaminathan 				    &emlxs_init_debug_msg,
568*82527734SSukumar Swaminathan 				    "No VPD acknowledgment. offset=%x",
569*82527734SSukumar Swaminathan 				    offset);
570*82527734SSukumar Swaminathan 				break;
571*82527734SSukumar Swaminathan 			}
572*82527734SSukumar Swaminathan 		}
573291a2b48SSukumar Swaminathan 
574291a2b48SSukumar Swaminathan 	}
575291a2b48SSukumar Swaminathan 
576*82527734SSukumar Swaminathan 	if (vpd_data[0]) {
577*82527734SSukumar Swaminathan 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset);
578291a2b48SSukumar Swaminathan 
579*82527734SSukumar Swaminathan 		/*
580*82527734SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
581*82527734SSukumar Swaminathan 		 * match the current default HBA model info,
582*82527734SSukumar Swaminathan 		 * replace the default data with an entry that
583*82527734SSukumar Swaminathan 		 * does match.
584*82527734SSukumar Swaminathan 		 *
585*82527734SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
586*82527734SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
587*82527734SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
588*82527734SSukumar Swaminathan 		 */
589291a2b48SSukumar Swaminathan 
590*82527734SSukumar Swaminathan 		rval = 0;
591*82527734SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
592*82527734SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
593291a2b48SSukumar Swaminathan 
594*82527734SSukumar Swaminathan 			/* First scan for a V2 match */
595291a2b48SSukumar Swaminathan 
596*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
597*82527734SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
598*82527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
599*82527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
600*82527734SSukumar Swaminathan 					    &hba->model_info,
601*82527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
602*82527734SSukumar Swaminathan 					rval = 1;
603*82527734SSukumar Swaminathan 					break;
604*82527734SSukumar Swaminathan 				}
605*82527734SSukumar Swaminathan 			}
606*82527734SSukumar Swaminathan 		}
607291a2b48SSukumar Swaminathan 
608*82527734SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
609*82527734SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
610291a2b48SSukumar Swaminathan 
611*82527734SSukumar Swaminathan 			/* Next scan for a PN match */
612291a2b48SSukumar Swaminathan 
613*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
614*82527734SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
615*82527734SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
616*82527734SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
617*82527734SSukumar Swaminathan 					    &hba->model_info,
618*82527734SSukumar Swaminathan 					    sizeof (emlxs_model_t));
619*82527734SSukumar Swaminathan 					break;
620*82527734SSukumar Swaminathan 				}
621*82527734SSukumar Swaminathan 			}
622*82527734SSukumar Swaminathan 		}
623291a2b48SSukumar Swaminathan 
624*82527734SSukumar Swaminathan 		/*
625*82527734SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
626*82527734SSukumar Swaminathan 		 * VPD data, if any.
627*82527734SSukumar Swaminathan 		 */
628291a2b48SSukumar Swaminathan 
629*82527734SSukumar Swaminathan 		/*
630*82527734SSukumar Swaminathan 		 * Replace the default model description with vpd data
631*82527734SSukumar Swaminathan 		 */
632*82527734SSukumar Swaminathan 		if (vpd->model_desc[0] != 0) {
633*82527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model_desc,
634*82527734SSukumar Swaminathan 			    vpd->model_desc);
635291a2b48SSukumar Swaminathan 		}
636291a2b48SSukumar Swaminathan 
637*82527734SSukumar Swaminathan 		/* Replace the default model with vpd data */
638*82527734SSukumar Swaminathan 		if (vpd->model[0] != 0) {
639*82527734SSukumar Swaminathan 			(void) strcpy(hba->model_info.model, vpd->model);
640*82527734SSukumar Swaminathan 		}
641*82527734SSukumar Swaminathan 
642*82527734SSukumar Swaminathan 		/* Replace the default program types with vpd data */
643*82527734SSukumar Swaminathan 		if (vpd->prog_types[0] != 0) {
644*82527734SSukumar Swaminathan 			emlxs_parse_prog_types(hba, vpd->prog_types);
645*82527734SSukumar Swaminathan 		}
646291a2b48SSukumar Swaminathan 	}
647291a2b48SSukumar Swaminathan 
648291a2b48SSukumar Swaminathan 	/*
649*82527734SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
650*82527734SSukumar Swaminathan 	 * lets double check if adapter is not supported
651291a2b48SSukumar Swaminathan 	 */
652*82527734SSukumar Swaminathan 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
653*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
654*82527734SSukumar Swaminathan 		    "Unsupported adapter found.  "
655*82527734SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
656*82527734SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
657*82527734SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
658*82527734SSukumar Swaminathan 
659*82527734SSukumar Swaminathan 		rval = EIO;
660*82527734SSukumar Swaminathan 		goto failed;
661*82527734SSukumar Swaminathan 	}
662291a2b48SSukumar Swaminathan 
663*82527734SSukumar Swaminathan 	/* Read the adapter's wakeup parms */
664*82527734SSukumar Swaminathan 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
665*82527734SSukumar Swaminathan 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
666*82527734SSukumar Swaminathan 	    vpd->boot_version);
667291a2b48SSukumar Swaminathan 
668*82527734SSukumar Swaminathan 	/* Get fcode version property */
669*82527734SSukumar Swaminathan 	emlxs_get_fcode_version(hba);
670291a2b48SSukumar Swaminathan 
671*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
672*82527734SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
673*82527734SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
674291a2b48SSukumar Swaminathan 
675*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
676*82527734SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
677*82527734SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
678291a2b48SSukumar Swaminathan 
679*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
680*82527734SSukumar Swaminathan 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
681291a2b48SSukumar Swaminathan 
682*82527734SSukumar Swaminathan 	/*
683*82527734SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
684*82527734SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
685*82527734SSukumar Swaminathan 	 */
686*82527734SSukumar Swaminathan 	if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
687*82527734SSukumar Swaminathan 	    hba->model_info.fwid) || ((fw_check == 2) &&
688*82527734SSukumar Swaminathan 	    hba->model_info.fwid)) {
689*82527734SSukumar Swaminathan 		emlxs_firmware_t *fw;
690*82527734SSukumar Swaminathan 
691*82527734SSukumar Swaminathan 		/* Find firmware image indicated by adapter model */
692*82527734SSukumar Swaminathan 		fw = NULL;
693*82527734SSukumar Swaminathan 		for (i = 0; i < emlxs_fw_count; i++) {
694*82527734SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
695*82527734SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
696*82527734SSukumar Swaminathan 				break;
697*82527734SSukumar Swaminathan 			}
698291a2b48SSukumar Swaminathan 		}
699291a2b48SSukumar Swaminathan 
700291a2b48SSukumar Swaminathan 		/*
701*82527734SSukumar Swaminathan 		 * If the image was found, then verify current firmware
702*82527734SSukumar Swaminathan 		 * versions of adapter
703291a2b48SSukumar Swaminathan 		 */
704*82527734SSukumar Swaminathan 		if (fw) {
705*82527734SSukumar Swaminathan 			if ((fw->kern && (vpd->postKernRev != fw->kern)) ||
706*82527734SSukumar Swaminathan 			    (fw->stub && (vpd->opFwRev != fw->stub)) ||
707*82527734SSukumar Swaminathan 			    (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) ||
708*82527734SSukumar Swaminathan 			    (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) ||
709*82527734SSukumar Swaminathan 			    (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) ||
710*82527734SSukumar Swaminathan 			    (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) {
711*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
712*82527734SSukumar Swaminathan 				    "Firmware update needed. "
713*82527734SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
714*82527734SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
715*82527734SSukumar Swaminathan 
716*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
717*82527734SSukumar Swaminathan 				/*
718*82527734SSukumar Swaminathan 				 * Load the firmware image now
719*82527734SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
720*82527734SSukumar Swaminathan 				 * firmware image will already be defined
721*82527734SSukumar Swaminathan 				 * in the emlxs_fw_table
722*82527734SSukumar Swaminathan 				 */
723*82527734SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
724*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
725291a2b48SSukumar Swaminathan 
726*82527734SSukumar Swaminathan 				if (fw->image && fw->size) {
727*82527734SSukumar Swaminathan 					if (emlxs_fw_download(hba,
728*82527734SSukumar Swaminathan 					    (char *)fw->image, fw->size, 0)) {
729*82527734SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
730*82527734SSukumar Swaminathan 						    &emlxs_init_msg,
731*82527734SSukumar Swaminathan 						    "Firmware update failed.");
732*82527734SSukumar Swaminathan 					}
733*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT
734*82527734SSukumar Swaminathan 					/*
735*82527734SSukumar Swaminathan 					 * Unload the firmware image from
736*82527734SSukumar Swaminathan 					 * kernel memory
737*82527734SSukumar Swaminathan 					 */
738*82527734SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
739*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */
740291a2b48SSukumar Swaminathan 
741*82527734SSukumar Swaminathan 					fw_check = 0;
742*82527734SSukumar Swaminathan 
743*82527734SSukumar Swaminathan 					goto reset;
744*82527734SSukumar Swaminathan 				}
745*82527734SSukumar Swaminathan 
746*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
747*82527734SSukumar Swaminathan 				    "Firmware image unavailable.");
748*82527734SSukumar Swaminathan 			} else {
749*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
750*82527734SSukumar Swaminathan 				    "Firmware update not needed.");
751*82527734SSukumar Swaminathan 			}
752*82527734SSukumar Swaminathan 		} else {
753*82527734SSukumar Swaminathan 			/* This should not happen */
754*82527734SSukumar Swaminathan 
755*82527734SSukumar Swaminathan 			/*
756*82527734SSukumar Swaminathan 			 * This means either the adapter database is not
757*82527734SSukumar Swaminathan 			 * correct or a firmware image is missing from the
758*82527734SSukumar Swaminathan 			 * compile
759*82527734SSukumar Swaminathan 			 */
760*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
761*82527734SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
762*82527734SSukumar Swaminathan 			    hba->model_info.id, hba->model_info.fwid);
763291a2b48SSukumar Swaminathan 		}
764291a2b48SSukumar Swaminathan 	}
765291a2b48SSukumar 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).");
7744baa2c25SSukumar Swaminathan 
775*82527734SSukumar Swaminathan 		rval = EIO;
776*82527734SSukumar Swaminathan 		goto failed;
777*82527734SSukumar Swaminathan 	}
778291a2b48SSukumar Swaminathan 
779*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
780291a2b48SSukumar Swaminathan 
781*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
782*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
783291a2b48SSukumar Swaminathan 
784*82527734SSukumar Swaminathan 	(void) emlxs_mb_config_port(hba, mbq, sli_mode, key);
785*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
786*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
787*82527734SSukumar Swaminathan 		    "Unable to configure port. "
788*82527734SSukumar Swaminathan 		    "Mailbox cmd=%x status=%x slimode=%d key=%x",
789*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus, sli_mode, key);
790291a2b48SSukumar Swaminathan 
791*82527734SSukumar Swaminathan 		for (sli_mode--; sli_mode > 0; sli_mode--) {
792*82527734SSukumar Swaminathan 			/* Check if sli_mode is supported by this adapter */
793*82527734SSukumar Swaminathan 			if (hba->model_info.sli_mask &
794*82527734SSukumar Swaminathan 			    EMLXS_SLI_MASK(sli_mode)) {
795*82527734SSukumar Swaminathan 				sli_mode_mask = EMLXS_SLI_MASK(sli_mode);
796*82527734SSukumar Swaminathan 				break;
797*82527734SSukumar Swaminathan 			}
798*82527734SSukumar Swaminathan 		}
7994baa2c25SSukumar Swaminathan 
800*82527734SSukumar Swaminathan 		if (sli_mode) {
801*82527734SSukumar Swaminathan 			fw_check = 0;
8024baa2c25SSukumar Swaminathan 
803*82527734SSukumar Swaminathan 			goto reset;
804*82527734SSukumar Swaminathan 		}
805291a2b48SSukumar Swaminathan 
806*82527734SSukumar Swaminathan 		hba->flag &= ~FC_SLIM2_MODE;
807*82527734SSukumar Swaminathan 
808*82527734SSukumar Swaminathan 		rval = EIO;
809*82527734SSukumar Swaminathan 		goto failed;
810291a2b48SSukumar Swaminathan 	}
811291a2b48SSukumar Swaminathan 
812*82527734SSukumar Swaminathan 	/* Check if SLI3 mode was achieved */
813*82527734SSukumar Swaminathan 	if (mb->un.varCfgPort.rMA &&
814*82527734SSukumar Swaminathan 	    (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) {
815291a2b48SSukumar Swaminathan 
816*82527734SSukumar Swaminathan 		if (mb->un.varCfgPort.vpi_max > 1) {
817*82527734SSukumar Swaminathan 			hba->flag |= FC_NPIV_ENABLED;
818291a2b48SSukumar Swaminathan 
819*82527734SSukumar Swaminathan 			if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
820*82527734SSukumar Swaminathan 				hba->vpi_max =
821*82527734SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
822*82527734SSukumar Swaminathan 				    MAX_VPORTS - 1);
823*82527734SSukumar Swaminathan 			} else {
824*82527734SSukumar Swaminathan 				hba->vpi_max =
825*82527734SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
826*82527734SSukumar Swaminathan 				    MAX_VPORTS_LIMITED - 1);
827*82527734SSukumar Swaminathan 			}
828*82527734SSukumar Swaminathan 		}
829291a2b48SSukumar Swaminathan 
830*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
831*82527734SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports =
832*82527734SSukumar Swaminathan 		    (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0;
833*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
834*82527734SSukumar Swaminathan 
835*82527734SSukumar Swaminathan 		if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) {
836*82527734SSukumar Swaminathan 			hba->flag |= FC_HBQ_ENABLED;
837291a2b48SSukumar Swaminathan 		}
838*82527734SSukumar Swaminathan 
839*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
840*82527734SSukumar Swaminathan 		    "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max);
841*82527734SSukumar Swaminathan 	} else {
842*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
843*82527734SSukumar Swaminathan 		    "SLI2 mode: flag=%x", hba->flag);
844*82527734SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
845*82527734SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
846*82527734SSukumar Swaminathan 		hba->sli_mode = sli_mode;
847291a2b48SSukumar Swaminathan 	}
848291a2b48SSukumar Swaminathan 
849*82527734SSukumar Swaminathan 	/* Get and save the current firmware version (based on sli_mode) */
850*82527734SSukumar Swaminathan 	emlxs_decode_firmware_rev(hba, vpd);
851291a2b48SSukumar Swaminathan 
852*82527734SSukumar Swaminathan 	emlxs_pcix_mxr_update(hba, 0);
853291a2b48SSukumar Swaminathan 
854*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
855*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
856291a2b48SSukumar Swaminathan 
857*82527734SSukumar Swaminathan 	emlxs_mb_read_config(hba, mbq);
858*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
859*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
860*82527734SSukumar Swaminathan 		    "Unable to read configuration.  Mailbox cmd=%x status=%x",
861*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
862291a2b48SSukumar Swaminathan 
863*82527734SSukumar Swaminathan 		rval = EIO;
864*82527734SSukumar Swaminathan 		goto failed;
865*82527734SSukumar Swaminathan 	}
866291a2b48SSukumar Swaminathan 
867*82527734SSukumar Swaminathan 	/* Save the link speed capabilities */
868*82527734SSukumar Swaminathan 	vpd->link_speed = mb->un.varRdConfig.lmt;
869*82527734SSukumar Swaminathan 	emlxs_process_link_speed(hba);
870291a2b48SSukumar Swaminathan 
871*82527734SSukumar Swaminathan 	/* Set the max node count */
872*82527734SSukumar Swaminathan 	if (cfg[CFG_NUM_NODES].current > 0) {
873*82527734SSukumar Swaminathan 		hba->max_nodes =
874*82527734SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
875*82527734SSukumar Swaminathan 		    mb->un.varRdConfig.max_rpi);
876*82527734SSukumar Swaminathan 	} else {
877*82527734SSukumar Swaminathan 		hba->max_nodes = mb->un.varRdConfig.max_rpi;
878*82527734SSukumar Swaminathan 	}
879291a2b48SSukumar Swaminathan 
880*82527734SSukumar Swaminathan 	/* Set the io throttle */
881*82527734SSukumar Swaminathan 	hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE;
882*82527734SSukumar Swaminathan 	hba->max_iotag = mb->un.varRdConfig.max_xri;
883291a2b48SSukumar Swaminathan 
884*82527734SSukumar Swaminathan 	/*
885*82527734SSukumar Swaminathan 	 * Allocate some memory for buffers
886*82527734SSukumar Swaminathan 	 */
887*82527734SSukumar Swaminathan 	if (emlxs_mem_alloc_buffer(hba) == 0) {
888*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
889*82527734SSukumar Swaminathan 		    "Unable to allocate memory buffers.");
890291a2b48SSukumar Swaminathan 
891*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
892*82527734SSukumar Swaminathan 		return (ENOMEM);
893*82527734SSukumar Swaminathan 	}
894291a2b48SSukumar Swaminathan 
895*82527734SSukumar Swaminathan 	/*
896*82527734SSukumar Swaminathan 	 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
897*82527734SSukumar Swaminathan 	 */
898*82527734SSukumar Swaminathan 	if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) ||
899*82527734SSukumar Swaminathan 	    ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0)) {
900*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
901*82527734SSukumar Swaminathan 		    "Unable to allocate diag buffers.");
902*82527734SSukumar Swaminathan 
903*82527734SSukumar Swaminathan 		rval = ENOMEM;
904*82527734SSukumar Swaminathan 		goto failed;
905291a2b48SSukumar Swaminathan 	}
906291a2b48SSukumar Swaminathan 
907*82527734SSukumar Swaminathan 	bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
908*82527734SSukumar Swaminathan 	    MEM_ELSBUF_SIZE);
909*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
910*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
911291a2b48SSukumar Swaminathan 
912*82527734SSukumar Swaminathan 	bzero(mp1->virt, MEM_ELSBUF_SIZE);
913*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
914*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
915291a2b48SSukumar Swaminathan 
916*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
917*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
918291a2b48SSukumar Swaminathan 
919*82527734SSukumar Swaminathan 	(void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys);
920*82527734SSukumar Swaminathan 
921*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
922*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
923*82527734SSukumar Swaminathan 		    "Unable to run BIU diag.  Mailbox cmd=%x status=%x",
924*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
925*82527734SSukumar Swaminathan 
926*82527734SSukumar Swaminathan 		rval = EIO;
927*82527734SSukumar Swaminathan 		goto failed;
928291a2b48SSukumar Swaminathan 	}
929291a2b48SSukumar Swaminathan 
930*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
931*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
932291a2b48SSukumar Swaminathan 
933*82527734SSukumar Swaminathan 	outptr = mp->virt;
934*82527734SSukumar Swaminathan 	inptr = mp1->virt;
935*82527734SSukumar Swaminathan 
936*82527734SSukumar Swaminathan 	for (i = 0; i < MEM_ELSBUF_SIZE; i++) {
937*82527734SSukumar Swaminathan 		if (*outptr++ != *inptr++) {
938*82527734SSukumar Swaminathan 			outptr--;
939*82527734SSukumar Swaminathan 			inptr--;
940*82527734SSukumar Swaminathan 
941*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
942*82527734SSukumar Swaminathan 			    "BIU diagnostic failed. "
943*82527734SSukumar Swaminathan 			    "offset %x value %x should be %x.",
944*82527734SSukumar Swaminathan 			    i, (uint32_t)*inptr, (uint32_t)*outptr);
945*82527734SSukumar Swaminathan 
946*82527734SSukumar Swaminathan 			rval = EIO;
947*82527734SSukumar Swaminathan 			goto failed;
948*82527734SSukumar Swaminathan 		}
949291a2b48SSukumar Swaminathan 	}
950291a2b48SSukumar Swaminathan 
951*82527734SSukumar Swaminathan 	hba->channel_fcp = FC_FCP_RING;
952*82527734SSukumar Swaminathan 	hba->channel_els = FC_ELS_RING;
953*82527734SSukumar Swaminathan 	hba->channel_ip = FC_IP_RING;
954*82527734SSukumar Swaminathan 	hba->channel_ct = FC_CT_RING;
955*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_count = MAX_RINGS;
956291a2b48SSukumar Swaminathan 
957*82527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
958*82527734SSukumar Swaminathan 	hba->io_count = 0;
959*82527734SSukumar Swaminathan 	hba->fc_iotag = 1;
960291a2b48SSukumar Swaminathan 
961*82527734SSukumar Swaminathan 	/*
962*82527734SSukumar Swaminathan 	 * OutOfRange (oor) iotags are used for abort or
963*82527734SSukumar Swaminathan 	 * close XRI commands
964*82527734SSukumar Swaminathan 	 */
965*82527734SSukumar Swaminathan 	hba->fc_oor_iotag = hba->max_iotag;
966291a2b48SSukumar Swaminathan 
967*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
968*82527734SSukumar Swaminathan 		cp = &hba->chan[i];
969291a2b48SSukumar Swaminathan 
970*82527734SSukumar Swaminathan 		/* 1 to 1 mapping between ring and channel */
971*82527734SSukumar Swaminathan 		cp->iopath = (void *)&hba->sli.sli3.ring[i];
972291a2b48SSukumar Swaminathan 
973*82527734SSukumar Swaminathan 		cp->hba = hba;
974*82527734SSukumar Swaminathan 		cp->channelno = i;
975291a2b48SSukumar Swaminathan 	}
976291a2b48SSukumar Swaminathan 
977*82527734SSukumar Swaminathan 	/*
978*82527734SSukumar Swaminathan 	 * Setup and issue mailbox CONFIGURE RING command
979*82527734SSukumar Swaminathan 	 */
980*82527734SSukumar Swaminathan 	for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) {
981*82527734SSukumar Swaminathan 		/*
982*82527734SSukumar Swaminathan 		 * Initialize cmd/rsp ring pointers
983*82527734SSukumar Swaminathan 		 */
984*82527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
985291a2b48SSukumar Swaminathan 
986*82527734SSukumar Swaminathan 		/* 1 to 1 mapping between ring and channel */
987*82527734SSukumar Swaminathan 		rp->channelp = &hba->chan[i];
988291a2b48SSukumar Swaminathan 
989*82527734SSukumar Swaminathan 		rp->hba = hba;
990*82527734SSukumar Swaminathan 		rp->ringno = (uint8_t)i;
991*82527734SSukumar Swaminathan 
992*82527734SSukumar Swaminathan 		rp->fc_cmdidx = 0;
993*82527734SSukumar Swaminathan 		rp->fc_rspidx = 0;
994*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING);
995*82527734SSukumar Swaminathan 
996*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
997*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
998*82527734SSukumar Swaminathan 
999*82527734SSukumar Swaminathan 		emlxs_mb_config_ring(hba, i, mbq);
1000*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1001*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1002*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1003*82527734SSukumar Swaminathan 			    "Unable to configure ring. "
1004*82527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1005*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1006*82527734SSukumar Swaminathan 
1007*82527734SSukumar Swaminathan 			rval = EIO;
1008*82527734SSukumar Swaminathan 			goto failed;
1009*82527734SSukumar Swaminathan 		}
1010291a2b48SSukumar Swaminathan 	}
1011291a2b48SSukumar Swaminathan 
1012*82527734SSukumar Swaminathan 	/*
1013*82527734SSukumar Swaminathan 	 * Setup link timers
1014*82527734SSukumar Swaminathan 	 */
1015*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
1016291a2b48SSukumar Swaminathan 
1017*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
1018*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
1019291a2b48SSukumar Swaminathan 
1020*82527734SSukumar Swaminathan 	emlxs_mb_config_link(hba, mbq);
1021*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1022*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1023*82527734SSukumar Swaminathan 		    "Unable to configure link. Mailbox cmd=%x status=%x",
1024*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1025291a2b48SSukumar Swaminathan 
1026*82527734SSukumar Swaminathan 		rval = EIO;
1027*82527734SSukumar Swaminathan 		goto failed;
1028*82527734SSukumar Swaminathan 	}
1029291a2b48SSukumar Swaminathan 
1030*82527734SSukumar Swaminathan #ifdef MAX_RRDY_SUPPORT
1031*82527734SSukumar Swaminathan 	/* Set MAX_RRDY if one is provided */
1032*82527734SSukumar Swaminathan 	if (cfg[CFG_MAX_RRDY].current) {
1033291a2b48SSukumar Swaminathan 
1034*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
1035*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1036*82527734SSukumar Swaminathan 
1037*82527734SSukumar Swaminathan 		emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412,
1038*82527734SSukumar Swaminathan 		    cfg[CFG_MAX_RRDY].current);
1039*82527734SSukumar Swaminathan 
1040*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1041*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1042*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1043*82527734SSukumar Swaminathan 			    "MAX_RRDY: Unable to set.  status=%x " \
1044*82527734SSukumar Swaminathan 			    "value=%d",
1045*82527734SSukumar Swaminathan 			    mb->mbxStatus, cfg[CFG_MAX_RRDY].current);
1046*82527734SSukumar Swaminathan 		} else {
1047*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1048*82527734SSukumar Swaminathan 			    "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current);
1049*82527734SSukumar Swaminathan 		}
1050*82527734SSukumar Swaminathan 	}
1051*82527734SSukumar Swaminathan #endif /* MAX_RRDY_SUPPORT */
1052*82527734SSukumar Swaminathan 
1053*82527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
1054*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
1055*82527734SSukumar Swaminathan 	mp = NULL;
1056*82527734SSukumar Swaminathan 
1057*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
1058*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
1059*82527734SSukumar Swaminathan 
1060*82527734SSukumar Swaminathan 	/*
1061*82527734SSukumar Swaminathan 	 * We need to get login parameters for NID
1062*82527734SSukumar Swaminathan 	 */
1063*82527734SSukumar Swaminathan 	(void) emlxs_mb_read_sparam(hba, mbq);
1064*82527734SSukumar Swaminathan 	mp = (MATCHMAP *)(mbq->bp);
1065*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1066*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1067*82527734SSukumar Swaminathan 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
1068*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1069*82527734SSukumar Swaminathan 
1070*82527734SSukumar Swaminathan 		rval = EIO;
1071*82527734SSukumar Swaminathan 		goto failed;
1072*82527734SSukumar Swaminathan 	}
1073*82527734SSukumar Swaminathan 
1074*82527734SSukumar Swaminathan 	/* Free the buffer since we were polling */
1075*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
1076*82527734SSukumar Swaminathan 	mp = NULL;
1077*82527734SSukumar Swaminathan 
1078*82527734SSukumar Swaminathan 	/* If no serial number in VPD data, then use the WWPN */
1079*82527734SSukumar Swaminathan 	if (vpd->serial_num[0] == 0) {
1080*82527734SSukumar Swaminathan 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
1081*82527734SSukumar Swaminathan 		for (i = 0; i < 12; i++) {
1082*82527734SSukumar Swaminathan 			status = *outptr++;
1083*82527734SSukumar Swaminathan 			j = ((status & 0xf0) >> 4);
1084*82527734SSukumar Swaminathan 			if (j <= 9) {
1085*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
1086*82527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
1087*82527734SSukumar Swaminathan 			} else {
1088*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
1089*82527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1090*82527734SSukumar Swaminathan 			}
1091*82527734SSukumar Swaminathan 
1092*82527734SSukumar Swaminathan 			i++;
1093*82527734SSukumar Swaminathan 			j = (status & 0xf);
1094*82527734SSukumar Swaminathan 			if (j <= 9) {
1095*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
1096*82527734SSukumar Swaminathan 				    (char)((uint8_t)'0' + (uint8_t)j);
1097*82527734SSukumar Swaminathan 			} else {
1098*82527734SSukumar Swaminathan 				vpd->serial_num[i] =
1099*82527734SSukumar Swaminathan 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1100291a2b48SSukumar Swaminathan 			}
1101291a2b48SSukumar Swaminathan 		}
1102*82527734SSukumar Swaminathan 
1103291a2b48SSukumar Swaminathan 		/*
1104*82527734SSukumar Swaminathan 		 * Set port number and port index to zero
1105*82527734SSukumar Swaminathan 		 * The WWN's are unique to each port and therefore port_num
1106*82527734SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
1107*82527734SSukumar Swaminathan 		 * in fca_bind_port()
1108291a2b48SSukumar Swaminathan 		 */
1109*82527734SSukumar Swaminathan 		vpd->port_num[0] = 0;
1110*82527734SSukumar Swaminathan 		vpd->port_index = 0;
1111*82527734SSukumar Swaminathan 	}
1112291a2b48SSukumar Swaminathan 
1113*82527734SSukumar Swaminathan 	/*
1114*82527734SSukumar Swaminathan 	 * Make first attempt to set a port index
1115*82527734SSukumar Swaminathan 	 * Check if this is a multifunction adapter
1116*82527734SSukumar Swaminathan 	 */
1117*82527734SSukumar Swaminathan 	if ((vpd->port_index == -1) &&
1118*82527734SSukumar Swaminathan 	    (hba->model_info.chip >= EMLXS_THOR_CHIP)) {
1119*82527734SSukumar Swaminathan 		char *buffer;
1120*82527734SSukumar Swaminathan 		int32_t i;
1121291a2b48SSukumar Swaminathan 
1122*82527734SSukumar Swaminathan 		/*
1123*82527734SSukumar Swaminathan 		 * The port address looks like this:
1124*82527734SSukumar Swaminathan 		 * 1	- for port index 0
1125*82527734SSukumar Swaminathan 		 * 1,1	- for port index 1
1126*82527734SSukumar Swaminathan 		 * 1,2	- for port index 2
1127*82527734SSukumar Swaminathan 		 */
1128*82527734SSukumar Swaminathan 		buffer = ddi_get_name_addr(hba->dip);
1129291a2b48SSukumar Swaminathan 
1130*82527734SSukumar Swaminathan 		if (buffer) {
1131*82527734SSukumar Swaminathan 			vpd->port_index = 0;
1132291a2b48SSukumar Swaminathan 
1133*82527734SSukumar Swaminathan 			/* Reverse scan for a comma */
1134*82527734SSukumar Swaminathan 			for (i = strlen(buffer) - 1; i > 0; i--) {
1135*82527734SSukumar Swaminathan 				if (buffer[i] == ',') {
1136*82527734SSukumar Swaminathan 					/* Comma found - set index now */
1137*82527734SSukumar Swaminathan 					vpd->port_index =
1138*82527734SSukumar Swaminathan 					    emlxs_strtol(&buffer[i + 1], 10);
1139*82527734SSukumar Swaminathan 					break;
1140*82527734SSukumar Swaminathan 				}
1141*82527734SSukumar Swaminathan 			}
1142*82527734SSukumar Swaminathan 		}
1143*82527734SSukumar Swaminathan 	}
1144291a2b48SSukumar Swaminathan 
1145*82527734SSukumar Swaminathan 	/* Make final attempt to set a port index */
1146*82527734SSukumar Swaminathan 	if (vpd->port_index == -1) {
1147*82527734SSukumar Swaminathan 		dev_info_t *p_dip;
1148*82527734SSukumar Swaminathan 		dev_info_t *c_dip;
1149291a2b48SSukumar Swaminathan 
1150*82527734SSukumar Swaminathan 		p_dip = ddi_get_parent(hba->dip);
1151*82527734SSukumar Swaminathan 		c_dip = ddi_get_child(p_dip);
1152291a2b48SSukumar Swaminathan 
1153*82527734SSukumar Swaminathan 		vpd->port_index = 0;
1154*82527734SSukumar Swaminathan 		while (c_dip && (hba->dip != c_dip)) {
1155*82527734SSukumar Swaminathan 			c_dip = ddi_get_next_sibling(c_dip);
1156*82527734SSukumar Swaminathan 			vpd->port_index++;
1157291a2b48SSukumar Swaminathan 		}
1158*82527734SSukumar Swaminathan 	}
1159291a2b48SSukumar Swaminathan 
1160*82527734SSukumar Swaminathan 	if (vpd->port_num[0] == 0) {
1161*82527734SSukumar Swaminathan 		if (hba->model_info.channels > 1) {
1162*82527734SSukumar Swaminathan 			(void) sprintf(vpd->port_num, "%d", vpd->port_index);
1163*82527734SSukumar Swaminathan 		}
1164*82527734SSukumar Swaminathan 	}
1165291a2b48SSukumar Swaminathan 
1166*82527734SSukumar Swaminathan 	if (vpd->id[0] == 0) {
1167*82527734SSukumar Swaminathan 		(void) strcpy(vpd->id, hba->model_info.model_desc);
1168*82527734SSukumar Swaminathan 	}
1169291a2b48SSukumar Swaminathan 
1170*82527734SSukumar Swaminathan 	if (vpd->manufacturer[0] == 0) {
1171*82527734SSukumar Swaminathan 		(void) strcpy(vpd->manufacturer, hba->model_info.manufacturer);
1172*82527734SSukumar Swaminathan 	}
1173291a2b48SSukumar Swaminathan 
1174*82527734SSukumar Swaminathan 	if (vpd->part_num[0] == 0) {
1175*82527734SSukumar Swaminathan 		(void) strcpy(vpd->part_num, hba->model_info.model);
1176*82527734SSukumar Swaminathan 	}
1177291a2b48SSukumar Swaminathan 
1178*82527734SSukumar Swaminathan 	if (vpd->model_desc[0] == 0) {
1179*82527734SSukumar Swaminathan 		(void) strcpy(vpd->model_desc, hba->model_info.model_desc);
1180*82527734SSukumar Swaminathan 	}
1181291a2b48SSukumar Swaminathan 
1182*82527734SSukumar Swaminathan 	if (vpd->model[0] == 0) {
1183*82527734SSukumar Swaminathan 		(void) strcpy(vpd->model, hba->model_info.model);
1184*82527734SSukumar Swaminathan 	}
1185291a2b48SSukumar Swaminathan 
1186*82527734SSukumar Swaminathan 	if (vpd->prog_types[0] == 0) {
1187*82527734SSukumar Swaminathan 		emlxs_build_prog_types(hba, vpd->prog_types);
1188291a2b48SSukumar Swaminathan 	}
1189291a2b48SSukumar Swaminathan 
1190*82527734SSukumar Swaminathan 	/* Create the symbolic names */
1191*82527734SSukumar Swaminathan 	(void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s",
1192*82527734SSukumar Swaminathan 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
1193*82527734SSukumar Swaminathan 	    (char *)utsname.nodename);
1194291a2b48SSukumar Swaminathan 
1195*82527734SSukumar Swaminathan 	(void) sprintf(hba->spn,
1196*82527734SSukumar Swaminathan 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1197*82527734SSukumar Swaminathan 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
1198*82527734SSukumar Swaminathan 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
1199*82527734SSukumar Swaminathan 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1200291a2b48SSukumar Swaminathan 
1201*82527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
1202*82527734SSukumar Swaminathan 		if ((hba->sparam.portName.nameType != NAME_IEEE) ||
1203*82527734SSukumar Swaminathan 		    (hba->sparam.portName.IEEEextMsn != 0) ||
1204*82527734SSukumar Swaminathan 		    (hba->sparam.portName.IEEEextLsb != 0)) {
1205291a2b48SSukumar Swaminathan 
1206*82527734SSukumar Swaminathan 			cfg[CFG_NETWORK_ON].current = 0;
1207291a2b48SSukumar Swaminathan 
1208*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1209*82527734SSukumar Swaminathan 			    "WWPN doesn't conform to IP profile: nameType=%x",
1210*82527734SSukumar Swaminathan 			    hba->sparam.portName.nameType);
1211*82527734SSukumar Swaminathan 		}
1212291a2b48SSukumar Swaminathan 
1213*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
1214*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1215291a2b48SSukumar Swaminathan 
1216*82527734SSukumar Swaminathan 		/* Issue CONFIG FARP */
1217*82527734SSukumar Swaminathan 		emlxs_mb_config_farp(hba, mbq);
1218*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1219*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1220*82527734SSukumar Swaminathan 			/*
1221*82527734SSukumar Swaminathan 			 * Let it go through even if failed.
1222*82527734SSukumar Swaminathan 			 */
1223*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1224*82527734SSukumar Swaminathan 			    "Unable to configure FARP. "
1225*82527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1226*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1227*82527734SSukumar Swaminathan 		}
1228291a2b48SSukumar Swaminathan 	}
1229*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
1230*82527734SSukumar Swaminathan 	/* Configure MSI map if required */
1231*82527734SSukumar Swaminathan 	if (hba->intr_count > 1) {
1232*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
1233*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1234291a2b48SSukumar Swaminathan 
1235*82527734SSukumar Swaminathan 		emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count);
1236291a2b48SSukumar Swaminathan 
1237*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
1238*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1239*82527734SSukumar Swaminathan 			goto msi_configured;
1240*82527734SSukumar Swaminathan 		}
1241291a2b48SSukumar Swaminathan 
1242*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1243*82527734SSukumar Swaminathan 		    "Unable to config MSIX.  Mailbox cmd=0x%x status=0x%x",
1244*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1245291a2b48SSukumar Swaminathan 
1246*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
1247*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1248291a2b48SSukumar Swaminathan 
1249*82527734SSukumar Swaminathan 		emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count);
1250291a2b48SSukumar Swaminathan 
1251*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
1252*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1253*82527734SSukumar Swaminathan 			goto msi_configured;
1254291a2b48SSukumar Swaminathan 		}
1255291a2b48SSukumar Swaminathan 
1256291a2b48SSukumar Swaminathan 
1257*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1258*82527734SSukumar Swaminathan 		    "Unable to config MSI.  Mailbox cmd=0x%x status=0x%x",
1259*82527734SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
1260291a2b48SSukumar Swaminathan 
1261*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1262*82527734SSukumar Swaminathan 		    "Attempting single interrupt mode...");
1263291a2b48SSukumar Swaminathan 
1264*82527734SSukumar Swaminathan 		/* First cleanup old interrupts */
1265*82527734SSukumar Swaminathan 		(void) emlxs_msi_remove(hba);
1266*82527734SSukumar Swaminathan 		(void) emlxs_msi_uninit(hba);
1267291a2b48SSukumar Swaminathan 
1268*82527734SSukumar Swaminathan 		status = emlxs_msi_init(hba, 1);
1269291a2b48SSukumar Swaminathan 
1270*82527734SSukumar Swaminathan 		if (status != DDI_SUCCESS) {
1271*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1272*82527734SSukumar Swaminathan 			    "Unable to initialize interrupt. status=%d",
1273*82527734SSukumar Swaminathan 			    status);
1274291a2b48SSukumar Swaminathan 
1275*82527734SSukumar Swaminathan 			rval = EIO;
1276*82527734SSukumar Swaminathan 			goto failed;
1277291a2b48SSukumar Swaminathan 		}
1278291a2b48SSukumar Swaminathan 
1279*82527734SSukumar Swaminathan 		/*
1280*82527734SSukumar Swaminathan 		 * Reset adapter - The adapter needs to be reset because
1281*82527734SSukumar Swaminathan 		 * the bus cannot handle the MSI change without handshaking
1282*82527734SSukumar Swaminathan 		 * with the adapter again
1283*82527734SSukumar Swaminathan 		 */
1284291a2b48SSukumar Swaminathan 
1285*82527734SSukumar Swaminathan 		(void) emlxs_mem_free_buffer(hba);
1286*82527734SSukumar Swaminathan 		fw_check = 0;
1287*82527734SSukumar Swaminathan 		goto reset;
1288*82527734SSukumar Swaminathan 	}
1289291a2b48SSukumar Swaminathan 
1290*82527734SSukumar Swaminathan msi_configured:
1291291a2b48SSukumar Swaminathan 
1292*82527734SSukumar Swaminathan 
1293*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
1294*82527734SSukumar Swaminathan 
1295*82527734SSukumar Swaminathan 	/*
1296*82527734SSukumar Swaminathan 	 * We always disable the firmware traffic cop feature
1297*82527734SSukumar Swaminathan 	 */
1298*82527734SSukumar Swaminathan 	if (emlxs_disable_traffic_cop) {
1299*82527734SSukumar Swaminathan 		/* Reuse mbq from previous mbox */
1300*82527734SSukumar Swaminathan 		bzero(mbq, sizeof (MAILBOXQ));
1301*82527734SSukumar Swaminathan 
1302*82527734SSukumar Swaminathan 		emlxs_disable_tc(hba, mbq);
1303*82527734SSukumar Swaminathan 		if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1304*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
1305*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1306*82527734SSukumar Swaminathan 			    "Unable to disable traffic cop. "
1307*82527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1308*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1309*82527734SSukumar Swaminathan 
1310*82527734SSukumar Swaminathan 			rval = EIO;
1311*82527734SSukumar Swaminathan 			goto failed;
1312291a2b48SSukumar Swaminathan 		}
1313*82527734SSukumar Swaminathan 	}
1314291a2b48SSukumar Swaminathan 
1315*82527734SSukumar Swaminathan 
1316*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
1317*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
1318*82527734SSukumar Swaminathan 
1319*82527734SSukumar Swaminathan 	/* Register for async events */
1320*82527734SSukumar Swaminathan 	emlxs_mb_async_event(hba, mbq);
1321*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1322*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1323*82527734SSukumar Swaminathan 		    "Async events disabled. Mailbox status=%x",
1324*82527734SSukumar Swaminathan 		    mb->mbxStatus);
1325*82527734SSukumar Swaminathan 	} else {
1326*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1327*82527734SSukumar Swaminathan 		    "Async events enabled.");
1328*82527734SSukumar Swaminathan 		hba->flag |= FC_ASYNC_EVENTS;
1329291a2b48SSukumar Swaminathan 	}
1330291a2b48SSukumar Swaminathan 
1331*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
1332291a2b48SSukumar Swaminathan 
1333*82527734SSukumar Swaminathan 	emlxs_sli3_enable_intr(hba);
1334291a2b48SSukumar Swaminathan 
1335*82527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
1336*82527734SSukumar Swaminathan 		if (hba->tgt_mode) {
1337*82527734SSukumar Swaminathan 			if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) {
1338*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1339*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
1340*82527734SSukumar Swaminathan 				    "Unable to setup FCT HBQ.");
1341291a2b48SSukumar Swaminathan 
1342*82527734SSukumar Swaminathan 				rval = ENOMEM;
1343*82527734SSukumar Swaminathan 				goto failed;
1344*82527734SSukumar Swaminathan 			}
1345*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1346*82527734SSukumar Swaminathan 			    "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1347*82527734SSukumar Swaminathan 		}
1348291a2b48SSukumar Swaminathan 
1349*82527734SSukumar Swaminathan 		if (cfg[CFG_NETWORK_ON].current) {
1350*82527734SSukumar Swaminathan 			if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) {
1351*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1352*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
1353*82527734SSukumar Swaminathan 				    "Unable to setup IP HBQ.");
1354291a2b48SSukumar Swaminathan 
1355*82527734SSukumar Swaminathan 				rval = ENOMEM;
1356*82527734SSukumar Swaminathan 				goto failed;
1357*82527734SSukumar Swaminathan 			}
1358*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1359*82527734SSukumar Swaminathan 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1360*82527734SSukumar Swaminathan 		}
1361291a2b48SSukumar Swaminathan 
1362*82527734SSukumar Swaminathan 		if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) {
1363*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1364*82527734SSukumar Swaminathan 			    "Unable to setup ELS HBQ.");
1365*82527734SSukumar Swaminathan 			rval = ENOMEM;
1366*82527734SSukumar Swaminathan 			goto failed;
1367*82527734SSukumar Swaminathan 		}
1368*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1369*82527734SSukumar Swaminathan 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1370291a2b48SSukumar Swaminathan 
1371*82527734SSukumar Swaminathan 		if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) {
1372*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1373*82527734SSukumar Swaminathan 			    "Unable to setup CT HBQ.");
1374291a2b48SSukumar Swaminathan 
1375*82527734SSukumar Swaminathan 			rval = ENOMEM;
1376*82527734SSukumar Swaminathan 			goto failed;
1377*82527734SSukumar Swaminathan 		}
1378*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1379*82527734SSukumar Swaminathan 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1380*82527734SSukumar Swaminathan 	} else {
1381*82527734SSukumar Swaminathan 		if (hba->tgt_mode) {
1382*82527734SSukumar Swaminathan 			/* Post the FCT unsol buffers */
1383*82527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[FC_FCT_RING];
1384*82527734SSukumar Swaminathan 			for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) {
1385*82527734SSukumar Swaminathan 				(void) emlxs_post_buffer(hba, rp, 2);
1386*82527734SSukumar Swaminathan 			}
1387*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1388*82527734SSukumar Swaminathan 			    "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1389*82527734SSukumar Swaminathan 		}
1390291a2b48SSukumar Swaminathan 
1391*82527734SSukumar Swaminathan 		if (cfg[CFG_NETWORK_ON].current) {
1392*82527734SSukumar Swaminathan 			/* Post the IP unsol buffers */
1393*82527734SSukumar Swaminathan 			rp = &hba->sli.sli3.ring[FC_IP_RING];
1394*82527734SSukumar Swaminathan 			for (j = 0; j < MEM_IPBUF_COUNT; j += 2) {
1395*82527734SSukumar Swaminathan 				(void) emlxs_post_buffer(hba, rp, 2);
1396*82527734SSukumar Swaminathan 			}
1397*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1398*82527734SSukumar Swaminathan 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1399*82527734SSukumar Swaminathan 		}
1400291a2b48SSukumar Swaminathan 
1401*82527734SSukumar Swaminathan 		/* Post the ELS unsol buffers */
1402*82527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[FC_ELS_RING];
1403*82527734SSukumar Swaminathan 		for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) {
1404*82527734SSukumar Swaminathan 			(void) emlxs_post_buffer(hba, rp, 2);
1405*82527734SSukumar Swaminathan 		}
1406*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1407*82527734SSukumar Swaminathan 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1408291a2b48SSukumar Swaminathan 
1409*82527734SSukumar Swaminathan 
1410*82527734SSukumar Swaminathan 		/* Post the CT unsol buffers */
1411*82527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[FC_CT_RING];
1412*82527734SSukumar Swaminathan 		for (j = 0; j < MEM_CTBUF_COUNT; j += 2) {
1413*82527734SSukumar Swaminathan 			(void) emlxs_post_buffer(hba, rp, 2);
1414*82527734SSukumar Swaminathan 		}
1415*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1416*82527734SSukumar Swaminathan 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1417291a2b48SSukumar Swaminathan 	}
1418291a2b48SSukumar Swaminathan 
1419291a2b48SSukumar Swaminathan 
1420*82527734SSukumar Swaminathan 	/* Reuse mbq from previous mbox */
1421*82527734SSukumar Swaminathan 	bzero(mbq, sizeof (MAILBOXQ));
1422291a2b48SSukumar Swaminathan 
1423*82527734SSukumar Swaminathan 	/*
1424*82527734SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command
1425*82527734SSukumar Swaminathan 	 * At this point, the interrupt will be generated by the HW
1426*82527734SSukumar Swaminathan 	 * Do this only if persist-linkdown is not set
1427*82527734SSukumar Swaminathan 	 */
1428*82527734SSukumar Swaminathan 	if (cfg[CFG_PERSIST_LINKDOWN].current == 0) {
1429*82527734SSukumar Swaminathan 		emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current,
1430*82527734SSukumar Swaminathan 		    cfg[CFG_LINK_SPEED].current);
1431291a2b48SSukumar Swaminathan 
1432*82527734SSukumar Swaminathan 		rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1433*82527734SSukumar Swaminathan 		if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1434291a2b48SSukumar Swaminathan 
1435*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1436*82527734SSukumar Swaminathan 			    "Unable to initialize link. " \
1437*82527734SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1438*82527734SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1439291a2b48SSukumar Swaminathan 
1440*82527734SSukumar Swaminathan 			rval = EIO;
1441*82527734SSukumar Swaminathan 			goto failed;
1442*82527734SSukumar Swaminathan 		}
1443291a2b48SSukumar Swaminathan 
1444*82527734SSukumar Swaminathan 		/*
1445*82527734SSukumar Swaminathan 		 * Enable link attention interrupt
1446*82527734SSukumar Swaminathan 		 */
1447*82527734SSukumar Swaminathan 		emlxs_enable_latt(hba);
1448291a2b48SSukumar Swaminathan 
1449*82527734SSukumar Swaminathan 		/* Wait for link to come up */
1450*82527734SSukumar Swaminathan 		i = cfg[CFG_LINKUP_DELAY].current;
1451*82527734SSukumar Swaminathan 		while (i && (hba->state < FC_LINK_UP)) {
1452*82527734SSukumar Swaminathan 			/* Check for hardware error */
1453*82527734SSukumar Swaminathan 			if (hba->state == FC_ERROR) {
1454*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1455*82527734SSukumar Swaminathan 				    &emlxs_init_failed_msg,
1456*82527734SSukumar Swaminathan 				    "Adapter error.", mb->mbxCommand,
1457*82527734SSukumar Swaminathan 				    mb->mbxStatus);
1458291a2b48SSukumar Swaminathan 
1459*82527734SSukumar Swaminathan 				rval = EIO;
1460*82527734SSukumar Swaminathan 				goto failed;
1461*82527734SSukumar Swaminathan 			}
1462*82527734SSukumar Swaminathan 
1463*82527734SSukumar Swaminathan 			DELAYMS(1000);
1464*82527734SSukumar Swaminathan 			i--;
1465*82527734SSukumar Swaminathan 		}
1466*82527734SSukumar Swaminathan 	} else {
1467*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1468*82527734SSukumar Swaminathan 	}
1469*82527734SSukumar Swaminathan 
1470*82527734SSukumar Swaminathan 	/*
1471*82527734SSukumar Swaminathan 	 * The leadvile driver will now handle the FLOGI at the driver level
1472*82527734SSukumar Swaminathan 	 */
1473291a2b48SSukumar Swaminathan 
1474291a2b48SSukumar Swaminathan 	return (0);
1475291a2b48SSukumar Swaminathan 
1476*82527734SSukumar Swaminathan failed:
1477291a2b48SSukumar Swaminathan 
1478*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
1479291a2b48SSukumar Swaminathan 
1480*82527734SSukumar Swaminathan 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
1481*82527734SSukumar Swaminathan 		(void) EMLXS_INTR_REMOVE(hba);
1482*82527734SSukumar Swaminathan 	}
1483291a2b48SSukumar Swaminathan 
1484*82527734SSukumar Swaminathan 	if (mp) {
1485*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
1486*82527734SSukumar Swaminathan 		mp = NULL;
1487*82527734SSukumar Swaminathan 	}
1488291a2b48SSukumar Swaminathan 
1489*82527734SSukumar Swaminathan 	if (mp1) {
1490*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
1491*82527734SSukumar Swaminathan 		mp1 = NULL;
1492*82527734SSukumar Swaminathan 	}
1493291a2b48SSukumar Swaminathan 
1494*82527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1495291a2b48SSukumar Swaminathan 
1496*82527734SSukumar Swaminathan 	if (mbq) {
1497*82527734SSukumar Swaminathan 		(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1498*82527734SSukumar Swaminathan 		mbq = NULL;
1499*82527734SSukumar Swaminathan 		mb = NULL;
1500291a2b48SSukumar Swaminathan 	}
1501291a2b48SSukumar Swaminathan 
1502*82527734SSukumar Swaminathan 	if (rval == 0) {
1503*82527734SSukumar Swaminathan 		rval = EIO;
1504*82527734SSukumar Swaminathan 	}
1505291a2b48SSukumar Swaminathan 
1506*82527734SSukumar Swaminathan 	return (rval);
1507291a2b48SSukumar Swaminathan 
1508*82527734SSukumar Swaminathan } /* emlxs_sli3_online() */
1509291a2b48SSukumar Swaminathan 
1510291a2b48SSukumar Swaminathan 
1511*82527734SSukumar Swaminathan static void
1512*82527734SSukumar Swaminathan emlxs_sli3_offline(emlxs_hba_t *hba)
1513*82527734SSukumar Swaminathan {
1514*82527734SSukumar Swaminathan 	/* Reverse emlxs_sli3_online */
1515291a2b48SSukumar Swaminathan 
1516*82527734SSukumar Swaminathan 	/* Kill the adapter */
1517*82527734SSukumar Swaminathan 	emlxs_sli3_hba_kill(hba);
1518291a2b48SSukumar Swaminathan 
1519*82527734SSukumar Swaminathan 	/* Free driver shared memory */
1520*82527734SSukumar Swaminathan 	(void) emlxs_mem_free_buffer(hba);
1521291a2b48SSukumar Swaminathan 
1522*82527734SSukumar Swaminathan } /* emlxs_sli3_offline() */
1523291a2b48SSukumar Swaminathan 
1524291a2b48SSukumar Swaminathan 
1525*82527734SSukumar Swaminathan static int
1526*82527734SSukumar Swaminathan emlxs_sli3_map_hdw(emlxs_hba_t *hba)
1527291a2b48SSukumar Swaminathan {
1528*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
1529*82527734SSukumar Swaminathan 	dev_info_t		*dip;
1530*82527734SSukumar Swaminathan 	ddi_device_acc_attr_t	dev_attr;
1531*82527734SSukumar Swaminathan 	int			status;
1532291a2b48SSukumar Swaminathan 
1533*82527734SSukumar Swaminathan 	dip = (dev_info_t *)hba->dip;
1534*82527734SSukumar Swaminathan 	dev_attr = emlxs_dev_acc_attr;
1535291a2b48SSukumar Swaminathan 
1536*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
1537291a2b48SSukumar Swaminathan 
1538*82527734SSukumar Swaminathan 		if (hba->sli.sli3.slim_acc_handle == 0) {
1539*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip,
1540*82527734SSukumar Swaminathan 			    SBUS_DFLY_SLIM_RINDEX,
1541*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.slim_addr,
1542*82527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
1543*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1544*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1545*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1546*82527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup SLIM failed. "
1547*82527734SSukumar Swaminathan 				    "status=%x", status);
1548*82527734SSukumar Swaminathan 				goto failed;
1549*82527734SSukumar Swaminathan 			}
1550*82527734SSukumar Swaminathan 		}
1551*82527734SSukumar Swaminathan 		if (hba->sli.sli3.csr_acc_handle == 0) {
1552*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip,
1553*82527734SSukumar Swaminathan 			    SBUS_DFLY_CSR_RINDEX,
1554*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.csr_addr,
1555*82527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
1556*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1557*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1558*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1559*82527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup DFLY CSR "
1560*82527734SSukumar Swaminathan 				    "failed. status=%x", status);
1561*82527734SSukumar Swaminathan 				goto failed;
1562*82527734SSukumar Swaminathan 			}
1563*82527734SSukumar Swaminathan 		}
1564*82527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_flash_acc_handle == 0) {
1565*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR,
1566*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0,
1567*82527734SSukumar Swaminathan 			    &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle);
1568*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1569*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1570*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1571*82527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup Fcode Flash "
1572*82527734SSukumar Swaminathan 				    "failed. status=%x", status);
1573*82527734SSukumar Swaminathan 				goto failed;
1574*82527734SSukumar Swaminathan 			}
1575*82527734SSukumar Swaminathan 		}
1576*82527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_core_acc_handle == 0) {
1577*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX,
1578*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0,
1579*82527734SSukumar Swaminathan 			    &dev_attr, &hba->sli.sli3.sbus_core_acc_handle);
1580*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1581*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1582*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1583*82527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup TITAN CORE "
1584*82527734SSukumar Swaminathan 				    "failed. status=%x", status);
1585*82527734SSukumar Swaminathan 				goto failed;
1586*82527734SSukumar Swaminathan 			}
1587291a2b48SSukumar Swaminathan 		}
1588291a2b48SSukumar Swaminathan 
1589*82527734SSukumar Swaminathan 		if (hba->sli.sli3.sbus_csr_handle == 0) {
1590*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX,
1591*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.sbus_csr_addr,
1592*82527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle);
1593*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1594*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1595*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1596*82527734SSukumar Swaminathan 				    "(SBUS) ddi_regs_map_setup TITAN CSR "
1597*82527734SSukumar Swaminathan 				    "failed. status=%x", status);
1598*82527734SSukumar Swaminathan 				goto failed;
1599291a2b48SSukumar Swaminathan 			}
1600291a2b48SSukumar Swaminathan 		}
1601*82527734SSukumar Swaminathan 	} else {	/* ****** PCI ****** */
1602291a2b48SSukumar Swaminathan 
1603*82527734SSukumar Swaminathan 		if (hba->sli.sli3.slim_acc_handle == 0) {
1604*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX,
1605*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.slim_addr,
1606*82527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
1607*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1608*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1609*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1610*82527734SSukumar Swaminathan 				    "(PCI) ddi_regs_map_setup SLIM failed. "
1611*82527734SSukumar Swaminathan 				    "stat=%d mem=%p attr=%p hdl=%p",
1612*82527734SSukumar Swaminathan 				    status, &hba->sli.sli3.slim_addr, &dev_attr,
1613*82527734SSukumar Swaminathan 				    &hba->sli.sli3.slim_acc_handle);
1614*82527734SSukumar Swaminathan 				goto failed;
1615*82527734SSukumar Swaminathan 			}
1616291a2b48SSukumar Swaminathan 		}
1617291a2b48SSukumar Swaminathan 
1618*82527734SSukumar Swaminathan 		/*
1619*82527734SSukumar Swaminathan 		 * Map in control registers, using memory-mapped version of
1620*82527734SSukumar Swaminathan 		 * the registers rather than the I/O space-mapped registers.
1621*82527734SSukumar Swaminathan 		 */
1622*82527734SSukumar Swaminathan 		if (hba->sli.sli3.csr_acc_handle == 0) {
1623*82527734SSukumar Swaminathan 			status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX,
1624*82527734SSukumar Swaminathan 			    (caddr_t *)&hba->sli.sli3.csr_addr,
1625*82527734SSukumar Swaminathan 			    0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
1626*82527734SSukumar Swaminathan 			if (status != DDI_SUCCESS) {
1627*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1628*82527734SSukumar Swaminathan 				    &emlxs_attach_failed_msg,
1629*82527734SSukumar Swaminathan 				    "ddi_regs_map_setup CSR failed. status=%x",
1630*82527734SSukumar Swaminathan 				    status);
1631*82527734SSukumar Swaminathan 				goto failed;
1632*82527734SSukumar Swaminathan 			}
1633*82527734SSukumar Swaminathan 		}
1634291a2b48SSukumar Swaminathan 	}
1635291a2b48SSukumar Swaminathan 
1636*82527734SSukumar Swaminathan 	if (hba->sli.sli3.slim2.virt == 0) {
1637*82527734SSukumar Swaminathan 		MBUF_INFO	*buf_info;
1638*82527734SSukumar Swaminathan 		MBUF_INFO	bufinfo;
1639291a2b48SSukumar Swaminathan 
1640*82527734SSukumar Swaminathan 		buf_info = &bufinfo;
1641291a2b48SSukumar Swaminathan 
1642*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1643*82527734SSukumar Swaminathan 		buf_info->size = SLI_SLIM2_SIZE;
1644*82527734SSukumar Swaminathan 		buf_info->flags =
1645*82527734SSukumar Swaminathan 		    FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1646*82527734SSukumar Swaminathan 		buf_info->align = ddi_ptob(dip, 1L);
1647291a2b48SSukumar Swaminathan 
1648*82527734SSukumar Swaminathan 		(void) emlxs_mem_alloc(hba, buf_info);
1649291a2b48SSukumar Swaminathan 
1650*82527734SSukumar Swaminathan 		if (buf_info->virt == NULL) {
1651*82527734SSukumar Swaminathan 			goto failed;
1652291a2b48SSukumar Swaminathan 		}
1653*82527734SSukumar Swaminathan 
1654*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.virt = (uint8_t *)buf_info->virt;
1655*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.phys = buf_info->phys;
1656*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE;
1657*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.data_handle = buf_info->data_handle;
1658*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle;
1659*82527734SSukumar Swaminathan 		bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE);
1660291a2b48SSukumar Swaminathan 	}
1661291a2b48SSukumar Swaminathan 
1662*82527734SSukumar Swaminathan 	/* offset from beginning of register space */
1663*82527734SSukumar Swaminathan 	hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1664*82527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HA_REG_OFFSET));
1665*82527734SSukumar Swaminathan 	hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1666*82527734SSukumar Swaminathan 	    (sizeof (uint32_t) * CA_REG_OFFSET));
1667*82527734SSukumar Swaminathan 	hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1668*82527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HS_REG_OFFSET));
1669*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1670*82527734SSukumar Swaminathan 	    (sizeof (uint32_t) * HC_REG_OFFSET));
1671*82527734SSukumar Swaminathan 	hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1672*82527734SSukumar Swaminathan 	    (sizeof (uint32_t) * BC_REG_OFFSET));
1673291a2b48SSukumar Swaminathan 
1674*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
1675*82527734SSukumar Swaminathan 		/* offset from beginning of register space */
1676*82527734SSukumar Swaminathan 		/* for TITAN registers */
1677*82527734SSukumar Swaminathan 		hba->sli.sli3.shc_reg_addr =
1678*82527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1679*82527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET));
1680*82527734SSukumar Swaminathan 		hba->sli.sli3.shs_reg_addr =
1681*82527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1682*82527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET));
1683*82527734SSukumar Swaminathan 		hba->sli.sli3.shu_reg_addr =
1684*82527734SSukumar Swaminathan 		    (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1685*82527734SSukumar Swaminathan 		    (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET));
1686*82527734SSukumar Swaminathan 	}
1687*82527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
1688291a2b48SSukumar Swaminathan 
1689*82527734SSukumar Swaminathan 	return (0);
1690291a2b48SSukumar Swaminathan 
1691*82527734SSukumar Swaminathan failed:
1692291a2b48SSukumar Swaminathan 
1693*82527734SSukumar Swaminathan 	emlxs_sli3_unmap_hdw(hba);
1694*82527734SSukumar Swaminathan 	return (ENOMEM);
1695291a2b48SSukumar Swaminathan 
1696*82527734SSukumar Swaminathan } /* emlxs_sli3_map_hdw() */
1697291a2b48SSukumar Swaminathan 
1698291a2b48SSukumar Swaminathan 
1699*82527734SSukumar Swaminathan static void
1700*82527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(emlxs_hba_t *hba)
1701*82527734SSukumar Swaminathan {
1702*82527734SSukumar Swaminathan 	MBUF_INFO	bufinfo;
1703*82527734SSukumar Swaminathan 	MBUF_INFO	*buf_info = &bufinfo;
1704291a2b48SSukumar Swaminathan 
1705*82527734SSukumar Swaminathan 	if (hba->sli.sli3.csr_acc_handle) {
1706*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle);
1707*82527734SSukumar Swaminathan 		hba->sli.sli3.csr_acc_handle = 0;
1708*82527734SSukumar Swaminathan 	}
1709291a2b48SSukumar Swaminathan 
1710*82527734SSukumar Swaminathan 	if (hba->sli.sli3.slim_acc_handle) {
1711*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle);
1712*82527734SSukumar Swaminathan 		hba->sli.sli3.slim_acc_handle = 0;
1713*82527734SSukumar Swaminathan 	}
1714291a2b48SSukumar Swaminathan 
1715*82527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_flash_acc_handle) {
1716*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle);
1717*82527734SSukumar Swaminathan 		hba->sli.sli3.sbus_flash_acc_handle = 0;
1718*82527734SSukumar Swaminathan 	}
1719291a2b48SSukumar Swaminathan 
1720*82527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_core_acc_handle) {
1721*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle);
1722*82527734SSukumar Swaminathan 		hba->sli.sli3.sbus_core_acc_handle = 0;
1723*82527734SSukumar Swaminathan 	}
1724291a2b48SSukumar Swaminathan 
1725*82527734SSukumar Swaminathan 	if (hba->sli.sli3.sbus_csr_handle) {
1726*82527734SSukumar Swaminathan 		ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle);
1727*82527734SSukumar Swaminathan 		hba->sli.sli3.sbus_csr_handle = 0;
1728*82527734SSukumar Swaminathan 	}
1729291a2b48SSukumar Swaminathan 
1730*82527734SSukumar Swaminathan 	if (hba->sli.sli3.slim2.virt) {
1731*82527734SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
1732291a2b48SSukumar Swaminathan 
1733*82527734SSukumar Swaminathan 		if (hba->sli.sli3.slim2.phys) {
1734*82527734SSukumar Swaminathan 			buf_info->phys = hba->sli.sli3.slim2.phys;
1735*82527734SSukumar Swaminathan 			buf_info->data_handle = hba->sli.sli3.slim2.data_handle;
1736*82527734SSukumar Swaminathan 			buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle;
1737*82527734SSukumar Swaminathan 			buf_info->flags = FC_MBUF_DMA;
1738*82527734SSukumar Swaminathan 		}
1739291a2b48SSukumar Swaminathan 
1740*82527734SSukumar Swaminathan 		buf_info->virt = (uint32_t *)hba->sli.sli3.slim2.virt;
1741*82527734SSukumar Swaminathan 		buf_info->size = hba->sli.sli3.slim2.size;
1742*82527734SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
1743291a2b48SSukumar Swaminathan 
1744*82527734SSukumar Swaminathan 		hba->sli.sli3.slim2.virt = 0;
1745291a2b48SSukumar Swaminathan 	}
1746291a2b48SSukumar Swaminathan 
1747291a2b48SSukumar Swaminathan 
1748*82527734SSukumar Swaminathan 	return;
1749291a2b48SSukumar Swaminathan 
1750*82527734SSukumar Swaminathan } /* emlxs_sli3_unmap_hdw() */
1751291a2b48SSukumar Swaminathan 
1752291a2b48SSukumar Swaminathan 
1753*82527734SSukumar Swaminathan static uint32_t
1754*82527734SSukumar Swaminathan emlxs_sli3_hba_init(emlxs_hba_t *hba)
1755*82527734SSukumar Swaminathan {
1756*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1757*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
1758*82527734SSukumar Swaminathan 	emlxs_config_t *cfg;
1759*82527734SSukumar Swaminathan 	int32_t i;
17604baa2c25SSukumar Swaminathan 
1761*82527734SSukumar Swaminathan 	cfg = &CFG;
1762*82527734SSukumar Swaminathan 	i = 0;
1763291a2b48SSukumar Swaminathan 
1764*82527734SSukumar Swaminathan 	/* Restart the adapter */
1765*82527734SSukumar Swaminathan 	if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) {
1766*82527734SSukumar Swaminathan 		return (1);
1767*82527734SSukumar Swaminathan 	}
1768291a2b48SSukumar Swaminathan 
1769*82527734SSukumar Swaminathan 	hba->channel_fcp = FC_FCP_RING;
1770*82527734SSukumar Swaminathan 	hba->channel_els = FC_ELS_RING;
1771*82527734SSukumar Swaminathan 	hba->channel_ip = FC_IP_RING;
1772*82527734SSukumar Swaminathan 	hba->channel_ct = FC_CT_RING;
1773*82527734SSukumar Swaminathan 	hba->chan_count = MAX_RINGS;
1774*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_count = MAX_RINGS;
1775291a2b48SSukumar Swaminathan 
1776291a2b48SSukumar Swaminathan 	/*
1777*82527734SSukumar Swaminathan 	 * WARNING: There is a max of 6 ring masks allowed
1778291a2b48SSukumar Swaminathan 	 */
1779*82527734SSukumar Swaminathan 	/* RING 0 - FCP */
1780*82527734SSukumar Swaminathan 	if (hba->tgt_mode) {
1781*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_FCP_RING] = 1;
1782*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_rval[i] = FC_FCP_CMND;
1783*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_rmask[i] = 0;
1784*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_tval[i] = FC_FCP_DATA;
1785*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_tmask[i++] = 0xFF;
1786*82527734SSukumar Swaminathan 	} else {
1787*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_FCP_RING] = 0;
1788291a2b48SSukumar Swaminathan 	}
1789291a2b48SSukumar Swaminathan 
1790*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES;
1791*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES;
1792291a2b48SSukumar Swaminathan 
1793*82527734SSukumar Swaminathan 	/* RING 1 - IP */
1794*82527734SSukumar Swaminathan 	if (cfg[CFG_NETWORK_ON].current) {
1795*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_IP_RING] = 1;
1796*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */
1797*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_rmask[i] = 0xFF;
1798*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_tval[i] = FC_LLC_SNAP; /* LLC/SNAP */
1799*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_tmask[i++] = 0xFF;
1800291a2b48SSukumar Swaminathan 	} else {
1801*82527734SSukumar Swaminathan 		hba->sli.sli3.ring_masks[FC_IP_RING] = 0;
1802291a2b48SSukumar Swaminathan 	}
1803291a2b48SSukumar Swaminathan 
1804*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES;
1805*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES;
18064baa2c25SSukumar Swaminathan 
1807*82527734SSukumar Swaminathan 	/* RING 2 - ELS */
1808*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_masks[FC_ELS_RING] = 1;
1809*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_rval[i] = FC_ELS_REQ;	/* ELS request/rsp */
1810*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_rmask[i] = 0xFE;
1811*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_tval[i] = FC_ELS_DATA;	/* ELS */
1812*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_tmask[i++] = 0xFF;
1813291a2b48SSukumar Swaminathan 
1814*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES;
1815*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES;
1816291a2b48SSukumar Swaminathan 
1817*82527734SSukumar Swaminathan 	/* RING 3 - CT */
1818*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_masks[FC_CT_RING] = 1;
1819*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL;	/* CT request/rsp */
1820*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_rmask[i] = 0xFE;
1821*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_tval[i] = FC_CT_TYPE;	/* CT */
1822*82527734SSukumar Swaminathan 	hba->sli.sli3.ring_tmask[i++] = 0xFF;
1823291a2b48SSukumar Swaminathan 
1824*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES;
1825*82527734SSukumar Swaminathan 	hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES;
1826291a2b48SSukumar Swaminathan 
1827*82527734SSukumar Swaminathan 	if (i > 6) {
1828*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
1829*82527734SSukumar Swaminathan 		    "emlxs_hba_init: Too many ring masks defined. cnt=%d", i);
1830*82527734SSukumar Swaminathan 		return (1);
1831*82527734SSukumar Swaminathan 	}
1832*82527734SSukumar Swaminathan 
1833*82527734SSukumar Swaminathan 	/* Initialize all the port objects */
1834*82527734SSukumar Swaminathan 	hba->vpi_base = 0;
1835*82527734SSukumar Swaminathan 	hba->vpi_max = 0;
1836*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
1837*82527734SSukumar Swaminathan 		vport = &VPORT(i);
1838*82527734SSukumar Swaminathan 		vport->hba = hba;
1839*82527734SSukumar Swaminathan 		vport->vpi = i;
1840*82527734SSukumar Swaminathan 	}
1841*82527734SSukumar Swaminathan 
1842*82527734SSukumar Swaminathan 	/*
1843*82527734SSukumar Swaminathan 	 * Initialize the max_node count to a default value if needed
1844*82527734SSukumar Swaminathan 	 * This determines how many node objects we preallocate in the pool
1845*82527734SSukumar Swaminathan 	 * The actual max_nodes will be set later based on adapter info
1846*82527734SSukumar Swaminathan 	 */
1847*82527734SSukumar Swaminathan 	if (hba->max_nodes == 0) {
1848*82527734SSukumar Swaminathan 		if (cfg[CFG_NUM_NODES].current > 0) {
1849*82527734SSukumar Swaminathan 			hba->max_nodes = cfg[CFG_NUM_NODES].current;
1850*82527734SSukumar Swaminathan 		} else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
1851*82527734SSukumar Swaminathan 			hba->max_nodes = 4096;
1852*82527734SSukumar Swaminathan 		} else {
1853*82527734SSukumar Swaminathan 			hba->max_nodes = 512;
1854*82527734SSukumar Swaminathan 		}
1855*82527734SSukumar Swaminathan 	}
1856291a2b48SSukumar Swaminathan 
1857*82527734SSukumar Swaminathan 	return (0);
1858291a2b48SSukumar Swaminathan 
1859*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_init() */
1860291a2b48SSukumar Swaminathan 
1861291a2b48SSukumar Swaminathan 
1862*82527734SSukumar Swaminathan /*
1863*82527734SSukumar Swaminathan  * 0: quiesce indicates the call is not from quiesce routine.
1864*82527734SSukumar Swaminathan  * 1: quiesce indicates the call is from quiesce routine.
1865*82527734SSukumar Swaminathan  */
1866*82527734SSukumar Swaminathan static uint32_t
1867*82527734SSukumar Swaminathan emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
1868*82527734SSukumar Swaminathan 	uint32_t quiesce)
1869291a2b48SSukumar Swaminathan {
1870*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1871*82527734SSukumar Swaminathan 	MAILBOX *swpmb;
1872*82527734SSukumar Swaminathan 	MAILBOX *mb;
1873*82527734SSukumar Swaminathan 	uint32_t word0;
1874*82527734SSukumar Swaminathan 	uint16_t cfg_value;
1875*82527734SSukumar Swaminathan 	uint32_t status;
1876*82527734SSukumar Swaminathan 	uint32_t status1;
1877*82527734SSukumar Swaminathan 	uint32_t status2;
1878*82527734SSukumar Swaminathan 	uint32_t i;
1879*82527734SSukumar Swaminathan 	uint32_t ready;
1880*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
1881*82527734SSukumar Swaminathan 	RING *rp;
1882*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
1883291a2b48SSukumar Swaminathan 
1884*82527734SSukumar Swaminathan 	i = 0;
1885291a2b48SSukumar Swaminathan 
1886*82527734SSukumar Swaminathan 	if (!cfg[CFG_RESET_ENABLE].current) {
1887*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1888*82527734SSukumar Swaminathan 		    "Adapter reset disabled.");
1889*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
1890291a2b48SSukumar Swaminathan 
1891*82527734SSukumar Swaminathan 		return (1);
1892291a2b48SSukumar Swaminathan 	}
1893291a2b48SSukumar Swaminathan 
1894*82527734SSukumar Swaminathan 	/* Kill the adapter first */
1895*82527734SSukumar Swaminathan 	if (quiesce == 0) {
1896*82527734SSukumar Swaminathan 		emlxs_sli3_hba_kill(hba);
1897*82527734SSukumar Swaminathan 	} else {
1898*82527734SSukumar Swaminathan 		emlxs_sli3_hba_kill4quiesce(hba);
1899291a2b48SSukumar Swaminathan 	}
1900291a2b48SSukumar Swaminathan 
1901*82527734SSukumar Swaminathan 	if (restart) {
1902*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1903*82527734SSukumar Swaminathan 		    "Restarting.");
1904*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_INIT_START);
1905291a2b48SSukumar Swaminathan 
1906*82527734SSukumar Swaminathan 		ready = (HS_FFRDY | HS_MBRDY);
1907*82527734SSukumar Swaminathan 	} else {
1908*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1909*82527734SSukumar Swaminathan 		    "Resetting.");
1910*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_WARM_START);
1911291a2b48SSukumar Swaminathan 
1912*82527734SSukumar Swaminathan 		ready = HS_MBRDY;
1913291a2b48SSukumar Swaminathan 	}
1914291a2b48SSukumar Swaminathan 
1915*82527734SSukumar Swaminathan 	hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR);
1916291a2b48SSukumar Swaminathan 
1917*82527734SSukumar Swaminathan 	mb = FC_SLIM1_MAILBOX(hba);
1918*82527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
1919291a2b48SSukumar Swaminathan 
1920*82527734SSukumar Swaminathan reset:
1921291a2b48SSukumar Swaminathan 
1922*82527734SSukumar Swaminathan 	/* Save reset time */
1923*82527734SSukumar Swaminathan 	HBASTATS.ResetTime = hba->timer_tics;
1924291a2b48SSukumar Swaminathan 
1925*82527734SSukumar Swaminathan 	if (restart) {
1926*82527734SSukumar Swaminathan 		/* First put restart command in mailbox */
1927*82527734SSukumar Swaminathan 		word0 = 0;
1928*82527734SSukumar Swaminathan 		swpmb->mbxCommand = MBX_RESTART;
1929*82527734SSukumar Swaminathan 		swpmb->mbxHc = 1;
1930*82527734SSukumar Swaminathan 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0);
1931*82527734SSukumar Swaminathan 
1932*82527734SSukumar Swaminathan 		/* Only skip post after emlxs_sli3_online is completed */
1933*82527734SSukumar Swaminathan 		if (skip_post) {
1934*82527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
1935*82527734SSukumar Swaminathan 			    1);
1936*82527734SSukumar Swaminathan 		} else {
1937*82527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
1938*82527734SSukumar Swaminathan 			    0);
1939291a2b48SSukumar Swaminathan 		}
1940291a2b48SSukumar Swaminathan 
1941*82527734SSukumar Swaminathan 	}
1942291a2b48SSukumar Swaminathan 
1943*82527734SSukumar Swaminathan 	/*
1944*82527734SSukumar Swaminathan 	 * Turn off SERR, PERR in PCI cmd register
1945*82527734SSukumar Swaminathan 	 */
1946*82527734SSukumar Swaminathan 	cfg_value = ddi_get16(hba->pci_acc_handle,
1947*82527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER));
1948291a2b48SSukumar Swaminathan 
1949*82527734SSukumar Swaminathan 	ddi_put16(hba->pci_acc_handle,
1950*82527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
1951*82527734SSukumar Swaminathan 	    (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL)));
1952291a2b48SSukumar Swaminathan 
1953*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = HC_INITFF;
1954*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
1955291a2b48SSukumar Swaminathan 
1956*82527734SSukumar Swaminathan 	/* Wait 1 msec before restoring PCI config */
1957*82527734SSukumar Swaminathan 	DELAYMS(1);
1958291a2b48SSukumar Swaminathan 
1959*82527734SSukumar Swaminathan 	/* Restore PCI cmd register */
1960*82527734SSukumar Swaminathan 	ddi_put16(hba->pci_acc_handle,
1961*82527734SSukumar Swaminathan 	    (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
1962*82527734SSukumar Swaminathan 	    (uint16_t)cfg_value);
1963291a2b48SSukumar Swaminathan 
1964*82527734SSukumar Swaminathan 	/* Wait 3 seconds before checking */
1965*82527734SSukumar Swaminathan 	DELAYMS(3000);
1966*82527734SSukumar Swaminathan 	i += 3;
1967291a2b48SSukumar Swaminathan 
1968*82527734SSukumar Swaminathan 	/* Wait for reset completion */
1969*82527734SSukumar Swaminathan 	while (i < 30) {
1970*82527734SSukumar Swaminathan 		/* Check status register to see what current state is */
1971*82527734SSukumar Swaminathan 		status = READ_CSR_REG(hba, FC_HS_REG(hba));
1972291a2b48SSukumar Swaminathan 
1973*82527734SSukumar Swaminathan 		/* Check to see if any errors occurred during init */
1974*82527734SSukumar Swaminathan 		if (status & HS_FFERM) {
1975*82527734SSukumar Swaminathan 			status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
1976*82527734SSukumar Swaminathan 			    hba->sli.sli3.slim_addr + 0xa8));
1977*82527734SSukumar Swaminathan 			status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
1978*82527734SSukumar Swaminathan 			    hba->sli.sli3.slim_addr + 0xac));
1979291a2b48SSukumar Swaminathan 
1980*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1981*82527734SSukumar Swaminathan 			    "HS_FFERM: status=0x%x status1=0x%x status2=0x%x",
1982*82527734SSukumar Swaminathan 			    status, status1, status2);
1983291a2b48SSukumar Swaminathan 
1984*82527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE(hba, FC_ERROR);
1985*82527734SSukumar Swaminathan 			return (1);
1986291a2b48SSukumar Swaminathan 		}
1987291a2b48SSukumar Swaminathan 
1988*82527734SSukumar Swaminathan 		if ((status & ready) == ready) {
1989*82527734SSukumar Swaminathan 			/* Reset Done !! */
1990*82527734SSukumar Swaminathan 			goto done;
1991*82527734SSukumar Swaminathan 		}
1992291a2b48SSukumar Swaminathan 
1993*82527734SSukumar Swaminathan 		/*
1994*82527734SSukumar Swaminathan 		 * Check every 1 second for 15 seconds, then reset board
1995*82527734SSukumar Swaminathan 		 * again (w/post), then check every 1 second for 15 * seconds.
1996*82527734SSukumar Swaminathan 		 */
1997*82527734SSukumar Swaminathan 		DELAYMS(1000);
1998*82527734SSukumar Swaminathan 		i++;
1999291a2b48SSukumar Swaminathan 
2000*82527734SSukumar Swaminathan 		/* Reset again (w/post) at 15 seconds */
2001*82527734SSukumar Swaminathan 		if (i == 15) {
2002*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2003*82527734SSukumar Swaminathan 			    "Reset failed. Retrying...");
2004291a2b48SSukumar Swaminathan 
2005*82527734SSukumar Swaminathan 			goto reset;
2006291a2b48SSukumar Swaminathan 		}
2007291a2b48SSukumar Swaminathan 	}
2008291a2b48SSukumar Swaminathan 
2009*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
2010*82527734SSukumar Swaminathan reset_fail:
2011*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
2012291a2b48SSukumar Swaminathan 
2013*82527734SSukumar Swaminathan 	/* Timeout occurred */
2014*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2015*82527734SSukumar Swaminathan 	    "Timeout: status=0x%x", status);
2016*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_ERROR);
2017291a2b48SSukumar Swaminathan 
2018*82527734SSukumar Swaminathan 	/* Log a dump event */
2019*82527734SSukumar Swaminathan 	emlxs_log_dump_event(port, NULL, 0);
2020291a2b48SSukumar Swaminathan 
2021*82527734SSukumar Swaminathan 	return (1);
2022291a2b48SSukumar Swaminathan 
2023*82527734SSukumar Swaminathan done:
2024291a2b48SSukumar Swaminathan 
2025*82527734SSukumar Swaminathan 	/* Initialize hc_copy */
2026*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba));
2027291a2b48SSukumar Swaminathan 
20284baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
20294baa2c25SSukumar Swaminathan 	/* Access handle validation */
2030*82527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
20314baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) ||
2032*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2033*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
2034*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
20354baa2c25SSukumar Swaminathan 	    != DDI_FM_OK)) {
20364baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
20374baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
2038*82527734SSukumar Swaminathan 		goto reset_fail;
20394baa2c25SSukumar Swaminathan 	}
20404baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
20414baa2c25SSukumar Swaminathan 
2042*82527734SSukumar Swaminathan 	/* Reset the hba structure */
2043*82527734SSukumar Swaminathan 	hba->flag &= FC_RESET_MASK;
2044*82527734SSukumar Swaminathan 	hba->channel_tx_count = 0;
2045*82527734SSukumar Swaminathan 	hba->io_count = 0;
2046*82527734SSukumar Swaminathan 	hba->iodone_count = 0;
2047*82527734SSukumar Swaminathan 	hba->topology = 0;
2048*82527734SSukumar Swaminathan 	hba->linkspeed = 0;
2049*82527734SSukumar Swaminathan 	hba->heartbeat_active = 0;
2050*82527734SSukumar Swaminathan 	hba->discovery_timer = 0;
2051*82527734SSukumar Swaminathan 	hba->linkup_timer = 0;
2052*82527734SSukumar Swaminathan 	hba->loopback_tics = 0;
2053291a2b48SSukumar Swaminathan 
2054291a2b48SSukumar Swaminathan 
2055*82527734SSukumar Swaminathan 	/* Reset the ring objects */
2056*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_RINGS; i++) {
2057*82527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
2058*82527734SSukumar Swaminathan 		rp->fc_mpon = 0;
2059*82527734SSukumar Swaminathan 		rp->fc_mpoff = 0;
2060*82527734SSukumar Swaminathan 	}
2061291a2b48SSukumar Swaminathan 
2062*82527734SSukumar Swaminathan 	/* Reset the port objects */
2063*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
2064*82527734SSukumar Swaminathan 		vport = &VPORT(i);
2065291a2b48SSukumar Swaminathan 
2066*82527734SSukumar Swaminathan 		vport->flag &= EMLXS_PORT_RESET_MASK;
2067*82527734SSukumar Swaminathan 		vport->did = 0;
2068*82527734SSukumar Swaminathan 		vport->prev_did = 0;
2069*82527734SSukumar Swaminathan 		vport->lip_type = 0;
2070*82527734SSukumar Swaminathan 		bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2071*82527734SSukumar Swaminathan 
2072*82527734SSukumar Swaminathan 		bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
2073*82527734SSukumar Swaminathan 		vport->node_base.nlp_Rpi = 0;
2074*82527734SSukumar Swaminathan 		vport->node_base.nlp_DID = 0xffffff;
2075*82527734SSukumar Swaminathan 		vport->node_base.nlp_list_next = NULL;
2076*82527734SSukumar Swaminathan 		vport->node_base.nlp_list_prev = NULL;
2077*82527734SSukumar Swaminathan 		vport->node_base.nlp_active = 1;
2078*82527734SSukumar Swaminathan 		vport->node_count = 0;
2079*82527734SSukumar Swaminathan 
2080*82527734SSukumar Swaminathan 		if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
2081*82527734SSukumar Swaminathan 			vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
2082291a2b48SSukumar Swaminathan 		}
2083*82527734SSukumar Swaminathan 	}
2084291a2b48SSukumar Swaminathan 
2085*82527734SSukumar Swaminathan 	return (0);
2086291a2b48SSukumar Swaminathan 
2087*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_reset */
2088291a2b48SSukumar Swaminathan 
2089291a2b48SSukumar Swaminathan 
2090*82527734SSukumar Swaminathan #define	BPL_CMD		0
2091*82527734SSukumar Swaminathan #define	BPL_RESP	1
2092*82527734SSukumar Swaminathan #define	BPL_DATA	2
2093291a2b48SSukumar Swaminathan 
2094*82527734SSukumar Swaminathan static ULP_BDE64 *
2095*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(ULP_BDE64 *bpl, fc_packet_t *pkt, uint32_t bpl_type,
2096*82527734SSukumar Swaminathan     uint8_t bdeFlags)
2097*82527734SSukumar Swaminathan {
2098*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp;
2099*82527734SSukumar Swaminathan 	uint_t	i;
2100*82527734SSukumar Swaminathan 	int32_t	size;
2101*82527734SSukumar Swaminathan 	uint_t	cookie_cnt;
2102291a2b48SSukumar Swaminathan 
2103*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
2104*82527734SSukumar Swaminathan 	switch (bpl_type) {
2105*82527734SSukumar Swaminathan 	case BPL_CMD:
2106*82527734SSukumar Swaminathan 		cp = pkt->pkt_cmd_cookie;
2107*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_cmd_cookie_cnt;
2108*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
2109*82527734SSukumar Swaminathan 		break;
2110291a2b48SSukumar Swaminathan 
2111*82527734SSukumar Swaminathan 	case BPL_RESP:
2112*82527734SSukumar Swaminathan 		cp = pkt->pkt_resp_cookie;
2113*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_resp_cookie_cnt;
2114*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
2115*82527734SSukumar Swaminathan 		break;
2116291a2b48SSukumar Swaminathan 
2117291a2b48SSukumar Swaminathan 
2118*82527734SSukumar Swaminathan 	case BPL_DATA:
2119*82527734SSukumar Swaminathan 		cp = pkt->pkt_data_cookie;
2120*82527734SSukumar Swaminathan 		cookie_cnt = pkt->pkt_data_cookie_cnt;
2121*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
2122*82527734SSukumar Swaminathan 		break;
2123*82527734SSukumar Swaminathan 	}
2124291a2b48SSukumar Swaminathan 
2125*82527734SSukumar Swaminathan #else
2126*82527734SSukumar Swaminathan 	switch (bpl_type) {
2127*82527734SSukumar Swaminathan 	case BPL_CMD:
2128*82527734SSukumar Swaminathan 		cp = &pkt->pkt_cmd_cookie;
2129*82527734SSukumar Swaminathan 		cookie_cnt = 1;
2130*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_cmdlen;
2131*82527734SSukumar Swaminathan 		break;
2132291a2b48SSukumar Swaminathan 
2133*82527734SSukumar Swaminathan 	case BPL_RESP:
2134*82527734SSukumar Swaminathan 		cp = &pkt->pkt_resp_cookie;
2135*82527734SSukumar Swaminathan 		cookie_cnt = 1;
2136*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_rsplen;
2137*82527734SSukumar Swaminathan 		break;
2138291a2b48SSukumar Swaminathan 
2139291a2b48SSukumar Swaminathan 
2140*82527734SSukumar Swaminathan 	case BPL_DATA:
2141*82527734SSukumar Swaminathan 		cp = &pkt->pkt_data_cookie;
2142*82527734SSukumar Swaminathan 		cookie_cnt = 1;
2143*82527734SSukumar Swaminathan 		size = (int32_t)pkt->pkt_datalen;
2144*82527734SSukumar Swaminathan 		break;
2145*82527734SSukumar Swaminathan 	}
2146*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2147291a2b48SSukumar Swaminathan 
2148*82527734SSukumar Swaminathan 	for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
2149*82527734SSukumar Swaminathan 		bpl->addrHigh =
2150*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_HI(cp->dmac_laddress));
2151*82527734SSukumar Swaminathan 		bpl->addrLow =
2152*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_LO(cp->dmac_laddress));
2153*82527734SSukumar Swaminathan 		bpl->tus.f.bdeSize = MIN(size, cp->dmac_size);
2154*82527734SSukumar Swaminathan 		bpl->tus.f.bdeFlags = bdeFlags;
2155*82527734SSukumar Swaminathan 		bpl->tus.w = BE_SWAP32(bpl->tus.w);
2156291a2b48SSukumar Swaminathan 
2157*82527734SSukumar Swaminathan 		bpl++;
2158*82527734SSukumar Swaminathan 		size -= cp->dmac_size;
2159*82527734SSukumar Swaminathan 	}
2160291a2b48SSukumar Swaminathan 
2161*82527734SSukumar Swaminathan 	return (bpl);
2162291a2b48SSukumar Swaminathan 
2163*82527734SSukumar Swaminathan } /* emlxs_pkt_to_bpl */
2164291a2b48SSukumar Swaminathan 
2165291a2b48SSukumar Swaminathan 
2166*82527734SSukumar Swaminathan static uint32_t
2167*82527734SSukumar Swaminathan emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2168*82527734SSukumar Swaminathan {
2169*82527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
2170*82527734SSukumar Swaminathan 	fc_packet_t	*pkt;
2171*82527734SSukumar Swaminathan 	MATCHMAP	*bmp;
2172*82527734SSukumar Swaminathan 	ULP_BDE64	*bpl;
2173*82527734SSukumar Swaminathan 	uint64_t	bp;
2174*82527734SSukumar Swaminathan 	uint8_t		bdeFlag;
2175*82527734SSukumar Swaminathan 	IOCB		*iocb;
2176*82527734SSukumar Swaminathan 	IOCBQ		*iocbq;
2177*82527734SSukumar Swaminathan 	CHANNEL	*cp;
2178*82527734SSukumar Swaminathan 	uint32_t	cmd_cookie_cnt;
2179*82527734SSukumar Swaminathan 	uint32_t	resp_cookie_cnt;
2180*82527734SSukumar Swaminathan 	uint32_t	data_cookie_cnt;
2181*82527734SSukumar Swaminathan 	uint32_t	cookie_cnt;
2182291a2b48SSukumar Swaminathan 
2183*82527734SSukumar Swaminathan 	cp = sbp->channel;
2184*82527734SSukumar Swaminathan 	iocb = (IOCB *) & sbp->iocbq;
2185*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2186291a2b48SSukumar Swaminathan 
2187*82527734SSukumar Swaminathan #ifdef EMLXS_SPARC
2188*82527734SSukumar Swaminathan 	/* Use FCP MEM_BPL table to get BPL buffer */
2189*82527734SSukumar Swaminathan 	bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag];
2190*82527734SSukumar Swaminathan #else
2191*82527734SSukumar Swaminathan 	/* Use MEM_BPL pool to get BPL buffer */
2192*82527734SSukumar Swaminathan 	bmp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL, 0);
2193291a2b48SSukumar Swaminathan 
2194*82527734SSukumar Swaminathan #endif
2195291a2b48SSukumar Swaminathan 
2196*82527734SSukumar Swaminathan 	if (!bmp) {
2197*82527734SSukumar Swaminathan 		return (1);
2198*82527734SSukumar Swaminathan 	}
2199291a2b48SSukumar Swaminathan 
2200*82527734SSukumar Swaminathan 	sbp->bmp = bmp;
2201*82527734SSukumar Swaminathan 	bpl = (ULP_BDE64 *)bmp->virt;
2202*82527734SSukumar Swaminathan 	bp = bmp->phys;
2203*82527734SSukumar Swaminathan 	cookie_cnt = 0;
2204291a2b48SSukumar Swaminathan 
2205*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
2206*82527734SSukumar Swaminathan 	cmd_cookie_cnt  = pkt->pkt_cmd_cookie_cnt;
2207*82527734SSukumar Swaminathan 	resp_cookie_cnt = pkt->pkt_resp_cookie_cnt;
2208*82527734SSukumar Swaminathan 	data_cookie_cnt = pkt->pkt_data_cookie_cnt;
2209*82527734SSukumar Swaminathan #else
2210*82527734SSukumar Swaminathan 	cmd_cookie_cnt  = 1;
2211*82527734SSukumar Swaminathan 	resp_cookie_cnt = 1;
2212*82527734SSukumar Swaminathan 	data_cookie_cnt = 1;
2213*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2214291a2b48SSukumar Swaminathan 
2215*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
2216*82527734SSukumar Swaminathan 	if (iocbq->flag & IOCB_FCP_CMD)
2217*82527734SSukumar Swaminathan 		goto fcpcmd;
2218*82527734SSukumar Swaminathan 
2219*82527734SSukumar Swaminathan 	switch (cp->channelno) {
2220*82527734SSukumar Swaminathan 	case FC_FCP_RING:
2221*82527734SSukumar Swaminathan fcpcmd:
2222*82527734SSukumar Swaminathan 		/* CMD payload */
2223*82527734SSukumar Swaminathan 		bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0);
2224*82527734SSukumar Swaminathan 		cookie_cnt = cmd_cookie_cnt;
2225*82527734SSukumar Swaminathan 
2226*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) {
2227*82527734SSukumar Swaminathan 			/* RSP payload */
2228*82527734SSukumar Swaminathan 			bpl =
2229*82527734SSukumar Swaminathan 			    emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP,
2230*82527734SSukumar Swaminathan 			    BUFF_USE_RCV);
2231*82527734SSukumar Swaminathan 			cookie_cnt += resp_cookie_cnt;
2232*82527734SSukumar Swaminathan 
2233*82527734SSukumar Swaminathan 			/* DATA payload */
2234*82527734SSukumar Swaminathan 			if (pkt->pkt_datalen != 0) {
2235*82527734SSukumar Swaminathan 				bdeFlag =
2236*82527734SSukumar Swaminathan 				    (pkt->pkt_tran_type ==
2237*82527734SSukumar Swaminathan 				    FC_PKT_FCP_READ) ? BUFF_USE_RCV : 0;
2238*82527734SSukumar Swaminathan 				bpl =
2239*82527734SSukumar Swaminathan 				    emlxs_pkt_to_bpl(bpl, pkt, BPL_DATA,
2240*82527734SSukumar Swaminathan 				    bdeFlag);
2241*82527734SSukumar Swaminathan 				cookie_cnt += data_cookie_cnt;
2242*82527734SSukumar Swaminathan 			}
2243291a2b48SSukumar Swaminathan 		}
2244*82527734SSukumar Swaminathan 		/*
2245*82527734SSukumar Swaminathan 		 * else
2246*82527734SSukumar Swaminathan 		 * {
2247*82527734SSukumar Swaminathan 		 * 	Target mode FCP status. Do nothing more.
2248*82527734SSukumar Swaminathan 		 * }
2249*82527734SSukumar Swaminathan 		 */
2250291a2b48SSukumar Swaminathan 
2251*82527734SSukumar Swaminathan 		break;
2252291a2b48SSukumar Swaminathan 
2253*82527734SSukumar Swaminathan 	case FC_IP_RING:
2254*82527734SSukumar Swaminathan 
2255*82527734SSukumar Swaminathan 		/* CMD payload */
2256*82527734SSukumar Swaminathan 		bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0);
2257*82527734SSukumar Swaminathan 		cookie_cnt = cmd_cookie_cnt;
2258291a2b48SSukumar Swaminathan 
2259291a2b48SSukumar Swaminathan 		break;
2260291a2b48SSukumar Swaminathan 
2261*82527734SSukumar Swaminathan 	case FC_ELS_RING:
2262291a2b48SSukumar Swaminathan 
2263*82527734SSukumar Swaminathan 		/* CMD payload */
2264*82527734SSukumar Swaminathan 		bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0);
2265*82527734SSukumar Swaminathan 		cookie_cnt = cmd_cookie_cnt;
2266291a2b48SSukumar Swaminathan 
2267*82527734SSukumar Swaminathan 		/* RSP payload */
2268*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) {
2269*82527734SSukumar Swaminathan 			bpl =
2270*82527734SSukumar Swaminathan 			    emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP,
2271*82527734SSukumar Swaminathan 			    BUFF_USE_RCV);
2272*82527734SSukumar Swaminathan 			cookie_cnt += resp_cookie_cnt;
2273*82527734SSukumar Swaminathan 		}
2274291a2b48SSukumar Swaminathan 
2275*82527734SSukumar Swaminathan 		break;
2276291a2b48SSukumar Swaminathan 
2277291a2b48SSukumar Swaminathan 
2278*82527734SSukumar Swaminathan 	case FC_CT_RING:
2279291a2b48SSukumar Swaminathan 
2280*82527734SSukumar Swaminathan 		/* CMD payload */
2281*82527734SSukumar Swaminathan 		bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0);
2282*82527734SSukumar Swaminathan 		cookie_cnt = cmd_cookie_cnt;
2283291a2b48SSukumar Swaminathan 
2284*82527734SSukumar Swaminathan 		if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) ||
2285*82527734SSukumar Swaminathan 		    (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) {
2286*82527734SSukumar Swaminathan 			/* RSP payload */
2287*82527734SSukumar Swaminathan 			bpl =
2288*82527734SSukumar Swaminathan 			    emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP,
2289*82527734SSukumar Swaminathan 			    BUFF_USE_RCV);
2290*82527734SSukumar Swaminathan 			cookie_cnt += resp_cookie_cnt;
2291*82527734SSukumar Swaminathan 		}
2292291a2b48SSukumar Swaminathan 
2293*82527734SSukumar Swaminathan 		break;
2294291a2b48SSukumar Swaminathan 
2295291a2b48SSukumar Swaminathan 	}
2296291a2b48SSukumar Swaminathan 
2297*82527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
2298*82527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp);
2299*82527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.addrLow  = PADDR_LO(bp);
2300*82527734SSukumar Swaminathan 	iocb->un.genreq64.bdl.bdeSize  = cookie_cnt * sizeof (ULP_BDE64);
2301291a2b48SSukumar Swaminathan 
2302*82527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 1;
2303*82527734SSukumar Swaminathan 	iocb->ULPLE = 1;
2304291a2b48SSukumar Swaminathan 
2305*82527734SSukumar Swaminathan 	return (0);
2306291a2b48SSukumar Swaminathan 
2307*82527734SSukumar Swaminathan } /* emlxs_sli2_bde_setup */
2308291a2b48SSukumar Swaminathan 
2309291a2b48SSukumar Swaminathan 
2310*82527734SSukumar Swaminathan static uint32_t
2311*82527734SSukumar Swaminathan emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2312*82527734SSukumar Swaminathan {
2313*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_cmd;
2314*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_resp;
2315*82527734SSukumar Swaminathan 	ddi_dma_cookie_t *cp_data;
2316*82527734SSukumar Swaminathan 	fc_packet_t	*pkt;
2317*82527734SSukumar Swaminathan 	ULP_BDE64	*bde;
2318*82527734SSukumar Swaminathan 	int		data_cookie_cnt;
2319*82527734SSukumar Swaminathan 	uint32_t	i;
2320*82527734SSukumar Swaminathan 	IOCB		*iocb;
2321*82527734SSukumar Swaminathan 	IOCBQ		*iocbq;
2322*82527734SSukumar Swaminathan 	CHANNEL		*cp;
2323291a2b48SSukumar Swaminathan 
2324*82527734SSukumar Swaminathan 	cp = sbp->channel;
2325*82527734SSukumar Swaminathan 	iocb = (IOCB *) & sbp->iocbq;
2326*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
2327*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
2328*82527734SSukumar Swaminathan 	if ((pkt->pkt_cmd_cookie_cnt > 1) ||
2329*82527734SSukumar Swaminathan 	    (pkt->pkt_resp_cookie_cnt > 1) ||
2330*82527734SSukumar Swaminathan 	    ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt +
2331*82527734SSukumar Swaminathan 	    pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) {
2332*82527734SSukumar Swaminathan 		i = emlxs_sli2_bde_setup(port, sbp);
2333*82527734SSukumar Swaminathan 		return (i);
2334*82527734SSukumar Swaminathan 	}
2335291a2b48SSukumar Swaminathan 
2336*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2337291a2b48SSukumar Swaminathan 
2338*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3)
2339*82527734SSukumar Swaminathan 	cp_cmd = pkt->pkt_cmd_cookie;
2340*82527734SSukumar Swaminathan 	cp_resp = pkt->pkt_resp_cookie;
2341*82527734SSukumar Swaminathan 	cp_data = pkt->pkt_data_cookie;
2342*82527734SSukumar Swaminathan 	data_cookie_cnt = pkt->pkt_data_cookie_cnt;
2343*82527734SSukumar Swaminathan #else
2344*82527734SSukumar Swaminathan 	cp_cmd  = &pkt->pkt_cmd_cookie;
2345*82527734SSukumar Swaminathan 	cp_resp = &pkt->pkt_resp_cookie;
2346*82527734SSukumar Swaminathan 	cp_data = &pkt->pkt_data_cookie;
2347*82527734SSukumar Swaminathan 	data_cookie_cnt = 1;
2348*82527734SSukumar Swaminathan #endif	/* >= EMLXS_MODREV3 */
2349291a2b48SSukumar Swaminathan 
2350*82527734SSukumar Swaminathan 	iocb->unsli3.ext_iocb.ebde_count = 0;
2351291a2b48SSukumar Swaminathan 
2352*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
2353*82527734SSukumar Swaminathan 	if (iocbq->flag & IOCB_FCP_CMD)
2354*82527734SSukumar Swaminathan 		goto fcpcmd;
2355291a2b48SSukumar Swaminathan 
2356*82527734SSukumar Swaminathan 	switch (cp->channelno) {
2357*82527734SSukumar Swaminathan 	case FC_FCP_RING:
2358*82527734SSukumar Swaminathan fcpcmd:
2359*82527734SSukumar Swaminathan 		/* CMD payload */
2360*82527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.addrHigh =
2361*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
2362*82527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.addrLow =
2363*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
2364*82527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.bdeSize  = pkt->pkt_cmdlen;
2365*82527734SSukumar Swaminathan 		iocb->un.fcpi64.bdl.bdeFlags = 0;
2366291a2b48SSukumar Swaminathan 
2367*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) {
2368*82527734SSukumar Swaminathan 			/* RSP payload */
2369*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrHigh =
2370*82527734SSukumar Swaminathan 			    PADDR_HI(cp_resp->dmac_laddress);
2371*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrLow =
2372*82527734SSukumar Swaminathan 			    PADDR_LO(cp_resp->dmac_laddress);
2373*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize =
2374*82527734SSukumar Swaminathan 			    pkt->pkt_rsplen;
2375*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0;
2376*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde_count = 1;
2377291a2b48SSukumar Swaminathan 
2378*82527734SSukumar Swaminathan 			/* DATA payload */
2379*82527734SSukumar Swaminathan 			if (pkt->pkt_datalen != 0) {
2380*82527734SSukumar Swaminathan 				bde =
2381*82527734SSukumar Swaminathan 				    (ULP_BDE64 *)&iocb->unsli3.ext_iocb.
2382*82527734SSukumar Swaminathan 				    ebde2;
2383*82527734SSukumar Swaminathan 				for (i = 0; i < data_cookie_cnt; i++) {
2384*82527734SSukumar Swaminathan 					bde->addrHigh =
2385*82527734SSukumar Swaminathan 					    PADDR_HI(cp_data->
2386*82527734SSukumar Swaminathan 					    dmac_laddress);
2387*82527734SSukumar Swaminathan 					bde->addrLow =
2388*82527734SSukumar Swaminathan 					    PADDR_LO(cp_data->
2389*82527734SSukumar Swaminathan 					    dmac_laddress);
2390*82527734SSukumar Swaminathan 					bde->tus.f.bdeSize =
2391*82527734SSukumar Swaminathan 					    cp_data->dmac_size;
2392*82527734SSukumar Swaminathan 					bde->tus.f.bdeFlags = 0;
2393*82527734SSukumar Swaminathan 					cp_data++;
2394*82527734SSukumar Swaminathan 					bde++;
2395*82527734SSukumar Swaminathan 				}
2396*82527734SSukumar Swaminathan 				iocb->unsli3.ext_iocb.ebde_count +=
2397*82527734SSukumar Swaminathan 				    data_cookie_cnt;
2398*82527734SSukumar Swaminathan 			}
2399*82527734SSukumar Swaminathan 		}
2400*82527734SSukumar Swaminathan 		/*
2401*82527734SSukumar Swaminathan 		 * else
2402*82527734SSukumar Swaminathan 		 * {
2403*82527734SSukumar Swaminathan 		 * 	Target mode FCP status. Do nothing more.
2404*82527734SSukumar Swaminathan 		 * }
2405*82527734SSukumar Swaminathan 		 */
2406291a2b48SSukumar Swaminathan 
2407*82527734SSukumar Swaminathan 		break;
2408291a2b48SSukumar Swaminathan 
2409*82527734SSukumar Swaminathan 	case FC_IP_RING:
2410291a2b48SSukumar Swaminathan 
2411*82527734SSukumar Swaminathan 		/* CMD payload */
2412*82527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.addrHigh =
2413*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
2414*82527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.addrLow =
2415*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
2416*82527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2417*82527734SSukumar Swaminathan 		iocb->un.xseq64.bdl.bdeFlags = 0;
2418291a2b48SSukumar Swaminathan 
2419*82527734SSukumar Swaminathan 		break;
2420291a2b48SSukumar Swaminathan 
2421*82527734SSukumar Swaminathan 	case FC_ELS_RING:
2422291a2b48SSukumar Swaminathan 
2423*82527734SSukumar Swaminathan 		/* CMD payload */
2424*82527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.addrHigh =
2425*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
2426*82527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.addrLow =
2427*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
2428*82527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2429*82527734SSukumar Swaminathan 		iocb->un.elsreq64.bdl.bdeFlags = 0;
2430291a2b48SSukumar Swaminathan 
2431*82527734SSukumar Swaminathan 		/* RSP payload */
2432*82527734SSukumar Swaminathan 		if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) {
2433*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrHigh =
2434*82527734SSukumar Swaminathan 			    PADDR_HI(cp_resp->dmac_laddress);
2435*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrLow =
2436*82527734SSukumar Swaminathan 			    PADDR_LO(cp_resp->dmac_laddress);
2437*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize =
2438*82527734SSukumar Swaminathan 			    pkt->pkt_rsplen;
2439*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags =
2440*82527734SSukumar Swaminathan 			    BUFF_USE_RCV;
2441*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde_count = 1;
2442*82527734SSukumar Swaminathan 		}
2443291a2b48SSukumar Swaminathan 
2444*82527734SSukumar Swaminathan 		break;
2445291a2b48SSukumar Swaminathan 
2446*82527734SSukumar Swaminathan 	case FC_CT_RING:
2447291a2b48SSukumar Swaminathan 
2448*82527734SSukumar Swaminathan 		/* CMD payload */
2449*82527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.addrHigh =
2450*82527734SSukumar Swaminathan 		    PADDR_HI(cp_cmd->dmac_laddress);
2451*82527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.addrLow =
2452*82527734SSukumar Swaminathan 		    PADDR_LO(cp_cmd->dmac_laddress);
2453*82527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2454*82527734SSukumar Swaminathan 		iocb->un.genreq64.bdl.bdeFlags = 0;
2455291a2b48SSukumar Swaminathan 
2456*82527734SSukumar Swaminathan 		if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) ||
2457*82527734SSukumar Swaminathan 		    (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) {
2458*82527734SSukumar Swaminathan 			/* RSP payload */
2459*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrHigh =
2460*82527734SSukumar Swaminathan 			    PADDR_HI(cp_resp->dmac_laddress);
2461*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.addrLow =
2462*82527734SSukumar Swaminathan 			    PADDR_LO(cp_resp->dmac_laddress);
2463*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize =
2464*82527734SSukumar Swaminathan 			    pkt->pkt_rsplen;
2465*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags =
2466*82527734SSukumar Swaminathan 			    BUFF_USE_RCV;
2467*82527734SSukumar Swaminathan 			iocb->unsli3.ext_iocb.ebde_count = 1;
2468*82527734SSukumar Swaminathan 		}
2469291a2b48SSukumar Swaminathan 
2470*82527734SSukumar Swaminathan 		break;
2471291a2b48SSukumar Swaminathan 	}
2472291a2b48SSukumar Swaminathan 
2473*82527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 0;
2474*82527734SSukumar Swaminathan 	iocb->ULPLE = 0;
2475291a2b48SSukumar Swaminathan 
2476*82527734SSukumar Swaminathan 	return (0);
2477291a2b48SSukumar Swaminathan 
2478*82527734SSukumar Swaminathan } /* emlxs_sli3_bde_setup */
2479291a2b48SSukumar Swaminathan 
2480291a2b48SSukumar Swaminathan 
2481*82527734SSukumar Swaminathan /* Only used for FCP Data xfers */
2482*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
2483*82527734SSukumar Swaminathan /*ARGSUSED*/
2484*82527734SSukumar Swaminathan static uint32_t
2485*82527734SSukumar Swaminathan emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2486*82527734SSukumar Swaminathan {
2487*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
2488*82527734SSukumar Swaminathan 	scsi_task_t *fct_task;
2489*82527734SSukumar Swaminathan 	MATCHMAP *bmp;
2490*82527734SSukumar Swaminathan 	ULP_BDE64 *bpl;
2491*82527734SSukumar Swaminathan 	uint64_t bp;
2492*82527734SSukumar Swaminathan 	uint8_t bdeFlags;
2493*82527734SSukumar Swaminathan 	IOCB *iocb;
2494*82527734SSukumar Swaminathan 	uint32_t resid;
2495*82527734SSukumar Swaminathan 	uint32_t count;
2496*82527734SSukumar Swaminathan 	uint32_t size;
2497*82527734SSukumar Swaminathan 	uint32_t sgllen;
2498*82527734SSukumar Swaminathan 	struct stmf_sglist_ent *sgl;
2499*82527734SSukumar Swaminathan 	emlxs_fct_dmem_bctl_t *bctl;
2500291a2b48SSukumar Swaminathan 
2501291a2b48SSukumar Swaminathan 
2502*82527734SSukumar Swaminathan 	iocb = (IOCB *)&sbp->iocbq;
2503*82527734SSukumar Swaminathan 	sbp->bmp = NULL;
2504291a2b48SSukumar Swaminathan 
2505*82527734SSukumar Swaminathan 	if (!sbp->fct_buf) {
2506*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
2507*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
2508*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
2509*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
2510*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
2511*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
2512*82527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
2513*82527734SSukumar Swaminathan 		iocb->ULPLE = 1;
2514*82527734SSukumar Swaminathan 		return (0);
2515291a2b48SSukumar Swaminathan 	}
2516*82527734SSukumar Swaminathan #ifdef EMLXS_SPARC
2517*82527734SSukumar Swaminathan 	/* Use FCP MEM_BPL table to get BPL buffer */
2518*82527734SSukumar Swaminathan 	bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag];
2519*82527734SSukumar Swaminathan #else
2520*82527734SSukumar Swaminathan 	/* Use MEM_BPL pool to get BPL buffer */
2521*82527734SSukumar Swaminathan 	bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL, 0);
2522*82527734SSukumar Swaminathan #endif /* EMLXS_SPARC */
2523291a2b48SSukumar Swaminathan 
2524*82527734SSukumar Swaminathan 	if (!bmp) {
2525*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2526*82527734SSukumar Swaminathan 		    "emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x",
2527*82527734SSukumar Swaminathan 		    sbp->iotag);
2528291a2b48SSukumar Swaminathan 
2529*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
2530*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
2531*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
2532*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
2533*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
2534*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
2535*82527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
2536*82527734SSukumar Swaminathan 		iocb->ULPLE = 1;
2537*82527734SSukumar Swaminathan 		return (1);
2538*82527734SSukumar Swaminathan 	}
2539291a2b48SSukumar Swaminathan 
2540*82527734SSukumar Swaminathan 	bpl = (ULP_BDE64 *)bmp->virt;
2541*82527734SSukumar Swaminathan 	bp = bmp->phys;
2542291a2b48SSukumar Swaminathan 
2543291a2b48SSukumar Swaminathan 
2544*82527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2545291a2b48SSukumar Swaminathan 
2546*82527734SSukumar Swaminathan 	size = sbp->fct_buf->db_data_size;
2547*82527734SSukumar Swaminathan 	count = sbp->fct_buf->db_sglist_length;
2548*82527734SSukumar Swaminathan 	bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private;
2549291a2b48SSukumar Swaminathan 
2550*82527734SSukumar Swaminathan 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2551*82527734SSukumar Swaminathan 	sgl = sbp->fct_buf->db_sglist;
2552*82527734SSukumar Swaminathan 	resid = size;
2553291a2b48SSukumar Swaminathan 
2554*82527734SSukumar Swaminathan 	/* Init the buffer list */
2555*82527734SSukumar Swaminathan 	for (sgllen = 0; sgllen < count && resid > 0; sgllen++) {
2556*82527734SSukumar Swaminathan 		bpl->addrHigh =
2557*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_HI(bctl->bctl_dev_addr));
2558*82527734SSukumar Swaminathan 		bpl->addrLow =
2559*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_LO(bctl->bctl_dev_addr));
2560*82527734SSukumar Swaminathan 		bpl->tus.f.bdeSize = MIN(resid, sgl->seg_length);
2561*82527734SSukumar Swaminathan 		bpl->tus.f.bdeFlags = bdeFlags;
2562*82527734SSukumar Swaminathan 		bpl->tus.w = BE_SWAP32(bpl->tus.w);
2563*82527734SSukumar Swaminathan 		bpl++;
2564291a2b48SSukumar Swaminathan 
2565*82527734SSukumar Swaminathan 		resid -= MIN(resid, sgl->seg_length);
2566*82527734SSukumar Swaminathan 		sgl++;
2567*82527734SSukumar Swaminathan 	}
2568291a2b48SSukumar Swaminathan 
2569*82527734SSukumar Swaminathan 	/* Init the IOCB */
2570*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp);
2571*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp);
2572*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeSize = sgllen * sizeof (ULP_BDE64);
2573*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL;
2574291a2b48SSukumar Swaminathan 
2575*82527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Length =
2576*82527734SSukumar Swaminathan 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
2577*82527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = 0;
2578291a2b48SSukumar Swaminathan 
2579*82527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 1;
2580*82527734SSukumar Swaminathan 	iocb->ULPLE = 1;
2581*82527734SSukumar Swaminathan 	sbp->bmp = bmp;
2582291a2b48SSukumar Swaminathan 
2583*82527734SSukumar Swaminathan 	return (0);
2584291a2b48SSukumar Swaminathan 
2585*82527734SSukumar Swaminathan } /* emlxs_sli2_fct_bde_setup */
2586*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2587291a2b48SSukumar Swaminathan 
2588291a2b48SSukumar Swaminathan 
2589*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
2590*82527734SSukumar Swaminathan /*ARGSUSED*/
2591*82527734SSukumar Swaminathan static uint32_t
2592*82527734SSukumar Swaminathan emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2593*82527734SSukumar Swaminathan {
2594*82527734SSukumar Swaminathan 	scsi_task_t *fct_task;
2595*82527734SSukumar Swaminathan 	ULP_BDE64 *bde;
2596*82527734SSukumar Swaminathan 	IOCB *iocb;
2597*82527734SSukumar Swaminathan 	uint32_t size;
2598*82527734SSukumar Swaminathan 	uint32_t count;
2599*82527734SSukumar Swaminathan 	uint32_t sgllen;
2600*82527734SSukumar Swaminathan 	int32_t resid;
2601*82527734SSukumar Swaminathan 	struct stmf_sglist_ent *sgl;
2602*82527734SSukumar Swaminathan 	uint32_t bdeFlags;
2603*82527734SSukumar Swaminathan 	emlxs_fct_dmem_bctl_t *bctl;
2604291a2b48SSukumar Swaminathan 
2605*82527734SSukumar Swaminathan 	iocb = (IOCB *)&sbp->iocbq;
2606291a2b48SSukumar Swaminathan 
2607*82527734SSukumar Swaminathan 	if (!sbp->fct_buf) {
2608*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrHigh = 0;
2609*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.addrLow = 0;
2610*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeSize = 0;
2611*82527734SSukumar Swaminathan 		iocb->un.fcpt64.bdl.bdeFlags = 0;
2612*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Offset = 0;
2613*82527734SSukumar Swaminathan 		iocb->un.fcpt64.fcpt_Length = 0;
2614*82527734SSukumar Swaminathan 		iocb->ULPBDECOUNT = 0;
2615*82527734SSukumar Swaminathan 		iocb->ULPLE = 0;
2616*82527734SSukumar Swaminathan 		iocb->unsli3.ext_iocb.ebde_count = 0;
2617*82527734SSukumar Swaminathan 		return (0);
2618291a2b48SSukumar Swaminathan 	}
2619291a2b48SSukumar Swaminathan 
2620*82527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2621291a2b48SSukumar Swaminathan 
2622*82527734SSukumar Swaminathan 	size = sbp->fct_buf->db_data_size;
2623*82527734SSukumar Swaminathan 	count = sbp->fct_buf->db_sglist_length;
2624*82527734SSukumar Swaminathan 	bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private;
2625291a2b48SSukumar Swaminathan 
2626*82527734SSukumar Swaminathan 	bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2627*82527734SSukumar Swaminathan 	sgl = sbp->fct_buf->db_sglist;
2628*82527734SSukumar Swaminathan 	resid = size;
2629291a2b48SSukumar Swaminathan 
2630*82527734SSukumar Swaminathan 	/* Init first BDE */
2631*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bctl->bctl_dev_addr);
2632*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bctl->bctl_dev_addr);
2633*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeSize = MIN(resid, sgl->seg_length);
2634*82527734SSukumar Swaminathan 	iocb->un.fcpt64.bdl.bdeFlags = bdeFlags;
2635*82527734SSukumar Swaminathan 	resid -= MIN(resid, sgl->seg_length);
2636*82527734SSukumar Swaminathan 	sgl++;
2637291a2b48SSukumar Swaminathan 
2638*82527734SSukumar Swaminathan 	/* Init remaining BDE's */
2639*82527734SSukumar Swaminathan 	bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde1;
2640*82527734SSukumar Swaminathan 	for (sgllen = 1; sgllen < count && resid > 0; sgllen++) {
2641*82527734SSukumar Swaminathan 		bde->addrHigh = PADDR_HI(bctl->bctl_dev_addr);
2642*82527734SSukumar Swaminathan 		bde->addrLow = PADDR_LO(bctl->bctl_dev_addr);
2643*82527734SSukumar Swaminathan 		bde->tus.f.bdeSize = MIN(resid, sgl->seg_length);
2644*82527734SSukumar Swaminathan 		bde->tus.f.bdeFlags = bdeFlags;
2645*82527734SSukumar Swaminathan 		bde++;
2646291a2b48SSukumar Swaminathan 
2647*82527734SSukumar Swaminathan 		resid -= MIN(resid, sgl->seg_length);
2648*82527734SSukumar Swaminathan 		sgl++;
2649291a2b48SSukumar Swaminathan 	}
2650291a2b48SSukumar Swaminathan 
2651*82527734SSukumar Swaminathan 	iocb->unsli3.ext_iocb.ebde_count = sgllen - 1;
2652*82527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Length =
2653*82527734SSukumar Swaminathan 	    (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
2654*82527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = 0;
2655291a2b48SSukumar Swaminathan 
2656*82527734SSukumar Swaminathan 	iocb->ULPBDECOUNT = 0;
2657*82527734SSukumar Swaminathan 	iocb->ULPLE = 0;
2658291a2b48SSukumar Swaminathan 
2659*82527734SSukumar Swaminathan 	return (0);
2660291a2b48SSukumar Swaminathan 
2661*82527734SSukumar Swaminathan } /* emlxs_sli3_fct_bde_setup */
2662*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2663291a2b48SSukumar Swaminathan 
2664291a2b48SSukumar Swaminathan 
2665*82527734SSukumar Swaminathan static void
2666*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2667291a2b48SSukumar Swaminathan {
2668*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
2669*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2670*82527734SSukumar Swaminathan #endif	/* FMA_SUPPORT */
2671*82527734SSukumar Swaminathan 	PGP *pgp;
2672*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
2673*82527734SSukumar Swaminathan 	SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
2674291a2b48SSukumar Swaminathan 	RING *rp;
2675*82527734SSukumar Swaminathan 	uint32_t nextIdx;
2676*82527734SSukumar Swaminathan 	uint32_t status;
2677*82527734SSukumar Swaminathan 	void *ioa2;
2678*82527734SSukumar Swaminathan 	off_t offset;
2679*82527734SSukumar Swaminathan 	uint32_t count = 0;
2680*82527734SSukumar Swaminathan 	uint32_t flag;
2681*82527734SSukumar Swaminathan 	uint32_t channelno;
2682*82527734SSukumar Swaminathan 	int32_t throttle;
2683291a2b48SSukumar Swaminathan 
2684*82527734SSukumar Swaminathan 	channelno = cp->channelno;
2685*82527734SSukumar Swaminathan 	rp = (RING *)cp->iopath;
2686291a2b48SSukumar Swaminathan 
2687*82527734SSukumar Swaminathan 	throttle = 0;
2688291a2b48SSukumar Swaminathan 
2689*82527734SSukumar Swaminathan 	/* Check if FCP ring and adapter is not ready */
2690*82527734SSukumar Swaminathan 	/* We may use any ring for FCP_CMD */
2691*82527734SSukumar Swaminathan 	if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
2692*82527734SSukumar Swaminathan 		if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2693*82527734SSukumar Swaminathan 		    !(((emlxs_port_t *)iocbq->port)->tgt_mode)) {
2694*82527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 1);
2695*82527734SSukumar Swaminathan 			return;
2696*82527734SSukumar Swaminathan 		}
2697291a2b48SSukumar Swaminathan 	}
2698291a2b48SSukumar Swaminathan 
2699*82527734SSukumar Swaminathan 	/* Attempt to acquire CMD_RING lock */
2700*82527734SSukumar Swaminathan 	if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) {
2701*82527734SSukumar Swaminathan 		/* Queue it for later */
2702*82527734SSukumar Swaminathan 		if (iocbq) {
2703*82527734SSukumar Swaminathan 			if ((hba->io_count -
2704*82527734SSukumar Swaminathan 			    hba->channel_tx_count) > 10) {
2705*82527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
2706*82527734SSukumar Swaminathan 				return;
2707*82527734SSukumar Swaminathan 			} else {
2708291a2b48SSukumar Swaminathan 
2709*82527734SSukumar Swaminathan 				/*
2710*82527734SSukumar Swaminathan 				 * EMLXS_MSGF(EMLXS_CONTEXT,
2711*82527734SSukumar Swaminathan 				 * &emlxs_ring_watchdog_msg,
2712*82527734SSukumar Swaminathan 				 * "%s host=%d port=%d cnt=%d,%d  RACE
2713*82527734SSukumar Swaminathan 				 * CONDITION3 DETECTED.",
2714*82527734SSukumar Swaminathan 				 * emlxs_ring_xlate(channelno),
2715*82527734SSukumar Swaminathan 				 * rp->fc_cmdidx, rp->fc_port_cmdidx,
2716*82527734SSukumar Swaminathan 				 * hba->channel_tx_count,
2717*82527734SSukumar Swaminathan 				 * hba->io_count);
2718*82527734SSukumar Swaminathan 				 */
2719*82527734SSukumar Swaminathan 				mutex_enter(&EMLXS_CMD_RING_LOCK(channelno));
2720*82527734SSukumar Swaminathan 			}
2721*82527734SSukumar Swaminathan 		} else {
2722*82527734SSukumar Swaminathan 			return;
2723*82527734SSukumar Swaminathan 		}
2724291a2b48SSukumar Swaminathan 	}
2725*82527734SSukumar Swaminathan 	/* CMD_RING_LOCK acquired */
2726291a2b48SSukumar Swaminathan 
2727*82527734SSukumar Swaminathan 	/* Throttle check only applies to non special iocb */
2728*82527734SSukumar Swaminathan 	if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
2729*82527734SSukumar Swaminathan 		/* Check if HBA is full */
2730*82527734SSukumar Swaminathan 		throttle = hba->io_throttle - hba->io_active;
2731*82527734SSukumar Swaminathan 		if (throttle <= 0) {
2732*82527734SSukumar Swaminathan 			/* Hitting adapter throttle limit */
2733*82527734SSukumar Swaminathan 			/* Queue it for later */
2734*82527734SSukumar Swaminathan 			if (iocbq) {
2735*82527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
2736291a2b48SSukumar Swaminathan 			}
2737*82527734SSukumar Swaminathan 
2738*82527734SSukumar Swaminathan 			goto busy;
2739291a2b48SSukumar Swaminathan 		}
2740291a2b48SSukumar Swaminathan 	}
2741291a2b48SSukumar Swaminathan 
2742*82527734SSukumar Swaminathan 	/* Read adapter's get index */
2743*82527734SSukumar Swaminathan 	pgp = (PGP *)
2744*82527734SSukumar Swaminathan 	    &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno];
2745*82527734SSukumar Swaminathan 	offset =
2746*82527734SSukumar Swaminathan 	    (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) -
2747*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
2748*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
2749*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
2750*82527734SSukumar Swaminathan 	rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2751291a2b48SSukumar Swaminathan 
2752*82527734SSukumar Swaminathan 	/* Calculate the next put index */
2753*82527734SSukumar Swaminathan 	nextIdx =
2754*82527734SSukumar Swaminathan 	    (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
2755291a2b48SSukumar Swaminathan 
2756*82527734SSukumar Swaminathan 	/* Check if ring is full */
2757*82527734SSukumar Swaminathan 	if (nextIdx == rp->fc_port_cmdidx) {
2758*82527734SSukumar Swaminathan 		/* Try one more time */
2759*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
2760*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
2761*82527734SSukumar Swaminathan 		rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2762291a2b48SSukumar Swaminathan 
2763*82527734SSukumar Swaminathan 		if (nextIdx == rp->fc_port_cmdidx) {
2764*82527734SSukumar Swaminathan 			/* Queue it for later */
2765*82527734SSukumar Swaminathan 			if (iocbq) {
2766*82527734SSukumar Swaminathan 				emlxs_tx_put(iocbq, 1);
2767*82527734SSukumar Swaminathan 			}
2768291a2b48SSukumar Swaminathan 
2769*82527734SSukumar Swaminathan 			goto busy;
2770*82527734SSukumar Swaminathan 		}
2771291a2b48SSukumar Swaminathan 	}
2772291a2b48SSukumar Swaminathan 
2773*82527734SSukumar Swaminathan 	/*
2774*82527734SSukumar Swaminathan 	 * We have a command ring slot available
2775*82527734SSukumar Swaminathan 	 * Make sure we have an iocb to send
2776*82527734SSukumar Swaminathan 	 */
2777*82527734SSukumar Swaminathan 	if (iocbq) {
2778*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2779291a2b48SSukumar Swaminathan 
2780*82527734SSukumar Swaminathan 		/* Check if the ring already has iocb's waiting */
2781*82527734SSukumar Swaminathan 		if (cp->nodeq.q_first != NULL) {
2782*82527734SSukumar Swaminathan 			/* Put the current iocbq on the tx queue */
2783*82527734SSukumar Swaminathan 			emlxs_tx_put(iocbq, 0);
2784291a2b48SSukumar Swaminathan 
2785*82527734SSukumar Swaminathan 			/*
2786*82527734SSukumar Swaminathan 			 * Attempt to replace it with the next iocbq
2787*82527734SSukumar Swaminathan 			 * in the tx queue
2788*82527734SSukumar Swaminathan 			 */
2789*82527734SSukumar Swaminathan 			iocbq = emlxs_tx_get(cp, 0);
2790*82527734SSukumar Swaminathan 		}
2791291a2b48SSukumar Swaminathan 
2792*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2793291a2b48SSukumar Swaminathan 	} else {
2794*82527734SSukumar Swaminathan 		/* Try to get the next iocb on the tx queue */
2795*82527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
2796291a2b48SSukumar Swaminathan 	}
2797291a2b48SSukumar Swaminathan 
2798*82527734SSukumar Swaminathan sendit:
2799*82527734SSukumar Swaminathan 	count = 0;
2800291a2b48SSukumar Swaminathan 
2801*82527734SSukumar Swaminathan 	/* Process each iocbq */
2802*82527734SSukumar Swaminathan 	while (iocbq) {
2803291a2b48SSukumar Swaminathan 
2804*82527734SSukumar Swaminathan 		sbp = iocbq->sbp;
2805*82527734SSukumar Swaminathan 		if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) {
2806*82527734SSukumar Swaminathan 			/*
2807*82527734SSukumar Swaminathan 			 * Update adapter if needed, since we are about to
2808*82527734SSukumar Swaminathan 			 * delay here
2809*82527734SSukumar Swaminathan 			 */
2810*82527734SSukumar Swaminathan 			if (count) {
2811*82527734SSukumar Swaminathan 				count = 0;
2812291a2b48SSukumar Swaminathan 
2813*82527734SSukumar Swaminathan 				/* Update the adapter's cmd put index */
2814*82527734SSukumar Swaminathan 				if (hba->bus_type == SBUS_FC) {
2815*82527734SSukumar Swaminathan 					slim2p->mbx.us.s2.host[channelno].
2816*82527734SSukumar Swaminathan 					    cmdPutInx =
2817*82527734SSukumar Swaminathan 					    BE_SWAP32(rp->fc_cmdidx);
2818291a2b48SSukumar Swaminathan 
2819*82527734SSukumar Swaminathan 					/* DMA sync the index for the adapter */
2820*82527734SSukumar Swaminathan 					offset = (off_t)
2821*82527734SSukumar Swaminathan 					    ((uint64_t)
2822*82527734SSukumar Swaminathan 					    ((unsigned long)&(slim2p->mbx.us.
2823*82527734SSukumar Swaminathan 					    s2.host[channelno].cmdPutInx)) -
2824*82527734SSukumar Swaminathan 					    (uint64_t)((unsigned long)slim2p));
2825*82527734SSukumar Swaminathan 					EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.
2826*82527734SSukumar Swaminathan 					    dma_handle, offset, 4,
2827*82527734SSukumar Swaminathan 					    DDI_DMA_SYNC_FORDEV);
2828*82527734SSukumar Swaminathan 				} else {
2829*82527734SSukumar Swaminathan 					ioa2 = (void *)
2830*82527734SSukumar Swaminathan 					    ((char *)hba->sli.sli3.slim_addr +
2831*82527734SSukumar Swaminathan 					    hba->sli.sli3.hgp_ring_offset +
2832*82527734SSukumar Swaminathan 					    ((channelno * 2) *
2833*82527734SSukumar Swaminathan 					    sizeof (uint32_t)));
2834*82527734SSukumar Swaminathan 					WRITE_SLIM_ADDR(hba,
2835*82527734SSukumar Swaminathan 					    (volatile uint32_t *)ioa2,
2836*82527734SSukumar Swaminathan 					    rp->fc_cmdidx);
2837*82527734SSukumar Swaminathan 				}
2838291a2b48SSukumar Swaminathan 
2839*82527734SSukumar Swaminathan 				status = (CA_R0ATT << (channelno * 4));
2840*82527734SSukumar Swaminathan 				WRITE_CSR_REG(hba, FC_CA_REG(hba),
2841*82527734SSukumar Swaminathan 				    (volatile uint32_t)status);
2842291a2b48SSukumar Swaminathan 
2843*82527734SSukumar Swaminathan 			}
2844*82527734SSukumar Swaminathan 			/* Perform delay */
2845*82527734SSukumar Swaminathan 			if ((channelno == FC_ELS_RING) &&
2846*82527734SSukumar Swaminathan 			    !(iocbq->flag & IOCB_FCP_CMD)) {
2847*82527734SSukumar Swaminathan 				drv_usecwait(100000);
2848*82527734SSukumar Swaminathan 			} else {
2849*82527734SSukumar Swaminathan 				drv_usecwait(20000);
2850*82527734SSukumar Swaminathan 			}
2851*82527734SSukumar Swaminathan 		}
2852*82527734SSukumar Swaminathan 
2853*82527734SSukumar Swaminathan 		/*
2854*82527734SSukumar Swaminathan 		 * At this point, we have a command ring slot available
2855*82527734SSukumar Swaminathan 		 * and an iocb to send
2856*82527734SSukumar Swaminathan 		 */
2857*82527734SSukumar Swaminathan 		flag =  iocbq->flag;
2858291a2b48SSukumar Swaminathan 
2859*82527734SSukumar Swaminathan 		/* Send the iocb */
2860*82527734SSukumar Swaminathan 		emlxs_sli3_issue_iocb(hba, rp, iocbq);
2861*82527734SSukumar Swaminathan 		/*
2862*82527734SSukumar Swaminathan 		 * After this, the sbp / iocb should not be
2863*82527734SSukumar Swaminathan 		 * accessed in the xmit path.
2864*82527734SSukumar Swaminathan 		 */
2865291a2b48SSukumar Swaminathan 
2866*82527734SSukumar Swaminathan 		count++;
2867*82527734SSukumar Swaminathan 		if (iocbq && (!(flag & IOCB_SPECIAL))) {
2868*82527734SSukumar Swaminathan 			/* Check if HBA is full */
2869*82527734SSukumar Swaminathan 			throttle = hba->io_throttle - hba->io_active;
2870*82527734SSukumar Swaminathan 			if (throttle <= 0) {
2871*82527734SSukumar Swaminathan 				goto busy;
2872*82527734SSukumar Swaminathan 			}
2873*82527734SSukumar Swaminathan 		}
2874291a2b48SSukumar Swaminathan 
2875*82527734SSukumar Swaminathan 		/* Calculate the next put index */
2876*82527734SSukumar Swaminathan 		nextIdx =
2877*82527734SSukumar Swaminathan 		    (rp->fc_cmdidx + 1 >=
2878*82527734SSukumar Swaminathan 		    rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
2879291a2b48SSukumar Swaminathan 
2880*82527734SSukumar Swaminathan 		/* Check if ring is full */
2881*82527734SSukumar Swaminathan 		if (nextIdx == rp->fc_port_cmdidx) {
2882*82527734SSukumar Swaminathan 			/* Try one more time */
2883*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
2884*82527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORKERNEL);
2885*82527734SSukumar Swaminathan 			rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2886291a2b48SSukumar Swaminathan 
2887*82527734SSukumar Swaminathan 			if (nextIdx == rp->fc_port_cmdidx) {
2888*82527734SSukumar Swaminathan 				goto busy;
2889*82527734SSukumar Swaminathan 			}
2890*82527734SSukumar Swaminathan 		}
2891291a2b48SSukumar Swaminathan 
2892*82527734SSukumar Swaminathan 		/* Get the next iocb from the tx queue if there is one */
2893*82527734SSukumar Swaminathan 		iocbq = emlxs_tx_get(cp, 1);
2894291a2b48SSukumar Swaminathan 	}
2895291a2b48SSukumar Swaminathan 
2896*82527734SSukumar Swaminathan 	if (count) {
2897*82527734SSukumar Swaminathan 		/* Update the adapter's cmd put index */
2898*82527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
2899*82527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channelno].
2900*82527734SSukumar Swaminathan 			    cmdPutInx = BE_SWAP32(rp->fc_cmdidx);
2901291a2b48SSukumar Swaminathan 
2902*82527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
2903*82527734SSukumar Swaminathan 			offset = (off_t)
2904*82527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
2905*82527734SSukumar Swaminathan 			    host[channelno].cmdPutInx)) -
2906*82527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
2907*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
2908*82527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
2909*82527734SSukumar Swaminathan 		} else {
2910*82527734SSukumar Swaminathan 			ioa2 =
2911*82527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
2912*82527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset +
2913*82527734SSukumar Swaminathan 			    ((channelno * 2) * sizeof (uint32_t)));
2914*82527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
2915*82527734SSukumar Swaminathan 			    rp->fc_cmdidx);
2916*82527734SSukumar Swaminathan 		}
2917291a2b48SSukumar Swaminathan 
2918*82527734SSukumar Swaminathan 		status = (CA_R0ATT << (channelno * 4));
2919*82527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_CA_REG(hba),
2920*82527734SSukumar Swaminathan 		    (volatile uint32_t)status);
2921291a2b48SSukumar Swaminathan 
2922*82527734SSukumar Swaminathan 		/* Check tx queue one more time before releasing */
2923*82527734SSukumar Swaminathan 		if ((iocbq = emlxs_tx_get(cp, 1))) {
2924*82527734SSukumar Swaminathan 			/*
2925*82527734SSukumar Swaminathan 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg,
2926*82527734SSukumar Swaminathan 			 * "%s host=%d port=%d   RACE CONDITION1
2927*82527734SSukumar Swaminathan 			 * DETECTED.", emlxs_ring_xlate(channelno),
2928*82527734SSukumar Swaminathan 			 * rp->fc_cmdidx, rp->fc_port_cmdidx);
2929*82527734SSukumar Swaminathan 			 */
2930*82527734SSukumar Swaminathan 			goto sendit;
2931*82527734SSukumar Swaminathan 		}
2932291a2b48SSukumar Swaminathan 	}
2933291a2b48SSukumar Swaminathan 
2934*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
2935*82527734SSukumar Swaminathan 	/* Access handle validation */
2936*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
2937*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
2938*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
2939291a2b48SSukumar Swaminathan 
2940*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
2941291a2b48SSukumar Swaminathan 
2942*82527734SSukumar Swaminathan 	return;
2943291a2b48SSukumar Swaminathan 
2944*82527734SSukumar Swaminathan busy:
2945291a2b48SSukumar Swaminathan 
2946291a2b48SSukumar Swaminathan 	/*
2947*82527734SSukumar Swaminathan 	 * Set ring to SET R0CE_REQ in Chip Att register.
2948*82527734SSukumar Swaminathan 	 * Chip will tell us when an entry is freed.
2949291a2b48SSukumar Swaminathan 	 */
2950*82527734SSukumar Swaminathan 	if (count) {
2951*82527734SSukumar Swaminathan 		/* Update the adapter's cmd put index */
2952*82527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
2953*82527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channelno].cmdPutInx =
2954*82527734SSukumar Swaminathan 			    BE_SWAP32(rp->fc_cmdidx);
2955291a2b48SSukumar Swaminathan 
2956*82527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
2957*82527734SSukumar Swaminathan 			offset = (off_t)
2958*82527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
2959*82527734SSukumar Swaminathan 			    host[channelno].cmdPutInx)) -
2960*82527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
2961*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
2962*82527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
2963*82527734SSukumar Swaminathan 		} else {
2964*82527734SSukumar Swaminathan 			ioa2 =
2965*82527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
2966*82527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset +
2967*82527734SSukumar Swaminathan 			    ((channelno * 2) * sizeof (uint32_t)));
2968*82527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
2969*82527734SSukumar Swaminathan 			    rp->fc_cmdidx);
2970291a2b48SSukumar Swaminathan 		}
2971*82527734SSukumar Swaminathan 	}
2972291a2b48SSukumar Swaminathan 
2973*82527734SSukumar Swaminathan 	status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4));
2974*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status);
2975*82527734SSukumar Swaminathan 
2976*82527734SSukumar Swaminathan 	if (throttle <= 0) {
2977*82527734SSukumar Swaminathan 		HBASTATS.IocbThrottled++;
2978*82527734SSukumar Swaminathan 	} else {
2979*82527734SSukumar Swaminathan 		HBASTATS.IocbRingFull[channelno]++;
2980291a2b48SSukumar Swaminathan 	}
2981291a2b48SSukumar Swaminathan 
2982*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
2983*82527734SSukumar Swaminathan 	/* Access handle validation */
2984*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
2985*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
2986*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
2987291a2b48SSukumar Swaminathan 
2988*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
2989291a2b48SSukumar Swaminathan 
2990291a2b48SSukumar Swaminathan 	return;
2991291a2b48SSukumar Swaminathan 
2992*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb_cmd() */
2993291a2b48SSukumar Swaminathan 
2994291a2b48SSukumar Swaminathan 
2995*82527734SSukumar Swaminathan /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */
2996*82527734SSukumar Swaminathan /* MBX_WAIT   - returns MBX_TIMEOUT or mailbox_status */
2997*82527734SSukumar Swaminathan /* MBX_SLEEP  - returns MBX_TIMEOUT or mailbox_status */
2998*82527734SSukumar Swaminathan /* MBX_POLL   - returns MBX_TIMEOUT or mailbox_status */
2999291a2b48SSukumar Swaminathan 
3000*82527734SSukumar Swaminathan static uint32_t
3001*82527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3002*82527734SSukumar Swaminathan     uint32_t tmo)
3003291a2b48SSukumar Swaminathan {
3004*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
3005*82527734SSukumar Swaminathan 	SLIM2			*slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
3006*82527734SSukumar Swaminathan 	MAILBOX			*mbox;
3007*82527734SSukumar Swaminathan 	MAILBOX			*mb;
3008*82527734SSukumar Swaminathan 	volatile uint32_t	word0;
3009*82527734SSukumar Swaminathan 	volatile uint32_t	ldata;
3010*82527734SSukumar Swaminathan 	uint32_t		ha_copy;
3011*82527734SSukumar Swaminathan 	off_t			offset;
3012*82527734SSukumar Swaminathan 	MATCHMAP		*mbox_bp;
3013*82527734SSukumar Swaminathan 	uint32_t		tmo_local;
3014*82527734SSukumar Swaminathan 	MAILBOX			*swpmb;
3015291a2b48SSukumar Swaminathan 
3016*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
3017*82527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
3018291a2b48SSukumar Swaminathan 
3019*82527734SSukumar Swaminathan 	mb->mbxStatus = MBX_SUCCESS;
3020291a2b48SSukumar Swaminathan 
3021*82527734SSukumar Swaminathan 	/* Check for minimum timeouts */
3022*82527734SSukumar Swaminathan 	switch (mb->mbxCommand) {
3023*82527734SSukumar Swaminathan 	/* Mailbox commands that erase/write flash */
3024*82527734SSukumar Swaminathan 	case MBX_DOWN_LOAD:
3025*82527734SSukumar Swaminathan 	case MBX_UPDATE_CFG:
3026*82527734SSukumar Swaminathan 	case MBX_LOAD_AREA:
3027*82527734SSukumar Swaminathan 	case MBX_LOAD_EXP_ROM:
3028*82527734SSukumar Swaminathan 	case MBX_WRITE_NV:
3029*82527734SSukumar Swaminathan 	case MBX_FLASH_WR_ULA:
3030*82527734SSukumar Swaminathan 	case MBX_DEL_LD_ENTRY:
3031*82527734SSukumar Swaminathan 	case MBX_LOAD_SM:
3032*82527734SSukumar Swaminathan 		if (tmo < 300) {
3033*82527734SSukumar Swaminathan 			tmo = 300;
3034291a2b48SSukumar Swaminathan 		}
3035*82527734SSukumar Swaminathan 		break;
3036291a2b48SSukumar Swaminathan 
3037*82527734SSukumar Swaminathan 	default:
3038*82527734SSukumar Swaminathan 		if (tmo < 30) {
3039*82527734SSukumar Swaminathan 			tmo = 30;
3040*82527734SSukumar Swaminathan 		}
3041*82527734SSukumar Swaminathan 		break;
3042*82527734SSukumar Swaminathan 	}
3043291a2b48SSukumar Swaminathan 
3044*82527734SSukumar Swaminathan 	/* Convert tmo seconds to 10 millisecond tics */
3045*82527734SSukumar Swaminathan 	tmo_local = tmo * 100;
3046291a2b48SSukumar Swaminathan 
3047*82527734SSukumar Swaminathan 	/* Adjust wait flag */
3048*82527734SSukumar Swaminathan 	if (flag != MBX_NOWAIT) {
3049*82527734SSukumar Swaminathan 		/* If interrupt is enabled, use sleep, otherwise poll */
3050*82527734SSukumar Swaminathan 		if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) {
3051*82527734SSukumar Swaminathan 			flag = MBX_SLEEP;
3052291a2b48SSukumar Swaminathan 		} else {
3053*82527734SSukumar Swaminathan 			flag = MBX_POLL;
3054291a2b48SSukumar Swaminathan 		}
3055*82527734SSukumar Swaminathan 	}
3056291a2b48SSukumar Swaminathan 
3057*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
3058291a2b48SSukumar Swaminathan 
3059*82527734SSukumar Swaminathan 	/* Check for hardware error */
3060*82527734SSukumar Swaminathan 	if (hba->flag & FC_HARDWARE_ERROR) {
3061*82527734SSukumar Swaminathan 		mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ?
3062*82527734SSukumar Swaminathan 		    MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
3063291a2b48SSukumar Swaminathan 
3064*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
3065291a2b48SSukumar Swaminathan 
3066*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3067*82527734SSukumar Swaminathan 		    "Hardware error reported. %s failed. status=%x mb=%p",
3068*82527734SSukumar Swaminathan 		    emlxs_mb_cmd_xlate(mb->mbxCommand),  mb->mbxStatus, mb);
3069291a2b48SSukumar Swaminathan 
3070*82527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
3071291a2b48SSukumar Swaminathan 	}
3072291a2b48SSukumar Swaminathan 
3073*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
3074*82527734SSukumar Swaminathan 		/* If we are not polling, then queue it for later */
3075*82527734SSukumar Swaminathan 		if (flag == MBX_NOWAIT) {
3076*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3077*82527734SSukumar Swaminathan 			    "Busy.      %s: mb=%p NoWait.",
3078*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3079291a2b48SSukumar Swaminathan 
3080*82527734SSukumar Swaminathan 			emlxs_mb_put(hba, mbq);
3081291a2b48SSukumar Swaminathan 
3082*82527734SSukumar Swaminathan 			HBASTATS.MboxBusy++;
3083291a2b48SSukumar Swaminathan 
3084*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
3085291a2b48SSukumar Swaminathan 
3086*82527734SSukumar Swaminathan 			return (MBX_BUSY);
3087*82527734SSukumar Swaminathan 		}
3088291a2b48SSukumar Swaminathan 
3089*82527734SSukumar Swaminathan 		while (hba->mbox_queue_flag) {
3090*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
3091291a2b48SSukumar Swaminathan 
3092*82527734SSukumar Swaminathan 			if (tmo_local-- == 0) {
3093*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3094*82527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
3095*82527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
3096*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3097*82527734SSukumar Swaminathan 				    tmo);
3098291a2b48SSukumar Swaminathan 
3099*82527734SSukumar Swaminathan 				/* Non-lethalStatus mailbox timeout */
3100*82527734SSukumar Swaminathan 				/* Does not indicate a hardware error */
3101*82527734SSukumar Swaminathan 				mb->mbxStatus = MBX_TIMEOUT;
3102*82527734SSukumar Swaminathan 				return (MBX_TIMEOUT);
3103*82527734SSukumar Swaminathan 			}
3104291a2b48SSukumar Swaminathan 
3105*82527734SSukumar Swaminathan 			DELAYMS(10);
3106*82527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
31074baa2c25SSukumar Swaminathan 		}
3108291a2b48SSukumar Swaminathan 	}
3109291a2b48SSukumar Swaminathan 
3110*82527734SSukumar Swaminathan 	/* Initialize mailbox area */
3111*82527734SSukumar Swaminathan 	emlxs_mb_init(hba, mbq, flag, tmo);
3112291a2b48SSukumar Swaminathan 
3113*82527734SSukumar Swaminathan 	switch (flag) {
3114*82527734SSukumar Swaminathan 	case MBX_NOWAIT:
3115291a2b48SSukumar Swaminathan 
3116*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_HEARTBEAT) {
3117*82527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD &&
3118*82527734SSukumar Swaminathan 			    mb->mbxCommand != MBX_DUMP_MEMORY) {
3119*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3120*82527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
3121*82527734SSukumar Swaminathan 				    "Sending.   %s: mb=%p NoWait.",
3122*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3123*82527734SSukumar Swaminathan 			}
3124*82527734SSukumar Swaminathan 		}
3125291a2b48SSukumar Swaminathan 
3126*82527734SSukumar Swaminathan 		break;
3127291a2b48SSukumar Swaminathan 
3128*82527734SSukumar Swaminathan 	case MBX_SLEEP:
3129*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
3130*82527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
3131*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3132*82527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Sleep.",
3133*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3134*82527734SSukumar Swaminathan 		}
3135291a2b48SSukumar Swaminathan 
3136*82527734SSukumar Swaminathan 		break;
3137291a2b48SSukumar Swaminathan 
3138*82527734SSukumar Swaminathan 	case MBX_POLL:
3139*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
3140*82527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
3141*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3142*82527734SSukumar Swaminathan 			    "Sending.   %s: mb=%p Polled.",
3143*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3144*82527734SSukumar Swaminathan 		}
3145*82527734SSukumar Swaminathan 		break;
3146*82527734SSukumar Swaminathan 	}
3147291a2b48SSukumar Swaminathan 
3148*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_CHIP;
3149291a2b48SSukumar Swaminathan 
3150*82527734SSukumar Swaminathan 	/* Clear the attention bit */
3151*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
3152291a2b48SSukumar Swaminathan 
3153*82527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
3154*82527734SSukumar Swaminathan 		/* First copy command data */
3155*82527734SSukumar Swaminathan 		mbox = FC_SLIM2_MAILBOX(hba);
3156*82527734SSukumar Swaminathan 		offset =
3157*82527734SSukumar Swaminathan 		    (off_t)((uint64_t)((unsigned long)mbox)
3158*82527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)slim2p));
3159291a2b48SSukumar Swaminathan 
3160*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
3161*82527734SSukumar Swaminathan 		if (mbq->extbuf) {
3162*82527734SSukumar Swaminathan 			uint32_t *mbox_ext =
3163*82527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
3164*82527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
3165*82527734SSukumar Swaminathan 			off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3166291a2b48SSukumar Swaminathan 
3167*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf,
3168*82527734SSukumar Swaminathan 			    (uint8_t *)mbox_ext, mbq->extsize);
3169291a2b48SSukumar Swaminathan 
3170*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3171*82527734SSukumar Swaminathan 			    offset_ext, mbq->extsize,
3172*82527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORDEV);
3173291a2b48SSukumar Swaminathan 		}
3174*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3175291a2b48SSukumar Swaminathan 
3176*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox,
3177*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE);
3178291a2b48SSukumar Swaminathan 
3179*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
3180*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
3181*82527734SSukumar Swaminathan 	}
3182*82527734SSukumar Swaminathan 	/* Check for config port command */
3183*82527734SSukumar Swaminathan 	else if (mb->mbxCommand == MBX_CONFIG_PORT) {
3184*82527734SSukumar Swaminathan 		/* copy command data into host mbox for cmpl */
3185*82527734SSukumar Swaminathan 		mbox = FC_SLIM2_MAILBOX(hba);
3186*82527734SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)mbox)
3187*82527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)slim2p));
3188291a2b48SSukumar Swaminathan 
3189*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox,
3190*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE);
3191291a2b48SSukumar Swaminathan 
3192*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
3193*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
3194291a2b48SSukumar Swaminathan 
3195*82527734SSukumar Swaminathan 		/* First copy command data */
3196*82527734SSukumar Swaminathan 		mbox = FC_SLIM1_MAILBOX(hba);
3197*82527734SSukumar Swaminathan 		WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
3198*82527734SSukumar Swaminathan 		    (MAILBOX_CMD_WSIZE - 1));
3199291a2b48SSukumar Swaminathan 
3200*82527734SSukumar Swaminathan 		/* copy over last word, with mbxOwner set */
3201*82527734SSukumar Swaminathan 		ldata = *((volatile uint32_t *)mb);
3202*82527734SSukumar Swaminathan 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata);
3203291a2b48SSukumar Swaminathan 
3204*82527734SSukumar Swaminathan 		/* switch over to host mailbox */
3205*82527734SSukumar Swaminathan 		hba->flag |= FC_SLIM2_MODE;
3206*82527734SSukumar Swaminathan 	} else {	/* SLIM 1 */
3207291a2b48SSukumar Swaminathan 
3208*82527734SSukumar Swaminathan 		mbox = FC_SLIM1_MAILBOX(hba);
3209291a2b48SSukumar Swaminathan 
3210*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
3211*82527734SSukumar Swaminathan 		if (mbq->extbuf) {
3212*82527734SSukumar Swaminathan 			uint32_t *mbox_ext =
3213*82527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
3214*82527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
3215*82527734SSukumar Swaminathan 			WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
3216*82527734SSukumar Swaminathan 			    mbox_ext, (mbq->extsize / 4));
3217*82527734SSukumar Swaminathan 		}
3218*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3219291a2b48SSukumar Swaminathan 
3220*82527734SSukumar Swaminathan 		/* First copy command data */
3221*82527734SSukumar Swaminathan 		WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
3222*82527734SSukumar Swaminathan 		    (MAILBOX_CMD_WSIZE - 1));
3223291a2b48SSukumar Swaminathan 
3224*82527734SSukumar Swaminathan 		/* copy over last word, with mbxOwner set */
3225*82527734SSukumar Swaminathan 		ldata = *((volatile uint32_t *)mb);
3226*82527734SSukumar Swaminathan 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata);
3227291a2b48SSukumar Swaminathan 	}
3228291a2b48SSukumar Swaminathan 
3229*82527734SSukumar Swaminathan 	/* Interrupt board to do it right away */
3230*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
3231291a2b48SSukumar Swaminathan 
3232*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
3233291a2b48SSukumar Swaminathan 
32344baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
32354baa2c25SSukumar Swaminathan 	/* Access handle validation */
3236*82527734SSukumar Swaminathan 	if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
3237*82527734SSukumar Swaminathan 	    != DDI_FM_OK) ||
3238*82527734SSukumar Swaminathan 	    (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
32394baa2c25SSukumar Swaminathan 	    != DDI_FM_OK)) {
32404baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
32414baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
3242*82527734SSukumar Swaminathan 		return (MBX_HARDWARE_ERROR);
32434baa2c25SSukumar Swaminathan 	}
32444baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
32454baa2c25SSukumar Swaminathan 
3246*82527734SSukumar Swaminathan 	switch (flag) {
3247*82527734SSukumar Swaminathan 	case MBX_NOWAIT:
3248*82527734SSukumar Swaminathan 		return (MBX_SUCCESS);
3249291a2b48SSukumar Swaminathan 
3250*82527734SSukumar Swaminathan 	case MBX_SLEEP:
32514baa2c25SSukumar Swaminathan 
3252*82527734SSukumar Swaminathan 		/* Wait for completion */
3253*82527734SSukumar Swaminathan 		/* The driver clock is timing the mailbox. */
3254*82527734SSukumar Swaminathan 		/* emlxs_mb_fini() will be called externally. */
3255291a2b48SSukumar Swaminathan 
3256*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
3257*82527734SSukumar Swaminathan 		while (!(mbq->flag & MBQ_COMPLETED)) {
3258*82527734SSukumar Swaminathan 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
3259*82527734SSukumar Swaminathan 		}
3260*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
3261291a2b48SSukumar Swaminathan 
3262*82527734SSukumar Swaminathan 		if (mb->mbxStatus == MBX_TIMEOUT) {
3263*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3264*82527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%d. Sleep.",
3265*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3266*82527734SSukumar Swaminathan 		} else {
3267*82527734SSukumar Swaminathan 			if (mb->mbxCommand != MBX_DOWN_LOAD &&
3268*82527734SSukumar Swaminathan 			    mb->mbxCommand != MBX_DUMP_MEMORY) {
3269*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3270*82527734SSukumar Swaminathan 				    &emlxs_mbox_detail_msg,
3271*82527734SSukumar Swaminathan 				    "Completed. %s: mb=%p status=%x Sleep.",
3272*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3273*82527734SSukumar Swaminathan 				    mb->mbxStatus);
3274*82527734SSukumar Swaminathan 			}
3275*82527734SSukumar Swaminathan 		}
3276291a2b48SSukumar Swaminathan 
3277*82527734SSukumar Swaminathan 		break;
3278291a2b48SSukumar Swaminathan 
3279*82527734SSukumar Swaminathan 	case MBX_POLL:
3280291a2b48SSukumar Swaminathan 
3281*82527734SSukumar Swaminathan 		/* Convert tmo seconds to 500 usec tics */
3282*82527734SSukumar Swaminathan 		tmo_local = tmo * 2000;
3283291a2b48SSukumar Swaminathan 
3284*82527734SSukumar Swaminathan 		if (hba->state >= FC_INIT_START) {
3285*82527734SSukumar Swaminathan 			ha_copy =
3286*82527734SSukumar Swaminathan 			    READ_CSR_REG(hba, FC_HA_REG(hba));
3287291a2b48SSukumar Swaminathan 
3288*82527734SSukumar Swaminathan 			/* Wait for command to complete */
3289*82527734SSukumar Swaminathan 			while (!(ha_copy & HA_MBATT) &&
3290*82527734SSukumar Swaminathan 			    !(mbq->flag & MBQ_COMPLETED)) {
3291*82527734SSukumar Swaminathan 				if (!hba->timer_id && (tmo_local-- == 0)) {
3292*82527734SSukumar Swaminathan 					/* self time */
3293*82527734SSukumar Swaminathan 					EMLXS_MSGF(EMLXS_CONTEXT,
3294*82527734SSukumar Swaminathan 					    &emlxs_mbox_timeout_msg,
3295*82527734SSukumar Swaminathan 					    "%s: mb=%p Polled.",
3296*82527734SSukumar Swaminathan 					    emlxs_mb_cmd_xlate(mb->
3297*82527734SSukumar Swaminathan 					    mbxCommand), mb);
3298291a2b48SSukumar Swaminathan 
3299*82527734SSukumar Swaminathan 					hba->flag |= FC_MBOX_TIMEOUT;
3300*82527734SSukumar Swaminathan 					EMLXS_STATE_CHANGE(hba, FC_ERROR);
3301*82527734SSukumar Swaminathan 					emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3302291a2b48SSukumar Swaminathan 
3303*82527734SSukumar Swaminathan 					break;
3304*82527734SSukumar Swaminathan 				}
3305291a2b48SSukumar Swaminathan 
3306*82527734SSukumar Swaminathan 				DELAYUS(500);
3307*82527734SSukumar Swaminathan 				ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
3308*82527734SSukumar Swaminathan 			}
3309291a2b48SSukumar Swaminathan 
3310*82527734SSukumar Swaminathan 			if (mb->mbxStatus == MBX_TIMEOUT) {
3311*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3312*82527734SSukumar Swaminathan 				    &emlxs_mbox_event_msg,
3313*82527734SSukumar Swaminathan 				    "Timeout.   %s: mb=%p tmo=%d. Polled.",
3314*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3315*82527734SSukumar Swaminathan 				    tmo);
3316291a2b48SSukumar Swaminathan 
3317*82527734SSukumar Swaminathan 				break;
3318*82527734SSukumar Swaminathan 			}
3319*82527734SSukumar Swaminathan 		}
3320291a2b48SSukumar Swaminathan 
3321*82527734SSukumar Swaminathan 		/* Get first word of mailbox */
3322*82527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
3323*82527734SSukumar Swaminathan 			mbox = FC_SLIM2_MAILBOX(hba);
3324*82527734SSukumar Swaminathan 			offset = (off_t)((uint64_t)((unsigned long)mbox) -
3325*82527734SSukumar Swaminathan 			    (uint64_t)((unsigned long)slim2p));
3326291a2b48SSukumar Swaminathan 
3327*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3328*82527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3329*82527734SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mbox);
3330*82527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
3331*82527734SSukumar Swaminathan 		} else {
3332*82527734SSukumar Swaminathan 			mbox = FC_SLIM1_MAILBOX(hba);
3333*82527734SSukumar Swaminathan 			word0 =
3334*82527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
33354baa2c25SSukumar Swaminathan 		}
33364baa2c25SSukumar Swaminathan 
3337*82527734SSukumar Swaminathan 		/* Wait for command to complete */
3338*82527734SSukumar Swaminathan 		while ((swpmb->mbxOwner == OWN_CHIP) &&
3339*82527734SSukumar Swaminathan 		    !(mbq->flag & MBQ_COMPLETED)) {
3340*82527734SSukumar Swaminathan 			if (!hba->timer_id && (tmo_local-- == 0)) {
3341*82527734SSukumar Swaminathan 				/* self time */
3342*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3343*82527734SSukumar Swaminathan 				    &emlxs_mbox_timeout_msg,
3344*82527734SSukumar Swaminathan 				    "%s: mb=%p Polled.",
3345*82527734SSukumar Swaminathan 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3346291a2b48SSukumar Swaminathan 
3347*82527734SSukumar Swaminathan 				hba->flag |= FC_MBOX_TIMEOUT;
3348*82527734SSukumar Swaminathan 				EMLXS_STATE_CHANGE(hba, FC_ERROR);
3349*82527734SSukumar Swaminathan 				emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3350291a2b48SSukumar Swaminathan 
3351*82527734SSukumar Swaminathan 				break;
3352*82527734SSukumar Swaminathan 			}
3353291a2b48SSukumar Swaminathan 
3354*82527734SSukumar Swaminathan 			DELAYUS(500);
3355291a2b48SSukumar Swaminathan 
3356*82527734SSukumar Swaminathan 			/* Get first word of mailbox */
3357*82527734SSukumar Swaminathan 			if (hba->flag & FC_SLIM2_MODE) {
3358*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(
3359*82527734SSukumar Swaminathan 				    hba->sli.sli3.slim2.dma_handle, offset,
3360*82527734SSukumar Swaminathan 				    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3361*82527734SSukumar Swaminathan 				word0 = *((volatile uint32_t *)mbox);
3362*82527734SSukumar Swaminathan 				word0 = BE_SWAP32(word0);
3363*82527734SSukumar Swaminathan 			} else {
3364*82527734SSukumar Swaminathan 				word0 =
3365*82527734SSukumar Swaminathan 				    READ_SLIM_ADDR(hba,
3366*82527734SSukumar Swaminathan 				    ((volatile uint32_t *)mbox));
3367*82527734SSukumar Swaminathan 			}
3368291a2b48SSukumar Swaminathan 
3369*82527734SSukumar Swaminathan 		}	/* while */
3370291a2b48SSukumar Swaminathan 
3371*82527734SSukumar Swaminathan 		if (mb->mbxStatus == MBX_TIMEOUT) {
3372*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3373*82527734SSukumar Swaminathan 			    "Timeout.   %s: mb=%p tmo=%d. Polled.",
3374*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3375*82527734SSukumar Swaminathan 
3376*82527734SSukumar Swaminathan 			break;
3377291a2b48SSukumar Swaminathan 		}
3378291a2b48SSukumar Swaminathan 
3379*82527734SSukumar Swaminathan 		/* copy results back to user */
3380*82527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
3381*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3382*82527734SSukumar Swaminathan 			    offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3383291a2b48SSukumar Swaminathan 
3384*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
3385*82527734SSukumar Swaminathan 			    MAILBOX_CMD_BSIZE);
3386*82527734SSukumar Swaminathan 		} else {
3387*82527734SSukumar Swaminathan 			READ_SLIM_COPY(hba, (uint32_t *)mb,
3388*82527734SSukumar Swaminathan 			    (uint32_t *)mbox, MAILBOX_CMD_WSIZE);
3389*82527734SSukumar Swaminathan 		}
3390291a2b48SSukumar Swaminathan 
3391*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
3392*82527734SSukumar Swaminathan 		if (mbq->extbuf) {
3393*82527734SSukumar Swaminathan 			uint32_t *mbox_ext =
3394*82527734SSukumar Swaminathan 			    (uint32_t *)((uint8_t *)mbox +
3395*82527734SSukumar Swaminathan 			    MBOX_EXTENSION_OFFSET);
3396*82527734SSukumar Swaminathan 			off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3397291a2b48SSukumar Swaminathan 
3398*82527734SSukumar Swaminathan 			if (hba->flag & FC_SLIM2_MODE) {
3399*82527734SSukumar Swaminathan 				EMLXS_MPDATA_SYNC(
3400*82527734SSukumar Swaminathan 				    hba->sli.sli3.slim2.dma_handle, offset_ext,
3401*82527734SSukumar Swaminathan 				    mbq->extsize, DDI_DMA_SYNC_FORKERNEL);
3402291a2b48SSukumar Swaminathan 
3403*82527734SSukumar Swaminathan 				BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
3404*82527734SSukumar Swaminathan 				    (uint8_t *)mbq->extbuf, mbq->extsize);
3405*82527734SSukumar Swaminathan 			} else {
3406*82527734SSukumar Swaminathan 				READ_SLIM_COPY(hba,
3407*82527734SSukumar Swaminathan 				    (uint32_t *)mbq->extbuf, mbox_ext,
3408*82527734SSukumar Swaminathan 				    (mbq->extsize / 4));
3409*82527734SSukumar Swaminathan 			}
3410*82527734SSukumar Swaminathan 		}
3411*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
3412291a2b48SSukumar Swaminathan 
3413*82527734SSukumar Swaminathan 		/* Sync the memory buffer */
3414*82527734SSukumar Swaminathan 		if (mbq->bp) {
3415*82527734SSukumar Swaminathan 			mbox_bp = (MATCHMAP *)mbq->bp;
3416*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0,
3417*82527734SSukumar Swaminathan 			    mbox_bp->size, DDI_DMA_SYNC_FORKERNEL);
3418*82527734SSukumar Swaminathan 		}
3419291a2b48SSukumar Swaminathan 
3420*82527734SSukumar Swaminathan 		if (mb->mbxCommand != MBX_DOWN_LOAD &&
3421*82527734SSukumar Swaminathan 		    mb->mbxCommand != MBX_DUMP_MEMORY) {
3422*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3423*82527734SSukumar Swaminathan 			    "Completed. %s: mb=%p status=%x Polled.",
3424*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3425*82527734SSukumar Swaminathan 			    mb->mbxStatus);
3426*82527734SSukumar Swaminathan 		}
3427291a2b48SSukumar Swaminathan 
3428*82527734SSukumar Swaminathan 		/* Process the result */
3429*82527734SSukumar Swaminathan 		if (!(mbq->flag & MBQ_PASSTHRU)) {
3430*82527734SSukumar Swaminathan 			if (mbq->mbox_cmpl) {
3431*82527734SSukumar Swaminathan 				(void) (mbq->mbox_cmpl)(hba, mbq);
3432*82527734SSukumar Swaminathan 			}
3433*82527734SSukumar Swaminathan 		}
3434291a2b48SSukumar Swaminathan 
3435*82527734SSukumar Swaminathan 		/* Clear the attention bit */
3436*82527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
34374baa2c25SSukumar Swaminathan 
3438*82527734SSukumar Swaminathan 		/* Clean up the mailbox area */
3439*82527734SSukumar Swaminathan 		emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3440291a2b48SSukumar Swaminathan 
3441*82527734SSukumar Swaminathan 		break;
3442291a2b48SSukumar Swaminathan 
3443*82527734SSukumar Swaminathan 	}	/* switch (flag) */
3444*82527734SSukumar Swaminathan 
3445*82527734SSukumar Swaminathan 	return (mb->mbxStatus);
3446*82527734SSukumar Swaminathan 
3447*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_mbox_cmd() */
3448*82527734SSukumar Swaminathan 
3449*82527734SSukumar Swaminathan 
3450*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
3451*82527734SSukumar Swaminathan static uint32_t
3452*82527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp,
3453*82527734SSukumar Swaminathan 	int channel)
3454291a2b48SSukumar Swaminathan {
3455*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3456*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
3457*82527734SSukumar Swaminathan 	fct_cmd_t *fct_cmd;
3458*82527734SSukumar Swaminathan 	stmf_data_buf_t *dbuf;
3459*82527734SSukumar Swaminathan 	scsi_task_t *fct_task;
3460*82527734SSukumar Swaminathan 	uint32_t did;
3461*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3462*82527734SSukumar Swaminathan 	IOCB *iocb;
3463*82527734SSukumar Swaminathan 	uint32_t timeout;
3464*82527734SSukumar Swaminathan 	uint32_t iotag;
3465*82527734SSukumar Swaminathan 	emlxs_node_t *ndlp;
3466*82527734SSukumar Swaminathan 	CHANNEL *cp;
3467291a2b48SSukumar Swaminathan 
3468*82527734SSukumar Swaminathan 	dbuf = cmd_sbp->fct_buf;
3469*82527734SSukumar Swaminathan 	fct_cmd = cmd_sbp->fct_cmd;
3470*82527734SSukumar Swaminathan 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
3471*82527734SSukumar Swaminathan 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
3472*82527734SSukumar Swaminathan 	did = fct_cmd->cmd_rportid;
3473291a2b48SSukumar Swaminathan 
3474*82527734SSukumar Swaminathan 	cp = (CHANNEL *)cmd_sbp->channel;
3475291a2b48SSukumar Swaminathan 
3476*82527734SSukumar Swaminathan 	channel = channel;
3477*82527734SSukumar Swaminathan 	iocbq = &cmd_sbp->iocbq;
3478*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3479291a2b48SSukumar Swaminathan 
3480*82527734SSukumar Swaminathan 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
3481*82527734SSukumar Swaminathan 		timeout =
3482*82527734SSukumar Swaminathan 		    ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
3483*82527734SSukumar Swaminathan 	} else {
3484*82527734SSukumar Swaminathan 		timeout = 0x80000000;
3485*82527734SSukumar Swaminathan 	}
3486291a2b48SSukumar Swaminathan 
3487*82527734SSukumar Swaminathan #ifdef FCT_API_TRACE
3488*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3489*82527734SSukumar Swaminathan 	    "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d,%d,%d",
3490*82527734SSukumar Swaminathan 	    fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length,
3491*82527734SSukumar Swaminathan 	    fct_task->task_nbytes_transferred, dbuf->db_data_size,
3492*82527734SSukumar Swaminathan 	    fct_task->task_expected_xfer_length, channel);
3493*82527734SSukumar Swaminathan #endif /* FCT_API_TRACE */
3494291a2b48SSukumar Swaminathan 
3495291a2b48SSukumar Swaminathan 
3496*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
3497*82527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, cmd_sbp);
3498291a2b48SSukumar Swaminathan 
3499*82527734SSukumar Swaminathan 	if (!iotag) {
3500*82527734SSukumar Swaminathan 		/* No more command slots available, retry later */
3501*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3502*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
35034baa2c25SSukumar Swaminathan 
3504*82527734SSukumar Swaminathan 		return (IOERR_NO_RESOURCES);
3505291a2b48SSukumar Swaminathan 	}
3506291a2b48SSukumar Swaminathan 
3507*82527734SSukumar Swaminathan 	cmd_sbp->ticks =
3508*82527734SSukumar Swaminathan 	    hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
3509291a2b48SSukumar Swaminathan 
3510*82527734SSukumar Swaminathan 	/* Initalize iocbq */
3511*82527734SSukumar Swaminathan 	iocbq->port = (void *)port;
3512*82527734SSukumar Swaminathan 	iocbq->node = (void *)ndlp;
3513291a2b48SSukumar Swaminathan 
3514291a2b48SSukumar Swaminathan 
3515*82527734SSukumar Swaminathan 	iocbq->channel = (void *)cmd_sbp->channel;
3516291a2b48SSukumar Swaminathan 
3517*82527734SSukumar Swaminathan 	if (emlxs_fct_bde_setup(port, cmd_sbp)) {
3518*82527734SSukumar Swaminathan 		/* Unregister the packet */
3519*82527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0);
3520291a2b48SSukumar Swaminathan 
3521*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3522*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3523291a2b48SSukumar Swaminathan 
3524*82527734SSukumar Swaminathan 		return (IOERR_INTERNAL_ERROR);
3525*82527734SSukumar Swaminathan 	}
3526*82527734SSukumar Swaminathan 	/* Point of no return */
3527291a2b48SSukumar Swaminathan 
3528*82527734SSukumar Swaminathan 	/* Initalize iocb */
3529*82527734SSukumar Swaminathan 	iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid;
3530*82527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
3531*82527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout);
3532*82527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
3533*82527734SSukumar Swaminathan 	iocb->ULPCLASS = cmd_sbp->class;
3534291a2b48SSukumar Swaminathan 
3535*82527734SSukumar Swaminathan 	iocb->ULPPU = 1;	/* Wd4 is relative offset */
3536*82527734SSukumar Swaminathan 	iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset;
3537291a2b48SSukumar Swaminathan 
3538*82527734SSukumar Swaminathan 	if (fct_task->task_flags & TF_WRITE_DATA) {
3539*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
3540*82527734SSukumar Swaminathan 	} else {	/* TF_READ_DATA */
3541291a2b48SSukumar Swaminathan 
3542*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
3543291a2b48SSukumar Swaminathan 
3544*82527734SSukumar Swaminathan 		if (dbuf->db_data_size ==
3545*82527734SSukumar Swaminathan 		    fct_task->task_expected_xfer_length)
3546*82527734SSukumar Swaminathan 			iocb->ULPCT = 0x1;
3547*82527734SSukumar Swaminathan 			/* enable auto-rsp AP feature */
3548*82527734SSukumar Swaminathan 	}
3549291a2b48SSukumar Swaminathan 
3550*82527734SSukumar Swaminathan 	return (IOERR_SUCCESS);
3551291a2b48SSukumar Swaminathan 
3552*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_fct_iocb() */
3553291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3554291a2b48SSukumar Swaminathan 
3555*82527734SSukumar Swaminathan /* ARGSUSED */
3556*82527734SSukumar Swaminathan static uint32_t
3557*82527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
3558*82527734SSukumar Swaminathan {
3559*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3560*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
3561*82527734SSukumar Swaminathan 	CHANNEL *cp;
3562*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3563*82527734SSukumar Swaminathan 	IOCB *iocb;
3564*82527734SSukumar Swaminathan 	NODELIST *ndlp;
3565*82527734SSukumar Swaminathan 	uint16_t iotag;
3566*82527734SSukumar Swaminathan 	uint32_t did;
3567*82527734SSukumar Swaminathan 
3568*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3569*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3570*82527734SSukumar Swaminathan 	cp = &hba->chan[FC_FCP_RING];
3571*82527734SSukumar Swaminathan 
3572*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3573*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3574*82527734SSukumar Swaminathan 
3575*82527734SSukumar Swaminathan 	/* Find target node object */
3576*82527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
3577*82527734SSukumar Swaminathan 
3578*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
3579*82527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
3580*82527734SSukumar Swaminathan 
3581*82527734SSukumar Swaminathan 	if (!iotag) {
3582*82527734SSukumar Swaminathan 		/*
3583*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
3584*82527734SSukumar Swaminathan 		 */
3585*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3586*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
3587*82527734SSukumar Swaminathan 
3588*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3589*82527734SSukumar Swaminathan 	}
3590*82527734SSukumar Swaminathan 
3591*82527734SSukumar Swaminathan 	/* Initalize iocbq */
3592*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
3593*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
3594*82527734SSukumar Swaminathan 
3595*82527734SSukumar Swaminathan 	/* Indicate this is a FCP cmd */
3596*82527734SSukumar Swaminathan 	iocbq->flag |= IOCB_FCP_CMD;
3597*82527734SSukumar Swaminathan 
3598*82527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
3599*82527734SSukumar Swaminathan 		/* Unregister the packet */
3600*82527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
3601*82527734SSukumar Swaminathan 
3602*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3603*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3604*82527734SSukumar Swaminathan 
3605*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3606*82527734SSukumar Swaminathan 	}
3607*82527734SSukumar Swaminathan 	/* Point of no return */
3608*82527734SSukumar Swaminathan 
3609*82527734SSukumar Swaminathan 	/* Initalize iocb */
3610*82527734SSukumar Swaminathan 	iocb->ULPCONTEXT = ndlp->nlp_Rpi;
3611*82527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
3612*82527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
3613*82527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3614*82527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
3615*82527734SSukumar Swaminathan 
3616*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3617*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
3618*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
3619*82527734SSukumar Swaminathan 		break;
3620*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
3621*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
3622*82527734SSukumar Swaminathan 		/* iocb->ULPCLASS = CLASS3; */
3623*82527734SSukumar Swaminathan 		break;
3624*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
3625*82527734SSukumar Swaminathan 	default:
3626*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
3627*82527734SSukumar Swaminathan 		break;
3628*82527734SSukumar Swaminathan 	}
3629*82527734SSukumar Swaminathan 
3630*82527734SSukumar Swaminathan 	/* if device is FCP-2 device, set the following bit */
3631*82527734SSukumar Swaminathan 	/* that says to run the FC-TAPE protocol. */
3632*82527734SSukumar Swaminathan 	if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
3633*82527734SSukumar Swaminathan 		iocb->ULPFCP2RCVY = 1;
3634*82527734SSukumar Swaminathan 	}
3635*82527734SSukumar Swaminathan 
3636*82527734SSukumar Swaminathan 	if (pkt->pkt_datalen == 0) {
3637*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
3638*82527734SSukumar Swaminathan 	} else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
3639*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
3640*82527734SSukumar Swaminathan 		iocb->ULPPU = PARM_READ_CHECK;
3641*82527734SSukumar Swaminathan 		iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen;
3642*82527734SSukumar Swaminathan 	} else {
3643*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
3644*82527734SSukumar Swaminathan 	}
3645*82527734SSukumar Swaminathan 
3646*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3647*82527734SSukumar Swaminathan 
3648*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_fcp_iocb() */
3649*82527734SSukumar Swaminathan 
3650*82527734SSukumar Swaminathan 
3651*82527734SSukumar Swaminathan static uint32_t
3652*82527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3653*82527734SSukumar Swaminathan {
3654*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3655*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
3656*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3657*82527734SSukumar Swaminathan 	IOCB *iocb;
3658*82527734SSukumar Swaminathan 	CHANNEL *cp;
3659*82527734SSukumar Swaminathan 	NODELIST *ndlp;
3660*82527734SSukumar Swaminathan 	uint16_t iotag;
3661*82527734SSukumar Swaminathan 	uint32_t did;
3662*82527734SSukumar Swaminathan 
3663*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3664*82527734SSukumar Swaminathan 	cp = &hba->chan[FC_IP_RING];
3665*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3666*82527734SSukumar Swaminathan 
3667*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3668*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3669*82527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
3670*82527734SSukumar Swaminathan 
3671*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
3672*82527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
3673*82527734SSukumar Swaminathan 
3674*82527734SSukumar Swaminathan 	if (!iotag) {
3675*82527734SSukumar Swaminathan 		/*
3676*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
3677*82527734SSukumar Swaminathan 		 */
3678*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3679*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
3680*82527734SSukumar Swaminathan 
3681*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3682*82527734SSukumar Swaminathan 	}
3683*82527734SSukumar Swaminathan 
3684*82527734SSukumar Swaminathan 	/* Initalize iocbq */
3685*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
3686*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
3687*82527734SSukumar Swaminathan 
3688*82527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
3689*82527734SSukumar Swaminathan 		/* Unregister the packet */
3690*82527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
3691*82527734SSukumar Swaminathan 
3692*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3693*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3694*82527734SSukumar Swaminathan 
3695*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3696*82527734SSukumar Swaminathan 	}
3697*82527734SSukumar Swaminathan 	/* Point of no return */
3698*82527734SSukumar Swaminathan 
3699*82527734SSukumar Swaminathan 	/* Initalize iocb */
3700*82527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Fctl = 0;
3701*82527734SSukumar Swaminathan 
3702*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) {
3703*82527734SSukumar Swaminathan 		iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ;
3704*82527734SSukumar Swaminathan 	}
3705*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
3706*82527734SSukumar Swaminathan 		iocb->un.xseq64.w5.hcsw.Fctl |= SI;
3707*82527734SSukumar Swaminathan 	}
3708*82527734SSukumar Swaminathan 
3709*82527734SSukumar Swaminathan 	/* network headers */
3710*82527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl;
3711*82527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
3712*82527734SSukumar Swaminathan 	iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type;
3713*82527734SSukumar Swaminathan 
3714*82527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
3715*82527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
3716*82527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3717*82527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
3718*82527734SSukumar Swaminathan 
3719*82527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_BROADCAST) {
3720*82527734SSukumar Swaminathan 		HBASTATS.IpBcastIssued++;
3721*82527734SSukumar Swaminathan 
3722*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN;
3723*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = 0;
3724*82527734SSukumar Swaminathan 
3725*82527734SSukumar Swaminathan 		if (hba->sli_mode == 3) {
3726*82527734SSukumar Swaminathan 			if (hba->topology != TOPOLOGY_LOOP) {
3727*82527734SSukumar Swaminathan 				iocb->ULPCT = 0x1;
3728*82527734SSukumar Swaminathan 			}
3729*82527734SSukumar Swaminathan 			iocb->ULPCONTEXT = port->vpi;
3730*82527734SSukumar Swaminathan 		}
3731*82527734SSukumar Swaminathan 
3732*82527734SSukumar Swaminathan 	} else {
3733*82527734SSukumar Swaminathan 		HBASTATS.IpSeqIssued++;
3734*82527734SSukumar Swaminathan 
3735*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
3736*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = ndlp->nlp_Xri;
3737*82527734SSukumar Swaminathan 	}
3738*82527734SSukumar Swaminathan 
3739*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3740*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
3741*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
3742*82527734SSukumar Swaminathan 		break;
3743*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
3744*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
3745*82527734SSukumar Swaminathan 		break;
3746*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
3747*82527734SSukumar Swaminathan 	default:
3748*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
3749*82527734SSukumar Swaminathan 		break;
3750*82527734SSukumar Swaminathan 	}
3751*82527734SSukumar Swaminathan 
3752*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3753*82527734SSukumar Swaminathan 
3754*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_ip_iocb() */
3755*82527734SSukumar Swaminathan 
3756*82527734SSukumar Swaminathan 
3757*82527734SSukumar Swaminathan static uint32_t
3758*82527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3759*82527734SSukumar Swaminathan {
3760*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3761*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
3762*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3763*82527734SSukumar Swaminathan 	IOCB *iocb;
3764*82527734SSukumar Swaminathan 	CHANNEL *cp;
3765*82527734SSukumar Swaminathan 	uint16_t iotag;
3766*82527734SSukumar Swaminathan 	uint32_t did;
3767*82527734SSukumar Swaminathan 	uint32_t cmd;
3768*82527734SSukumar Swaminathan 
3769*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3770*82527734SSukumar Swaminathan 	cp = &hba->chan[FC_ELS_RING];
3771*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3772*82527734SSukumar Swaminathan 
3773*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3774*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3775*82527734SSukumar Swaminathan 
3776*82527734SSukumar Swaminathan 
3777*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
3778*82527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
3779*82527734SSukumar Swaminathan 
3780*82527734SSukumar Swaminathan 	if (!iotag) {
3781*82527734SSukumar Swaminathan 		/*
3782*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
3783*82527734SSukumar Swaminathan 		 */
3784*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3785*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
3786*82527734SSukumar Swaminathan 
3787*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3788*82527734SSukumar Swaminathan 	}
3789*82527734SSukumar Swaminathan 	/* Initalize iocbq */
3790*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
3791*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
3792*82527734SSukumar Swaminathan 
3793*82527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
3794*82527734SSukumar Swaminathan 		/* Unregister the packet */
3795*82527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
3796*82527734SSukumar Swaminathan 
3797*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3798*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3799*82527734SSukumar Swaminathan 
3800*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3801*82527734SSukumar Swaminathan 	}
3802*82527734SSukumar Swaminathan 	/* Point of no return */
3803*82527734SSukumar Swaminathan 
3804*82527734SSukumar Swaminathan 	/* Initalize iocb */
3805*82527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
3806*82527734SSukumar Swaminathan 		/* ELS Response */
3807*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id;
3808*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
3809*82527734SSukumar Swaminathan 	} else {
3810*82527734SSukumar Swaminathan 		/* ELS Request */
3811*82527734SSukumar Swaminathan 		iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
3812*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT =
3813*82527734SSukumar Swaminathan 		    (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0;
3814*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
3815*82527734SSukumar Swaminathan 
3816*82527734SSukumar Swaminathan 		if (hba->topology != TOPOLOGY_LOOP) {
3817*82527734SSukumar Swaminathan 			cmd = *((uint32_t *)pkt->pkt_cmd);
3818*82527734SSukumar Swaminathan 			cmd &= ELS_CMD_MASK;
3819*82527734SSukumar Swaminathan 
3820*82527734SSukumar Swaminathan 			if ((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) {
3821*82527734SSukumar Swaminathan 				iocb->ULPCT = 0x2;
3822*82527734SSukumar Swaminathan 			} else {
3823*82527734SSukumar Swaminathan 				iocb->ULPCT = 0x1;
3824*82527734SSukumar Swaminathan 			}
3825*82527734SSukumar Swaminathan 		}
3826*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT = port->vpi;
3827*82527734SSukumar Swaminathan 	}
3828*82527734SSukumar Swaminathan 	iocb->ULPIOTAG = iotag;
3829*82527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
3830*82527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3831*82527734SSukumar Swaminathan 	iocb->ULPOWNER = OWN_CHIP;
3832*82527734SSukumar Swaminathan 
3833*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3834*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
3835*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
3836*82527734SSukumar Swaminathan 		break;
3837*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
3838*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
3839*82527734SSukumar Swaminathan 		break;
3840*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
3841*82527734SSukumar Swaminathan 	default:
3842*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
3843*82527734SSukumar Swaminathan 		break;
3844*82527734SSukumar Swaminathan 	}
3845*82527734SSukumar Swaminathan 	sbp->class = iocb->ULPCLASS;
3846*82527734SSukumar Swaminathan 
3847*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3848*82527734SSukumar Swaminathan 
3849*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_els_iocb() */
3850*82527734SSukumar Swaminathan 
3851*82527734SSukumar Swaminathan 
3852*82527734SSukumar Swaminathan static uint32_t
3853*82527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3854*82527734SSukumar Swaminathan {
3855*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3856*82527734SSukumar Swaminathan 	fc_packet_t *pkt;
3857*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
3858*82527734SSukumar Swaminathan 	IOCB *iocb;
3859*82527734SSukumar Swaminathan 	CHANNEL *cp;
3860*82527734SSukumar Swaminathan 	NODELIST *ndlp;
3861*82527734SSukumar Swaminathan 	uint16_t iotag;
3862*82527734SSukumar Swaminathan 	uint32_t did;
3863*82527734SSukumar Swaminathan 
3864*82527734SSukumar Swaminathan 	pkt = PRIV2PKT(sbp);
3865*82527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3866*82527734SSukumar Swaminathan 	cp = &hba->chan[FC_CT_RING];
3867*82527734SSukumar Swaminathan 
3868*82527734SSukumar Swaminathan 	iocbq = &sbp->iocbq;
3869*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
3870*82527734SSukumar Swaminathan 	ndlp = (NODELIST *)iocbq->node;
3871*82527734SSukumar Swaminathan 
3872*82527734SSukumar Swaminathan 	/* Get the iotag by registering the packet */
3873*82527734SSukumar Swaminathan 	iotag = emlxs_register_pkt(cp, sbp);
3874*82527734SSukumar Swaminathan 
3875*82527734SSukumar Swaminathan 	if (!iotag) {
3876*82527734SSukumar Swaminathan 		/*
3877*82527734SSukumar Swaminathan 		 * No more command slots available, retry later
3878*82527734SSukumar Swaminathan 		 */
3879*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3880*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
3881*82527734SSukumar Swaminathan 
3882*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3883*82527734SSukumar Swaminathan 	}
3884*82527734SSukumar Swaminathan 
3885*82527734SSukumar Swaminathan 	if (emlxs_bde_setup(port, sbp)) {
3886*82527734SSukumar Swaminathan 		/* Unregister the packet */
3887*82527734SSukumar Swaminathan 		(void) emlxs_unregister_pkt(cp, iotag, 0);
3888*82527734SSukumar Swaminathan 
3889*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3890*82527734SSukumar Swaminathan 		    "Adapter Busy. Unable to setup buffer list. did=%x", did);
3891*82527734SSukumar Swaminathan 
3892*82527734SSukumar Swaminathan 		return (FC_TRAN_BUSY);
3893*82527734SSukumar Swaminathan 	}
3894*82527734SSukumar Swaminathan 
3895*82527734SSukumar Swaminathan 	/* Point of no return */
3896*82527734SSukumar Swaminathan 
3897*82527734SSukumar Swaminathan 	/* Initalize iocbq */
3898*82527734SSukumar Swaminathan 	iocbq->port = (void *) port;
3899*82527734SSukumar Swaminathan 	iocbq->channel = (void *) cp;
3900*82527734SSukumar Swaminathan 
3901*82527734SSukumar Swaminathan 	/* Fill in rest of iocb */
3902*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Fctl = LA;
3903*82527734SSukumar Swaminathan 
3904*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
3905*82527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ;
3906*82527734SSukumar Swaminathan 	}
3907*82527734SSukumar Swaminathan 	if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
3908*82527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Fctl |= SI;
3909*82527734SSukumar Swaminathan 	}
3910*82527734SSukumar Swaminathan 
3911*82527734SSukumar Swaminathan 	/* Initalize iocb */
3912*82527734SSukumar Swaminathan 	if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
3913*82527734SSukumar Swaminathan 		/* CT Response */
3914*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
3915*82527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
3916*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT  = pkt->pkt_cmd_fhdr.rx_id;
3917*82527734SSukumar Swaminathan 	} else {
3918*82527734SSukumar Swaminathan 		/* CT Request */
3919*82527734SSukumar Swaminathan 		iocb->ULPCOMMAND  = CMD_GEN_REQUEST64_CR;
3920*82527734SSukumar Swaminathan 		iocb->un.genreq64.w5.hcsw.Dfctl = 0;
3921*82527734SSukumar Swaminathan 		iocb->ULPCONTEXT  = ndlp->nlp_Rpi;
3922*82527734SSukumar Swaminathan 	}
3923*82527734SSukumar Swaminathan 
3924*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
3925*82527734SSukumar Swaminathan 	iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
3926*82527734SSukumar Swaminathan 
3927*82527734SSukumar Swaminathan 	iocb->ULPIOTAG    = iotag;
3928*82527734SSukumar Swaminathan 	iocb->ULPRSVDBYTE =
3929*82527734SSukumar Swaminathan 	    ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3930*82527734SSukumar Swaminathan 	iocb->ULPOWNER    = OWN_CHIP;
3931*82527734SSukumar Swaminathan 
3932*82527734SSukumar Swaminathan 	switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3933*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS1:
3934*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS1;
3935*82527734SSukumar Swaminathan 		break;
3936*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS2:
3937*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS2;
3938*82527734SSukumar Swaminathan 		break;
3939*82527734SSukumar Swaminathan 	case FC_TRAN_CLASS3:
3940*82527734SSukumar Swaminathan 	default:
3941*82527734SSukumar Swaminathan 		iocb->ULPCLASS = CLASS3;
3942*82527734SSukumar Swaminathan 		break;
3943*82527734SSukumar Swaminathan 	}
3944*82527734SSukumar Swaminathan 
3945*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
3946*82527734SSukumar Swaminathan 
3947*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_ct_iocb() */
3948*82527734SSukumar Swaminathan 
3949*82527734SSukumar Swaminathan 
3950291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3951*82527734SSukumar Swaminathan static uint32_t
3952*82527734SSukumar Swaminathan emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
3953*82527734SSukumar Swaminathan {
3954*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
3955*82527734SSukumar Swaminathan 	uint32_t sgllen = 1;
3956*82527734SSukumar Swaminathan 	uint32_t rval;
3957*82527734SSukumar Swaminathan 	uint32_t size;
3958*82527734SSukumar Swaminathan 	uint32_t count;
3959*82527734SSukumar Swaminathan 	uint32_t resid;
3960*82527734SSukumar Swaminathan 	struct stmf_sglist_ent *sgl;
3961*82527734SSukumar Swaminathan 
3962*82527734SSukumar Swaminathan 	size = sbp->fct_buf->db_data_size;
3963*82527734SSukumar Swaminathan 	count = sbp->fct_buf->db_sglist_length;
3964*82527734SSukumar Swaminathan 	sgl = sbp->fct_buf->db_sglist;
3965*82527734SSukumar Swaminathan 	resid = size;
3966*82527734SSukumar Swaminathan 
3967*82527734SSukumar Swaminathan 	for (sgllen = 0; sgllen < count && resid > 0; sgllen++) {
3968*82527734SSukumar Swaminathan 		resid -= MIN(resid, sgl->seg_length);
3969*82527734SSukumar Swaminathan 		sgl++;
3970*82527734SSukumar Swaminathan 	}
3971*82527734SSukumar Swaminathan 
3972*82527734SSukumar Swaminathan 	if (resid > 0) {
3973*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
3974*82527734SSukumar Swaminathan 		    "emlxs_fct_bde_setup: Not enough scatter gather buffers "
3975*82527734SSukumar Swaminathan 		    " size=%d resid=%d count=%d",
3976*82527734SSukumar Swaminathan 		    size, resid, count);
3977*82527734SSukumar Swaminathan 		return (1);
3978*82527734SSukumar Swaminathan 	}
3979*82527734SSukumar Swaminathan 
3980*82527734SSukumar Swaminathan 	if ((hba->sli_mode < 3) || (sgllen > SLI3_MAX_BDE)) {
3981*82527734SSukumar Swaminathan 		rval = emlxs_sli2_fct_bde_setup(port, sbp);
3982*82527734SSukumar Swaminathan 	} else {
3983*82527734SSukumar Swaminathan 		rval = emlxs_sli3_fct_bde_setup(port, sbp);
3984*82527734SSukumar Swaminathan 	}
3985*82527734SSukumar Swaminathan 
3986*82527734SSukumar Swaminathan 	return (rval);
3987*82527734SSukumar Swaminathan 
3988*82527734SSukumar Swaminathan } /* emlxs_fct_bde_setup() */
3989291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3990291a2b48SSukumar Swaminathan 
3991*82527734SSukumar Swaminathan static uint32_t
3992*82527734SSukumar Swaminathan emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
3993*82527734SSukumar Swaminathan {
3994*82527734SSukumar Swaminathan 	uint32_t	rval;
3995*82527734SSukumar Swaminathan 	emlxs_hba_t	*hba = HBA;
3996*82527734SSukumar Swaminathan 
3997*82527734SSukumar Swaminathan 	if (hba->sli_mode < 3) {
3998*82527734SSukumar Swaminathan 		rval = emlxs_sli2_bde_setup(port, sbp);
3999*82527734SSukumar Swaminathan 	} else {
4000*82527734SSukumar Swaminathan 		rval = emlxs_sli3_bde_setup(port, sbp);
4001*82527734SSukumar Swaminathan 	}
4002*82527734SSukumar Swaminathan 
4003*82527734SSukumar Swaminathan 	return (rval);
4004*82527734SSukumar Swaminathan 
4005*82527734SSukumar Swaminathan } /* emlxs_bde_setup() */
4006*82527734SSukumar Swaminathan 
4007*82527734SSukumar Swaminathan 
4008*82527734SSukumar Swaminathan static void
4009*82527734SSukumar Swaminathan emlxs_sli3_poll_intr(emlxs_hba_t *hba, uint32_t att_bit)
4010*82527734SSukumar Swaminathan {
4011*82527734SSukumar Swaminathan 	uint32_t ha_copy;
4012*82527734SSukumar Swaminathan 
4013*82527734SSukumar Swaminathan 	/*
4014*82527734SSukumar Swaminathan 	 * Polling a specific attention bit.
4015*82527734SSukumar Swaminathan 	 */
4016*82527734SSukumar Swaminathan 	for (;;) {
4017*82527734SSukumar Swaminathan 		ha_copy = emlxs_check_attention(hba);
4018*82527734SSukumar Swaminathan 
4019*82527734SSukumar Swaminathan 		if (ha_copy & att_bit) {
4020*82527734SSukumar Swaminathan 			break;
4021*82527734SSukumar Swaminathan 		}
4022*82527734SSukumar Swaminathan 
4023*82527734SSukumar Swaminathan 	}
4024*82527734SSukumar Swaminathan 
4025*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4026*82527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, -1);
4027*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4028*82527734SSukumar Swaminathan 
4029*82527734SSukumar Swaminathan 	/* Process the attentions */
4030*82527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
4031*82527734SSukumar Swaminathan 
4032*82527734SSukumar Swaminathan 	return;
4033*82527734SSukumar Swaminathan 
4034*82527734SSukumar Swaminathan } /* emlxs_sli3_poll_intr() */
4035*82527734SSukumar Swaminathan 
4036*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
4037*82527734SSukumar Swaminathan static uint32_t
4038*82527734SSukumar Swaminathan emlxs_sli3_msi_intr(char *arg1, char *arg2)
4039*82527734SSukumar Swaminathan {
4040*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
4041*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4042*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4043*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4044*82527734SSukumar Swaminathan 	uint16_t msgid;
4045*82527734SSukumar Swaminathan 	uint32_t hc_copy;
4046*82527734SSukumar Swaminathan 	uint32_t ha_copy;
4047*82527734SSukumar Swaminathan 	uint32_t restore = 0;
4048291a2b48SSukumar Swaminathan 
4049*82527734SSukumar Swaminathan 	/*
4050*82527734SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
4051*82527734SSukumar Swaminathan 	 * "emlxs_sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2);
4052*82527734SSukumar Swaminathan 	 */
4053291a2b48SSukumar Swaminathan 
4054*82527734SSukumar Swaminathan 	/* Check for legacy interrupt handling */
4055*82527734SSukumar Swaminathan 	if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
4056*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
4057291a2b48SSukumar Swaminathan 
4058*82527734SSukumar Swaminathan 		if (hba->flag & FC_OFFLINE_MODE) {
4059*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
4060291a2b48SSukumar Swaminathan 
4061*82527734SSukumar Swaminathan 			if (hba->bus_type == SBUS_FC) {
4062*82527734SSukumar Swaminathan 				return (DDI_INTR_CLAIMED);
4063*82527734SSukumar Swaminathan 			} else {
4064*82527734SSukumar Swaminathan 				return (DDI_INTR_UNCLAIMED);
4065*82527734SSukumar Swaminathan 			}
4066291a2b48SSukumar Swaminathan 		}
4067291a2b48SSukumar Swaminathan 
4068*82527734SSukumar Swaminathan 		/* Get host attention bits */
4069*82527734SSukumar Swaminathan 		ha_copy = emlxs_get_attention(hba, -1);
4070291a2b48SSukumar Swaminathan 
4071*82527734SSukumar Swaminathan 		if (ha_copy == 0) {
4072*82527734SSukumar Swaminathan 			if (hba->intr_unclaimed) {
4073*82527734SSukumar Swaminathan 				mutex_exit(&EMLXS_PORT_LOCK);
4074*82527734SSukumar Swaminathan 				return (DDI_INTR_UNCLAIMED);
4075*82527734SSukumar Swaminathan 			}
4076291a2b48SSukumar Swaminathan 
4077*82527734SSukumar Swaminathan 			hba->intr_unclaimed = 1;
4078*82527734SSukumar Swaminathan 		} else {
4079*82527734SSukumar Swaminathan 			hba->intr_unclaimed = 0;
4080291a2b48SSukumar Swaminathan 		}
4081291a2b48SSukumar Swaminathan 
4082*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4083291a2b48SSukumar Swaminathan 
4084*82527734SSukumar Swaminathan 		/* Process the interrupt */
4085*82527734SSukumar Swaminathan 		emlxs_proc_attention(hba, ha_copy);
4086291a2b48SSukumar Swaminathan 
4087*82527734SSukumar Swaminathan 		return (DDI_INTR_CLAIMED);
4088*82527734SSukumar Swaminathan 	}
4089291a2b48SSukumar Swaminathan 
4090*82527734SSukumar Swaminathan 	/* DDI_INTR_TYPE_MSI  */
4091*82527734SSukumar Swaminathan 	/* DDI_INTR_TYPE_MSIX */
4092291a2b48SSukumar Swaminathan 
4093*82527734SSukumar Swaminathan 	/* Get MSI message id */
4094*82527734SSukumar Swaminathan 	msgid = (uint16_t)((unsigned long)arg2);
4095291a2b48SSukumar Swaminathan 
4096*82527734SSukumar Swaminathan 	/* Validate the message id */
4097*82527734SSukumar Swaminathan 	if (msgid >= hba->intr_count) {
4098*82527734SSukumar Swaminathan 		msgid = 0;
4099*82527734SSukumar Swaminathan 	}
4100291a2b48SSukumar Swaminathan 
4101*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_INTR_LOCK(msgid));
4102291a2b48SSukumar Swaminathan 
4103*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4104*82527734SSukumar Swaminathan 
4105*82527734SSukumar Swaminathan 	/* Check if adapter is offline */
4106*82527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
4107*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4108*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_INTR_LOCK(msgid));
4109*82527734SSukumar Swaminathan 
4110*82527734SSukumar Swaminathan 		/* Always claim an MSI interrupt */
4111*82527734SSukumar Swaminathan 		return (DDI_INTR_CLAIMED);
4112*82527734SSukumar Swaminathan 	}
4113*82527734SSukumar Swaminathan 
4114*82527734SSukumar Swaminathan 	/* Disable interrupts associated with this msgid */
4115*82527734SSukumar Swaminathan 	if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) {
4116*82527734SSukumar Swaminathan 		hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask;
4117*82527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy);
4118*82527734SSukumar Swaminathan 		restore = 1;
4119*82527734SSukumar Swaminathan 	}
4120*82527734SSukumar Swaminathan 
4121*82527734SSukumar Swaminathan 	/* Get host attention bits */
4122*82527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, msgid);
4123*82527734SSukumar Swaminathan 
4124*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4125*82527734SSukumar Swaminathan 
4126*82527734SSukumar Swaminathan 	/* Process the interrupt */
4127*82527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
4128*82527734SSukumar Swaminathan 
4129*82527734SSukumar Swaminathan 	/* Restore interrupts */
4130*82527734SSukumar Swaminathan 	if (restore) {
4131*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
4132*82527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
4133*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4134*82527734SSukumar Swaminathan 		/* Access handle validation */
4135*82527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4136*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4137*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4138*82527734SSukumar Swaminathan 	}
4139*82527734SSukumar Swaminathan 
4140*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_INTR_LOCK(msgid));
4141*82527734SSukumar Swaminathan 
4142*82527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
4143*82527734SSukumar Swaminathan 
4144*82527734SSukumar Swaminathan } /* emlxs_sli3_msi_intr() */
4145*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
4146*82527734SSukumar Swaminathan 
4147*82527734SSukumar Swaminathan 
4148*82527734SSukumar Swaminathan static int
4149*82527734SSukumar Swaminathan emlxs_sli3_intx_intr(char *arg)
4150*82527734SSukumar Swaminathan {
4151*82527734SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
4152*82527734SSukumar Swaminathan 	uint32_t ha_copy = 0;
4153*82527734SSukumar Swaminathan 
4154*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
4155*82527734SSukumar Swaminathan 
4156*82527734SSukumar Swaminathan 	if (hba->flag & FC_OFFLINE_MODE) {
4157*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
4158*82527734SSukumar Swaminathan 
4159*82527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
4160*82527734SSukumar Swaminathan 			return (DDI_INTR_CLAIMED);
4161*82527734SSukumar Swaminathan 		} else {
4162*82527734SSukumar Swaminathan 			return (DDI_INTR_UNCLAIMED);
4163291a2b48SSukumar Swaminathan 		}
4164*82527734SSukumar Swaminathan 	}
4165291a2b48SSukumar Swaminathan 
4166*82527734SSukumar Swaminathan 	/* Get host attention bits */
4167*82527734SSukumar Swaminathan 	ha_copy = emlxs_get_attention(hba, -1);
4168291a2b48SSukumar Swaminathan 
4169*82527734SSukumar Swaminathan 	if (ha_copy == 0) {
4170*82527734SSukumar Swaminathan 		if (hba->intr_unclaimed) {
4171*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
4172*82527734SSukumar Swaminathan 			return (DDI_INTR_UNCLAIMED);
4173291a2b48SSukumar Swaminathan 		}
4174291a2b48SSukumar Swaminathan 
4175*82527734SSukumar Swaminathan 		hba->intr_unclaimed = 1;
4176*82527734SSukumar Swaminathan 	} else {
4177*82527734SSukumar Swaminathan 		hba->intr_unclaimed = 0;
4178*82527734SSukumar Swaminathan 	}
4179*82527734SSukumar Swaminathan 
4180*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
4181*82527734SSukumar Swaminathan 
4182*82527734SSukumar Swaminathan 	/* Process the interrupt */
4183*82527734SSukumar Swaminathan 	emlxs_proc_attention(hba, ha_copy);
4184*82527734SSukumar Swaminathan 
4185*82527734SSukumar Swaminathan 	return (DDI_INTR_CLAIMED);
4186*82527734SSukumar Swaminathan 
4187*82527734SSukumar Swaminathan } /* emlxs_sli3_intx_intr() */
4188*82527734SSukumar Swaminathan 
4189*82527734SSukumar Swaminathan 
4190*82527734SSukumar Swaminathan /* EMLXS_PORT_LOCK must be held when call this routine */
4191*82527734SSukumar Swaminathan static uint32_t
4192*82527734SSukumar Swaminathan emlxs_get_attention(emlxs_hba_t *hba, uint32_t msgid)
4193*82527734SSukumar Swaminathan {
4194*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4195*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4196*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4197*82527734SSukumar Swaminathan 	uint32_t ha_copy = 0;
4198*82527734SSukumar Swaminathan 	uint32_t ha_copy2;
4199*82527734SSukumar Swaminathan 	uint32_t mask = hba->sli.sli3.hc_copy;
4200*82527734SSukumar Swaminathan 
4201*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT
4202*82527734SSukumar Swaminathan 
4203*82527734SSukumar Swaminathan read_ha_register:
4204*82527734SSukumar Swaminathan 
4205*82527734SSukumar Swaminathan 	/* Check for default MSI interrupt */
4206*82527734SSukumar Swaminathan 	if (msgid == 0) {
4207*82527734SSukumar Swaminathan 		/* Read host attention register to determine interrupt source */
4208*82527734SSukumar Swaminathan 		ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4209*82527734SSukumar Swaminathan 
4210*82527734SSukumar Swaminathan 		/* Filter out MSI non-default attention bits */
4211*82527734SSukumar Swaminathan 		ha_copy2 &= ~(hba->intr_cond);
4212*82527734SSukumar Swaminathan 	}
4213*82527734SSukumar Swaminathan 
4214*82527734SSukumar Swaminathan 	/* Check for polled or fixed type interrupt */
4215*82527734SSukumar Swaminathan 	else if (msgid == -1) {
4216*82527734SSukumar Swaminathan 		/* Read host attention register to determine interrupt source */
4217*82527734SSukumar Swaminathan 		ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4218*82527734SSukumar Swaminathan 	}
4219*82527734SSukumar Swaminathan 
4220*82527734SSukumar Swaminathan 	/* Otherwise, assume a mapped MSI interrupt */
4221*82527734SSukumar Swaminathan 	else {
4222*82527734SSukumar Swaminathan 		/* Convert MSI msgid to mapped attention bits */
4223*82527734SSukumar Swaminathan 		ha_copy2 = hba->intr_map[msgid];
4224*82527734SSukumar Swaminathan 	}
4225*82527734SSukumar Swaminathan 
4226*82527734SSukumar Swaminathan #else /* !MSI_SUPPORT */
4227*82527734SSukumar Swaminathan 
4228*82527734SSukumar Swaminathan 	/* Read host attention register to determine interrupt source */
4229*82527734SSukumar Swaminathan 	ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4230*82527734SSukumar Swaminathan 
4231*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */
4232*82527734SSukumar Swaminathan 
4233*82527734SSukumar Swaminathan 	/* Check if Hardware error interrupt is enabled */
4234*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) {
4235*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_ERATT;
4236*82527734SSukumar Swaminathan 	}
4237*82527734SSukumar Swaminathan 
4238*82527734SSukumar Swaminathan 	/* Check if link interrupt is enabled */
4239*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) {
4240*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_LATT;
4241*82527734SSukumar Swaminathan 	}
4242*82527734SSukumar Swaminathan 
4243*82527734SSukumar Swaminathan 	/* Check if Mailbox interrupt is enabled */
4244*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) {
4245*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_MBATT;
4246*82527734SSukumar Swaminathan 	}
4247*82527734SSukumar Swaminathan 
4248*82527734SSukumar Swaminathan 	/* Check if ring0 interrupt is enabled */
4249*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) {
4250*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R0ATT;
4251*82527734SSukumar Swaminathan 	}
4252*82527734SSukumar Swaminathan 
4253*82527734SSukumar Swaminathan 	/* Check if ring1 interrupt is enabled */
4254*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) {
4255*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R1ATT;
4256*82527734SSukumar Swaminathan 	}
4257*82527734SSukumar Swaminathan 
4258*82527734SSukumar Swaminathan 	/* Check if ring2 interrupt is enabled */
4259*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) {
4260*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R2ATT;
4261*82527734SSukumar Swaminathan 	}
4262*82527734SSukumar Swaminathan 
4263*82527734SSukumar Swaminathan 	/* Check if ring3 interrupt is enabled */
4264*82527734SSukumar Swaminathan 	if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) {
4265*82527734SSukumar Swaminathan 		ha_copy2 &= ~HA_R3ATT;
4266*82527734SSukumar Swaminathan 	}
4267291a2b48SSukumar Swaminathan 
4268*82527734SSukumar Swaminathan 	/* Accumulate attention bits */
4269*82527734SSukumar Swaminathan 	ha_copy |= ha_copy2;
4270291a2b48SSukumar Swaminathan 
4271*82527734SSukumar Swaminathan 	/* Clear attentions except for error, link, and autoclear(MSIX) */
4272*82527734SSukumar Swaminathan 	ha_copy2 &= ~(HA_ERATT | HA_LATT);	/* | hba->intr_autoClear */
4273291a2b48SSukumar Swaminathan 
4274*82527734SSukumar Swaminathan 	if (ha_copy2) {
4275*82527734SSukumar Swaminathan 		WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2);
4276*82527734SSukumar Swaminathan 	}
4277291a2b48SSukumar Swaminathan 
42784baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
4279*82527734SSukumar Swaminathan 	/* Access handle validation */
4280*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
42814baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4282291a2b48SSukumar Swaminathan 
4283*82527734SSukumar Swaminathan 	return (ha_copy);
4284291a2b48SSukumar Swaminathan 
4285*82527734SSukumar Swaminathan } /* emlxs_get_attention() */
4286291a2b48SSukumar Swaminathan 
4287291a2b48SSukumar Swaminathan 
4288*82527734SSukumar Swaminathan static void
4289*82527734SSukumar Swaminathan emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy)
4290*82527734SSukumar Swaminathan {
42914baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
4292*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
42934baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
42944baa2c25SSukumar Swaminathan 
4295*82527734SSukumar Swaminathan 	/* ha_copy should be pre-filtered */
4296291a2b48SSukumar Swaminathan 
4297*82527734SSukumar Swaminathan 	/*
4298*82527734SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4299*82527734SSukumar Swaminathan 	 * "emlxs_proc_attention: ha_copy=%x", ha_copy);
4300*82527734SSukumar Swaminathan 	 */
4301291a2b48SSukumar Swaminathan 
4302*82527734SSukumar Swaminathan 	if (hba->state < FC_WARM_START) {
4303*82527734SSukumar Swaminathan 		return;
4304291a2b48SSukumar Swaminathan 	}
4305291a2b48SSukumar Swaminathan 
4306*82527734SSukumar Swaminathan 	if (!ha_copy) {
4307*82527734SSukumar Swaminathan 		return;
4308*82527734SSukumar Swaminathan 	}
4309291a2b48SSukumar Swaminathan 
4310*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
4311*82527734SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
4312*82527734SSukumar Swaminathan 	}
4313291a2b48SSukumar Swaminathan 
4314*82527734SSukumar Swaminathan 	/* Adapter error */
4315*82527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
4316*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[6]++;
4317*82527734SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
4318*82527734SSukumar Swaminathan 		return;
4319*82527734SSukumar Swaminathan 	}
4320291a2b48SSukumar Swaminathan 
4321*82527734SSukumar Swaminathan 	/* Mailbox interrupt */
4322*82527734SSukumar Swaminathan 	if (ha_copy & HA_MBATT) {
4323*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[5]++;
4324*82527734SSukumar Swaminathan 		(void) emlxs_handle_mb_event(hba);
4325*82527734SSukumar Swaminathan 	}
4326291a2b48SSukumar Swaminathan 
4327*82527734SSukumar Swaminathan 	/* Link Attention interrupt */
4328*82527734SSukumar Swaminathan 	if (ha_copy & HA_LATT) {
4329*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[4]++;
4330*82527734SSukumar Swaminathan 		emlxs_sli3_handle_link_event(hba);
4331*82527734SSukumar Swaminathan 	}
4332291a2b48SSukumar Swaminathan 
4333*82527734SSukumar Swaminathan 	/* event on ring 0 - FCP Ring */
4334*82527734SSukumar Swaminathan 	if (ha_copy & HA_R0ATT) {
4335*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[0]++;
4336*82527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 0, ha_copy);
4337*82527734SSukumar Swaminathan 	}
4338291a2b48SSukumar Swaminathan 
4339*82527734SSukumar Swaminathan 	/* event on ring 1 - IP Ring */
4340*82527734SSukumar Swaminathan 	if (ha_copy & HA_R1ATT) {
4341*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[1]++;
4342*82527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 1, ha_copy);
4343*82527734SSukumar Swaminathan 	}
4344291a2b48SSukumar Swaminathan 
4345*82527734SSukumar Swaminathan 	/* event on ring 2 - ELS Ring */
4346*82527734SSukumar Swaminathan 	if (ha_copy & HA_R2ATT) {
4347*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[2]++;
4348*82527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 2, ha_copy);
4349*82527734SSukumar Swaminathan 	}
4350291a2b48SSukumar Swaminathan 
4351*82527734SSukumar Swaminathan 	/* event on ring 3 - CT Ring */
4352*82527734SSukumar Swaminathan 	if (ha_copy & HA_R3ATT) {
4353*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[3]++;
4354*82527734SSukumar Swaminathan 		emlxs_sli3_handle_ring_event(hba, 3, ha_copy);
4355*82527734SSukumar Swaminathan 	}
4356291a2b48SSukumar Swaminathan 
4357*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
4358*82527734SSukumar Swaminathan 		WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP);
4359291a2b48SSukumar Swaminathan 	}
4360291a2b48SSukumar Swaminathan 
4361*82527734SSukumar Swaminathan 	/* Set heartbeat flag to show activity */
4362*82527734SSukumar Swaminathan 	hba->heartbeat_flag = 1;
4363291a2b48SSukumar Swaminathan 
4364*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4365*82527734SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
4366*82527734SSukumar Swaminathan 		/* Access handle validation */
4367*82527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle);
4368291a2b48SSukumar Swaminathan 	}
4369*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4370291a2b48SSukumar Swaminathan 
4371*82527734SSukumar Swaminathan 	return;
4372291a2b48SSukumar Swaminathan 
4373*82527734SSukumar Swaminathan } /* emlxs_proc_attention() */
4374291a2b48SSukumar Swaminathan 
4375291a2b48SSukumar Swaminathan 
4376*82527734SSukumar Swaminathan /*
4377*82527734SSukumar Swaminathan  * emlxs_handle_ff_error()
4378*82527734SSukumar Swaminathan  *
4379*82527734SSukumar Swaminathan  *    Description: Processes a FireFly error
4380*82527734SSukumar Swaminathan  *    Runs at Interrupt level
4381*82527734SSukumar Swaminathan  */
4382*82527734SSukumar Swaminathan static void
4383*82527734SSukumar Swaminathan emlxs_handle_ff_error(emlxs_hba_t *hba)
4384*82527734SSukumar Swaminathan {
4385*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4386*82527734SSukumar Swaminathan 	uint32_t status;
4387*82527734SSukumar Swaminathan 	uint32_t status1;
4388*82527734SSukumar Swaminathan 	uint32_t status2;
4389*82527734SSukumar Swaminathan 	int i = 0;
4390291a2b48SSukumar Swaminathan 
4391*82527734SSukumar Swaminathan 	/* do what needs to be done, get error from STATUS REGISTER */
4392*82527734SSukumar Swaminathan 	status = READ_CSR_REG(hba, FC_HS_REG(hba));
4393291a2b48SSukumar Swaminathan 
4394*82527734SSukumar Swaminathan 	/* Clear Chip error bit */
4395*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT);
4396291a2b48SSukumar Swaminathan 
4397*82527734SSukumar Swaminathan 	/* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */
4398*82527734SSukumar Swaminathan 	if (status & HS_FFER1) {
4399*82527734SSukumar Swaminathan 
4400*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4401*82527734SSukumar Swaminathan 		    "HS_FFER1 received");
4402*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4403*82527734SSukumar Swaminathan 		(void) emlxs_offline(hba);
4404*82527734SSukumar Swaminathan 		while ((status & HS_FFER1) && (i < 300)) {
4405*82527734SSukumar Swaminathan 			status =
4406*82527734SSukumar Swaminathan 			    READ_CSR_REG(hba, FC_HS_REG(hba));
4407*82527734SSukumar Swaminathan 			DELAYMS(1000);
4408*82527734SSukumar Swaminathan 			i++;
4409291a2b48SSukumar Swaminathan 		}
4410*82527734SSukumar Swaminathan 	}
4411291a2b48SSukumar Swaminathan 
4412*82527734SSukumar Swaminathan 	if (i == 300) {
4413*82527734SSukumar Swaminathan 		/* 5 minutes is up, shutdown HBA */
4414*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4415*82527734SSukumar Swaminathan 		    "HS_FFER1 clear timeout");
4416291a2b48SSukumar Swaminathan 
4417*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4418*82527734SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
4419291a2b48SSukumar Swaminathan 
4420*82527734SSukumar Swaminathan 		goto done;
4421291a2b48SSukumar Swaminathan 	}
4422291a2b48SSukumar Swaminathan 
4423*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4424*82527734SSukumar Swaminathan 	    "HS_FFER1 cleared");
4425*82527734SSukumar Swaminathan 
4426*82527734SSukumar Swaminathan 	if (status & HS_OVERTEMP) {
4427*82527734SSukumar Swaminathan 		status1 =
4428*82527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
4429*82527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0));
4430*82527734SSukumar Swaminathan 
4431*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4432*82527734SSukumar Swaminathan 		    "Maximum adapter temperature exceeded (%d �C).", status1);
4433*82527734SSukumar Swaminathan 
4434*82527734SSukumar Swaminathan 		hba->temperature = status1;
4435*82527734SSukumar Swaminathan 		hba->flag |= FC_OVERTEMP_EVENT;
4436*82527734SSukumar Swaminathan 
4437*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4438*82527734SSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_shutdown_thread,
4439*82527734SSukumar Swaminathan 		    NULL, NULL);
4440*82527734SSukumar Swaminathan 
4441*82527734SSukumar Swaminathan 	} else {
4442*82527734SSukumar Swaminathan 		status1 =
4443*82527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
4444*82527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8));
4445*82527734SSukumar Swaminathan 		status2 =
4446*82527734SSukumar Swaminathan 		    READ_SLIM_ADDR(hba,
4447*82527734SSukumar Swaminathan 		    ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac));
4448*82527734SSukumar Swaminathan 
4449*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4450*82527734SSukumar Swaminathan 		    "Host Error Attention: "
4451*82527734SSukumar Swaminathan 		    "status=0x%x status1=0x%x status2=0x%x",
4452*82527734SSukumar Swaminathan 		    status, status1, status2);
4453*82527734SSukumar Swaminathan 
4454*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
4455291a2b48SSukumar Swaminathan 
4456*82527734SSukumar Swaminathan 		if (status & HS_FFER6) {
4457*82527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_restart_thread,
4458*82527734SSukumar Swaminathan 			    NULL, NULL);
4459*82527734SSukumar Swaminathan 		} else {
4460*82527734SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_shutdown_thread,
4461*82527734SSukumar Swaminathan 			    NULL, NULL);
4462291a2b48SSukumar Swaminathan 		}
4463291a2b48SSukumar Swaminathan 	}
4464291a2b48SSukumar Swaminathan 
4465*82527734SSukumar Swaminathan done:
4466*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4467*82527734SSukumar Swaminathan 	/* Access handle validation */
4468*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
4469*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4470*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4471291a2b48SSukumar Swaminathan 
4472*82527734SSukumar Swaminathan 	return;
4473291a2b48SSukumar Swaminathan 
4474*82527734SSukumar Swaminathan } /* emlxs_handle_ff_error() */
4475291a2b48SSukumar Swaminathan 
4476291a2b48SSukumar Swaminathan 
4477*82527734SSukumar Swaminathan /*
4478*82527734SSukumar Swaminathan  *  emlxs_sli3_handle_link_event()
4479*82527734SSukumar Swaminathan  *
4480*82527734SSukumar Swaminathan  *    Description: Process a Link Attention.
4481*82527734SSukumar Swaminathan  */
4482*82527734SSukumar Swaminathan static void
4483*82527734SSukumar Swaminathan emlxs_sli3_handle_link_event(emlxs_hba_t *hba)
4484*82527734SSukumar Swaminathan {
4485*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4486*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
4487*82527734SSukumar Swaminathan 	int rc;
4488291a2b48SSukumar Swaminathan 
4489*82527734SSukumar Swaminathan 	HBASTATS.LinkEvent++;
4490291a2b48SSukumar Swaminathan 
4491*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x",
4492*82527734SSukumar Swaminathan 	    HBASTATS.LinkEvent);
4493291a2b48SSukumar Swaminathan 
4494*82527734SSukumar Swaminathan 	/* Make sure link is declared down */
4495*82527734SSukumar Swaminathan 	emlxs_linkdown(hba);
4496291a2b48SSukumar Swaminathan 
4497291a2b48SSukumar Swaminathan 
4498*82527734SSukumar Swaminathan 	/* Get a buffer which will be used for mailbox commands */
4499*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
4500*82527734SSukumar Swaminathan 		/* Get link attention message */
4501*82527734SSukumar Swaminathan 		if (emlxs_mb_read_la(hba, mbq) == 0) {
4502*82527734SSukumar Swaminathan 			rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq,
4503*82527734SSukumar Swaminathan 			    MBX_NOWAIT, 0);
4504*82527734SSukumar Swaminathan 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
4505*82527734SSukumar Swaminathan 				(void) emlxs_mem_put(hba, MEM_MBOX,
4506*82527734SSukumar Swaminathan 				    (uint8_t *)mbq);
4507*82527734SSukumar Swaminathan 			}
4508291a2b48SSukumar Swaminathan 
4509*82527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
4510291a2b48SSukumar Swaminathan 
4511291a2b48SSukumar Swaminathan 
4512*82527734SSukumar Swaminathan 			/*
4513*82527734SSukumar Swaminathan 			 * Clear Link Attention in HA REG
4514*82527734SSukumar Swaminathan 			 */
4515*82527734SSukumar Swaminathan 			WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT);
4516291a2b48SSukumar Swaminathan 
4517*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4518*82527734SSukumar Swaminathan 			/* Access handle validation */
4519*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4520*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4521291a2b48SSukumar Swaminathan 
4522*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
4523*82527734SSukumar Swaminathan 		} else {
4524*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
4525291a2b48SSukumar Swaminathan 		}
4526291a2b48SSukumar Swaminathan 	}
4527291a2b48SSukumar Swaminathan 
4528*82527734SSukumar Swaminathan } /* emlxs_sli3_handle_link_event()  */
4529291a2b48SSukumar Swaminathan 
4530291a2b48SSukumar Swaminathan 
4531*82527734SSukumar Swaminathan /*
4532*82527734SSukumar Swaminathan  *  emlxs_sli3_handle_ring_event()
4533*82527734SSukumar Swaminathan  *
4534*82527734SSukumar Swaminathan  *    Description: Process a Ring Attention.
4535*82527734SSukumar Swaminathan  */
4536291a2b48SSukumar Swaminathan static void
4537*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
4538*82527734SSukumar Swaminathan     uint32_t ha_copy)
4539291a2b48SSukumar Swaminathan {
4540*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4541*82527734SSukumar Swaminathan 	SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
4542*82527734SSukumar Swaminathan 	CHANNEL *cp;
4543*82527734SSukumar Swaminathan 	RING *rp;
4544*82527734SSukumar Swaminathan 	IOCB *entry;
4545*82527734SSukumar Swaminathan 	IOCBQ *iocbq;
4546*82527734SSukumar Swaminathan 	IOCBQ local_iocbq;
4547*82527734SSukumar Swaminathan 	PGP *pgp;
4548*82527734SSukumar Swaminathan 	uint32_t count;
4549*82527734SSukumar Swaminathan 	volatile uint32_t chipatt;
4550*82527734SSukumar Swaminathan 	void *ioa2;
4551*82527734SSukumar Swaminathan 	uint32_t reg;
4552*82527734SSukumar Swaminathan 	uint32_t channel_no;
4553291a2b48SSukumar Swaminathan 	off_t offset;
4554*82527734SSukumar Swaminathan 	IOCBQ *rsp_head = NULL;
4555*82527734SSukumar Swaminathan 	IOCBQ *rsp_tail = NULL;
4556*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp = NULL;
4557291a2b48SSukumar Swaminathan 
4558*82527734SSukumar Swaminathan 	count = 0;
4559*82527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[ring_no];
4560*82527734SSukumar Swaminathan 	cp = rp->channelp;
4561*82527734SSukumar Swaminathan 	channel_no = cp->channelno;
4562291a2b48SSukumar Swaminathan 
4563*82527734SSukumar Swaminathan 	/*
4564*82527734SSukumar Swaminathan 	 * Isolate this ring's host attention bits
4565*82527734SSukumar Swaminathan 	 * This makes all ring attention bits equal
4566*82527734SSukumar Swaminathan 	 * to Ring0 attention bits
4567*82527734SSukumar Swaminathan 	 */
4568*82527734SSukumar Swaminathan 	reg = (ha_copy >> (ring_no * 4)) & 0x0f;
4569291a2b48SSukumar Swaminathan 
4570*82527734SSukumar Swaminathan 	/*
4571*82527734SSukumar Swaminathan 	 * Gather iocb entries off response ring.
4572*82527734SSukumar Swaminathan 	 * Ensure entry is owned by the host.
4573*82527734SSukumar Swaminathan 	 */
4574*82527734SSukumar Swaminathan 	pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no];
4575*82527734SSukumar Swaminathan 	offset =
4576*82527734SSukumar Swaminathan 	    (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) -
4577*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)slim2p));
4578*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
4579*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
4580*82527734SSukumar Swaminathan 	rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx);
4581291a2b48SSukumar Swaminathan 
4582*82527734SSukumar Swaminathan 	/* While ring is not empty */
4583*82527734SSukumar Swaminathan 	while (rp->fc_rspidx != rp->fc_port_rspidx) {
4584*82527734SSukumar Swaminathan 		HBASTATS.IocbReceived[channel_no]++;
4585291a2b48SSukumar Swaminathan 
4586*82527734SSukumar Swaminathan 		/* Get the next response ring iocb */
4587*82527734SSukumar Swaminathan 		entry =
4588*82527734SSukumar Swaminathan 		    (IOCB *)(((char *)rp->fc_rspringaddr +
4589*82527734SSukumar Swaminathan 		    (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size)));
4590291a2b48SSukumar Swaminathan 
4591*82527734SSukumar Swaminathan 		/* DMA sync the response ring iocb for the adapter */
4592*82527734SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)entry)
4593*82527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)slim2p));
4594*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
4595*82527734SSukumar Swaminathan 		    hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL);
4596291a2b48SSukumar Swaminathan 
4597*82527734SSukumar Swaminathan 		count++;
4598291a2b48SSukumar Swaminathan 
4599*82527734SSukumar Swaminathan 		/* Copy word6 and word7 to local iocb for now */
4600*82527734SSukumar Swaminathan 		iocbq = &local_iocbq;
4601291a2b48SSukumar Swaminathan 
4602*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6),
4603*82527734SSukumar Swaminathan 		    (uint8_t *)iocbq + (sizeof (uint32_t) * 6),
4604*82527734SSukumar Swaminathan 		    (sizeof (uint32_t) * 2));
4605291a2b48SSukumar Swaminathan 
4606*82527734SSukumar Swaminathan 		/* when LE is not set, entire Command has not been received */
4607*82527734SSukumar Swaminathan 		if (!iocbq->iocb.ULPLE) {
4608*82527734SSukumar Swaminathan 			/* This should never happen */
4609*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg,
4610*82527734SSukumar Swaminathan 			    "ulpLE is not set. "
4611*82527734SSukumar Swaminathan 			    "ring=%d iotag=%x cmd=%x status=%x",
4612*82527734SSukumar Swaminathan 			    channel_no, iocbq->iocb.ULPIOTAG,
4613*82527734SSukumar Swaminathan 			    iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS);
4614291a2b48SSukumar Swaminathan 
4615*82527734SSukumar Swaminathan 			goto next;
4616291a2b48SSukumar Swaminathan 		}
4617291a2b48SSukumar Swaminathan 
4618*82527734SSukumar Swaminathan 		switch (iocbq->iocb.ULPCOMMAND) {
4619*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
4620*82527734SSukumar Swaminathan 		case CMD_CLOSE_XRI_CX:
4621*82527734SSukumar Swaminathan 		case CMD_CLOSE_XRI_CN:
4622*82527734SSukumar Swaminathan 		case CMD_ABORT_XRI_CX:
4623*82527734SSukumar Swaminathan 			if (!port->tgt_mode) {
4624*82527734SSukumar Swaminathan 				sbp = NULL;
4625*82527734SSukumar Swaminathan 				break;
4626*82527734SSukumar Swaminathan 			}
4627291a2b48SSukumar Swaminathan 
4628*82527734SSukumar Swaminathan 			sbp =
4629*82527734SSukumar Swaminathan 			    emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0);
4630*82527734SSukumar Swaminathan 			break;
4631*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4632291a2b48SSukumar Swaminathan 
4633*82527734SSukumar Swaminathan 			/* Ring 0 registered commands */
4634*82527734SSukumar Swaminathan 		case CMD_FCP_ICMND_CR:
4635*82527734SSukumar Swaminathan 		case CMD_FCP_ICMND_CX:
4636*82527734SSukumar Swaminathan 		case CMD_FCP_IREAD_CR:
4637*82527734SSukumar Swaminathan 		case CMD_FCP_IREAD_CX:
4638*82527734SSukumar Swaminathan 		case CMD_FCP_IWRITE_CR:
4639*82527734SSukumar Swaminathan 		case CMD_FCP_IWRITE_CX:
4640*82527734SSukumar Swaminathan 		case CMD_FCP_ICMND64_CR:
4641*82527734SSukumar Swaminathan 		case CMD_FCP_ICMND64_CX:
4642*82527734SSukumar Swaminathan 		case CMD_FCP_IREAD64_CR:
4643*82527734SSukumar Swaminathan 		case CMD_FCP_IREAD64_CX:
4644*82527734SSukumar Swaminathan 		case CMD_FCP_IWRITE64_CR:
4645*82527734SSukumar Swaminathan 		case CMD_FCP_IWRITE64_CX:
4646*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
4647*82527734SSukumar Swaminathan 		case CMD_FCP_TSEND_CX:
4648*82527734SSukumar Swaminathan 		case CMD_FCP_TSEND64_CX:
4649*82527734SSukumar Swaminathan 		case CMD_FCP_TRECEIVE_CX:
4650*82527734SSukumar Swaminathan 		case CMD_FCP_TRECEIVE64_CX:
4651*82527734SSukumar Swaminathan 		case CMD_FCP_TRSP_CX:
4652*82527734SSukumar Swaminathan 		case CMD_FCP_TRSP64_CX:
4653*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4654291a2b48SSukumar Swaminathan 
4655*82527734SSukumar Swaminathan 			/* Ring 1 registered commands */
4656*82527734SSukumar Swaminathan 		case CMD_XMIT_BCAST_CN:
4657*82527734SSukumar Swaminathan 		case CMD_XMIT_BCAST_CX:
4658*82527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE_CX:
4659*82527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE_CR:
4660*82527734SSukumar Swaminathan 		case CMD_XMIT_BCAST64_CN:
4661*82527734SSukumar Swaminathan 		case CMD_XMIT_BCAST64_CX:
4662*82527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE64_CX:
4663*82527734SSukumar Swaminathan 		case CMD_XMIT_SEQUENCE64_CR:
4664*82527734SSukumar Swaminathan 		case CMD_CREATE_XRI_CR:
4665*82527734SSukumar Swaminathan 		case CMD_CREATE_XRI_CX:
4666291a2b48SSukumar Swaminathan 
4667*82527734SSukumar Swaminathan 			/* Ring 2 registered commands */
4668*82527734SSukumar Swaminathan 		case CMD_ELS_REQUEST_CR:
4669*82527734SSukumar Swaminathan 		case CMD_ELS_REQUEST_CX:
4670*82527734SSukumar Swaminathan 		case CMD_XMIT_ELS_RSP_CX:
4671*82527734SSukumar Swaminathan 		case CMD_ELS_REQUEST64_CR:
4672*82527734SSukumar Swaminathan 		case CMD_ELS_REQUEST64_CX:
4673*82527734SSukumar Swaminathan 		case CMD_XMIT_ELS_RSP64_CX:
4674291a2b48SSukumar Swaminathan 
4675*82527734SSukumar Swaminathan 			/* Ring 3 registered commands */
4676*82527734SSukumar Swaminathan 		case CMD_GEN_REQUEST64_CR:
4677*82527734SSukumar Swaminathan 		case CMD_GEN_REQUEST64_CX:
4678291a2b48SSukumar Swaminathan 
4679*82527734SSukumar Swaminathan 			sbp =
4680*82527734SSukumar Swaminathan 			    emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0);
4681*82527734SSukumar Swaminathan 			break;
4682291a2b48SSukumar Swaminathan 
4683*82527734SSukumar Swaminathan 		default:
4684*82527734SSukumar Swaminathan 			sbp = NULL;
4685*82527734SSukumar Swaminathan 		}
4686291a2b48SSukumar Swaminathan 
4687*82527734SSukumar Swaminathan 		/* If packet is stale, then drop it. */
4688*82527734SSukumar Swaminathan 		if (sbp == STALE_PACKET) {
4689*82527734SSukumar Swaminathan 			cp->hbaCmplCmd_sbp++;
4690*82527734SSukumar Swaminathan 			/* Copy entry to the local iocbq */
4691*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
4692*82527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4693291a2b48SSukumar Swaminathan 
4694*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
4695*82527734SSukumar Swaminathan 			    "channelno=%d iocb=%p cmd=%x status=%x "
4696*82527734SSukumar Swaminathan 			    "error=%x iotag=%x context=%x info=%x",
4697*82527734SSukumar Swaminathan 			    channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
4698*82527734SSukumar Swaminathan 			    iocbq->iocb.ULPSTATUS,
4699*82527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
4700*82527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPIOTAG,
4701*82527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPCONTEXT,
4702*82527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.ULPRSVDBYTE);
4703291a2b48SSukumar Swaminathan 
4704*82527734SSukumar Swaminathan 			goto next;
4705291a2b48SSukumar Swaminathan 		}
4706291a2b48SSukumar Swaminathan 
4707*82527734SSukumar Swaminathan 		/*
4708*82527734SSukumar Swaminathan 		 * If a packet was found, then queue the packet's
4709*82527734SSukumar Swaminathan 		 * iocb for deferred processing
4710*82527734SSukumar Swaminathan 		 */
4711*82527734SSukumar Swaminathan 		else if (sbp) {
4712*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
4713*82527734SSukumar Swaminathan 			fct_cmd_t *fct_cmd;
4714*82527734SSukumar Swaminathan 			emlxs_buf_t *cmd_sbp;
4715291a2b48SSukumar Swaminathan 
4716*82527734SSukumar Swaminathan 			fct_cmd = sbp->fct_cmd;
4717*82527734SSukumar Swaminathan 			if (fct_cmd) {
4718*82527734SSukumar Swaminathan 				cmd_sbp =
4719*82527734SSukumar Swaminathan 				    (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4720*82527734SSukumar Swaminathan 				mutex_enter(&cmd_sbp->fct_mtx);
4721*82527734SSukumar Swaminathan 				EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
4722*82527734SSukumar Swaminathan 				    EMLXS_FCT_IOCB_COMPLETE);
4723*82527734SSukumar Swaminathan 				mutex_exit(&cmd_sbp->fct_mtx);
4724*82527734SSukumar Swaminathan 			}
4725*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4726*82527734SSukumar Swaminathan 			cp->hbaCmplCmd_sbp++;
4727*82527734SSukumar Swaminathan 			atomic_add_32(&hba->io_active, -1);
4728291a2b48SSukumar Swaminathan 
4729*82527734SSukumar Swaminathan 			/* Copy entry to sbp's iocbq */
4730*82527734SSukumar Swaminathan 			iocbq = &sbp->iocbq;
4731*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
4732*82527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4733291a2b48SSukumar Swaminathan 
4734*82527734SSukumar Swaminathan 			iocbq->next = NULL;
4735291a2b48SSukumar Swaminathan 
4736*82527734SSukumar Swaminathan 			/*
4737*82527734SSukumar Swaminathan 			 * If this is NOT a polled command completion
4738*82527734SSukumar Swaminathan 			 * or a driver allocated pkt, then defer pkt
4739*82527734SSukumar Swaminathan 			 * completion.
4740*82527734SSukumar Swaminathan 			 */
4741*82527734SSukumar Swaminathan 			if (!(sbp->pkt_flags &
4742*82527734SSukumar Swaminathan 			    (PACKET_POLLED | PACKET_ALLOCATED))) {
4743*82527734SSukumar Swaminathan 				/* Add the IOCB to the local list */
4744*82527734SSukumar Swaminathan 				if (!rsp_head) {
4745*82527734SSukumar Swaminathan 					rsp_head = iocbq;
4746*82527734SSukumar Swaminathan 				} else {
4747*82527734SSukumar Swaminathan 					rsp_tail->next = iocbq;
4748*82527734SSukumar Swaminathan 				}
4749291a2b48SSukumar Swaminathan 
4750*82527734SSukumar Swaminathan 				rsp_tail = iocbq;
4751291a2b48SSukumar Swaminathan 
4752*82527734SSukumar Swaminathan 				goto next;
4753*82527734SSukumar Swaminathan 			}
4754*82527734SSukumar Swaminathan 		} else {
4755*82527734SSukumar Swaminathan 			cp->hbaCmplCmd++;
4756*82527734SSukumar Swaminathan 			/* Copy entry to the local iocbq */
4757*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)entry,
4758*82527734SSukumar Swaminathan 			    (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4759291a2b48SSukumar Swaminathan 
4760*82527734SSukumar Swaminathan 			iocbq->next = NULL;
4761*82527734SSukumar Swaminathan 			iocbq->bp = NULL;
4762*82527734SSukumar Swaminathan 			iocbq->port = &PPORT;
4763*82527734SSukumar Swaminathan 			iocbq->channel = cp;
4764*82527734SSukumar Swaminathan 			iocbq->node = NULL;
4765*82527734SSukumar Swaminathan 			iocbq->sbp = NULL;
4766*82527734SSukumar Swaminathan 			iocbq->flag = 0;
4767*82527734SSukumar Swaminathan 		}
4768291a2b48SSukumar Swaminathan 
4769*82527734SSukumar Swaminathan 		/* process the channel event now */
4770*82527734SSukumar Swaminathan 		emlxs_proc_channel_event(hba, cp, iocbq);
4771291a2b48SSukumar Swaminathan 
4772*82527734SSukumar Swaminathan next:
4773*82527734SSukumar Swaminathan 		/* Increment the driver's local response get index */
4774*82527734SSukumar Swaminathan 		if (++rp->fc_rspidx >= rp->fc_numRiocb) {
4775*82527734SSukumar Swaminathan 			rp->fc_rspidx = 0;
4776*82527734SSukumar Swaminathan 		}
4777291a2b48SSukumar Swaminathan 
4778*82527734SSukumar Swaminathan 	}	/* while (TRUE) */
4779291a2b48SSukumar Swaminathan 
4780*82527734SSukumar Swaminathan 	if (rsp_head) {
4781*82527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
4782*82527734SSukumar Swaminathan 		if (cp->rsp_head == NULL) {
4783*82527734SSukumar Swaminathan 			cp->rsp_head = rsp_head;
4784*82527734SSukumar Swaminathan 			cp->rsp_tail = rsp_tail;
4785*82527734SSukumar Swaminathan 		} else {
4786*82527734SSukumar Swaminathan 			cp->rsp_tail->next = rsp_head;
4787*82527734SSukumar Swaminathan 			cp->rsp_tail = rsp_tail;
4788*82527734SSukumar Swaminathan 		}
4789*82527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
4790291a2b48SSukumar Swaminathan 
4791*82527734SSukumar Swaminathan 		emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp);
4792*82527734SSukumar Swaminathan 	}
4793291a2b48SSukumar Swaminathan 
4794*82527734SSukumar Swaminathan 	/* Check if at least one response entry was processed */
4795*82527734SSukumar Swaminathan 	if (count) {
4796*82527734SSukumar Swaminathan 		/* Update response get index for the adapter */
4797*82527734SSukumar Swaminathan 		if (hba->bus_type == SBUS_FC) {
4798*82527734SSukumar Swaminathan 			slim2p->mbx.us.s2.host[channel_no].rspGetInx
4799*82527734SSukumar Swaminathan 			    = BE_SWAP32(rp->fc_rspidx);
4800291a2b48SSukumar Swaminathan 
4801*82527734SSukumar Swaminathan 			/* DMA sync the index for the adapter */
4802*82527734SSukumar Swaminathan 			offset = (off_t)
4803*82527734SSukumar Swaminathan 			    ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
4804*82527734SSukumar Swaminathan 			    host[channel_no].rspGetInx))
4805*82527734SSukumar Swaminathan 			    - (uint64_t)((unsigned long)slim2p));
4806*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
4807*82527734SSukumar Swaminathan 			    offset, 4, DDI_DMA_SYNC_FORDEV);
4808*82527734SSukumar Swaminathan 		} else {
4809*82527734SSukumar Swaminathan 			ioa2 =
4810*82527734SSukumar Swaminathan 			    (void *)((char *)hba->sli.sli3.slim_addr +
4811*82527734SSukumar Swaminathan 			    hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) +
4812*82527734SSukumar Swaminathan 			    1) * sizeof (uint32_t)));
4813*82527734SSukumar Swaminathan 			WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
4814*82527734SSukumar Swaminathan 			    rp->fc_rspidx);
4815*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4816*82527734SSukumar Swaminathan 			/* Access handle validation */
4817*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
4818*82527734SSukumar Swaminathan 			    hba->sli.sli3.slim_acc_handle);
4819*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4820291a2b48SSukumar Swaminathan 		}
4821291a2b48SSukumar Swaminathan 
4822*82527734SSukumar Swaminathan 		if (reg & HA_R0RE_REQ) {
4823*82527734SSukumar Swaminathan 			/* HBASTATS.chipRingFree++; */
4824291a2b48SSukumar Swaminathan 
4825*82527734SSukumar Swaminathan 			mutex_enter(&EMLXS_PORT_LOCK);
4826291a2b48SSukumar Swaminathan 
4827*82527734SSukumar Swaminathan 			/* Tell the adapter we serviced the ring */
4828*82527734SSukumar Swaminathan 			chipatt = ((CA_R0ATT | CA_R0RE_RSP) <<
4829*82527734SSukumar Swaminathan 			    (channel_no * 4));
4830*82527734SSukumar Swaminathan 			WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt);
4831291a2b48SSukumar Swaminathan 
4832*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
4833*82527734SSukumar Swaminathan 			/* Access handle validation */
4834*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4835*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4836*82527734SSukumar Swaminathan 
4837*82527734SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
4838291a2b48SSukumar Swaminathan 		}
4839*82527734SSukumar Swaminathan 	}
4840291a2b48SSukumar Swaminathan 
4841*82527734SSukumar Swaminathan 	if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) {
4842*82527734SSukumar Swaminathan 		/* HBASTATS.hostRingFree++; */
4843291a2b48SSukumar Swaminathan 
4844*82527734SSukumar Swaminathan 		/* Cmd ring may be available. Try sending more iocbs */
4845*82527734SSukumar Swaminathan 		emlxs_sli3_issue_iocb_cmd(hba, cp, 0);
4846291a2b48SSukumar Swaminathan 	}
4847291a2b48SSukumar Swaminathan 
4848*82527734SSukumar Swaminathan 	/* HBASTATS.ringEvent++; */
4849291a2b48SSukumar Swaminathan 
4850*82527734SSukumar Swaminathan 	return;
4851291a2b48SSukumar Swaminathan 
4852*82527734SSukumar Swaminathan } /* emlxs_sli3_handle_ring_event() */
4853291a2b48SSukumar Swaminathan 
4854291a2b48SSukumar Swaminathan 
4855*82527734SSukumar Swaminathan extern int
4856*82527734SSukumar Swaminathan emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
4857*82527734SSukumar Swaminathan {
4858*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4859*82527734SSukumar Swaminathan 	IOCB *iocb;
4860*82527734SSukumar Swaminathan 	RING *rp;
4861*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
4862*82527734SSukumar Swaminathan 	uint64_t bdeAddr;
4863*82527734SSukumar Swaminathan 	uint32_t vpi = 0;
4864*82527734SSukumar Swaminathan 	uint32_t channelno;
4865*82527734SSukumar Swaminathan 	uint32_t size = 0;
4866*82527734SSukumar Swaminathan 	uint32_t *RcvError;
4867*82527734SSukumar Swaminathan 	uint32_t *RcvDropped;
4868*82527734SSukumar Swaminathan 	uint32_t *UbPosted;
4869*82527734SSukumar Swaminathan 	emlxs_msg_t *dropped_msg;
4870*82527734SSukumar Swaminathan 	char error_str[64];
4871*82527734SSukumar Swaminathan 	uint32_t buf_type;
4872*82527734SSukumar Swaminathan 	uint32_t *word;
4873*82527734SSukumar Swaminathan 	uint32_t hbq_id;
4874291a2b48SSukumar Swaminathan 
4875*82527734SSukumar Swaminathan 	channelno = cp->channelno;
4876*82527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[channelno];
4877291a2b48SSukumar Swaminathan 
4878*82527734SSukumar Swaminathan 	iocb = &iocbq->iocb;
4879*82527734SSukumar Swaminathan 	word = (uint32_t *)iocb;
4880291a2b48SSukumar Swaminathan 
4881*82527734SSukumar Swaminathan 	switch (channelno) {
4882*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
4883*82527734SSukumar Swaminathan 	case FC_FCT_RING:
4884*82527734SSukumar Swaminathan 		HBASTATS.FctRingEvent++;
4885*82527734SSukumar Swaminathan 		RcvError = &HBASTATS.FctRingError;
4886*82527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.FctRingDropped;
4887*82527734SSukumar Swaminathan 		UbPosted = &HBASTATS.FctUbPosted;
4888*82527734SSukumar Swaminathan 		dropped_msg = &emlxs_fct_detail_msg;
4889*82527734SSukumar Swaminathan 		buf_type = MEM_FCTBUF;
4890*82527734SSukumar Swaminathan 		break;
4891*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
4892291a2b48SSukumar Swaminathan 
4893*82527734SSukumar Swaminathan 	case FC_IP_RING:
4894*82527734SSukumar Swaminathan 		HBASTATS.IpRcvEvent++;
4895*82527734SSukumar Swaminathan 		RcvError = &HBASTATS.IpDropped;
4896*82527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.IpDropped;
4897*82527734SSukumar Swaminathan 		UbPosted = &HBASTATS.IpUbPosted;
4898*82527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_ip_dropped_msg;
4899*82527734SSukumar Swaminathan 		buf_type = MEM_IPBUF;
4900*82527734SSukumar Swaminathan 		break;
4901291a2b48SSukumar Swaminathan 
4902*82527734SSukumar Swaminathan 	case FC_ELS_RING:
4903*82527734SSukumar Swaminathan 		HBASTATS.ElsRcvEvent++;
4904*82527734SSukumar Swaminathan 		RcvError = &HBASTATS.ElsRcvError;
4905*82527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.ElsRcvDropped;
4906*82527734SSukumar Swaminathan 		UbPosted = &HBASTATS.ElsUbPosted;
4907*82527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_els_dropped_msg;
4908*82527734SSukumar Swaminathan 		buf_type = MEM_ELSBUF;
4909*82527734SSukumar Swaminathan 		break;
4910*82527734SSukumar Swaminathan 
4911*82527734SSukumar Swaminathan 	case FC_CT_RING:
4912*82527734SSukumar Swaminathan 		HBASTATS.CtRcvEvent++;
4913*82527734SSukumar Swaminathan 		RcvError = &HBASTATS.CtRcvError;
4914*82527734SSukumar Swaminathan 		RcvDropped = &HBASTATS.CtRcvDropped;
4915*82527734SSukumar Swaminathan 		UbPosted = &HBASTATS.CtUbPosted;
4916*82527734SSukumar Swaminathan 		dropped_msg = &emlxs_unsol_ct_dropped_msg;
4917*82527734SSukumar Swaminathan 		buf_type = MEM_CTBUF;
4918*82527734SSukumar Swaminathan 		break;
4919*82527734SSukumar Swaminathan 
4920*82527734SSukumar Swaminathan 	default:
4921*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
4922*82527734SSukumar Swaminathan 		    "channel=%d cmd=%x  %s %x %x %x %x",
4923*82527734SSukumar Swaminathan 		    channelno, iocb->ULPCOMMAND,
4924*82527734SSukumar Swaminathan 		    emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5],
4925*82527734SSukumar Swaminathan 		    word[6], word[7]);
4926*82527734SSukumar Swaminathan 		return (1);
4927*82527734SSukumar Swaminathan 	}
4928*82527734SSukumar Swaminathan 
4929*82527734SSukumar Swaminathan 	if (iocb->ULPSTATUS) {
4930*82527734SSukumar Swaminathan 		if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
4931*82527734SSukumar Swaminathan 		    (iocb->un.grsp.perr.statLocalError ==
4932*82527734SSukumar Swaminathan 		    IOERR_RCV_BUFFER_TIMEOUT)) {
4933*82527734SSukumar Swaminathan 			(void) strcpy(error_str, "Out of posted buffers:");
4934*82527734SSukumar Swaminathan 		} else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
4935*82527734SSukumar Swaminathan 		    (iocb->un.grsp.perr.statLocalError ==
4936*82527734SSukumar Swaminathan 		    IOERR_RCV_BUFFER_WAITING)) {
4937*82527734SSukumar Swaminathan 			(void) strcpy(error_str, "Buffer waiting:");
4938*82527734SSukumar Swaminathan 			goto done;
4939*82527734SSukumar Swaminathan 		} else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) {
4940*82527734SSukumar Swaminathan 			(void) strcpy(error_str, "Need Buffer Entry:");
4941*82527734SSukumar Swaminathan 			goto done;
4942*82527734SSukumar Swaminathan 		} else {
4943*82527734SSukumar Swaminathan 			(void) strcpy(error_str, "General error:");
4944291a2b48SSukumar Swaminathan 		}
4945291a2b48SSukumar Swaminathan 
4946*82527734SSukumar Swaminathan 		goto failed;
4947291a2b48SSukumar Swaminathan 	}
4948291a2b48SSukumar Swaminathan 
4949*82527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
4950*82527734SSukumar Swaminathan 		HBQ_INIT_t *hbq;
4951*82527734SSukumar Swaminathan 		HBQE_t *hbqE;
4952*82527734SSukumar Swaminathan 		uint32_t hbqe_tag;
4953291a2b48SSukumar Swaminathan 
4954*82527734SSukumar Swaminathan 		(*UbPosted)--;
4955291a2b48SSukumar Swaminathan 
4956*82527734SSukumar Swaminathan 		hbqE = (HBQE_t *)iocb;
4957*82527734SSukumar Swaminathan 		hbq_id = hbqE->unt.ext.HBQ_tag;
4958*82527734SSukumar Swaminathan 		hbqe_tag = hbqE->unt.ext.HBQE_tag;
4959291a2b48SSukumar Swaminathan 
4960*82527734SSukumar Swaminathan 		hbq = &hba->sli.sli3.hbq_table[hbq_id];
4961291a2b48SSukumar Swaminathan 
4962*82527734SSukumar Swaminathan 		if (hbqe_tag >= hbq->HBQ_numEntries) {
4963*82527734SSukumar Swaminathan 			(void) sprintf(error_str, "Invalid HBQE tag=%x:",
4964*82527734SSukumar Swaminathan 			    hbqe_tag);
4965*82527734SSukumar Swaminathan 			goto dropped;
4966*82527734SSukumar Swaminathan 		}
4967291a2b48SSukumar Swaminathan 
4968*82527734SSukumar Swaminathan 		mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag];
4969291a2b48SSukumar Swaminathan 
4970*82527734SSukumar Swaminathan 		size = iocb->unsli3.ext_rcv.seq_len;
4971*82527734SSukumar Swaminathan 	} else {
4972*82527734SSukumar Swaminathan 		bdeAddr =
4973*82527734SSukumar Swaminathan 		    PADDR(iocb->un.cont64[0].addrHigh,
4974*82527734SSukumar Swaminathan 		    iocb->un.cont64[0].addrLow);
4975291a2b48SSukumar Swaminathan 
4976*82527734SSukumar Swaminathan 		/* Check for invalid buffer */
4977*82527734SSukumar Swaminathan 		if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) {
4978*82527734SSukumar Swaminathan 			(void) strcpy(error_str, "Invalid buffer:");
4979*82527734SSukumar Swaminathan 			goto dropped;
4980291a2b48SSukumar Swaminathan 		}
4981291a2b48SSukumar Swaminathan 
4982*82527734SSukumar Swaminathan 		mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
4983291a2b48SSukumar Swaminathan 
4984*82527734SSukumar Swaminathan 		size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize;
4985291a2b48SSukumar Swaminathan 	}
4986291a2b48SSukumar Swaminathan 
4987*82527734SSukumar Swaminathan 	if (!mp) {
4988*82527734SSukumar Swaminathan 		(void) strcpy(error_str, "Buffer not mapped:");
4989*82527734SSukumar Swaminathan 		goto dropped;
4990*82527734SSukumar Swaminathan 	}
4991291a2b48SSukumar Swaminathan 
4992*82527734SSukumar Swaminathan 	if (!size) {
4993*82527734SSukumar Swaminathan 		(void) strcpy(error_str, "Buffer empty:");
4994*82527734SSukumar Swaminathan 		goto dropped;
4995*82527734SSukumar Swaminathan 	}
4996291a2b48SSukumar Swaminathan 
4997*82527734SSukumar Swaminathan 	/* To avoid we drop the broadcast packets */
4998*82527734SSukumar Swaminathan 	if (channelno != FC_IP_RING) {
4999*82527734SSukumar Swaminathan 		/* Get virtual port */
5000*82527734SSukumar Swaminathan 		if (hba->flag & FC_NPIV_ENABLED) {
5001*82527734SSukumar Swaminathan 			vpi = iocb->unsli3.ext_rcv.vpi;
5002*82527734SSukumar Swaminathan 			if (vpi >= hba->vpi_max) {
5003*82527734SSukumar Swaminathan 				(void) sprintf(error_str,
5004*82527734SSukumar Swaminathan 				"Invalid VPI=%d:", vpi);
5005*82527734SSukumar Swaminathan 				goto dropped;
5006*82527734SSukumar Swaminathan 			}
5007291a2b48SSukumar Swaminathan 
5008*82527734SSukumar Swaminathan 			port = &VPORT(vpi);
5009*82527734SSukumar Swaminathan 		}
50104baa2c25SSukumar Swaminathan 	}
50114baa2c25SSukumar Swaminathan 
5012*82527734SSukumar Swaminathan 	/* Process request */
5013*82527734SSukumar Swaminathan 	switch (channelno) {
5014*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
5015*82527734SSukumar Swaminathan 	case FC_FCT_RING:
5016*82527734SSukumar Swaminathan 		(void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp, size);
5017*82527734SSukumar Swaminathan 		break;
5018*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5019291a2b48SSukumar Swaminathan 
5020*82527734SSukumar Swaminathan 	case FC_IP_RING:
5021*82527734SSukumar Swaminathan 		(void) emlxs_ip_handle_unsol_req(port, cp, iocbq, mp, size);
5022*82527734SSukumar Swaminathan 		break;
5023291a2b48SSukumar Swaminathan 
5024*82527734SSukumar Swaminathan 	case FC_ELS_RING:
5025*82527734SSukumar Swaminathan 		/* If this is a target port, then let fct handle this */
5026*82527734SSukumar Swaminathan 		if (port->ini_mode) {
5027*82527734SSukumar Swaminathan 			(void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp,
5028*82527734SSukumar Swaminathan 			    size);
5029*82527734SSukumar Swaminathan 		}
5030*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
5031*82527734SSukumar Swaminathan 		else if (port->tgt_mode) {
5032*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp,
5033*82527734SSukumar Swaminathan 			    size);
5034*82527734SSukumar Swaminathan 		}
5035*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5036*82527734SSukumar Swaminathan 		break;
5037291a2b48SSukumar Swaminathan 
5038*82527734SSukumar Swaminathan 	case FC_CT_RING:
5039*82527734SSukumar Swaminathan 		(void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size);
5040*82527734SSukumar Swaminathan 		break;
5041*82527734SSukumar Swaminathan 	}
5042291a2b48SSukumar Swaminathan 
5043*82527734SSukumar Swaminathan 	goto done;
5044291a2b48SSukumar Swaminathan 
5045*82527734SSukumar Swaminathan dropped:
5046*82527734SSukumar Swaminathan 	(*RcvDropped)++;
5047291a2b48SSukumar Swaminathan 
5048*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
5049*82527734SSukumar Swaminathan 	    "%s: cmd=%x  %s %x %x %x %x",
5050*82527734SSukumar Swaminathan 	    error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
5051*82527734SSukumar Swaminathan 	    word[4], word[5], word[6], word[7]);
5052291a2b48SSukumar Swaminathan 
5053*82527734SSukumar Swaminathan 	if (channelno == FC_FCT_RING) {
5054*82527734SSukumar Swaminathan 		uint32_t sid;
5055291a2b48SSukumar Swaminathan 
5056*82527734SSukumar Swaminathan 		if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) {
5057*82527734SSukumar Swaminathan 			emlxs_node_t *ndlp;
5058*82527734SSukumar Swaminathan 			ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
5059*82527734SSukumar Swaminathan 			sid = ndlp->nlp_DID;
5060*82527734SSukumar Swaminathan 		} else {
5061*82527734SSukumar Swaminathan 			sid = iocb->un.ulpWord[4] & 0xFFFFFF;
5062*82527734SSukumar Swaminathan 		}
5063291a2b48SSukumar Swaminathan 
5064*82527734SSukumar Swaminathan 		emlxs_send_logo(port, sid);
5065291a2b48SSukumar Swaminathan 	}
5066291a2b48SSukumar Swaminathan 
5067*82527734SSukumar Swaminathan 	goto done;
5068291a2b48SSukumar Swaminathan 
5069*82527734SSukumar Swaminathan failed:
5070*82527734SSukumar Swaminathan 	(*RcvError)++;
5071291a2b48SSukumar Swaminathan 
5072*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
5073*82527734SSukumar Swaminathan 	    "%s: cmd=%x %s  %x %x %x %x  hba:%x %x",
5074*82527734SSukumar Swaminathan 	    error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
5075*82527734SSukumar Swaminathan 	    word[4], word[5], word[6], word[7], hba->state, hba->flag);
5076291a2b48SSukumar Swaminathan 
5077*82527734SSukumar Swaminathan done:
5078291a2b48SSukumar Swaminathan 
5079*82527734SSukumar Swaminathan 	if (hba->flag & FC_HBQ_ENABLED) {
5080*82527734SSukumar Swaminathan 		emlxs_update_HBQ_index(hba, hbq_id);
5081*82527734SSukumar Swaminathan 	} else {
5082*82527734SSukumar Swaminathan 		if (mp) {
5083*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, buf_type, (uint8_t *)mp);
5084291a2b48SSukumar Swaminathan 		}
5085*82527734SSukumar Swaminathan 		(void) emlxs_post_buffer(hba, rp, 1);
5086291a2b48SSukumar Swaminathan 	}
5087291a2b48SSukumar Swaminathan 
5088*82527734SSukumar Swaminathan 	return (0);
5089291a2b48SSukumar Swaminathan 
5090*82527734SSukumar Swaminathan } /* emlxs_handle_rcv_seq() */
5091291a2b48SSukumar Swaminathan 
5092291a2b48SSukumar Swaminathan 
5093*82527734SSukumar Swaminathan /* EMLXS_CMD_RING_LOCK must be held when calling this function */
5094*82527734SSukumar Swaminathan static void
5095*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
5096291a2b48SSukumar Swaminathan {
5097*82527734SSukumar Swaminathan 	emlxs_port_t *port;
5098*82527734SSukumar Swaminathan 	IOCB *icmd;
5099*82527734SSukumar Swaminathan 	IOCB *iocb;
5100*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
5101*82527734SSukumar Swaminathan 	off_t offset;
5102*82527734SSukumar Swaminathan 	uint32_t ringno;
5103291a2b48SSukumar Swaminathan 
5104*82527734SSukumar Swaminathan 	ringno = rp->ringno;
5105*82527734SSukumar Swaminathan 	sbp = iocbq->sbp;
5106*82527734SSukumar Swaminathan 	icmd = &iocbq->iocb;
5107*82527734SSukumar Swaminathan 	port = iocbq->port;
5108291a2b48SSukumar Swaminathan 
5109*82527734SSukumar Swaminathan 	HBASTATS.IocbIssued[ringno]++;
5110291a2b48SSukumar Swaminathan 
5111*82527734SSukumar Swaminathan 	/* Check for ULP pkt request */
5112*82527734SSukumar Swaminathan 	if (sbp) {
5113*82527734SSukumar Swaminathan 		mutex_enter(&sbp->mtx);
5114291a2b48SSukumar Swaminathan 
5115*82527734SSukumar Swaminathan 		if (sbp->node == NULL) {
5116*82527734SSukumar Swaminathan 			/* Set node to base node by default */
5117*82527734SSukumar Swaminathan 			iocbq->node = (void *)&port->node_base;
5118*82527734SSukumar Swaminathan 			sbp->node = (void *)&port->node_base;
5119*82527734SSukumar Swaminathan 		}
5120291a2b48SSukumar Swaminathan 
5121*82527734SSukumar Swaminathan 		sbp->pkt_flags |= PACKET_IN_CHIPQ;
5122*82527734SSukumar Swaminathan 		mutex_exit(&sbp->mtx);
5123291a2b48SSukumar Swaminathan 
5124*82527734SSukumar Swaminathan 		atomic_add_32(&hba->io_active, 1);
5125291a2b48SSukumar Swaminathan 
5126*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT
5127*82527734SSukumar Swaminathan #ifdef FCT_IO_TRACE
5128*82527734SSukumar Swaminathan 		if (sbp->fct_cmd) {
5129*82527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
5130*82527734SSukumar Swaminathan 			    EMLXS_FCT_IOCB_ISSUED);
5131*82527734SSukumar Swaminathan 			emlxs_fct_io_trace(port, sbp->fct_cmd,
5132*82527734SSukumar Swaminathan 			    icmd->ULPCOMMAND);
5133*82527734SSukumar Swaminathan 		}
5134*82527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */
5135*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */
5136291a2b48SSukumar Swaminathan 
5137*82527734SSukumar Swaminathan 		rp->channelp->hbaSendCmd_sbp++;
5138*82527734SSukumar Swaminathan 		iocbq->channel = rp->channelp;
5139291a2b48SSukumar Swaminathan 	} else {
5140*82527734SSukumar Swaminathan 		rp->channelp->hbaSendCmd++;
5141291a2b48SSukumar Swaminathan 	}
5142291a2b48SSukumar Swaminathan 
5143*82527734SSukumar Swaminathan 	/* get the next available command ring iocb */
5144*82527734SSukumar Swaminathan 	iocb =
5145*82527734SSukumar Swaminathan 	    (IOCB *)(((char *)rp->fc_cmdringaddr +
5146*82527734SSukumar Swaminathan 	    (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size)));
5147291a2b48SSukumar Swaminathan 
5148*82527734SSukumar Swaminathan 	/* Copy the local iocb to the command ring iocb */
5149*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb,
5150*82527734SSukumar Swaminathan 	    hba->sli.sli3.iocb_cmd_size);
5151291a2b48SSukumar Swaminathan 
5152*82527734SSukumar Swaminathan 	/* DMA sync the command ring iocb for the adapter */
5153*82527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)iocb)
5154*82527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5155*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5156*82527734SSukumar Swaminathan 	    hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV);
5157291a2b48SSukumar Swaminathan 
5158*82527734SSukumar Swaminathan 	/*
5159*82527734SSukumar Swaminathan 	 * After this, the sbp / iocb should not be
5160*82527734SSukumar Swaminathan 	 * accessed in the xmit path.
5161*82527734SSukumar Swaminathan 	 */
5162*82527734SSukumar Swaminathan 
5163*82527734SSukumar Swaminathan 	/* Free the local iocb if there is no sbp tracking it */
5164*82527734SSukumar Swaminathan 	if (!sbp) {
5165*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq);
5166291a2b48SSukumar Swaminathan 	}
5167291a2b48SSukumar Swaminathan 
5168*82527734SSukumar Swaminathan 	/* update local ring index to next available ring index */
5169*82527734SSukumar Swaminathan 	rp->fc_cmdidx =
5170*82527734SSukumar Swaminathan 	    (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
5171291a2b48SSukumar Swaminathan 
5172291a2b48SSukumar Swaminathan 
5173*82527734SSukumar Swaminathan 	return;
51744baa2c25SSukumar Swaminathan 
5175*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb() */
5176291a2b48SSukumar Swaminathan 
5177291a2b48SSukumar Swaminathan 
5178*82527734SSukumar Swaminathan static void
5179*82527734SSukumar Swaminathan emlxs_sli3_hba_kill(emlxs_hba_t *hba)
5180*82527734SSukumar Swaminathan {
5181*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5182*82527734SSukumar Swaminathan 	MAILBOX *swpmb;
5183*82527734SSukumar Swaminathan 	MAILBOX *mb2;
5184*82527734SSukumar Swaminathan 	MAILBOX *mb1;
5185*82527734SSukumar Swaminathan 	uint32_t word0;
5186*82527734SSukumar Swaminathan 	uint32_t j;
5187*82527734SSukumar Swaminathan 	uint32_t interlock_failed;
5188*82527734SSukumar Swaminathan 	uint32_t ha_copy;
5189*82527734SSukumar Swaminathan 	uint32_t value;
5190*82527734SSukumar Swaminathan 	off_t offset;
5191*82527734SSukumar Swaminathan 	uint32_t size;
5192291a2b48SSukumar Swaminathan 
5193*82527734SSukumar Swaminathan 	/* Perform adapter interlock to kill adapter */
5194*82527734SSukumar Swaminathan 	interlock_failed = 0;
5195291a2b48SSukumar Swaminathan 
5196*82527734SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
5197*82527734SSukumar Swaminathan 	if (hba->flag & FC_INTERLOCKED) {
5198*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5199291a2b48SSukumar Swaminathan 
5200*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5201291a2b48SSukumar Swaminathan 
5202*82527734SSukumar Swaminathan 		return;
5203*82527734SSukumar Swaminathan 	}
5204291a2b48SSukumar Swaminathan 
5205*82527734SSukumar Swaminathan 	j = 0;
5206*82527734SSukumar Swaminathan 	while (j++ < 10000) {
5207*82527734SSukumar Swaminathan 		if (hba->mbox_queue_flag == 0) {
5208*82527734SSukumar Swaminathan 			break;
5209*82527734SSukumar Swaminathan 		}
5210291a2b48SSukumar Swaminathan 
5211*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5212*82527734SSukumar Swaminathan 		DELAYUS(100);
5213*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_PORT_LOCK);
5214*82527734SSukumar Swaminathan 	}
5215291a2b48SSukumar Swaminathan 
5216*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag != 0) {
5217*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5218*82527734SSukumar Swaminathan 		    "Interlock failed. Mailbox busy.");
5219*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5220*82527734SSukumar Swaminathan 		return;
5221*82527734SSukumar Swaminathan 	}
5222291a2b48SSukumar Swaminathan 
5223*82527734SSukumar Swaminathan 	hba->flag |= FC_INTERLOCKED;
5224*82527734SSukumar Swaminathan 	hba->mbox_queue_flag = 1;
5225291a2b48SSukumar Swaminathan 
5226*82527734SSukumar Swaminathan 	/* Disable all host interrupts */
5227*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
5228*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
5229*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5230291a2b48SSukumar Swaminathan 
5231*82527734SSukumar Swaminathan 	mb2 = FC_SLIM2_MAILBOX(hba);
5232*82527734SSukumar Swaminathan 	mb1 = FC_SLIM1_MAILBOX(hba);
5233*82527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5234291a2b48SSukumar Swaminathan 
5235*82527734SSukumar Swaminathan 	if (!(hba->flag & FC_SLIM2_MODE)) {
5236*82527734SSukumar Swaminathan 		goto mode_B;
5237*82527734SSukumar Swaminathan 	}
5238291a2b48SSukumar Swaminathan 
5239*82527734SSukumar Swaminathan mode_A:
5240291a2b48SSukumar Swaminathan 
5241*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5242*82527734SSukumar Swaminathan 	    "Attempting SLIM2 Interlock...");
5243291a2b48SSukumar Swaminathan 
5244*82527734SSukumar Swaminathan interlock_A:
5245291a2b48SSukumar Swaminathan 
5246*82527734SSukumar Swaminathan 	value = 0xFFFFFFFF;
5247*82527734SSukumar Swaminathan 	word0 = 0;
5248*82527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
5249*82527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
5250291a2b48SSukumar Swaminathan 
5251*82527734SSukumar Swaminathan 	/* Write value to SLIM */
5252*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5253*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5254291a2b48SSukumar Swaminathan 
5255*82527734SSukumar Swaminathan 	/* Send Kill board request */
5256*82527734SSukumar Swaminathan 	mb2->un.varWords[0] = value;
5257*82527734SSukumar Swaminathan 	mb2->mbxCommand = MBX_KILL_BOARD;
5258*82527734SSukumar Swaminathan 	mb2->mbxOwner = OWN_CHIP;
5259291a2b48SSukumar Swaminathan 
5260*82527734SSukumar Swaminathan 	/* Sync the memory */
5261*82527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)mb2)
5262*82527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5263*82527734SSukumar Swaminathan 	size = (sizeof (uint32_t) * 2);
5264291a2b48SSukumar Swaminathan 
5265*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5266291a2b48SSukumar Swaminathan 
5267*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
5268*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
5269291a2b48SSukumar Swaminathan 
5270*82527734SSukumar Swaminathan 	/* interrupt board to do it right away */
5271*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5272291a2b48SSukumar Swaminathan 
5273*82527734SSukumar Swaminathan 	/* First wait for command acceptence */
5274*82527734SSukumar Swaminathan 	j = 0;
5275*82527734SSukumar Swaminathan 	while (j++ < 1000) {
5276*82527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5277291a2b48SSukumar Swaminathan 
5278*82527734SSukumar Swaminathan 		if (value == 0) {
5279*82527734SSukumar Swaminathan 			break;
5280291a2b48SSukumar Swaminathan 		}
5281291a2b48SSukumar Swaminathan 
5282*82527734SSukumar Swaminathan 		DELAYUS(50);
5283*82527734SSukumar Swaminathan 	}
5284291a2b48SSukumar Swaminathan 
5285*82527734SSukumar Swaminathan 	if (value == 0) {
5286*82527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
5287*82527734SSukumar Swaminathan 		while (j++ < 10000) {
5288*82527734SSukumar Swaminathan 			word0 =
5289*82527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5290291a2b48SSukumar Swaminathan 
5291*82527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
5292*82527734SSukumar Swaminathan 				break;
52934baa2c25SSukumar Swaminathan 			}
5294*82527734SSukumar Swaminathan 
5295*82527734SSukumar Swaminathan 			DELAYUS(50);
5296291a2b48SSukumar Swaminathan 		}
5297291a2b48SSukumar Swaminathan 
5298*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5299*82527734SSukumar Swaminathan 		    "Interlock succeeded.");
5300291a2b48SSukumar Swaminathan 
5301*82527734SSukumar Swaminathan 		goto done;
5302*82527734SSukumar Swaminathan 	}
5303291a2b48SSukumar Swaminathan 
5304*82527734SSukumar Swaminathan 	/* Interlock failed !!! */
5305*82527734SSukumar Swaminathan 	interlock_failed = 1;
5306291a2b48SSukumar Swaminathan 
5307*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed.");
5308291a2b48SSukumar Swaminathan 
5309*82527734SSukumar Swaminathan mode_B:
5310291a2b48SSukumar Swaminathan 
5311*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5312*82527734SSukumar Swaminathan 	    "Attempting SLIM1 Interlock...");
5313291a2b48SSukumar Swaminathan 
5314*82527734SSukumar Swaminathan interlock_B:
53154baa2c25SSukumar Swaminathan 
5316*82527734SSukumar Swaminathan 	value = 0xFFFFFFFF;
5317*82527734SSukumar Swaminathan 	word0 = 0;
5318*82527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
5319*82527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
53204baa2c25SSukumar Swaminathan 
5321*82527734SSukumar Swaminathan 	/* Write KILL BOARD to mailbox */
5322*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5323*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0);
5324291a2b48SSukumar Swaminathan 
5325*82527734SSukumar Swaminathan 	/* interrupt board to do it right away */
5326*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5327291a2b48SSukumar Swaminathan 
5328*82527734SSukumar Swaminathan 	/* First wait for command acceptence */
5329*82527734SSukumar Swaminathan 	j = 0;
5330*82527734SSukumar Swaminathan 	while (j++ < 1000) {
5331*82527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5332291a2b48SSukumar Swaminathan 
5333*82527734SSukumar Swaminathan 		if (value == 0) {
5334*82527734SSukumar Swaminathan 			break;
5335291a2b48SSukumar Swaminathan 		}
5336*82527734SSukumar Swaminathan 
5337*82527734SSukumar Swaminathan 		DELAYUS(50);
5338291a2b48SSukumar Swaminathan 	}
5339291a2b48SSukumar Swaminathan 
5340*82527734SSukumar Swaminathan 	if (value == 0) {
5341*82527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
5342*82527734SSukumar Swaminathan 		while (j++ < 10000) {
5343*82527734SSukumar Swaminathan 			word0 =
5344*82527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5345291a2b48SSukumar Swaminathan 
5346*82527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
5347*82527734SSukumar Swaminathan 				break;
5348*82527734SSukumar Swaminathan 			}
5349291a2b48SSukumar Swaminathan 
5350*82527734SSukumar Swaminathan 			DELAYUS(50);
5351291a2b48SSukumar Swaminathan 		}
5352291a2b48SSukumar Swaminathan 
5353*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5354*82527734SSukumar Swaminathan 		    "Interlock succeeded.");
5355291a2b48SSukumar Swaminathan 
5356*82527734SSukumar Swaminathan 		goto done;
5357*82527734SSukumar Swaminathan 	}
5358291a2b48SSukumar Swaminathan 
5359*82527734SSukumar Swaminathan 	/* Interlock failed !!! */
5360291a2b48SSukumar Swaminathan 
5361*82527734SSukumar Swaminathan 	/* If this is the first time then try again */
5362*82527734SSukumar Swaminathan 	if (interlock_failed == 0) {
5363*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5364*82527734SSukumar Swaminathan 		    "Interlock failed. Retrying...");
5365291a2b48SSukumar Swaminathan 
5366*82527734SSukumar Swaminathan 		/* Try again */
5367*82527734SSukumar Swaminathan 		interlock_failed = 1;
5368*82527734SSukumar Swaminathan 		goto interlock_B;
5369291a2b48SSukumar Swaminathan 	}
5370291a2b48SSukumar Swaminathan 
5371291a2b48SSukumar Swaminathan 	/*
5372*82527734SSukumar Swaminathan 	 * Now check for error attention to indicate the board has
5373*82527734SSukumar Swaminathan 	 * been kiilled
5374291a2b48SSukumar Swaminathan 	 */
5375*82527734SSukumar Swaminathan 	j = 0;
5376*82527734SSukumar Swaminathan 	while (j++ < 10000) {
5377*82527734SSukumar Swaminathan 		ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
5378bb63f56eSSukumar Swaminathan 
5379*82527734SSukumar Swaminathan 		if (ha_copy & HA_ERATT) {
5380*82527734SSukumar Swaminathan 			break;
5381*82527734SSukumar Swaminathan 		}
53823be114edSSukumar Swaminathan 
5383*82527734SSukumar Swaminathan 		DELAYUS(50);
5384*82527734SSukumar Swaminathan 	}
5385291a2b48SSukumar Swaminathan 
5386*82527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
5387*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5388*82527734SSukumar Swaminathan 		    "Interlock failed. Board killed.");
5389*82527734SSukumar Swaminathan 	} else {
5390*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5391*82527734SSukumar Swaminathan 		    "Interlock failed. Board not killed.");
5392*82527734SSukumar Swaminathan 	}
5393291a2b48SSukumar Swaminathan 
5394*82527734SSukumar Swaminathan done:
5395291a2b48SSukumar Swaminathan 
5396*82527734SSukumar Swaminathan 	hba->mbox_queue_flag = 0;
5397291a2b48SSukumar Swaminathan 
5398*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5399291a2b48SSukumar Swaminathan 
5400*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
5401*82527734SSukumar Swaminathan 	/* Access handle validation */
5402*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5403*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
5404*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5405291a2b48SSukumar Swaminathan 
5406*82527734SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
5407291a2b48SSukumar Swaminathan 
5408*82527734SSukumar Swaminathan 	return;
5409291a2b48SSukumar Swaminathan 
5410*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill() */
5411291a2b48SSukumar Swaminathan 
5412291a2b48SSukumar Swaminathan 
5413*82527734SSukumar Swaminathan static void
5414*82527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba)
5415*82527734SSukumar Swaminathan {
5416*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5417*82527734SSukumar Swaminathan 	MAILBOX *swpmb;
5418*82527734SSukumar Swaminathan 	MAILBOX *mb2;
5419*82527734SSukumar Swaminathan 	MAILBOX *mb1;
5420*82527734SSukumar Swaminathan 	uint32_t word0;
5421*82527734SSukumar Swaminathan 	off_t offset;
5422*82527734SSukumar Swaminathan 	uint32_t j;
5423*82527734SSukumar Swaminathan 	uint32_t value;
5424*82527734SSukumar Swaminathan 	uint32_t size;
5425291a2b48SSukumar Swaminathan 
5426*82527734SSukumar Swaminathan 	/* Disable all host interrupts */
5427*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = 0;
5428*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
5429*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5430291a2b48SSukumar Swaminathan 
5431*82527734SSukumar Swaminathan 	mb2 = FC_SLIM2_MAILBOX(hba);
5432*82527734SSukumar Swaminathan 	mb1 = FC_SLIM1_MAILBOX(hba);
5433*82527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5434291a2b48SSukumar Swaminathan 
5435*82527734SSukumar Swaminathan 	value = 0xFFFFFFFF;
5436*82527734SSukumar Swaminathan 	word0 = 0;
5437*82527734SSukumar Swaminathan 	swpmb->mbxCommand = MBX_KILL_BOARD;
5438*82527734SSukumar Swaminathan 	swpmb->mbxOwner = OWN_CHIP;
5439291a2b48SSukumar Swaminathan 
5440*82527734SSukumar Swaminathan 	/* Write value to SLIM */
5441*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5442*82527734SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5443291a2b48SSukumar Swaminathan 
5444*82527734SSukumar Swaminathan 	/* Send Kill board request */
5445*82527734SSukumar Swaminathan 	mb2->un.varWords[0] = value;
5446*82527734SSukumar Swaminathan 	mb2->mbxCommand = MBX_KILL_BOARD;
5447*82527734SSukumar Swaminathan 	mb2->mbxOwner = OWN_CHIP;
5448291a2b48SSukumar Swaminathan 
5449*82527734SSukumar Swaminathan 	/* Sync the memory */
5450*82527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)mb2)
5451*82527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5452*82527734SSukumar Swaminathan 	size = (sizeof (uint32_t) * 2);
5453291a2b48SSukumar Swaminathan 
5454*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5455291a2b48SSukumar Swaminathan 
5456*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
5457*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORDEV);
5458291a2b48SSukumar Swaminathan 
5459*82527734SSukumar Swaminathan 	/* interrupt board to do it right away */
5460*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5461291a2b48SSukumar Swaminathan 
5462*82527734SSukumar Swaminathan 	/* First wait for command acceptence */
5463*82527734SSukumar Swaminathan 	j = 0;
5464*82527734SSukumar Swaminathan 	while (j++ < 1000) {
5465*82527734SSukumar Swaminathan 		value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5466291a2b48SSukumar Swaminathan 
5467*82527734SSukumar Swaminathan 		if (value == 0) {
5468*82527734SSukumar Swaminathan 			break;
5469*82527734SSukumar Swaminathan 		}
5470*82527734SSukumar Swaminathan 		DELAYUS(50);
5471*82527734SSukumar Swaminathan 	}
5472*82527734SSukumar Swaminathan 	if (value == 0) {
5473*82527734SSukumar Swaminathan 		/* Now wait for mailbox ownership to clear */
5474*82527734SSukumar Swaminathan 		while (j++ < 10000) {
5475*82527734SSukumar Swaminathan 			word0 =
5476*82527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5477*82527734SSukumar Swaminathan 			if (swpmb->mbxOwner == 0) {
5478*82527734SSukumar Swaminathan 				break;
5479291a2b48SSukumar Swaminathan 			}
5480*82527734SSukumar Swaminathan 			DELAYUS(50);
5481291a2b48SSukumar Swaminathan 		}
5482*82527734SSukumar Swaminathan 		goto done;
5483*82527734SSukumar Swaminathan 	}
5484291a2b48SSukumar Swaminathan 
5485*82527734SSukumar Swaminathan done:
5486*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5487291a2b48SSukumar Swaminathan 
5488*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT
5489*82527734SSukumar Swaminathan 	/* Access handle validation */
5490*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5491*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
5492*82527734SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5493*82527734SSukumar Swaminathan 	return;
5494291a2b48SSukumar Swaminathan 
5495*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill4quiesce */
5496291a2b48SSukumar Swaminathan 
5497291a2b48SSukumar Swaminathan 
5498*82527734SSukumar Swaminathan static uint32_t
5499*82527734SSukumar Swaminathan emlxs_reset_ring(emlxs_hba_t *hba, uint32_t ringno)
5500*82527734SSukumar Swaminathan {
5501*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5502*82527734SSukumar Swaminathan 	RING *rp;
5503*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
5504*82527734SSukumar Swaminathan 	MAILBOX *mb;
5505*82527734SSukumar Swaminathan 	PGP *pgp;
5506*82527734SSukumar Swaminathan 	off_t offset;
5507*82527734SSukumar Swaminathan 	NODELIST *ndlp;
5508*82527734SSukumar Swaminathan 	uint32_t i;
5509*82527734SSukumar Swaminathan 	emlxs_port_t *vport;
5510291a2b48SSukumar Swaminathan 
5511*82527734SSukumar Swaminathan 	rp = &hba->sli.sli3.ring[ringno];
5512*82527734SSukumar Swaminathan 	pgp =
5513*82527734SSukumar Swaminathan 	    (PGP *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[ringno];
5514291a2b48SSukumar Swaminathan 
5515*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
5516*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg,
5517*82527734SSukumar Swaminathan 		    "%s: Unable to allocate mailbox buffer.",
5518*82527734SSukumar Swaminathan 		    emlxs_ring_xlate(ringno));
5519291a2b48SSukumar Swaminathan 
5520*82527734SSukumar Swaminathan 		return ((uint32_t)FC_FAILURE);
5521*82527734SSukumar Swaminathan 	}
5522*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
5523291a2b48SSukumar Swaminathan 
5524*82527734SSukumar Swaminathan 	emlxs_mb_reset_ring(hba, mbq, ringno);
5525*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
5526*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg,
5527*82527734SSukumar Swaminathan 		    "%s: Unable to reset ring. Mailbox cmd=%x status=%x",
5528*82527734SSukumar Swaminathan 		    emlxs_ring_xlate(ringno), mb->mbxCommand, mb->mbxStatus);
5529291a2b48SSukumar Swaminathan 
5530*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
5531*82527734SSukumar Swaminathan 		return ((uint32_t)FC_FAILURE);
5532*82527734SSukumar Swaminathan 	}
5533291a2b48SSukumar Swaminathan 
5534*82527734SSukumar Swaminathan 	/* Free the mailbox */
5535*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
5536291a2b48SSukumar Swaminathan 
5537*82527734SSukumar Swaminathan 	/* Update the response ring indicies */
5538*82527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx))
5539*82527734SSukumar Swaminathan 	    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5540*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
5541*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
5542*82527734SSukumar Swaminathan 	rp->fc_rspidx = rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx);
5543291a2b48SSukumar Swaminathan 
5544*82527734SSukumar Swaminathan 	/* Update the command ring indicies */
5545*82527734SSukumar Swaminathan 	offset = (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) -
5546*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5547*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
5548*82527734SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
5549*82527734SSukumar Swaminathan 	rp->fc_cmdidx = rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
5550291a2b48SSukumar Swaminathan 
5551*82527734SSukumar Swaminathan 	for (i = 0; i < MAX_VPORTS; i++) {
5552*82527734SSukumar Swaminathan 		vport = &VPORT(i);
5553*82527734SSukumar Swaminathan 
5554*82527734SSukumar Swaminathan 		if (!(vport->flag & EMLXS_PORT_BOUND)) {
5555*82527734SSukumar Swaminathan 			continue;
5556*82527734SSukumar Swaminathan 		}
5557291a2b48SSukumar Swaminathan 
5558*82527734SSukumar Swaminathan 		/* Clear all node XRI contexts */
5559*82527734SSukumar Swaminathan 		rw_enter(&vport->node_rwlock, RW_WRITER);
5560*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
5561*82527734SSukumar Swaminathan 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
5562*82527734SSukumar Swaminathan 			ndlp = vport->node_table[i];
5563*82527734SSukumar Swaminathan 			while (ndlp != NULL) {
5564*82527734SSukumar Swaminathan 				ndlp->nlp_flag[FC_IP_RING] &= ~NLP_RPI_XRI;
5565*82527734SSukumar Swaminathan 				ndlp = ndlp->nlp_list_next;
5566291a2b48SSukumar Swaminathan 			}
5567291a2b48SSukumar Swaminathan 		}
5568*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
5569*82527734SSukumar Swaminathan 		rw_exit(&vport->node_rwlock);
5570*82527734SSukumar Swaminathan 	}
5571*82527734SSukumar Swaminathan 
5572*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, "%s",
5573*82527734SSukumar Swaminathan 	    emlxs_ring_xlate(ringno));
5574*82527734SSukumar Swaminathan 
5575*82527734SSukumar Swaminathan 	return (FC_SUCCESS);
5576291a2b48SSukumar Swaminathan 
5577*82527734SSukumar Swaminathan } /* emlxs_reset_ring() */
5578291a2b48SSukumar Swaminathan 
5579291a2b48SSukumar Swaminathan 
5580*82527734SSukumar Swaminathan /*
5581*82527734SSukumar Swaminathan  * emlxs_handle_mb_event
5582*82527734SSukumar Swaminathan  *
5583*82527734SSukumar Swaminathan  * Description: Process a Mailbox Attention.
5584*82527734SSukumar Swaminathan  * Called from host_interrupt to process MBATT
5585*82527734SSukumar Swaminathan  *
5586*82527734SSukumar Swaminathan  *   Returns:
5587*82527734SSukumar Swaminathan  *
5588*82527734SSukumar Swaminathan  */
5589*82527734SSukumar Swaminathan static uint32_t
5590*82527734SSukumar Swaminathan emlxs_handle_mb_event(emlxs_hba_t *hba)
5591*82527734SSukumar Swaminathan {
5592*82527734SSukumar Swaminathan 	emlxs_port_t		*port = &PPORT;
5593*82527734SSukumar Swaminathan 	MAILBOX			*mb;
5594*82527734SSukumar Swaminathan 	MAILBOX			*swpmb;
5595*82527734SSukumar Swaminathan 	MAILBOX			*mbox;
5596*82527734SSukumar Swaminathan 	MAILBOXQ		*mbq;
5597*82527734SSukumar Swaminathan 	volatile uint32_t	word0;
5598*82527734SSukumar Swaminathan 	MATCHMAP		*mbox_bp;
5599*82527734SSukumar Swaminathan 	off_t			offset;
5600*82527734SSukumar Swaminathan 	uint32_t		i;
5601*82527734SSukumar Swaminathan 	int			rc;
5602*82527734SSukumar Swaminathan 
5603*82527734SSukumar Swaminathan 	swpmb = (MAILBOX *)&word0;
5604291a2b48SSukumar Swaminathan 
5605*82527734SSukumar Swaminathan 	switch (hba->mbox_queue_flag) {
5606*82527734SSukumar Swaminathan 	case 0:
5607*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5608*82527734SSukumar Swaminathan 		    "No mailbox active.");
5609*82527734SSukumar Swaminathan 		return (0);
5610291a2b48SSukumar Swaminathan 
5611*82527734SSukumar Swaminathan 	case MBX_POLL:
5612291a2b48SSukumar Swaminathan 
5613*82527734SSukumar Swaminathan 		/* Mark mailbox complete, this should wake up any polling */
5614*82527734SSukumar Swaminathan 		/* threads. This can happen if interrupts are enabled while */
5615*82527734SSukumar Swaminathan 		/* a polled mailbox command is outstanding. If we don't set */
5616*82527734SSukumar Swaminathan 		/* MBQ_COMPLETED here, the polling thread may wait until */
5617*82527734SSukumar Swaminathan 		/* timeout error occurs */
5618291a2b48SSukumar Swaminathan 
5619*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
5620*82527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
5621*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
5622*82527734SSukumar Swaminathan 		if (mbq) {
5623*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5624*82527734SSukumar Swaminathan 			    "Mailbox event. Completing Polled command.");
5625*82527734SSukumar Swaminathan 			mbq->flag |= MBQ_COMPLETED;
5626*82527734SSukumar Swaminathan 		}
5627291a2b48SSukumar Swaminathan 
5628*82527734SSukumar Swaminathan 		return (0);
5629291a2b48SSukumar Swaminathan 
5630*82527734SSukumar Swaminathan 	case MBX_SLEEP:
5631*82527734SSukumar Swaminathan 	case MBX_NOWAIT:
5632*82527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
5633*82527734SSukumar Swaminathan 		mbq = (MAILBOXQ *)hba->mbox_mbq;
5634*82527734SSukumar Swaminathan 		mb = (MAILBOX *)mbq;
5635*82527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
5636*82527734SSukumar Swaminathan 		break;
5637291a2b48SSukumar Swaminathan 
5638*82527734SSukumar Swaminathan 	default:
5639*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
5640*82527734SSukumar Swaminathan 		    "Invalid Mailbox flag (%x).");
5641*82527734SSukumar Swaminathan 		return (0);
5642*82527734SSukumar Swaminathan 	}
5643291a2b48SSukumar Swaminathan 
5644*82527734SSukumar Swaminathan 	/* Get first word of mailbox */
5645*82527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
5646*82527734SSukumar Swaminathan 		mbox = FC_SLIM2_MAILBOX(hba);
5647*82527734SSukumar Swaminathan 		offset = (off_t)((uint64_t)((unsigned long)mbox)
5648*82527734SSukumar Swaminathan 		    - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5649291a2b48SSukumar Swaminathan 
5650*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5651*82527734SSukumar Swaminathan 		    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
5652*82527734SSukumar Swaminathan 		word0 = *((volatile uint32_t *)mbox);
5653*82527734SSukumar Swaminathan 		word0 = BE_SWAP32(word0);
5654*82527734SSukumar Swaminathan 	} else {
5655*82527734SSukumar Swaminathan 		mbox = FC_SLIM1_MAILBOX(hba);
5656*82527734SSukumar Swaminathan 		word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
5657*82527734SSukumar Swaminathan 	}
5658291a2b48SSukumar Swaminathan 
5659*82527734SSukumar Swaminathan 	i = 0;
5660*82527734SSukumar Swaminathan 	while (swpmb->mbxOwner == OWN_CHIP) {
5661*82527734SSukumar Swaminathan 		if (i++ > 10000) {
5662*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5663*82527734SSukumar Swaminathan 			    "OWN_CHIP: %s: status=%x",
5664*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5665*82527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5666291a2b48SSukumar Swaminathan 
5667*82527734SSukumar Swaminathan 			return (1);
5668*82527734SSukumar Swaminathan 		}
5669291a2b48SSukumar Swaminathan 
5670*82527734SSukumar Swaminathan 		/* Get first word of mailbox */
5671*82527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
5672*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5673*82527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
5674*82527734SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mbox);
5675*82527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
5676*82527734SSukumar Swaminathan 		} else {
5677*82527734SSukumar Swaminathan 			word0 =
5678*82527734SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
5679*82527734SSukumar Swaminathan 		}
5680*82527734SSukumar Swaminathan 		}
5681291a2b48SSukumar Swaminathan 
5682*82527734SSukumar Swaminathan 	/* Now that we are the owner, DMA Sync entire mailbox if needed */
5683*82527734SSukumar Swaminathan 	if (hba->flag & FC_SLIM2_MODE) {
5684*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5685*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
5686291a2b48SSukumar Swaminathan 
5687*82527734SSukumar Swaminathan 		BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
5688*82527734SSukumar Swaminathan 		    MAILBOX_CMD_BSIZE);
5689*82527734SSukumar Swaminathan 	} else {
5690*82527734SSukumar Swaminathan 		READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox,
5691*82527734SSukumar Swaminathan 		    MAILBOX_CMD_WSIZE);
5692*82527734SSukumar Swaminathan 	}
5693291a2b48SSukumar Swaminathan 
5694*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT
5695*82527734SSukumar Swaminathan 	if (mbq->extbuf) {
5696*82527734SSukumar Swaminathan 		uint32_t *mbox_ext =
5697*82527734SSukumar Swaminathan 		    (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET);
5698*82527734SSukumar Swaminathan 		off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
5699291a2b48SSukumar Swaminathan 
5700*82527734SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
5701*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5702*82527734SSukumar Swaminathan 			    offset_ext, mbq->extsize,
5703*82527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
5704*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
5705*82527734SSukumar Swaminathan 			    (uint8_t *)mbq->extbuf, mbq->extsize);
5706*82527734SSukumar Swaminathan 		} else {
5707*82527734SSukumar Swaminathan 			READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
5708*82527734SSukumar Swaminathan 			    mbox_ext, (mbq->extsize / 4));
5709291a2b48SSukumar Swaminathan 		}
5710*82527734SSukumar Swaminathan 	}
5711*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */
5712291a2b48SSukumar Swaminathan 
57134baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
5714*82527734SSukumar Swaminathan 	if (!(hba->flag & FC_SLIM2_MODE)) {
5715*82527734SSukumar Swaminathan 		/* Access handle validation */
5716*82527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5717*82527734SSukumar Swaminathan 	}
57184baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5719291a2b48SSukumar Swaminathan 
5720*82527734SSukumar Swaminathan 	/* Now sync the memory buffer if one was used */
5721*82527734SSukumar Swaminathan 	if (mbq->bp) {
5722*82527734SSukumar Swaminathan 		mbox_bp = (MATCHMAP *)mbq->bp;
5723*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
5724*82527734SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
5725*82527734SSukumar Swaminathan 	}
5726291a2b48SSukumar Swaminathan 
5727*82527734SSukumar Swaminathan 	/* Mailbox has been completely received at this point */
5728291a2b48SSukumar Swaminathan 
5729*82527734SSukumar Swaminathan 	if (mb->mbxCommand == MBX_HEARTBEAT) {
5730*82527734SSukumar Swaminathan 		hba->heartbeat_active = 0;
5731*82527734SSukumar Swaminathan 		goto done;
5732291a2b48SSukumar Swaminathan 	}
5733291a2b48SSukumar Swaminathan 
5734*82527734SSukumar Swaminathan 	if (hba->mbox_queue_flag == MBX_SLEEP) {
5735*82527734SSukumar Swaminathan 		if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
5736*82527734SSukumar Swaminathan 		    swpmb->mbxCommand != MBX_DUMP_MEMORY) {
5737*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5738*82527734SSukumar Swaminathan 			    "Received.  %s: status=%x Sleep.",
5739*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5740*82527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5741291a2b48SSukumar Swaminathan 		}
5742*82527734SSukumar Swaminathan 	} else {
5743*82527734SSukumar Swaminathan 		if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
5744*82527734SSukumar Swaminathan 		    swpmb->mbxCommand != MBX_DUMP_MEMORY) {
5745*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5746*82527734SSukumar Swaminathan 			    "Completed. %s: status=%x",
5747*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5748*82527734SSukumar Swaminathan 			    swpmb->mbxStatus);
5749291a2b48SSukumar Swaminathan 		}
5750*82527734SSukumar Swaminathan 	}
5751291a2b48SSukumar Swaminathan 
5752*82527734SSukumar Swaminathan 	/* Filter out passthru mailbox */
5753*82527734SSukumar Swaminathan 	if (mbq->flag & MBQ_PASSTHRU) {
5754*82527734SSukumar Swaminathan 		goto done;
5755*82527734SSukumar Swaminathan 	}
5756291a2b48SSukumar Swaminathan 
5757*82527734SSukumar Swaminathan 	if (mb->mbxStatus) {
5758*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5759*82527734SSukumar Swaminathan 		    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
5760*82527734SSukumar Swaminathan 		    (uint32_t)mb->mbxStatus);
5761*82527734SSukumar Swaminathan 	}
5762291a2b48SSukumar Swaminathan 
5763*82527734SSukumar Swaminathan 	if (mbq->mbox_cmpl) {
5764*82527734SSukumar Swaminathan 		rc = (mbq->mbox_cmpl)(hba, mbq);
5765*82527734SSukumar Swaminathan 		/* If mbox was retried, return immediately */
5766*82527734SSukumar Swaminathan 		if (rc) {
5767*82527734SSukumar Swaminathan 			return (0);
5768*82527734SSukumar Swaminathan 		}
5769*82527734SSukumar Swaminathan 	}
5770291a2b48SSukumar Swaminathan 
5771*82527734SSukumar Swaminathan done:
5772291a2b48SSukumar Swaminathan 
5773*82527734SSukumar Swaminathan 	/* Clean up the mailbox area */
5774*82527734SSukumar Swaminathan 	emlxs_mb_fini(hba, mb, mb->mbxStatus);
5775*82527734SSukumar Swaminathan 
5776*82527734SSukumar Swaminathan 	mbq = (MAILBOXQ *)emlxs_mb_get(hba);
5777*82527734SSukumar Swaminathan 	if (mbq) {
5778*82527734SSukumar Swaminathan 		/* Attempt to send pending mailboxes */
5779*82527734SSukumar Swaminathan 		rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
5780*82527734SSukumar Swaminathan 		if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5781*82527734SSukumar Swaminathan 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
5782291a2b48SSukumar Swaminathan 		}
5783*82527734SSukumar Swaminathan 	}
5784*82527734SSukumar Swaminathan 	return (0);
5785291a2b48SSukumar Swaminathan 
5786*82527734SSukumar Swaminathan } /* emlxs_handle_mb_event() */
5787291a2b48SSukumar Swaminathan 
5788291a2b48SSukumar Swaminathan 
5789*82527734SSukumar Swaminathan extern void
5790*82527734SSukumar Swaminathan emlxs_sli3_timer(emlxs_hba_t *hba)
5791*82527734SSukumar Swaminathan {
5792*82527734SSukumar Swaminathan 	/* Perform SLI3 level timer checks */
5793291a2b48SSukumar Swaminathan 
5794*82527734SSukumar Swaminathan 	emlxs_sli3_timer_check_mbox(hba);
5795291a2b48SSukumar Swaminathan 
5796*82527734SSukumar Swaminathan } /* emlxs_sli3_timer() */
5797291a2b48SSukumar Swaminathan 
5798*82527734SSukumar Swaminathan 
5799*82527734SSukumar Swaminathan static void
5800*82527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba)
5801291a2b48SSukumar Swaminathan {
5802291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
5803291a2b48SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
5804*82527734SSukumar Swaminathan 	MAILBOX *mb = NULL;
5805291a2b48SSukumar Swaminathan 	uint32_t word0;
5806291a2b48SSukumar Swaminathan 	uint32_t offset;
5807291a2b48SSukumar Swaminathan 	uint32_t ha_copy = 0;
5808291a2b48SSukumar Swaminathan 
5809291a2b48SSukumar Swaminathan 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
5810291a2b48SSukumar Swaminathan 		return;
5811291a2b48SSukumar Swaminathan 	}
5812291a2b48SSukumar Swaminathan 
5813291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
5814291a2b48SSukumar Swaminathan 
5815291a2b48SSukumar Swaminathan 	/* Return if timer hasn't expired */
5816291a2b48SSukumar Swaminathan 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
5817291a2b48SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5818291a2b48SSukumar Swaminathan 		return;
5819291a2b48SSukumar Swaminathan 	}
5820291a2b48SSukumar Swaminathan 	hba->mbox_timer = 0;
5821291a2b48SSukumar Swaminathan 
5822291a2b48SSukumar Swaminathan 	/* Mailbox timed out, first check for error attention */
5823291a2b48SSukumar Swaminathan 	ha_copy = emlxs_check_attention(hba);
5824291a2b48SSukumar Swaminathan 
5825291a2b48SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
5826291a2b48SSukumar Swaminathan 		mutex_exit(&EMLXS_PORT_LOCK);
5827291a2b48SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
5828291a2b48SSukumar Swaminathan 		return;
5829291a2b48SSukumar Swaminathan 	}
5830291a2b48SSukumar Swaminathan 
5831291a2b48SSukumar Swaminathan 	if (hba->mbox_queue_flag) {
5832291a2b48SSukumar Swaminathan 		/* Get first word of mailbox */
5833291a2b48SSukumar Swaminathan 		if (hba->flag & FC_SLIM2_MODE) {
5834291a2b48SSukumar Swaminathan 			mb = FC_SLIM2_MAILBOX(hba);
5835*82527734SSukumar Swaminathan 			offset =
5836*82527734SSukumar Swaminathan 			    (off_t)((uint64_t)((unsigned long)mb) - (uint64_t)
5837*82527734SSukumar Swaminathan 			    ((unsigned long)hba->sli.sli3.slim2.virt));
5838291a2b48SSukumar Swaminathan 
5839*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5840*82527734SSukumar Swaminathan 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
5841291a2b48SSukumar Swaminathan 			word0 = *((volatile uint32_t *)mb);
5842*82527734SSukumar Swaminathan 			word0 = BE_SWAP32(word0);
5843291a2b48SSukumar Swaminathan 		} else {
5844291a2b48SSukumar Swaminathan 			mb = FC_SLIM1_MAILBOX(hba);
5845291a2b48SSukumar Swaminathan 			word0 =
5846291a2b48SSukumar Swaminathan 			    READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb));
58474baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
58484baa2c25SSukumar Swaminathan 			/* Access handle validation */
5849*82527734SSukumar Swaminathan 			EMLXS_CHK_ACC_HANDLE(hba,
5850*82527734SSukumar Swaminathan 			    hba->sli.sli3.slim_acc_handle);
58514baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5852291a2b48SSukumar Swaminathan 		}
5853291a2b48SSukumar Swaminathan 
5854291a2b48SSukumar Swaminathan 		mb = (MAILBOX *)&word0;
5855291a2b48SSukumar Swaminathan 
5856291a2b48SSukumar Swaminathan 		/* Check if mailbox has actually completed */
5857291a2b48SSukumar Swaminathan 		if (mb->mbxOwner == OWN_HOST) {
5858291a2b48SSukumar Swaminathan 			/* Read host attention register to determine */
5859291a2b48SSukumar Swaminathan 			/* interrupt source */
5860291a2b48SSukumar Swaminathan 			uint32_t ha_copy = emlxs_check_attention(hba);
5861291a2b48SSukumar Swaminathan 
5862291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5863291a2b48SSukumar Swaminathan 			    "Mailbox attention missed: %s. Forcing event. "
5864291a2b48SSukumar Swaminathan 			    "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
5865*82527734SSukumar Swaminathan 			    hba->sli.sli3.hc_copy, ha_copy);
5866291a2b48SSukumar Swaminathan 
5867291a2b48SSukumar Swaminathan 			mutex_exit(&EMLXS_PORT_LOCK);
5868291a2b48SSukumar Swaminathan 
5869291a2b48SSukumar Swaminathan 			(void) emlxs_handle_mb_event(hba);
5870291a2b48SSukumar Swaminathan 
5871291a2b48SSukumar Swaminathan 			return;
5872291a2b48SSukumar Swaminathan 		}
5873291a2b48SSukumar Swaminathan 
5874291a2b48SSukumar Swaminathan 		if (hba->mbox_mbq) {
5875291a2b48SSukumar Swaminathan 			mb = (MAILBOX *)hba->mbox_mbq;
5876291a2b48SSukumar Swaminathan 		}
5877291a2b48SSukumar Swaminathan 	}
5878291a2b48SSukumar Swaminathan 
5879*82527734SSukumar Swaminathan 	if (mb) {
5880*82527734SSukumar Swaminathan 		switch (hba->mbox_queue_flag) {
5881*82527734SSukumar Swaminathan 		case MBX_NOWAIT:
5882*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
5883*82527734SSukumar Swaminathan 			    "%s: Nowait.",
5884*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand));
5885*82527734SSukumar Swaminathan 			break;
5886291a2b48SSukumar Swaminathan 
5887*82527734SSukumar Swaminathan 		case MBX_SLEEP:
5888*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
5889*82527734SSukumar Swaminathan 			    "%s: mb=%p Sleep.",
5890*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
5891*82527734SSukumar Swaminathan 			    mb);
5892*82527734SSukumar Swaminathan 			break;
5893291a2b48SSukumar Swaminathan 
5894*82527734SSukumar Swaminathan 		case MBX_POLL:
5895*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
5896*82527734SSukumar Swaminathan 			    "%s: mb=%p Polled.",
5897*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
5898*82527734SSukumar Swaminathan 			    mb);
5899*82527734SSukumar Swaminathan 			break;
5900291a2b48SSukumar Swaminathan 
5901*82527734SSukumar Swaminathan 		default:
5902*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
5903*82527734SSukumar Swaminathan 			    "%s: mb=%p (%d).",
5904*82527734SSukumar Swaminathan 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
5905*82527734SSukumar Swaminathan 			    mb, hba->mbox_queue_flag);
5906*82527734SSukumar Swaminathan 			break;
5907*82527734SSukumar Swaminathan 		}
5908*82527734SSukumar Swaminathan 	} else {
5909291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
5910291a2b48SSukumar Swaminathan 	}
5911291a2b48SSukumar Swaminathan 
5912291a2b48SSukumar Swaminathan 	hba->flag |= FC_MBOX_TIMEOUT;
5913*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
5914291a2b48SSukumar Swaminathan 
5915291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
5916291a2b48SSukumar Swaminathan 
5917291a2b48SSukumar Swaminathan 	/* Perform mailbox cleanup */
5918291a2b48SSukumar Swaminathan 	/* This will wake any sleeping or polling threads */
5919291a2b48SSukumar Swaminathan 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
5920291a2b48SSukumar Swaminathan 
5921291a2b48SSukumar Swaminathan 	/* Trigger adapter shutdown */
5922bb63f56eSSukumar Swaminathan 	emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
5923291a2b48SSukumar Swaminathan 
5924291a2b48SSukumar Swaminathan 	return;
5925291a2b48SSukumar Swaminathan 
5926*82527734SSukumar Swaminathan } /* emlxs_sli3_timer_check_mbox() */
5927291a2b48SSukumar Swaminathan 
5928291a2b48SSukumar Swaminathan 
5929291a2b48SSukumar Swaminathan /*
5930291a2b48SSukumar Swaminathan  * emlxs_mb_config_port  Issue a CONFIG_PORT mailbox command
5931291a2b48SSukumar Swaminathan  */
5932*82527734SSukumar Swaminathan static uint32_t
5933*82527734SSukumar Swaminathan emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode,
5934291a2b48SSukumar Swaminathan     uint32_t hbainit)
5935291a2b48SSukumar Swaminathan {
5936*82527734SSukumar Swaminathan 	MAILBOX		*mb = (MAILBOX *)mbq;
5937291a2b48SSukumar Swaminathan 	emlxs_vpd_t	*vpd = &VPD;
5938291a2b48SSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
5939291a2b48SSukumar Swaminathan 	emlxs_config_t	*cfg;
5940291a2b48SSukumar Swaminathan 	RING		*rp;
5941291a2b48SSukumar Swaminathan 	uint64_t	pcb;
5942291a2b48SSukumar Swaminathan 	uint64_t	mbx;
5943291a2b48SSukumar Swaminathan 	uint64_t	hgp;
5944291a2b48SSukumar Swaminathan 	uint64_t	pgp;
5945291a2b48SSukumar Swaminathan 	uint64_t	rgp;
5946291a2b48SSukumar Swaminathan 	MAILBOX		*mbox;
5947291a2b48SSukumar Swaminathan 	SLIM2		*slim;
5948291a2b48SSukumar Swaminathan 	SLI2_RDSC	*rdsc;
5949291a2b48SSukumar Swaminathan 	uint64_t	offset;
5950291a2b48SSukumar Swaminathan 	uint32_t	Laddr;
5951291a2b48SSukumar Swaminathan 	uint32_t	i;
5952291a2b48SSukumar Swaminathan 
5953291a2b48SSukumar Swaminathan 	cfg = &CFG;
5954291a2b48SSukumar Swaminathan 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
5955291a2b48SSukumar Swaminathan 	mbox = NULL;
5956291a2b48SSukumar Swaminathan 	slim = NULL;
5957291a2b48SSukumar Swaminathan 
5958291a2b48SSukumar Swaminathan 	mb->mbxCommand = MBX_CONFIG_PORT;
5959291a2b48SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
5960*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
5961291a2b48SSukumar Swaminathan 
5962291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.pcbLen = sizeof (PCB);
5963291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.hbainit[0] = hbainit;
5964291a2b48SSukumar Swaminathan 
5965*82527734SSukumar Swaminathan 	pcb = hba->sli.sli3.slim2.phys +
5966*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(slim->pcb));
5967*82527734SSukumar Swaminathan 	mb->un.varCfgPort.pcbLow = PADDR_LO(pcb);
5968*82527734SSukumar Swaminathan 	mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb);
5969291a2b48SSukumar Swaminathan 
5970291a2b48SSukumar Swaminathan 	/* Set Host pointers in SLIM flag */
5971291a2b48SSukumar Swaminathan 	mb->un.varCfgPort.hps = 1;
5972291a2b48SSukumar Swaminathan 
5973291a2b48SSukumar Swaminathan 	/* Initialize hba structure for assumed default SLI2 mode */
5974291a2b48SSukumar Swaminathan 	/* If config port succeeds, then we will update it then   */
5975291a2b48SSukumar Swaminathan 	hba->sli_mode = sli_mode;
5976*82527734SSukumar Swaminathan 	hba->vpi_max = 0;
5977291a2b48SSukumar Swaminathan 	hba->flag &= ~FC_NPIV_ENABLED;
5978291a2b48SSukumar Swaminathan 
5979*82527734SSukumar Swaminathan 	if (sli_mode == EMLXS_HBA_SLI3_MODE) {
5980291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE;
5981291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.cerbm = 1;
5982291a2b48SSukumar Swaminathan 		mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ;
5983291a2b48SSukumar Swaminathan 
5984291a2b48SSukumar Swaminathan 		if (cfg[CFG_NPIV_ENABLE].current) {
5985291a2b48SSukumar Swaminathan 			if (vpd->feaLevelHigh >= 0x09) {
5986291a2b48SSukumar Swaminathan 				if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
5987291a2b48SSukumar Swaminathan 					mb->un.varCfgPort.vpi_max =
5988291a2b48SSukumar Swaminathan 					    MAX_VPORTS - 1;
5989291a2b48SSukumar Swaminathan 				} else {
5990291a2b48SSukumar Swaminathan 					mb->un.varCfgPort.vpi_max =
5991291a2b48SSukumar Swaminathan 					    MAX_VPORTS_LIMITED - 1;
5992291a2b48SSukumar Swaminathan 				}
5993291a2b48SSukumar Swaminathan 
5994291a2b48SSukumar Swaminathan 				mb->un.varCfgPort.cmv = 1;
5995291a2b48SSukumar Swaminathan 			} else {
5996291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
5997291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
5998291a2b48SSukumar Swaminathan 				    "CFGPORT: Firmware does not support NPIV. "
5999291a2b48SSukumar Swaminathan 				    "level=%d", vpd->feaLevelHigh);
6000291a2b48SSukumar Swaminathan 			}
6001291a2b48SSukumar Swaminathan 
6002291a2b48SSukumar Swaminathan 		}
6003291a2b48SSukumar Swaminathan 	}
6004291a2b48SSukumar Swaminathan 
6005291a2b48SSukumar Swaminathan 	/*
6006291a2b48SSukumar Swaminathan 	 * Now setup pcb
6007291a2b48SSukumar Swaminathan 	 */
6008*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2;
6009*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2;
6010*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing =
6011*82527734SSukumar Swaminathan 	    (hba->sli.sli3.ring_count - 1);
6012*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize =
6013291a2b48SSukumar Swaminathan 	    sizeof (MAILBOX) + MBOX_EXTENSION_SIZE;
6014291a2b48SSukumar Swaminathan 
6015*82527734SSukumar Swaminathan 	mbx = hba->sli.sli3.slim2.phys +
6016*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(slim->mbx));
6017*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx);
6018*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx);
6019291a2b48SSukumar Swaminathan 
6020291a2b48SSukumar Swaminathan 
6021291a2b48SSukumar Swaminathan 	/*
6022291a2b48SSukumar Swaminathan 	 * Set up HGP - Port Memory
6023291a2b48SSukumar Swaminathan 	 *
6024291a2b48SSukumar Swaminathan 	 * CR0Put   - SLI2(no HBQs) =	0xc0, With HBQs =	0x80
6025291a2b48SSukumar Swaminathan 	 * RR0Get			0xc4			0x84
6026291a2b48SSukumar Swaminathan 	 * CR1Put			0xc8			0x88
6027291a2b48SSukumar Swaminathan 	 * RR1Get			0xcc			0x8c
6028291a2b48SSukumar Swaminathan 	 * CR2Put			0xd0			0x90
6029291a2b48SSukumar Swaminathan 	 * RR2Get			0xd4			0x94
6030291a2b48SSukumar Swaminathan 	 * CR3Put			0xd8			0x98
6031291a2b48SSukumar Swaminathan 	 * RR3Get			0xdc			0x9c
6032291a2b48SSukumar Swaminathan 	 *
6033291a2b48SSukumar Swaminathan 	 * Reserved			0xa0-0xbf
6034291a2b48SSukumar Swaminathan 	 *
6035291a2b48SSukumar Swaminathan 	 * If HBQs configured:
6036291a2b48SSukumar Swaminathan 	 * HBQ 0 Put ptr  0xc0
6037291a2b48SSukumar Swaminathan 	 * HBQ 1 Put ptr  0xc4
6038291a2b48SSukumar Swaminathan 	 * HBQ 2 Put ptr  0xc8
6039291a2b48SSukumar Swaminathan 	 * ...
6040291a2b48SSukumar Swaminathan 	 * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
6041291a2b48SSukumar Swaminathan 	 */
6042291a2b48SSukumar Swaminathan 
6043291a2b48SSukumar Swaminathan 	if (sli_mode >= EMLXS_HBA_SLI3_MODE) {
6044291a2b48SSukumar Swaminathan 		/* ERBM is enabled */
6045*82527734SSukumar Swaminathan 		hba->sli.sli3.hgp_ring_offset = 0x80;
6046*82527734SSukumar Swaminathan 		hba->sli.sli3.hgp_hbq_offset = 0xC0;
6047291a2b48SSukumar Swaminathan 
6048*82527734SSukumar Swaminathan 		hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
6049*82527734SSukumar Swaminathan 		hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
6050291a2b48SSukumar Swaminathan 
6051*82527734SSukumar Swaminathan 	} else { /* SLI2 */
6052291a2b48SSukumar Swaminathan 		/* ERBM is disabled */
6053*82527734SSukumar Swaminathan 		hba->sli.sli3.hgp_ring_offset = 0xC0;
6054*82527734SSukumar Swaminathan 		hba->sli.sli3.hgp_hbq_offset = 0;
6055291a2b48SSukumar Swaminathan 
6056*82527734SSukumar Swaminathan 		hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
6057*82527734SSukumar Swaminathan 		hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
6058291a2b48SSukumar Swaminathan 	}
6059291a2b48SSukumar Swaminathan 
6060291a2b48SSukumar Swaminathan 	/* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */
6061291a2b48SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
6062*82527734SSukumar Swaminathan 		hgp = hba->sli.sli3.slim2.phys +
6063291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(mbox->us.s2.host));
6064*82527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
6065*82527734SSukumar Swaminathan 		    PADDR_HI(hgp);
6066*82527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
6067*82527734SSukumar Swaminathan 		    PADDR_LO(hgp);
6068291a2b48SSukumar Swaminathan 	} else {
6069*82527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
6070291a2b48SSukumar Swaminathan 		    (uint32_t)ddi_get32(hba->pci_acc_handle,
6071291a2b48SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER));
6072291a2b48SSukumar Swaminathan 
6073291a2b48SSukumar Swaminathan 		Laddr =
6074291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
6075291a2b48SSukumar Swaminathan 		    (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER));
6076291a2b48SSukumar Swaminathan 		Laddr &= ~0x4;
6077*82527734SSukumar Swaminathan 		((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
6078*82527734SSukumar Swaminathan 		    (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset);
6079291a2b48SSukumar Swaminathan 
60804baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
60814baa2c25SSukumar Swaminathan 		/* Access handle validation */
6082*82527734SSukumar Swaminathan 		EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
60834baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6084*82527734SSukumar Swaminathan 
6085291a2b48SSukumar Swaminathan 	}
6086291a2b48SSukumar Swaminathan 
6087*82527734SSukumar Swaminathan 	pgp = hba->sli.sli3.slim2.phys +
6088*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)&(mbox->us.s2.port));
6089*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh =
6090*82527734SSukumar Swaminathan 	    PADDR_HI(pgp);
6091*82527734SSukumar Swaminathan 	((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow =
6092*82527734SSukumar Swaminathan 	    PADDR_LO(pgp);
6093291a2b48SSukumar Swaminathan 
6094291a2b48SSukumar Swaminathan 	offset = 0;
6095291a2b48SSukumar Swaminathan 	for (i = 0; i < 4; i++) {
6096*82527734SSukumar Swaminathan 		rp = &hba->sli.sli3.ring[i];
6097*82527734SSukumar Swaminathan 		rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i];
6098291a2b48SSukumar Swaminathan 
6099291a2b48SSukumar Swaminathan 		/* Setup command ring */
6100*82527734SSukumar Swaminathan 		rgp = hba->sli.sli3.slim2.phys +
6101291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
6102*82527734SSukumar Swaminathan 		rdsc->cmdAddrHigh = PADDR_HI(rgp);
6103*82527734SSukumar Swaminathan 		rdsc->cmdAddrLow = PADDR_LO(rgp);
6104291a2b48SSukumar Swaminathan 		rdsc->cmdEntries = rp->fc_numCiocb;
6105291a2b48SSukumar Swaminathan 
6106291a2b48SSukumar Swaminathan 		rp->fc_cmdringaddr =
6107*82527734SSukumar Swaminathan 		    (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
6108*82527734SSukumar Swaminathan 		offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size;
6109291a2b48SSukumar Swaminathan 
6110291a2b48SSukumar Swaminathan 		/* Setup response ring */
6111*82527734SSukumar Swaminathan 		rgp = hba->sli.sli3.slim2.phys +
6112291a2b48SSukumar Swaminathan 		    (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
6113*82527734SSukumar Swaminathan 		rdsc->rspAddrHigh = PADDR_HI(rgp);
6114*82527734SSukumar Swaminathan 		rdsc->rspAddrLow = PADDR_LO(rgp);
6115291a2b48SSukumar Swaminathan 		rdsc->rspEntries = rp->fc_numRiocb;
6116291a2b48SSukumar Swaminathan 
6117291a2b48SSukumar Swaminathan 		rp->fc_rspringaddr =
6118*82527734SSukumar Swaminathan 		    (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
6119*82527734SSukumar Swaminathan 		offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size;
6120291a2b48SSukumar Swaminathan 	}
6121291a2b48SSukumar Swaminathan 
6122*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY((uint8_t *)
6123*82527734SSukumar Swaminathan 	    (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
6124*82527734SSukumar Swaminathan 	    (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
6125*82527734SSukumar Swaminathan 	    sizeof (PCB));
6126291a2b48SSukumar Swaminathan 
6127*82527734SSukumar Swaminathan 	offset = ((uint64_t)((unsigned long)
6128*82527734SSukumar Swaminathan 	    &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) -
6129*82527734SSukumar Swaminathan 	    (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
6130*82527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset,
6131*82527734SSukumar Swaminathan 	    sizeof (PCB), DDI_DMA_SYNC_FORDEV);
6132291a2b48SSukumar Swaminathan 
6133291a2b48SSukumar Swaminathan 	return (0);
6134291a2b48SSukumar Swaminathan 
6135291a2b48SSukumar Swaminathan } /* emlxs_mb_config_port() */
6136291a2b48SSukumar Swaminathan 
6137291a2b48SSukumar Swaminathan 
6138*82527734SSukumar Swaminathan static uint32_t
6139291a2b48SSukumar Swaminathan emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id)
6140291a2b48SSukumar Swaminathan {
6141291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
6142291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6143291a2b48SSukumar Swaminathan 	MATCHMAP *mp;
6144291a2b48SSukumar Swaminathan 	HBQE_t *hbqE;
6145291a2b48SSukumar Swaminathan 	MAILBOX *mb;
6146*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
6147291a2b48SSukumar Swaminathan 	void *ioa2;
6148291a2b48SSukumar Swaminathan 	uint32_t j;
6149291a2b48SSukumar Swaminathan 	uint32_t count;
6150291a2b48SSukumar Swaminathan 	uint32_t size;
6151291a2b48SSukumar Swaminathan 	uint32_t ringno;
6152291a2b48SSukumar Swaminathan 	uint32_t seg;
6153291a2b48SSukumar Swaminathan 
6154291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6155291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6156291a2b48SSukumar Swaminathan 		count = MEM_ELSBUF_COUNT;
6157291a2b48SSukumar Swaminathan 		size = MEM_ELSBUF_SIZE;
6158291a2b48SSukumar Swaminathan 		ringno = FC_ELS_RING;
6159291a2b48SSukumar Swaminathan 		seg = MEM_ELSBUF;
6160291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted = count;
6161291a2b48SSukumar Swaminathan 		break;
6162291a2b48SSukumar Swaminathan 
6163291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6164291a2b48SSukumar Swaminathan 		count = MEM_IPBUF_COUNT;
6165291a2b48SSukumar Swaminathan 		size = MEM_IPBUF_SIZE;
6166291a2b48SSukumar Swaminathan 		ringno = FC_IP_RING;
6167291a2b48SSukumar Swaminathan 		seg = MEM_IPBUF;
6168291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted = count;
6169291a2b48SSukumar Swaminathan 		break;
6170291a2b48SSukumar Swaminathan 
6171291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6172291a2b48SSukumar Swaminathan 		count = MEM_CTBUF_COUNT;
6173291a2b48SSukumar Swaminathan 		size = MEM_CTBUF_SIZE;
6174291a2b48SSukumar Swaminathan 		ringno = FC_CT_RING;
6175291a2b48SSukumar Swaminathan 		seg = MEM_CTBUF;
6176291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted = count;
6177291a2b48SSukumar Swaminathan 		break;
6178291a2b48SSukumar Swaminathan 
6179291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6180291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6181291a2b48SSukumar Swaminathan 		count = MEM_FCTBUF_COUNT;
6182291a2b48SSukumar Swaminathan 		size = MEM_FCTBUF_SIZE;
6183291a2b48SSukumar Swaminathan 		ringno = FC_FCT_RING;
6184291a2b48SSukumar Swaminathan 		seg = MEM_FCTBUF;
6185291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted = count;
6186291a2b48SSukumar Swaminathan 		break;
6187291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6188291a2b48SSukumar Swaminathan 
6189291a2b48SSukumar Swaminathan 	default:
6190291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6191291a2b48SSukumar Swaminathan 		    "emlxs_hbq_setup: Invalid HBQ id. (%x)", hbq_id);
6192291a2b48SSukumar Swaminathan 		return (1);
6193291a2b48SSukumar Swaminathan 	}
6194291a2b48SSukumar Swaminathan 
6195291a2b48SSukumar Swaminathan 	/* Configure HBQ */
6196*82527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6197291a2b48SSukumar Swaminathan 	hbq->HBQ_numEntries = count;
6198291a2b48SSukumar Swaminathan 
6199291a2b48SSukumar Swaminathan 	/* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */
6200*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
6201291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6202291a2b48SSukumar Swaminathan 		    "emlxs_hbq_setup: Unable to get mailbox.");
6203291a2b48SSukumar Swaminathan 		return (1);
6204291a2b48SSukumar Swaminathan 	}
6205*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
6206291a2b48SSukumar Swaminathan 
6207291a2b48SSukumar Swaminathan 	/* Allocate HBQ Host buffer and Initialize the HBQEs */
6208291a2b48SSukumar Swaminathan 	if (emlxs_hbq_alloc(hba, hbq_id)) {
6209291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6210291a2b48SSukumar Swaminathan 		    "emlxs_hbq_setup: Unable to allocate HBQ.");
6211*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6212291a2b48SSukumar Swaminathan 		return (1);
6213291a2b48SSukumar Swaminathan 	}
6214291a2b48SSukumar Swaminathan 
6215291a2b48SSukumar Swaminathan 	hbq->HBQ_recvNotify = 1;
6216291a2b48SSukumar Swaminathan 	hbq->HBQ_num_mask = 0;			/* Bind to ring */
6217291a2b48SSukumar Swaminathan 	hbq->HBQ_profile = 0;			/* Selection profile */
6218291a2b48SSukumar Swaminathan 						/* 0=all, 7=logentry */
6219291a2b48SSukumar Swaminathan 	hbq->HBQ_ringMask = 1 << ringno;	/* b0100 * ringno - Binds */
6220291a2b48SSukumar Swaminathan 						/* HBQ to a ring */
6221291a2b48SSukumar Swaminathan 						/* Ring0=b0001, Ring1=b0010, */
6222291a2b48SSukumar Swaminathan 						/* Ring2=b0100 */
6223291a2b48SSukumar Swaminathan 	hbq->HBQ_headerLen = 0;			/* 0 if not profile 4 or 5 */
6224291a2b48SSukumar Swaminathan 	hbq->HBQ_logEntry = 0;			/* Set to 1 if this HBQ will */
6225291a2b48SSukumar Swaminathan 						/* be used for */
6226291a2b48SSukumar Swaminathan 	hbq->HBQ_id = hbq_id;
6227291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx_next = 0;
6228291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1;
6229291a2b48SSukumar Swaminathan 	hbq->HBQ_GetIdx = 0;
6230291a2b48SSukumar Swaminathan 	hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries;
6231291a2b48SSukumar Swaminathan 	bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs));
6232291a2b48SSukumar Swaminathan 
6233291a2b48SSukumar Swaminathan 	/* Fill in POST BUFFERs in HBQE */
6234291a2b48SSukumar Swaminathan 	hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt;
6235291a2b48SSukumar Swaminathan 	for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) {
6236291a2b48SSukumar Swaminathan 		/* Allocate buffer to post */
6237291a2b48SSukumar Swaminathan 		if ((mp = (MATCHMAP *)emlxs_mem_get(hba,
6238*82527734SSukumar Swaminathan 		    seg, 1)) == 0) {
6239291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6240291a2b48SSukumar Swaminathan 			    "emlxs_hbq_setup: Unable to allocate HBQ buffer. "
6241291a2b48SSukumar Swaminathan 			    "cnt=%d", j);
6242291a2b48SSukumar Swaminathan 			emlxs_hbq_free_all(hba, hbq_id);
6243291a2b48SSukumar Swaminathan 			return (1);
6244291a2b48SSukumar Swaminathan 		}
6245291a2b48SSukumar Swaminathan 
6246291a2b48SSukumar Swaminathan 		hbq->HBQ_PostBufs[j] = mp;
6247291a2b48SSukumar Swaminathan 
6248291a2b48SSukumar Swaminathan 		hbqE->unt.ext.HBQ_tag = hbq_id;
6249291a2b48SSukumar Swaminathan 		hbqE->unt.ext.HBQE_tag = j;
6250291a2b48SSukumar Swaminathan 		hbqE->bde.tus.f.bdeSize = size;
6251291a2b48SSukumar Swaminathan 		hbqE->bde.tus.f.bdeFlags = 0;
6252*82527734SSukumar Swaminathan 		hbqE->unt.w = BE_SWAP32(hbqE->unt.w);
6253*82527734SSukumar Swaminathan 		hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w);
6254291a2b48SSukumar Swaminathan 		hbqE->bde.addrLow =
6255*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_LO(mp->phys));
6256291a2b48SSukumar Swaminathan 		hbqE->bde.addrHigh =
6257*82527734SSukumar Swaminathan 		    BE_SWAP32(PADDR_HI(mp->phys));
6258291a2b48SSukumar Swaminathan 	}
6259291a2b48SSukumar Swaminathan 
6260291a2b48SSukumar Swaminathan 	/* Issue CONFIG_HBQ */
6261*82527734SSukumar Swaminathan 	emlxs_mb_config_hbq(hba, mbq, hbq_id);
6262*82527734SSukumar Swaminathan 	if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
6263291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
6264291a2b48SSukumar Swaminathan 		    "emlxs_hbq_setup: Unable to config HBQ. cmd=%x status=%x",
6265291a2b48SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
6266291a2b48SSukumar Swaminathan 
6267*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6268291a2b48SSukumar Swaminathan 		emlxs_hbq_free_all(hba, hbq_id);
6269291a2b48SSukumar Swaminathan 		return (1);
6270291a2b48SSukumar Swaminathan 	}
6271291a2b48SSukumar Swaminathan 
6272291a2b48SSukumar Swaminathan 	/* Setup HBQ Get/Put indexes */
6273*82527734SSukumar Swaminathan 	ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
6274*82527734SSukumar Swaminathan 	    (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6275291a2b48SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx);
6276291a2b48SSukumar Swaminathan 
6277*82527734SSukumar Swaminathan 	hba->sli.sli3.hbq_count++;
6278291a2b48SSukumar Swaminathan 
6279*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
6280291a2b48SSukumar Swaminathan 
62814baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
62824baa2c25SSukumar Swaminathan 	/* Access handle validation */
6283*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
62844baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
62854baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
62864baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
62874baa2c25SSukumar Swaminathan 		emlxs_hbq_free_all(hba, hbq_id);
62884baa2c25SSukumar Swaminathan 		return (1);
62894baa2c25SSukumar Swaminathan 	}
62904baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
62914baa2c25SSukumar Swaminathan 
6292291a2b48SSukumar Swaminathan 	return (0);
6293291a2b48SSukumar Swaminathan 
6294*82527734SSukumar Swaminathan } /* emlxs_hbq_setup() */
6295291a2b48SSukumar Swaminathan 
6296291a2b48SSukumar Swaminathan 
6297*82527734SSukumar Swaminathan extern void
6298291a2b48SSukumar Swaminathan emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id)
6299291a2b48SSukumar Swaminathan {
6300291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6301291a2b48SSukumar Swaminathan 	MBUF_INFO *buf_info;
6302291a2b48SSukumar Swaminathan 	MBUF_INFO bufinfo;
6303291a2b48SSukumar Swaminathan 	uint32_t seg;
6304291a2b48SSukumar Swaminathan 	uint32_t j;
6305291a2b48SSukumar Swaminathan 
6306291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6307291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6308291a2b48SSukumar Swaminathan 		seg = MEM_ELSBUF;
6309291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted = 0;
6310291a2b48SSukumar Swaminathan 		break;
6311291a2b48SSukumar Swaminathan 
6312291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6313291a2b48SSukumar Swaminathan 		seg = MEM_IPBUF;
6314291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted = 0;
6315291a2b48SSukumar Swaminathan 		break;
6316291a2b48SSukumar Swaminathan 
6317291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6318291a2b48SSukumar Swaminathan 		seg = MEM_CTBUF;
6319291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted = 0;
6320291a2b48SSukumar Swaminathan 		break;
6321291a2b48SSukumar Swaminathan 
6322291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6323291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6324291a2b48SSukumar Swaminathan 		seg = MEM_FCTBUF;
6325291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted = 0;
6326291a2b48SSukumar Swaminathan 		break;
6327291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6328291a2b48SSukumar Swaminathan 
6329291a2b48SSukumar Swaminathan 	default:
6330291a2b48SSukumar Swaminathan 		return;
6331291a2b48SSukumar Swaminathan 	}
6332291a2b48SSukumar Swaminathan 
6333291a2b48SSukumar Swaminathan 
6334*82527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6335291a2b48SSukumar Swaminathan 
6336291a2b48SSukumar Swaminathan 	if (hbq->HBQ_host_buf.virt != 0) {
6337291a2b48SSukumar Swaminathan 		for (j = 0; j < hbq->HBQ_PostBufCnt; j++) {
6338291a2b48SSukumar Swaminathan 			(void) emlxs_mem_put(hba, seg,
6339291a2b48SSukumar Swaminathan 			    (uint8_t *)hbq->HBQ_PostBufs[j]);
6340291a2b48SSukumar Swaminathan 			hbq->HBQ_PostBufs[j] = NULL;
6341291a2b48SSukumar Swaminathan 		}
6342291a2b48SSukumar Swaminathan 		hbq->HBQ_PostBufCnt = 0;
6343291a2b48SSukumar Swaminathan 
6344291a2b48SSukumar Swaminathan 		buf_info = &bufinfo;
6345291a2b48SSukumar Swaminathan 		bzero(buf_info, sizeof (MBUF_INFO));
6346291a2b48SSukumar Swaminathan 
6347291a2b48SSukumar Swaminathan 		buf_info->size = hbq->HBQ_host_buf.size;
6348291a2b48SSukumar Swaminathan 		buf_info->virt = hbq->HBQ_host_buf.virt;
6349291a2b48SSukumar Swaminathan 		buf_info->phys = hbq->HBQ_host_buf.phys;
6350291a2b48SSukumar Swaminathan 		buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle;
6351291a2b48SSukumar Swaminathan 		buf_info->data_handle = hbq->HBQ_host_buf.data_handle;
6352291a2b48SSukumar Swaminathan 		buf_info->flags = FC_MBUF_DMA;
6353291a2b48SSukumar Swaminathan 
6354291a2b48SSukumar Swaminathan 		emlxs_mem_free(hba, buf_info);
6355291a2b48SSukumar Swaminathan 
6356291a2b48SSukumar Swaminathan 		hbq->HBQ_host_buf.virt = NULL;
6357291a2b48SSukumar Swaminathan 	}
6358291a2b48SSukumar Swaminathan 
6359291a2b48SSukumar Swaminathan 	return;
6360291a2b48SSukumar Swaminathan 
6361*82527734SSukumar Swaminathan } /* emlxs_hbq_free_all() */
6362291a2b48SSukumar Swaminathan 
6363291a2b48SSukumar Swaminathan 
6364*82527734SSukumar Swaminathan extern void
6365291a2b48SSukumar Swaminathan emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id)
6366291a2b48SSukumar Swaminathan {
63674baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
63684baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
63694baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6370291a2b48SSukumar Swaminathan 	void *ioa2;
6371291a2b48SSukumar Swaminathan 	uint32_t status;
6372291a2b48SSukumar Swaminathan 	uint32_t HBQ_PortGetIdx;
6373291a2b48SSukumar Swaminathan 	HBQ_INIT_t *hbq;
6374291a2b48SSukumar Swaminathan 
6375291a2b48SSukumar Swaminathan 	switch (hbq_id) {
6376291a2b48SSukumar Swaminathan 	case EMLXS_ELS_HBQ_ID:
6377291a2b48SSukumar Swaminathan 		HBASTATS.ElsUbPosted++;
6378291a2b48SSukumar Swaminathan 		break;
6379291a2b48SSukumar Swaminathan 
6380291a2b48SSukumar Swaminathan 	case EMLXS_IP_HBQ_ID:
6381291a2b48SSukumar Swaminathan 		HBASTATS.IpUbPosted++;
6382291a2b48SSukumar Swaminathan 		break;
6383291a2b48SSukumar Swaminathan 
6384291a2b48SSukumar Swaminathan 	case EMLXS_CT_HBQ_ID:
6385291a2b48SSukumar Swaminathan 		HBASTATS.CtUbPosted++;
6386291a2b48SSukumar Swaminathan 		break;
6387291a2b48SSukumar Swaminathan 
6388291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
6389291a2b48SSukumar Swaminathan 	case EMLXS_FCT_HBQ_ID:
6390291a2b48SSukumar Swaminathan 		HBASTATS.FctUbPosted++;
6391291a2b48SSukumar Swaminathan 		break;
6392291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
6393291a2b48SSukumar Swaminathan 
6394291a2b48SSukumar Swaminathan 	default:
6395291a2b48SSukumar Swaminathan 		return;
6396291a2b48SSukumar Swaminathan 	}
6397291a2b48SSukumar Swaminathan 
6398*82527734SSukumar Swaminathan 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
6399291a2b48SSukumar Swaminathan 
6400291a2b48SSukumar Swaminathan 	hbq->HBQ_PutIdx =
6401291a2b48SSukumar Swaminathan 	    (hbq->HBQ_PutIdx + 1 >=
6402291a2b48SSukumar Swaminathan 	    hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1;
6403291a2b48SSukumar Swaminathan 
6404291a2b48SSukumar Swaminathan 	if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6405291a2b48SSukumar Swaminathan 		HBQ_PortGetIdx =
6406*82527734SSukumar Swaminathan 		    BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.
6407291a2b48SSukumar Swaminathan 		    HBQ_PortGetIdx[hbq_id]);
6408291a2b48SSukumar Swaminathan 
6409291a2b48SSukumar Swaminathan 		hbq->HBQ_GetIdx = HBQ_PortGetIdx;
6410291a2b48SSukumar Swaminathan 
6411291a2b48SSukumar Swaminathan 		if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6412291a2b48SSukumar Swaminathan 			return;
6413291a2b48SSukumar Swaminathan 		}
6414291a2b48SSukumar Swaminathan 	}
6415291a2b48SSukumar Swaminathan 
6416*82527734SSukumar Swaminathan 	ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
6417*82527734SSukumar Swaminathan 	    (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6418291a2b48SSukumar Swaminathan 	status = hbq->HBQ_PutIdx;
6419291a2b48SSukumar Swaminathan 	WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status);
6420291a2b48SSukumar Swaminathan 
64214baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64224baa2c25SSukumar Swaminathan 	/* Access handle validation */
6423*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
64244baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
64254baa2c25SSukumar Swaminathan 
6426291a2b48SSukumar Swaminathan 	return;
6427291a2b48SSukumar Swaminathan 
6428*82527734SSukumar Swaminathan } /* emlxs_update_HBQ_index() */
6429291a2b48SSukumar Swaminathan 
6430291a2b48SSukumar Swaminathan 
6431*82527734SSukumar Swaminathan static void
6432*82527734SSukumar Swaminathan emlxs_sli3_enable_intr(emlxs_hba_t *hba)
6433291a2b48SSukumar Swaminathan {
64344baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64354baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
64364baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6437291a2b48SSukumar Swaminathan 	uint32_t status;
6438291a2b48SSukumar Swaminathan 
6439291a2b48SSukumar Swaminathan 	/* Enable mailbox, error attention interrupts */
6440*82527734SSukumar Swaminathan 	status = (uint32_t)(HC_MBINT_ENA);
6441291a2b48SSukumar Swaminathan 
6442291a2b48SSukumar Swaminathan 	/* Enable ring interrupts */
6443*82527734SSukumar Swaminathan 	if (hba->sli.sli3.ring_count >= 4) {
6444291a2b48SSukumar Swaminathan 		status |=
6445291a2b48SSukumar Swaminathan 		    (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA |
6446291a2b48SSukumar Swaminathan 		    HC_R0INT_ENA);
6447*82527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 3) {
6448291a2b48SSukumar Swaminathan 		status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA);
6449*82527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 2) {
6450291a2b48SSukumar Swaminathan 		status |= (HC_R1INT_ENA | HC_R0INT_ENA);
6451*82527734SSukumar Swaminathan 	} else if (hba->sli.sli3.ring_count == 1) {
6452291a2b48SSukumar Swaminathan 		status |= (HC_R0INT_ENA);
6453291a2b48SSukumar Swaminathan 	}
6454291a2b48SSukumar Swaminathan 
6455*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = status;
6456*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
64574baa2c25SSukumar Swaminathan 
64584baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64594baa2c25SSukumar Swaminathan 	/* Access handle validation */
6460*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
64614baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6462291a2b48SSukumar Swaminathan 
6463*82527734SSukumar Swaminathan } /* emlxs_sli3_enable_intr() */
6464*82527734SSukumar Swaminathan 
6465*82527734SSukumar Swaminathan 
6466*82527734SSukumar Swaminathan static void
6467291a2b48SSukumar Swaminathan emlxs_enable_latt(emlxs_hba_t *hba)
6468291a2b48SSukumar Swaminathan {
64694baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64704baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
64714baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
64724baa2c25SSukumar Swaminathan 
6473291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_PORT_LOCK);
6474*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
6475*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
64764baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64774baa2c25SSukumar Swaminathan 	/* Access handle validation */
6478*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
64794baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6480291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_PORT_LOCK);
6481291a2b48SSukumar Swaminathan 
6482*82527734SSukumar Swaminathan } /* emlxs_enable_latt() */
6483*82527734SSukumar Swaminathan 
6484*82527734SSukumar Swaminathan 
6485*82527734SSukumar Swaminathan static void
6486*82527734SSukumar Swaminathan emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att)
6487291a2b48SSukumar Swaminathan {
64884baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64894baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
64904baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
64914baa2c25SSukumar Swaminathan 
6492291a2b48SSukumar Swaminathan 	/* Disable all adapter interrupts */
6493*82527734SSukumar Swaminathan 	hba->sli.sli3.hc_copy = att;
6494*82527734SSukumar Swaminathan 	WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
64954baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
64964baa2c25SSukumar Swaminathan 	/* Access handle validation */
6497*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
64984baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6499291a2b48SSukumar Swaminathan 
6500*82527734SSukumar Swaminathan } /* emlxs_sli3_disable_intr() */
6501*82527734SSukumar Swaminathan 
6502*82527734SSukumar Swaminathan 
6503*82527734SSukumar Swaminathan static uint32_t
6504291a2b48SSukumar Swaminathan emlxs_check_attention(emlxs_hba_t *hba)
6505291a2b48SSukumar Swaminathan {
65064baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
65074baa2c25SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
65084baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6509291a2b48SSukumar Swaminathan 	uint32_t ha_copy;
6510291a2b48SSukumar Swaminathan 
6511*82527734SSukumar Swaminathan 	ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
65124baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
65134baa2c25SSukumar Swaminathan 	/* Access handle validation */
6514*82527734SSukumar Swaminathan 	EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
65154baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
6516291a2b48SSukumar Swaminathan 	return (ha_copy);
6517*82527734SSukumar Swaminathan 
6518*82527734SSukumar Swaminathan } /* emlxs_check_attention() */
6519*82527734SSukumar Swaminathan 
6520*82527734SSukumar Swaminathan void
6521*82527734SSukumar Swaminathan emlxs_sli3_poll_erratt(emlxs_hba_t *hba)
6522*82527734SSukumar Swaminathan {
6523*82527734SSukumar Swaminathan 	uint32_t ha_copy;
6524*82527734SSukumar Swaminathan 
6525*82527734SSukumar Swaminathan 	ha_copy = emlxs_check_attention(hba);
6526*82527734SSukumar Swaminathan 
6527*82527734SSukumar Swaminathan 	/* Adapter error */
6528*82527734SSukumar Swaminathan 	if (ha_copy & HA_ERATT) {
6529*82527734SSukumar Swaminathan 		HBASTATS.IntrEvent[6]++;
6530*82527734SSukumar Swaminathan 		emlxs_handle_ff_error(hba);
6531*82527734SSukumar Swaminathan 	}
6532291a2b48SSukumar Swaminathan }
6533