1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23*291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24fcf3ce44SJohn Forte  * Use is subject to License terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27*291a2b48SSukumar Swaminathan #define	EMLXS_FW_TABLE_DEF
28fcf3ce44SJohn Forte #define	EMLXS_MODEL_DEF
29fcf3ce44SJohn Forte 
30*291a2b48SSukumar Swaminathan #include <emlxs.h>
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
33fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_HBA_C);
34fcf3ce44SJohn Forte 
35fcf3ce44SJohn Forte static uint32_t emlxs_decode_biu_rev(uint32_t rev);
36fcf3ce44SJohn Forte static uint32_t emlxs_decode_endec_rev(uint32_t rev);
37fcf3ce44SJohn Forte static void emlxs_parse_prog_types(emlxs_hba_t *hba, char *types);
38*291a2b48SSukumar Swaminathan static int32_t emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd,
39*291a2b48SSukumar Swaminathan     uint32_t size);
40fcf3ce44SJohn Forte static void emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types);
41*291a2b48SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp,
42*291a2b48SSukumar Swaminathan     IOCBQ *iocbq);
43fcf3ce44SJohn Forte static void emlxs_process_link_speed(emlxs_hba_t *hba);
44fcf3ce44SJohn Forte static void emlxs_decode_label(char *label, char *buffer);
45fcf3ce44SJohn Forte 
46*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
47*291a2b48SSukumar Swaminathan static void emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw);
48*291a2b48SSukumar Swaminathan static void emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw);
49*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
50*291a2b48SSukumar Swaminathan 
51fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
52fcf3ce44SJohn Forte uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
53*291a2b48SSukumar Swaminathan 	{EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
54fcf3ce44SJohn Forte uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
55*291a2b48SSukumar Swaminathan 	{EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
56*291a2b48SSukumar Swaminathan 	EMLXS_MSI0_MASK8};
57*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte static uint32_t emlxs_disable_traffic_cop = 1;
61fcf3ce44SJohn Forte 
62*291a2b48SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = {
63fcf3ce44SJohn Forte 	{FC_FCP_RING, "FCP Ring"},
64fcf3ce44SJohn Forte 	{FC_IP_RING, "IP  Ring"},
65fcf3ce44SJohn Forte 	{FC_ELS_RING, "ELS Ring"},
66fcf3ce44SJohn Forte 	{FC_CT_RING, "CT  Ring"}
67fcf3ce44SJohn Forte 
68*291a2b48SSukumar Swaminathan }; /* emlxs_ring_table */
69fcf3ce44SJohn Forte 
70fcf3ce44SJohn Forte 
71*291a2b48SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = {
72fcf3ce44SJohn Forte 	{0, "NULL"},
73fcf3ce44SJohn Forte 	{FC_ERROR, "ERROR"},
74fcf3ce44SJohn Forte 	{FC_KILLED, "KILLED"},
75fcf3ce44SJohn Forte 	{FC_WARM_START, "WARM_START"},
76fcf3ce44SJohn Forte 	{FC_INIT_START, "INIT_START"},
77fcf3ce44SJohn Forte 	{FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
78fcf3ce44SJohn Forte 	{FC_INIT_REV, "INIT_REV"},
79fcf3ce44SJohn Forte 	{FC_INIT_CFGPORT, "INIT_CFGPORT"},
80fcf3ce44SJohn Forte 	{FC_INIT_CFGRING, "INIT_CFGRING"},
81fcf3ce44SJohn Forte 	{FC_INIT_INITLINK, "INIT_INITLINK"},
82fcf3ce44SJohn Forte 	{FC_LINK_DOWN, "LINK_DOWN"},
83fcf3ce44SJohn Forte 	{FC_LINK_UP, "LINK_UP"},
84fcf3ce44SJohn Forte 	{FC_CLEAR_LA, "CLEAR_LA"},
85fcf3ce44SJohn Forte 	{FC_READY, "READY"}
86fcf3ce44SJohn Forte 
87*291a2b48SSukumar Swaminathan }; /* emlxs_ffstate_table */
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte /*
91*291a2b48SSukumar Swaminathan  * emlxs_ffinit()
92fcf3ce44SJohn Forte  *
93fcf3ce44SJohn Forte  * This routine will start initialization of the FireFly Chipset
94fcf3ce44SJohn Forte  */
95fcf3ce44SJohn Forte extern int
96fcf3ce44SJohn Forte emlxs_ffinit(emlxs_hba_t *hba)
97fcf3ce44SJohn Forte {
98fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
99fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
100fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
101fcf3ce44SJohn Forte 	MAILBOX *mb;
102fcf3ce44SJohn Forte 	RING *rp;
103fcf3ce44SJohn Forte 	MATCHMAP *mp;
104fcf3ce44SJohn Forte 	MATCHMAP *mp1;
105fcf3ce44SJohn Forte 	uint8_t *inptr;
106fcf3ce44SJohn Forte 	uint8_t *outptr;
107fcf3ce44SJohn Forte 	uint32_t status;
108fcf3ce44SJohn Forte 	uint32_t i;
109fcf3ce44SJohn Forte 	uint32_t j;
110fcf3ce44SJohn Forte 	uint32_t read_rev_reset;
111fcf3ce44SJohn Forte 	uint32_t key = 0;
112fcf3ce44SJohn Forte 	uint32_t fw_check;
113fcf3ce44SJohn Forte 	uint32_t rval;
114fcf3ce44SJohn Forte 	uint32_t offset;
115fcf3ce44SJohn Forte 	uint8_t vpd_data[DMP_VPD_SIZE];
116fcf3ce44SJohn Forte 	uint32_t MaxRbusSize;
117fcf3ce44SJohn Forte 	uint32_t MaxIbusSize;
118fcf3ce44SJohn Forte 	uint32_t sli_mode;
119*291a2b48SSukumar Swaminathan 	uint32_t sli_mode_mask;
120fcf3ce44SJohn Forte 
121fcf3ce44SJohn Forte 	cfg = &CFG;
122fcf3ce44SJohn Forte 	vpd = &VPD;
123fcf3ce44SJohn Forte 	mb = 0;
124fcf3ce44SJohn Forte 	MaxRbusSize = 0;
125fcf3ce44SJohn Forte 	MaxIbusSize = 0;
126fcf3ce44SJohn Forte 	read_rev_reset = 0;
127*291a2b48SSukumar Swaminathan 
128*291a2b48SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
129*291a2b48SSukumar Swaminathan 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba,
130*291a2b48SSukumar Swaminathan 		    hba->sbus_csr_addr));
131*291a2b48SSukumar Swaminathan 	}
132fcf3ce44SJohn Forte 
133fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
134fcf3ce44SJohn Forte 	/* Initialize sli mode based on configuration parameter */
135fcf3ce44SJohn Forte 	switch (cfg[CFG_SLI_MODE].current) {
136fcf3ce44SJohn Forte 	case 2:	/* SLI2 mode */
137*291a2b48SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
138*291a2b48SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
139*291a2b48SSukumar Swaminathan 		break;
140*291a2b48SSukumar Swaminathan 
141*291a2b48SSukumar Swaminathan 	case 3:	/* SLI3 mode */
142*291a2b48SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI3_MODE;
143*291a2b48SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI3_MASK;
144fcf3ce44SJohn Forte 		break;
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte 	case 0:	/* Best available */
147fcf3ce44SJohn Forte 	case 1:	/* Best available */
148fcf3ce44SJohn Forte 	default:
149*291a2b48SSukumar Swaminathan 		if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
150*291a2b48SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI4_MODE;
151*291a2b48SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI4_MASK;
152*291a2b48SSukumar Swaminathan 		} else if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) {
153*291a2b48SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
154*291a2b48SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
155*291a2b48SSukumar Swaminathan 		} else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) {
156*291a2b48SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
157*291a2b48SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
158*291a2b48SSukumar Swaminathan 		}
159*291a2b48SSukumar Swaminathan 	}
160*291a2b48SSukumar Swaminathan 	/* SBUS adapters only available in SLI2 */
161*291a2b48SSukumar Swaminathan 	if (hba->bus_type == SBUS_FC) {
162*291a2b48SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
163*291a2b48SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
164fcf3ce44SJohn Forte 	}
165*291a2b48SSukumar Swaminathan 
166*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 	/* Set the fw_check flag */
169fcf3ce44SJohn Forte 	fw_check = cfg[CFG_FW_CHECK].current;
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte 	hba->mbox_queue_flag = 0;
172fcf3ce44SJohn Forte 	hba->hc_copy = 0;
173fcf3ce44SJohn Forte 	hba->fc_edtov = FF_DEF_EDTOV;
174fcf3ce44SJohn Forte 	hba->fc_ratov = FF_DEF_RATOV;
175fcf3ce44SJohn Forte 	hba->fc_altov = FF_DEF_ALTOV;
176fcf3ce44SJohn Forte 	hba->fc_arbtov = FF_DEF_ARBTOV;
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte reset:
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 	/* Reset and initialize the adapter */
181*291a2b48SSukumar Swaminathan 	if (emlxs_sli_online(hba)) {
182fcf3ce44SJohn Forte 		return (EIO);
183fcf3ce44SJohn Forte 	}
184*291a2b48SSukumar Swaminathan 
185*291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
186*291a2b48SSukumar Swaminathan 	/* Access handle validation */
187*291a2b48SSukumar Swaminathan 	if (hba->fm_caps & DDI_FM_ACCCHK_CAPABLE) {
188*291a2b48SSukumar Swaminathan 		if ((emlxs_fm_check_acc_handle(hba->pci_acc_handle)
189*291a2b48SSukumar Swaminathan 		    != DDI_FM_OK) ||
190*291a2b48SSukumar Swaminathan 		    (emlxs_fm_check_acc_handle(hba->slim_acc_handle)
191*291a2b48SSukumar Swaminathan 		    != DDI_FM_OK) ||
192*291a2b48SSukumar Swaminathan 		    (emlxs_fm_check_acc_handle(hba->csr_acc_handle)
193*291a2b48SSukumar Swaminathan 		    != DDI_FM_OK)) {
194*291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
195*291a2b48SSukumar Swaminathan 			    &emlxs_invalid_access_handle_msg, NULL);
196*291a2b48SSukumar Swaminathan 			return (EIO);
197*291a2b48SSukumar Swaminathan 		}
198*291a2b48SSukumar Swaminathan 	}
199*291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
200*291a2b48SSukumar Swaminathan 
201fcf3ce44SJohn Forte 	/*
202fcf3ce44SJohn Forte 	 * Allocate some memory for buffers
203fcf3ce44SJohn Forte 	 */
204fcf3ce44SJohn Forte 	if (emlxs_mem_alloc_buffer(hba) == 0) {
205fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
206fcf3ce44SJohn Forte 		    "Unable to allocate memory buffers.");
207fcf3ce44SJohn Forte 
208fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 		return (ENOMEM);
211fcf3ce44SJohn Forte 	}
212*291a2b48SSukumar Swaminathan 
213fcf3ce44SJohn Forte 	/*
214fcf3ce44SJohn Forte 	 * Get a buffer which will be used repeatedly for mailbox commands
215fcf3ce44SJohn Forte 	 */
216fcf3ce44SJohn Forte 	if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) {
217fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
218fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
221fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 		return (ENOMEM);
224fcf3ce44SJohn Forte 	}
225*291a2b48SSukumar Swaminathan 
226fcf3ce44SJohn Forte 	/* Check for the LP9802 (This is a special case) */
227fcf3ce44SJohn Forte 	/* We need to check for dual channel adapter */
228fcf3ce44SJohn Forte 	if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) {
229fcf3ce44SJohn Forte 		/* Try to determine if this is a DC adapter */
230fcf3ce44SJohn Forte 		if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) {
231fcf3ce44SJohn Forte 			if (MaxRbusSize == REDUCED_SRAM_CFG) {
232fcf3ce44SJohn Forte 				/* LP9802DC */
233fcf3ce44SJohn Forte 				for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
234fcf3ce44SJohn Forte 					if (emlxs_pci_model[i].id == LP9802DC) {
235fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
236fcf3ce44SJohn Forte 						    &hba->model_info,
237fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
238fcf3ce44SJohn Forte 						break;
239fcf3ce44SJohn Forte 					}
240fcf3ce44SJohn Forte 				}
241fcf3ce44SJohn Forte 			} else if (hba->model_info.id != LP9802) {
242fcf3ce44SJohn Forte 				/* LP9802 */
243fcf3ce44SJohn Forte 				for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
244fcf3ce44SJohn Forte 					if (emlxs_pci_model[i].id == LP9802) {
245fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
246fcf3ce44SJohn Forte 						    &hba->model_info,
247fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
248fcf3ce44SJohn Forte 						break;
249fcf3ce44SJohn Forte 					}
250fcf3ce44SJohn Forte 				}
251fcf3ce44SJohn Forte 			}
252fcf3ce44SJohn Forte 		}
253fcf3ce44SJohn Forte 	}
254*291a2b48SSukumar Swaminathan 
255fcf3ce44SJohn Forte 	/*
256fcf3ce44SJohn Forte 	 * Setup and issue mailbox READ REV command
257fcf3ce44SJohn Forte 	 */
258fcf3ce44SJohn Forte 	vpd->opFwRev = 0;
259fcf3ce44SJohn Forte 	vpd->postKernRev = 0;
260fcf3ce44SJohn Forte 	vpd->sli1FwRev = 0;
261fcf3ce44SJohn Forte 	vpd->sli2FwRev = 0;
262fcf3ce44SJohn Forte 	vpd->sli3FwRev = 0;
263fcf3ce44SJohn Forte 	vpd->sli4FwRev = 0;
264fcf3ce44SJohn Forte 
265fcf3ce44SJohn Forte 	vpd->postKernName[0] = 0;
266fcf3ce44SJohn Forte 	vpd->opFwName[0] = 0;
267fcf3ce44SJohn Forte 	vpd->sli1FwName[0] = 0;
268fcf3ce44SJohn Forte 	vpd->sli2FwName[0] = 0;
269fcf3ce44SJohn Forte 	vpd->sli3FwName[0] = 0;
270fcf3ce44SJohn Forte 	vpd->sli4FwName[0] = 0;
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte 	vpd->opFwLabel[0] = 0;
273fcf3ce44SJohn Forte 	vpd->sli1FwLabel[0] = 0;
274fcf3ce44SJohn Forte 	vpd->sli2FwLabel[0] = 0;
275fcf3ce44SJohn Forte 	vpd->sli3FwLabel[0] = 0;
276fcf3ce44SJohn Forte 	vpd->sli4FwLabel[0] = 0;
277fcf3ce44SJohn Forte 
278fcf3ce44SJohn Forte 	emlxs_ffstate_change(hba, FC_INIT_REV);
279fcf3ce44SJohn Forte 	emlxs_mb_read_rev(hba, mb, 0);
280*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
281fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
282fcf3ce44SJohn Forte 		    "Unable to read rev. Mailbox cmd=%x status=%x",
283fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
286fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
287fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
288fcf3ce44SJohn Forte 
289fcf3ce44SJohn Forte 		return (EIO);
290fcf3ce44SJohn Forte 	}
291*291a2b48SSukumar Swaminathan 
292fcf3ce44SJohn Forte 	if (mb->un.varRdRev.rr == 0) {
293fcf3ce44SJohn Forte 		/* Old firmware */
294fcf3ce44SJohn Forte 		if (read_rev_reset == 0) {
295fcf3ce44SJohn Forte 			/* Clean up */
296fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
297fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 			read_rev_reset = 1;
300fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte 			goto reset;
302fcf3ce44SJohn Forte 		} else {
303fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
304fcf3ce44SJohn Forte 			    "Outdated firmware detected.");
305fcf3ce44SJohn Forte 		}
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte 		vpd->rBit = 0;
308fcf3ce44SJohn Forte 	} else {
309fcf3ce44SJohn Forte 		if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) {
310fcf3ce44SJohn Forte 			if (read_rev_reset == 0) {
311fcf3ce44SJohn Forte 				/* Clean up */
312fcf3ce44SJohn Forte 				(void) emlxs_mem_put(hba, MEM_MBOX,
313fcf3ce44SJohn Forte 				    (uint8_t *)mb);
314fcf3ce44SJohn Forte 				(void) emlxs_mem_free_buffer(hba);
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 				read_rev_reset = 1;
317fcf3ce44SJohn Forte 
318fcf3ce44SJohn Forte 				goto reset;
319fcf3ce44SJohn Forte 			} else {
320fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
321fcf3ce44SJohn Forte 				    "Non-operational firmware detected. "
322fcf3ce44SJohn Forte 				    "type=%x",
323fcf3ce44SJohn Forte 				    mb->un.varRdRev.un.b.ProgType);
324fcf3ce44SJohn Forte 			}
325fcf3ce44SJohn Forte 		}
326*291a2b48SSukumar Swaminathan 
327fcf3ce44SJohn Forte 		vpd->rBit = 1;
328fcf3ce44SJohn Forte 		vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1;
329*291a2b48SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel,
330*291a2b48SSukumar Swaminathan 		    16);
331fcf3ce44SJohn Forte 		vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2;
332*291a2b48SSukumar Swaminathan 		bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel,
333*291a2b48SSukumar Swaminathan 		    16);
334fcf3ce44SJohn Forte 
335*291a2b48SSukumar Swaminathan 		/*
336*291a2b48SSukumar Swaminathan 		 * Lets try to read the SLI3 version
337*291a2b48SSukumar Swaminathan 		 * Setup and issue mailbox READ REV(v3) command
338*291a2b48SSukumar Swaminathan 		 */
339fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_INIT_REV);
340fcf3ce44SJohn Forte 		emlxs_mb_read_rev(hba, mb, 1);
341fcf3ce44SJohn Forte 
342*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
343*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
344fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
345fcf3ce44SJohn Forte 			    "Unable to read rev (v3). Mailbox cmd=%x status=%x",
346fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
347fcf3ce44SJohn Forte 
348fcf3ce44SJohn Forte 			emlxs_ffstate_change(hba, FC_ERROR);
349fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
350fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
351fcf3ce44SJohn Forte 
352fcf3ce44SJohn Forte 			return (EIO);
353fcf3ce44SJohn Forte 		}
354*291a2b48SSukumar Swaminathan 
355fcf3ce44SJohn Forte 		if (mb->un.varRdRev.rf3) {
356fcf3ce44SJohn Forte 			/*
357*291a2b48SSukumar Swaminathan 			 * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1;
358*291a2b48SSukumar Swaminathan 			 * Not needed
359fcf3ce44SJohn Forte 			 */
360fcf3ce44SJohn Forte 			vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2;
361fcf3ce44SJohn Forte 			bcopy((char *)mb->un.varRdRev.sliFwName2,
362fcf3ce44SJohn Forte 			    vpd->sli3FwLabel, 16);
363fcf3ce44SJohn Forte 		}
364fcf3ce44SJohn Forte 	}
365fcf3ce44SJohn Forte 
366*291a2b48SSukumar Swaminathan 
367*291a2b48SSukumar Swaminathan 	if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) {
368*291a2b48SSukumar Swaminathan 		if (vpd->sli2FwRev) {
369*291a2b48SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI2_MODE;
370*291a2b48SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI2_MASK;
371fcf3ce44SJohn Forte 		} else {
372fcf3ce44SJohn Forte 			sli_mode = 0;
373*291a2b48SSukumar Swaminathan 			sli_mode_mask = 0;
374fcf3ce44SJohn Forte 		}
375*291a2b48SSukumar Swaminathan 	}
376*291a2b48SSukumar Swaminathan 
377*291a2b48SSukumar Swaminathan 	else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) {
378*291a2b48SSukumar Swaminathan 		if (vpd->sli3FwRev) {
379*291a2b48SSukumar Swaminathan 			sli_mode = EMLXS_HBA_SLI3_MODE;
380*291a2b48SSukumar Swaminathan 			sli_mode_mask = EMLXS_SLI3_MASK;
381fcf3ce44SJohn Forte 		} else {
382fcf3ce44SJohn Forte 			sli_mode = 0;
383*291a2b48SSukumar Swaminathan 			sli_mode_mask = 0;
384fcf3ce44SJohn Forte 		}
385fcf3ce44SJohn Forte 	}
386*291a2b48SSukumar Swaminathan 
387*291a2b48SSukumar Swaminathan 	if (!(hba->model_info.sli_mask & sli_mode_mask)) {
388fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
389fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
390fcf3ce44SJohn Forte 		    "Firmware not available. sli-mode=%d",
391fcf3ce44SJohn Forte 		    cfg[CFG_SLI_MODE].current);
392fcf3ce44SJohn Forte #else
393fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
394fcf3ce44SJohn Forte 		    "Firmware not available. sli-mode=2");
395*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */
396fcf3ce44SJohn Forte 
397fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
398fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
399fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
400fcf3ce44SJohn Forte 
401fcf3ce44SJohn Forte 		return (EIO);
402fcf3ce44SJohn Forte 	}
403*291a2b48SSukumar Swaminathan 
404fcf3ce44SJohn Forte 	/* Save information as VPD data */
405fcf3ce44SJohn Forte 	vpd->postKernRev = mb->un.varRdRev.postKernRev;
406fcf3ce44SJohn Forte 	vpd->opFwRev = mb->un.varRdRev.opFwRev;
407fcf3ce44SJohn Forte 	bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16);
408fcf3ce44SJohn Forte 	vpd->biuRev = mb->un.varRdRev.biuRev;
409fcf3ce44SJohn Forte 	vpd->smRev = mb->un.varRdRev.smRev;
410fcf3ce44SJohn Forte 	vpd->smFwRev = mb->un.varRdRev.un.smFwRev;
411fcf3ce44SJohn Forte 	vpd->endecRev = mb->un.varRdRev.endecRev;
412fcf3ce44SJohn Forte 	vpd->fcphHigh = mb->un.varRdRev.fcphHigh;
413fcf3ce44SJohn Forte 	vpd->fcphLow = mb->un.varRdRev.fcphLow;
414fcf3ce44SJohn Forte 	vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh;
415fcf3ce44SJohn Forte 	vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow;
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte 	/* Decode FW names */
418fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->postKernRev, vpd->postKernName);
419fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->opFwRev, vpd->opFwName);
420fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName);
421fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName);
422fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName);
423fcf3ce44SJohn Forte 	emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName);
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 	/* Decode FW labels */
426fcf3ce44SJohn Forte 	emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel);
427fcf3ce44SJohn Forte 	emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel);
428fcf3ce44SJohn Forte 	emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel);
429fcf3ce44SJohn Forte 	emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel);
430fcf3ce44SJohn Forte 	emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel);
431fcf3ce44SJohn Forte 
432fcf3ce44SJohn Forte 	key = emlxs_get_key(hba, mb);
433fcf3ce44SJohn Forte 
434fcf3ce44SJohn Forte 	/* Get adapter VPD information */
435fcf3ce44SJohn Forte 	offset = 0;
436fcf3ce44SJohn Forte 	bzero(vpd_data, sizeof (vpd_data));
437fcf3ce44SJohn Forte 	vpd->port_index = (uint32_t)-1;
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	while (offset < DMP_VPD_SIZE) {
440fcf3ce44SJohn Forte 		emlxs_mb_dump_vpd(hba, mb, offset);
441*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
442*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
443fcf3ce44SJohn Forte 			/*
444*291a2b48SSukumar Swaminathan 			 * Let it go through even if failed.
445*291a2b48SSukumar Swaminathan 			 * Not all adapter's have VPD info and thus will
446*291a2b48SSukumar Swaminathan 			 * fail here. This is not a problem
447fcf3ce44SJohn Forte 			 */
448fcf3ce44SJohn Forte 
449fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
450*291a2b48SSukumar Swaminathan 			    "No VPD found. offset=%x status=%x", offset,
451*291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
452fcf3ce44SJohn Forte 			break;
453fcf3ce44SJohn Forte 		} else {
454fcf3ce44SJohn Forte 			if (mb->un.varDmp.ra == 1) {
455fcf3ce44SJohn Forte 				uint32_t *lp1, *lp2;
456fcf3ce44SJohn Forte 				uint32_t bsize;
457fcf3ce44SJohn Forte 				uint32_t wsize;
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 				/*
460fcf3ce44SJohn Forte 				 * mb->un.varDmp.word_cnt is actually byte
461fcf3ce44SJohn Forte 				 * count for the dump reply
462fcf3ce44SJohn Forte 				 */
463fcf3ce44SJohn Forte 				bsize = mb->un.varDmp.word_cnt;
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 				/* Stop if no data was received */
466fcf3ce44SJohn Forte 				if (bsize == 0) {
467fcf3ce44SJohn Forte 					break;
468fcf3ce44SJohn Forte 				}
469*291a2b48SSukumar Swaminathan 
470fcf3ce44SJohn Forte 				/* Check limit on byte size */
471*291a2b48SSukumar Swaminathan 				bsize = (bsize >
472*291a2b48SSukumar Swaminathan 				    (sizeof (vpd_data) - offset)) ?
473fcf3ce44SJohn Forte 				    (sizeof (vpd_data) - offset) : bsize;
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 				/*
476fcf3ce44SJohn Forte 				 * Convert size from bytes to words with
477fcf3ce44SJohn Forte 				 * minimum of 1 word
478fcf3ce44SJohn Forte 				 */
479fcf3ce44SJohn Forte 				wsize = (bsize > 4) ? (bsize >> 2) : 1;
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 				/*
482fcf3ce44SJohn Forte 				 * Transfer data into vpd_data buffer one
483fcf3ce44SJohn Forte 				 * word at a time
484fcf3ce44SJohn Forte 				 */
485fcf3ce44SJohn Forte 				lp1 = (uint32_t *)&mb->un.varDmp.resp_offset;
486fcf3ce44SJohn Forte 				lp2 = (uint32_t *)&vpd_data[offset];
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 				for (i = 0; i < wsize; i++) {
489fcf3ce44SJohn Forte 					status = *lp1++;
490fcf3ce44SJohn Forte 					*lp2++ = SWAP_LONG(status);
491fcf3ce44SJohn Forte 				}
492fcf3ce44SJohn Forte 
493fcf3ce44SJohn Forte 				/* Increment total byte count saved */
494fcf3ce44SJohn Forte 				offset += (wsize << 2);
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 				/*
497fcf3ce44SJohn Forte 				 * Stop if less than a full transfer was
498fcf3ce44SJohn Forte 				 * received
499fcf3ce44SJohn Forte 				 */
500fcf3ce44SJohn Forte 				if (wsize < DMP_VPD_DUMP_WCOUNT) {
501fcf3ce44SJohn Forte 					break;
502fcf3ce44SJohn Forte 				}
503*291a2b48SSukumar Swaminathan 
504fcf3ce44SJohn Forte 			} else {
505*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
506*291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
507*291a2b48SSukumar Swaminathan 				    "No VPD acknowledgment. offset=%x",
508*291a2b48SSukumar Swaminathan 				    offset);
509fcf3ce44SJohn Forte 				break;
510fcf3ce44SJohn Forte 			}
511fcf3ce44SJohn Forte 		}
512fcf3ce44SJohn Forte 
513fcf3ce44SJohn Forte 	}
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte 	if (vpd_data[0]) {
516fcf3ce44SJohn Forte 		(void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset);
517fcf3ce44SJohn Forte 
518fcf3ce44SJohn Forte 		/*
519*291a2b48SSukumar Swaminathan 		 * If there is a VPD part number, and it does not
520*291a2b48SSukumar Swaminathan 		 * match the current default HBA model info,
521*291a2b48SSukumar Swaminathan 		 * replace the default data with an entry that
522*291a2b48SSukumar Swaminathan 		 * does match.
523*291a2b48SSukumar Swaminathan 		 *
524*291a2b48SSukumar Swaminathan 		 * After emlxs_parse_vpd model holds the VPD value
525*291a2b48SSukumar Swaminathan 		 * for V2 and part_num hold the value for PN. These
526*291a2b48SSukumar Swaminathan 		 * 2 values are NOT necessarily the same.
527fcf3ce44SJohn Forte 		 */
528fcf3ce44SJohn Forte 
529*291a2b48SSukumar Swaminathan 		rval = 0;
530*291a2b48SSukumar Swaminathan 		if ((vpd->model[0] != 0) &&
531*291a2b48SSukumar Swaminathan 		    (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
532*291a2b48SSukumar Swaminathan 
533*291a2b48SSukumar Swaminathan 			/* First scan for a V2 match */
534*291a2b48SSukumar Swaminathan 
535*291a2b48SSukumar Swaminathan 			for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
536*291a2b48SSukumar Swaminathan 				if (strcmp(&vpd->model[0],
537*291a2b48SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
538*291a2b48SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
539*291a2b48SSukumar Swaminathan 					    &hba->model_info,
540*291a2b48SSukumar Swaminathan 					    sizeof (emlxs_model_t));
541*291a2b48SSukumar Swaminathan 					rval = 1;
542*291a2b48SSukumar Swaminathan 					break;
543fcf3ce44SJohn Forte 				}
544fcf3ce44SJohn Forte 			}
545fcf3ce44SJohn Forte 		}
546*291a2b48SSukumar Swaminathan 
547*291a2b48SSukumar Swaminathan 		if (!rval && (vpd->part_num[0] != 0) &&
548*291a2b48SSukumar Swaminathan 		    (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
549*291a2b48SSukumar Swaminathan 
550*291a2b48SSukumar Swaminathan 			/* Next scan for a PN match */
551*291a2b48SSukumar Swaminathan 
552*291a2b48SSukumar Swaminathan 			for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
553*291a2b48SSukumar Swaminathan 				if (strcmp(&vpd->part_num[0],
554*291a2b48SSukumar Swaminathan 				    emlxs_pci_model[i].model) == 0) {
555*291a2b48SSukumar Swaminathan 					bcopy(&emlxs_pci_model[i],
556*291a2b48SSukumar Swaminathan 					    &hba->model_info,
557*291a2b48SSukumar Swaminathan 					    sizeof (emlxs_model_t));
558*291a2b48SSukumar Swaminathan 					break;
559fcf3ce44SJohn Forte 				}
560fcf3ce44SJohn Forte 			}
561fcf3ce44SJohn Forte 		}
562*291a2b48SSukumar Swaminathan 
563fcf3ce44SJohn Forte 		/*
564*291a2b48SSukumar Swaminathan 		 * Now lets update hba->model_info with the real
565*291a2b48SSukumar Swaminathan 		 * VPD data, if any.
566*291a2b48SSukumar Swaminathan 		 */
567*291a2b48SSukumar Swaminathan 
568*291a2b48SSukumar Swaminathan 		/*
569*291a2b48SSukumar Swaminathan 		 * Replace the default model description with vpd data
570fcf3ce44SJohn Forte 		 */
571fcf3ce44SJohn Forte 		if (vpd->model_desc[0] != 0) {
572fcf3ce44SJohn Forte 			(void) strcpy(hba->model_info.model_desc,
573fcf3ce44SJohn Forte 			    vpd->model_desc);
574fcf3ce44SJohn Forte 		}
575*291a2b48SSukumar Swaminathan 
576fcf3ce44SJohn Forte 		/* Replace the default model with vpd data */
577fcf3ce44SJohn Forte 		if (vpd->model[0] != 0) {
578fcf3ce44SJohn Forte 			(void) strcpy(hba->model_info.model, vpd->model);
579fcf3ce44SJohn Forte 		}
580*291a2b48SSukumar Swaminathan 
581fcf3ce44SJohn Forte 		/* Replace the default program types with vpd data */
582fcf3ce44SJohn Forte 		if (vpd->prog_types[0] != 0) {
583fcf3ce44SJohn Forte 			emlxs_parse_prog_types(hba, vpd->prog_types);
584fcf3ce44SJohn Forte 		}
585fcf3ce44SJohn Forte 	}
586*291a2b48SSukumar Swaminathan 
587*291a2b48SSukumar Swaminathan 	/*
588*291a2b48SSukumar Swaminathan 	 * Since the adapter model may have changed with the vpd data
589*291a2b48SSukumar Swaminathan 	 * lets double check if adapter is not supported
590*291a2b48SSukumar Swaminathan 	 */
591fcf3ce44SJohn Forte 	if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
592fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
593*291a2b48SSukumar Swaminathan 		    "Unsupported adapter found.  "
594*291a2b48SSukumar Swaminathan 		    "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
595*291a2b48SSukumar Swaminathan 		    hba->model_info.id, hba->model_info.device_id,
596*291a2b48SSukumar Swaminathan 		    hba->model_info.ssdid, hba->model_info.model);
597fcf3ce44SJohn Forte 
598fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
599fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
600fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte 		return (EIO);
603fcf3ce44SJohn Forte 	}
604*291a2b48SSukumar Swaminathan 
605fcf3ce44SJohn Forte 	/* Read the adapter's wakeup parms */
606fcf3ce44SJohn Forte 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
607fcf3ce44SJohn Forte 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
608fcf3ce44SJohn Forte 	    vpd->boot_version);
609fcf3ce44SJohn Forte 
610fcf3ce44SJohn Forte 	/* Get fcode version property */
611fcf3ce44SJohn Forte 	emlxs_get_fcode_version(hba);
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
614*291a2b48SSukumar Swaminathan 	    "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
615*291a2b48SSukumar Swaminathan 	    vpd->opFwRev, vpd->sli1FwRev);
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
618*291a2b48SSukumar Swaminathan 	    "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
619*291a2b48SSukumar Swaminathan 	    vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
622fcf3ce44SJohn Forte 	    "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
623fcf3ce44SJohn Forte 
624fcf3ce44SJohn Forte 	/*
625*291a2b48SSukumar Swaminathan 	 * If firmware checking is enabled and the adapter model indicates
626*291a2b48SSukumar Swaminathan 	 * a firmware image, then perform firmware version check
627fcf3ce44SJohn Forte 	 */
628fcf3ce44SJohn Forte 	if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
629*291a2b48SSukumar Swaminathan 	    hba->model_info.fwid) || ((fw_check == 2) &&
630*291a2b48SSukumar Swaminathan 	    hba->model_info.fwid)) {
631*291a2b48SSukumar Swaminathan 		emlxs_firmware_t *fw;
632fcf3ce44SJohn Forte 
633fcf3ce44SJohn Forte 		/* Find firmware image indicated by adapter model */
634*291a2b48SSukumar Swaminathan 		fw = NULL;
635*291a2b48SSukumar Swaminathan 		for (i = 0; i < EMLXS_FW_COUNT; i++) {
636*291a2b48SSukumar Swaminathan 			if (emlxs_fw_table[i].id == hba->model_info.fwid) {
637*291a2b48SSukumar Swaminathan 				fw = &emlxs_fw_table[i];
638fcf3ce44SJohn Forte 				break;
639fcf3ce44SJohn Forte 			}
640fcf3ce44SJohn Forte 		}
641fcf3ce44SJohn Forte 
642fcf3ce44SJohn Forte 		/*
643fcf3ce44SJohn Forte 		 * If the image was found, then verify current firmware
644fcf3ce44SJohn Forte 		 * versions of adapter
645fcf3ce44SJohn Forte 		 */
646*291a2b48SSukumar Swaminathan 		if (fw) {
647*291a2b48SSukumar Swaminathan 			if ((vpd->postKernRev != fw->kern) ||
648*291a2b48SSukumar Swaminathan 			    (vpd->opFwRev != fw->stub) ||
649*291a2b48SSukumar Swaminathan 			    (vpd->sli1FwRev != fw->sli1) ||
650*291a2b48SSukumar Swaminathan 			    (vpd->sli2FwRev != fw->sli2) ||
651*291a2b48SSukumar Swaminathan 			    (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) ||
652*291a2b48SSukumar Swaminathan 			    (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) {
653fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
654*291a2b48SSukumar Swaminathan 				    "Firmware update needed. "
655*291a2b48SSukumar Swaminathan 				    "Updating. id=%d fw=%d",
656*291a2b48SSukumar Swaminathan 				    hba->model_info.id, hba->model_info.fwid);
657fcf3ce44SJohn Forte 
658*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
659*291a2b48SSukumar Swaminathan 				/*
660*291a2b48SSukumar Swaminathan 				 * Load the firmware image now
661*291a2b48SSukumar Swaminathan 				 * If MODFW_SUPPORT is not defined, the
662*291a2b48SSukumar Swaminathan 				 * firmware image will already be defined
663*291a2b48SSukumar Swaminathan 				 * in the emlxs_fw_table
664*291a2b48SSukumar Swaminathan 				 */
665*291a2b48SSukumar Swaminathan 				emlxs_fw_load(hba, fw);
666*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
667*291a2b48SSukumar Swaminathan 
668*291a2b48SSukumar Swaminathan 				if (fw->image && fw->size) {
669*291a2b48SSukumar Swaminathan 					if (emlxs_fw_download(hba,
670*291a2b48SSukumar Swaminathan 					    (char *)fw->image, fw->size, 0)) {
671*291a2b48SSukumar Swaminathan 						EMLXS_MSGF(EMLXS_CONTEXT,
672*291a2b48SSukumar Swaminathan 						    &emlxs_init_msg,
673*291a2b48SSukumar Swaminathan 						    "Firmware update failed.");
674*291a2b48SSukumar Swaminathan 					}
675*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
676*291a2b48SSukumar Swaminathan 					/*
677*291a2b48SSukumar Swaminathan 					 * Unload the firmware image from
678*291a2b48SSukumar Swaminathan 					 * kernel memory
679*291a2b48SSukumar Swaminathan 					 */
680*291a2b48SSukumar Swaminathan 					emlxs_fw_unload(hba, fw);
681*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
682fcf3ce44SJohn Forte 
683*291a2b48SSukumar Swaminathan 					(void) emlxs_mem_put(hba, MEM_MBOX,
684*291a2b48SSukumar Swaminathan 					    (uint8_t *)mb);
685*291a2b48SSukumar Swaminathan 					(void) emlxs_mem_free_buffer(hba);
686fcf3ce44SJohn Forte 
687*291a2b48SSukumar Swaminathan 					fw_check = 0;
688*291a2b48SSukumar Swaminathan 
689*291a2b48SSukumar Swaminathan 					goto reset;
690*291a2b48SSukumar Swaminathan 				}
691*291a2b48SSukumar Swaminathan 
692*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
693*291a2b48SSukumar Swaminathan 				    "Firmware image unavailable.");
694fcf3ce44SJohn Forte 			}
695fcf3ce44SJohn Forte 		} else {
696fcf3ce44SJohn Forte 			/* This should not happen */
697fcf3ce44SJohn Forte 
698fcf3ce44SJohn Forte 			/*
699fcf3ce44SJohn Forte 			 * This means either the adapter database is not
700fcf3ce44SJohn Forte 			 * correct or a firmware image is missing from the
701fcf3ce44SJohn Forte 			 * compile
702fcf3ce44SJohn Forte 			 */
703fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
704*291a2b48SSukumar Swaminathan 			    "Firmware image unavailable. id=%d fw=%d",
705fcf3ce44SJohn Forte 			    hba->model_info.id, hba->model_info.fwid);
706fcf3ce44SJohn Forte 		}
707fcf3ce44SJohn Forte 	}
708*291a2b48SSukumar Swaminathan 
709fcf3ce44SJohn Forte 	/*
710*291a2b48SSukumar Swaminathan 	 * Add our interrupt routine to kernel's interrupt chain & enable it
711*291a2b48SSukumar Swaminathan 	 * If MSI is enabled this will cause Solaris to program the MSI address
712*291a2b48SSukumar Swaminathan 	 * and data registers in PCI config space
713fcf3ce44SJohn Forte 	 */
714fcf3ce44SJohn Forte 	if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
715fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
716fcf3ce44SJohn Forte 		    "Unable to add interrupt(s).");
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
719fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
720fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
721fcf3ce44SJohn Forte 
722fcf3ce44SJohn Forte 		return (EIO);
723fcf3ce44SJohn Forte 	}
724fcf3ce44SJohn Forte 
725fcf3ce44SJohn Forte 	emlxs_ffstate_change(hba, FC_INIT_CFGPORT);
726fcf3ce44SJohn Forte 	(void) emlxs_mb_config_port(hba, mb, sli_mode, key);
727*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
728fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
729*291a2b48SSukumar Swaminathan 		    "Unable to configure port. "
730*291a2b48SSukumar Swaminathan 		    "Mailbox cmd=%x status=%x slimode=%d key=%x",
731*291a2b48SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus, sli_mode, key);
732fcf3ce44SJohn Forte 
733fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
734*291a2b48SSukumar Swaminathan 		for (sli_mode--; sli_mode > 0; sli_mode--) {
735*291a2b48SSukumar Swaminathan 			/* Check if sli_mode is supported by this adapter */
736*291a2b48SSukumar Swaminathan 			if (hba->model_info.sli_mask &
737*291a2b48SSukumar Swaminathan 			    EMLXS_SLI_MASK(sli_mode)) {
738*291a2b48SSukumar Swaminathan 				sli_mode_mask = EMLXS_SLI_MASK(sli_mode);
739*291a2b48SSukumar Swaminathan 				break;
740*291a2b48SSukumar Swaminathan 			}
741*291a2b48SSukumar Swaminathan 		}
742fcf3ce44SJohn Forte 
743*291a2b48SSukumar Swaminathan 		if (sli_mode) {
744fcf3ce44SJohn Forte 			/* Clean up */
745fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
746fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
747fcf3ce44SJohn Forte 
748fcf3ce44SJohn Forte 			fw_check = 0;
749fcf3ce44SJohn Forte 
750fcf3ce44SJohn Forte 			goto reset;
751fcf3ce44SJohn Forte 		}
752*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 		hba->flag &= ~FC_SLIM2_MODE;
755fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
756fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
757fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
758fcf3ce44SJohn Forte 
759fcf3ce44SJohn Forte 		return (EIO);
760fcf3ce44SJohn Forte 	}
761fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
762fcf3ce44SJohn Forte 	/* Check if SLI3 mode was achieved */
763*291a2b48SSukumar Swaminathan 	if (mb->un.varCfgPort.rMA &&
764*291a2b48SSukumar Swaminathan 	    (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) {
765fcf3ce44SJohn Forte 
766fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
767fcf3ce44SJohn Forte 		if (mb->un.varCfgPort.vpi_max > 1) {
768fcf3ce44SJohn Forte 			hba->flag |= FC_NPIV_ENABLED;
769fcf3ce44SJohn Forte 
770fcf3ce44SJohn Forte 			if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
771*291a2b48SSukumar Swaminathan 				hba->vpi_max =
772*291a2b48SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
773fcf3ce44SJohn Forte 				    MAX_VPORTS - 1);
774fcf3ce44SJohn Forte 			} else {
775*291a2b48SSukumar Swaminathan 				hba->vpi_max =
776*291a2b48SSukumar Swaminathan 				    min(mb->un.varCfgPort.vpi_max,
777fcf3ce44SJohn Forte 				    MAX_VPORTS_LIMITED - 1);
778fcf3ce44SJohn Forte 			}
779fcf3ce44SJohn Forte 		}
780*291a2b48SSukumar Swaminathan 
781*291a2b48SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5)
782*291a2b48SSukumar Swaminathan 		hba->fca_tran->fca_num_npivports =
783*291a2b48SSukumar Swaminathan 		    (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0;
784*291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */
785*291a2b48SSukumar Swaminathan 
786*291a2b48SSukumar Swaminathan #endif /* NPIV_SUPPORT */
787fcf3ce44SJohn Forte 
788fcf3ce44SJohn Forte 		if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) {
789fcf3ce44SJohn Forte 			hba->flag |= FC_HBQ_ENABLED;
790fcf3ce44SJohn Forte 		}
791*291a2b48SSukumar Swaminathan 
792fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
793fcf3ce44SJohn Forte 		    "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max);
794fcf3ce44SJohn Forte 	} else {
795fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
796fcf3ce44SJohn Forte 		    "SLI2 mode: flag=%x", hba->flag);
797*291a2b48SSukumar Swaminathan 		sli_mode = EMLXS_HBA_SLI2_MODE;
798*291a2b48SSukumar Swaminathan 		sli_mode_mask = EMLXS_SLI2_MASK;
799*291a2b48SSukumar Swaminathan 		hba->sli_mode = sli_mode;
800fcf3ce44SJohn Forte 	}
801*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */
802fcf3ce44SJohn Forte 
803fcf3ce44SJohn Forte 	/* Get and save the current firmware version (based on sli_mode) */
804fcf3ce44SJohn Forte 	emlxs_decode_firmware_rev(hba, vpd);
805fcf3ce44SJohn Forte 
806fcf3ce44SJohn Forte 	emlxs_pcix_mxr_update(hba, 0);
807fcf3ce44SJohn Forte 
808fcf3ce44SJohn Forte 	/*
809fcf3ce44SJohn Forte 	 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
810fcf3ce44SJohn Forte 	 */
811fcf3ce44SJohn Forte 	mp = 0;
812fcf3ce44SJohn Forte 	mp1 = 0;
813*291a2b48SSukumar Swaminathan 	if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) ||
814*291a2b48SSukumar Swaminathan 	    ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0)) {
815fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
816fcf3ce44SJohn Forte 		    "Unable to allocate diag buffers.");
817fcf3ce44SJohn Forte 
818fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
819fcf3ce44SJohn Forte 
820fcf3ce44SJohn Forte 		if (mp) {
821fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
822fcf3ce44SJohn Forte 		}
823fcf3ce44SJohn Forte 		if (mp1) {
824fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
825fcf3ce44SJohn Forte 		}
826*291a2b48SSukumar Swaminathan 
827fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
828fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
829fcf3ce44SJohn Forte 
830fcf3ce44SJohn Forte 		return (ENOMEM);
831fcf3ce44SJohn Forte 	}
832*291a2b48SSukumar Swaminathan 
833fcf3ce44SJohn Forte 	bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
834fcf3ce44SJohn Forte 	    MEM_ELSBUF_SIZE);
835fcf3ce44SJohn Forte 	emlxs_mpdata_sync(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
836fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 	bzero(mp1->virt, MEM_ELSBUF_SIZE);
839fcf3ce44SJohn Forte 	emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
840fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
841fcf3ce44SJohn Forte 
842fcf3ce44SJohn Forte 	(void) emlxs_mb_run_biu_diag(hba, mb, mp->phys, mp1->phys);
843fcf3ce44SJohn Forte 
844*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
845fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
846fcf3ce44SJohn Forte 		    "Unable to run BIU diag.  Mailbox cmd=%x status=%x",
847fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
848fcf3ce44SJohn Forte 
849fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
850fcf3ce44SJohn Forte 
851fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
852fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
853fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
854fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
855fcf3ce44SJohn Forte 
856fcf3ce44SJohn Forte 		return (EIO);
857fcf3ce44SJohn Forte 	}
858*291a2b48SSukumar Swaminathan 
859fcf3ce44SJohn Forte 	emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
860fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORKERNEL);
861fcf3ce44SJohn Forte 
862fcf3ce44SJohn Forte 	outptr = mp->virt;
863fcf3ce44SJohn Forte 	inptr = mp1->virt;
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte 	for (i = 0; i < MEM_ELSBUF_SIZE; i++) {
866fcf3ce44SJohn Forte 		if (*outptr++ != *inptr++) {
867fcf3ce44SJohn Forte 			outptr--;
868fcf3ce44SJohn Forte 			inptr--;
869fcf3ce44SJohn Forte 
870fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
871*291a2b48SSukumar Swaminathan 			    "BIU diagnostic failed. "
872*291a2b48SSukumar Swaminathan 			    "offset %x value %x should be %x.",
873*291a2b48SSukumar Swaminathan 			    i, (uint32_t)*inptr, (uint32_t)*outptr);
874fcf3ce44SJohn Forte 
875fcf3ce44SJohn Forte 			emlxs_ffstate_change(hba, FC_ERROR);
876fcf3ce44SJohn Forte 
877fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
878fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
879fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
880fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
881fcf3ce44SJohn Forte 
882fcf3ce44SJohn Forte 			return (EIO);
883fcf3ce44SJohn Forte 		}
884fcf3ce44SJohn Forte 	}
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
887fcf3ce44SJohn Forte 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1);
888fcf3ce44SJohn Forte 
889fcf3ce44SJohn Forte 	/*
890fcf3ce44SJohn Forte 	 * Setup and issue mailbox CONFIGURE RING command
891fcf3ce44SJohn Forte 	 */
892fcf3ce44SJohn Forte 	for (i = 0; i < (uint32_t)hba->ring_count; i++) {
893*291a2b48SSukumar Swaminathan 		/*
894*291a2b48SSukumar Swaminathan 		 * Initialize cmd/rsp ring pointers
895*291a2b48SSukumar Swaminathan 		 */
896*291a2b48SSukumar Swaminathan 		rp = &hba->ring[i];
897*291a2b48SSukumar Swaminathan 
898*291a2b48SSukumar Swaminathan 		rp->hba = hba;
899*291a2b48SSukumar Swaminathan 		rp->ringno = (uint8_t)i;
900*291a2b48SSukumar Swaminathan 
901*291a2b48SSukumar Swaminathan 		rp->fc_iocbhd = 0;
902*291a2b48SSukumar Swaminathan 		rp->fc_iocbtl = 0;
903*291a2b48SSukumar Swaminathan 		rp->fc_cmdidx = 0;
904*291a2b48SSukumar Swaminathan 		rp->fc_rspidx = 0;
905*291a2b48SSukumar Swaminathan 		rp->fc_iotag = 1;	/* Used for pkt io */
906*291a2b48SSukumar Swaminathan 		rp->fc_abort_iotag = rp->max_iotag;	/* Used for abort or */
907*291a2b48SSukumar Swaminathan 							/* close XRI iotags */
908fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_INIT_CFGRING);
909fcf3ce44SJohn Forte 		emlxs_mb_config_ring(hba, i, mb);
910*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
911*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
912fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
913*291a2b48SSukumar Swaminathan 			    "Unable to configure ring. "
914*291a2b48SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
915*291a2b48SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
916fcf3ce44SJohn Forte 
917fcf3ce44SJohn Forte 			emlxs_ffstate_change(hba, FC_ERROR);
918fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
919fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
920fcf3ce44SJohn Forte 
921fcf3ce44SJohn Forte 			return (EIO);
922fcf3ce44SJohn Forte 		}
923fcf3ce44SJohn Forte 	}
924fcf3ce44SJohn Forte 
925fcf3ce44SJohn Forte 	/*
926fcf3ce44SJohn Forte 	 * Setup link timers
927fcf3ce44SJohn Forte 	 */
928fcf3ce44SJohn Forte 	emlxs_ffstate_change(hba, FC_INIT_INITLINK);
929fcf3ce44SJohn Forte 	emlxs_mb_config_link(hba, mb);
930*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
931fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
932fcf3ce44SJohn Forte 		    "Unable to configure link. Mailbox cmd=%x status=%x",
933fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
936fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
937fcf3ce44SJohn Forte 		emlxs_ffcleanup(hba);
938fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
939fcf3ce44SJohn Forte 
940fcf3ce44SJohn Forte 		return (EIO);
941fcf3ce44SJohn Forte 	}
942fcf3ce44SJohn Forte #ifdef MAX_RRDY_PATCH
943fcf3ce44SJohn Forte 	/* Set MAX_RRDY if one is provided */
944fcf3ce44SJohn Forte 	if (cfg[CFG_MAX_RRDY].current) {
945*291a2b48SSukumar Swaminathan 		emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00060412,
946fcf3ce44SJohn Forte 		    cfg[CFG_MAX_RRDY].current);
947fcf3ce44SJohn Forte 
948*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
949*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
950fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
951fcf3ce44SJohn Forte 			    "MAX_RRDY: Unable to set.  status=%x value=%d",
952fcf3ce44SJohn Forte 			    mb->mbxStatus, cfg[CFG_MAX_RRDY].current);
953fcf3ce44SJohn Forte 		} else {
954fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
955fcf3ce44SJohn Forte 			    "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current);
956fcf3ce44SJohn Forte 		}
957fcf3ce44SJohn Forte 	}
958*291a2b48SSukumar Swaminathan #endif /* MAX_RRDY_PATCH */
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 	/*
961fcf3ce44SJohn Forte 	 * We need to get login parameters for NID
962fcf3ce44SJohn Forte 	 */
963fcf3ce44SJohn Forte 	(void) emlxs_mb_read_sparam(hba, mb);
964*291a2b48SSukumar Swaminathan 	mp = (MATCHMAP *)(((MAILBOXQ *)mb)->bp);
965*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
966fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
967fcf3ce44SJohn Forte 		    "Unable to read parameters. Mailbox cmd=%x status=%x",
968fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
969fcf3ce44SJohn Forte 
970fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
971fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
972fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
973fcf3ce44SJohn Forte 		emlxs_ffcleanup(hba);
974fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
975fcf3ce44SJohn Forte 
976fcf3ce44SJohn Forte 		return (EIO);
977fcf3ce44SJohn Forte 	}
978*291a2b48SSukumar Swaminathan 
979fcf3ce44SJohn Forte 	/* Free the buffer since we were polling */
980fcf3ce44SJohn Forte 	(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
981fcf3ce44SJohn Forte 
982fcf3ce44SJohn Forte 	/* If no serial number in VPD data, then use the WWPN */
983fcf3ce44SJohn Forte 	if (vpd->serial_num[0] == 0) {
984fcf3ce44SJohn Forte 		outptr = (uint8_t *)&hba->wwpn.IEEE[0];
985fcf3ce44SJohn Forte 		for (i = 0; i < 12; i++) {
986fcf3ce44SJohn Forte 			status = *outptr++;
987fcf3ce44SJohn Forte 			j = ((status & 0xf0) >> 4);
988fcf3ce44SJohn Forte 			if (j <= 9) {
989fcf3ce44SJohn Forte 				vpd->serial_num[i] =
990fcf3ce44SJohn Forte 				    (char)((uint8_t)'0' + (uint8_t)j);
991fcf3ce44SJohn Forte 			} else {
992fcf3ce44SJohn Forte 				vpd->serial_num[i] =
993fcf3ce44SJohn Forte 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
994fcf3ce44SJohn Forte 			}
995fcf3ce44SJohn Forte 
996fcf3ce44SJohn Forte 			i++;
997fcf3ce44SJohn Forte 			j = (status & 0xf);
998fcf3ce44SJohn Forte 			if (j <= 9) {
999fcf3ce44SJohn Forte 				vpd->serial_num[i] =
1000fcf3ce44SJohn Forte 				    (char)((uint8_t)'0' + (uint8_t)j);
1001fcf3ce44SJohn Forte 			} else {
1002fcf3ce44SJohn Forte 				vpd->serial_num[i] =
1003fcf3ce44SJohn Forte 				    (char)((uint8_t)'A' + (uint8_t)(j - 10));
1004fcf3ce44SJohn Forte 			}
1005fcf3ce44SJohn Forte 		}
1006fcf3ce44SJohn Forte 
1007fcf3ce44SJohn Forte 		/*
1008*291a2b48SSukumar Swaminathan 		 * Set port number and port index to zero
1009fcf3ce44SJohn Forte 		 * The WWN's are unique to each port and therefore port_num
1010*291a2b48SSukumar Swaminathan 		 * must equal zero. This effects the hba_fru_details structure
1011*291a2b48SSukumar Swaminathan 		 * in fca_bind_port()
1012fcf3ce44SJohn Forte 		 */
1013fcf3ce44SJohn Forte 		vpd->port_num[0] = 0;
1014fcf3ce44SJohn Forte 		vpd->port_index = 0;
1015fcf3ce44SJohn Forte 	}
1016*291a2b48SSukumar Swaminathan 
1017*291a2b48SSukumar Swaminathan 	/*
1018*291a2b48SSukumar Swaminathan 	 * Make first attempt to set a port index
1019*291a2b48SSukumar Swaminathan 	 * Check if this is a multifunction adapter
1020*291a2b48SSukumar Swaminathan 	 */
1021fcf3ce44SJohn Forte 	if ((vpd->port_index == -1) &&
1022fcf3ce44SJohn Forte 	    (hba->model_info.chip >= EMLXS_THOR_CHIP)) {
1023fcf3ce44SJohn Forte 		char *buffer;
1024fcf3ce44SJohn Forte 		int32_t i;
1025fcf3ce44SJohn Forte 
1026*291a2b48SSukumar Swaminathan 		/*
1027*291a2b48SSukumar Swaminathan 		 * The port address looks like this:
1028*291a2b48SSukumar Swaminathan 		 * 1	- for port index 0
1029*291a2b48SSukumar Swaminathan 		 * 1,1	- for port index 1
1030*291a2b48SSukumar Swaminathan 		 * 1,2	- for port index 2
1031*291a2b48SSukumar Swaminathan 		 */
1032fcf3ce44SJohn Forte 		buffer = ddi_get_name_addr(hba->dip);
1033fcf3ce44SJohn Forte 
1034fcf3ce44SJohn Forte 		if (buffer) {
1035fcf3ce44SJohn Forte 			vpd->port_index = 0;
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 			/* Reverse scan for a comma */
1038fcf3ce44SJohn Forte 			for (i = strlen(buffer) - 1; i > 0; i--) {
1039fcf3ce44SJohn Forte 				if (buffer[i] == ',') {
1040fcf3ce44SJohn Forte 					/* Comma found - set index now */
1041fcf3ce44SJohn Forte 					vpd->port_index =
1042fcf3ce44SJohn Forte 					    emlxs_strtol(&buffer[i + 1], 10);
1043fcf3ce44SJohn Forte 					break;
1044fcf3ce44SJohn Forte 				}
1045fcf3ce44SJohn Forte 			}
1046fcf3ce44SJohn Forte 		}
1047fcf3ce44SJohn Forte 	}
1048*291a2b48SSukumar Swaminathan 
1049fcf3ce44SJohn Forte 	/* Make final attempt to set a port index */
1050fcf3ce44SJohn Forte 	if (vpd->port_index == -1) {
1051fcf3ce44SJohn Forte 		dev_info_t *p_dip;
1052fcf3ce44SJohn Forte 		dev_info_t *c_dip;
1053fcf3ce44SJohn Forte 
1054fcf3ce44SJohn Forte 		p_dip = ddi_get_parent(hba->dip);
1055fcf3ce44SJohn Forte 		c_dip = ddi_get_child(p_dip);
1056fcf3ce44SJohn Forte 
1057fcf3ce44SJohn Forte 		vpd->port_index = 0;
1058fcf3ce44SJohn Forte 		while (c_dip && (hba->dip != c_dip)) {
1059fcf3ce44SJohn Forte 			c_dip = ddi_get_next_sibling(c_dip);
1060fcf3ce44SJohn Forte 			vpd->port_index++;
1061fcf3ce44SJohn Forte 		}
1062fcf3ce44SJohn Forte 	}
1063*291a2b48SSukumar Swaminathan 
1064fcf3ce44SJohn Forte 	if (vpd->port_num[0] == 0) {
1065fcf3ce44SJohn Forte 		if (hba->model_info.channels > 1) {
1066fcf3ce44SJohn Forte 			(void) sprintf(vpd->port_num, "%d", vpd->port_index);
1067fcf3ce44SJohn Forte 		}
1068fcf3ce44SJohn Forte 	}
1069*291a2b48SSukumar Swaminathan 
1070fcf3ce44SJohn Forte 	if (vpd->id[0] == 0) {
1071fcf3ce44SJohn Forte 		(void) strcpy(vpd->id, hba->model_info.model_desc);
1072fcf3ce44SJohn Forte 	}
1073*291a2b48SSukumar Swaminathan 
1074fcf3ce44SJohn Forte 	if (vpd->manufacturer[0] == 0) {
1075fcf3ce44SJohn Forte 		(void) strcpy(vpd->manufacturer, hba->model_info.manufacturer);
1076fcf3ce44SJohn Forte 	}
1077*291a2b48SSukumar Swaminathan 
1078fcf3ce44SJohn Forte 	if (vpd->part_num[0] == 0) {
1079fcf3ce44SJohn Forte 		(void) strcpy(vpd->part_num, hba->model_info.model);
1080fcf3ce44SJohn Forte 	}
1081*291a2b48SSukumar Swaminathan 
1082fcf3ce44SJohn Forte 	if (vpd->model_desc[0] == 0) {
1083fcf3ce44SJohn Forte 		(void) strcpy(vpd->model_desc, hba->model_info.model_desc);
1084fcf3ce44SJohn Forte 	}
1085*291a2b48SSukumar Swaminathan 
1086fcf3ce44SJohn Forte 	if (vpd->model[0] == 0) {
1087fcf3ce44SJohn Forte 		(void) strcpy(vpd->model, hba->model_info.model);
1088fcf3ce44SJohn Forte 	}
1089*291a2b48SSukumar Swaminathan 
1090fcf3ce44SJohn Forte 	if (vpd->prog_types[0] == 0) {
1091fcf3ce44SJohn Forte 		emlxs_build_prog_types(hba, vpd->prog_types);
1092fcf3ce44SJohn Forte 	}
1093*291a2b48SSukumar Swaminathan 
1094fcf3ce44SJohn Forte 	/* Create the symbolic names */
1095fcf3ce44SJohn Forte 	(void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s",
1096fcf3ce44SJohn Forte 	    hba->model_info.model, hba->vpd.fw_version, emlxs_version,
1097fcf3ce44SJohn Forte 	    (char *)utsname.nodename);
1098fcf3ce44SJohn Forte 
1099fcf3ce44SJohn Forte 	(void) sprintf(hba->spn,
1100fcf3ce44SJohn Forte 	    "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1101fcf3ce44SJohn Forte 	    hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
1102fcf3ce44SJohn Forte 	    hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
1103fcf3ce44SJohn Forte 	    hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1104fcf3ce44SJohn Forte 
1105fcf3ce44SJohn Forte 	if (cfg[CFG_NETWORK_ON].current) {
1106fcf3ce44SJohn Forte 		if ((hba->sparam.portName.nameType != NAME_IEEE) ||
1107fcf3ce44SJohn Forte 		    (hba->sparam.portName.IEEEextMsn != 0) ||
1108fcf3ce44SJohn Forte 		    (hba->sparam.portName.IEEEextLsb != 0)) {
1109fcf3ce44SJohn Forte 
1110fcf3ce44SJohn Forte 			cfg[CFG_NETWORK_ON].current = 0;
1111fcf3ce44SJohn Forte 
1112fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1113fcf3ce44SJohn Forte 			    "WWPN doesn't conform to IP profile: nameType=%x",
1114fcf3ce44SJohn Forte 			    hba->sparam.portName.nameType);
1115fcf3ce44SJohn Forte 		}
1116*291a2b48SSukumar Swaminathan 
1117fcf3ce44SJohn Forte 		/* Issue CONFIG FARP */
1118fcf3ce44SJohn Forte 		emlxs_mb_config_farp(hba, mb);
1119*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
1120*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
1121fcf3ce44SJohn Forte 			/*
1122fcf3ce44SJohn Forte 			 * Let it go through even if failed.
1123fcf3ce44SJohn Forte 			 */
1124fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1125*291a2b48SSukumar Swaminathan 			    "Unable to configure FARP. "
1126*291a2b48SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1127*291a2b48SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1128fcf3ce44SJohn Forte 		}
1129fcf3ce44SJohn Forte 	}
1130fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
1131fcf3ce44SJohn Forte 	/* Configure MSI map if required */
1132fcf3ce44SJohn Forte 	if (hba->intr_count > 1) {
1133fcf3ce44SJohn Forte 		emlxs_mb_config_msix(hba, mb, hba->intr_map, hba->intr_count);
1134fcf3ce44SJohn Forte 
1135*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) ==
1136*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
1137fcf3ce44SJohn Forte 			goto msi_configured;
1138fcf3ce44SJohn Forte 		}
1139*291a2b48SSukumar Swaminathan 
1140fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1141fcf3ce44SJohn Forte 		    "Unable to config MSIX.  Mailbox cmd=0x%x status=0x%x",
1142fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
1143fcf3ce44SJohn Forte 
1144fcf3ce44SJohn Forte 		emlxs_mb_config_msi(hba, mb, hba->intr_map, hba->intr_count);
1145fcf3ce44SJohn Forte 
1146*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) ==
1147*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
1148fcf3ce44SJohn Forte 			goto msi_configured;
1149fcf3ce44SJohn Forte 		}
1150*291a2b48SSukumar Swaminathan 
1151*291a2b48SSukumar Swaminathan 
1152fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1153fcf3ce44SJohn Forte 		    "Unable to config MSI.  Mailbox cmd=0x%x status=0x%x",
1154fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
1155fcf3ce44SJohn Forte 
1156fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1157fcf3ce44SJohn Forte 		    "Attempting single interrupt mode...");
1158fcf3ce44SJohn Forte 
1159fcf3ce44SJohn Forte 		/* First cleanup old interrupts */
1160fcf3ce44SJohn Forte 		(void) emlxs_msi_remove(hba);
1161fcf3ce44SJohn Forte 		(void) emlxs_msi_uninit(hba);
1162fcf3ce44SJohn Forte 
1163fcf3ce44SJohn Forte 		status = emlxs_msi_init(hba, 1);
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte 		if (status != DDI_SUCCESS) {
1166fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1167fcf3ce44SJohn Forte 			    "Unable to initialize interrupt. status=%d",
1168fcf3ce44SJohn Forte 			    status);
1169fcf3ce44SJohn Forte 
1170fcf3ce44SJohn Forte 			emlxs_ffstate_change(hba, FC_ERROR);
1171fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1172fcf3ce44SJohn Forte 			emlxs_ffcleanup(hba);
1173fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte 			return (EIO);
1176fcf3ce44SJohn Forte 		}
1177*291a2b48SSukumar Swaminathan 
1178fcf3ce44SJohn Forte 		/*
1179*291a2b48SSukumar Swaminathan 		 * Reset adapter - The adapter needs to be reset because
1180*291a2b48SSukumar Swaminathan 		 * the bus cannot handle the MSI change without handshaking
1181*291a2b48SSukumar Swaminathan 		 * with the adapter again
1182fcf3ce44SJohn Forte 		 */
1183fcf3ce44SJohn Forte 
1184fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1185fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
1186fcf3ce44SJohn Forte 		fw_check = 0;
1187fcf3ce44SJohn Forte 		goto reset;
1188fcf3ce44SJohn Forte 	}
1189*291a2b48SSukumar Swaminathan 
1190fcf3ce44SJohn Forte msi_configured:
1191fcf3ce44SJohn Forte 
1192*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
1193fcf3ce44SJohn Forte 
1194fcf3ce44SJohn Forte 	/*
1195fcf3ce44SJohn Forte 	 * We always disable the firmware traffic cop feature
1196fcf3ce44SJohn Forte 	 */
1197fcf3ce44SJohn Forte 	if (emlxs_disable_traffic_cop) {
1198*291a2b48SSukumar Swaminathan 		emlxs_disable_tc(hba, (MAILBOX *)mb);
1199*291a2b48SSukumar Swaminathan 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
1200*291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
1201fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1202*291a2b48SSukumar Swaminathan 			    "Unable to disable traffic cop. "
1203*291a2b48SSukumar Swaminathan 			    "Mailbox cmd=%x status=%x",
1204*291a2b48SSukumar Swaminathan 			    mb->mbxCommand, mb->mbxStatus);
1205fcf3ce44SJohn Forte 
1206fcf3ce44SJohn Forte 			(void) EMLXS_INTR_REMOVE(hba);
1207fcf3ce44SJohn Forte 			emlxs_ffstate_change(hba, FC_ERROR);
1208fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1209fcf3ce44SJohn Forte 			emlxs_ffcleanup(hba);
1210fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
1211fcf3ce44SJohn Forte 
1212fcf3ce44SJohn Forte 			return (EIO);
1213fcf3ce44SJohn Forte 		}
1214fcf3ce44SJohn Forte 	}
1215*291a2b48SSukumar Swaminathan 
1216*291a2b48SSukumar Swaminathan 	emlxs_mb_read_config(hba, (MAILBOX *)mb);
1217*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1218fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1219fcf3ce44SJohn Forte 		    "Unable to read configuration.  Mailbox cmd=%x status=%x",
1220fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
1221fcf3ce44SJohn Forte 
1222fcf3ce44SJohn Forte 		(void) EMLXS_INTR_REMOVE(hba);
1223fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
1224fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1225fcf3ce44SJohn Forte 		emlxs_ffcleanup(hba);
1226fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
1227fcf3ce44SJohn Forte 
1228fcf3ce44SJohn Forte 		return (EIO);
1229fcf3ce44SJohn Forte 	}
1230*291a2b48SSukumar Swaminathan 
1231fcf3ce44SJohn Forte 	/* Save the link speed capabilities */
1232fcf3ce44SJohn Forte 	vpd->link_speed = mb->un.varRdConfig.lmt;
1233fcf3ce44SJohn Forte 	emlxs_process_link_speed(hba);
1234fcf3ce44SJohn Forte 
1235fcf3ce44SJohn Forte 	/* Set the io throttle */
1236fcf3ce44SJohn Forte 	hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE;
1237fcf3ce44SJohn Forte 
1238fcf3ce44SJohn Forte 	/* Set the max node count */
1239fcf3ce44SJohn Forte 	if (cfg[CFG_NUM_NODES].current > 0) {
1240fcf3ce44SJohn Forte 		hba->max_nodes =
1241*291a2b48SSukumar Swaminathan 		    min(cfg[CFG_NUM_NODES].current,
1242*291a2b48SSukumar Swaminathan 		    mb->un.varRdConfig.max_rpi);
1243fcf3ce44SJohn Forte 	} else {
1244fcf3ce44SJohn Forte 		hba->max_nodes = mb->un.varRdConfig.max_rpi;
1245fcf3ce44SJohn Forte 	}
1246fcf3ce44SJohn Forte 
1247*291a2b48SSukumar Swaminathan 	/* Register for async events */
1248*291a2b48SSukumar Swaminathan 	emlxs_mb_async_event(hba, mb);
1249*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1250*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1251*291a2b48SSukumar Swaminathan 		    "Async events disabled. Mailbox status=%x",
1252*291a2b48SSukumar Swaminathan 		    mb->mbxStatus);
1253*291a2b48SSukumar Swaminathan 	} else {
1254*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1255*291a2b48SSukumar Swaminathan 		    "Async events enabled.");
1256*291a2b48SSukumar Swaminathan 		hba->flag |= FC_ASYNC_EVENTS;
1257*291a2b48SSukumar Swaminathan 	}
1258fcf3ce44SJohn Forte 
1259*291a2b48SSukumar Swaminathan 	emlxs_ffstate_change(hba, FC_LINK_DOWN);
1260fcf3ce44SJohn Forte 
1261*291a2b48SSukumar Swaminathan 	emlxs_intr_initialize(hba);
1262fcf3ce44SJohn Forte 
1263fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1264fcf3ce44SJohn Forte 
1265fcf3ce44SJohn Forte 	if (hba->flag & FC_HBQ_ENABLED) {
1266fcf3ce44SJohn Forte 		if (hba->tgt_mode) {
1267fcf3ce44SJohn Forte 			if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) {
1268fcf3ce44SJohn Forte 				return (ENOMEM);
1269fcf3ce44SJohn Forte 			}
1270fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1271fcf3ce44SJohn Forte 			    "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1272fcf3ce44SJohn Forte 		}
1273*291a2b48SSukumar Swaminathan 
1274fcf3ce44SJohn Forte 		if (cfg[CFG_NETWORK_ON].current) {
1275fcf3ce44SJohn Forte 			if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) {
1276fcf3ce44SJohn Forte 				return (ENOMEM);
1277fcf3ce44SJohn Forte 			}
1278fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1279fcf3ce44SJohn Forte 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1280fcf3ce44SJohn Forte 		}
1281*291a2b48SSukumar Swaminathan 
1282fcf3ce44SJohn Forte 		if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) {
1283fcf3ce44SJohn Forte 			return (ENOMEM);
1284fcf3ce44SJohn Forte 		}
1285fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1286fcf3ce44SJohn Forte 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1287fcf3ce44SJohn Forte 
1288fcf3ce44SJohn Forte 		if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) {
1289fcf3ce44SJohn Forte 			return (ENOMEM);
1290fcf3ce44SJohn Forte 		}
1291fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1292fcf3ce44SJohn Forte 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1293fcf3ce44SJohn Forte 	} else
1294*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */
1295fcf3ce44SJohn Forte 	{
1296fcf3ce44SJohn Forte 		if (hba->tgt_mode) {
1297fcf3ce44SJohn Forte 			/* Post the FCT unsol buffers */
1298fcf3ce44SJohn Forte 			rp = &hba->ring[FC_FCT_RING];
1299fcf3ce44SJohn Forte 			for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) {
1300fcf3ce44SJohn Forte 				(void) emlxs_post_buffer(hba, rp, 2);
1301fcf3ce44SJohn Forte 			}
1302fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1303fcf3ce44SJohn Forte 			    "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1304fcf3ce44SJohn Forte 		}
1305*291a2b48SSukumar Swaminathan 
1306fcf3ce44SJohn Forte 		if (cfg[CFG_NETWORK_ON].current) {
1307fcf3ce44SJohn Forte 			/* Post the IP unsol buffers */
1308fcf3ce44SJohn Forte 			rp = &hba->ring[FC_IP_RING];
1309fcf3ce44SJohn Forte 			for (j = 0; j < MEM_IPBUF_COUNT; j += 2) {
1310fcf3ce44SJohn Forte 				(void) emlxs_post_buffer(hba, rp, 2);
1311fcf3ce44SJohn Forte 			}
1312fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1313fcf3ce44SJohn Forte 			    "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1314fcf3ce44SJohn Forte 		}
1315*291a2b48SSukumar Swaminathan 
1316fcf3ce44SJohn Forte 		/* Post the ELS unsol buffers */
1317fcf3ce44SJohn Forte 		rp = &hba->ring[FC_ELS_RING];
1318fcf3ce44SJohn Forte 		for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) {
1319fcf3ce44SJohn Forte 			(void) emlxs_post_buffer(hba, rp, 2);
1320fcf3ce44SJohn Forte 		}
1321fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1322fcf3ce44SJohn Forte 		    "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1323fcf3ce44SJohn Forte 
1324fcf3ce44SJohn Forte 
1325fcf3ce44SJohn Forte 		/* Post the CT unsol buffers */
1326fcf3ce44SJohn Forte 		rp = &hba->ring[FC_CT_RING];
1327fcf3ce44SJohn Forte 		for (j = 0; j < MEM_CTBUF_COUNT; j += 2) {
1328fcf3ce44SJohn Forte 			(void) emlxs_post_buffer(hba, rp, 2);
1329fcf3ce44SJohn Forte 		}
1330fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1331fcf3ce44SJohn Forte 		    "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1332fcf3ce44SJohn Forte 	}
1333fcf3ce44SJohn Forte 
1334fcf3ce44SJohn Forte 
1335fcf3ce44SJohn Forte 	/*
1336*291a2b48SSukumar Swaminathan 	 * Setup and issue mailbox INITIALIZE LINK command At this point,
1337*291a2b48SSukumar Swaminathan 	 * the interrupt will be generated by the HW
1338fcf3ce44SJohn Forte 	 */
1339*291a2b48SSukumar Swaminathan 	emlxs_mb_init_link(hba,
1340*291a2b48SSukumar Swaminathan 	    mb, cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
1341fcf3ce44SJohn Forte 
1342*291a2b48SSukumar Swaminathan 	rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0);
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte 	if (rval != MBX_SUCCESS && rval != MBX_BUSY) {
1345fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1346fcf3ce44SJohn Forte 		    "Unable to initialize link.  Mailbox cmd=%x status=%x",
1347fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
1348fcf3ce44SJohn Forte 
1349fcf3ce44SJohn Forte 		(void) EMLXS_INTR_REMOVE(hba);
1350fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
1351fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1352fcf3ce44SJohn Forte 		emlxs_ffcleanup(hba);
1353fcf3ce44SJohn Forte 		(void) emlxs_mem_free_buffer(hba);
1354fcf3ce44SJohn Forte 
1355fcf3ce44SJohn Forte 		return (EIO);
1356fcf3ce44SJohn Forte 	}
1357*291a2b48SSukumar Swaminathan 
1358fcf3ce44SJohn Forte 	(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
1359fcf3ce44SJohn Forte 
1360fcf3ce44SJohn Forte 	/*
1361fcf3ce44SJohn Forte 	 * Enable link attention interrupt
1362fcf3ce44SJohn Forte 	 */
1363*291a2b48SSukumar Swaminathan 	emlxs_enable_latt(hba);
1364fcf3ce44SJohn Forte 
1365fcf3ce44SJohn Forte 	/* Wait for link to come up */
1366fcf3ce44SJohn Forte 	i = cfg[CFG_LINKUP_DELAY].current;
1367fcf3ce44SJohn Forte 	while (i && (hba->state < FC_LINK_UP)) {
1368fcf3ce44SJohn Forte 		/* Check for hardware error */
1369fcf3ce44SJohn Forte 		if (hba->state == FC_ERROR) {
1370fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1371fcf3ce44SJohn Forte 			    "Adapter error.", mb->mbxCommand, mb->mbxStatus);
1372fcf3ce44SJohn Forte 
1373fcf3ce44SJohn Forte 			(void) EMLXS_INTR_REMOVE(hba);
1374fcf3ce44SJohn Forte 			emlxs_ffcleanup(hba);
1375fcf3ce44SJohn Forte 			(void) emlxs_mem_free_buffer(hba);
1376fcf3ce44SJohn Forte 
1377fcf3ce44SJohn Forte 			return (EIO);
1378fcf3ce44SJohn Forte 		}
1379*291a2b48SSukumar Swaminathan 
1380fcf3ce44SJohn Forte 		DELAYMS(1000);
1381fcf3ce44SJohn Forte 		i--;
1382fcf3ce44SJohn Forte 	}
1383fcf3ce44SJohn Forte 
1384fcf3ce44SJohn Forte out:
1385fcf3ce44SJohn Forte 
1386fcf3ce44SJohn Forte 	/*
1387fcf3ce44SJohn Forte 	 * The leadvile driver will now handle the FLOGI at the driver level
1388fcf3ce44SJohn Forte 	 */
1389fcf3ce44SJohn Forte 
1390fcf3ce44SJohn Forte 	return (0);
1391*291a2b48SSukumar Swaminathan }  /* emlxs_ffinit() */
1392fcf3ce44SJohn Forte 
1393fcf3ce44SJohn Forte 
1394fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
1395fcf3ce44SJohn Forte 
1396fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
1397fcf3ce44SJohn Forte int32_t
1398fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
1399fcf3ce44SJohn Forte {
1400fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1401fcf3ce44SJohn Forte 	int32_t pass = 0;
1402fcf3ce44SJohn Forte 	int32_t type = 0;
1403fcf3ce44SJohn Forte 	char s_type[16];
1404fcf3ce44SJohn Forte 	int32_t types;
1405fcf3ce44SJohn Forte 	int32_t count;
1406fcf3ce44SJohn Forte 	int32_t nintrs;
1407fcf3ce44SJohn Forte 	int32_t mode;
1408fcf3ce44SJohn Forte 	int32_t actual;
1409fcf3ce44SJohn Forte 	int32_t new_actual;
1410fcf3ce44SJohn Forte 	int32_t i;
1411fcf3ce44SJohn Forte 	int32_t ret;
1412fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable = NULL;
1413fcf3ce44SJohn Forte 	ddi_intr_handle_t *new_htable = NULL;
1414fcf3ce44SJohn Forte 	uint32_t *intr_pri = NULL;
1415fcf3ce44SJohn Forte 	int32_t *intr_cap = NULL;
1416fcf3ce44SJohn Forte 	int32_t hilevel_pri;
1417fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
1418fcf3ce44SJohn Forte 	char buf[64];
1419fcf3ce44SJohn Forte 
1420fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
1421fcf3ce44SJohn Forte 		return (emlxs_intx_init(hba, max));
1422fcf3ce44SJohn Forte 	}
1423*291a2b48SSukumar Swaminathan 
1424fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_MSI_INITED) {
1425fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1426fcf3ce44SJohn Forte 	}
1427*291a2b48SSukumar Swaminathan 
1428fcf3ce44SJohn Forte 	/* Set max interrupt count if not specified */
1429fcf3ce44SJohn Forte 	if (max == 0) {
1430fcf3ce44SJohn Forte 		if ((cfg[CFG_MSI_MODE].current == 2) ||
1431fcf3ce44SJohn Forte 		    (cfg[CFG_MSI_MODE].current == 3)) {
1432fcf3ce44SJohn Forte 			max = EMLXS_MSI_MAX_INTRS;
1433fcf3ce44SJohn Forte 		} else {
1434fcf3ce44SJohn Forte 			max = 1;
1435fcf3ce44SJohn Forte 		}
1436fcf3ce44SJohn Forte 	}
1437*291a2b48SSukumar Swaminathan 
1438fcf3ce44SJohn Forte 	/* Filter max interrupt count with adapter model specification */
1439fcf3ce44SJohn Forte 	if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
1440fcf3ce44SJohn Forte 		max = hba->model_info.intr_limit;
1441fcf3ce44SJohn Forte 	}
1442*291a2b48SSukumar Swaminathan 
1443fcf3ce44SJohn Forte 	/* Get the available interrupt types from the kernel */
1444fcf3ce44SJohn Forte 	types = 0;
1445fcf3ce44SJohn Forte 	ret = ddi_intr_get_supported_types(hba->dip, &types);
1446fcf3ce44SJohn Forte 
1447fcf3ce44SJohn Forte 	if ((ret != DDI_SUCCESS)) {
1448fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1449fcf3ce44SJohn Forte 		    "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 		/* Default to fixed type */
1452fcf3ce44SJohn Forte 		types = DDI_INTR_TYPE_FIXED;
1453fcf3ce44SJohn Forte 	}
1454*291a2b48SSukumar Swaminathan 
1455fcf3ce44SJohn Forte 	/* Check if fixed interrupts are being forced */
1456fcf3ce44SJohn Forte 	if (cfg[CFG_MSI_MODE].current == 0) {
1457fcf3ce44SJohn Forte 		types &= DDI_INTR_TYPE_FIXED;
1458fcf3ce44SJohn Forte 	}
1459*291a2b48SSukumar Swaminathan 
1460fcf3ce44SJohn Forte 	/* Check if MSI interrupts are being forced */
1461fcf3ce44SJohn Forte 	else if ((cfg[CFG_MSI_MODE].current == 1) ||
1462fcf3ce44SJohn Forte 	    (cfg[CFG_MSI_MODE].current == 2)) {
1463fcf3ce44SJohn Forte 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
1464fcf3ce44SJohn Forte 	}
1465*291a2b48SSukumar Swaminathan 
1466fcf3ce44SJohn Forte begin:
1467fcf3ce44SJohn Forte 
1468fcf3ce44SJohn Forte 	/* Set interrupt type and interrupt count */
1469fcf3ce44SJohn Forte 	type = 0;
1470fcf3ce44SJohn Forte 
1471fcf3ce44SJohn Forte 	/* Check if MSIX is fully supported */
1472fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_MSIX) &&
1473fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
1474fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
1475fcf3ce44SJohn Forte 		nintrs = 0;
1476fcf3ce44SJohn Forte 		ret =
1477*291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
1478*291a2b48SSukumar Swaminathan 		    &nintrs);
1479fcf3ce44SJohn Forte 
1480fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS && nintrs) {
1481fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_MSIX;
1482fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_MSIX");
1483fcf3ce44SJohn Forte 			goto initialize;
1484fcf3ce44SJohn Forte 		}
1485fcf3ce44SJohn Forte 	}
1486*291a2b48SSukumar Swaminathan 
1487fcf3ce44SJohn Forte 	/* Check if MSI is fully supported */
1488fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_MSI) &&
1489fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
1490fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
1491fcf3ce44SJohn Forte 		nintrs = 0;
1492*291a2b48SSukumar Swaminathan 		ret =
1493*291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
1494fcf3ce44SJohn Forte 
1495fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS && nintrs) {
1496fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_MSI;
1497fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_MSI");
1498fcf3ce44SJohn Forte 			goto initialize;
1499fcf3ce44SJohn Forte 		}
1500fcf3ce44SJohn Forte 	}
1501*291a2b48SSukumar Swaminathan 
1502fcf3ce44SJohn Forte 	/* Check if fixed interrupts are fully supported */
1503fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_FIXED) &&
1504fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
1505fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
1506fcf3ce44SJohn Forte 		nintrs = 0;
1507fcf3ce44SJohn Forte 		ret =
1508*291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
1509*291a2b48SSukumar Swaminathan 		    &nintrs);
1510fcf3ce44SJohn Forte 
1511fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS) {
1512fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_FIXED;
1513fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_FIXED");
1514fcf3ce44SJohn Forte 			goto initialize;
1515fcf3ce44SJohn Forte 		}
1516fcf3ce44SJohn Forte 	}
1517*291a2b48SSukumar Swaminathan 
1518fcf3ce44SJohn Forte 	goto init_failed;
1519fcf3ce44SJohn Forte 
1520fcf3ce44SJohn Forte 
1521fcf3ce44SJohn Forte initialize:
1522fcf3ce44SJohn Forte 
1523fcf3ce44SJohn Forte 	pass++;
1524fcf3ce44SJohn Forte 	mode = 0;
1525fcf3ce44SJohn Forte 	actual = 0;
1526fcf3ce44SJohn Forte 	htable = NULL;
1527fcf3ce44SJohn Forte 	intr_pri = NULL;
1528fcf3ce44SJohn Forte 	intr_cap = NULL;
1529fcf3ce44SJohn Forte 	hilevel_pri = 0;
1530fcf3ce44SJohn Forte 
1531fcf3ce44SJohn Forte 	if (pass == 1) {
1532fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1533*291a2b48SSukumar Swaminathan 		    "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
1534*291a2b48SSukumar Swaminathan 		    cfg[CFG_MSI_MODE].current, types, nintrs);
1535fcf3ce44SJohn Forte 	}
1536*291a2b48SSukumar Swaminathan 
1537fcf3ce44SJohn Forte 	/* Validate interrupt count */
1538fcf3ce44SJohn Forte 	count = min(nintrs, max);
1539fcf3ce44SJohn Forte 
1540fcf3ce44SJohn Forte 	if (count >= 8) {
1541fcf3ce44SJohn Forte 		count = 8;
1542fcf3ce44SJohn Forte 	} else if (count >= 4) {
1543fcf3ce44SJohn Forte 		count = 4;
1544fcf3ce44SJohn Forte 	} else if (count >= 2) {
1545fcf3ce44SJohn Forte 		count = 2;
1546fcf3ce44SJohn Forte 	} else {
1547fcf3ce44SJohn Forte 		count = 1;
1548fcf3ce44SJohn Forte 	}
1549fcf3ce44SJohn Forte 
1550fcf3ce44SJohn Forte 	/* Allocate an array of interrupt handles */
1551fcf3ce44SJohn Forte 	htable =
1552*291a2b48SSukumar Swaminathan 	    kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
1553*291a2b48SSukumar Swaminathan 	    KM_SLEEP);
1554fcf3ce44SJohn Forte 
1555fcf3ce44SJohn Forte 	if (htable == NULL) {
1556fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1557fcf3ce44SJohn Forte 		    "MSI: Unable to allocate interrupt handle table");
1558fcf3ce44SJohn Forte 
1559fcf3ce44SJohn Forte 		goto init_failed;
1560fcf3ce44SJohn Forte 	}
1561*291a2b48SSukumar Swaminathan 
1562fcf3ce44SJohn Forte 	/* Allocate 'count' interrupts */
1563*291a2b48SSukumar Swaminathan 	ret =
1564*291a2b48SSukumar Swaminathan 	    ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
1565fcf3ce44SJohn Forte 	    &actual, DDI_INTR_ALLOC_NORMAL);
1566fcf3ce44SJohn Forte 
1567fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1568fcf3ce44SJohn Forte 	    "MSI: %s: count=%d actual=%d", s_type, count, actual);
1569fcf3ce44SJohn Forte 
1570fcf3ce44SJohn Forte 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
1571fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1572fcf3ce44SJohn Forte 		    "MSI: Unable to allocate interrupts. error=%d", ret);
1573fcf3ce44SJohn Forte 
1574fcf3ce44SJohn Forte 		goto init_failed;
1575fcf3ce44SJohn Forte 	}
1576*291a2b48SSukumar Swaminathan 
1577fcf3ce44SJohn Forte 	if (actual != count) {
1578fcf3ce44SJohn Forte 		/* Validate actual count */
1579fcf3ce44SJohn Forte 		if (actual >= 8) {
1580fcf3ce44SJohn Forte 			new_actual = 8;
1581fcf3ce44SJohn Forte 		} else if (actual >= 4) {
1582fcf3ce44SJohn Forte 			new_actual = 4;
1583fcf3ce44SJohn Forte 		} else if (actual >= 2) {
1584fcf3ce44SJohn Forte 			new_actual = 2;
1585fcf3ce44SJohn Forte 		} else {
1586fcf3ce44SJohn Forte 			new_actual = 1;
1587fcf3ce44SJohn Forte 		}
1588fcf3ce44SJohn Forte 
1589fcf3ce44SJohn Forte 		if (new_actual < actual) {
1590fcf3ce44SJohn Forte 			/* Free extra handles */
1591fcf3ce44SJohn Forte 			for (i = new_actual; i < actual; i++) {
1592fcf3ce44SJohn Forte 				(void) ddi_intr_free(htable[i]);
1593fcf3ce44SJohn Forte 			}
1594fcf3ce44SJohn Forte 
1595fcf3ce44SJohn Forte 			actual = new_actual;
1596fcf3ce44SJohn Forte 		}
1597*291a2b48SSukumar Swaminathan 
1598fcf3ce44SJohn Forte 		/* Allocate a new array of interrupt handles */
1599fcf3ce44SJohn Forte 		new_htable =
1600fcf3ce44SJohn Forte 		    kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
1601fcf3ce44SJohn Forte 		    KM_SLEEP);
1602fcf3ce44SJohn Forte 
1603fcf3ce44SJohn Forte 		if (new_htable == NULL) {
1604fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1605*291a2b48SSukumar Swaminathan 			    "MSI: Unable to allocate new "
1606*291a2b48SSukumar Swaminathan 			    "interrupt handle table");
1607fcf3ce44SJohn Forte 
1608fcf3ce44SJohn Forte 			goto init_failed;
1609fcf3ce44SJohn Forte 		}
1610*291a2b48SSukumar Swaminathan 
1611fcf3ce44SJohn Forte 		/* Copy old array to new array */
1612fcf3ce44SJohn Forte 		bcopy((uint8_t *)htable, (uint8_t *)new_htable,
1613fcf3ce44SJohn Forte 		    (actual * sizeof (ddi_intr_handle_t)));
1614fcf3ce44SJohn Forte 
1615fcf3ce44SJohn Forte 		/* Free the old array */
1616fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
1617fcf3ce44SJohn Forte 
1618fcf3ce44SJohn Forte 		htable = new_htable;
1619fcf3ce44SJohn Forte 		count = actual;
1620fcf3ce44SJohn Forte 	}
1621*291a2b48SSukumar Swaminathan 
1622fcf3ce44SJohn Forte 	/* Allocate interrupt priority table */
1623fcf3ce44SJohn Forte 	intr_pri =
1624fcf3ce44SJohn Forte 	    (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
1625fcf3ce44SJohn Forte 	    KM_SLEEP);
1626fcf3ce44SJohn Forte 
1627fcf3ce44SJohn Forte 	if (intr_pri == NULL) {
1628fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1629fcf3ce44SJohn Forte 		    "MSI: Unable to allocate interrupt priority table");
1630fcf3ce44SJohn Forte 
1631fcf3ce44SJohn Forte 		goto init_failed;
1632fcf3ce44SJohn Forte 	}
1633*291a2b48SSukumar Swaminathan 
1634fcf3ce44SJohn Forte 	/* Allocate interrupt capability table */
1635fcf3ce44SJohn Forte 	intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
1636fcf3ce44SJohn Forte 
1637fcf3ce44SJohn Forte 	if (intr_cap == NULL) {
1638fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1639fcf3ce44SJohn Forte 		    "MSI: Unable to allocate interrupt capability table");
1640fcf3ce44SJohn Forte 
1641fcf3ce44SJohn Forte 		goto init_failed;
1642fcf3ce44SJohn Forte 	}
1643*291a2b48SSukumar Swaminathan 
1644fcf3ce44SJohn Forte 	/* Get minimum hilevel priority */
1645fcf3ce44SJohn Forte 	hilevel_pri = ddi_intr_get_hilevel_pri();
1646fcf3ce44SJohn Forte 
1647fcf3ce44SJohn Forte 	/* Fill the priority and capability tables */
1648fcf3ce44SJohn Forte 	for (i = 0; i < count; ++i) {
1649fcf3ce44SJohn Forte 		ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
1650fcf3ce44SJohn Forte 
1651fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1652fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1653fcf3ce44SJohn Forte 			    "MSI: ddi_intr_get_pri(%d) failed. "
1654*291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
1655*291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
1656fcf3ce44SJohn Forte 
1657fcf3ce44SJohn Forte 			/* Clean up the interrupts */
1658fcf3ce44SJohn Forte 			goto init_failed;
1659fcf3ce44SJohn Forte 		}
1660*291a2b48SSukumar Swaminathan 
1661fcf3ce44SJohn Forte 		if (intr_pri[i] >= hilevel_pri) {
1662fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1663fcf3ce44SJohn Forte 			    "MSI: Interrupt(%d) level too high. "
1664fcf3ce44SJohn Forte 			    "pri=0x%x hilevel=0x%x",
1665fcf3ce44SJohn Forte 			    i, intr_pri[i], hilevel_pri);
1666fcf3ce44SJohn Forte 
1667fcf3ce44SJohn Forte 			/* Clean up the interrupts */
1668fcf3ce44SJohn Forte 			goto init_failed;
1669fcf3ce44SJohn Forte 		}
1670*291a2b48SSukumar Swaminathan 
1671fcf3ce44SJohn Forte 		ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
1672fcf3ce44SJohn Forte 
1673fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1674fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1675*291a2b48SSukumar Swaminathan 			    "MSI: ddi_intr_get_cap(%d) failed. "
1676*291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
1677*291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
1678fcf3ce44SJohn Forte 
1679fcf3ce44SJohn Forte 			/* Clean up the interrupts */
1680fcf3ce44SJohn Forte 			goto init_failed;
1681fcf3ce44SJohn Forte 		}
1682*291a2b48SSukumar Swaminathan 
1683fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1684*291a2b48SSukumar Swaminathan 		    "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
1685*291a2b48SSukumar Swaminathan 		    intr_cap[i], intr_pri[i], hilevel_pri);
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 	}
1688fcf3ce44SJohn Forte 
1689fcf3ce44SJohn Forte 	/* Set mode */
1690fcf3ce44SJohn Forte 	switch (count) {
1691fcf3ce44SJohn Forte 	case 8:
1692fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE8;
1693fcf3ce44SJohn Forte 		break;
1694fcf3ce44SJohn Forte 
1695fcf3ce44SJohn Forte 	case 4:
1696fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE4;
1697fcf3ce44SJohn Forte 		break;
1698fcf3ce44SJohn Forte 
1699fcf3ce44SJohn Forte 	case 2:
1700fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE2;
1701fcf3ce44SJohn Forte 		break;
1702fcf3ce44SJohn Forte 
1703fcf3ce44SJohn Forte 	default:
1704fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE1;
1705fcf3ce44SJohn Forte 	}
1706fcf3ce44SJohn Forte 
1707fcf3ce44SJohn Forte 	/* Save the info */
1708fcf3ce44SJohn Forte 	hba->intr_htable = htable;
1709fcf3ce44SJohn Forte 	hba->intr_count = count;
1710fcf3ce44SJohn Forte 	hba->intr_pri = intr_pri;
1711fcf3ce44SJohn Forte 	hba->intr_cap = intr_cap;
1712fcf3ce44SJohn Forte 	hba->intr_type = type;
1713*291a2b48SSukumar Swaminathan 	hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
1714fcf3ce44SJohn Forte 	hba->intr_mask = emlxs_msi_mask[mode];
1715fcf3ce44SJohn Forte 
1716fcf3ce44SJohn Forte 	hba->intr_cond = 0;
1717fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
1718fcf3ce44SJohn Forte 		hba->intr_map[i] = emlxs_msi_map[mode][i];
1719fcf3ce44SJohn Forte 		hba->intr_cond |= emlxs_msi_map[mode][i];
1720fcf3ce44SJohn Forte 
1721fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
1722fcf3ce44SJohn Forte 		    hba->ddiinst, i);
1723fcf3ce44SJohn Forte 		mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
1724*291a2b48SSukumar Swaminathan 		    (void *)hba->intr_arg);
1725fcf3ce44SJohn Forte 	}
1726fcf3ce44SJohn Forte 
1727fcf3ce44SJohn Forte 	/* Set flag to indicate support */
1728fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_MSI_INITED;
1729fcf3ce44SJohn Forte 
1730fcf3ce44SJohn Forte 	/* Create the interrupt threads */
1731fcf3ce44SJohn Forte 	for (i = 0; i < MAX_RINGS; i++) {
1732fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME,
1733fcf3ce44SJohn Forte 		    hba->ddiinst, i);
1734fcf3ce44SJohn Forte 		mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER,
1735*291a2b48SSukumar Swaminathan 		    (void *)hba->intr_arg);
1736fcf3ce44SJohn Forte 
1737fcf3ce44SJohn Forte 		emlxs_thread_create(hba, &hba->ring[i].intr_thread);
1738fcf3ce44SJohn Forte 	}
1739fcf3ce44SJohn Forte 
1740fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
1741fcf3ce44SJohn Forte 
1742fcf3ce44SJohn Forte 
1743fcf3ce44SJohn Forte init_failed:
1744fcf3ce44SJohn Forte 
1745fcf3ce44SJohn Forte 	if (intr_cap) {
1746fcf3ce44SJohn Forte 		kmem_free(intr_cap, (count * sizeof (int32_t)));
1747fcf3ce44SJohn Forte 	}
1748*291a2b48SSukumar Swaminathan 
1749fcf3ce44SJohn Forte 	if (intr_pri) {
1750fcf3ce44SJohn Forte 		kmem_free(intr_pri, (count * sizeof (int32_t)));
1751fcf3ce44SJohn Forte 	}
1752*291a2b48SSukumar Swaminathan 
1753fcf3ce44SJohn Forte 	if (htable) {
1754fcf3ce44SJohn Forte 		/* Process the interrupt handlers */
1755fcf3ce44SJohn Forte 		for (i = 0; i < actual; i++) {
1756fcf3ce44SJohn Forte 			/* Free the handle[i] */
1757fcf3ce44SJohn Forte 			(void) ddi_intr_free(htable[i]);
1758fcf3ce44SJohn Forte 		}
1759fcf3ce44SJohn Forte 
1760fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
1761fcf3ce44SJohn Forte 	}
1762*291a2b48SSukumar Swaminathan 
1763fcf3ce44SJohn Forte 	/* Initialize */
1764fcf3ce44SJohn Forte 	hba->intr_htable = NULL;
1765fcf3ce44SJohn Forte 	hba->intr_count = 0;
1766fcf3ce44SJohn Forte 	hba->intr_pri = NULL;
1767fcf3ce44SJohn Forte 	hba->intr_cap = NULL;
1768fcf3ce44SJohn Forte 	hba->intr_type = 0;
1769fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
1770fcf3ce44SJohn Forte 	hba->intr_cond = 0;
1771fcf3ce44SJohn Forte 	bzero(hba->intr_map, sizeof (hba->intr_map));
1772fcf3ce44SJohn Forte 	bzero(hba->intr_lock, sizeof (hba->intr_lock));
1773fcf3ce44SJohn Forte 
1774fcf3ce44SJohn Forte 	if (type == DDI_INTR_TYPE_MSIX) {
1775fcf3ce44SJohn Forte 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
1776fcf3ce44SJohn Forte 		goto begin;
1777fcf3ce44SJohn Forte 	} else if (type == DDI_INTR_TYPE_MSI) {
1778fcf3ce44SJohn Forte 		types &= DDI_INTR_TYPE_FIXED;
1779fcf3ce44SJohn Forte 		goto begin;
1780fcf3ce44SJohn Forte 	}
1781*291a2b48SSukumar Swaminathan 
1782fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1783fcf3ce44SJohn Forte 	    "MSI: Unable to initialize interrupts");
1784fcf3ce44SJohn Forte 
1785fcf3ce44SJohn Forte 	return (DDI_FAILURE);
1786fcf3ce44SJohn Forte 
1787fcf3ce44SJohn Forte 
1788*291a2b48SSukumar Swaminathan }  /* emlxs_msi_init() */
1789fcf3ce44SJohn Forte 
1790fcf3ce44SJohn Forte 
1791fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
1792fcf3ce44SJohn Forte int32_t
1793fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba)
1794fcf3ce44SJohn Forte {
1795fcf3ce44SJohn Forte 	uint32_t count;
1796fcf3ce44SJohn Forte 	int32_t i;
1797fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable;
1798fcf3ce44SJohn Forte 	uint32_t *intr_pri;
1799fcf3ce44SJohn Forte 	int32_t *intr_cap;
1800fcf3ce44SJohn Forte 	int32_t ret;
1801fcf3ce44SJohn Forte 
1802fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
1803fcf3ce44SJohn Forte 		return (emlxs_intx_uninit(hba));
1804fcf3ce44SJohn Forte 	}
1805*291a2b48SSukumar Swaminathan 
1806fcf3ce44SJohn Forte 	/*
1807*291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1808*291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_uninit called. flags=%x",
1809*291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
1810fcf3ce44SJohn Forte 	 */
1811fcf3ce44SJohn Forte 
1812fcf3ce44SJohn Forte 	/* Make sure interrupts have been removed first */
1813fcf3ce44SJohn Forte 	if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
1814fcf3ce44SJohn Forte 		ret = emlxs_msi_remove(hba);
1815fcf3ce44SJohn Forte 
1816fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1817fcf3ce44SJohn Forte 			return (ret);
1818fcf3ce44SJohn Forte 		}
1819fcf3ce44SJohn Forte 	}
1820*291a2b48SSukumar Swaminathan 
1821fcf3ce44SJohn Forte 	/* Check if the interrupts are still initialized */
1822fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
1823fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1824fcf3ce44SJohn Forte 	}
1825fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_MSI_INITED;
1826fcf3ce44SJohn Forte 
1827fcf3ce44SJohn Forte 	/* Get handle table parameters */
1828fcf3ce44SJohn Forte 	htable = hba->intr_htable;
1829fcf3ce44SJohn Forte 	count = hba->intr_count;
1830fcf3ce44SJohn Forte 	intr_pri = hba->intr_pri;
1831fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
1832fcf3ce44SJohn Forte 
1833fcf3ce44SJohn Forte 	/* Clean up */
1834fcf3ce44SJohn Forte 	hba->intr_count = 0;
1835fcf3ce44SJohn Forte 	hba->intr_htable = NULL;
1836fcf3ce44SJohn Forte 	hba->intr_pri = NULL;
1837fcf3ce44SJohn Forte 	hba->intr_cap = NULL;
1838fcf3ce44SJohn Forte 	hba->intr_type = 0;
1839fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
1840fcf3ce44SJohn Forte 	hba->intr_cond = 0;
1841fcf3ce44SJohn Forte 	bzero(hba->intr_map, sizeof (hba->intr_map));
1842fcf3ce44SJohn Forte 
1843fcf3ce44SJohn Forte 	if (intr_cap) {
1844fcf3ce44SJohn Forte 		kmem_free(intr_cap, (count * sizeof (int32_t)));
1845fcf3ce44SJohn Forte 	}
1846*291a2b48SSukumar Swaminathan 
1847fcf3ce44SJohn Forte 	if (intr_pri) {
1848fcf3ce44SJohn Forte 		kmem_free(intr_pri, (count * sizeof (int32_t)));
1849fcf3ce44SJohn Forte 	}
1850*291a2b48SSukumar Swaminathan 
1851fcf3ce44SJohn Forte 	if (htable) {
1852fcf3ce44SJohn Forte 		/* Process the interrupt handlers */
1853fcf3ce44SJohn Forte 		for (i = 0; i < count; ++i) {
1854fcf3ce44SJohn Forte 			/* Free the handle[i] */
1855*291a2b48SSukumar Swaminathan 			ret = ddi_intr_free(htable[i]);
1856fcf3ce44SJohn Forte 		}
1857fcf3ce44SJohn Forte 
1858fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
1859fcf3ce44SJohn Forte 	}
1860*291a2b48SSukumar Swaminathan 
1861fcf3ce44SJohn Forte 	/* Destroy the intr locks */
1862fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
1863fcf3ce44SJohn Forte 		mutex_destroy(&hba->intr_lock[i]);
1864fcf3ce44SJohn Forte 	}
1865fcf3ce44SJohn Forte 
1866fcf3ce44SJohn Forte 	/* Destroy the interrupt threads */
1867fcf3ce44SJohn Forte 	for (i = 0; i < MAX_RINGS; i++) {
1868fcf3ce44SJohn Forte 		emlxs_thread_destroy(&hba->ring[i].intr_thread);
1869fcf3ce44SJohn Forte 		mutex_destroy(&hba->ring[i].rsp_lock);
1870fcf3ce44SJohn Forte 	}
1871fcf3ce44SJohn Forte 
1872fcf3ce44SJohn Forte 	/*
1873*291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1874*291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_uninit done. flags=%x",
1875*291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
1876fcf3ce44SJohn Forte 	 */
1877fcf3ce44SJohn Forte 
1878fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
1879fcf3ce44SJohn Forte 
1880*291a2b48SSukumar Swaminathan }  /* emlxs_msi_uninit() */
1881fcf3ce44SJohn Forte 
1882fcf3ce44SJohn Forte 
1883fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */
1884fcf3ce44SJohn Forte int32_t
1885fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba)
1886fcf3ce44SJohn Forte {
1887fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1888fcf3ce44SJohn Forte 	int32_t count;
1889fcf3ce44SJohn Forte 	int32_t i;
1890fcf3ce44SJohn Forte 	int32_t ret;
1891fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable = NULL;
1892fcf3ce44SJohn Forte 	int32_t *intr_cap = NULL;
1893fcf3ce44SJohn Forte 
1894fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
1895fcf3ce44SJohn Forte 		return (emlxs_intx_add(hba));
1896fcf3ce44SJohn Forte 	}
1897*291a2b48SSukumar Swaminathan 
1898fcf3ce44SJohn Forte 	/* Check if interrupts have already been added */
1899fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
1900fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
1901fcf3ce44SJohn Forte 	}
1902*291a2b48SSukumar Swaminathan 
1903fcf3ce44SJohn Forte 	/* Check if interrupts have been initialized */
1904fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
1905fcf3ce44SJohn Forte 		ret = emlxs_msi_init(hba, 0);
1906fcf3ce44SJohn Forte 
1907fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1908fcf3ce44SJohn Forte 			return (ret);
1909fcf3ce44SJohn Forte 		}
1910fcf3ce44SJohn Forte 	}
1911*291a2b48SSukumar Swaminathan 
1912fcf3ce44SJohn Forte 	/* Get handle table parameters */
1913fcf3ce44SJohn Forte 	htable = hba->intr_htable;
1914fcf3ce44SJohn Forte 	count = hba->intr_count;
1915fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
1916fcf3ce44SJohn Forte 
1917fcf3ce44SJohn Forte 	/* Add the interrupt handlers */
1918fcf3ce44SJohn Forte 	for (i = 0; i < count; ++i) {
1919fcf3ce44SJohn Forte 		/* add handler for handle[i] */
1920*291a2b48SSukumar Swaminathan 		ret =
1921*291a2b48SSukumar Swaminathan 		    ddi_intr_add_handler(htable[i], emlxs_sli_msi_intr,
1922*291a2b48SSukumar Swaminathan 		    (char *)hba, (char *)((unsigned long)i));
1923fcf3ce44SJohn Forte 
1924fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1925fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1926*291a2b48SSukumar Swaminathan 			    "MSI: ddi_intr_add_handler(%d) failed. "
1927*291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
1928*291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
1929fcf3ce44SJohn Forte 
1930fcf3ce44SJohn Forte 			/* Process the remaining interrupt handlers */
1931fcf3ce44SJohn Forte 			while (i) {
1932fcf3ce44SJohn Forte 				/* Decrement i */
1933fcf3ce44SJohn Forte 				i--;
1934fcf3ce44SJohn Forte 
1935fcf3ce44SJohn Forte 				/* Remove the handler */
1936fcf3ce44SJohn Forte 				ret = ddi_intr_remove_handler(htable[i]);
1937fcf3ce44SJohn Forte 
1938fcf3ce44SJohn Forte 			}
1939fcf3ce44SJohn Forte 
1940fcf3ce44SJohn Forte 			return (DDI_FAILURE);
1941fcf3ce44SJohn Forte 		}
1942fcf3ce44SJohn Forte 	}
1943fcf3ce44SJohn Forte 
1944fcf3ce44SJohn Forte 	/* Enable the interrupts */
1945fcf3ce44SJohn Forte 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
1946fcf3ce44SJohn Forte 		ret = ddi_intr_block_enable(htable, count);
1947fcf3ce44SJohn Forte 
1948fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
1949fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1950fcf3ce44SJohn Forte 			    "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
1951fcf3ce44SJohn Forte 			    count, ret);
1952fcf3ce44SJohn Forte 
1953fcf3ce44SJohn Forte 			for (i = 0; i < count; ++i) {
1954fcf3ce44SJohn Forte 				ret = ddi_intr_enable(htable[i]);
1955fcf3ce44SJohn Forte 
1956fcf3ce44SJohn Forte 				if (ret != DDI_SUCCESS) {
1957fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1958fcf3ce44SJohn Forte 					    &emlxs_init_debug_msg,
1959fcf3ce44SJohn Forte 					    "MSI: ddi_intr_enable(%d) failed. "
1960*291a2b48SSukumar Swaminathan 					    "ret=%d",
1961*291a2b48SSukumar Swaminathan 					    i, ret);
1962fcf3ce44SJohn Forte 				}
1963fcf3ce44SJohn Forte 			}
1964fcf3ce44SJohn Forte 		}
1965fcf3ce44SJohn Forte 	} else {
1966fcf3ce44SJohn Forte 		for (i = 0; i < count; ++i) {
1967fcf3ce44SJohn Forte 			ret = ddi_intr_enable(htable[i]);
1968fcf3ce44SJohn Forte 
1969fcf3ce44SJohn Forte 			if (ret != DDI_SUCCESS) {
1970*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1971*291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
1972fcf3ce44SJohn Forte 				    "MSI: ddi_intr_enable(%d) failed. ret=%d",
1973fcf3ce44SJohn Forte 				    i, ret);
1974fcf3ce44SJohn Forte 			}
1975fcf3ce44SJohn Forte 		}
1976fcf3ce44SJohn Forte 	}
1977fcf3ce44SJohn Forte 
1978fcf3ce44SJohn Forte 
1979fcf3ce44SJohn Forte 	/* Set flag to indicate support */
1980fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_MSI_ADDED;
1981fcf3ce44SJohn Forte 
1982fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
1983fcf3ce44SJohn Forte 
1984*291a2b48SSukumar Swaminathan }  /* emlxs_msi_add() */
1985fcf3ce44SJohn Forte 
1986fcf3ce44SJohn Forte 
1987fcf3ce44SJohn Forte 
1988fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
1989fcf3ce44SJohn Forte int32_t
1990fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba)
1991fcf3ce44SJohn Forte {
1992fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1993fcf3ce44SJohn Forte 	uint32_t count;
1994fcf3ce44SJohn Forte 	int32_t i;
1995fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable;
1996fcf3ce44SJohn Forte 	int32_t *intr_cap;
1997fcf3ce44SJohn Forte 	int32_t ret;
1998fcf3ce44SJohn Forte 
1999fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
2000fcf3ce44SJohn Forte 		return (emlxs_intx_remove(hba));
2001fcf3ce44SJohn Forte 	}
2002*291a2b48SSukumar Swaminathan 
2003fcf3ce44SJohn Forte 	/*
2004*291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2005*291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_remove called. flags=%x",
2006*291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
2007fcf3ce44SJohn Forte 	 */
2008fcf3ce44SJohn Forte 
2009fcf3ce44SJohn Forte 	/* Check if interrupts have already been removed */
2010fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
2011fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
2012fcf3ce44SJohn Forte 	}
2013fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_MSI_ADDED;
2014fcf3ce44SJohn Forte 
2015fcf3ce44SJohn Forte 	/* Disable all adapter interrupts */
2016*291a2b48SSukumar Swaminathan 	emlxs_disable_intr(hba, 0);
2017fcf3ce44SJohn Forte 
2018fcf3ce44SJohn Forte 	/* Get handle table parameters */
2019fcf3ce44SJohn Forte 	htable = hba->intr_htable;
2020fcf3ce44SJohn Forte 	count = hba->intr_count;
2021fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
2022fcf3ce44SJohn Forte 
2023fcf3ce44SJohn Forte 	/* Disable the interrupts */
2024fcf3ce44SJohn Forte 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
2025fcf3ce44SJohn Forte 		ret = ddi_intr_block_disable(htable, count);
2026fcf3ce44SJohn Forte 
2027fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
2028fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2029fcf3ce44SJohn Forte 			    "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
2030fcf3ce44SJohn Forte 			    count, ret);
2031fcf3ce44SJohn Forte 
2032fcf3ce44SJohn Forte 			for (i = 0; i < count; i++) {
2033fcf3ce44SJohn Forte 				ret = ddi_intr_disable(htable[i]);
2034fcf3ce44SJohn Forte 
2035fcf3ce44SJohn Forte 				if (ret != DDI_SUCCESS) {
2036fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2037fcf3ce44SJohn Forte 					    &emlxs_init_debug_msg,
2038fcf3ce44SJohn Forte 					    "MSI: ddi_intr_disable(%d) failed. "
2039*291a2b48SSukumar Swaminathan 					    "ret=%d",
2040*291a2b48SSukumar Swaminathan 					    i, ret);
2041fcf3ce44SJohn Forte 				}
2042fcf3ce44SJohn Forte 			}
2043fcf3ce44SJohn Forte 		}
2044fcf3ce44SJohn Forte 	} else {
2045fcf3ce44SJohn Forte 		for (i = 0; i < count; i++) {
2046fcf3ce44SJohn Forte 			ret = ddi_intr_disable(htable[i]);
2047fcf3ce44SJohn Forte 
2048fcf3ce44SJohn Forte 			if (ret != DDI_SUCCESS) {
2049*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2050*291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
2051fcf3ce44SJohn Forte 				    "MSI: ddi_intr_disable(%d) failed. ret=%d",
2052fcf3ce44SJohn Forte 				    i, ret);
2053fcf3ce44SJohn Forte 			}
2054fcf3ce44SJohn Forte 		}
2055fcf3ce44SJohn Forte 	}
2056fcf3ce44SJohn Forte 
2057fcf3ce44SJohn Forte 	/* Process the interrupt handlers */
2058fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
2059fcf3ce44SJohn Forte 		/* Remove the handler */
2060fcf3ce44SJohn Forte 		ret = ddi_intr_remove_handler(htable[i]);
2061fcf3ce44SJohn Forte 
2062fcf3ce44SJohn Forte 
2063fcf3ce44SJohn Forte 	}
2064fcf3ce44SJohn Forte 
2065fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
2066fcf3ce44SJohn Forte 
2067*291a2b48SSukumar Swaminathan }  /* emlxs_msi_remove() */
2068fcf3ce44SJohn Forte 
2069fcf3ce44SJohn Forte 
2070*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
2071fcf3ce44SJohn Forte 
2072fcf3ce44SJohn Forte 
2073fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
2074fcf3ce44SJohn Forte /* ARGSUSED */
2075fcf3ce44SJohn Forte int32_t
2076fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
2077fcf3ce44SJohn Forte {
2078fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2079fcf3ce44SJohn Forte 	int32_t ret;
2080fcf3ce44SJohn Forte 	uint32_t i;
2081fcf3ce44SJohn Forte 	char buf[64];
2082fcf3ce44SJohn Forte 
2083fcf3ce44SJohn Forte 	/* Check if interrupts have already been initialized */
2084fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_INTX_INITED) {
2085fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
2086fcf3ce44SJohn Forte 	}
2087*291a2b48SSukumar Swaminathan 
2088fcf3ce44SJohn Forte 	/* Check if adapter is flagged for INTX support */
2089fcf3ce44SJohn Forte 	if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
2090fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2091fcf3ce44SJohn Forte 		    "INTX: %s does not support INTX.  flags=0x%x",
2092fcf3ce44SJohn Forte 		    hba->model_info.model, hba->model_info.flags);
2093fcf3ce44SJohn Forte 
2094fcf3ce44SJohn Forte 		return (DDI_FAILURE);
2095fcf3ce44SJohn Forte 	}
2096*291a2b48SSukumar Swaminathan 
2097fcf3ce44SJohn Forte 	/*
2098*291a2b48SSukumar Swaminathan 	 * Interrupt number '0' is a high-level interrupt. This driver
2099*291a2b48SSukumar Swaminathan 	 * does not support having its interrupts mapped above scheduler
2100*291a2b48SSukumar Swaminathan 	 * priority; i.e., we always expect to be able to call general
2101*291a2b48SSukumar Swaminathan 	 * kernel routines that may invoke the scheduler.
2102fcf3ce44SJohn Forte 	 */
2103fcf3ce44SJohn Forte 	if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
2104fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2105fcf3ce44SJohn Forte 		    "INTX: High-level interrupt not supported.");
2106fcf3ce44SJohn Forte 
2107fcf3ce44SJohn Forte 		return (DDI_FAILURE);
2108fcf3ce44SJohn Forte 	}
2109*291a2b48SSukumar Swaminathan 
2110fcf3ce44SJohn Forte 	/* Get an iblock cookie */
2111*291a2b48SSukumar Swaminathan 	ret =
2112*291a2b48SSukumar Swaminathan 	    ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
2113fcf3ce44SJohn Forte 	    (ddi_iblock_cookie_t *)&hba->intr_arg);
2114fcf3ce44SJohn Forte 	if (ret != DDI_SUCCESS) {
2115fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2116fcf3ce44SJohn Forte 		    "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
2117fcf3ce44SJohn Forte 
2118fcf3ce44SJohn Forte 		return (ret);
2119fcf3ce44SJohn Forte 	}
2120*291a2b48SSukumar Swaminathan 
2121fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_INTX_INITED;
2122fcf3ce44SJohn Forte 
2123fcf3ce44SJohn Forte 	/* Create the interrupt threads */
2124fcf3ce44SJohn Forte 	for (i = 0; i < MAX_RINGS; i++) {
2125fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME,
2126fcf3ce44SJohn Forte 		    hba->ddiinst, i);
2127fcf3ce44SJohn Forte 		mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER,
2128fcf3ce44SJohn Forte 		    (void *)hba->intr_arg);
2129fcf3ce44SJohn Forte 
2130fcf3ce44SJohn Forte 		emlxs_thread_create(hba, &hba->ring[i].intr_thread);
2131fcf3ce44SJohn Forte 	}
2132fcf3ce44SJohn Forte 
2133fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
2134fcf3ce44SJohn Forte 
2135*291a2b48SSukumar Swaminathan }  /* emlxs_intx_init() */
2136fcf3ce44SJohn Forte 
2137fcf3ce44SJohn Forte 
2138fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
2139fcf3ce44SJohn Forte int32_t
2140fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba)
2141fcf3ce44SJohn Forte {
2142fcf3ce44SJohn Forte 	int32_t ret;
2143fcf3ce44SJohn Forte 	uint32_t i;
2144fcf3ce44SJohn Forte 
2145fcf3ce44SJohn Forte 	/* Make sure interrupts have been removed */
2146fcf3ce44SJohn Forte 	if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
2147fcf3ce44SJohn Forte 		ret = emlxs_intx_remove(hba);
2148fcf3ce44SJohn Forte 
2149fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
2150fcf3ce44SJohn Forte 			return (ret);
2151fcf3ce44SJohn Forte 		}
2152fcf3ce44SJohn Forte 	}
2153*291a2b48SSukumar Swaminathan 
2154fcf3ce44SJohn Forte 	/* Check if the interrupts are still initialized */
2155fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
2156fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
2157fcf3ce44SJohn Forte 	}
2158fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_INTX_INITED;
2159fcf3ce44SJohn Forte 
2160fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
2161fcf3ce44SJohn Forte 
2162fcf3ce44SJohn Forte 	/* Create the interrupt threads */
2163fcf3ce44SJohn Forte 	for (i = 0; i < MAX_RINGS; i++) {
2164fcf3ce44SJohn Forte 		emlxs_thread_destroy(&hba->ring[i].intr_thread);
2165fcf3ce44SJohn Forte 		mutex_destroy(&hba->ring[i].rsp_lock);
2166fcf3ce44SJohn Forte 	}
2167fcf3ce44SJohn Forte 
2168fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
2169fcf3ce44SJohn Forte 
2170*291a2b48SSukumar Swaminathan }  /* emlxs_intx_uninit() */
2171fcf3ce44SJohn Forte 
2172fcf3ce44SJohn Forte 
2173*291a2b48SSukumar Swaminathan /*
2174*291a2b48SSukumar Swaminathan  * This is the legacy method for adding interrupts in Solaris
2175*291a2b48SSukumar Swaminathan  * EMLXS_INTR_ADD
2176*291a2b48SSukumar Swaminathan  */
2177fcf3ce44SJohn Forte int32_t
2178fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba)
2179fcf3ce44SJohn Forte {
2180fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2181fcf3ce44SJohn Forte 	int32_t ret;
2182fcf3ce44SJohn Forte 
2183fcf3ce44SJohn Forte 	/* Check if interrupts have already been added */
2184fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_INTX_ADDED) {
2185fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
2186fcf3ce44SJohn Forte 	}
2187*291a2b48SSukumar Swaminathan 
2188fcf3ce44SJohn Forte 	/* Check if interrupts have been initialized */
2189fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
2190fcf3ce44SJohn Forte 		ret = emlxs_intx_init(hba, 0);
2191fcf3ce44SJohn Forte 
2192fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
2193fcf3ce44SJohn Forte 			return (ret);
2194fcf3ce44SJohn Forte 		}
2195fcf3ce44SJohn Forte 	}
2196*291a2b48SSukumar Swaminathan 
2197fcf3ce44SJohn Forte 	/* add intrrupt handler routine */
2198*291a2b48SSukumar Swaminathan 	ret = ddi_add_intr((void *)hba->dip,
2199*291a2b48SSukumar Swaminathan 	    (uint_t)EMLXS_INUMBER,
2200*291a2b48SSukumar Swaminathan 	    (ddi_iblock_cookie_t *)&hba->intr_arg,
2201*291a2b48SSukumar Swaminathan 	    (ddi_idevice_cookie_t *)0,
2202*291a2b48SSukumar Swaminathan 	    (uint_t(*)())emlxs_sli_intx_intr, (caddr_t)hba);
2203fcf3ce44SJohn Forte 
2204fcf3ce44SJohn Forte 	if (ret != DDI_SUCCESS) {
2205fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
2206fcf3ce44SJohn Forte 		    "INTX: ddi_add_intr failed. ret=%d", ret);
2207fcf3ce44SJohn Forte 
2208fcf3ce44SJohn Forte 		return (ret);
2209fcf3ce44SJohn Forte 	}
2210*291a2b48SSukumar Swaminathan 
2211fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_INTX_ADDED;
2212fcf3ce44SJohn Forte 
2213fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
2214fcf3ce44SJohn Forte 
2215*291a2b48SSukumar Swaminathan }  /* emlxs_intx_add() */
2216fcf3ce44SJohn Forte 
2217fcf3ce44SJohn Forte 
2218fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
2219fcf3ce44SJohn Forte int32_t
2220fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba)
2221fcf3ce44SJohn Forte {
2222fcf3ce44SJohn Forte 	/* Check if interrupts have already been removed */
2223fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
2224fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
2225fcf3ce44SJohn Forte 	}
2226fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_INTX_ADDED;
2227fcf3ce44SJohn Forte 
2228fcf3ce44SJohn Forte 	/* Diable all adapter interrupts */
2229*291a2b48SSukumar Swaminathan 	emlxs_disable_intr(hba, 0);
2230fcf3ce44SJohn Forte 
2231fcf3ce44SJohn Forte 	/* Remove the interrupt */
2232fcf3ce44SJohn Forte 	(void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
2233fcf3ce44SJohn Forte 	    hba->intr_arg);
2234fcf3ce44SJohn Forte 
2235fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
2236fcf3ce44SJohn Forte 
2237*291a2b48SSukumar Swaminathan }  /* emlxs_intx_remove() */
2238fcf3ce44SJohn Forte 
2239fcf3ce44SJohn Forte 
2240fcf3ce44SJohn Forte static void
2241fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba)
2242fcf3ce44SJohn Forte {
2243fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
2244fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
2245fcf3ce44SJohn Forte 	char *cptr;
2246fcf3ce44SJohn Forte 	uint32_t hi;
2247fcf3ce44SJohn Forte 
2248fcf3ce44SJohn Forte 	/*
2249*291a2b48SSukumar Swaminathan 	 * This routine modifies the link-speed config parameter entry
2250*291a2b48SSukumar Swaminathan 	 * based on adapter capabilities
2251fcf3ce44SJohn Forte 	 */
2252fcf3ce44SJohn Forte 	vpd = &VPD;
2253fcf3ce44SJohn Forte 	cfg = &hba->config[CFG_LINK_SPEED];
2254fcf3ce44SJohn Forte 
2255fcf3ce44SJohn Forte 	cptr = cfg->help;
2256fcf3ce44SJohn Forte 	(void) strcpy(cptr, "Select link speed. [0=Auto");
2257fcf3ce44SJohn Forte 	cptr += 26;
2258fcf3ce44SJohn Forte 	hi = 0;
2259fcf3ce44SJohn Forte 
2260fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
2261fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 1=1Gb");
2262fcf3ce44SJohn Forte 		cptr += 7;
2263fcf3ce44SJohn Forte 		hi = 1;
2264fcf3ce44SJohn Forte 	}
2265*291a2b48SSukumar Swaminathan 
2266fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
2267fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 2=2Gb");
2268fcf3ce44SJohn Forte 		cptr += 7;
2269fcf3ce44SJohn Forte 		hi = 2;
2270fcf3ce44SJohn Forte 	}
2271*291a2b48SSukumar Swaminathan 
2272fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
2273fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 4=4Gb");
2274fcf3ce44SJohn Forte 		cptr += 7;
2275fcf3ce44SJohn Forte 		hi = 4;
2276fcf3ce44SJohn Forte 	}
2277*291a2b48SSukumar Swaminathan 
2278fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
2279fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 8=8Gb");
2280fcf3ce44SJohn Forte 		cptr += 7;
2281fcf3ce44SJohn Forte 		hi = 8;
2282fcf3ce44SJohn Forte 	}
2283*291a2b48SSukumar Swaminathan 
2284fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
2285fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 10=10Gb");
2286fcf3ce44SJohn Forte 		cptr += 9;
2287fcf3ce44SJohn Forte 		hi = 10;
2288fcf3ce44SJohn Forte 	}
2289*291a2b48SSukumar Swaminathan 
2290fcf3ce44SJohn Forte 	(void) strcpy(cptr, "]");
2291fcf3ce44SJohn Forte 	cfg->hi = hi;
2292fcf3ce44SJohn Forte 
2293fcf3ce44SJohn Forte 	/* Now revalidate the current parameter setting */
2294fcf3ce44SJohn Forte 	cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
2295fcf3ce44SJohn Forte 
2296fcf3ce44SJohn Forte 	return;
2297fcf3ce44SJohn Forte 
2298*291a2b48SSukumar Swaminathan }  /* emlxs_process_link_speed() */
2299fcf3ce44SJohn Forte 
2300fcf3ce44SJohn Forte 
2301fcf3ce44SJohn Forte /*
2302*291a2b48SSukumar Swaminathan  * emlxs_parse_vpd()
2303fcf3ce44SJohn Forte  *
2304fcf3ce44SJohn Forte  * This routine will parse the VPD data
2305fcf3ce44SJohn Forte  */
2306fcf3ce44SJohn Forte extern int
2307fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
2308fcf3ce44SJohn Forte {
2309fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2310fcf3ce44SJohn Forte 	char tag[3];
2311fcf3ce44SJohn Forte 	uint8_t lenlo, lenhi;
2312fcf3ce44SJohn Forte 	uint32_t n;
2313fcf3ce44SJohn Forte 	uint16_t block_size;
2314fcf3ce44SJohn Forte 	uint32_t block_index = 0;
2315fcf3ce44SJohn Forte 	uint8_t sub_size;
2316fcf3ce44SJohn Forte 	uint32_t sub_index;
2317fcf3ce44SJohn Forte 	int32_t finished = 0;
2318fcf3ce44SJohn Forte 	int32_t index = 0;
2319fcf3ce44SJohn Forte 	char buffer[128];
2320fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
2321fcf3ce44SJohn Forte 
2322fcf3ce44SJohn Forte 	vpd = &VPD;
2323fcf3ce44SJohn Forte 
2324fcf3ce44SJohn Forte 
2325fcf3ce44SJohn Forte 	while (!finished && (block_index < size)) {
2326fcf3ce44SJohn Forte 		/*
2327*291a2b48SSukumar Swaminathan 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2328*291a2b48SSukumar Swaminathan 		 *    "block_index = %x", block_index);
2329fcf3ce44SJohn Forte 		 */
2330fcf3ce44SJohn Forte 
2331fcf3ce44SJohn Forte 		switch (vpd_buf[block_index]) {
2332fcf3ce44SJohn Forte 		case 0x82:
2333fcf3ce44SJohn Forte 			index = block_index;
2334fcf3ce44SJohn Forte 			index += 1;
2335fcf3ce44SJohn Forte 			lenlo = vpd_buf[index];
2336fcf3ce44SJohn Forte 			index += 1;
2337fcf3ce44SJohn Forte 			lenhi = vpd_buf[index];
2338fcf3ce44SJohn Forte 			index += 1;
2339fcf3ce44SJohn Forte 			block_index = index;
2340fcf3ce44SJohn Forte 
2341fcf3ce44SJohn Forte 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
2342fcf3ce44SJohn Forte 			block_index += block_size;
2343fcf3ce44SJohn Forte 
2344fcf3ce44SJohn Forte 			/*
2345fcf3ce44SJohn Forte 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2346*291a2b48SSukumar Swaminathan 			 *    "block_size = %x", block_size);
2347fcf3ce44SJohn Forte 			 */
2348fcf3ce44SJohn Forte 
2349fcf3ce44SJohn Forte 			n = sizeof (buffer);
2350fcf3ce44SJohn Forte 			bzero(buffer, n);
2351fcf3ce44SJohn Forte 			bcopy(&vpd_buf[index], buffer,
2352fcf3ce44SJohn Forte 			    (block_size < (n - 1)) ? block_size : (n - 1));
2353fcf3ce44SJohn Forte 
2354fcf3ce44SJohn Forte 			(void) strcpy(vpd->id, buffer);
2355*291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
2356*291a2b48SSukumar Swaminathan 			    vpd->id);
2357fcf3ce44SJohn Forte 
2358fcf3ce44SJohn Forte 			break;
2359fcf3ce44SJohn Forte 
2360fcf3ce44SJohn Forte 		case 0x90:
2361fcf3ce44SJohn Forte 			index = block_index;
2362fcf3ce44SJohn Forte 			index += 1;
2363fcf3ce44SJohn Forte 			lenlo = vpd_buf[index];
2364fcf3ce44SJohn Forte 			index += 1;
2365fcf3ce44SJohn Forte 			lenhi = vpd_buf[index];
2366fcf3ce44SJohn Forte 			index += 1;
2367fcf3ce44SJohn Forte 			block_index = index;
2368fcf3ce44SJohn Forte 			sub_index = index;
2369fcf3ce44SJohn Forte 
2370fcf3ce44SJohn Forte 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
2371fcf3ce44SJohn Forte 			block_index += block_size;
2372fcf3ce44SJohn Forte 
2373fcf3ce44SJohn Forte 			/*
2374fcf3ce44SJohn Forte 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2375*291a2b48SSukumar Swaminathan 			 *    "block_size = %x", block_size);
2376fcf3ce44SJohn Forte 			 */
2377fcf3ce44SJohn Forte 
2378fcf3ce44SJohn Forte 			/* Scan for sub-blocks */
2379fcf3ce44SJohn Forte 			while ((sub_index < block_index) &&
2380fcf3ce44SJohn Forte 			    (sub_index < size)) {
2381fcf3ce44SJohn Forte 				/*
2382fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2383*291a2b48SSukumar Swaminathan 				 *    "sub_index = %x", sub_index);
2384fcf3ce44SJohn Forte 				 */
2385fcf3ce44SJohn Forte 
2386fcf3ce44SJohn Forte 				index = sub_index;
2387fcf3ce44SJohn Forte 				tag[0] = vpd_buf[index++];
2388fcf3ce44SJohn Forte 				tag[1] = vpd_buf[index++];
2389fcf3ce44SJohn Forte 				tag[2] = 0;
2390fcf3ce44SJohn Forte 				sub_size = vpd_buf[index++];
2391fcf3ce44SJohn Forte 
2392fcf3ce44SJohn Forte 				/*
2393fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2394*291a2b48SSukumar Swaminathan 				 *    "sub_size = %x", sub_size);
2395fcf3ce44SJohn Forte 				 */
2396fcf3ce44SJohn Forte 
2397fcf3ce44SJohn Forte 				sub_index = (index + sub_size);
2398fcf3ce44SJohn Forte 
2399fcf3ce44SJohn Forte 				n = sizeof (buffer);
2400fcf3ce44SJohn Forte 				bzero(buffer, n);
2401fcf3ce44SJohn Forte 				bcopy(&vpd_buf[index], buffer,
2402fcf3ce44SJohn Forte 				    (sub_size < (n - 1)) ? sub_size : (n - 1));
2403fcf3ce44SJohn Forte 
2404fcf3ce44SJohn Forte 				/*
2405fcf3ce44SJohn Forte 				 * Look for Engineering Change (EC)
2406fcf3ce44SJohn Forte 				 */
2407fcf3ce44SJohn Forte 				if (strcmp(tag, "EC") == 0) {
2408fcf3ce44SJohn Forte 					(void) strcpy(vpd->eng_change, buffer);
2409fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2410*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "EC: %s",
2411*291a2b48SSukumar Swaminathan 					    vpd->eng_change);
2412fcf3ce44SJohn Forte 				}
2413fcf3ce44SJohn Forte 				/*
2414fcf3ce44SJohn Forte 				 * Look for Manufacturer (MN)
2415fcf3ce44SJohn Forte 				 */
2416fcf3ce44SJohn Forte 				else if (strcmp(tag, "MN") == 0) {
2417fcf3ce44SJohn Forte 					(void) strcpy(vpd->manufacturer,
2418fcf3ce44SJohn Forte 					    buffer);
2419fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2420*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "MN: %s",
2421*291a2b48SSukumar Swaminathan 					    vpd->manufacturer);
2422fcf3ce44SJohn Forte 				}
2423fcf3ce44SJohn Forte 				/*
2424fcf3ce44SJohn Forte 				 * Look for Serial Number (SN)
2425fcf3ce44SJohn Forte 				 */
2426fcf3ce44SJohn Forte 				else if (strcmp(tag, "SN") == 0) {
2427fcf3ce44SJohn Forte 					(void) strcpy(vpd->serial_num, buffer);
2428fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2429*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "SN: %s",
2430*291a2b48SSukumar Swaminathan 					    vpd->serial_num);
2431fcf3ce44SJohn Forte 
2432fcf3ce44SJohn Forte 					/* Validate the serial number */
2433*291a2b48SSukumar Swaminathan 					if (strncmp(buffer, "FFFFFFFFFF", 10) ==
2434*291a2b48SSukumar Swaminathan 					    0 ||
2435*291a2b48SSukumar Swaminathan 					    strncmp(buffer, "0000000000", 10) ==
2436*291a2b48SSukumar Swaminathan 					    0) {
2437fcf3ce44SJohn Forte 						vpd->serial_num[0] = 0;
2438fcf3ce44SJohn Forte 					}
2439fcf3ce44SJohn Forte 				}
2440fcf3ce44SJohn Forte 				/*
2441fcf3ce44SJohn Forte 				 * Look for Part Number (PN)
2442fcf3ce44SJohn Forte 				 */
2443fcf3ce44SJohn Forte 				else if (strcmp(tag, "PN") == 0) {
2444fcf3ce44SJohn Forte 					(void) strcpy(vpd->part_num, buffer);
2445fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2446*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "PN: %s",
2447*291a2b48SSukumar Swaminathan 					    vpd->part_num);
2448fcf3ce44SJohn Forte 				}
2449fcf3ce44SJohn Forte 				/*
2450fcf3ce44SJohn Forte 				 * Look for (V0)
2451fcf3ce44SJohn Forte 				 */
2452fcf3ce44SJohn Forte 				else if (strcmp(tag, "V0") == 0) {
2453fcf3ce44SJohn Forte 					/* Not used */
2454fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2455*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "V0: %s", buffer);
2456fcf3ce44SJohn Forte 				}
2457fcf3ce44SJohn Forte 				/*
2458fcf3ce44SJohn Forte 				 * Look for model description (V1)
2459fcf3ce44SJohn Forte 				 */
2460fcf3ce44SJohn Forte 				else if (strcmp(tag, "V1") == 0) {
2461fcf3ce44SJohn Forte 					(void) strcpy(vpd->model_desc, buffer);
2462fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2463*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Desc: %s",
2464*291a2b48SSukumar Swaminathan 					    vpd->model_desc);
2465fcf3ce44SJohn Forte 				}
2466fcf3ce44SJohn Forte 				/*
2467fcf3ce44SJohn Forte 				 * Look for model (V2)
2468fcf3ce44SJohn Forte 				 */
2469fcf3ce44SJohn Forte 				else if (strcmp(tag, "V2") == 0) {
2470fcf3ce44SJohn Forte 					(void) strcpy(vpd->model, buffer);
2471fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2472*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Model: %s",
2473*291a2b48SSukumar Swaminathan 					    vpd->model);
2474fcf3ce44SJohn Forte 				}
2475fcf3ce44SJohn Forte 				/*
2476fcf3ce44SJohn Forte 				 * Look for program type (V3)
2477fcf3ce44SJohn Forte 				 */
2478fcf3ce44SJohn Forte 
2479fcf3ce44SJohn Forte 				else if (strcmp(tag, "V3") == 0) {
2480fcf3ce44SJohn Forte 					(void) strcpy(vpd->prog_types, buffer);
2481fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2482*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Prog Types: %s",
2483*291a2b48SSukumar Swaminathan 					    vpd->prog_types);
2484fcf3ce44SJohn Forte 				}
2485fcf3ce44SJohn Forte 				/*
2486fcf3ce44SJohn Forte 				 * Look for port number (V4)
2487fcf3ce44SJohn Forte 				 */
2488fcf3ce44SJohn Forte 				else if (strcmp(tag, "V4") == 0) {
2489fcf3ce44SJohn Forte 					(void) strcpy(vpd->port_num, buffer);
2490fcf3ce44SJohn Forte 					vpd->port_index =
2491fcf3ce44SJohn Forte 					    emlxs_strtol(vpd->port_num, 10);
2492fcf3ce44SJohn Forte 
2493fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2494*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Port: %s",
2495*291a2b48SSukumar Swaminathan 					    (vpd->port_num[0]) ? vpd->
2496*291a2b48SSukumar Swaminathan 					    port_num : "not applicable");
2497fcf3ce44SJohn Forte 				}
2498fcf3ce44SJohn Forte 				/*
2499fcf3ce44SJohn Forte 				 * Look for checksum (RV)
2500fcf3ce44SJohn Forte 				 */
2501fcf3ce44SJohn Forte 				else if (strcmp(tag, "RV") == 0) {
2502fcf3ce44SJohn Forte 					/* Not used */
2503fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2504*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Checksum: 0x%x",
2505*291a2b48SSukumar Swaminathan 					    buffer[0]);
2506*291a2b48SSukumar Swaminathan 				}
2507*291a2b48SSukumar Swaminathan 
2508*291a2b48SSukumar Swaminathan 				else {
2509fcf3ce44SJohn Forte 					/* Generic */
2510fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2511*291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Tag: %s: %s",
2512*291a2b48SSukumar Swaminathan 					    tag, buffer);
2513fcf3ce44SJohn Forte 				}
2514fcf3ce44SJohn Forte 			}
2515fcf3ce44SJohn Forte 
2516fcf3ce44SJohn Forte 			break;
2517fcf3ce44SJohn Forte 
2518fcf3ce44SJohn Forte 		case 0x78:
2519fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
2520fcf3ce44SJohn Forte 			finished = 1;
2521fcf3ce44SJohn Forte 			break;
2522fcf3ce44SJohn Forte 
2523fcf3ce44SJohn Forte 		default:
2524fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2525fcf3ce44SJohn Forte 			    "Unknown block: %x %x %x %x %x %x %x %x",
2526fcf3ce44SJohn Forte 			    vpd_buf[index], vpd_buf[index + 1],
2527fcf3ce44SJohn Forte 			    vpd_buf[index + 2], vpd_buf[index + 3],
2528fcf3ce44SJohn Forte 			    vpd_buf[index + 4], vpd_buf[index + 5],
2529fcf3ce44SJohn Forte 			    vpd_buf[index + 6], vpd_buf[index + 7]);
2530fcf3ce44SJohn Forte 			return (0);
2531fcf3ce44SJohn Forte 		}
2532fcf3ce44SJohn Forte 	}
2533fcf3ce44SJohn Forte 
2534fcf3ce44SJohn Forte 	return (1);
2535fcf3ce44SJohn Forte 
2536*291a2b48SSukumar Swaminathan }  /* emlxs_parse_vpd */
2537fcf3ce44SJohn Forte 
2538fcf3ce44SJohn Forte 
2539fcf3ce44SJohn Forte 
2540fcf3ce44SJohn Forte static uint32_t
2541fcf3ce44SJohn Forte emlxs_decode_biu_rev(uint32_t rev)
2542fcf3ce44SJohn Forte {
2543fcf3ce44SJohn Forte 	return (rev & 0xf);
2544*291a2b48SSukumar Swaminathan }  /* End emlxs_decode_biu_rev */
2545fcf3ce44SJohn Forte 
2546fcf3ce44SJohn Forte 
2547fcf3ce44SJohn Forte static uint32_t
2548fcf3ce44SJohn Forte emlxs_decode_endec_rev(uint32_t rev)
2549fcf3ce44SJohn Forte {
2550fcf3ce44SJohn Forte 	return ((rev >> 28) & 0xf);
2551*291a2b48SSukumar Swaminathan }  /* End emlxs_decode_endec_rev */
2552fcf3ce44SJohn Forte 
2553fcf3ce44SJohn Forte 
2554fcf3ce44SJohn Forte extern void
2555fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
2556fcf3ce44SJohn Forte {
2557fcf3ce44SJohn Forte 	if (vpd->rBit) {
2558fcf3ce44SJohn Forte 		switch (hba->sli_mode) {
2559*291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI4_MODE:
2560fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli4FwName);
2561fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli4FwLabel);
2562fcf3ce44SJohn Forte 			break;
2563*291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI3_MODE:
2564fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli3FwName);
2565fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli3FwLabel);
2566fcf3ce44SJohn Forte 			break;
2567*291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI2_MODE:
2568fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli2FwName);
2569fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli2FwLabel);
2570fcf3ce44SJohn Forte 			break;
2571*291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI1_MODE:
2572fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli1FwName);
2573fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli1FwLabel);
2574fcf3ce44SJohn Forte 			break;
2575fcf3ce44SJohn Forte 		default:
2576fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, "unknown");
2577fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->fw_version);
2578fcf3ce44SJohn Forte 		}
2579fcf3ce44SJohn Forte 	} else {
2580fcf3ce44SJohn Forte 		emlxs_decode_version(vpd->smFwRev, vpd->fw_version);
2581fcf3ce44SJohn Forte 		(void) strcpy(vpd->fw_label, vpd->fw_version);
2582fcf3ce44SJohn Forte 	}
2583fcf3ce44SJohn Forte 
2584fcf3ce44SJohn Forte 	return;
2585fcf3ce44SJohn Forte 
2586*291a2b48SSukumar Swaminathan }  /* emlxs_decode_firmware_rev() */
2587fcf3ce44SJohn Forte 
2588fcf3ce44SJohn Forte 
2589fcf3ce44SJohn Forte 
2590fcf3ce44SJohn Forte extern void
2591fcf3ce44SJohn Forte emlxs_decode_version(uint32_t version, char *buffer)
2592fcf3ce44SJohn Forte {
2593fcf3ce44SJohn Forte 	uint32_t b1, b2, b3, b4;
2594fcf3ce44SJohn Forte 	char c;
2595fcf3ce44SJohn Forte 
2596fcf3ce44SJohn Forte 	b1 = (version & 0x0000f000) >> 12;
2597fcf3ce44SJohn Forte 	b2 = (version & 0x00000f00) >> 8;
2598fcf3ce44SJohn Forte 	b3 = (version & 0x000000c0) >> 6;
2599fcf3ce44SJohn Forte 	b4 = (version & 0x00000030) >> 4;
2600fcf3ce44SJohn Forte 
2601fcf3ce44SJohn Forte 	if (b1 == 0 && b2 == 0) {
2602fcf3ce44SJohn Forte 		(void) sprintf(buffer, "none");
2603fcf3ce44SJohn Forte 		return;
2604fcf3ce44SJohn Forte 	}
2605*291a2b48SSukumar Swaminathan 
2606fcf3ce44SJohn Forte 	c = 0;
2607fcf3ce44SJohn Forte 	switch (b4) {
2608fcf3ce44SJohn Forte 	case 0:
2609fcf3ce44SJohn Forte 		c = 'n';
2610fcf3ce44SJohn Forte 		break;
2611fcf3ce44SJohn Forte 	case 1:
2612fcf3ce44SJohn Forte 		c = 'a';
2613fcf3ce44SJohn Forte 		break;
2614fcf3ce44SJohn Forte 	case 2:
2615fcf3ce44SJohn Forte 		c = 'b';
2616fcf3ce44SJohn Forte 		break;
2617fcf3ce44SJohn Forte 	case 3:
2618fcf3ce44SJohn Forte 		if ((version & 0x0000000f)) {
2619fcf3ce44SJohn Forte 			c = 'x';
2620fcf3ce44SJohn Forte 		}
2621fcf3ce44SJohn Forte 		break;
2622fcf3ce44SJohn Forte 
2623fcf3ce44SJohn Forte 	}
2624fcf3ce44SJohn Forte 	b4 = (version & 0x0000000f);
2625fcf3ce44SJohn Forte 
2626fcf3ce44SJohn Forte 	if (c == 0) {
2627fcf3ce44SJohn Forte 		(void) sprintf(buffer, "%d.%d%d", b1, b2, b3);
2628fcf3ce44SJohn Forte 	} else {
2629fcf3ce44SJohn Forte 		(void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4);
2630fcf3ce44SJohn Forte 	}
2631fcf3ce44SJohn Forte 
2632fcf3ce44SJohn Forte 	return;
2633fcf3ce44SJohn Forte 
2634*291a2b48SSukumar Swaminathan }  /* emlxs_decode_version() */
2635fcf3ce44SJohn Forte 
2636fcf3ce44SJohn Forte 
2637fcf3ce44SJohn Forte static void
2638fcf3ce44SJohn Forte emlxs_decode_label(char *label, char *buffer)
2639fcf3ce44SJohn Forte {
2640fcf3ce44SJohn Forte 	uint32_t i;
2641fcf3ce44SJohn Forte 	char name[16];
2642fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN
2643fcf3ce44SJohn Forte 	uint32_t *wptr;
2644fcf3ce44SJohn Forte 	uint32_t word;
2645*291a2b48SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
2646fcf3ce44SJohn Forte 
2647fcf3ce44SJohn Forte 	bcopy(label, name, 16);
2648fcf3ce44SJohn Forte 
2649fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN
2650fcf3ce44SJohn Forte 	wptr = (uint32_t *)name;
2651fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
2652fcf3ce44SJohn Forte 		word = *wptr;
2653fcf3ce44SJohn Forte 		word = SWAP_DATA32(word);
2654fcf3ce44SJohn Forte 		*wptr++ = word;
2655fcf3ce44SJohn Forte 	}
2656*291a2b48SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
2657fcf3ce44SJohn Forte 
2658fcf3ce44SJohn Forte 	for (i = 0; i < 16; i++) {
2659fcf3ce44SJohn Forte 		if (name[i] == 0x20) {
2660fcf3ce44SJohn Forte 			name[i] = 0;
2661fcf3ce44SJohn Forte 		}
2662fcf3ce44SJohn Forte 	}
2663fcf3ce44SJohn Forte 
2664fcf3ce44SJohn Forte 	(void) strcpy(buffer, name);
2665fcf3ce44SJohn Forte 
2666fcf3ce44SJohn Forte 	return;
2667fcf3ce44SJohn Forte 
2668*291a2b48SSukumar Swaminathan }  /* emlxs_decode_label() */
2669fcf3ce44SJohn Forte 
2670fcf3ce44SJohn Forte 
2671fcf3ce44SJohn Forte extern uint32_t
2672fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base)
2673fcf3ce44SJohn Forte {
2674fcf3ce44SJohn Forte 	uint32_t value = 0;
2675fcf3ce44SJohn Forte 	char *ptr;
2676fcf3ce44SJohn Forte 	uint32_t factor = 1;
2677fcf3ce44SJohn Forte 	uint32_t digits;
2678fcf3ce44SJohn Forte 
2679fcf3ce44SJohn Forte 	if (*str == 0) {
2680fcf3ce44SJohn Forte 		return (0);
2681fcf3ce44SJohn Forte 	}
2682*291a2b48SSukumar Swaminathan 
2683fcf3ce44SJohn Forte 	if (base != 10 && base != 16) {
2684fcf3ce44SJohn Forte 		return (0);
2685fcf3ce44SJohn Forte 	}
2686*291a2b48SSukumar Swaminathan 
2687fcf3ce44SJohn Forte 	/* Get max digits of value */
2688fcf3ce44SJohn Forte 	digits = (base == 10) ? 9 : 8;
2689fcf3ce44SJohn Forte 
2690fcf3ce44SJohn Forte 	/* Position pointer to end of string */
2691fcf3ce44SJohn Forte 	ptr = str + strlen(str);
2692fcf3ce44SJohn Forte 
2693fcf3ce44SJohn Forte 	/* Process string backwards */
2694fcf3ce44SJohn Forte 	while ((ptr-- > str) && digits) {
2695fcf3ce44SJohn Forte 		/* check for base 10 numbers */
2696fcf3ce44SJohn Forte 		if (*ptr >= '0' && *ptr <= '9') {
2697fcf3ce44SJohn Forte 			value += ((uint32_t)(*ptr - '0')) * factor;
2698fcf3ce44SJohn Forte 			factor *= base;
2699fcf3ce44SJohn Forte 			digits--;
2700fcf3ce44SJohn Forte 		} else if (base == 16) {
2701fcf3ce44SJohn Forte 			/* Check for base 16 numbers */
2702fcf3ce44SJohn Forte 			if (*ptr >= 'a' && *ptr <= 'f') {
2703*291a2b48SSukumar Swaminathan 				value +=
2704*291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
2705fcf3ce44SJohn Forte 				factor *= base;
2706fcf3ce44SJohn Forte 				digits--;
2707fcf3ce44SJohn Forte 			} else if (*ptr >= 'A' && *ptr <= 'F') {
2708*291a2b48SSukumar Swaminathan 				value +=
2709*291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
2710fcf3ce44SJohn Forte 				factor *= base;
2711fcf3ce44SJohn Forte 				digits--;
2712fcf3ce44SJohn Forte 			} else if (factor > 1) {
2713fcf3ce44SJohn Forte 				break;
2714fcf3ce44SJohn Forte 			}
2715fcf3ce44SJohn Forte 		} else if (factor > 1) {
2716fcf3ce44SJohn Forte 			break;
2717fcf3ce44SJohn Forte 		}
2718fcf3ce44SJohn Forte 	}
2719fcf3ce44SJohn Forte 
2720fcf3ce44SJohn Forte 	return (value);
2721fcf3ce44SJohn Forte 
2722*291a2b48SSukumar Swaminathan }  /* emlxs_strtol() */
2723fcf3ce44SJohn Forte 
2724fcf3ce44SJohn Forte 
2725fcf3ce44SJohn Forte extern uint64_t
2726fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base)
2727fcf3ce44SJohn Forte {
2728fcf3ce44SJohn Forte 	uint64_t value = 0;
2729fcf3ce44SJohn Forte 	char *ptr;
2730fcf3ce44SJohn Forte 	uint32_t factor = 1;
2731fcf3ce44SJohn Forte 	uint32_t digits;
2732fcf3ce44SJohn Forte 
2733fcf3ce44SJohn Forte 	if (*str == 0) {
2734fcf3ce44SJohn Forte 		return (0);
2735fcf3ce44SJohn Forte 	}
2736*291a2b48SSukumar Swaminathan 
2737fcf3ce44SJohn Forte 	if (base != 10 && base != 16) {
2738fcf3ce44SJohn Forte 		return (0);
2739fcf3ce44SJohn Forte 	}
2740*291a2b48SSukumar Swaminathan 
2741fcf3ce44SJohn Forte 	/* Get max digits of value */
2742fcf3ce44SJohn Forte 	digits = (base == 10) ? 19 : 16;
2743fcf3ce44SJohn Forte 
2744fcf3ce44SJohn Forte 	/* Position pointer to end of string */
2745fcf3ce44SJohn Forte 	ptr = str + strlen(str);
2746fcf3ce44SJohn Forte 
2747fcf3ce44SJohn Forte 	/* Process string backwards */
2748fcf3ce44SJohn Forte 	while ((ptr-- > str) && digits) {
2749fcf3ce44SJohn Forte 		/* check for base 10 numbers */
2750fcf3ce44SJohn Forte 		if (*ptr >= '0' && *ptr <= '9') {
2751fcf3ce44SJohn Forte 			value += ((uint32_t)(*ptr - '0')) * factor;
2752fcf3ce44SJohn Forte 			factor *= base;
2753fcf3ce44SJohn Forte 			digits--;
2754fcf3ce44SJohn Forte 		} else if (base == 16) {
2755fcf3ce44SJohn Forte 			/* Check for base 16 numbers */
2756fcf3ce44SJohn Forte 			if (*ptr >= 'a' && *ptr <= 'f') {
2757*291a2b48SSukumar Swaminathan 				value +=
2758*291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
2759fcf3ce44SJohn Forte 				factor *= base;
2760fcf3ce44SJohn Forte 				digits--;
2761fcf3ce44SJohn Forte 			} else if (*ptr >= 'A' && *ptr <= 'F') {
2762*291a2b48SSukumar Swaminathan 				value +=
2763*291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
2764fcf3ce44SJohn Forte 				factor *= base;
2765fcf3ce44SJohn Forte 				digits--;
2766fcf3ce44SJohn Forte 			} else if (factor > 1) {
2767fcf3ce44SJohn Forte 				break;
2768fcf3ce44SJohn Forte 			}
2769fcf3ce44SJohn Forte 		} else if (factor > 1) {
2770fcf3ce44SJohn Forte 			break;
2771fcf3ce44SJohn Forte 		}
2772fcf3ce44SJohn Forte 	}
2773fcf3ce44SJohn Forte 
2774fcf3ce44SJohn Forte 	return (value);
2775fcf3ce44SJohn Forte 
2776*291a2b48SSukumar Swaminathan }  /* emlxs_strtoll() */
2777fcf3ce44SJohn Forte 
2778fcf3ce44SJohn Forte static void
2779fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
2780fcf3ce44SJohn Forte {
2781fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2782fcf3ce44SJohn Forte 	uint32_t i;
2783fcf3ce44SJohn Forte 	char *ptr;
2784fcf3ce44SJohn Forte 	emlxs_model_t *model;
2785fcf3ce44SJohn Forte 	char types_buffer[256];
2786fcf3ce44SJohn Forte 	char *types;
2787fcf3ce44SJohn Forte 
2788fcf3ce44SJohn Forte 	bcopy(prog_types, types_buffer, 256);
2789fcf3ce44SJohn Forte 	types = types_buffer;
2790fcf3ce44SJohn Forte 
2791fcf3ce44SJohn Forte 	model = &hba->model_info;
2792fcf3ce44SJohn Forte 
2793fcf3ce44SJohn Forte 	while (*types) {
2794fcf3ce44SJohn Forte 		if (strncmp(types, "T2:", 3) == 0) {
2795fcf3ce44SJohn Forte 			bzero(model->pt_2, sizeof (model->pt_2));
2796fcf3ce44SJohn Forte 			types += 3;
2797fcf3ce44SJohn Forte 
2798fcf3ce44SJohn Forte 			i = 0;
2799fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2800fcf3ce44SJohn Forte 				/* Null terminate the next value */
2801fcf3ce44SJohn Forte 				ptr = types;
2802fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2803fcf3ce44SJohn Forte 					ptr++;
2804fcf3ce44SJohn Forte 				*ptr = 0;
2805fcf3ce44SJohn Forte 
2806fcf3ce44SJohn Forte 				/* Save the value */
2807fcf3ce44SJohn Forte 				model->pt_2[i++] =
2808fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2809fcf3ce44SJohn Forte 
2810fcf3ce44SJohn Forte 				/*
2811fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2812fcf3ce44SJohn Forte 				 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
2813fcf3ce44SJohn Forte 				 */
2814fcf3ce44SJohn Forte 
2815fcf3ce44SJohn Forte 				/* Move the str pointer */
2816fcf3ce44SJohn Forte 				types = ptr + 1;
2817fcf3ce44SJohn Forte 			}
2818fcf3ce44SJohn Forte 
2819fcf3ce44SJohn Forte 		} else if (strncmp(types, "T3:", 3) == 0) {
2820fcf3ce44SJohn Forte 			bzero(model->pt_3, sizeof (model->pt_3));
2821fcf3ce44SJohn Forte 			types += 3;
2822fcf3ce44SJohn Forte 
2823fcf3ce44SJohn Forte 			i = 0;
2824fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2825fcf3ce44SJohn Forte 				/* Null terminate the next value */
2826fcf3ce44SJohn Forte 				ptr = types;
2827fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2828fcf3ce44SJohn Forte 					ptr++;
2829fcf3ce44SJohn Forte 				*ptr = 0;
2830fcf3ce44SJohn Forte 
2831fcf3ce44SJohn Forte 				/* Save the value */
2832fcf3ce44SJohn Forte 				model->pt_3[i++] =
2833fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2834fcf3ce44SJohn Forte 
2835fcf3ce44SJohn Forte 				/*
2836fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2837fcf3ce44SJohn Forte 				 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
2838fcf3ce44SJohn Forte 				 */
2839fcf3ce44SJohn Forte 
2840fcf3ce44SJohn Forte 				/* Move the str pointer */
2841fcf3ce44SJohn Forte 				types = ptr + 1;
2842fcf3ce44SJohn Forte 			}
2843fcf3ce44SJohn Forte 		} else if (strncmp(types, "T6:", 3) == 0) {
2844fcf3ce44SJohn Forte 			bzero(model->pt_6, sizeof (model->pt_6));
2845fcf3ce44SJohn Forte 			types += 3;
2846fcf3ce44SJohn Forte 
2847fcf3ce44SJohn Forte 			i = 0;
2848fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2849fcf3ce44SJohn Forte 				/* Null terminate the next value */
2850fcf3ce44SJohn Forte 				ptr = types;
2851fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2852fcf3ce44SJohn Forte 					ptr++;
2853fcf3ce44SJohn Forte 				*ptr = 0;
2854fcf3ce44SJohn Forte 
2855fcf3ce44SJohn Forte 				/* Save the value */
2856fcf3ce44SJohn Forte 				model->pt_6[i++] =
2857fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2858fcf3ce44SJohn Forte 				model->pt_6[i] = 0;
2859fcf3ce44SJohn Forte 
2860fcf3ce44SJohn Forte 				/*
2861fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2862fcf3ce44SJohn Forte 				 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
2863fcf3ce44SJohn Forte 				 */
2864fcf3ce44SJohn Forte 
2865fcf3ce44SJohn Forte 				/* Move the str pointer */
2866fcf3ce44SJohn Forte 				types = ptr + 1;
2867fcf3ce44SJohn Forte 			}
2868fcf3ce44SJohn Forte 		} else if (strncmp(types, "T7:", 3) == 0) {
2869fcf3ce44SJohn Forte 			bzero(model->pt_7, sizeof (model->pt_7));
2870fcf3ce44SJohn Forte 			types += 3;
2871fcf3ce44SJohn Forte 
2872fcf3ce44SJohn Forte 			i = 0;
2873fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2874fcf3ce44SJohn Forte 				/* Null terminate the next value */
2875fcf3ce44SJohn Forte 				ptr = types;
2876fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2877fcf3ce44SJohn Forte 					ptr++;
2878fcf3ce44SJohn Forte 				*ptr = 0;
2879fcf3ce44SJohn Forte 
2880fcf3ce44SJohn Forte 				/* Save the value */
2881fcf3ce44SJohn Forte 				model->pt_7[i++] =
2882fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2883fcf3ce44SJohn Forte 				model->pt_7[i] = 0;
2884fcf3ce44SJohn Forte 
2885fcf3ce44SJohn Forte 				/*
2886fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2887fcf3ce44SJohn Forte 				 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
2888fcf3ce44SJohn Forte 				 */
2889fcf3ce44SJohn Forte 
2890fcf3ce44SJohn Forte 				/* Move the str pointer */
2891fcf3ce44SJohn Forte 				types = ptr + 1;
2892fcf3ce44SJohn Forte 			}
2893fcf3ce44SJohn Forte 		} else if (strncmp(types, "TA:", 3) == 0) {
2894fcf3ce44SJohn Forte 			bzero(model->pt_A, sizeof (model->pt_A));
2895fcf3ce44SJohn Forte 			types += 3;
2896fcf3ce44SJohn Forte 
2897fcf3ce44SJohn Forte 			i = 0;
2898fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2899fcf3ce44SJohn Forte 				/* Null terminate the next value */
2900fcf3ce44SJohn Forte 				ptr = types;
2901fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2902fcf3ce44SJohn Forte 					ptr++;
2903fcf3ce44SJohn Forte 				*ptr = 0;
2904fcf3ce44SJohn Forte 
2905fcf3ce44SJohn Forte 				/* Save the value */
2906fcf3ce44SJohn Forte 				model->pt_A[i++] =
2907fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2908fcf3ce44SJohn Forte 
2909fcf3ce44SJohn Forte 				/*
2910fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2911fcf3ce44SJohn Forte 				 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
2912fcf3ce44SJohn Forte 				 */
2913fcf3ce44SJohn Forte 
2914fcf3ce44SJohn Forte 				/* Move the str pointer */
2915fcf3ce44SJohn Forte 				types = ptr + 1;
2916fcf3ce44SJohn Forte 			}
2917fcf3ce44SJohn Forte 		} else if (strncmp(types, "TB:", 3) == 0) {
2918fcf3ce44SJohn Forte 			bzero(model->pt_B, sizeof (model->pt_B));
2919fcf3ce44SJohn Forte 			types += 3;
2920fcf3ce44SJohn Forte 
2921fcf3ce44SJohn Forte 			i = 0;
2922fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2923fcf3ce44SJohn Forte 				/* Null terminate the next value */
2924fcf3ce44SJohn Forte 				ptr = types;
2925fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2926fcf3ce44SJohn Forte 					ptr++;
2927fcf3ce44SJohn Forte 				*ptr = 0;
2928fcf3ce44SJohn Forte 
2929fcf3ce44SJohn Forte 				/* Save the value */
2930fcf3ce44SJohn Forte 				model->pt_B[i++] =
2931fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2932fcf3ce44SJohn Forte 
2933fcf3ce44SJohn Forte 				/*
2934fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2935fcf3ce44SJohn Forte 				 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
2936fcf3ce44SJohn Forte 				 */
2937fcf3ce44SJohn Forte 
2938fcf3ce44SJohn Forte 				/* Move the str pointer */
2939fcf3ce44SJohn Forte 				types = ptr + 1;
2940fcf3ce44SJohn Forte 			}
2941fcf3ce44SJohn Forte 		} else if (strncmp(types, "TFF:", 4) == 0) {
2942fcf3ce44SJohn Forte 			bzero(model->pt_FF, sizeof (model->pt_FF));
2943fcf3ce44SJohn Forte 			types += 4;
2944fcf3ce44SJohn Forte 
2945fcf3ce44SJohn Forte 			i = 0;
2946fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
2947fcf3ce44SJohn Forte 				/* Null terminate the next value */
2948fcf3ce44SJohn Forte 				ptr = types;
2949fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
2950fcf3ce44SJohn Forte 					ptr++;
2951fcf3ce44SJohn Forte 				*ptr = 0;
2952fcf3ce44SJohn Forte 
2953fcf3ce44SJohn Forte 				/* Save the value */
2954fcf3ce44SJohn Forte 				model->pt_FF[i++] =
2955fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
2956fcf3ce44SJohn Forte 
2957fcf3ce44SJohn Forte 				/*
2958fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2959fcf3ce44SJohn Forte 				 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
2960fcf3ce44SJohn Forte 				 */
2961fcf3ce44SJohn Forte 
2962*291a2b48SSukumar Swaminathan 				/* Move the str pointer */
2963*291a2b48SSukumar Swaminathan 				types = ptr + 1;
2964*291a2b48SSukumar Swaminathan 			}
2965*291a2b48SSukumar Swaminathan 		} else if (strncmp(types, "T20:", 4) == 0) {
2966*291a2b48SSukumar Swaminathan 			bzero(model->pt_20, sizeof (model->pt_20));
2967*291a2b48SSukumar Swaminathan 			types += 4;
2968*291a2b48SSukumar Swaminathan 
2969*291a2b48SSukumar Swaminathan 			i = 0;
2970*291a2b48SSukumar Swaminathan 			while (*types && *types != 'T') {
2971*291a2b48SSukumar Swaminathan 				/* Null terminate the next value */
2972*291a2b48SSukumar Swaminathan 				ptr = types;
2973*291a2b48SSukumar Swaminathan 				while (*ptr && (*ptr != ','))
2974*291a2b48SSukumar Swaminathan 					ptr++;
2975*291a2b48SSukumar Swaminathan 				*ptr = 0;
2976*291a2b48SSukumar Swaminathan 
2977*291a2b48SSukumar Swaminathan 				/* Save the value */
2978*291a2b48SSukumar Swaminathan 				model->pt_20[i++] =
2979*291a2b48SSukumar Swaminathan 				    (uint8_t)emlxs_strtol(types, 16);
2980*291a2b48SSukumar Swaminathan 				model->pt_20[i] = 0;
2981*291a2b48SSukumar Swaminathan 
2982*291a2b48SSukumar Swaminathan 				/*
2983*291a2b48SSukumar Swaminathan 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2984*291a2b48SSukumar Swaminathan 				 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
2985*291a2b48SSukumar Swaminathan 				 */
2986*291a2b48SSukumar Swaminathan 
2987fcf3ce44SJohn Forte 				/* Move the str pointer */
2988fcf3ce44SJohn Forte 				types = ptr + 1;
2989fcf3ce44SJohn Forte 			}
2990fcf3ce44SJohn Forte 		} else {
2991fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
2992fcf3ce44SJohn Forte 			    "Unknown prog type string = %s", types);
2993fcf3ce44SJohn Forte 			break;
2994fcf3ce44SJohn Forte 		}
2995fcf3ce44SJohn Forte 	}
2996fcf3ce44SJohn Forte 
2997fcf3ce44SJohn Forte 	return;
2998fcf3ce44SJohn Forte 
2999*291a2b48SSukumar Swaminathan }  /* emlxs_parse_prog_types() */
3000fcf3ce44SJohn Forte 
3001fcf3ce44SJohn Forte 
3002fcf3ce44SJohn Forte static void
3003fcf3ce44SJohn Forte emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types)
3004fcf3ce44SJohn Forte {
3005fcf3ce44SJohn Forte 	uint32_t i;
3006fcf3ce44SJohn Forte 	uint32_t found = 0;
3007fcf3ce44SJohn Forte 	char buffer[256];
3008fcf3ce44SJohn Forte 
3009fcf3ce44SJohn Forte 	bzero(prog_types, 256);
3010fcf3ce44SJohn Forte 
3011fcf3ce44SJohn Forte 	/* Rebuild the prog type string */
3012fcf3ce44SJohn Forte 	if (hba->model_info.pt_2[0]) {
3013fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T2:");
3014fcf3ce44SJohn Forte 		found = 1;
3015fcf3ce44SJohn Forte 
3016fcf3ce44SJohn Forte 		i = 0;
3017fcf3ce44SJohn Forte 		while (hba->model_info.pt_2[i] && i < 8) {
3018fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]);
3019fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3020fcf3ce44SJohn Forte 			i++;
3021fcf3ce44SJohn Forte 		}
3022fcf3ce44SJohn Forte 	}
3023*291a2b48SSukumar Swaminathan 
3024fcf3ce44SJohn Forte 	if (hba->model_info.pt_3[0]) {
3025fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T3:");
3026fcf3ce44SJohn Forte 		found = 1;
3027fcf3ce44SJohn Forte 
3028fcf3ce44SJohn Forte 		i = 0;
3029fcf3ce44SJohn Forte 		while (hba->model_info.pt_3[i] && i < 8) {
3030fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]);
3031fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3032fcf3ce44SJohn Forte 			i++;
3033fcf3ce44SJohn Forte 
3034fcf3ce44SJohn Forte 		}
3035fcf3ce44SJohn Forte 	}
3036*291a2b48SSukumar Swaminathan 
3037fcf3ce44SJohn Forte 	if (hba->model_info.pt_6[0]) {
3038fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T6:");
3039fcf3ce44SJohn Forte 		found = 1;
3040fcf3ce44SJohn Forte 
3041fcf3ce44SJohn Forte 		i = 0;
3042fcf3ce44SJohn Forte 		while (hba->model_info.pt_6[i] && i < 8) {
3043fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]);
3044fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3045fcf3ce44SJohn Forte 			i++;
3046fcf3ce44SJohn Forte 		}
3047fcf3ce44SJohn Forte 	}
3048*291a2b48SSukumar Swaminathan 
3049fcf3ce44SJohn Forte 	if (hba->model_info.pt_7[0]) {
3050fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T7:");
3051fcf3ce44SJohn Forte 		found = 1;
3052fcf3ce44SJohn Forte 
3053fcf3ce44SJohn Forte 		i = 0;
3054fcf3ce44SJohn Forte 		while (hba->model_info.pt_7[i] && i < 8) {
3055fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]);
3056fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3057fcf3ce44SJohn Forte 			i++;
3058fcf3ce44SJohn Forte 		}
3059fcf3ce44SJohn Forte 	}
3060*291a2b48SSukumar Swaminathan 
3061fcf3ce44SJohn Forte 	if (hba->model_info.pt_A[0]) {
3062fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TA:");
3063fcf3ce44SJohn Forte 		found = 1;
3064fcf3ce44SJohn Forte 
3065fcf3ce44SJohn Forte 		i = 0;
3066fcf3ce44SJohn Forte 		while (hba->model_info.pt_A[i] && i < 8) {
3067fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]);
3068fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3069fcf3ce44SJohn Forte 			i++;
3070fcf3ce44SJohn Forte 		}
3071fcf3ce44SJohn Forte 	}
3072*291a2b48SSukumar Swaminathan 
3073*291a2b48SSukumar Swaminathan 
3074fcf3ce44SJohn Forte 	if (hba->model_info.pt_B[0]) {
3075fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TB:");
3076fcf3ce44SJohn Forte 		found = 1;
3077fcf3ce44SJohn Forte 
3078fcf3ce44SJohn Forte 		i = 0;
3079fcf3ce44SJohn Forte 		while (hba->model_info.pt_B[i] && i < 8) {
3080fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]);
3081fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3082fcf3ce44SJohn Forte 			i++;
3083fcf3ce44SJohn Forte 		}
3084fcf3ce44SJohn Forte 	}
3085*291a2b48SSukumar Swaminathan 
3086*291a2b48SSukumar Swaminathan 	if (hba->model_info.pt_20[0]) {
3087*291a2b48SSukumar Swaminathan 		(void) strcat(prog_types, "T20:");
3088*291a2b48SSukumar Swaminathan 		found = 1;
3089*291a2b48SSukumar Swaminathan 
3090*291a2b48SSukumar Swaminathan 		i = 0;
3091*291a2b48SSukumar Swaminathan 		while (hba->model_info.pt_20[i] && i < 8) {
3092*291a2b48SSukumar Swaminathan 			(void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]);
3093*291a2b48SSukumar Swaminathan 			(void) strcat(prog_types, buffer);
3094*291a2b48SSukumar Swaminathan 			i++;
3095*291a2b48SSukumar Swaminathan 		}
3096*291a2b48SSukumar Swaminathan 	}
3097*291a2b48SSukumar Swaminathan 
3098fcf3ce44SJohn Forte 	if (hba->model_info.pt_FF[0]) {
3099fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TFF:");
3100fcf3ce44SJohn Forte 		found = 1;
3101fcf3ce44SJohn Forte 
3102fcf3ce44SJohn Forte 		i = 0;
3103fcf3ce44SJohn Forte 		while (hba->model_info.pt_FF[i] && i < 8) {
3104fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]);
3105fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
3106fcf3ce44SJohn Forte 			i++;
3107fcf3ce44SJohn Forte 		}
3108fcf3ce44SJohn Forte 	}
3109*291a2b48SSukumar Swaminathan 
3110fcf3ce44SJohn Forte 	if (found) {
3111fcf3ce44SJohn Forte 		/* Terminate at the last comma in string */
3112fcf3ce44SJohn Forte 		prog_types[(strlen(prog_types) - 1)] = 0;
3113fcf3ce44SJohn Forte 	}
3114*291a2b48SSukumar Swaminathan 
3115fcf3ce44SJohn Forte 	return;
3116fcf3ce44SJohn Forte 
3117*291a2b48SSukumar Swaminathan }  /* emlxs_build_prog_types() */
3118fcf3ce44SJohn Forte 
3119fcf3ce44SJohn Forte 
3120fcf3ce44SJohn Forte 
3121fcf3ce44SJohn Forte 
3122fcf3ce44SJohn Forte extern uint32_t
3123fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba)
3124fcf3ce44SJohn Forte {
3125fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3126fcf3ce44SJohn Forte 	uint32_t pci_id;
3127fcf3ce44SJohn Forte 	uint32_t cache_line;
3128fcf3ce44SJohn Forte 	uint32_t channels;
3129fcf3ce44SJohn Forte 	uint16_t device_id;
3130fcf3ce44SJohn Forte 	uint16_t ssdid;
3131fcf3ce44SJohn Forte 	uint32_t i;
3132fcf3ce44SJohn Forte 	uint32_t found = 0;
3133fcf3ce44SJohn Forte 
3134fcf3ce44SJohn Forte 	if (hba->bus_type == SBUS_FC) {
3135fcf3ce44SJohn Forte 		if (hba->pci_acc_handle == NULL) {
3136fcf3ce44SJohn Forte 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
3137fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
3138fcf3ce44SJohn Forte 
3139fcf3ce44SJohn Forte 			hba->model_info.device_id = 0;
3140fcf3ce44SJohn Forte 
3141fcf3ce44SJohn Forte 			return (0);
3142fcf3ce44SJohn Forte 		}
3143*291a2b48SSukumar Swaminathan 
3144fcf3ce44SJohn Forte 		/* Read the PCI device id */
3145*291a2b48SSukumar Swaminathan 		pci_id =
3146*291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
3147fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
3148fcf3ce44SJohn Forte 		device_id = (uint16_t)(pci_id >> 16);
3149fcf3ce44SJohn Forte 
3150fcf3ce44SJohn Forte 		/* Find matching adapter model */
3151fcf3ce44SJohn Forte 		for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
3152fcf3ce44SJohn Forte 			if (emlxs_sbus_model[i].device_id == device_id) {
3153fcf3ce44SJohn Forte 				bcopy(&emlxs_sbus_model[i], &hba->model_info,
3154fcf3ce44SJohn Forte 				    sizeof (emlxs_model_t));
3155fcf3ce44SJohn Forte 				found = 1;
3156fcf3ce44SJohn Forte 				break;
3157fcf3ce44SJohn Forte 			}
3158fcf3ce44SJohn Forte 		}
3159fcf3ce44SJohn Forte 
3160fcf3ce44SJohn Forte 		/* If not found then use the unknown model */
3161fcf3ce44SJohn Forte 		if (!found) {
3162fcf3ce44SJohn Forte 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
3163fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
3164fcf3ce44SJohn Forte 
3165fcf3ce44SJohn Forte 			hba->model_info.device_id = device_id;
3166fcf3ce44SJohn Forte 
3167fcf3ce44SJohn Forte 			return (0);
3168fcf3ce44SJohn Forte 		}
3169fcf3ce44SJohn Forte 	} else {	/* PCI model */
3170*291a2b48SSukumar Swaminathan 
3171fcf3ce44SJohn Forte 		if (hba->pci_acc_handle == NULL) {
3172fcf3ce44SJohn Forte 			bcopy(&emlxs_pci_model[0], &hba->model_info,
3173fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
3174fcf3ce44SJohn Forte 
3175fcf3ce44SJohn Forte 			hba->model_info.device_id = 0;
3176fcf3ce44SJohn Forte 
3177fcf3ce44SJohn Forte 			return (0);
3178fcf3ce44SJohn Forte 		}
3179*291a2b48SSukumar Swaminathan 
3180fcf3ce44SJohn Forte 		/* Read the PCI device id */
3181*291a2b48SSukumar Swaminathan 		device_id =
3182*291a2b48SSukumar Swaminathan 		    ddi_get16(hba->pci_acc_handle,
3183fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
3184fcf3ce44SJohn Forte 
3185fcf3ce44SJohn Forte 		/* Read the PCI Subsystem id */
3186*291a2b48SSukumar Swaminathan 		ssdid =
3187*291a2b48SSukumar Swaminathan 		    ddi_get16(hba->pci_acc_handle,
3188fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
3189fcf3ce44SJohn Forte 
3190fcf3ce44SJohn Forte 		if (ssdid == 0 || ssdid == 0xffff) {
3191fcf3ce44SJohn Forte 			ssdid = device_id;
3192fcf3ce44SJohn Forte 		}
3193*291a2b48SSukumar Swaminathan 
3194fcf3ce44SJohn Forte 		/* Read the Cache Line reg */
3195*291a2b48SSukumar Swaminathan 		cache_line =
3196*291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
3197fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
3198fcf3ce44SJohn Forte 
3199fcf3ce44SJohn Forte 		/* Check for the multifunction bit being set */
3200fcf3ce44SJohn Forte 		if ((cache_line & 0x00ff0000) == 0x00800000) {
3201fcf3ce44SJohn Forte 			channels = 2;
3202fcf3ce44SJohn Forte 		} else {
3203fcf3ce44SJohn Forte 			channels = 1;
3204fcf3ce44SJohn Forte 		}
3205fcf3ce44SJohn Forte 
3206fcf3ce44SJohn Forte 		/* If device ids are unique, then use them for search */
3207fcf3ce44SJohn Forte 		if (device_id != ssdid) {
3208fcf3ce44SJohn Forte 			if (channels > 1) {
3209fcf3ce44SJohn Forte 				/*
3210fcf3ce44SJohn Forte 				 * Find matching adapter model using
3211fcf3ce44SJohn Forte 				 * device_id, ssdid and channels
3212fcf3ce44SJohn Forte 				 */
3213fcf3ce44SJohn Forte 				for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
3214*291a2b48SSukumar Swaminathan 					if (emlxs_pci_model[i].device_id ==
3215*291a2b48SSukumar Swaminathan 					    device_id &&
3216*291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].ssdid == ssdid &&
3217*291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].channels ==
3218*291a2b48SSukumar Swaminathan 					    channels) {
3219fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
3220fcf3ce44SJohn Forte 						    &hba->model_info,
3221fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
3222fcf3ce44SJohn Forte 						found = 1;
3223fcf3ce44SJohn Forte 						break;
3224fcf3ce44SJohn Forte 					}
3225fcf3ce44SJohn Forte 				}
3226fcf3ce44SJohn Forte 			} else {
3227fcf3ce44SJohn Forte 				/*
3228fcf3ce44SJohn Forte 				 * Find matching adapter model using
3229fcf3ce44SJohn Forte 				 * device_id and ssdid
3230fcf3ce44SJohn Forte 				 */
3231fcf3ce44SJohn Forte 				for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
3232*291a2b48SSukumar Swaminathan 					if (emlxs_pci_model[i].device_id ==
3233*291a2b48SSukumar Swaminathan 					    device_id &&
3234*291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].ssdid == ssdid) {
3235fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
3236fcf3ce44SJohn Forte 						    &hba->model_info,
3237fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
3238fcf3ce44SJohn Forte 						found = 1;
3239fcf3ce44SJohn Forte 						break;
3240fcf3ce44SJohn Forte 					}
3241fcf3ce44SJohn Forte 				}
3242fcf3ce44SJohn Forte 			}
3243fcf3ce44SJohn Forte 		}
3244*291a2b48SSukumar Swaminathan 
3245fcf3ce44SJohn Forte 		/* If adapter not found, try again */
3246fcf3ce44SJohn Forte 		if (!found) {
3247fcf3ce44SJohn Forte 			/* Find matching adapter model */
3248fcf3ce44SJohn Forte 			for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
3249fcf3ce44SJohn Forte 				if (emlxs_pci_model[i].device_id == device_id &&
3250fcf3ce44SJohn Forte 				    emlxs_pci_model[i].channels == channels) {
3251fcf3ce44SJohn Forte 					bcopy(&emlxs_pci_model[i],
3252fcf3ce44SJohn Forte 					    &hba->model_info,
3253fcf3ce44SJohn Forte 					    sizeof (emlxs_model_t));
3254fcf3ce44SJohn Forte 					found = 1;
3255fcf3ce44SJohn Forte 					break;
3256fcf3ce44SJohn Forte 				}
3257fcf3ce44SJohn Forte 			}
3258fcf3ce44SJohn Forte 		}
3259*291a2b48SSukumar Swaminathan 
3260fcf3ce44SJohn Forte 		/* If adapter not found, try one last time */
3261fcf3ce44SJohn Forte 		if (!found) {
3262fcf3ce44SJohn Forte 			/* Find matching adapter model */
3263fcf3ce44SJohn Forte 			for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) {
3264fcf3ce44SJohn Forte 				if (emlxs_pci_model[i].device_id == device_id) {
3265fcf3ce44SJohn Forte 					bcopy(&emlxs_pci_model[i],
3266fcf3ce44SJohn Forte 					    &hba->model_info,
3267fcf3ce44SJohn Forte 					    sizeof (emlxs_model_t));
3268fcf3ce44SJohn Forte 					found = 1;
3269fcf3ce44SJohn Forte 					break;
3270fcf3ce44SJohn Forte 				}
3271fcf3ce44SJohn Forte 			}
3272fcf3ce44SJohn Forte 		}
3273*291a2b48SSukumar Swaminathan 
3274fcf3ce44SJohn Forte 		/* If not found, set adapter to unknown */
3275fcf3ce44SJohn Forte 		if (!found) {
3276fcf3ce44SJohn Forte 			bcopy(&emlxs_pci_model[0], &hba->model_info,
3277fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
3278fcf3ce44SJohn Forte 
3279fcf3ce44SJohn Forte 			hba->model_info.device_id = device_id;
3280fcf3ce44SJohn Forte 			hba->model_info.ssdid = ssdid;
3281fcf3ce44SJohn Forte 
3282fcf3ce44SJohn Forte 			return (0);
3283fcf3ce44SJohn Forte 		}
3284fcf3ce44SJohn Forte 
3285fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT
3286fcf3ce44SJohn Forte 		/*
3287*291a2b48SSukumar Swaminathan 		 * This will disable MSI support for Saturn adapter's
3288*291a2b48SSukumar Swaminathan 		 * due to a PCI bus issue
3289fcf3ce44SJohn Forte 		 */
3290fcf3ce44SJohn Forte 		if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
3291fcf3ce44SJohn Forte 			hba->model_info.flags &=
3292fcf3ce44SJohn Forte 			    ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
3293fcf3ce44SJohn Forte 		}
3294*291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */
3295fcf3ce44SJohn Forte 
3296fcf3ce44SJohn Forte 
3297fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
3298fcf3ce44SJohn Forte 		/* Verify MSI support */
3299fcf3ce44SJohn Forte 		if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) {
3300fcf3ce44SJohn Forte 			uint32_t offset;
3301fcf3ce44SJohn Forte 			uint32_t reg;
3302fcf3ce44SJohn Forte 
3303fcf3ce44SJohn Forte 			/* Scan for MSI capabilities register */
3304*291a2b48SSukumar Swaminathan 			offset =
3305*291a2b48SSukumar Swaminathan 			    ddi_get32(hba->pci_acc_handle,
3306fcf3ce44SJohn Forte 			    (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
3307fcf3ce44SJohn Forte 			offset &= 0xff;
3308fcf3ce44SJohn Forte 
3309fcf3ce44SJohn Forte 			while (offset) {
3310*291a2b48SSukumar Swaminathan 				reg =
3311*291a2b48SSukumar Swaminathan 				    ddi_get32(hba->pci_acc_handle,
3312fcf3ce44SJohn Forte 				    (uint32_t *)(hba->pci_addr + offset));
3313fcf3ce44SJohn Forte 
3314fcf3ce44SJohn Forte 				if ((reg & 0xff) == MSI_CAP_ID) {
3315fcf3ce44SJohn Forte 					break;
3316fcf3ce44SJohn Forte 				}
3317fcf3ce44SJohn Forte 				offset = (reg >> 8) & 0xff;
3318fcf3ce44SJohn Forte 			}
3319fcf3ce44SJohn Forte 
3320fcf3ce44SJohn Forte 			if (offset) {
3321fcf3ce44SJohn Forte 				hba->msi_cap_offset = offset + 2;
3322fcf3ce44SJohn Forte 			} else {
3323fcf3ce44SJohn Forte 				hba->msi_cap_offset = 0;
3324fcf3ce44SJohn Forte 				hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
3325fcf3ce44SJohn Forte 
3326*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3327*291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3328fcf3ce44SJohn Forte 				    "MSI: control_reg capability not found!");
3329fcf3ce44SJohn Forte 			}
3330fcf3ce44SJohn Forte 		}
3331*291a2b48SSukumar Swaminathan 
3332fcf3ce44SJohn Forte 		/* Verify MSI-X support */
3333fcf3ce44SJohn Forte 		if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) {
3334fcf3ce44SJohn Forte 			uint32_t offset;
3335fcf3ce44SJohn Forte 			uint32_t reg;
3336fcf3ce44SJohn Forte 
3337fcf3ce44SJohn Forte 			/* Scan for MSI capabilities register */
3338*291a2b48SSukumar Swaminathan 			offset =
3339*291a2b48SSukumar Swaminathan 			    ddi_get32(hba->pci_acc_handle,
3340fcf3ce44SJohn Forte 			    (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
3341fcf3ce44SJohn Forte 			offset &= 0xff;
3342fcf3ce44SJohn Forte 
3343fcf3ce44SJohn Forte 			while (offset) {
3344*291a2b48SSukumar Swaminathan 				reg =
3345*291a2b48SSukumar Swaminathan 				    ddi_get32(hba->pci_acc_handle,
3346fcf3ce44SJohn Forte 				    (uint32_t *)(hba->pci_addr + offset));
3347fcf3ce44SJohn Forte 
3348fcf3ce44SJohn Forte 				if ((reg & 0xff) == MSIX_CAP_ID) {
3349fcf3ce44SJohn Forte 					break;
3350fcf3ce44SJohn Forte 				}
3351fcf3ce44SJohn Forte 				offset = (reg >> 8) & 0xff;
3352fcf3ce44SJohn Forte 			}
3353fcf3ce44SJohn Forte 
3354fcf3ce44SJohn Forte 			if (offset) {
3355fcf3ce44SJohn Forte 				hba->msix_cap_offset = offset;
3356fcf3ce44SJohn Forte 			} else {
3357fcf3ce44SJohn Forte 				hba->msix_cap_offset = 0;
3358*291a2b48SSukumar Swaminathan 				hba->model_info.flags &=
3359*291a2b48SSukumar Swaminathan 				    ~EMLXS_MSIX_SUPPORTED;
3360fcf3ce44SJohn Forte 
3361*291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3362*291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3363fcf3ce44SJohn Forte 				    "MSIX: control_reg capability not found!");
3364fcf3ce44SJohn Forte 			}
3365fcf3ce44SJohn Forte 		}
3366*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
3367*291a2b48SSukumar Swaminathan 
3368*291a2b48SSukumar Swaminathan 	}
3369fcf3ce44SJohn Forte 
3370*291a2b48SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
3371*291a2b48SSukumar Swaminathan 		return (0);
3372fcf3ce44SJohn Forte 	}
3373fcf3ce44SJohn Forte 
3374*291a2b48SSukumar Swaminathan 	/* For now we just support SLI2 and SLI3 */
3375*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_map_hdw = emlxs_sli3_map_hdw;
3376*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_unmap_hdw = emlxs_sli3_unmap_hdw;
3377*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_online = emlxs_sli3_online;
3378*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_offline = emlxs_sli3_offline;
3379*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_hba_reset = emlxs_sli3_hba_reset;
3380*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_issue_iocb_cmd = emlxs_sli3_issue_iocb_cmd;
3381*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_issue_mbox_cmd = emlxs_sli3_issue_mbox_cmd;
3382*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3383*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_prep_fct_iocb = emlxs_sli3_prep_fct_iocb;
3384*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3385*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_prep_fcp_iocb = emlxs_sli3_prep_fcp_iocb;
3386*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_prep_ip_iocb = emlxs_sli3_prep_ip_iocb;
3387*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_prep_els_iocb = emlxs_sli3_prep_els_iocb;
3388*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_prep_ct_iocb = emlxs_sli3_prep_ct_iocb;
3389*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_poll_intr = emlxs_sli3_poll_intr;
3390*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_intx_intr = emlxs_sli3_intx_intr;
3391*291a2b48SSukumar Swaminathan 	hba->emlxs_sli_api_msi_intr = emlxs_sli3_msi_intr;
3392fcf3ce44SJohn Forte 	return (1);
3393fcf3ce44SJohn Forte 
3394*291a2b48SSukumar Swaminathan }  /* emlxs_init_adapter_info()  */
3395fcf3ce44SJohn Forte 
3396fcf3ce44SJohn Forte 
3397*291a2b48SSukumar Swaminathan /* ARGSUSED */
3398*291a2b48SSukumar Swaminathan static void
3399*291a2b48SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
3400fcf3ce44SJohn Forte {
3401*291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3402*291a2b48SSukumar Swaminathan 	IOCB *iocb;
3403*291a2b48SSukumar Swaminathan 	uint32_t *w;
3404*291a2b48SSukumar Swaminathan 	int i, j;
3405fcf3ce44SJohn Forte 
3406*291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
3407fcf3ce44SJohn Forte 
3408*291a2b48SSukumar Swaminathan 	if (iocb->ulpStatus != 0) {
3409*291a2b48SSukumar Swaminathan 		return;
3410fcf3ce44SJohn Forte 	}
3411fcf3ce44SJohn Forte 
3412*291a2b48SSukumar Swaminathan 	switch (iocb->un.astat.EventCode) {
3413*291a2b48SSukumar Swaminathan 	case 0x0100:	/* Temp Warning */
3414*291a2b48SSukumar Swaminathan 
3415*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
3416*291a2b48SSukumar Swaminathan 		    "Adapter is very hot (%d �C). Take corrective action.",
3417*291a2b48SSukumar Swaminathan 		    iocb->ulpContext);
3418fcf3ce44SJohn Forte 
3419*291a2b48SSukumar Swaminathan 		emlxs_log_temp_event(port, 0x02, iocb->ulpContext);
3420fcf3ce44SJohn Forte 
3421*291a2b48SSukumar Swaminathan 		break;
3422fcf3ce44SJohn Forte 
3423fcf3ce44SJohn Forte 
3424*291a2b48SSukumar Swaminathan 	case 0x0101:	/* Temp Safe */
3425fcf3ce44SJohn Forte 
3426*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
3427*291a2b48SSukumar Swaminathan 		    "Adapter temperature now safe (%d �C).",
3428*291a2b48SSukumar Swaminathan 		    iocb->ulpContext);
3429fcf3ce44SJohn Forte 
3430*291a2b48SSukumar Swaminathan 		emlxs_log_temp_event(port, 0x03, iocb->ulpContext);
3431fcf3ce44SJohn Forte 
3432*291a2b48SSukumar Swaminathan 		break;
3433fcf3ce44SJohn Forte 
3434*291a2b48SSukumar Swaminathan 	default:
3435fcf3ce44SJohn Forte 
3436*291a2b48SSukumar Swaminathan 		w = (uint32_t *)iocb;
3437*291a2b48SSukumar Swaminathan 		for (i = 0, j = 0; i < 8; i++, j += 2) {
3438*291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
3439*291a2b48SSukumar Swaminathan 			    "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
3440*291a2b48SSukumar Swaminathan 			    w[j + 1]);
3441*291a2b48SSukumar Swaminathan 		}
3442fcf3ce44SJohn Forte 
3443*291a2b48SSukumar Swaminathan 		emlxs_log_async_event(port, iocb);
3444fcf3ce44SJohn Forte 	}
3445fcf3ce44SJohn Forte 
3446fcf3ce44SJohn Forte 	return;
3447fcf3ce44SJohn Forte 
3448*291a2b48SSukumar Swaminathan }  /* emlxs_handle_async_event() */
3449fcf3ce44SJohn Forte 
3450fcf3ce44SJohn Forte 
3451*291a2b48SSukumar Swaminathan extern void
3452*291a2b48SSukumar Swaminathan emlxs_reset_link_thread(void *arg)
3453fcf3ce44SJohn Forte {
3454*291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
3455*291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3456fcf3ce44SJohn Forte 
3457*291a2b48SSukumar Swaminathan 	/* Attempt a link reset to recover */
3458*291a2b48SSukumar Swaminathan 	(void) emlxs_reset(port, FC_FCA_LINK_RESET);
3459fcf3ce44SJohn Forte 
3460*291a2b48SSukumar Swaminathan 	thread_exit();
3461fcf3ce44SJohn Forte 
3462*291a2b48SSukumar Swaminathan }  /* emlxs_reset_link_thread() */
3463fcf3ce44SJohn Forte 
3464fcf3ce44SJohn Forte 
3465fcf3ce44SJohn Forte extern void
3466fcf3ce44SJohn Forte emlxs_restart_thread(void *arg)
3467fcf3ce44SJohn Forte {
3468fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
3469fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3470fcf3ce44SJohn Forte 
3471fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
3472fcf3ce44SJohn Forte 
3473fcf3ce44SJohn Forte 	/* Attempt a full hardware reset to recover */
3474fcf3ce44SJohn Forte 	if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
3475fcf3ce44SJohn Forte 		emlxs_ffstate_change(hba, FC_ERROR);
3476fcf3ce44SJohn Forte 
3477*291a2b48SSukumar Swaminathan 		thread_create(NULL, 0, emlxs_shutdown_thread, (char *)hba, 0,
3478*291a2b48SSukumar Swaminathan 		    &p0, TS_RUN, v.v_maxsyspri - 2);
3479fcf3ce44SJohn Forte 	}
3480fcf3ce44SJohn Forte 
3481*291a2b48SSukumar Swaminathan 	thread_exit();
3482*291a2b48SSukumar Swaminathan 
3483*291a2b48SSukumar Swaminathan }  /* emlxs_restart_thread() */
3484fcf3ce44SJohn Forte 
3485fcf3ce44SJohn Forte 
3486fcf3ce44SJohn Forte extern void
3487fcf3ce44SJohn Forte emlxs_shutdown_thread(void *arg)
3488fcf3ce44SJohn Forte {
3489fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
3490fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3491fcf3ce44SJohn Forte 
3492fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
3493fcf3ce44SJohn Forte 	if (hba->flag & FC_SHUTDOWN) {
3494fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
3495*291a2b48SSukumar Swaminathan 		thread_exit();
3496fcf3ce44SJohn Forte 	}
3497fcf3ce44SJohn Forte 	hba->flag |= FC_SHUTDOWN;
3498fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
3499fcf3ce44SJohn Forte 
3500*291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
3501*291a2b48SSukumar Swaminathan 	    "Shutting down...");
3502fcf3ce44SJohn Forte 
3503fcf3ce44SJohn Forte 	/* Take adapter offline and leave it there */
3504fcf3ce44SJohn Forte 	(void) emlxs_offline(hba);
3505fcf3ce44SJohn Forte 
3506fcf3ce44SJohn Forte 	/* Log a dump event */
3507fcf3ce44SJohn Forte 	emlxs_log_dump_event(port, NULL, 0);
3508fcf3ce44SJohn Forte 
3509fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
3510fcf3ce44SJohn Forte 
3511*291a2b48SSukumar Swaminathan 	thread_exit();
3512fcf3ce44SJohn Forte 
3513*291a2b48SSukumar Swaminathan }  /* emlxs_shutdown_thread() */
3514fcf3ce44SJohn Forte 
3515fcf3ce44SJohn Forte 
3516fcf3ce44SJohn Forte /* ARGSUSED */
3517fcf3ce44SJohn Forte extern void
3518fcf3ce44SJohn Forte emlxs_proc_ring(emlxs_hba_t *hba, RING *rp, void *arg2)
3519fcf3ce44SJohn Forte {
3520fcf3ce44SJohn Forte 	IOCBQ *iocbq;
3521fcf3ce44SJohn Forte 	IOCBQ *rsp_head;
3522fcf3ce44SJohn Forte 
3523fcf3ce44SJohn Forte 	/*
3524*291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3525*291a2b48SSukumar Swaminathan 	 * "emlxs_proc_ring: ringo=%d", rp->ringno);
3526fcf3ce44SJohn Forte 	 */
3527fcf3ce44SJohn Forte 
3528fcf3ce44SJohn Forte 	mutex_enter(&rp->rsp_lock);
3529fcf3ce44SJohn Forte 
3530fcf3ce44SJohn Forte 	while ((rsp_head = rp->rsp_head) != NULL) {
3531fcf3ce44SJohn Forte 		rp->rsp_head = NULL;
3532fcf3ce44SJohn Forte 		rp->rsp_tail = NULL;
3533fcf3ce44SJohn Forte 
3534fcf3ce44SJohn Forte 		mutex_exit(&rp->rsp_lock);
3535fcf3ce44SJohn Forte 
3536fcf3ce44SJohn Forte 		while ((iocbq = rsp_head) != NULL) {
3537fcf3ce44SJohn Forte 			rsp_head = (IOCBQ *) iocbq->next;
3538fcf3ce44SJohn Forte 
3539fcf3ce44SJohn Forte 			emlxs_proc_ring_event(hba, rp, iocbq);
3540fcf3ce44SJohn Forte 		}
3541fcf3ce44SJohn Forte 
3542fcf3ce44SJohn Forte 		mutex_enter(&rp->rsp_lock);
3543fcf3ce44SJohn Forte 	}
3544fcf3ce44SJohn Forte 
3545fcf3ce44SJohn Forte 	mutex_exit(&rp->rsp_lock);
3546fcf3ce44SJohn Forte 
3547*291a2b48SSukumar Swaminathan 	emlxs_sli_issue_iocb_cmd(hba, rp, 0);
3548fcf3ce44SJohn Forte 
3549fcf3ce44SJohn Forte 	return;
3550fcf3ce44SJohn Forte 
3551*291a2b48SSukumar Swaminathan }  /* emlxs_proc_ring() */
3552fcf3ce44SJohn Forte 
3553fcf3ce44SJohn Forte 
3554fcf3ce44SJohn Forte /*
3555*291a2b48SSukumar Swaminathan  * Called from SLI ring event routines to process a rsp ring IOCB.
3556fcf3ce44SJohn Forte  */
3557*291a2b48SSukumar Swaminathan void
3558fcf3ce44SJohn Forte emlxs_proc_ring_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
3559fcf3ce44SJohn Forte {
3560fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3561fcf3ce44SJohn Forte 	char buffer[MAX_MSG_DATA + 1];
3562fcf3ce44SJohn Forte 	IOCB *iocb;
3563fcf3ce44SJohn Forte 
3564fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
3565fcf3ce44SJohn Forte 
3566fcf3ce44SJohn Forte 	/* Check for IOCB local error */
3567fcf3ce44SJohn Forte 	if (iocb->ulpStatus == IOSTAT_LOCAL_REJECT) {
3568fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
3569*291a2b48SSukumar Swaminathan 		    "Local reject. ringno=%d iocb=%p cmd=%x "
3570*291a2b48SSukumar Swaminathan 		    "iotag=%x context=%x info=%x error=%x",
3571fcf3ce44SJohn Forte 		    rp->ringno, iocb, (uint8_t)iocb->ulpCommand,
3572fcf3ce44SJohn Forte 		    (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext,
3573fcf3ce44SJohn Forte 		    (uint8_t)iocb->ulpRsvdByte,
3574fcf3ce44SJohn Forte 		    (uint8_t)iocb->un.grsp.perr.statLocalError);
3575fcf3ce44SJohn Forte 	} else if (iocb->ulpStatus == IOSTAT_ILLEGAL_FRAME_RCVD) {
3576fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
3577*291a2b48SSukumar Swaminathan 		    "Illegal frame. ringno=%d iocb=%p cmd=%x "
3578*291a2b48SSukumar Swaminathan 		    "iotag=%x context=%x info=%x error=%x",
3579fcf3ce44SJohn Forte 		    rp->ringno, iocb, (uint8_t)iocb->ulpCommand,
3580fcf3ce44SJohn Forte 		    (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext,
3581fcf3ce44SJohn Forte 		    (uint8_t)iocb->ulpRsvdByte,
3582fcf3ce44SJohn Forte 		    (uint8_t)iocb->un.grsp.perr.statLocalError);
3583fcf3ce44SJohn Forte 	}
3584*291a2b48SSukumar Swaminathan 
3585fcf3ce44SJohn Forte 	switch (iocb->ulpCommand) {
3586fcf3ce44SJohn Forte 		/* RING 0 FCP commands */
3587fcf3ce44SJohn Forte 	case CMD_FCP_ICMND_CR:
3588fcf3ce44SJohn Forte 	case CMD_FCP_ICMND_CX:
3589fcf3ce44SJohn Forte 	case CMD_FCP_IREAD_CR:
3590fcf3ce44SJohn Forte 	case CMD_FCP_IREAD_CX:
3591fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE_CR:
3592fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE_CX:
3593fcf3ce44SJohn Forte 	case CMD_FCP_ICMND64_CR:
3594fcf3ce44SJohn Forte 	case CMD_FCP_ICMND64_CX:
3595fcf3ce44SJohn Forte 	case CMD_FCP_IREAD64_CR:
3596fcf3ce44SJohn Forte 	case CMD_FCP_IREAD64_CX:
3597fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE64_CR:
3598fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE64_CX:
3599*291a2b48SSukumar Swaminathan 		emlxs_handle_fcp_event(hba, rp, iocbq);
3600fcf3ce44SJohn Forte 		break;
3601fcf3ce44SJohn Forte 
3602fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
3603*291a2b48SSukumar Swaminathan 	case CMD_FCP_TSEND_CX:		/* FCP_TARGET IOCB command */
3604fcf3ce44SJohn Forte 	case CMD_FCP_TSEND64_CX:	/* FCP_TARGET IOCB command */
3605fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE_CX:	/* FCP_TARGET IOCB command */
3606fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE64_CX:	/* FCP_TARGET IOCB command */
3607*291a2b48SSukumar Swaminathan 	case CMD_FCP_TRSP_CX:		/* FCP_TARGET IOCB command */
3608*291a2b48SSukumar Swaminathan 	case CMD_FCP_TRSP64_CX:		/* FCP_TARGET IOCB command */
3609fcf3ce44SJohn Forte 		(void) emlxs_fct_handle_fcp_event(hba, rp, iocbq);
3610fcf3ce44SJohn Forte 		break;
3611*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3612fcf3ce44SJohn Forte 
3613fcf3ce44SJohn Forte 		/* RING 1 IP commands */
3614fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CN:
3615fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CX:
3616fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CN:
3617fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CX:
3618fcf3ce44SJohn Forte 		(void) emlxs_ip_handle_event(hba, rp, iocbq);
3619fcf3ce44SJohn Forte 		break;
3620fcf3ce44SJohn Forte 
3621fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CX:
3622fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CR:
3623fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CX:
3624fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CR:
3625fcf3ce44SJohn Forte 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
3626fcf3ce44SJohn Forte 		case FC_TYPE_IS8802_SNAP:
3627fcf3ce44SJohn Forte 			(void) emlxs_ip_handle_event(hba, rp, iocbq);
3628fcf3ce44SJohn Forte 			break;
3629fcf3ce44SJohn Forte 
3630fcf3ce44SJohn Forte 		case FC_TYPE_FC_SERVICES:
3631fcf3ce44SJohn Forte 			(void) emlxs_ct_handle_event(hba, rp, iocbq);
3632fcf3ce44SJohn Forte 			break;
3633fcf3ce44SJohn Forte 
3634fcf3ce44SJohn Forte 		default:
3635fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
3636fcf3ce44SJohn Forte 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
3637fcf3ce44SJohn Forte 			    iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type,
3638*291a2b48SSukumar Swaminathan 			    iocb->ulpStatus, iocb->ulpIoTag,
3639*291a2b48SSukumar Swaminathan 			    iocb->ulpContext);
3640fcf3ce44SJohn Forte 		}
3641fcf3ce44SJohn Forte 		break;
3642fcf3ce44SJohn Forte 
3643fcf3ce44SJohn Forte 	case CMD_RCV_SEQUENCE_CX:
3644fcf3ce44SJohn Forte 	case CMD_RCV_SEQUENCE64_CX:
3645fcf3ce44SJohn Forte 	case CMD_RCV_SEQ64_CX:
3646fcf3ce44SJohn Forte 	case CMD_RCV_ELS_REQ_CX:	/* Unsolicited ELS frame  */
3647fcf3ce44SJohn Forte 	case CMD_RCV_ELS_REQ64_CX:	/* Unsolicited ELS frame  */
3648*291a2b48SSukumar Swaminathan 	case CMD_RCV_ELS64_CX:		/* Unsolicited ELS frame  */
3649fcf3ce44SJohn Forte 		(void) emlxs_handle_rcv_seq(hba, rp, iocbq);
3650fcf3ce44SJohn Forte 		break;
3651fcf3ce44SJohn Forte 
3652fcf3ce44SJohn Forte 	case CMD_RCV_SEQ_LIST64_CX:
3653fcf3ce44SJohn Forte 		(void) emlxs_ip_handle_rcv_seq_list(hba, rp, iocbq);
3654fcf3ce44SJohn Forte 		break;
3655fcf3ce44SJohn Forte 
3656fcf3ce44SJohn Forte 	case CMD_CREATE_XRI_CR:
3657fcf3ce44SJohn Forte 	case CMD_CREATE_XRI_CX:
3658fcf3ce44SJohn Forte 		(void) emlxs_handle_create_xri(hba, rp, iocbq);
3659fcf3ce44SJohn Forte 		break;
3660fcf3ce44SJohn Forte 
3661fcf3ce44SJohn Forte 		/* RING 2 ELS commands */
3662fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST_CR:
3663fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST_CX:
3664fcf3ce44SJohn Forte 	case CMD_XMIT_ELS_RSP_CX:
3665fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST64_CR:
3666fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST64_CX:
3667fcf3ce44SJohn Forte 	case CMD_XMIT_ELS_RSP64_CX:
3668fcf3ce44SJohn Forte 		(void) emlxs_els_handle_event(hba, rp, iocbq);
3669fcf3ce44SJohn Forte 		break;
3670fcf3ce44SJohn Forte 
3671fcf3ce44SJohn Forte 		/* RING 3 CT commands */
3672fcf3ce44SJohn Forte 	case CMD_GEN_REQUEST64_CR:
3673fcf3ce44SJohn Forte 	case CMD_GEN_REQUEST64_CX:
3674fcf3ce44SJohn Forte 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
3675fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
3676fcf3ce44SJohn Forte 		case EMLXS_MENLO_TYPE:
3677fcf3ce44SJohn Forte 			(void) emlxs_menlo_handle_event(hba, rp, iocbq);
3678fcf3ce44SJohn Forte 			break;
3679*291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
3680fcf3ce44SJohn Forte 
3681fcf3ce44SJohn Forte 		case FC_TYPE_FC_SERVICES:
3682fcf3ce44SJohn Forte 			(void) emlxs_ct_handle_event(hba, rp, iocbq);
3683fcf3ce44SJohn Forte 			break;
3684fcf3ce44SJohn Forte 
3685fcf3ce44SJohn Forte 		default:
3686fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
3687fcf3ce44SJohn Forte 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
3688fcf3ce44SJohn Forte 			    iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type,
3689*291a2b48SSukumar Swaminathan 			    iocb->ulpStatus, iocb->ulpIoTag,
3690*291a2b48SSukumar Swaminathan 			    iocb->ulpContext);
3691fcf3ce44SJohn Forte 		}
3692fcf3ce44SJohn Forte 		break;
3693fcf3ce44SJohn Forte 
3694fcf3ce44SJohn Forte 	case CMD_ABORT_XRI_CN:	/* Abort fcp command */
3695fcf3ce44SJohn Forte 
3696fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
3697fcf3ce44SJohn Forte 		    "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
3698fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
3699*291a2b48SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus,
3700*291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
3701fcf3ce44SJohn Forte 
3702*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3703*291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
3704*291a2b48SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, rp, iocbq);
3705*291a2b48SSukumar Swaminathan 		}
3706*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3707fcf3ce44SJohn Forte 		break;
3708fcf3ce44SJohn Forte 
3709fcf3ce44SJohn Forte 	case CMD_ABORT_XRI_CX:	/* Abort command */
3710fcf3ce44SJohn Forte 
3711fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
3712*291a2b48SSukumar Swaminathan 		    "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
3713fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
3714*291a2b48SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus,
3715*291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm, iocbq->sbp);
3716fcf3ce44SJohn Forte 
3717*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3718*291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
3719*291a2b48SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, rp, iocbq);
3720*291a2b48SSukumar Swaminathan 		}
3721*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3722fcf3ce44SJohn Forte 		break;
3723fcf3ce44SJohn Forte 
3724fcf3ce44SJohn Forte 	case CMD_XRI_ABORTED_CX:	/* Handle ABORT condition */
3725fcf3ce44SJohn Forte 
3726fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
3727fcf3ce44SJohn Forte 		    "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x",
3728fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
3729*291a2b48SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus,
3730*291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
3731fcf3ce44SJohn Forte 
3732*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3733*291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
3734*291a2b48SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, rp, iocbq);
3735*291a2b48SSukumar Swaminathan 		}
3736*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3737fcf3ce44SJohn Forte 		break;
3738fcf3ce44SJohn Forte 
3739fcf3ce44SJohn Forte 	case CMD_CLOSE_XRI_CN:	/* Handle CLOSE condition */
3740fcf3ce44SJohn Forte 
3741fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
3742fcf3ce44SJohn Forte 		    "CLOSE_XRI_CR: rpi=%d iotag=%x status=%x parm=%x",
3743fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
3744*291a2b48SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus,
3745*291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
3746fcf3ce44SJohn Forte 
3747*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3748*291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
3749*291a2b48SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, rp, iocbq);
3750*291a2b48SSukumar Swaminathan 		}
3751*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3752fcf3ce44SJohn Forte 		break;
3753fcf3ce44SJohn Forte 
3754fcf3ce44SJohn Forte 	case CMD_CLOSE_XRI_CX:	/* Handle CLOSE condition */
3755fcf3ce44SJohn Forte 
3756fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
3757*291a2b48SSukumar Swaminathan 		    "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
3758fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
3759*291a2b48SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus,
3760*291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm, iocbq->sbp);
3761fcf3ce44SJohn Forte 
3762*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
3763*291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
3764*291a2b48SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, rp, iocbq);
3765*291a2b48SSukumar Swaminathan 		}
3766*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
3767fcf3ce44SJohn Forte 		break;
3768fcf3ce44SJohn Forte 
3769fcf3ce44SJohn Forte 	case CMD_ADAPTER_MSG:
3770fcf3ce44SJohn Forte 		/* Allows debug adapter firmware messages to print on host */
3771fcf3ce44SJohn Forte 		bzero(buffer, sizeof (buffer));
3772fcf3ce44SJohn Forte 		bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
3773fcf3ce44SJohn Forte 
3774fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
3775fcf3ce44SJohn Forte 
3776fcf3ce44SJohn Forte 		break;
3777fcf3ce44SJohn Forte 
3778fcf3ce44SJohn Forte 	case CMD_QUE_RING_LIST64_CN:
3779fcf3ce44SJohn Forte 	case CMD_QUE_RING_BUF64_CN:
3780fcf3ce44SJohn Forte 		break;
3781fcf3ce44SJohn Forte 
3782fcf3ce44SJohn Forte 	case CMD_ASYNC_STATUS:
3783*291a2b48SSukumar Swaminathan 		emlxs_handle_async_event(hba, rp, iocbq);
3784fcf3ce44SJohn Forte 		break;
3785fcf3ce44SJohn Forte 
3786fcf3ce44SJohn Forte 	default:
3787fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
3788*291a2b48SSukumar Swaminathan 		    "cmd=%x status=%x iotag=%x context=%x", iocb->ulpCommand,
3789*291a2b48SSukumar Swaminathan 		    iocb->ulpStatus, iocb->ulpIoTag, iocb->ulpContext);
3790fcf3ce44SJohn Forte 
3791fcf3ce44SJohn Forte 		break;
3792fcf3ce44SJohn Forte 	}	/* switch(entry->ulpCommand) */
3793fcf3ce44SJohn Forte 
3794fcf3ce44SJohn Forte 	return;
3795fcf3ce44SJohn Forte 
3796*291a2b48SSukumar Swaminathan }  /* emlxs_proc_ring_event() */
3797fcf3ce44SJohn Forte 
3798fcf3ce44SJohn Forte 
3799fcf3ce44SJohn Forte 
3800*291a2b48SSukumar Swaminathan extern char *
3801*291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state)
3802fcf3ce44SJohn Forte {
3803*291a2b48SSukumar Swaminathan 	static char buffer[32];
3804*291a2b48SSukumar Swaminathan 	uint32_t i;
3805*291a2b48SSukumar Swaminathan 	uint32_t count;
3806fcf3ce44SJohn Forte 
3807*291a2b48SSukumar Swaminathan 	count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
3808*291a2b48SSukumar Swaminathan 	for (i = 0; i < count; i++) {
3809*291a2b48SSukumar Swaminathan 		if (state == emlxs_ffstate_table[i].code) {
3810*291a2b48SSukumar Swaminathan 			return (emlxs_ffstate_table[i].string);
3811fcf3ce44SJohn Forte 		}
3812fcf3ce44SJohn Forte 	}
3813fcf3ce44SJohn Forte 
3814*291a2b48SSukumar Swaminathan 	(void) sprintf(buffer, "state=0x%x", state);
3815*291a2b48SSukumar Swaminathan 	return (buffer);
3816fcf3ce44SJohn Forte 
3817*291a2b48SSukumar Swaminathan }  /* emlxs_ffstate_xlate() */
3818fcf3ce44SJohn Forte 
3819fcf3ce44SJohn Forte 
3820fcf3ce44SJohn Forte extern char *
3821fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno)
3822fcf3ce44SJohn Forte {
3823fcf3ce44SJohn Forte 	static char buffer[32];
3824fcf3ce44SJohn Forte 	uint32_t i;
3825fcf3ce44SJohn Forte 	uint32_t count;
3826fcf3ce44SJohn Forte 
3827fcf3ce44SJohn Forte 	count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
3828fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
3829fcf3ce44SJohn Forte 		if (ringno == emlxs_ring_table[i].code) {
3830fcf3ce44SJohn Forte 			return (emlxs_ring_table[i].string);
3831fcf3ce44SJohn Forte 		}
3832fcf3ce44SJohn Forte 	}
3833fcf3ce44SJohn Forte 
3834fcf3ce44SJohn Forte 	(void) sprintf(buffer, "ring=0x%x", ringno);
3835fcf3ce44SJohn Forte 	return (buffer);
3836fcf3ce44SJohn Forte 
3837*291a2b48SSukumar Swaminathan }  /* emlxs_ring_xlate() */
3838fcf3ce44SJohn Forte 
3839fcf3ce44SJohn Forte 
3840fcf3ce44SJohn Forte 
3841fcf3ce44SJohn Forte extern void
3842fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
3843fcf3ce44SJohn Forte {
3844fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3845fcf3ce44SJohn Forte 	MAILBOX *mb;
3846fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
3847fcf3ce44SJohn Forte 	uint32_t value;
3848fcf3ce44SJohn Forte 
3849fcf3ce44SJohn Forte 	cfg = &CFG;
3850fcf3ce44SJohn Forte 
3851fcf3ce44SJohn Forte xlate:
3852fcf3ce44SJohn Forte 
3853fcf3ce44SJohn Forte 	switch (cfg[CFG_PCI_MAX_READ].current) {
3854fcf3ce44SJohn Forte 	case 512:
3855fcf3ce44SJohn Forte 		value = 0;
3856fcf3ce44SJohn Forte 		break;
3857fcf3ce44SJohn Forte 
3858fcf3ce44SJohn Forte 	case 1024:
3859fcf3ce44SJohn Forte 		value = 1;
3860fcf3ce44SJohn Forte 		break;
3861fcf3ce44SJohn Forte 
3862fcf3ce44SJohn Forte 	case 2048:
3863fcf3ce44SJohn Forte 		value = 2;
3864fcf3ce44SJohn Forte 		break;
3865fcf3ce44SJohn Forte 
3866fcf3ce44SJohn Forte 	case 4096:
3867fcf3ce44SJohn Forte 		value = 3;
3868fcf3ce44SJohn Forte 		break;
3869fcf3ce44SJohn Forte 
3870fcf3ce44SJohn Forte 	default:
3871fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3872fcf3ce44SJohn Forte 		    "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
3873fcf3ce44SJohn Forte 		    cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
3874fcf3ce44SJohn Forte 
3875fcf3ce44SJohn Forte 		cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
3876fcf3ce44SJohn Forte 		goto xlate;
3877fcf3ce44SJohn Forte 	}
3878fcf3ce44SJohn Forte 
3879*291a2b48SSukumar Swaminathan 	if ((mb = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) {
3880fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3881fcf3ce44SJohn Forte 		    "PCI_MAX_READ: Unable to allocate mailbox buffer.");
3882fcf3ce44SJohn Forte 		return;
3883fcf3ce44SJohn Forte 	}
3884fcf3ce44SJohn Forte 
3885*291a2b48SSukumar Swaminathan 	emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00100506, value);
3886*291a2b48SSukumar Swaminathan 
3887*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
3888fcf3ce44SJohn Forte 		if (verbose || (mb->mbxStatus != 0x12)) {
3889fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3890*291a2b48SSukumar Swaminathan 			    "PCI_MAX_READ: Unable to update. "
3891*291a2b48SSukumar Swaminathan 			    "status=%x value=%d (%d bytes)",
3892*291a2b48SSukumar Swaminathan 			    mb->mbxStatus, value,
3893fcf3ce44SJohn Forte 			    cfg[CFG_PCI_MAX_READ].current);
3894fcf3ce44SJohn Forte 		}
3895fcf3ce44SJohn Forte 	} else {
3896*291a2b48SSukumar Swaminathan 		if (verbose &&
3897*291a2b48SSukumar Swaminathan 		    (cfg[CFG_PCI_MAX_READ].current !=
3898fcf3ce44SJohn Forte 		    cfg[CFG_PCI_MAX_READ].def)) {
3899fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3900fcf3ce44SJohn Forte 			    "PCI_MAX_READ: Updated. %d bytes",
3901fcf3ce44SJohn Forte 			    cfg[CFG_PCI_MAX_READ].current);
3902fcf3ce44SJohn Forte 		}
3903fcf3ce44SJohn Forte 	}
3904fcf3ce44SJohn Forte 
3905fcf3ce44SJohn Forte 	(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
3906fcf3ce44SJohn Forte 
3907fcf3ce44SJohn Forte 	return;
3908fcf3ce44SJohn Forte 
3909*291a2b48SSukumar Swaminathan }  /* emlxs_pcix_mxr_update */
3910fcf3ce44SJohn Forte 
3911fcf3ce44SJohn Forte 
3912fcf3ce44SJohn Forte 
3913fcf3ce44SJohn Forte extern uint32_t
3914fcf3ce44SJohn Forte emlxs_get_key(emlxs_hba_t *hba, MAILBOX *mb)
3915fcf3ce44SJohn Forte {
3916fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3917fcf3ce44SJohn Forte 	uint32_t npname0, npname1;
3918fcf3ce44SJohn Forte 	uint32_t tmpkey, theKey;
3919fcf3ce44SJohn Forte 	uint16_t key850;
3920fcf3ce44SJohn Forte 	uint32_t t1, t2, t3, t4;
3921fcf3ce44SJohn Forte 	uint32_t ts;
3922fcf3ce44SJohn Forte 
3923fcf3ce44SJohn Forte #define	SEED 0x876EDC21
3924fcf3ce44SJohn Forte 
3925fcf3ce44SJohn Forte 	/* This key is only used currently for SBUS adapters */
3926fcf3ce44SJohn Forte 	if (hba->bus_type != SBUS_FC) {
3927fcf3ce44SJohn Forte 		return (0);
3928fcf3ce44SJohn Forte 	}
3929*291a2b48SSukumar Swaminathan 
3930fcf3ce44SJohn Forte 	tmpkey = mb->un.varWords[30];
3931fcf3ce44SJohn Forte 	emlxs_ffstate_change(hba, FC_INIT_NVPARAMS);
3932fcf3ce44SJohn Forte 
3933fcf3ce44SJohn Forte 	emlxs_mb_read_nv(hba, mb);
3934*291a2b48SSukumar Swaminathan 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
3935fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3936*291a2b48SSukumar Swaminathan 		    "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
3937*291a2b48SSukumar Swaminathan 		    mb->mbxStatus);
3938fcf3ce44SJohn Forte 
3939fcf3ce44SJohn Forte 		return (0);
3940fcf3ce44SJohn Forte 	}
3941fcf3ce44SJohn Forte 	npname0 = mb->un.varRDnvp.portname[0];
3942fcf3ce44SJohn Forte 	npname1 = mb->un.varRDnvp.portname[1];
3943fcf3ce44SJohn Forte 
3944fcf3ce44SJohn Forte 	key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
3945fcf3ce44SJohn Forte 	ts = (uint16_t)(npname1 + 1);
3946fcf3ce44SJohn Forte 	t1 = ts * key850;
3947fcf3ce44SJohn Forte 	ts = (uint16_t)((npname1 >> 16) + 1);
3948fcf3ce44SJohn Forte 	t2 = ts * key850;
3949fcf3ce44SJohn Forte 	ts = (uint16_t)(npname0 + 1);
3950fcf3ce44SJohn Forte 	t3 = ts * key850;
3951fcf3ce44SJohn Forte 	ts = (uint16_t)((npname0 >> 16) + 1);
3952fcf3ce44SJohn Forte 	t4 = ts * key850;
3953fcf3ce44SJohn Forte 	theKey = SEED + t1 + t2 + t3 + t4;
3954fcf3ce44SJohn Forte 
3955fcf3ce44SJohn Forte 	return (theKey);
3956fcf3ce44SJohn Forte 
3957*291a2b48SSukumar Swaminathan }  /* emlxs_get_key() */
3958*291a2b48SSukumar Swaminathan 
3959*291a2b48SSukumar Swaminathan 
3960*291a2b48SSukumar Swaminathan extern void
3961*291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba)
3962*291a2b48SSukumar Swaminathan {
3963*291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3964*291a2b48SSukumar Swaminathan 	uint32_t i;
3965*291a2b48SSukumar Swaminathan 
3966*291a2b48SSukumar Swaminathan 	/* Display firmware library one time */
3967*291a2b48SSukumar Swaminathan 	for (i = 0; i < EMLXS_FW_COUNT; i++) {
3968*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
3969*291a2b48SSukumar Swaminathan 		    emlxs_fw_table[i].label);
3970*291a2b48SSukumar Swaminathan 	}
3971*291a2b48SSukumar Swaminathan 
3972*291a2b48SSukumar Swaminathan 	return;
3973*291a2b48SSukumar Swaminathan 
3974*291a2b48SSukumar Swaminathan }  /* emlxs_fw_show() */
3975*291a2b48SSukumar Swaminathan 
3976*291a2b48SSukumar Swaminathan 
3977*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
3978*291a2b48SSukumar Swaminathan static void
3979*291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
3980*291a2b48SSukumar Swaminathan {
3981*291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
3982*291a2b48SSukumar Swaminathan 	int (*emlxs_fw_get)(emlxs_firmware_t *);
3983*291a2b48SSukumar Swaminathan 	int err;
3984*291a2b48SSukumar Swaminathan 
3985*291a2b48SSukumar Swaminathan 	/* Make sure image is unloaded and image buffer pointer is clear */
3986*291a2b48SSukumar Swaminathan 	emlxs_fw_unload(hba, fw);
3987*291a2b48SSukumar Swaminathan 
3988*291a2b48SSukumar Swaminathan 	err = 0;
3989*291a2b48SSukumar Swaminathan 	hba->fw_modhandle =
3990*291a2b48SSukumar Swaminathan 	    ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
3991*291a2b48SSukumar Swaminathan 	if (!hba->fw_modhandle) {
3992*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
3993*291a2b48SSukumar Swaminathan 		    "Unable to load firmware module. error=%d", err);
3994*291a2b48SSukumar Swaminathan 
3995*291a2b48SSukumar Swaminathan 		return;
3996*291a2b48SSukumar Swaminathan 	} else {
3997*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
3998*291a2b48SSukumar Swaminathan 		    "Firmware module loaded.");
3999*291a2b48SSukumar Swaminathan 	}
4000*291a2b48SSukumar Swaminathan 
4001*291a2b48SSukumar Swaminathan 	err = 0;
4002*291a2b48SSukumar Swaminathan 	emlxs_fw_get =
4003*291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err);
4004*291a2b48SSukumar Swaminathan 	if ((void *)emlxs_fw_get == NULL) {
4005*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
4006*291a2b48SSukumar Swaminathan 		    "emlxs_fw_get not present. error=%d", err);
4007*291a2b48SSukumar Swaminathan 
4008*291a2b48SSukumar Swaminathan 		emlxs_fw_unload(hba, fw);
4009*291a2b48SSukumar Swaminathan 		return;
4010*291a2b48SSukumar Swaminathan 	}
4011*291a2b48SSukumar Swaminathan 
4012*291a2b48SSukumar Swaminathan 	if (emlxs_fw_get(fw)) {
4013*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
4014*291a2b48SSukumar Swaminathan 		    "Invalid firmware image module found. %s", fw->label);
4015*291a2b48SSukumar Swaminathan 
4016*291a2b48SSukumar Swaminathan 		emlxs_fw_unload(hba, fw);
4017*291a2b48SSukumar Swaminathan 		return;
4018*291a2b48SSukumar Swaminathan 	}
4019*291a2b48SSukumar Swaminathan 
4020*291a2b48SSukumar Swaminathan 	return;
4021*291a2b48SSukumar Swaminathan 
4022*291a2b48SSukumar Swaminathan }  /* emlxs_fw_load() */
4023*291a2b48SSukumar Swaminathan 
4024*291a2b48SSukumar Swaminathan 
4025*291a2b48SSukumar Swaminathan static void
4026*291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
4027*291a2b48SSukumar Swaminathan {
4028*291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
4029*291a2b48SSukumar Swaminathan 
4030*291a2b48SSukumar Swaminathan 	/* Clear the firmware image */
4031*291a2b48SSukumar Swaminathan 	fw->image = NULL;
4032*291a2b48SSukumar Swaminathan 	fw->size = 0;
4033*291a2b48SSukumar Swaminathan 
4034*291a2b48SSukumar Swaminathan 	if (hba->fw_modhandle) {
4035*291a2b48SSukumar Swaminathan 		/* Close the module */
4036*291a2b48SSukumar Swaminathan 		(void) ddi_modclose(hba->fw_modhandle);
4037*291a2b48SSukumar Swaminathan 		hba->fw_modhandle = NULL;
4038*291a2b48SSukumar Swaminathan 
4039*291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
4040*291a2b48SSukumar Swaminathan 		    "Firmware module unloaded.");
4041*291a2b48SSukumar Swaminathan 	}
4042*291a2b48SSukumar Swaminathan 
4043*291a2b48SSukumar Swaminathan 	return;
4044*291a2b48SSukumar Swaminathan 
4045*291a2b48SSukumar Swaminathan }  /* emlxs_fw_unload() */
4046*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
4047