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 /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan 
28*82527734SSukumar Swaminathan #define	EMLXS_FW_TABLE_DEF
29*82527734SSukumar Swaminathan #define	EMLXS_MODEL_DEF
30fcf3ce44SJohn Forte 
31*82527734SSukumar Swaminathan #include <emlxs.h>
32fcf3ce44SJohn Forte 
33*82527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34*82527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_HBA_C);
35fcf3ce44SJohn Forte 
36*82527734SSukumar Swaminathan static uint32_t emlxs_decode_biu_rev(uint32_t rev);
37*82527734SSukumar Swaminathan static uint32_t emlxs_decode_endec_rev(uint32_t rev);
38*82527734SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
39*82527734SSukumar Swaminathan     IOCBQ *iocbq);
40291a2b48SSukumar Swaminathan 
41fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
42*82527734SSukumar Swaminathan uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
43*82527734SSukumar Swaminathan 	{EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
44*82527734SSukumar Swaminathan uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
45*82527734SSukumar Swaminathan 	{EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
46*82527734SSukumar Swaminathan 	EMLXS_MSI0_MASK8};
47291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
48fcf3ce44SJohn Forte 
49*82527734SSukumar Swaminathan emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
50*82527734SSukumar Swaminathan int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
51291a2b48SSukumar Swaminathan 
52*82527734SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = {
53*82527734SSukumar Swaminathan 	{FC_FCP_RING, "FCP Ring"},
54*82527734SSukumar Swaminathan 	{FC_IP_RING, "IP  Ring"},
55*82527734SSukumar Swaminathan 	{FC_ELS_RING, "ELS Ring"},
56*82527734SSukumar Swaminathan 	{FC_CT_RING, "CT  Ring"}
57291a2b48SSukumar Swaminathan 
58*82527734SSukumar Swaminathan }; /* emlxs_ring_table */
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte 
61*82527734SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = {
62*82527734SSukumar Swaminathan 	{0, "NULL"},
63*82527734SSukumar Swaminathan 	{FC_ERROR, "ERROR"},
64*82527734SSukumar Swaminathan 	{FC_KILLED, "KILLED"},
65*82527734SSukumar Swaminathan 	{FC_WARM_START, "WARM_START"},
66*82527734SSukumar Swaminathan 	{FC_INIT_START, "INIT_START"},
67*82527734SSukumar Swaminathan 	{FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
68*82527734SSukumar Swaminathan 	{FC_INIT_REV, "INIT_REV"},
69*82527734SSukumar Swaminathan 	{FC_INIT_CFGPORT, "INIT_CFGPORT"},
70*82527734SSukumar Swaminathan 	{FC_INIT_CFGRING, "INIT_CFGRING"},
71*82527734SSukumar Swaminathan 	{FC_INIT_INITLINK, "INIT_INITLINK"},
72*82527734SSukumar Swaminathan 	{FC_LINK_DOWN, "LINK_DOWN"},
73*82527734SSukumar Swaminathan 	{FC_LINK_UP, "LINK_UP"},
74*82527734SSukumar Swaminathan 	{FC_CLEAR_LA, "CLEAR_LA"},
75*82527734SSukumar Swaminathan 	{FC_READY, "READY"}
76fcf3ce44SJohn Forte 
77*82527734SSukumar Swaminathan }; /* emlxs_ffstate_table */
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
81fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
82fcf3ce44SJohn Forte int32_t
83fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
84fcf3ce44SJohn Forte {
85fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
86fcf3ce44SJohn Forte 	int32_t pass = 0;
87fcf3ce44SJohn Forte 	int32_t type = 0;
88fcf3ce44SJohn Forte 	char s_type[16];
89fcf3ce44SJohn Forte 	int32_t types;
90fcf3ce44SJohn Forte 	int32_t count;
91fcf3ce44SJohn Forte 	int32_t nintrs;
92fcf3ce44SJohn Forte 	int32_t mode;
93fcf3ce44SJohn Forte 	int32_t actual;
94fcf3ce44SJohn Forte 	int32_t new_actual;
95fcf3ce44SJohn Forte 	int32_t i;
96fcf3ce44SJohn Forte 	int32_t ret;
97fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable = NULL;
98fcf3ce44SJohn Forte 	ddi_intr_handle_t *new_htable = NULL;
99fcf3ce44SJohn Forte 	uint32_t *intr_pri = NULL;
100fcf3ce44SJohn Forte 	int32_t *intr_cap = NULL;
101fcf3ce44SJohn Forte 	int32_t hilevel_pri;
102fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
103fcf3ce44SJohn Forte 	char buf[64];
104fcf3ce44SJohn Forte 
105fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
106fcf3ce44SJohn Forte 		return (emlxs_intx_init(hba, max));
107fcf3ce44SJohn Forte 	}
108291a2b48SSukumar Swaminathan 
109fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_MSI_INITED) {
110fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
111fcf3ce44SJohn Forte 	}
112291a2b48SSukumar Swaminathan 
113fcf3ce44SJohn Forte 	/* Set max interrupt count if not specified */
114fcf3ce44SJohn Forte 	if (max == 0) {
115fcf3ce44SJohn Forte 		if ((cfg[CFG_MSI_MODE].current == 2) ||
116fcf3ce44SJohn Forte 		    (cfg[CFG_MSI_MODE].current == 3)) {
117fcf3ce44SJohn Forte 			max = EMLXS_MSI_MAX_INTRS;
118fcf3ce44SJohn Forte 		} else {
119fcf3ce44SJohn Forte 			max = 1;
120fcf3ce44SJohn Forte 		}
121fcf3ce44SJohn Forte 	}
122291a2b48SSukumar Swaminathan 
123fcf3ce44SJohn Forte 	/* Filter max interrupt count with adapter model specification */
124fcf3ce44SJohn Forte 	if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
125fcf3ce44SJohn Forte 		max = hba->model_info.intr_limit;
126fcf3ce44SJohn Forte 	}
127291a2b48SSukumar Swaminathan 
128fcf3ce44SJohn Forte 	/* Get the available interrupt types from the kernel */
129fcf3ce44SJohn Forte 	types = 0;
130fcf3ce44SJohn Forte 	ret = ddi_intr_get_supported_types(hba->dip, &types);
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 	if ((ret != DDI_SUCCESS)) {
133fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
134fcf3ce44SJohn Forte 		    "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 		/* Default to fixed type */
137fcf3ce44SJohn Forte 		types = DDI_INTR_TYPE_FIXED;
138fcf3ce44SJohn Forte 	}
139291a2b48SSukumar Swaminathan 
140fcf3ce44SJohn Forte 	/* Check if fixed interrupts are being forced */
141fcf3ce44SJohn Forte 	if (cfg[CFG_MSI_MODE].current == 0) {
142fcf3ce44SJohn Forte 		types &= DDI_INTR_TYPE_FIXED;
143fcf3ce44SJohn Forte 	}
144291a2b48SSukumar Swaminathan 
145fcf3ce44SJohn Forte 	/* Check if MSI interrupts are being forced */
146fcf3ce44SJohn Forte 	else if ((cfg[CFG_MSI_MODE].current == 1) ||
147fcf3ce44SJohn Forte 	    (cfg[CFG_MSI_MODE].current == 2)) {
148fcf3ce44SJohn Forte 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
149fcf3ce44SJohn Forte 	}
150291a2b48SSukumar Swaminathan 
151fcf3ce44SJohn Forte begin:
152fcf3ce44SJohn Forte 
153fcf3ce44SJohn Forte 	/* Set interrupt type and interrupt count */
154fcf3ce44SJohn Forte 	type = 0;
155fcf3ce44SJohn Forte 
156fcf3ce44SJohn Forte 	/* Check if MSIX is fully supported */
157fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_MSIX) &&
158fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
159fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
160fcf3ce44SJohn Forte 		nintrs = 0;
161fcf3ce44SJohn Forte 		ret =
162291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
163291a2b48SSukumar Swaminathan 		    &nintrs);
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS && nintrs) {
166fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_MSIX;
167fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_MSIX");
168fcf3ce44SJohn Forte 			goto initialize;
169fcf3ce44SJohn Forte 		}
170fcf3ce44SJohn Forte 	}
171291a2b48SSukumar Swaminathan 
172fcf3ce44SJohn Forte 	/* Check if MSI is fully supported */
173fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_MSI) &&
174fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
175fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
176fcf3ce44SJohn Forte 		nintrs = 0;
177291a2b48SSukumar Swaminathan 		ret =
178291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS && nintrs) {
181fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_MSI;
182fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_MSI");
183fcf3ce44SJohn Forte 			goto initialize;
184fcf3ce44SJohn Forte 		}
185fcf3ce44SJohn Forte 	}
186291a2b48SSukumar Swaminathan 
187fcf3ce44SJohn Forte 	/* Check if fixed interrupts are fully supported */
188fcf3ce44SJohn Forte 	if ((types & DDI_INTR_TYPE_FIXED) &&
189fcf3ce44SJohn Forte 	    (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
190fcf3ce44SJohn Forte 		/* Get the max interrupt count from the adapter */
191fcf3ce44SJohn Forte 		nintrs = 0;
192fcf3ce44SJohn Forte 		ret =
193291a2b48SSukumar Swaminathan 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
194291a2b48SSukumar Swaminathan 		    &nintrs);
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 		if (ret == DDI_SUCCESS) {
197fcf3ce44SJohn Forte 			type = DDI_INTR_TYPE_FIXED;
198fcf3ce44SJohn Forte 			(void) strcpy(s_type, "TYPE_FIXED");
199fcf3ce44SJohn Forte 			goto initialize;
200fcf3ce44SJohn Forte 		}
201fcf3ce44SJohn Forte 	}
202291a2b48SSukumar Swaminathan 
203fcf3ce44SJohn Forte 	goto init_failed;
204fcf3ce44SJohn Forte 
205fcf3ce44SJohn Forte 
206fcf3ce44SJohn Forte initialize:
207fcf3ce44SJohn Forte 
208fcf3ce44SJohn Forte 	pass++;
209fcf3ce44SJohn Forte 	mode = 0;
210fcf3ce44SJohn Forte 	actual = 0;
211fcf3ce44SJohn Forte 	htable = NULL;
212fcf3ce44SJohn Forte 	intr_pri = NULL;
213fcf3ce44SJohn Forte 	intr_cap = NULL;
214fcf3ce44SJohn Forte 	hilevel_pri = 0;
215fcf3ce44SJohn Forte 
216fcf3ce44SJohn Forte 	if (pass == 1) {
217fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
218291a2b48SSukumar Swaminathan 		    "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
219291a2b48SSukumar Swaminathan 		    cfg[CFG_MSI_MODE].current, types, nintrs);
220fcf3ce44SJohn Forte 	}
221291a2b48SSukumar Swaminathan 
222fcf3ce44SJohn Forte 	/* Validate interrupt count */
223fcf3ce44SJohn Forte 	count = min(nintrs, max);
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte 	if (count >= 8) {
226fcf3ce44SJohn Forte 		count = 8;
227fcf3ce44SJohn Forte 	} else if (count >= 4) {
228fcf3ce44SJohn Forte 		count = 4;
229fcf3ce44SJohn Forte 	} else if (count >= 2) {
230fcf3ce44SJohn Forte 		count = 2;
231fcf3ce44SJohn Forte 	} else {
232fcf3ce44SJohn Forte 		count = 1;
233fcf3ce44SJohn Forte 	}
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 	/* Allocate an array of interrupt handles */
236fcf3ce44SJohn Forte 	htable =
237291a2b48SSukumar Swaminathan 	    kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
238291a2b48SSukumar Swaminathan 	    KM_SLEEP);
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 	/* Allocate 'count' interrupts */
241291a2b48SSukumar Swaminathan 	ret =
242291a2b48SSukumar Swaminathan 	    ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
243fcf3ce44SJohn Forte 	    &actual, DDI_INTR_ALLOC_NORMAL);
244fcf3ce44SJohn Forte 
245fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
246*82527734SSukumar Swaminathan 	    "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
247fcf3ce44SJohn Forte 
248fcf3ce44SJohn Forte 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
249fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
250fcf3ce44SJohn Forte 		    "MSI: Unable to allocate interrupts. error=%d", ret);
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte 		goto init_failed;
253fcf3ce44SJohn Forte 	}
254291a2b48SSukumar Swaminathan 
255fcf3ce44SJohn Forte 	if (actual != count) {
256fcf3ce44SJohn Forte 		/* Validate actual count */
257fcf3ce44SJohn Forte 		if (actual >= 8) {
258fcf3ce44SJohn Forte 			new_actual = 8;
259fcf3ce44SJohn Forte 		} else if (actual >= 4) {
260fcf3ce44SJohn Forte 			new_actual = 4;
261fcf3ce44SJohn Forte 		} else if (actual >= 2) {
262fcf3ce44SJohn Forte 			new_actual = 2;
263fcf3ce44SJohn Forte 		} else {
264fcf3ce44SJohn Forte 			new_actual = 1;
265fcf3ce44SJohn Forte 		}
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 		if (new_actual < actual) {
268fcf3ce44SJohn Forte 			/* Free extra handles */
269fcf3ce44SJohn Forte 			for (i = new_actual; i < actual; i++) {
270fcf3ce44SJohn Forte 				(void) ddi_intr_free(htable[i]);
271fcf3ce44SJohn Forte 			}
272fcf3ce44SJohn Forte 
273fcf3ce44SJohn Forte 			actual = new_actual;
274fcf3ce44SJohn Forte 		}
275291a2b48SSukumar Swaminathan 
276fcf3ce44SJohn Forte 		/* Allocate a new array of interrupt handles */
277fcf3ce44SJohn Forte 		new_htable =
278fcf3ce44SJohn Forte 		    kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
279fcf3ce44SJohn Forte 		    KM_SLEEP);
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 		/* Copy old array to new array */
282fcf3ce44SJohn Forte 		bcopy((uint8_t *)htable, (uint8_t *)new_htable,
283fcf3ce44SJohn Forte 		    (actual * sizeof (ddi_intr_handle_t)));
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 		/* Free the old array */
286fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte 		htable = new_htable;
289fcf3ce44SJohn Forte 		count = actual;
290fcf3ce44SJohn Forte 	}
291291a2b48SSukumar Swaminathan 
292fcf3ce44SJohn Forte 	/* Allocate interrupt priority table */
293fcf3ce44SJohn Forte 	intr_pri =
294fcf3ce44SJohn Forte 	    (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
295fcf3ce44SJohn Forte 	    KM_SLEEP);
296fcf3ce44SJohn Forte 
297fcf3ce44SJohn Forte 	/* Allocate interrupt capability table */
298fcf3ce44SJohn Forte 	intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte 	/* Get minimum hilevel priority */
301fcf3ce44SJohn Forte 	hilevel_pri = ddi_intr_get_hilevel_pri();
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 	/* Fill the priority and capability tables */
304fcf3ce44SJohn Forte 	for (i = 0; i < count; ++i) {
305fcf3ce44SJohn Forte 		ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
308fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
309fcf3ce44SJohn Forte 			    "MSI: ddi_intr_get_pri(%d) failed. "
310291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
311291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 			/* Clean up the interrupts */
314fcf3ce44SJohn Forte 			goto init_failed;
315fcf3ce44SJohn Forte 		}
316291a2b48SSukumar Swaminathan 
317fcf3ce44SJohn Forte 		if (intr_pri[i] >= hilevel_pri) {
318fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
319fcf3ce44SJohn Forte 			    "MSI: Interrupt(%d) level too high. "
320fcf3ce44SJohn Forte 			    "pri=0x%x hilevel=0x%x",
321fcf3ce44SJohn Forte 			    i, intr_pri[i], hilevel_pri);
322fcf3ce44SJohn Forte 
323fcf3ce44SJohn Forte 			/* Clean up the interrupts */
324fcf3ce44SJohn Forte 			goto init_failed;
325fcf3ce44SJohn Forte 		}
326291a2b48SSukumar Swaminathan 
327fcf3ce44SJohn Forte 		ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
328fcf3ce44SJohn Forte 
329fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
330fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
331291a2b48SSukumar Swaminathan 			    "MSI: ddi_intr_get_cap(%d) failed. "
332291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
333291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
334fcf3ce44SJohn Forte 
335fcf3ce44SJohn Forte 			/* Clean up the interrupts */
336fcf3ce44SJohn Forte 			goto init_failed;
337fcf3ce44SJohn Forte 		}
338291a2b48SSukumar Swaminathan 
339fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
340291a2b48SSukumar Swaminathan 		    "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
341291a2b48SSukumar Swaminathan 		    intr_cap[i], intr_pri[i], hilevel_pri);
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 	}
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 	/* Set mode */
346fcf3ce44SJohn Forte 	switch (count) {
347fcf3ce44SJohn Forte 	case 8:
348fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE8;
349fcf3ce44SJohn Forte 		break;
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 	case 4:
352fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE4;
353fcf3ce44SJohn Forte 		break;
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 	case 2:
356fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE2;
357fcf3ce44SJohn Forte 		break;
358fcf3ce44SJohn Forte 
359fcf3ce44SJohn Forte 	default:
360fcf3ce44SJohn Forte 		mode = EMLXS_MSI_MODE1;
361fcf3ce44SJohn Forte 	}
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte 	/* Save the info */
364fcf3ce44SJohn Forte 	hba->intr_htable = htable;
365fcf3ce44SJohn Forte 	hba->intr_count = count;
366fcf3ce44SJohn Forte 	hba->intr_pri = intr_pri;
367fcf3ce44SJohn Forte 	hba->intr_cap = intr_cap;
368fcf3ce44SJohn Forte 	hba->intr_type = type;
369291a2b48SSukumar Swaminathan 	hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
370fcf3ce44SJohn Forte 	hba->intr_mask = emlxs_msi_mask[mode];
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 	hba->intr_cond = 0;
373*82527734SSukumar Swaminathan 
374*82527734SSukumar Swaminathan 	/* Adjust number of channels based on intr_count */
375*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
376*82527734SSukumar Swaminathan 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
377*82527734SSukumar Swaminathan 	}
378*82527734SSukumar Swaminathan 
379fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
380fcf3ce44SJohn Forte 		hba->intr_map[i] = emlxs_msi_map[mode][i];
381fcf3ce44SJohn Forte 		hba->intr_cond |= emlxs_msi_map[mode][i];
382fcf3ce44SJohn Forte 
383fcf3ce44SJohn Forte 		(void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
384fcf3ce44SJohn Forte 		    hba->ddiinst, i);
385fcf3ce44SJohn Forte 		mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
386291a2b48SSukumar Swaminathan 		    (void *)hba->intr_arg);
387fcf3ce44SJohn Forte 	}
388fcf3ce44SJohn Forte 
389fcf3ce44SJohn Forte 	/* Set flag to indicate support */
390fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_MSI_INITED;
391fcf3ce44SJohn Forte 
392fcf3ce44SJohn Forte 	/* Create the interrupt threads */
393*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
394*82527734SSukumar Swaminathan 		(void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
395fcf3ce44SJohn Forte 		    hba->ddiinst, i);
396*82527734SSukumar Swaminathan 		mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
397291a2b48SSukumar Swaminathan 		    (void *)hba->intr_arg);
398fcf3ce44SJohn Forte 
399*82527734SSukumar Swaminathan 		emlxs_thread_create(hba, &hba->chan[i].intr_thread);
400fcf3ce44SJohn Forte 	}
401fcf3ce44SJohn Forte 
402fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
403fcf3ce44SJohn Forte 
404fcf3ce44SJohn Forte init_failed:
405fcf3ce44SJohn Forte 
406fcf3ce44SJohn Forte 	if (intr_cap) {
407fcf3ce44SJohn Forte 		kmem_free(intr_cap, (count * sizeof (int32_t)));
408fcf3ce44SJohn Forte 	}
409291a2b48SSukumar Swaminathan 
410fcf3ce44SJohn Forte 	if (intr_pri) {
411fcf3ce44SJohn Forte 		kmem_free(intr_pri, (count * sizeof (int32_t)));
412fcf3ce44SJohn Forte 	}
413291a2b48SSukumar Swaminathan 
414fcf3ce44SJohn Forte 	if (htable) {
415fcf3ce44SJohn Forte 		/* Process the interrupt handlers */
416fcf3ce44SJohn Forte 		for (i = 0; i < actual; i++) {
417fcf3ce44SJohn Forte 			/* Free the handle[i] */
418fcf3ce44SJohn Forte 			(void) ddi_intr_free(htable[i]);
419fcf3ce44SJohn Forte 		}
420fcf3ce44SJohn Forte 
421fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
422fcf3ce44SJohn Forte 	}
423291a2b48SSukumar Swaminathan 
424fcf3ce44SJohn Forte 	/* Initialize */
425fcf3ce44SJohn Forte 	hba->intr_htable = NULL;
426fcf3ce44SJohn Forte 	hba->intr_count = 0;
427fcf3ce44SJohn Forte 	hba->intr_pri = NULL;
428fcf3ce44SJohn Forte 	hba->intr_cap = NULL;
429fcf3ce44SJohn Forte 	hba->intr_type = 0;
430fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
431fcf3ce44SJohn Forte 	hba->intr_cond = 0;
432fcf3ce44SJohn Forte 	bzero(hba->intr_map, sizeof (hba->intr_map));
433fcf3ce44SJohn Forte 	bzero(hba->intr_lock, sizeof (hba->intr_lock));
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte 	if (type == DDI_INTR_TYPE_MSIX) {
436fcf3ce44SJohn Forte 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
437fcf3ce44SJohn Forte 		goto begin;
438fcf3ce44SJohn Forte 	} else if (type == DDI_INTR_TYPE_MSI) {
439fcf3ce44SJohn Forte 		types &= DDI_INTR_TYPE_FIXED;
440fcf3ce44SJohn Forte 		goto begin;
441fcf3ce44SJohn Forte 	}
442291a2b48SSukumar Swaminathan 
443fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
444fcf3ce44SJohn Forte 	    "MSI: Unable to initialize interrupts");
445fcf3ce44SJohn Forte 
446fcf3ce44SJohn Forte 	return (DDI_FAILURE);
447fcf3ce44SJohn Forte 
448fcf3ce44SJohn Forte 
449*82527734SSukumar Swaminathan } /* emlxs_msi_init() */
450fcf3ce44SJohn Forte 
451fcf3ce44SJohn Forte 
452fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
453fcf3ce44SJohn Forte int32_t
454fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba)
455fcf3ce44SJohn Forte {
456fcf3ce44SJohn Forte 	uint32_t count;
457fcf3ce44SJohn Forte 	int32_t i;
458fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable;
459fcf3ce44SJohn Forte 	uint32_t *intr_pri;
460fcf3ce44SJohn Forte 	int32_t *intr_cap;
461fcf3ce44SJohn Forte 	int32_t ret;
462fcf3ce44SJohn Forte 
463fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
464fcf3ce44SJohn Forte 		return (emlxs_intx_uninit(hba));
465fcf3ce44SJohn Forte 	}
466291a2b48SSukumar Swaminathan 
467fcf3ce44SJohn Forte 	/*
468291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
469291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_uninit called. flags=%x",
470291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
471fcf3ce44SJohn Forte 	 */
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 	/* Make sure interrupts have been removed first */
474fcf3ce44SJohn Forte 	if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
475fcf3ce44SJohn Forte 		ret = emlxs_msi_remove(hba);
476fcf3ce44SJohn Forte 
477fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
478fcf3ce44SJohn Forte 			return (ret);
479fcf3ce44SJohn Forte 		}
480fcf3ce44SJohn Forte 	}
481291a2b48SSukumar Swaminathan 
482fcf3ce44SJohn Forte 	/* Check if the interrupts are still initialized */
483fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
484fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
485fcf3ce44SJohn Forte 	}
486fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_MSI_INITED;
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 	/* Get handle table parameters */
489fcf3ce44SJohn Forte 	htable = hba->intr_htable;
490fcf3ce44SJohn Forte 	count = hba->intr_count;
491fcf3ce44SJohn Forte 	intr_pri = hba->intr_pri;
492fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 	/* Clean up */
495fcf3ce44SJohn Forte 	hba->intr_count = 0;
496fcf3ce44SJohn Forte 	hba->intr_htable = NULL;
497fcf3ce44SJohn Forte 	hba->intr_pri = NULL;
498fcf3ce44SJohn Forte 	hba->intr_cap = NULL;
499fcf3ce44SJohn Forte 	hba->intr_type = 0;
500fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
501fcf3ce44SJohn Forte 	hba->intr_cond = 0;
502fcf3ce44SJohn Forte 	bzero(hba->intr_map, sizeof (hba->intr_map));
503fcf3ce44SJohn Forte 
504fcf3ce44SJohn Forte 	if (intr_cap) {
505fcf3ce44SJohn Forte 		kmem_free(intr_cap, (count * sizeof (int32_t)));
506fcf3ce44SJohn Forte 	}
507291a2b48SSukumar Swaminathan 
508fcf3ce44SJohn Forte 	if (intr_pri) {
509fcf3ce44SJohn Forte 		kmem_free(intr_pri, (count * sizeof (int32_t)));
510fcf3ce44SJohn Forte 	}
511291a2b48SSukumar Swaminathan 
512fcf3ce44SJohn Forte 	if (htable) {
513fcf3ce44SJohn Forte 		/* Process the interrupt handlers */
514fcf3ce44SJohn Forte 		for (i = 0; i < count; ++i) {
515fcf3ce44SJohn Forte 			/* Free the handle[i] */
516291a2b48SSukumar Swaminathan 			ret = ddi_intr_free(htable[i]);
517fcf3ce44SJohn Forte 		}
518fcf3ce44SJohn Forte 
519fcf3ce44SJohn Forte 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
520fcf3ce44SJohn Forte 	}
521291a2b48SSukumar Swaminathan 
522fcf3ce44SJohn Forte 	/* Destroy the intr locks */
523fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
524fcf3ce44SJohn Forte 		mutex_destroy(&hba->intr_lock[i]);
525fcf3ce44SJohn Forte 	}
526fcf3ce44SJohn Forte 
527fcf3ce44SJohn Forte 	/* Destroy the interrupt threads */
528*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
529*82527734SSukumar Swaminathan 		emlxs_thread_destroy(&hba->chan[i].intr_thread);
530*82527734SSukumar Swaminathan 		mutex_destroy(&hba->chan[i].rsp_lock);
531fcf3ce44SJohn Forte 	}
532fcf3ce44SJohn Forte 
533fcf3ce44SJohn Forte 	/*
534291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
535291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_uninit done. flags=%x",
536291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
537fcf3ce44SJohn Forte 	 */
538fcf3ce44SJohn Forte 
539fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
540fcf3ce44SJohn Forte 
541*82527734SSukumar Swaminathan } /* emlxs_msi_uninit() */
542fcf3ce44SJohn Forte 
543fcf3ce44SJohn Forte 
544fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */
545fcf3ce44SJohn Forte int32_t
546fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba)
547fcf3ce44SJohn Forte {
548fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
549fcf3ce44SJohn Forte 	int32_t count;
550fcf3ce44SJohn Forte 	int32_t i;
551fcf3ce44SJohn Forte 	int32_t ret;
552fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable = NULL;
553fcf3ce44SJohn Forte 	int32_t *intr_cap = NULL;
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
556fcf3ce44SJohn Forte 		return (emlxs_intx_add(hba));
557fcf3ce44SJohn Forte 	}
558291a2b48SSukumar Swaminathan 
559fcf3ce44SJohn Forte 	/* Check if interrupts have already been added */
560fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
561fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
562fcf3ce44SJohn Forte 	}
563291a2b48SSukumar Swaminathan 
564fcf3ce44SJohn Forte 	/* Check if interrupts have been initialized */
565fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
566fcf3ce44SJohn Forte 		ret = emlxs_msi_init(hba, 0);
567fcf3ce44SJohn Forte 
568fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
569fcf3ce44SJohn Forte 			return (ret);
570fcf3ce44SJohn Forte 		}
571fcf3ce44SJohn Forte 	}
572291a2b48SSukumar Swaminathan 
573fcf3ce44SJohn Forte 	/* Get handle table parameters */
574fcf3ce44SJohn Forte 	htable = hba->intr_htable;
575fcf3ce44SJohn Forte 	count = hba->intr_count;
576fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
577fcf3ce44SJohn Forte 
578fcf3ce44SJohn Forte 	/* Add the interrupt handlers */
579fcf3ce44SJohn Forte 	for (i = 0; i < count; ++i) {
580fcf3ce44SJohn Forte 		/* add handler for handle[i] */
581291a2b48SSukumar Swaminathan 		ret =
582*82527734SSukumar Swaminathan 		    ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
583291a2b48SSukumar Swaminathan 		    (char *)hba, (char *)((unsigned long)i));
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
586fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
587291a2b48SSukumar Swaminathan 			    "MSI: ddi_intr_add_handler(%d) failed. "
588291a2b48SSukumar Swaminathan 			    "handle=%p ret=%d",
589291a2b48SSukumar Swaminathan 			    i, &htable[i], ret);
590fcf3ce44SJohn Forte 
591fcf3ce44SJohn Forte 			/* Process the remaining interrupt handlers */
592fcf3ce44SJohn Forte 			while (i) {
593fcf3ce44SJohn Forte 				/* Decrement i */
594fcf3ce44SJohn Forte 				i--;
595fcf3ce44SJohn Forte 
596fcf3ce44SJohn Forte 				/* Remove the handler */
597fcf3ce44SJohn Forte 				ret = ddi_intr_remove_handler(htable[i]);
598fcf3ce44SJohn Forte 
599fcf3ce44SJohn Forte 			}
600fcf3ce44SJohn Forte 
601fcf3ce44SJohn Forte 			return (DDI_FAILURE);
602fcf3ce44SJohn Forte 		}
603fcf3ce44SJohn Forte 	}
604fcf3ce44SJohn Forte 
605fcf3ce44SJohn Forte 	/* Enable the interrupts */
606fcf3ce44SJohn Forte 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
607fcf3ce44SJohn Forte 		ret = ddi_intr_block_enable(htable, count);
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
610fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
611fcf3ce44SJohn Forte 			    "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
612fcf3ce44SJohn Forte 			    count, ret);
613fcf3ce44SJohn Forte 
614fcf3ce44SJohn Forte 			for (i = 0; i < count; ++i) {
615fcf3ce44SJohn Forte 				ret = ddi_intr_enable(htable[i]);
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 				if (ret != DDI_SUCCESS) {
618fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
619fcf3ce44SJohn Forte 					    &emlxs_init_debug_msg,
620fcf3ce44SJohn Forte 					    "MSI: ddi_intr_enable(%d) failed. "
621291a2b48SSukumar Swaminathan 					    "ret=%d",
622291a2b48SSukumar Swaminathan 					    i, ret);
623fcf3ce44SJohn Forte 				}
624fcf3ce44SJohn Forte 			}
625fcf3ce44SJohn Forte 		}
626fcf3ce44SJohn Forte 	} else {
627fcf3ce44SJohn Forte 		for (i = 0; i < count; ++i) {
628fcf3ce44SJohn Forte 			ret = ddi_intr_enable(htable[i]);
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 			if (ret != DDI_SUCCESS) {
631291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
632291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
633fcf3ce44SJohn Forte 				    "MSI: ddi_intr_enable(%d) failed. ret=%d",
634fcf3ce44SJohn Forte 				    i, ret);
635fcf3ce44SJohn Forte 			}
636fcf3ce44SJohn Forte 		}
637fcf3ce44SJohn Forte 	}
638fcf3ce44SJohn Forte 
639fcf3ce44SJohn Forte 
640fcf3ce44SJohn Forte 	/* Set flag to indicate support */
641fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_MSI_ADDED;
642fcf3ce44SJohn Forte 
643fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
644fcf3ce44SJohn Forte 
645*82527734SSukumar Swaminathan } /* emlxs_msi_add() */
646fcf3ce44SJohn Forte 
647fcf3ce44SJohn Forte 
648fcf3ce44SJohn Forte 
649fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
650fcf3ce44SJohn Forte int32_t
651fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba)
652fcf3ce44SJohn Forte {
653fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
654fcf3ce44SJohn Forte 	uint32_t count;
655fcf3ce44SJohn Forte 	int32_t i;
656fcf3ce44SJohn Forte 	ddi_intr_handle_t *htable;
657fcf3ce44SJohn Forte 	int32_t *intr_cap;
658fcf3ce44SJohn Forte 	int32_t ret;
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
661fcf3ce44SJohn Forte 		return (emlxs_intx_remove(hba));
662fcf3ce44SJohn Forte 	}
663291a2b48SSukumar Swaminathan 
664fcf3ce44SJohn Forte 	/*
665291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
666291a2b48SSukumar Swaminathan 	 *    "MSI: emlxs_msi_remove called. flags=%x",
667291a2b48SSukumar Swaminathan 	 *    hba->intr_flags);
668fcf3ce44SJohn Forte 	 */
669fcf3ce44SJohn Forte 
670fcf3ce44SJohn Forte 	/* Check if interrupts have already been removed */
671fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
672fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
673fcf3ce44SJohn Forte 	}
674fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_MSI_ADDED;
675fcf3ce44SJohn Forte 
676fcf3ce44SJohn Forte 	/* Disable all adapter interrupts */
677*82527734SSukumar Swaminathan 	EMLXS_SLI_DISABLE_INTR(hba, 0);
678fcf3ce44SJohn Forte 
679fcf3ce44SJohn Forte 	/* Get handle table parameters */
680fcf3ce44SJohn Forte 	htable = hba->intr_htable;
681fcf3ce44SJohn Forte 	count = hba->intr_count;
682fcf3ce44SJohn Forte 	intr_cap = hba->intr_cap;
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 	/* Disable the interrupts */
685fcf3ce44SJohn Forte 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
686fcf3ce44SJohn Forte 		ret = ddi_intr_block_disable(htable, count);
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
689fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
690fcf3ce44SJohn Forte 			    "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
691fcf3ce44SJohn Forte 			    count, ret);
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte 			for (i = 0; i < count; i++) {
694fcf3ce44SJohn Forte 				ret = ddi_intr_disable(htable[i]);
695fcf3ce44SJohn Forte 
696fcf3ce44SJohn Forte 				if (ret != DDI_SUCCESS) {
697fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
698fcf3ce44SJohn Forte 					    &emlxs_init_debug_msg,
699fcf3ce44SJohn Forte 					    "MSI: ddi_intr_disable(%d) failed. "
700291a2b48SSukumar Swaminathan 					    "ret=%d",
701291a2b48SSukumar Swaminathan 					    i, ret);
702fcf3ce44SJohn Forte 				}
703fcf3ce44SJohn Forte 			}
704fcf3ce44SJohn Forte 		}
705fcf3ce44SJohn Forte 	} else {
706fcf3ce44SJohn Forte 		for (i = 0; i < count; i++) {
707fcf3ce44SJohn Forte 			ret = ddi_intr_disable(htable[i]);
708fcf3ce44SJohn Forte 
709fcf3ce44SJohn Forte 			if (ret != DDI_SUCCESS) {
710291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
711291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
712fcf3ce44SJohn Forte 				    "MSI: ddi_intr_disable(%d) failed. ret=%d",
713fcf3ce44SJohn Forte 				    i, ret);
714fcf3ce44SJohn Forte 			}
715fcf3ce44SJohn Forte 		}
716fcf3ce44SJohn Forte 	}
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	/* Process the interrupt handlers */
719fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
720fcf3ce44SJohn Forte 		/* Remove the handler */
721fcf3ce44SJohn Forte 		ret = ddi_intr_remove_handler(htable[i]);
722fcf3ce44SJohn Forte 
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	}
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
727fcf3ce44SJohn Forte 
728*82527734SSukumar Swaminathan } /* emlxs_msi_remove() */
729fcf3ce44SJohn Forte 
730291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte 
733fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
734fcf3ce44SJohn Forte /* ARGSUSED */
735fcf3ce44SJohn Forte int32_t
736fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
737fcf3ce44SJohn Forte {
738fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
739*82527734SSukumar Swaminathan 	emlxs_config_t *cfg = &CFG;
740fcf3ce44SJohn Forte 	int32_t ret;
741fcf3ce44SJohn Forte 	uint32_t i;
742fcf3ce44SJohn Forte 	char buf[64];
743fcf3ce44SJohn Forte 
744fcf3ce44SJohn Forte 	/* Check if interrupts have already been initialized */
745fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_INTX_INITED) {
746fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
747fcf3ce44SJohn Forte 	}
748291a2b48SSukumar Swaminathan 
749fcf3ce44SJohn Forte 	/* Check if adapter is flagged for INTX support */
750fcf3ce44SJohn Forte 	if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
751fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
752fcf3ce44SJohn Forte 		    "INTX: %s does not support INTX.  flags=0x%x",
753fcf3ce44SJohn Forte 		    hba->model_info.model, hba->model_info.flags);
754fcf3ce44SJohn Forte 
755fcf3ce44SJohn Forte 		return (DDI_FAILURE);
756fcf3ce44SJohn Forte 	}
757291a2b48SSukumar Swaminathan 
758fcf3ce44SJohn Forte 	/*
759291a2b48SSukumar Swaminathan 	 * Interrupt number '0' is a high-level interrupt. This driver
760291a2b48SSukumar Swaminathan 	 * does not support having its interrupts mapped above scheduler
761291a2b48SSukumar Swaminathan 	 * priority; i.e., we always expect to be able to call general
762291a2b48SSukumar Swaminathan 	 * kernel routines that may invoke the scheduler.
763fcf3ce44SJohn Forte 	 */
764fcf3ce44SJohn Forte 	if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
765fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
766fcf3ce44SJohn Forte 		    "INTX: High-level interrupt not supported.");
767fcf3ce44SJohn Forte 
768fcf3ce44SJohn Forte 		return (DDI_FAILURE);
769fcf3ce44SJohn Forte 	}
770291a2b48SSukumar Swaminathan 
771fcf3ce44SJohn Forte 	/* Get an iblock cookie */
772291a2b48SSukumar Swaminathan 	ret =
773291a2b48SSukumar Swaminathan 	    ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
774fcf3ce44SJohn Forte 	    (ddi_iblock_cookie_t *)&hba->intr_arg);
775fcf3ce44SJohn Forte 	if (ret != DDI_SUCCESS) {
776fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
777fcf3ce44SJohn Forte 		    "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
778fcf3ce44SJohn Forte 
779fcf3ce44SJohn Forte 		return (ret);
780fcf3ce44SJohn Forte 	}
781291a2b48SSukumar Swaminathan 
782fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_INTX_INITED;
783fcf3ce44SJohn Forte 
784*82527734SSukumar Swaminathan 	hba->intr_count = 1;
785*82527734SSukumar Swaminathan 	/* Adjust number of channels based on intr_count */
786*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
787*82527734SSukumar Swaminathan 		hba->chan_count = cfg[CFG_NUM_WQ].current;
788*82527734SSukumar Swaminathan 	}
789*82527734SSukumar Swaminathan 
790fcf3ce44SJohn Forte 	/* Create the interrupt threads */
791*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
792*82527734SSukumar Swaminathan 		(void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
793fcf3ce44SJohn Forte 		    hba->ddiinst, i);
794*82527734SSukumar Swaminathan 		mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
795fcf3ce44SJohn Forte 		    (void *)hba->intr_arg);
796fcf3ce44SJohn Forte 
797*82527734SSukumar Swaminathan 		emlxs_thread_create(hba, &hba->chan[i].intr_thread);
798fcf3ce44SJohn Forte 	}
799fcf3ce44SJohn Forte 
800fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
801fcf3ce44SJohn Forte 
802*82527734SSukumar Swaminathan } /* emlxs_intx_init() */
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 
805fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
806fcf3ce44SJohn Forte int32_t
807fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba)
808fcf3ce44SJohn Forte {
809fcf3ce44SJohn Forte 	int32_t ret;
810fcf3ce44SJohn Forte 	uint32_t i;
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 	/* Make sure interrupts have been removed */
813fcf3ce44SJohn Forte 	if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
814fcf3ce44SJohn Forte 		ret = emlxs_intx_remove(hba);
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
817fcf3ce44SJohn Forte 			return (ret);
818fcf3ce44SJohn Forte 		}
819fcf3ce44SJohn Forte 	}
820291a2b48SSukumar Swaminathan 
821fcf3ce44SJohn Forte 	/* Check if the interrupts are still initialized */
822fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
823fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
824fcf3ce44SJohn Forte 	}
825fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_INTX_INITED;
826fcf3ce44SJohn Forte 
827fcf3ce44SJohn Forte 	hba->intr_arg = NULL;
828fcf3ce44SJohn Forte 
829fcf3ce44SJohn Forte 	/* Create the interrupt threads */
830*82527734SSukumar Swaminathan 	for (i = 0; i < hba->chan_count; i++) {
831*82527734SSukumar Swaminathan 		emlxs_thread_destroy(&hba->chan[i].intr_thread);
832*82527734SSukumar Swaminathan 		mutex_destroy(&hba->chan[i].rsp_lock);
833fcf3ce44SJohn Forte 	}
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
836fcf3ce44SJohn Forte 
837*82527734SSukumar Swaminathan } /* emlxs_intx_uninit() */
838fcf3ce44SJohn Forte 
839fcf3ce44SJohn Forte 
840291a2b48SSukumar Swaminathan /*
841291a2b48SSukumar Swaminathan  * This is the legacy method for adding interrupts in Solaris
842291a2b48SSukumar Swaminathan  * EMLXS_INTR_ADD
843291a2b48SSukumar Swaminathan  */
844fcf3ce44SJohn Forte int32_t
845fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba)
846fcf3ce44SJohn Forte {
847fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
848fcf3ce44SJohn Forte 	int32_t ret;
849fcf3ce44SJohn Forte 
850fcf3ce44SJohn Forte 	/* Check if interrupts have already been added */
851fcf3ce44SJohn Forte 	if (hba->intr_flags & EMLXS_INTX_ADDED) {
852fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
853fcf3ce44SJohn Forte 	}
854291a2b48SSukumar Swaminathan 
855fcf3ce44SJohn Forte 	/* Check if interrupts have been initialized */
856fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
857fcf3ce44SJohn Forte 		ret = emlxs_intx_init(hba, 0);
858fcf3ce44SJohn Forte 
859fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
860fcf3ce44SJohn Forte 			return (ret);
861fcf3ce44SJohn Forte 		}
862fcf3ce44SJohn Forte 	}
863291a2b48SSukumar Swaminathan 
864fcf3ce44SJohn Forte 	/* add intrrupt handler routine */
865291a2b48SSukumar Swaminathan 	ret = ddi_add_intr((void *)hba->dip,
866291a2b48SSukumar Swaminathan 	    (uint_t)EMLXS_INUMBER,
867291a2b48SSukumar Swaminathan 	    (ddi_iblock_cookie_t *)&hba->intr_arg,
868291a2b48SSukumar Swaminathan 	    (ddi_idevice_cookie_t *)0,
869*82527734SSukumar Swaminathan 	    (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
870fcf3ce44SJohn Forte 
871fcf3ce44SJohn Forte 	if (ret != DDI_SUCCESS) {
872fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
873fcf3ce44SJohn Forte 		    "INTX: ddi_add_intr failed. ret=%d", ret);
874fcf3ce44SJohn Forte 
875fcf3ce44SJohn Forte 		return (ret);
876fcf3ce44SJohn Forte 	}
877291a2b48SSukumar Swaminathan 
878fcf3ce44SJohn Forte 	hba->intr_flags |= EMLXS_INTX_ADDED;
879fcf3ce44SJohn Forte 
880fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
881fcf3ce44SJohn Forte 
882*82527734SSukumar Swaminathan } /* emlxs_intx_add() */
883fcf3ce44SJohn Forte 
884fcf3ce44SJohn Forte 
885fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
886fcf3ce44SJohn Forte int32_t
887fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba)
888fcf3ce44SJohn Forte {
889fcf3ce44SJohn Forte 	/* Check if interrupts have already been removed */
890fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
891fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
892fcf3ce44SJohn Forte 	}
893fcf3ce44SJohn Forte 	hba->intr_flags &= ~EMLXS_INTX_ADDED;
894fcf3ce44SJohn Forte 
895fcf3ce44SJohn Forte 	/* Diable all adapter interrupts */
896*82527734SSukumar Swaminathan 	EMLXS_SLI_DISABLE_INTR(hba, 0);
897fcf3ce44SJohn Forte 
898fcf3ce44SJohn Forte 	/* Remove the interrupt */
899fcf3ce44SJohn Forte 	(void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
900fcf3ce44SJohn Forte 	    hba->intr_arg);
901fcf3ce44SJohn Forte 
902fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
903fcf3ce44SJohn Forte 
904*82527734SSukumar Swaminathan } /* emlxs_intx_remove() */
905fcf3ce44SJohn Forte 
906fcf3ce44SJohn Forte 
907*82527734SSukumar Swaminathan extern void
908fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba)
909fcf3ce44SJohn Forte {
910fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
911fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
912fcf3ce44SJohn Forte 	char *cptr;
913fcf3ce44SJohn Forte 	uint32_t hi;
914fcf3ce44SJohn Forte 
915fcf3ce44SJohn Forte 	/*
916291a2b48SSukumar Swaminathan 	 * This routine modifies the link-speed config parameter entry
917291a2b48SSukumar Swaminathan 	 * based on adapter capabilities
918fcf3ce44SJohn Forte 	 */
919fcf3ce44SJohn Forte 	vpd = &VPD;
920fcf3ce44SJohn Forte 	cfg = &hba->config[CFG_LINK_SPEED];
921fcf3ce44SJohn Forte 
922fcf3ce44SJohn Forte 	cptr = cfg->help;
923fcf3ce44SJohn Forte 	(void) strcpy(cptr, "Select link speed. [0=Auto");
924fcf3ce44SJohn Forte 	cptr += 26;
925fcf3ce44SJohn Forte 	hi = 0;
926fcf3ce44SJohn Forte 
927fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
928fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 1=1Gb");
929fcf3ce44SJohn Forte 		cptr += 7;
930fcf3ce44SJohn Forte 		hi = 1;
931fcf3ce44SJohn Forte 	}
932291a2b48SSukumar Swaminathan 
933fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
934fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 2=2Gb");
935fcf3ce44SJohn Forte 		cptr += 7;
936fcf3ce44SJohn Forte 		hi = 2;
937fcf3ce44SJohn Forte 	}
938291a2b48SSukumar Swaminathan 
939fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
940fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 4=4Gb");
941fcf3ce44SJohn Forte 		cptr += 7;
942fcf3ce44SJohn Forte 		hi = 4;
943fcf3ce44SJohn Forte 	}
944291a2b48SSukumar Swaminathan 
945fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
946fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 8=8Gb");
947fcf3ce44SJohn Forte 		cptr += 7;
948fcf3ce44SJohn Forte 		hi = 8;
949fcf3ce44SJohn Forte 	}
950291a2b48SSukumar Swaminathan 
951fcf3ce44SJohn Forte 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
952fcf3ce44SJohn Forte 		(void) strcpy(cptr, ", 10=10Gb");
953fcf3ce44SJohn Forte 		cptr += 9;
954fcf3ce44SJohn Forte 		hi = 10;
955fcf3ce44SJohn Forte 	}
956291a2b48SSukumar Swaminathan 
957fcf3ce44SJohn Forte 	(void) strcpy(cptr, "]");
958fcf3ce44SJohn Forte 	cfg->hi = hi;
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 	/* Now revalidate the current parameter setting */
961fcf3ce44SJohn Forte 	cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
962fcf3ce44SJohn Forte 
963fcf3ce44SJohn Forte 	return;
964fcf3ce44SJohn Forte 
965*82527734SSukumar Swaminathan } /* emlxs_process_link_speed() */
966fcf3ce44SJohn Forte 
967fcf3ce44SJohn Forte 
968fcf3ce44SJohn Forte /*
969291a2b48SSukumar Swaminathan  * emlxs_parse_vpd()
970fcf3ce44SJohn Forte  *
971fcf3ce44SJohn Forte  * This routine will parse the VPD data
972fcf3ce44SJohn Forte  */
973fcf3ce44SJohn Forte extern int
974fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
975fcf3ce44SJohn Forte {
976fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
977fcf3ce44SJohn Forte 	char tag[3];
978fcf3ce44SJohn Forte 	uint8_t lenlo, lenhi;
979fcf3ce44SJohn Forte 	uint32_t n;
980fcf3ce44SJohn Forte 	uint16_t block_size;
981fcf3ce44SJohn Forte 	uint32_t block_index = 0;
982fcf3ce44SJohn Forte 	uint8_t sub_size;
983fcf3ce44SJohn Forte 	uint32_t sub_index;
984fcf3ce44SJohn Forte 	int32_t finished = 0;
985fcf3ce44SJohn Forte 	int32_t index = 0;
986fcf3ce44SJohn Forte 	char buffer[128];
987fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
988fcf3ce44SJohn Forte 
989fcf3ce44SJohn Forte 	vpd = &VPD;
990fcf3ce44SJohn Forte 
991fcf3ce44SJohn Forte 
992fcf3ce44SJohn Forte 	while (!finished && (block_index < size)) {
993fcf3ce44SJohn Forte 		/*
994291a2b48SSukumar Swaminathan 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
995291a2b48SSukumar Swaminathan 		 *    "block_index = %x", block_index);
996fcf3ce44SJohn Forte 		 */
997fcf3ce44SJohn Forte 
998fcf3ce44SJohn Forte 		switch (vpd_buf[block_index]) {
999fcf3ce44SJohn Forte 		case 0x82:
1000fcf3ce44SJohn Forte 			index = block_index;
1001fcf3ce44SJohn Forte 			index += 1;
1002fcf3ce44SJohn Forte 			lenlo = vpd_buf[index];
1003fcf3ce44SJohn Forte 			index += 1;
1004fcf3ce44SJohn Forte 			lenhi = vpd_buf[index];
1005fcf3ce44SJohn Forte 			index += 1;
1006fcf3ce44SJohn Forte 			block_index = index;
1007fcf3ce44SJohn Forte 
1008fcf3ce44SJohn Forte 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1009fcf3ce44SJohn Forte 			block_index += block_size;
1010fcf3ce44SJohn Forte 
1011fcf3ce44SJohn Forte 			/*
1012fcf3ce44SJohn Forte 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1013291a2b48SSukumar Swaminathan 			 *    "block_size = %x", block_size);
1014fcf3ce44SJohn Forte 			 */
1015fcf3ce44SJohn Forte 
1016fcf3ce44SJohn Forte 			n = sizeof (buffer);
1017fcf3ce44SJohn Forte 			bzero(buffer, n);
1018fcf3ce44SJohn Forte 			bcopy(&vpd_buf[index], buffer,
1019fcf3ce44SJohn Forte 			    (block_size < (n - 1)) ? block_size : (n - 1));
1020fcf3ce44SJohn Forte 
1021fcf3ce44SJohn Forte 			(void) strcpy(vpd->id, buffer);
1022291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
1023291a2b48SSukumar Swaminathan 			    vpd->id);
1024fcf3ce44SJohn Forte 
1025fcf3ce44SJohn Forte 			break;
1026fcf3ce44SJohn Forte 
1027fcf3ce44SJohn Forte 		case 0x90:
1028fcf3ce44SJohn Forte 			index = block_index;
1029fcf3ce44SJohn Forte 			index += 1;
1030fcf3ce44SJohn Forte 			lenlo = vpd_buf[index];
1031fcf3ce44SJohn Forte 			index += 1;
1032fcf3ce44SJohn Forte 			lenhi = vpd_buf[index];
1033fcf3ce44SJohn Forte 			index += 1;
1034fcf3ce44SJohn Forte 			block_index = index;
1035fcf3ce44SJohn Forte 			sub_index = index;
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1038fcf3ce44SJohn Forte 			block_index += block_size;
1039fcf3ce44SJohn Forte 
1040fcf3ce44SJohn Forte 			/*
1041fcf3ce44SJohn Forte 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1042291a2b48SSukumar Swaminathan 			 *    "block_size = %x", block_size);
1043fcf3ce44SJohn Forte 			 */
1044fcf3ce44SJohn Forte 
1045fcf3ce44SJohn Forte 			/* Scan for sub-blocks */
1046fcf3ce44SJohn Forte 			while ((sub_index < block_index) &&
1047fcf3ce44SJohn Forte 			    (sub_index < size)) {
1048fcf3ce44SJohn Forte 				/*
1049fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1050291a2b48SSukumar Swaminathan 				 *    "sub_index = %x", sub_index);
1051fcf3ce44SJohn Forte 				 */
1052fcf3ce44SJohn Forte 
1053fcf3ce44SJohn Forte 				index = sub_index;
1054fcf3ce44SJohn Forte 				tag[0] = vpd_buf[index++];
1055fcf3ce44SJohn Forte 				tag[1] = vpd_buf[index++];
1056fcf3ce44SJohn Forte 				tag[2] = 0;
1057fcf3ce44SJohn Forte 				sub_size = vpd_buf[index++];
1058fcf3ce44SJohn Forte 
1059fcf3ce44SJohn Forte 				/*
1060fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1061291a2b48SSukumar Swaminathan 				 *    "sub_size = %x", sub_size);
1062fcf3ce44SJohn Forte 				 */
1063fcf3ce44SJohn Forte 
1064fcf3ce44SJohn Forte 				sub_index = (index + sub_size);
1065fcf3ce44SJohn Forte 
1066fcf3ce44SJohn Forte 				n = sizeof (buffer);
1067fcf3ce44SJohn Forte 				bzero(buffer, n);
1068fcf3ce44SJohn Forte 				bcopy(&vpd_buf[index], buffer,
1069fcf3ce44SJohn Forte 				    (sub_size < (n - 1)) ? sub_size : (n - 1));
1070fcf3ce44SJohn Forte 
1071fcf3ce44SJohn Forte 				/*
1072fcf3ce44SJohn Forte 				 * Look for Engineering Change (EC)
1073fcf3ce44SJohn Forte 				 */
1074fcf3ce44SJohn Forte 				if (strcmp(tag, "EC") == 0) {
1075fcf3ce44SJohn Forte 					(void) strcpy(vpd->eng_change, buffer);
1076fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1077291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "EC: %s",
1078291a2b48SSukumar Swaminathan 					    vpd->eng_change);
1079fcf3ce44SJohn Forte 				}
1080fcf3ce44SJohn Forte 				/*
1081fcf3ce44SJohn Forte 				 * Look for Manufacturer (MN)
1082fcf3ce44SJohn Forte 				 */
1083fcf3ce44SJohn Forte 				else if (strcmp(tag, "MN") == 0) {
1084fcf3ce44SJohn Forte 					(void) strcpy(vpd->manufacturer,
1085fcf3ce44SJohn Forte 					    buffer);
1086fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1087291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "MN: %s",
1088291a2b48SSukumar Swaminathan 					    vpd->manufacturer);
1089fcf3ce44SJohn Forte 				}
1090fcf3ce44SJohn Forte 				/*
1091fcf3ce44SJohn Forte 				 * Look for Serial Number (SN)
1092fcf3ce44SJohn Forte 				 */
1093fcf3ce44SJohn Forte 				else if (strcmp(tag, "SN") == 0) {
1094fcf3ce44SJohn Forte 					(void) strcpy(vpd->serial_num, buffer);
1095fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1096291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "SN: %s",
1097291a2b48SSukumar Swaminathan 					    vpd->serial_num);
1098fcf3ce44SJohn Forte 
1099fcf3ce44SJohn Forte 					/* Validate the serial number */
1100291a2b48SSukumar Swaminathan 					if (strncmp(buffer, "FFFFFFFFFF", 10) ==
1101291a2b48SSukumar Swaminathan 					    0 ||
1102291a2b48SSukumar Swaminathan 					    strncmp(buffer, "0000000000", 10) ==
1103291a2b48SSukumar Swaminathan 					    0) {
1104fcf3ce44SJohn Forte 						vpd->serial_num[0] = 0;
1105fcf3ce44SJohn Forte 					}
1106fcf3ce44SJohn Forte 				}
1107fcf3ce44SJohn Forte 				/*
1108fcf3ce44SJohn Forte 				 * Look for Part Number (PN)
1109fcf3ce44SJohn Forte 				 */
1110fcf3ce44SJohn Forte 				else if (strcmp(tag, "PN") == 0) {
1111fcf3ce44SJohn Forte 					(void) strcpy(vpd->part_num, buffer);
1112fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1113291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "PN: %s",
1114291a2b48SSukumar Swaminathan 					    vpd->part_num);
1115fcf3ce44SJohn Forte 				}
1116fcf3ce44SJohn Forte 				/*
1117fcf3ce44SJohn Forte 				 * Look for (V0)
1118fcf3ce44SJohn Forte 				 */
1119fcf3ce44SJohn Forte 				else if (strcmp(tag, "V0") == 0) {
1120fcf3ce44SJohn Forte 					/* Not used */
1121fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1122291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "V0: %s", buffer);
1123fcf3ce44SJohn Forte 				}
1124fcf3ce44SJohn Forte 				/*
1125fcf3ce44SJohn Forte 				 * Look for model description (V1)
1126fcf3ce44SJohn Forte 				 */
1127fcf3ce44SJohn Forte 				else if (strcmp(tag, "V1") == 0) {
1128fcf3ce44SJohn Forte 					(void) strcpy(vpd->model_desc, buffer);
1129fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1130291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Desc: %s",
1131291a2b48SSukumar Swaminathan 					    vpd->model_desc);
1132fcf3ce44SJohn Forte 				}
1133fcf3ce44SJohn Forte 				/*
1134fcf3ce44SJohn Forte 				 * Look for model (V2)
1135fcf3ce44SJohn Forte 				 */
1136fcf3ce44SJohn Forte 				else if (strcmp(tag, "V2") == 0) {
1137fcf3ce44SJohn Forte 					(void) strcpy(vpd->model, buffer);
1138fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1139291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Model: %s",
1140291a2b48SSukumar Swaminathan 					    vpd->model);
1141fcf3ce44SJohn Forte 				}
1142fcf3ce44SJohn Forte 				/*
1143fcf3ce44SJohn Forte 				 * Look for program type (V3)
1144fcf3ce44SJohn Forte 				 */
1145fcf3ce44SJohn Forte 
1146fcf3ce44SJohn Forte 				else if (strcmp(tag, "V3") == 0) {
1147fcf3ce44SJohn Forte 					(void) strcpy(vpd->prog_types, buffer);
1148fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1149291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Prog Types: %s",
1150291a2b48SSukumar Swaminathan 					    vpd->prog_types);
1151fcf3ce44SJohn Forte 				}
1152fcf3ce44SJohn Forte 				/*
1153fcf3ce44SJohn Forte 				 * Look for port number (V4)
1154fcf3ce44SJohn Forte 				 */
1155fcf3ce44SJohn Forte 				else if (strcmp(tag, "V4") == 0) {
1156fcf3ce44SJohn Forte 					(void) strcpy(vpd->port_num, buffer);
1157fcf3ce44SJohn Forte 					vpd->port_index =
1158fcf3ce44SJohn Forte 					    emlxs_strtol(vpd->port_num, 10);
1159fcf3ce44SJohn Forte 
1160fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1161291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Port: %s",
1162291a2b48SSukumar Swaminathan 					    (vpd->port_num[0]) ? vpd->
1163291a2b48SSukumar Swaminathan 					    port_num : "not applicable");
1164fcf3ce44SJohn Forte 				}
1165fcf3ce44SJohn Forte 				/*
1166fcf3ce44SJohn Forte 				 * Look for checksum (RV)
1167fcf3ce44SJohn Forte 				 */
1168fcf3ce44SJohn Forte 				else if (strcmp(tag, "RV") == 0) {
1169fcf3ce44SJohn Forte 					/* Not used */
1170fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1171291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Checksum: 0x%x",
1172291a2b48SSukumar Swaminathan 					    buffer[0]);
1173291a2b48SSukumar Swaminathan 				}
1174291a2b48SSukumar Swaminathan 
1175291a2b48SSukumar Swaminathan 				else {
1176fcf3ce44SJohn Forte 					/* Generic */
1177fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
1178291a2b48SSukumar Swaminathan 					    &emlxs_vpd_msg, "Tag: %s: %s",
1179291a2b48SSukumar Swaminathan 					    tag, buffer);
1180fcf3ce44SJohn Forte 				}
1181fcf3ce44SJohn Forte 			}
1182fcf3ce44SJohn Forte 
1183fcf3ce44SJohn Forte 			break;
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 		case 0x78:
1186fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
1187fcf3ce44SJohn Forte 			finished = 1;
1188fcf3ce44SJohn Forte 			break;
1189fcf3ce44SJohn Forte 
1190fcf3ce44SJohn Forte 		default:
1191fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1192fcf3ce44SJohn Forte 			    "Unknown block: %x %x %x %x %x %x %x %x",
1193fcf3ce44SJohn Forte 			    vpd_buf[index], vpd_buf[index + 1],
1194fcf3ce44SJohn Forte 			    vpd_buf[index + 2], vpd_buf[index + 3],
1195fcf3ce44SJohn Forte 			    vpd_buf[index + 4], vpd_buf[index + 5],
1196fcf3ce44SJohn Forte 			    vpd_buf[index + 6], vpd_buf[index + 7]);
1197fcf3ce44SJohn Forte 			return (0);
1198fcf3ce44SJohn Forte 		}
1199fcf3ce44SJohn Forte 	}
1200fcf3ce44SJohn Forte 
1201fcf3ce44SJohn Forte 	return (1);
1202fcf3ce44SJohn Forte 
1203*82527734SSukumar Swaminathan } /* emlxs_parse_vpd */
1204*82527734SSukumar Swaminathan 
1205*82527734SSukumar Swaminathan 
1206*82527734SSukumar Swaminathan /*
1207*82527734SSukumar Swaminathan  * emlxs_parse_fcoe()
1208*82527734SSukumar Swaminathan  *
1209*82527734SSukumar Swaminathan  * This routine will parse the VPD data
1210*82527734SSukumar Swaminathan  */
1211*82527734SSukumar Swaminathan extern int
1212*82527734SSukumar Swaminathan emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
1213*82527734SSukumar Swaminathan {
1214*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1215*82527734SSukumar Swaminathan 	tlv_fcoe_t *fcoelist;
1216*82527734SSukumar Swaminathan 	tlv_fcfconnectlist_t *fcflist;
1217*82527734SSukumar Swaminathan 	int i;
1218*82527734SSukumar Swaminathan 
1219*82527734SSukumar Swaminathan 	/* Validate the config region 23 signature */
1220*82527734SSukumar Swaminathan 	if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
1221*82527734SSukumar Swaminathan 	    (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
1222*82527734SSukumar Swaminathan 		return (0);
1223*82527734SSukumar Swaminathan 	}
1224*82527734SSukumar Swaminathan 
1225*82527734SSukumar Swaminathan 	/* Search the config region 23, for FCOE Parameters record */
1226*82527734SSukumar Swaminathan 	i = 4;
1227*82527734SSukumar Swaminathan 	while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
1228*82527734SSukumar Swaminathan 		i += fcoep[i+1] * sizeof (uint32_t) + 2;
1229*82527734SSukumar Swaminathan 	}
1230*82527734SSukumar Swaminathan 
1231*82527734SSukumar Swaminathan 	if (*(fcoep+i) == 0xA0) {
1232*82527734SSukumar Swaminathan 		fcoelist = (tlv_fcoe_t *)(fcoep+i);
1233*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1234*82527734SSukumar Swaminathan 		    "Found FCOE Params (A0):%d  x%x",
1235*82527734SSukumar Swaminathan 		    fcoelist->length, fcoelist->fip_flags);
1236*82527734SSukumar Swaminathan 		bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
1237*82527734SSukumar Swaminathan 		    sizeof (tlv_fcoe_t));
1238*82527734SSukumar Swaminathan 	}
1239*82527734SSukumar Swaminathan 
1240*82527734SSukumar Swaminathan 
1241*82527734SSukumar Swaminathan 	/* Search the config region 23, for FCF record */
1242*82527734SSukumar Swaminathan 	i = 4;
1243*82527734SSukumar Swaminathan 	while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
1244*82527734SSukumar Swaminathan 		i += fcoep[i+1] * sizeof (uint32_t) + 2;
1245*82527734SSukumar Swaminathan 	}
1246*82527734SSukumar Swaminathan 
1247*82527734SSukumar Swaminathan 	if (*(fcoep+i) == 0xA1) {
1248*82527734SSukumar Swaminathan 		fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
1249*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1250*82527734SSukumar Swaminathan 		    "Found FCF ConnectList (A1):%d", fcflist->length);
1251*82527734SSukumar Swaminathan 		bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
1252*82527734SSukumar Swaminathan 		    sizeof (tlv_fcfconnectlist_t));
1253*82527734SSukumar Swaminathan 	}
1254*82527734SSukumar Swaminathan 
1255*82527734SSukumar Swaminathan 	return (1);
1256*82527734SSukumar Swaminathan 
1257*82527734SSukumar Swaminathan } /* emlxs_parse_fcoe */
1258fcf3ce44SJohn Forte 
1259fcf3ce44SJohn Forte 
1260fcf3ce44SJohn Forte 
1261fcf3ce44SJohn Forte static uint32_t
1262fcf3ce44SJohn Forte emlxs_decode_biu_rev(uint32_t rev)
1263fcf3ce44SJohn Forte {
1264fcf3ce44SJohn Forte 	return (rev & 0xf);
1265*82527734SSukumar Swaminathan } /* End emlxs_decode_biu_rev */
1266fcf3ce44SJohn Forte 
1267fcf3ce44SJohn Forte 
1268fcf3ce44SJohn Forte static uint32_t
1269fcf3ce44SJohn Forte emlxs_decode_endec_rev(uint32_t rev)
1270fcf3ce44SJohn Forte {
1271fcf3ce44SJohn Forte 	return ((rev >> 28) & 0xf);
1272*82527734SSukumar Swaminathan } /* End emlxs_decode_endec_rev */
1273fcf3ce44SJohn Forte 
1274fcf3ce44SJohn Forte 
1275fcf3ce44SJohn Forte extern void
1276fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1277fcf3ce44SJohn Forte {
1278fcf3ce44SJohn Forte 	if (vpd->rBit) {
1279fcf3ce44SJohn Forte 		switch (hba->sli_mode) {
1280291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI4_MODE:
1281fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli4FwName);
1282fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli4FwLabel);
1283fcf3ce44SJohn Forte 			break;
1284291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI3_MODE:
1285fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli3FwName);
1286fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli3FwLabel);
1287fcf3ce44SJohn Forte 			break;
1288291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI2_MODE:
1289fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli2FwName);
1290fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli2FwLabel);
1291fcf3ce44SJohn Forte 			break;
1292291a2b48SSukumar Swaminathan 		case EMLXS_HBA_SLI1_MODE:
1293fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, vpd->sli1FwName);
1294fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->sli1FwLabel);
1295fcf3ce44SJohn Forte 			break;
1296fcf3ce44SJohn Forte 		default:
1297fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_version, "unknown");
1298fcf3ce44SJohn Forte 			(void) strcpy(vpd->fw_label, vpd->fw_version);
1299fcf3ce44SJohn Forte 		}
1300fcf3ce44SJohn Forte 	} else {
1301fcf3ce44SJohn Forte 		emlxs_decode_version(vpd->smFwRev, vpd->fw_version);
1302fcf3ce44SJohn Forte 		(void) strcpy(vpd->fw_label, vpd->fw_version);
1303fcf3ce44SJohn Forte 	}
1304fcf3ce44SJohn Forte 
1305fcf3ce44SJohn Forte 	return;
1306fcf3ce44SJohn Forte 
1307*82527734SSukumar Swaminathan } /* emlxs_decode_firmware_rev() */
1308fcf3ce44SJohn Forte 
1309fcf3ce44SJohn Forte 
1310fcf3ce44SJohn Forte 
1311fcf3ce44SJohn Forte extern void
1312fcf3ce44SJohn Forte emlxs_decode_version(uint32_t version, char *buffer)
1313fcf3ce44SJohn Forte {
1314fcf3ce44SJohn Forte 	uint32_t b1, b2, b3, b4;
1315fcf3ce44SJohn Forte 	char c;
1316fcf3ce44SJohn Forte 
1317fcf3ce44SJohn Forte 	b1 = (version & 0x0000f000) >> 12;
1318fcf3ce44SJohn Forte 	b2 = (version & 0x00000f00) >> 8;
1319fcf3ce44SJohn Forte 	b3 = (version & 0x000000c0) >> 6;
1320fcf3ce44SJohn Forte 	b4 = (version & 0x00000030) >> 4;
1321fcf3ce44SJohn Forte 
1322fcf3ce44SJohn Forte 	if (b1 == 0 && b2 == 0) {
1323fcf3ce44SJohn Forte 		(void) sprintf(buffer, "none");
1324fcf3ce44SJohn Forte 		return;
1325fcf3ce44SJohn Forte 	}
1326291a2b48SSukumar Swaminathan 
1327fcf3ce44SJohn Forte 	c = 0;
1328fcf3ce44SJohn Forte 	switch (b4) {
1329fcf3ce44SJohn Forte 	case 0:
1330fcf3ce44SJohn Forte 		c = 'n';
1331fcf3ce44SJohn Forte 		break;
1332fcf3ce44SJohn Forte 	case 1:
1333fcf3ce44SJohn Forte 		c = 'a';
1334fcf3ce44SJohn Forte 		break;
1335fcf3ce44SJohn Forte 	case 2:
1336fcf3ce44SJohn Forte 		c = 'b';
1337fcf3ce44SJohn Forte 		break;
1338fcf3ce44SJohn Forte 	case 3:
1339fcf3ce44SJohn Forte 		if ((version & 0x0000000f)) {
1340fcf3ce44SJohn Forte 			c = 'x';
1341fcf3ce44SJohn Forte 		}
1342fcf3ce44SJohn Forte 		break;
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte 	}
1345fcf3ce44SJohn Forte 	b4 = (version & 0x0000000f);
1346fcf3ce44SJohn Forte 
1347fcf3ce44SJohn Forte 	if (c == 0) {
1348fcf3ce44SJohn Forte 		(void) sprintf(buffer, "%d.%d%d", b1, b2, b3);
1349fcf3ce44SJohn Forte 	} else {
1350fcf3ce44SJohn Forte 		(void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4);
1351fcf3ce44SJohn Forte 	}
1352fcf3ce44SJohn Forte 
1353fcf3ce44SJohn Forte 	return;
1354fcf3ce44SJohn Forte 
1355*82527734SSukumar Swaminathan } /* emlxs_decode_version() */
1356fcf3ce44SJohn Forte 
1357fcf3ce44SJohn Forte 
1358*82527734SSukumar Swaminathan extern void
1359*82527734SSukumar Swaminathan emlxs_decode_label(char *label, char *buffer, int bige)
1360fcf3ce44SJohn Forte {
1361fcf3ce44SJohn Forte 	uint32_t i;
1362fcf3ce44SJohn Forte 	char name[16];
1363fcf3ce44SJohn Forte 
1364*82527734SSukumar Swaminathan 	bcopy(label, name, sizeof (name));
1365*82527734SSukumar Swaminathan 	/* bige is TRUE if the data format is big endian */
1366fcf3ce44SJohn Forte 
1367*82527734SSukumar Swaminathan 	if (bige) {
1368*82527734SSukumar Swaminathan 		/* Data format big Endian */
1369*82527734SSukumar Swaminathan 		LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1370*82527734SSukumar Swaminathan 
1371*82527734SSukumar Swaminathan 		for (i = 0; i < sizeof (name); i++) {
1372*82527734SSukumar Swaminathan 			if (name[i] == 0x20) {
1373*82527734SSukumar Swaminathan 				name[i] = 0;
1374*82527734SSukumar Swaminathan 			}
1375*82527734SSukumar Swaminathan 		}
1376*82527734SSukumar Swaminathan 	} else {
1377*82527734SSukumar Swaminathan 		/* Data format little Endian */
1378*82527734SSukumar Swaminathan 		BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1379fcf3ce44SJohn Forte 
1380*82527734SSukumar Swaminathan 		for (i = 0; i < sizeof (name); i++) {
1381*82527734SSukumar Swaminathan 			if (name[i] == 0x20) {
1382*82527734SSukumar Swaminathan 				name[i] = 0;
1383*82527734SSukumar Swaminathan 			}
1384fcf3ce44SJohn Forte 		}
1385fcf3ce44SJohn Forte 	}
1386fcf3ce44SJohn Forte 
1387fcf3ce44SJohn Forte 	(void) strcpy(buffer, name);
1388fcf3ce44SJohn Forte 
1389fcf3ce44SJohn Forte 	return;
1390fcf3ce44SJohn Forte 
1391*82527734SSukumar Swaminathan } /* emlxs_decode_label() */
1392fcf3ce44SJohn Forte 
1393fcf3ce44SJohn Forte 
1394fcf3ce44SJohn Forte extern uint32_t
1395fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base)
1396fcf3ce44SJohn Forte {
1397fcf3ce44SJohn Forte 	uint32_t value = 0;
1398fcf3ce44SJohn Forte 	char *ptr;
1399fcf3ce44SJohn Forte 	uint32_t factor = 1;
1400fcf3ce44SJohn Forte 	uint32_t digits;
1401fcf3ce44SJohn Forte 
1402fcf3ce44SJohn Forte 	if (*str == 0) {
1403fcf3ce44SJohn Forte 		return (0);
1404fcf3ce44SJohn Forte 	}
1405291a2b48SSukumar Swaminathan 
1406fcf3ce44SJohn Forte 	if (base != 10 && base != 16) {
1407fcf3ce44SJohn Forte 		return (0);
1408fcf3ce44SJohn Forte 	}
1409291a2b48SSukumar Swaminathan 
1410fcf3ce44SJohn Forte 	/* Get max digits of value */
1411fcf3ce44SJohn Forte 	digits = (base == 10) ? 9 : 8;
1412fcf3ce44SJohn Forte 
1413fcf3ce44SJohn Forte 	/* Position pointer to end of string */
1414fcf3ce44SJohn Forte 	ptr = str + strlen(str);
1415fcf3ce44SJohn Forte 
1416fcf3ce44SJohn Forte 	/* Process string backwards */
1417fcf3ce44SJohn Forte 	while ((ptr-- > str) && digits) {
1418fcf3ce44SJohn Forte 		/* check for base 10 numbers */
1419fcf3ce44SJohn Forte 		if (*ptr >= '0' && *ptr <= '9') {
1420fcf3ce44SJohn Forte 			value += ((uint32_t)(*ptr - '0')) * factor;
1421fcf3ce44SJohn Forte 			factor *= base;
1422fcf3ce44SJohn Forte 			digits--;
1423fcf3ce44SJohn Forte 		} else if (base == 16) {
1424fcf3ce44SJohn Forte 			/* Check for base 16 numbers */
1425fcf3ce44SJohn Forte 			if (*ptr >= 'a' && *ptr <= 'f') {
1426291a2b48SSukumar Swaminathan 				value +=
1427291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
1428fcf3ce44SJohn Forte 				factor *= base;
1429fcf3ce44SJohn Forte 				digits--;
1430fcf3ce44SJohn Forte 			} else if (*ptr >= 'A' && *ptr <= 'F') {
1431291a2b48SSukumar Swaminathan 				value +=
1432291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
1433fcf3ce44SJohn Forte 				factor *= base;
1434fcf3ce44SJohn Forte 				digits--;
1435fcf3ce44SJohn Forte 			} else if (factor > 1) {
1436fcf3ce44SJohn Forte 				break;
1437fcf3ce44SJohn Forte 			}
1438fcf3ce44SJohn Forte 		} else if (factor > 1) {
1439fcf3ce44SJohn Forte 			break;
1440fcf3ce44SJohn Forte 		}
1441fcf3ce44SJohn Forte 	}
1442fcf3ce44SJohn Forte 
1443fcf3ce44SJohn Forte 	return (value);
1444fcf3ce44SJohn Forte 
1445*82527734SSukumar Swaminathan } /* emlxs_strtol() */
1446fcf3ce44SJohn Forte 
1447fcf3ce44SJohn Forte 
1448fcf3ce44SJohn Forte extern uint64_t
1449fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base)
1450fcf3ce44SJohn Forte {
1451fcf3ce44SJohn Forte 	uint64_t value = 0;
1452fcf3ce44SJohn Forte 	char *ptr;
1453fcf3ce44SJohn Forte 	uint32_t factor = 1;
1454fcf3ce44SJohn Forte 	uint32_t digits;
1455fcf3ce44SJohn Forte 
1456fcf3ce44SJohn Forte 	if (*str == 0) {
1457fcf3ce44SJohn Forte 		return (0);
1458fcf3ce44SJohn Forte 	}
1459291a2b48SSukumar Swaminathan 
1460fcf3ce44SJohn Forte 	if (base != 10 && base != 16) {
1461fcf3ce44SJohn Forte 		return (0);
1462fcf3ce44SJohn Forte 	}
1463291a2b48SSukumar Swaminathan 
1464fcf3ce44SJohn Forte 	/* Get max digits of value */
1465fcf3ce44SJohn Forte 	digits = (base == 10) ? 19 : 16;
1466fcf3ce44SJohn Forte 
1467fcf3ce44SJohn Forte 	/* Position pointer to end of string */
1468fcf3ce44SJohn Forte 	ptr = str + strlen(str);
1469fcf3ce44SJohn Forte 
1470fcf3ce44SJohn Forte 	/* Process string backwards */
1471fcf3ce44SJohn Forte 	while ((ptr-- > str) && digits) {
1472fcf3ce44SJohn Forte 		/* check for base 10 numbers */
1473fcf3ce44SJohn Forte 		if (*ptr >= '0' && *ptr <= '9') {
1474fcf3ce44SJohn Forte 			value += ((uint32_t)(*ptr - '0')) * factor;
1475fcf3ce44SJohn Forte 			factor *= base;
1476fcf3ce44SJohn Forte 			digits--;
1477fcf3ce44SJohn Forte 		} else if (base == 16) {
1478fcf3ce44SJohn Forte 			/* Check for base 16 numbers */
1479fcf3ce44SJohn Forte 			if (*ptr >= 'a' && *ptr <= 'f') {
1480291a2b48SSukumar Swaminathan 				value +=
1481291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
1482fcf3ce44SJohn Forte 				factor *= base;
1483fcf3ce44SJohn Forte 				digits--;
1484fcf3ce44SJohn Forte 			} else if (*ptr >= 'A' && *ptr <= 'F') {
1485291a2b48SSukumar Swaminathan 				value +=
1486291a2b48SSukumar Swaminathan 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
1487fcf3ce44SJohn Forte 				factor *= base;
1488fcf3ce44SJohn Forte 				digits--;
1489fcf3ce44SJohn Forte 			} else if (factor > 1) {
1490fcf3ce44SJohn Forte 				break;
1491fcf3ce44SJohn Forte 			}
1492fcf3ce44SJohn Forte 		} else if (factor > 1) {
1493fcf3ce44SJohn Forte 			break;
1494fcf3ce44SJohn Forte 		}
1495fcf3ce44SJohn Forte 	}
1496fcf3ce44SJohn Forte 
1497fcf3ce44SJohn Forte 	return (value);
1498fcf3ce44SJohn Forte 
1499*82527734SSukumar Swaminathan } /* emlxs_strtoll() */
1500fcf3ce44SJohn Forte 
1501*82527734SSukumar Swaminathan extern void
1502fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
1503fcf3ce44SJohn Forte {
1504fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1505fcf3ce44SJohn Forte 	uint32_t i;
1506fcf3ce44SJohn Forte 	char *ptr;
1507fcf3ce44SJohn Forte 	emlxs_model_t *model;
1508fcf3ce44SJohn Forte 	char types_buffer[256];
1509fcf3ce44SJohn Forte 	char *types;
1510fcf3ce44SJohn Forte 
1511fcf3ce44SJohn Forte 	bcopy(prog_types, types_buffer, 256);
1512fcf3ce44SJohn Forte 	types = types_buffer;
1513fcf3ce44SJohn Forte 
1514fcf3ce44SJohn Forte 	model = &hba->model_info;
1515fcf3ce44SJohn Forte 
1516fcf3ce44SJohn Forte 	while (*types) {
1517fcf3ce44SJohn Forte 		if (strncmp(types, "T2:", 3) == 0) {
1518fcf3ce44SJohn Forte 			bzero(model->pt_2, sizeof (model->pt_2));
1519fcf3ce44SJohn Forte 			types += 3;
1520fcf3ce44SJohn Forte 
1521fcf3ce44SJohn Forte 			i = 0;
1522fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1523fcf3ce44SJohn Forte 				/* Null terminate the next value */
1524fcf3ce44SJohn Forte 				ptr = types;
1525fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1526fcf3ce44SJohn Forte 					ptr++;
1527fcf3ce44SJohn Forte 				*ptr = 0;
1528fcf3ce44SJohn Forte 
1529fcf3ce44SJohn Forte 				/* Save the value */
1530fcf3ce44SJohn Forte 				model->pt_2[i++] =
1531fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1532fcf3ce44SJohn Forte 
1533fcf3ce44SJohn Forte 				/*
1534fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1535fcf3ce44SJohn Forte 				 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
1536fcf3ce44SJohn Forte 				 */
1537fcf3ce44SJohn Forte 
1538fcf3ce44SJohn Forte 				/* Move the str pointer */
1539fcf3ce44SJohn Forte 				types = ptr + 1;
1540fcf3ce44SJohn Forte 			}
1541fcf3ce44SJohn Forte 
1542fcf3ce44SJohn Forte 		} else if (strncmp(types, "T3:", 3) == 0) {
1543fcf3ce44SJohn Forte 			bzero(model->pt_3, sizeof (model->pt_3));
1544fcf3ce44SJohn Forte 			types += 3;
1545fcf3ce44SJohn Forte 
1546fcf3ce44SJohn Forte 			i = 0;
1547fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1548fcf3ce44SJohn Forte 				/* Null terminate the next value */
1549fcf3ce44SJohn Forte 				ptr = types;
1550fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1551fcf3ce44SJohn Forte 					ptr++;
1552fcf3ce44SJohn Forte 				*ptr = 0;
1553fcf3ce44SJohn Forte 
1554fcf3ce44SJohn Forte 				/* Save the value */
1555fcf3ce44SJohn Forte 				model->pt_3[i++] =
1556fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1557fcf3ce44SJohn Forte 
1558fcf3ce44SJohn Forte 				/*
1559fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1560fcf3ce44SJohn Forte 				 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
1561fcf3ce44SJohn Forte 				 */
1562fcf3ce44SJohn Forte 
1563fcf3ce44SJohn Forte 				/* Move the str pointer */
1564fcf3ce44SJohn Forte 				types = ptr + 1;
1565fcf3ce44SJohn Forte 			}
1566fcf3ce44SJohn Forte 		} else if (strncmp(types, "T6:", 3) == 0) {
1567fcf3ce44SJohn Forte 			bzero(model->pt_6, sizeof (model->pt_6));
1568fcf3ce44SJohn Forte 			types += 3;
1569fcf3ce44SJohn Forte 
1570fcf3ce44SJohn Forte 			i = 0;
1571fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1572fcf3ce44SJohn Forte 				/* Null terminate the next value */
1573fcf3ce44SJohn Forte 				ptr = types;
1574fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1575fcf3ce44SJohn Forte 					ptr++;
1576fcf3ce44SJohn Forte 				*ptr = 0;
1577fcf3ce44SJohn Forte 
1578fcf3ce44SJohn Forte 				/* Save the value */
1579fcf3ce44SJohn Forte 				model->pt_6[i++] =
1580fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1581fcf3ce44SJohn Forte 				model->pt_6[i] = 0;
1582fcf3ce44SJohn Forte 
1583fcf3ce44SJohn Forte 				/*
1584fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1585fcf3ce44SJohn Forte 				 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
1586fcf3ce44SJohn Forte 				 */
1587fcf3ce44SJohn Forte 
1588fcf3ce44SJohn Forte 				/* Move the str pointer */
1589fcf3ce44SJohn Forte 				types = ptr + 1;
1590fcf3ce44SJohn Forte 			}
1591fcf3ce44SJohn Forte 		} else if (strncmp(types, "T7:", 3) == 0) {
1592fcf3ce44SJohn Forte 			bzero(model->pt_7, sizeof (model->pt_7));
1593fcf3ce44SJohn Forte 			types += 3;
1594fcf3ce44SJohn Forte 
1595fcf3ce44SJohn Forte 			i = 0;
1596fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1597fcf3ce44SJohn Forte 				/* Null terminate the next value */
1598fcf3ce44SJohn Forte 				ptr = types;
1599fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1600fcf3ce44SJohn Forte 					ptr++;
1601fcf3ce44SJohn Forte 				*ptr = 0;
1602fcf3ce44SJohn Forte 
1603fcf3ce44SJohn Forte 				/* Save the value */
1604fcf3ce44SJohn Forte 				model->pt_7[i++] =
1605fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1606fcf3ce44SJohn Forte 				model->pt_7[i] = 0;
1607fcf3ce44SJohn Forte 
1608fcf3ce44SJohn Forte 				/*
1609fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1610fcf3ce44SJohn Forte 				 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
1611fcf3ce44SJohn Forte 				 */
1612fcf3ce44SJohn Forte 
1613fcf3ce44SJohn Forte 				/* Move the str pointer */
1614fcf3ce44SJohn Forte 				types = ptr + 1;
1615fcf3ce44SJohn Forte 			}
1616fcf3ce44SJohn Forte 		} else if (strncmp(types, "TA:", 3) == 0) {
1617fcf3ce44SJohn Forte 			bzero(model->pt_A, sizeof (model->pt_A));
1618fcf3ce44SJohn Forte 			types += 3;
1619fcf3ce44SJohn Forte 
1620fcf3ce44SJohn Forte 			i = 0;
1621fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1622fcf3ce44SJohn Forte 				/* Null terminate the next value */
1623fcf3ce44SJohn Forte 				ptr = types;
1624fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1625fcf3ce44SJohn Forte 					ptr++;
1626fcf3ce44SJohn Forte 				*ptr = 0;
1627fcf3ce44SJohn Forte 
1628fcf3ce44SJohn Forte 				/* Save the value */
1629fcf3ce44SJohn Forte 				model->pt_A[i++] =
1630fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1631fcf3ce44SJohn Forte 
1632fcf3ce44SJohn Forte 				/*
1633fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1634fcf3ce44SJohn Forte 				 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
1635fcf3ce44SJohn Forte 				 */
1636fcf3ce44SJohn Forte 
1637fcf3ce44SJohn Forte 				/* Move the str pointer */
1638fcf3ce44SJohn Forte 				types = ptr + 1;
1639fcf3ce44SJohn Forte 			}
1640fcf3ce44SJohn Forte 		} else if (strncmp(types, "TB:", 3) == 0) {
1641fcf3ce44SJohn Forte 			bzero(model->pt_B, sizeof (model->pt_B));
1642fcf3ce44SJohn Forte 			types += 3;
1643fcf3ce44SJohn Forte 
1644fcf3ce44SJohn Forte 			i = 0;
1645fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1646fcf3ce44SJohn Forte 				/* Null terminate the next value */
1647fcf3ce44SJohn Forte 				ptr = types;
1648fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1649fcf3ce44SJohn Forte 					ptr++;
1650fcf3ce44SJohn Forte 				*ptr = 0;
1651fcf3ce44SJohn Forte 
1652fcf3ce44SJohn Forte 				/* Save the value */
1653fcf3ce44SJohn Forte 				model->pt_B[i++] =
1654fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1655fcf3ce44SJohn Forte 
1656fcf3ce44SJohn Forte 				/*
1657fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1658fcf3ce44SJohn Forte 				 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
1659fcf3ce44SJohn Forte 				 */
1660fcf3ce44SJohn Forte 
1661fcf3ce44SJohn Forte 				/* Move the str pointer */
1662fcf3ce44SJohn Forte 				types = ptr + 1;
1663fcf3ce44SJohn Forte 			}
1664fcf3ce44SJohn Forte 		} else if (strncmp(types, "TFF:", 4) == 0) {
1665fcf3ce44SJohn Forte 			bzero(model->pt_FF, sizeof (model->pt_FF));
1666fcf3ce44SJohn Forte 			types += 4;
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 			i = 0;
1669fcf3ce44SJohn Forte 			while (*types && *types != 'T') {
1670fcf3ce44SJohn Forte 				/* Null terminate the next value */
1671fcf3ce44SJohn Forte 				ptr = types;
1672fcf3ce44SJohn Forte 				while (*ptr && (*ptr != ','))
1673fcf3ce44SJohn Forte 					ptr++;
1674fcf3ce44SJohn Forte 				*ptr = 0;
1675fcf3ce44SJohn Forte 
1676fcf3ce44SJohn Forte 				/* Save the value */
1677fcf3ce44SJohn Forte 				model->pt_FF[i++] =
1678fcf3ce44SJohn Forte 				    (uint8_t)emlxs_strtol(types, 16);
1679fcf3ce44SJohn Forte 
1680fcf3ce44SJohn Forte 				/*
1681fcf3ce44SJohn Forte 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1682fcf3ce44SJohn Forte 				 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
1683fcf3ce44SJohn Forte 				 */
1684fcf3ce44SJohn Forte 
1685291a2b48SSukumar Swaminathan 				/* Move the str pointer */
1686291a2b48SSukumar Swaminathan 				types = ptr + 1;
1687291a2b48SSukumar Swaminathan 			}
1688291a2b48SSukumar Swaminathan 		} else if (strncmp(types, "T20:", 4) == 0) {
1689291a2b48SSukumar Swaminathan 			bzero(model->pt_20, sizeof (model->pt_20));
1690291a2b48SSukumar Swaminathan 			types += 4;
1691291a2b48SSukumar Swaminathan 
1692291a2b48SSukumar Swaminathan 			i = 0;
1693291a2b48SSukumar Swaminathan 			while (*types && *types != 'T') {
1694291a2b48SSukumar Swaminathan 				/* Null terminate the next value */
1695291a2b48SSukumar Swaminathan 				ptr = types;
1696291a2b48SSukumar Swaminathan 				while (*ptr && (*ptr != ','))
1697291a2b48SSukumar Swaminathan 					ptr++;
1698291a2b48SSukumar Swaminathan 				*ptr = 0;
1699291a2b48SSukumar Swaminathan 
1700291a2b48SSukumar Swaminathan 				/* Save the value */
1701291a2b48SSukumar Swaminathan 				model->pt_20[i++] =
1702291a2b48SSukumar Swaminathan 				    (uint8_t)emlxs_strtol(types, 16);
1703291a2b48SSukumar Swaminathan 				model->pt_20[i] = 0;
1704291a2b48SSukumar Swaminathan 
1705291a2b48SSukumar Swaminathan 				/*
1706291a2b48SSukumar Swaminathan 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1707291a2b48SSukumar Swaminathan 				 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
1708291a2b48SSukumar Swaminathan 				 */
1709291a2b48SSukumar Swaminathan 
1710fcf3ce44SJohn Forte 				/* Move the str pointer */
1711fcf3ce44SJohn Forte 				types = ptr + 1;
1712fcf3ce44SJohn Forte 			}
1713fcf3ce44SJohn Forte 		} else {
1714fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1715fcf3ce44SJohn Forte 			    "Unknown prog type string = %s", types);
1716fcf3ce44SJohn Forte 			break;
1717fcf3ce44SJohn Forte 		}
1718fcf3ce44SJohn Forte 	}
1719fcf3ce44SJohn Forte 
1720fcf3ce44SJohn Forte 	return;
1721fcf3ce44SJohn Forte 
1722*82527734SSukumar Swaminathan } /* emlxs_parse_prog_types() */
1723fcf3ce44SJohn Forte 
1724fcf3ce44SJohn Forte 
1725*82527734SSukumar Swaminathan extern void
1726fcf3ce44SJohn Forte emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types)
1727fcf3ce44SJohn Forte {
1728fcf3ce44SJohn Forte 	uint32_t i;
1729fcf3ce44SJohn Forte 	uint32_t found = 0;
1730fcf3ce44SJohn Forte 	char buffer[256];
1731fcf3ce44SJohn Forte 
1732fcf3ce44SJohn Forte 	bzero(prog_types, 256);
1733fcf3ce44SJohn Forte 
1734fcf3ce44SJohn Forte 	/* Rebuild the prog type string */
1735fcf3ce44SJohn Forte 	if (hba->model_info.pt_2[0]) {
1736fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T2:");
1737fcf3ce44SJohn Forte 		found = 1;
1738fcf3ce44SJohn Forte 
1739fcf3ce44SJohn Forte 		i = 0;
1740fcf3ce44SJohn Forte 		while (hba->model_info.pt_2[i] && i < 8) {
1741fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]);
1742fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1743fcf3ce44SJohn Forte 			i++;
1744fcf3ce44SJohn Forte 		}
1745fcf3ce44SJohn Forte 	}
1746291a2b48SSukumar Swaminathan 
1747fcf3ce44SJohn Forte 	if (hba->model_info.pt_3[0]) {
1748fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T3:");
1749fcf3ce44SJohn Forte 		found = 1;
1750fcf3ce44SJohn Forte 
1751fcf3ce44SJohn Forte 		i = 0;
1752fcf3ce44SJohn Forte 		while (hba->model_info.pt_3[i] && i < 8) {
1753fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]);
1754fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1755fcf3ce44SJohn Forte 			i++;
1756fcf3ce44SJohn Forte 
1757fcf3ce44SJohn Forte 		}
1758fcf3ce44SJohn Forte 	}
1759291a2b48SSukumar Swaminathan 
1760fcf3ce44SJohn Forte 	if (hba->model_info.pt_6[0]) {
1761fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T6:");
1762fcf3ce44SJohn Forte 		found = 1;
1763fcf3ce44SJohn Forte 
1764fcf3ce44SJohn Forte 		i = 0;
1765fcf3ce44SJohn Forte 		while (hba->model_info.pt_6[i] && i < 8) {
1766fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]);
1767fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1768fcf3ce44SJohn Forte 			i++;
1769fcf3ce44SJohn Forte 		}
1770fcf3ce44SJohn Forte 	}
1771291a2b48SSukumar Swaminathan 
1772fcf3ce44SJohn Forte 	if (hba->model_info.pt_7[0]) {
1773fcf3ce44SJohn Forte 		(void) strcat(prog_types, "T7:");
1774fcf3ce44SJohn Forte 		found = 1;
1775fcf3ce44SJohn Forte 
1776fcf3ce44SJohn Forte 		i = 0;
1777fcf3ce44SJohn Forte 		while (hba->model_info.pt_7[i] && i < 8) {
1778fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]);
1779fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1780fcf3ce44SJohn Forte 			i++;
1781fcf3ce44SJohn Forte 		}
1782fcf3ce44SJohn Forte 	}
1783291a2b48SSukumar Swaminathan 
1784fcf3ce44SJohn Forte 	if (hba->model_info.pt_A[0]) {
1785fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TA:");
1786fcf3ce44SJohn Forte 		found = 1;
1787fcf3ce44SJohn Forte 
1788fcf3ce44SJohn Forte 		i = 0;
1789fcf3ce44SJohn Forte 		while (hba->model_info.pt_A[i] && i < 8) {
1790fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]);
1791fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1792fcf3ce44SJohn Forte 			i++;
1793fcf3ce44SJohn Forte 		}
1794fcf3ce44SJohn Forte 	}
1795291a2b48SSukumar Swaminathan 
1796291a2b48SSukumar Swaminathan 
1797fcf3ce44SJohn Forte 	if (hba->model_info.pt_B[0]) {
1798fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TB:");
1799fcf3ce44SJohn Forte 		found = 1;
1800fcf3ce44SJohn Forte 
1801fcf3ce44SJohn Forte 		i = 0;
1802fcf3ce44SJohn Forte 		while (hba->model_info.pt_B[i] && i < 8) {
1803fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]);
1804fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1805fcf3ce44SJohn Forte 			i++;
1806fcf3ce44SJohn Forte 		}
1807fcf3ce44SJohn Forte 	}
1808291a2b48SSukumar Swaminathan 
1809291a2b48SSukumar Swaminathan 	if (hba->model_info.pt_20[0]) {
1810291a2b48SSukumar Swaminathan 		(void) strcat(prog_types, "T20:");
1811291a2b48SSukumar Swaminathan 		found = 1;
1812291a2b48SSukumar Swaminathan 
1813291a2b48SSukumar Swaminathan 		i = 0;
1814291a2b48SSukumar Swaminathan 		while (hba->model_info.pt_20[i] && i < 8) {
1815291a2b48SSukumar Swaminathan 			(void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]);
1816291a2b48SSukumar Swaminathan 			(void) strcat(prog_types, buffer);
1817291a2b48SSukumar Swaminathan 			i++;
1818291a2b48SSukumar Swaminathan 		}
1819291a2b48SSukumar Swaminathan 	}
1820291a2b48SSukumar Swaminathan 
1821fcf3ce44SJohn Forte 	if (hba->model_info.pt_FF[0]) {
1822fcf3ce44SJohn Forte 		(void) strcat(prog_types, "TFF:");
1823fcf3ce44SJohn Forte 		found = 1;
1824fcf3ce44SJohn Forte 
1825fcf3ce44SJohn Forte 		i = 0;
1826fcf3ce44SJohn Forte 		while (hba->model_info.pt_FF[i] && i < 8) {
1827fcf3ce44SJohn Forte 			(void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]);
1828fcf3ce44SJohn Forte 			(void) strcat(prog_types, buffer);
1829fcf3ce44SJohn Forte 			i++;
1830fcf3ce44SJohn Forte 		}
1831fcf3ce44SJohn Forte 	}
1832291a2b48SSukumar Swaminathan 
1833fcf3ce44SJohn Forte 	if (found) {
1834fcf3ce44SJohn Forte 		/* Terminate at the last comma in string */
1835fcf3ce44SJohn Forte 		prog_types[(strlen(prog_types) - 1)] = 0;
1836fcf3ce44SJohn Forte 	}
1837291a2b48SSukumar Swaminathan 
1838fcf3ce44SJohn Forte 	return;
1839fcf3ce44SJohn Forte 
1840*82527734SSukumar Swaminathan } /* emlxs_build_prog_types() */
1841fcf3ce44SJohn Forte 
1842fcf3ce44SJohn Forte 
1843fcf3ce44SJohn Forte 
1844fcf3ce44SJohn Forte 
1845fcf3ce44SJohn Forte extern uint32_t
1846fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba)
1847fcf3ce44SJohn Forte {
1848fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1849fcf3ce44SJohn Forte 	uint32_t pci_id;
1850fcf3ce44SJohn Forte 	uint32_t cache_line;
1851fcf3ce44SJohn Forte 	uint32_t channels;
1852fcf3ce44SJohn Forte 	uint16_t device_id;
1853fcf3ce44SJohn Forte 	uint16_t ssdid;
1854fcf3ce44SJohn Forte 	uint32_t i;
1855fcf3ce44SJohn Forte 	uint32_t found = 0;
1856*82527734SSukumar Swaminathan 	int32_t *prop;
1857*82527734SSukumar Swaminathan 	uint32_t num_prop;
1858fcf3ce44SJohn Forte 
1859fcf3ce44SJohn Forte 	if (hba->bus_type == SBUS_FC) {
1860fcf3ce44SJohn Forte 		if (hba->pci_acc_handle == NULL) {
1861fcf3ce44SJohn Forte 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
1862fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
1863fcf3ce44SJohn Forte 
1864fcf3ce44SJohn Forte 			hba->model_info.device_id = 0;
1865fcf3ce44SJohn Forte 
1866fcf3ce44SJohn Forte 			return (0);
1867fcf3ce44SJohn Forte 		}
1868291a2b48SSukumar Swaminathan 
1869fcf3ce44SJohn Forte 		/* Read the PCI device id */
1870291a2b48SSukumar Swaminathan 		pci_id =
1871291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
1872fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
1873fcf3ce44SJohn Forte 		device_id = (uint16_t)(pci_id >> 16);
1874fcf3ce44SJohn Forte 
1875fcf3ce44SJohn Forte 		/* Find matching adapter model */
1876fcf3ce44SJohn Forte 		for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
1877fcf3ce44SJohn Forte 			if (emlxs_sbus_model[i].device_id == device_id) {
1878fcf3ce44SJohn Forte 				bcopy(&emlxs_sbus_model[i], &hba->model_info,
1879fcf3ce44SJohn Forte 				    sizeof (emlxs_model_t));
1880fcf3ce44SJohn Forte 				found = 1;
1881fcf3ce44SJohn Forte 				break;
1882fcf3ce44SJohn Forte 			}
1883fcf3ce44SJohn Forte 		}
1884fcf3ce44SJohn Forte 
1885fcf3ce44SJohn Forte 		/* If not found then use the unknown model */
1886fcf3ce44SJohn Forte 		if (!found) {
1887fcf3ce44SJohn Forte 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
1888fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
1889fcf3ce44SJohn Forte 
1890fcf3ce44SJohn Forte 			hba->model_info.device_id = device_id;
1891fcf3ce44SJohn Forte 
1892fcf3ce44SJohn Forte 			return (0);
1893fcf3ce44SJohn Forte 		}
1894fcf3ce44SJohn Forte 	} else {	/* PCI model */
1895291a2b48SSukumar Swaminathan 
1896fcf3ce44SJohn Forte 		if (hba->pci_acc_handle == NULL) {
1897fcf3ce44SJohn Forte 			bcopy(&emlxs_pci_model[0], &hba->model_info,
1898fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
1899fcf3ce44SJohn Forte 
1900fcf3ce44SJohn Forte 			hba->model_info.device_id = 0;
1901fcf3ce44SJohn Forte 
1902fcf3ce44SJohn Forte 			return (0);
1903fcf3ce44SJohn Forte 		}
1904291a2b48SSukumar Swaminathan 
1905fcf3ce44SJohn Forte 		/* Read the PCI device id */
1906291a2b48SSukumar Swaminathan 		device_id =
1907291a2b48SSukumar Swaminathan 		    ddi_get16(hba->pci_acc_handle,
1908fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
1909fcf3ce44SJohn Forte 
1910fcf3ce44SJohn Forte 		/* Read the PCI Subsystem id */
1911291a2b48SSukumar Swaminathan 		ssdid =
1912291a2b48SSukumar Swaminathan 		    ddi_get16(hba->pci_acc_handle,
1913fcf3ce44SJohn Forte 		    (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
1914fcf3ce44SJohn Forte 
1915fcf3ce44SJohn Forte 		if (ssdid == 0 || ssdid == 0xffff) {
1916fcf3ce44SJohn Forte 			ssdid = device_id;
1917fcf3ce44SJohn Forte 		}
1918291a2b48SSukumar Swaminathan 
1919fcf3ce44SJohn Forte 		/* Read the Cache Line reg */
1920291a2b48SSukumar Swaminathan 		cache_line =
1921291a2b48SSukumar Swaminathan 		    ddi_get32(hba->pci_acc_handle,
1922fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
1923fcf3ce44SJohn Forte 
1924fcf3ce44SJohn Forte 		/* Check for the multifunction bit being set */
1925fcf3ce44SJohn Forte 		if ((cache_line & 0x00ff0000) == 0x00800000) {
1926fcf3ce44SJohn Forte 			channels = 2;
1927fcf3ce44SJohn Forte 		} else {
1928fcf3ce44SJohn Forte 			channels = 1;
1929fcf3ce44SJohn Forte 		}
1930fcf3ce44SJohn Forte 
1931fcf3ce44SJohn Forte 		/* If device ids are unique, then use them for search */
1932fcf3ce44SJohn Forte 		if (device_id != ssdid) {
1933fcf3ce44SJohn Forte 			if (channels > 1) {
1934fcf3ce44SJohn Forte 				/*
1935fcf3ce44SJohn Forte 				 * Find matching adapter model using
1936fcf3ce44SJohn Forte 				 * device_id, ssdid and channels
1937fcf3ce44SJohn Forte 				 */
1938*82527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
1939291a2b48SSukumar Swaminathan 					if (emlxs_pci_model[i].device_id ==
1940291a2b48SSukumar Swaminathan 					    device_id &&
1941291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].ssdid == ssdid &&
1942291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].channels ==
1943291a2b48SSukumar Swaminathan 					    channels) {
1944fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
1945fcf3ce44SJohn Forte 						    &hba->model_info,
1946fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
1947fcf3ce44SJohn Forte 						found = 1;
1948fcf3ce44SJohn Forte 						break;
1949fcf3ce44SJohn Forte 					}
1950fcf3ce44SJohn Forte 				}
1951fcf3ce44SJohn Forte 			} else {
1952fcf3ce44SJohn Forte 				/*
1953fcf3ce44SJohn Forte 				 * Find matching adapter model using
1954fcf3ce44SJohn Forte 				 * device_id and ssdid
1955fcf3ce44SJohn Forte 				 */
1956*82527734SSukumar Swaminathan 				for (i = 1; i < emlxs_pci_model_count; i++) {
1957291a2b48SSukumar Swaminathan 					if (emlxs_pci_model[i].device_id ==
1958291a2b48SSukumar Swaminathan 					    device_id &&
1959291a2b48SSukumar Swaminathan 					    emlxs_pci_model[i].ssdid == ssdid) {
1960fcf3ce44SJohn Forte 						bcopy(&emlxs_pci_model[i],
1961fcf3ce44SJohn Forte 						    &hba->model_info,
1962fcf3ce44SJohn Forte 						    sizeof (emlxs_model_t));
1963fcf3ce44SJohn Forte 						found = 1;
1964fcf3ce44SJohn Forte 						break;
1965fcf3ce44SJohn Forte 					}
1966fcf3ce44SJohn Forte 				}
1967fcf3ce44SJohn Forte 			}
1968fcf3ce44SJohn Forte 		}
1969291a2b48SSukumar Swaminathan 
1970fcf3ce44SJohn Forte 		/* If adapter not found, try again */
1971fcf3ce44SJohn Forte 		if (!found) {
1972fcf3ce44SJohn Forte 			/* Find matching adapter model */
1973*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
1974fcf3ce44SJohn Forte 				if (emlxs_pci_model[i].device_id == device_id &&
1975fcf3ce44SJohn Forte 				    emlxs_pci_model[i].channels == channels) {
1976fcf3ce44SJohn Forte 					bcopy(&emlxs_pci_model[i],
1977fcf3ce44SJohn Forte 					    &hba->model_info,
1978fcf3ce44SJohn Forte 					    sizeof (emlxs_model_t));
1979fcf3ce44SJohn Forte 					found = 1;
1980fcf3ce44SJohn Forte 					break;
1981fcf3ce44SJohn Forte 				}
1982fcf3ce44SJohn Forte 			}
1983fcf3ce44SJohn Forte 		}
1984291a2b48SSukumar Swaminathan 
1985fcf3ce44SJohn Forte 		/* If adapter not found, try one last time */
1986fcf3ce44SJohn Forte 		if (!found) {
1987fcf3ce44SJohn Forte 			/* Find matching adapter model */
1988*82527734SSukumar Swaminathan 			for (i = 1; i < emlxs_pci_model_count; i++) {
1989fcf3ce44SJohn Forte 				if (emlxs_pci_model[i].device_id == device_id) {
1990fcf3ce44SJohn Forte 					bcopy(&emlxs_pci_model[i],
1991fcf3ce44SJohn Forte 					    &hba->model_info,
1992fcf3ce44SJohn Forte 					    sizeof (emlxs_model_t));
1993fcf3ce44SJohn Forte 					found = 1;
1994fcf3ce44SJohn Forte 					break;
1995fcf3ce44SJohn Forte 				}
1996fcf3ce44SJohn Forte 			}
1997fcf3ce44SJohn Forte 		}
1998291a2b48SSukumar Swaminathan 
1999fcf3ce44SJohn Forte 		/* If not found, set adapter to unknown */
2000fcf3ce44SJohn Forte 		if (!found) {
2001fcf3ce44SJohn Forte 			bcopy(&emlxs_pci_model[0], &hba->model_info,
2002fcf3ce44SJohn Forte 			    sizeof (emlxs_model_t));
2003fcf3ce44SJohn Forte 
2004fcf3ce44SJohn Forte 			hba->model_info.device_id = device_id;
2005fcf3ce44SJohn Forte 			hba->model_info.ssdid = ssdid;
2006fcf3ce44SJohn Forte 
2007fcf3ce44SJohn Forte 			return (0);
2008fcf3ce44SJohn Forte 		}
2009fcf3ce44SJohn Forte 
2010fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT
2011fcf3ce44SJohn Forte 		/*
2012291a2b48SSukumar Swaminathan 		 * This will disable MSI support for Saturn adapter's
2013291a2b48SSukumar Swaminathan 		 * due to a PCI bus issue
2014fcf3ce44SJohn Forte 		 */
2015fcf3ce44SJohn Forte 		if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2016fcf3ce44SJohn Forte 			hba->model_info.flags &=
2017fcf3ce44SJohn Forte 			    ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2018fcf3ce44SJohn Forte 		}
2019291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */
2020fcf3ce44SJohn Forte 
2021fcf3ce44SJohn Forte 
2022fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
2023fcf3ce44SJohn Forte 		/* Verify MSI support */
2024fcf3ce44SJohn Forte 		if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) {
2025fcf3ce44SJohn Forte 			uint32_t offset;
2026fcf3ce44SJohn Forte 			uint32_t reg;
2027fcf3ce44SJohn Forte 
2028fcf3ce44SJohn Forte 			/* Scan for MSI capabilities register */
2029291a2b48SSukumar Swaminathan 			offset =
2030291a2b48SSukumar Swaminathan 			    ddi_get32(hba->pci_acc_handle,
2031fcf3ce44SJohn Forte 			    (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
2032fcf3ce44SJohn Forte 			offset &= 0xff;
2033fcf3ce44SJohn Forte 
2034fcf3ce44SJohn Forte 			while (offset) {
2035291a2b48SSukumar Swaminathan 				reg =
2036291a2b48SSukumar Swaminathan 				    ddi_get32(hba->pci_acc_handle,
2037fcf3ce44SJohn Forte 				    (uint32_t *)(hba->pci_addr + offset));
2038fcf3ce44SJohn Forte 
2039fcf3ce44SJohn Forte 				if ((reg & 0xff) == MSI_CAP_ID) {
2040fcf3ce44SJohn Forte 					break;
2041fcf3ce44SJohn Forte 				}
2042fcf3ce44SJohn Forte 				offset = (reg >> 8) & 0xff;
2043fcf3ce44SJohn Forte 			}
2044fcf3ce44SJohn Forte 
2045fcf3ce44SJohn Forte 			if (offset) {
2046fcf3ce44SJohn Forte 				hba->msi_cap_offset = offset + 2;
2047fcf3ce44SJohn Forte 			} else {
2048fcf3ce44SJohn Forte 				hba->msi_cap_offset = 0;
2049fcf3ce44SJohn Forte 				hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2050fcf3ce44SJohn Forte 
2051291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2052291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
2053fcf3ce44SJohn Forte 				    "MSI: control_reg capability not found!");
2054fcf3ce44SJohn Forte 			}
2055fcf3ce44SJohn Forte 		}
2056291a2b48SSukumar Swaminathan 
2057fcf3ce44SJohn Forte 		/* Verify MSI-X support */
2058fcf3ce44SJohn Forte 		if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) {
2059fcf3ce44SJohn Forte 			uint32_t offset;
2060fcf3ce44SJohn Forte 			uint32_t reg;
2061fcf3ce44SJohn Forte 
2062fcf3ce44SJohn Forte 			/* Scan for MSI capabilities register */
2063291a2b48SSukumar Swaminathan 			offset =
2064291a2b48SSukumar Swaminathan 			    ddi_get32(hba->pci_acc_handle,
2065fcf3ce44SJohn Forte 			    (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
2066fcf3ce44SJohn Forte 			offset &= 0xff;
2067fcf3ce44SJohn Forte 
2068fcf3ce44SJohn Forte 			while (offset) {
2069291a2b48SSukumar Swaminathan 				reg =
2070291a2b48SSukumar Swaminathan 				    ddi_get32(hba->pci_acc_handle,
2071fcf3ce44SJohn Forte 				    (uint32_t *)(hba->pci_addr + offset));
2072fcf3ce44SJohn Forte 
2073fcf3ce44SJohn Forte 				if ((reg & 0xff) == MSIX_CAP_ID) {
2074fcf3ce44SJohn Forte 					break;
2075fcf3ce44SJohn Forte 				}
2076fcf3ce44SJohn Forte 				offset = (reg >> 8) & 0xff;
2077fcf3ce44SJohn Forte 			}
2078fcf3ce44SJohn Forte 
2079fcf3ce44SJohn Forte 			if (offset) {
2080fcf3ce44SJohn Forte 				hba->msix_cap_offset = offset;
2081fcf3ce44SJohn Forte 			} else {
2082fcf3ce44SJohn Forte 				hba->msix_cap_offset = 0;
2083291a2b48SSukumar Swaminathan 				hba->model_info.flags &=
2084291a2b48SSukumar Swaminathan 				    ~EMLXS_MSIX_SUPPORTED;
2085fcf3ce44SJohn Forte 
2086291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2087291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
2088fcf3ce44SJohn Forte 				    "MSIX: control_reg capability not found!");
2089fcf3ce44SJohn Forte 			}
2090fcf3ce44SJohn Forte 		}
2091291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
2092291a2b48SSukumar Swaminathan 
2093291a2b48SSukumar Swaminathan 	}
2094fcf3ce44SJohn Forte 
2095*82527734SSukumar Swaminathan 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2096*82527734SSukumar Swaminathan 	    "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
2097*82527734SSukumar Swaminathan 		/* Parse the property for PCI function, device and bus no. */
2098*82527734SSukumar Swaminathan 		hba->pci_function_number =
2099*82527734SSukumar Swaminathan 		    (uint8_t)((prop[0] & 0x00000700) >> 8);
2100*82527734SSukumar Swaminathan 		hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);
2101*82527734SSukumar Swaminathan 		hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16);
2102*82527734SSukumar Swaminathan 		ddi_prop_free((void *)prop);
2103*82527734SSukumar Swaminathan 	}
2104*82527734SSukumar Swaminathan 
2105*82527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
2106*82527734SSukumar Swaminathan 		hba->sli_api = emlxs_sli4_api;
2107*82527734SSukumar Swaminathan 	} else {
2108*82527734SSukumar Swaminathan 		hba->sli_api = emlxs_sli3_api;
2109*82527734SSukumar Swaminathan 	}
2110*82527734SSukumar Swaminathan 
21114baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
21124baa2c25SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
21134baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
21144baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
21154baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
21164baa2c25SSukumar Swaminathan 		return (0);
21174baa2c25SSukumar Swaminathan 	}
21184baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
21194baa2c25SSukumar Swaminathan 
2120fcf3ce44SJohn Forte 	return (1);
2121fcf3ce44SJohn Forte 
2122*82527734SSukumar Swaminathan } /* emlxs_init_adapter_info()  */
2123fcf3ce44SJohn Forte 
2124fcf3ce44SJohn Forte 
2125291a2b48SSukumar Swaminathan /* ARGSUSED */
2126291a2b48SSukumar Swaminathan static void
2127*82527734SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2128fcf3ce44SJohn Forte {
2129291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2130291a2b48SSukumar Swaminathan 	IOCB *iocb;
2131291a2b48SSukumar Swaminathan 	uint32_t *w;
2132291a2b48SSukumar Swaminathan 	int i, j;
2133fcf3ce44SJohn Forte 
2134291a2b48SSukumar Swaminathan 	iocb = &iocbq->iocb;
2135fcf3ce44SJohn Forte 
2136*82527734SSukumar Swaminathan 	if (iocb->ULPSTATUS != 0) {
2137291a2b48SSukumar Swaminathan 		return;
2138fcf3ce44SJohn Forte 	}
2139fcf3ce44SJohn Forte 
2140291a2b48SSukumar Swaminathan 	switch (iocb->un.astat.EventCode) {
2141291a2b48SSukumar Swaminathan 	case 0x0100:	/* Temp Warning */
2142291a2b48SSukumar Swaminathan 
2143291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
2144291a2b48SSukumar Swaminathan 		    "Adapter is very hot (%d �C). Take corrective action.",
2145*82527734SSukumar Swaminathan 		    iocb->ULPCONTEXT);
2146*82527734SSukumar Swaminathan 
2147*82527734SSukumar Swaminathan 		hba->temperature = iocb->ULPCONTEXT;
2148*82527734SSukumar Swaminathan 		emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
2149fcf3ce44SJohn Forte 
2150fcf3ce44SJohn Forte 
2151291a2b48SSukumar Swaminathan 		break;
2152fcf3ce44SJohn Forte 
2153fcf3ce44SJohn Forte 
2154291a2b48SSukumar Swaminathan 	case 0x0101:	/* Temp Safe */
2155fcf3ce44SJohn Forte 
2156291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
2157291a2b48SSukumar Swaminathan 		    "Adapter temperature now safe (%d �C).",
2158*82527734SSukumar Swaminathan 		    iocb->ULPCONTEXT);
2159fcf3ce44SJohn Forte 
2160*82527734SSukumar Swaminathan 		hba->temperature = iocb->ULPCONTEXT;
2161*82527734SSukumar Swaminathan 		emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
2162fcf3ce44SJohn Forte 
2163291a2b48SSukumar Swaminathan 		break;
2164fcf3ce44SJohn Forte 
2165291a2b48SSukumar Swaminathan 	default:
2166fcf3ce44SJohn Forte 
2167291a2b48SSukumar Swaminathan 		w = (uint32_t *)iocb;
2168291a2b48SSukumar Swaminathan 		for (i = 0, j = 0; i < 8; i++, j += 2) {
2169291a2b48SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
2170291a2b48SSukumar Swaminathan 			    "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
2171291a2b48SSukumar Swaminathan 			    w[j + 1]);
2172291a2b48SSukumar Swaminathan 		}
2173fcf3ce44SJohn Forte 
2174291a2b48SSukumar Swaminathan 		emlxs_log_async_event(port, iocb);
2175fcf3ce44SJohn Forte 	}
2176fcf3ce44SJohn Forte 
2177fcf3ce44SJohn Forte 	return;
2178fcf3ce44SJohn Forte 
2179*82527734SSukumar Swaminathan } /* emlxs_handle_async_event() */
2180fcf3ce44SJohn Forte 
2181fcf3ce44SJohn Forte 
2182bb63f56eSSukumar Swaminathan /* ARGSUSED */
2183291a2b48SSukumar Swaminathan extern void
2184bb63f56eSSukumar Swaminathan emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2185fcf3ce44SJohn Forte {
2186291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2187fcf3ce44SJohn Forte 
2188291a2b48SSukumar Swaminathan 	/* Attempt a link reset to recover */
2189291a2b48SSukumar Swaminathan 	(void) emlxs_reset(port, FC_FCA_LINK_RESET);
2190fcf3ce44SJohn Forte 
2191bb63f56eSSukumar Swaminathan 	return;
2192fcf3ce44SJohn Forte 
2193*82527734SSukumar Swaminathan } /* emlxs_reset_link_thread() */
2194fcf3ce44SJohn Forte 
2195fcf3ce44SJohn Forte 
2196bb63f56eSSukumar Swaminathan /* ARGSUSED */
2197fcf3ce44SJohn Forte extern void
2198bb63f56eSSukumar Swaminathan emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2199fcf3ce44SJohn Forte {
2200fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2201fcf3ce44SJohn Forte 
2202fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
2203fcf3ce44SJohn Forte 
2204fcf3ce44SJohn Forte 	/* Attempt a full hardware reset to recover */
2205fcf3ce44SJohn Forte 	if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
2206*82527734SSukumar Swaminathan 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
2207fcf3ce44SJohn Forte 
2208*82527734SSukumar Swaminathan 		emlxs_shutdown_thread(hba, arg1, arg2);
2209fcf3ce44SJohn Forte 	}
2210fcf3ce44SJohn Forte 
2211bb63f56eSSukumar Swaminathan 	return;
2212291a2b48SSukumar Swaminathan 
2213*82527734SSukumar Swaminathan } /* emlxs_restart_thread() */
2214fcf3ce44SJohn Forte 
2215fcf3ce44SJohn Forte 
2216bb63f56eSSukumar Swaminathan /* ARGSUSED */
2217fcf3ce44SJohn Forte extern void
2218bb63f56eSSukumar Swaminathan emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2219fcf3ce44SJohn Forte {
2220fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2221fcf3ce44SJohn Forte 
2222fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
2223fcf3ce44SJohn Forte 	if (hba->flag & FC_SHUTDOWN) {
2224fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2225bb63f56eSSukumar Swaminathan 		return;
2226fcf3ce44SJohn Forte 	}
2227fcf3ce44SJohn Forte 	hba->flag |= FC_SHUTDOWN;
2228fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
2229fcf3ce44SJohn Forte 
2230291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
2231291a2b48SSukumar Swaminathan 	    "Shutting down...");
2232fcf3ce44SJohn Forte 
2233fcf3ce44SJohn Forte 	/* Take adapter offline and leave it there */
2234fcf3ce44SJohn Forte 	(void) emlxs_offline(hba);
2235fcf3ce44SJohn Forte 
2236*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2237*82527734SSukumar Swaminathan 		/*
2238*82527734SSukumar Swaminathan 		 * Dump is not defined for SLI4, so just
2239*82527734SSukumar Swaminathan 		 * reset the HBA for now.
2240*82527734SSukumar Swaminathan 		 */
2241*82527734SSukumar Swaminathan 		EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
2242*82527734SSukumar Swaminathan 
2243*82527734SSukumar Swaminathan 	} else {
2244*82527734SSukumar Swaminathan 		if (hba->flag & FC_OVERTEMP_EVENT) {
2245*82527734SSukumar Swaminathan 			emlxs_log_temp_event(port, 0x01,
2246*82527734SSukumar Swaminathan 			    hba->temperature);
2247*82527734SSukumar Swaminathan 		} else {
2248*82527734SSukumar Swaminathan 			emlxs_log_dump_event(port, NULL, 0);
2249*82527734SSukumar Swaminathan 		}
2250*82527734SSukumar Swaminathan 	}
2251fcf3ce44SJohn Forte 
2252fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
2253fcf3ce44SJohn Forte 
2254bb63f56eSSukumar Swaminathan 	return;
2255fcf3ce44SJohn Forte 
2256*82527734SSukumar Swaminathan } /* emlxs_shutdown_thread() */
2257fcf3ce44SJohn Forte 
2258fcf3ce44SJohn Forte 
2259fcf3ce44SJohn Forte /* ARGSUSED */
2260fcf3ce44SJohn Forte extern void
2261*82527734SSukumar Swaminathan emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
2262fcf3ce44SJohn Forte {
2263fcf3ce44SJohn Forte 	IOCBQ *iocbq;
2264fcf3ce44SJohn Forte 	IOCBQ *rsp_head;
2265fcf3ce44SJohn Forte 
2266fcf3ce44SJohn Forte 	/*
2267291a2b48SSukumar Swaminathan 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2268*82527734SSukumar Swaminathan 	 * "emlxs_proc_channel: channel=%d", cp->channelno);
2269fcf3ce44SJohn Forte 	 */
2270fcf3ce44SJohn Forte 
2271*82527734SSukumar Swaminathan 	mutex_enter(&cp->rsp_lock);
2272fcf3ce44SJohn Forte 
2273*82527734SSukumar Swaminathan 	while ((rsp_head = cp->rsp_head) != NULL) {
2274*82527734SSukumar Swaminathan 		cp->rsp_head = NULL;
2275*82527734SSukumar Swaminathan 		cp->rsp_tail = NULL;
2276fcf3ce44SJohn Forte 
2277*82527734SSukumar Swaminathan 		mutex_exit(&cp->rsp_lock);
2278fcf3ce44SJohn Forte 
2279fcf3ce44SJohn Forte 		while ((iocbq = rsp_head) != NULL) {
2280fcf3ce44SJohn Forte 			rsp_head = (IOCBQ *) iocbq->next;
2281fcf3ce44SJohn Forte 
2282*82527734SSukumar Swaminathan 			emlxs_proc_channel_event(hba, cp, iocbq);
2283fcf3ce44SJohn Forte 		}
2284fcf3ce44SJohn Forte 
2285*82527734SSukumar Swaminathan 		mutex_enter(&cp->rsp_lock);
2286fcf3ce44SJohn Forte 	}
2287fcf3ce44SJohn Forte 
2288*82527734SSukumar Swaminathan 	mutex_exit(&cp->rsp_lock);
2289fcf3ce44SJohn Forte 
2290*82527734SSukumar Swaminathan 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
2291fcf3ce44SJohn Forte 
2292fcf3ce44SJohn Forte 	return;
2293fcf3ce44SJohn Forte 
2294*82527734SSukumar Swaminathan } /* emlxs_proc_channel() */
2295fcf3ce44SJohn Forte 
2296fcf3ce44SJohn Forte 
2297fcf3ce44SJohn Forte /*
2298291a2b48SSukumar Swaminathan  * Called from SLI ring event routines to process a rsp ring IOCB.
2299fcf3ce44SJohn Forte  */
2300291a2b48SSukumar Swaminathan void
2301*82527734SSukumar Swaminathan emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2302fcf3ce44SJohn Forte {
2303fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2304fcf3ce44SJohn Forte 	char buffer[MAX_MSG_DATA + 1];
2305fcf3ce44SJohn Forte 	IOCB *iocb;
2306*82527734SSukumar Swaminathan 	emlxs_buf_t *sbp;
2307fcf3ce44SJohn Forte 
2308fcf3ce44SJohn Forte 	iocb = &iocbq->iocb;
2309fcf3ce44SJohn Forte 
2310*82527734SSukumar Swaminathan #ifdef DEBUG_CMPL_IOCB
2311*82527734SSukumar Swaminathan 	emlxs_data_dump(hba, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2312*82527734SSukumar Swaminathan #endif
2313*82527734SSukumar Swaminathan 
2314*82527734SSukumar Swaminathan 	sbp = (emlxs_buf_t *)iocbq->sbp;
2315*82527734SSukumar Swaminathan 	if (sbp) {
2316*82527734SSukumar Swaminathan 		if (!(sbp->pkt_flags & PACKET_VALID) ||
2317*82527734SSukumar Swaminathan 		    (sbp->pkt_flags & (PACKET_ULP_OWNED |
2318*82527734SSukumar Swaminathan 		    PACKET_IN_COMPLETION))) {
2319*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
2320*82527734SSukumar Swaminathan 			    "Duplicate: iocb=%p cmd=%x status=%x "
2321*82527734SSukumar Swaminathan 			    "error=%x iotag=%x context=%x info=%x",
2322*82527734SSukumar Swaminathan 			    iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
2323*82527734SSukumar Swaminathan 			    iocbq->iocb.ULPSTATUS,
2324*82527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
2325*82527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPIOTAG,
2326*82527734SSukumar Swaminathan 			    (uint16_t)iocbq->iocb.ULPCONTEXT,
2327*82527734SSukumar Swaminathan 			    (uint8_t)iocbq->iocb.ULPRSVDBYTE);
2328*82527734SSukumar Swaminathan 
2329*82527734SSukumar Swaminathan 			/* Drop this IO immediately */
2330*82527734SSukumar Swaminathan 			return;
2331*82527734SSukumar Swaminathan 		}
2332*82527734SSukumar Swaminathan 
2333*82527734SSukumar Swaminathan 		if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
2334*82527734SSukumar Swaminathan 			/*
2335*82527734SSukumar Swaminathan 			 * If the packet is tagged for timeout then set the
2336*82527734SSukumar Swaminathan 			 * return codes appropriately
2337*82527734SSukumar Swaminathan 			 */
2338*82527734SSukumar Swaminathan 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2339*82527734SSukumar Swaminathan 			iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
2340*82527734SSukumar Swaminathan 		} else if (sbp->pkt_flags &
2341*82527734SSukumar Swaminathan 		    (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
2342*82527734SSukumar Swaminathan 			/*
2343*82527734SSukumar Swaminathan 			 * If the packet is tagged for abort then set the
2344*82527734SSukumar Swaminathan 			 * return codes appropriately
2345*82527734SSukumar Swaminathan 			 */
2346*82527734SSukumar Swaminathan 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2347*82527734SSukumar Swaminathan 			iocb->un.grsp.perr.statLocalError =
2348*82527734SSukumar Swaminathan 			    IOERR_ABORT_REQUESTED;
2349*82527734SSukumar Swaminathan 		}
2350*82527734SSukumar Swaminathan 	}
2351*82527734SSukumar Swaminathan 
2352fcf3ce44SJohn Forte 	/* Check for IOCB local error */
2353*82527734SSukumar Swaminathan 	if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
2354fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
2355291a2b48SSukumar Swaminathan 		    "Local reject. ringno=%d iocb=%p cmd=%x "
2356291a2b48SSukumar Swaminathan 		    "iotag=%x context=%x info=%x error=%x",
2357*82527734SSukumar Swaminathan 		    cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
2358*82527734SSukumar Swaminathan 		    (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
2359*82527734SSukumar Swaminathan 		    (uint8_t)iocb->ULPRSVDBYTE,
2360fcf3ce44SJohn Forte 		    (uint8_t)iocb->un.grsp.perr.statLocalError);
2361fcf3ce44SJohn Forte 	}
2362291a2b48SSukumar Swaminathan 
2363*82527734SSukumar Swaminathan 	switch (iocb->ULPCOMMAND) {
2364fcf3ce44SJohn Forte 		/* RING 0 FCP commands */
2365fcf3ce44SJohn Forte 	case CMD_FCP_ICMND_CR:
2366fcf3ce44SJohn Forte 	case CMD_FCP_ICMND_CX:
2367fcf3ce44SJohn Forte 	case CMD_FCP_IREAD_CR:
2368fcf3ce44SJohn Forte 	case CMD_FCP_IREAD_CX:
2369fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE_CR:
2370fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE_CX:
2371fcf3ce44SJohn Forte 	case CMD_FCP_ICMND64_CR:
2372fcf3ce44SJohn Forte 	case CMD_FCP_ICMND64_CX:
2373fcf3ce44SJohn Forte 	case CMD_FCP_IREAD64_CR:
2374fcf3ce44SJohn Forte 	case CMD_FCP_IREAD64_CX:
2375fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE64_CR:
2376fcf3ce44SJohn Forte 	case CMD_FCP_IWRITE64_CX:
2377*82527734SSukumar Swaminathan 		emlxs_handle_fcp_event(hba, cp, iocbq);
2378fcf3ce44SJohn Forte 		break;
2379fcf3ce44SJohn Forte 
2380fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
2381291a2b48SSukumar Swaminathan 	case CMD_FCP_TSEND_CX:		/* FCP_TARGET IOCB command */
2382fcf3ce44SJohn Forte 	case CMD_FCP_TSEND64_CX:	/* FCP_TARGET IOCB command */
2383fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE_CX:	/* FCP_TARGET IOCB command */
2384fcf3ce44SJohn Forte 	case CMD_FCP_TRECEIVE64_CX:	/* FCP_TARGET IOCB command */
2385291a2b48SSukumar Swaminathan 	case CMD_FCP_TRSP_CX:		/* FCP_TARGET IOCB command */
2386291a2b48SSukumar Swaminathan 	case CMD_FCP_TRSP64_CX:		/* FCP_TARGET IOCB command */
2387*82527734SSukumar Swaminathan 		(void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
2388fcf3ce44SJohn Forte 		break;
2389291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2390fcf3ce44SJohn Forte 
2391fcf3ce44SJohn Forte 		/* RING 1 IP commands */
2392fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CN:
2393fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST_CX:
2394fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CN:
2395fcf3ce44SJohn Forte 	case CMD_XMIT_BCAST64_CX:
2396*82527734SSukumar Swaminathan 		(void) emlxs_ip_handle_event(hba, cp, iocbq);
2397fcf3ce44SJohn Forte 		break;
2398fcf3ce44SJohn Forte 
2399fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CX:
2400fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE_CR:
2401fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CX:
2402fcf3ce44SJohn Forte 	case CMD_XMIT_SEQUENCE64_CR:
2403fcf3ce44SJohn Forte 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2404fcf3ce44SJohn Forte 		case FC_TYPE_IS8802_SNAP:
2405*82527734SSukumar Swaminathan 			(void) emlxs_ip_handle_event(hba, cp, iocbq);
2406fcf3ce44SJohn Forte 			break;
2407fcf3ce44SJohn Forte 
2408fcf3ce44SJohn Forte 		case FC_TYPE_FC_SERVICES:
2409*82527734SSukumar Swaminathan 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2410fcf3ce44SJohn Forte 			break;
2411fcf3ce44SJohn Forte 
2412fcf3ce44SJohn Forte 		default:
2413fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2414fcf3ce44SJohn Forte 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
2415*82527734SSukumar Swaminathan 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2416*82527734SSukumar Swaminathan 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2417*82527734SSukumar Swaminathan 			    iocb->ULPCONTEXT);
2418fcf3ce44SJohn Forte 		}
2419fcf3ce44SJohn Forte 		break;
2420fcf3ce44SJohn Forte 
2421fcf3ce44SJohn Forte 	case CMD_RCV_SEQUENCE_CX:
2422fcf3ce44SJohn Forte 	case CMD_RCV_SEQUENCE64_CX:
2423fcf3ce44SJohn Forte 	case CMD_RCV_SEQ64_CX:
2424fcf3ce44SJohn Forte 	case CMD_RCV_ELS_REQ_CX:	/* Unsolicited ELS frame  */
2425fcf3ce44SJohn Forte 	case CMD_RCV_ELS_REQ64_CX:	/* Unsolicited ELS frame  */
2426291a2b48SSukumar Swaminathan 	case CMD_RCV_ELS64_CX:		/* Unsolicited ELS frame  */
2427*82527734SSukumar Swaminathan 		if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
2428*82527734SSukumar Swaminathan 			(void) emlxs_handle_rcv_seq(hba, cp, iocbq);
2429*82527734SSukumar Swaminathan 		}
2430fcf3ce44SJohn Forte 		break;
2431fcf3ce44SJohn Forte 
2432fcf3ce44SJohn Forte 	case CMD_RCV_SEQ_LIST64_CX:
2433*82527734SSukumar Swaminathan 		(void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
2434fcf3ce44SJohn Forte 		break;
2435fcf3ce44SJohn Forte 
2436fcf3ce44SJohn Forte 	case CMD_CREATE_XRI_CR:
2437fcf3ce44SJohn Forte 	case CMD_CREATE_XRI_CX:
2438*82527734SSukumar Swaminathan 		(void) emlxs_handle_create_xri(hba, cp, iocbq);
2439fcf3ce44SJohn Forte 		break;
2440fcf3ce44SJohn Forte 
2441fcf3ce44SJohn Forte 		/* RING 2 ELS commands */
2442fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST_CR:
2443fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST_CX:
2444fcf3ce44SJohn Forte 	case CMD_XMIT_ELS_RSP_CX:
2445fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST64_CR:
2446fcf3ce44SJohn Forte 	case CMD_ELS_REQUEST64_CX:
2447fcf3ce44SJohn Forte 	case CMD_XMIT_ELS_RSP64_CX:
2448*82527734SSukumar Swaminathan 		(void) emlxs_els_handle_event(hba, cp, iocbq);
2449fcf3ce44SJohn Forte 		break;
2450fcf3ce44SJohn Forte 
2451fcf3ce44SJohn Forte 		/* RING 3 CT commands */
2452fcf3ce44SJohn Forte 	case CMD_GEN_REQUEST64_CR:
2453fcf3ce44SJohn Forte 	case CMD_GEN_REQUEST64_CX:
2454fcf3ce44SJohn Forte 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2455fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
2456fcf3ce44SJohn Forte 		case EMLXS_MENLO_TYPE:
2457*82527734SSukumar Swaminathan 			(void) emlxs_menlo_handle_event(hba, cp, iocbq);
2458fcf3ce44SJohn Forte 			break;
2459291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
2460fcf3ce44SJohn Forte 
2461fcf3ce44SJohn Forte 		case FC_TYPE_FC_SERVICES:
2462*82527734SSukumar Swaminathan 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2463fcf3ce44SJohn Forte 			break;
2464fcf3ce44SJohn Forte 
2465fcf3ce44SJohn Forte 		default:
2466fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2467fcf3ce44SJohn Forte 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
2468*82527734SSukumar Swaminathan 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2469*82527734SSukumar Swaminathan 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2470*82527734SSukumar Swaminathan 			    iocb->ULPCONTEXT);
2471fcf3ce44SJohn Forte 		}
2472fcf3ce44SJohn Forte 		break;
2473fcf3ce44SJohn Forte 
2474fcf3ce44SJohn Forte 	case CMD_ABORT_XRI_CN:	/* Abort fcp command */
2475fcf3ce44SJohn Forte 
2476fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2477fcf3ce44SJohn Forte 		    "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
2478fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
2479*82527734SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2480291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
2481fcf3ce44SJohn Forte 
2482291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
2483291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
2484*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2485291a2b48SSukumar Swaminathan 		}
2486291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2487fcf3ce44SJohn Forte 		break;
2488fcf3ce44SJohn Forte 
2489fcf3ce44SJohn Forte 	case CMD_ABORT_XRI_CX:	/* Abort command */
2490fcf3ce44SJohn Forte 
2491fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2492291a2b48SSukumar Swaminathan 		    "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
2493fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
2494*82527734SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2495291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm, iocbq->sbp);
2496fcf3ce44SJohn Forte 
2497291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
2498291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
2499*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2500291a2b48SSukumar Swaminathan 		}
2501291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2502fcf3ce44SJohn Forte 		break;
2503fcf3ce44SJohn Forte 
2504fcf3ce44SJohn Forte 	case CMD_XRI_ABORTED_CX:	/* Handle ABORT condition */
2505fcf3ce44SJohn Forte 
2506fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2507fcf3ce44SJohn Forte 		    "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x",
2508fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
2509*82527734SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2510291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
2511fcf3ce44SJohn Forte 
2512291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
2513291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
2514*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2515291a2b48SSukumar Swaminathan 		}
2516291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2517fcf3ce44SJohn Forte 		break;
2518fcf3ce44SJohn Forte 
2519fcf3ce44SJohn Forte 	case CMD_CLOSE_XRI_CN:	/* Handle CLOSE condition */
2520fcf3ce44SJohn Forte 
2521fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2522*82527734SSukumar Swaminathan 		    "CLOSE_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
2523fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
2524*82527734SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2525291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm);
2526fcf3ce44SJohn Forte 
2527291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
2528291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
2529*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2530291a2b48SSukumar Swaminathan 		}
2531291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2532fcf3ce44SJohn Forte 		break;
2533fcf3ce44SJohn Forte 
2534fcf3ce44SJohn Forte 	case CMD_CLOSE_XRI_CX:	/* Handle CLOSE condition */
2535fcf3ce44SJohn Forte 
2536fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2537291a2b48SSukumar Swaminathan 		    "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
2538fcf3ce44SJohn Forte 		    (uint32_t)iocb->un.acxri.abortContextTag,
2539*82527734SSukumar Swaminathan 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2540291a2b48SSukumar Swaminathan 		    iocb->un.acxri.parm, iocbq->sbp);
2541fcf3ce44SJohn Forte 
2542291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
2543291a2b48SSukumar Swaminathan 		if (port->tgt_mode) {
2544*82527734SSukumar Swaminathan 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2545291a2b48SSukumar Swaminathan 		}
2546291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2547fcf3ce44SJohn Forte 		break;
2548fcf3ce44SJohn Forte 
2549fcf3ce44SJohn Forte 	case CMD_ADAPTER_MSG:
2550fcf3ce44SJohn Forte 		/* Allows debug adapter firmware messages to print on host */
2551fcf3ce44SJohn Forte 		bzero(buffer, sizeof (buffer));
2552fcf3ce44SJohn Forte 		bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
2553fcf3ce44SJohn Forte 
2554fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
2555fcf3ce44SJohn Forte 
2556fcf3ce44SJohn Forte 		break;
2557fcf3ce44SJohn Forte 
2558fcf3ce44SJohn Forte 	case CMD_QUE_RING_LIST64_CN:
2559fcf3ce44SJohn Forte 	case CMD_QUE_RING_BUF64_CN:
2560fcf3ce44SJohn Forte 		break;
2561fcf3ce44SJohn Forte 
2562fcf3ce44SJohn Forte 	case CMD_ASYNC_STATUS:
2563*82527734SSukumar Swaminathan 		emlxs_handle_async_event(hba, cp, iocbq);
2564fcf3ce44SJohn Forte 		break;
2565fcf3ce44SJohn Forte 
2566fcf3ce44SJohn Forte 	default:
2567fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2568*82527734SSukumar Swaminathan 		    "cmd=%x status=%x iotag=%x context=%x", iocb->ULPCOMMAND,
2569*82527734SSukumar Swaminathan 		    iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
2570fcf3ce44SJohn Forte 
2571fcf3ce44SJohn Forte 		break;
2572*82527734SSukumar Swaminathan 	}	/* switch(entry->ULPCOMMAND) */
2573fcf3ce44SJohn Forte 
2574fcf3ce44SJohn Forte 	return;
2575fcf3ce44SJohn Forte 
2576*82527734SSukumar Swaminathan } /* emlxs_proc_channel_event() */
2577fcf3ce44SJohn Forte 
2578fcf3ce44SJohn Forte 
2579291a2b48SSukumar Swaminathan extern char *
2580291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state)
2581fcf3ce44SJohn Forte {
2582291a2b48SSukumar Swaminathan 	static char buffer[32];
2583291a2b48SSukumar Swaminathan 	uint32_t i;
2584291a2b48SSukumar Swaminathan 	uint32_t count;
2585fcf3ce44SJohn Forte 
2586291a2b48SSukumar Swaminathan 	count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
2587291a2b48SSukumar Swaminathan 	for (i = 0; i < count; i++) {
2588291a2b48SSukumar Swaminathan 		if (state == emlxs_ffstate_table[i].code) {
2589291a2b48SSukumar Swaminathan 			return (emlxs_ffstate_table[i].string);
2590fcf3ce44SJohn Forte 		}
2591fcf3ce44SJohn Forte 	}
2592fcf3ce44SJohn Forte 
2593291a2b48SSukumar Swaminathan 	(void) sprintf(buffer, "state=0x%x", state);
2594291a2b48SSukumar Swaminathan 	return (buffer);
2595fcf3ce44SJohn Forte 
2596*82527734SSukumar Swaminathan } /* emlxs_ffstate_xlate() */
2597fcf3ce44SJohn Forte 
2598fcf3ce44SJohn Forte 
2599fcf3ce44SJohn Forte extern char *
2600fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno)
2601fcf3ce44SJohn Forte {
2602fcf3ce44SJohn Forte 	static char buffer[32];
2603fcf3ce44SJohn Forte 	uint32_t i;
2604fcf3ce44SJohn Forte 	uint32_t count;
2605fcf3ce44SJohn Forte 
2606fcf3ce44SJohn Forte 	count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
2607fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
2608fcf3ce44SJohn Forte 		if (ringno == emlxs_ring_table[i].code) {
2609fcf3ce44SJohn Forte 			return (emlxs_ring_table[i].string);
2610fcf3ce44SJohn Forte 		}
2611fcf3ce44SJohn Forte 	}
2612fcf3ce44SJohn Forte 
2613fcf3ce44SJohn Forte 	(void) sprintf(buffer, "ring=0x%x", ringno);
2614fcf3ce44SJohn Forte 	return (buffer);
2615fcf3ce44SJohn Forte 
2616*82527734SSukumar Swaminathan } /* emlxs_ring_xlate() */
2617fcf3ce44SJohn Forte 
2618fcf3ce44SJohn Forte 
2619fcf3ce44SJohn Forte 
2620fcf3ce44SJohn Forte extern void
2621fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2622fcf3ce44SJohn Forte {
2623fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2624*82527734SSukumar Swaminathan 	MAILBOXQ *mbq;
2625fcf3ce44SJohn Forte 	MAILBOX *mb;
2626fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
2627fcf3ce44SJohn Forte 	uint32_t value;
2628fcf3ce44SJohn Forte 
2629fcf3ce44SJohn Forte 	cfg = &CFG;
2630fcf3ce44SJohn Forte 
2631fcf3ce44SJohn Forte xlate:
2632fcf3ce44SJohn Forte 
2633fcf3ce44SJohn Forte 	switch (cfg[CFG_PCI_MAX_READ].current) {
2634fcf3ce44SJohn Forte 	case 512:
2635fcf3ce44SJohn Forte 		value = 0;
2636fcf3ce44SJohn Forte 		break;
2637fcf3ce44SJohn Forte 
2638fcf3ce44SJohn Forte 	case 1024:
2639fcf3ce44SJohn Forte 		value = 1;
2640fcf3ce44SJohn Forte 		break;
2641fcf3ce44SJohn Forte 
2642fcf3ce44SJohn Forte 	case 2048:
2643fcf3ce44SJohn Forte 		value = 2;
2644fcf3ce44SJohn Forte 		break;
2645fcf3ce44SJohn Forte 
2646fcf3ce44SJohn Forte 	case 4096:
2647fcf3ce44SJohn Forte 		value = 3;
2648fcf3ce44SJohn Forte 		break;
2649fcf3ce44SJohn Forte 
2650fcf3ce44SJohn Forte 	default:
2651fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2652fcf3ce44SJohn Forte 		    "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
2653fcf3ce44SJohn Forte 		    cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
2654fcf3ce44SJohn Forte 
2655fcf3ce44SJohn Forte 		cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
2656fcf3ce44SJohn Forte 		goto xlate;
2657fcf3ce44SJohn Forte 	}
2658fcf3ce44SJohn Forte 
2659*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
2660fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2661fcf3ce44SJohn Forte 		    "PCI_MAX_READ: Unable to allocate mailbox buffer.");
2662fcf3ce44SJohn Forte 		return;
2663fcf3ce44SJohn Forte 	}
2664*82527734SSukumar Swaminathan 	mb = (MAILBOX *)mbq;
2665fcf3ce44SJohn Forte 
2666*82527734SSukumar Swaminathan 	emlxs_mb_set_var(hba, mbq, 0x00100506, value);
2667291a2b48SSukumar Swaminathan 
2668*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2669fcf3ce44SJohn Forte 		if (verbose || (mb->mbxStatus != 0x12)) {
2670fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2671291a2b48SSukumar Swaminathan 			    "PCI_MAX_READ: Unable to update. "
2672291a2b48SSukumar Swaminathan 			    "status=%x value=%d (%d bytes)",
2673291a2b48SSukumar Swaminathan 			    mb->mbxStatus, value,
2674fcf3ce44SJohn Forte 			    cfg[CFG_PCI_MAX_READ].current);
2675fcf3ce44SJohn Forte 		}
2676fcf3ce44SJohn Forte 	} else {
2677291a2b48SSukumar Swaminathan 		if (verbose &&
2678291a2b48SSukumar Swaminathan 		    (cfg[CFG_PCI_MAX_READ].current !=
2679fcf3ce44SJohn Forte 		    cfg[CFG_PCI_MAX_READ].def)) {
2680fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2681fcf3ce44SJohn Forte 			    "PCI_MAX_READ: Updated. %d bytes",
2682fcf3ce44SJohn Forte 			    cfg[CFG_PCI_MAX_READ].current);
2683fcf3ce44SJohn Forte 		}
2684fcf3ce44SJohn Forte 	}
2685fcf3ce44SJohn Forte 
2686*82527734SSukumar Swaminathan 	(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
2687fcf3ce44SJohn Forte 
2688fcf3ce44SJohn Forte 	return;
2689fcf3ce44SJohn Forte 
2690*82527734SSukumar Swaminathan } /* emlxs_pcix_mxr_update */
2691fcf3ce44SJohn Forte 
2692fcf3ce44SJohn Forte 
2693fcf3ce44SJohn Forte 
2694fcf3ce44SJohn Forte extern uint32_t
2695*82527734SSukumar Swaminathan emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
2696fcf3ce44SJohn Forte {
2697fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2698*82527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
2699fcf3ce44SJohn Forte 	uint32_t npname0, npname1;
2700fcf3ce44SJohn Forte 	uint32_t tmpkey, theKey;
2701fcf3ce44SJohn Forte 	uint16_t key850;
2702fcf3ce44SJohn Forte 	uint32_t t1, t2, t3, t4;
2703fcf3ce44SJohn Forte 	uint32_t ts;
2704fcf3ce44SJohn Forte 
2705fcf3ce44SJohn Forte #define	SEED 0x876EDC21
2706fcf3ce44SJohn Forte 
2707fcf3ce44SJohn Forte 	/* This key is only used currently for SBUS adapters */
2708fcf3ce44SJohn Forte 	if (hba->bus_type != SBUS_FC) {
2709fcf3ce44SJohn Forte 		return (0);
2710fcf3ce44SJohn Forte 	}
2711291a2b48SSukumar Swaminathan 
2712fcf3ce44SJohn Forte 	tmpkey = mb->un.varWords[30];
2713*82527734SSukumar Swaminathan 	EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
2714fcf3ce44SJohn Forte 
2715*82527734SSukumar Swaminathan 	emlxs_mb_read_nv(hba, mbq);
2716*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2717fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2718291a2b48SSukumar Swaminathan 		    "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
2719291a2b48SSukumar Swaminathan 		    mb->mbxStatus);
2720fcf3ce44SJohn Forte 
2721fcf3ce44SJohn Forte 		return (0);
2722fcf3ce44SJohn Forte 	}
2723fcf3ce44SJohn Forte 	npname0 = mb->un.varRDnvp.portname[0];
2724fcf3ce44SJohn Forte 	npname1 = mb->un.varRDnvp.portname[1];
2725fcf3ce44SJohn Forte 
2726fcf3ce44SJohn Forte 	key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
2727fcf3ce44SJohn Forte 	ts = (uint16_t)(npname1 + 1);
2728fcf3ce44SJohn Forte 	t1 = ts * key850;
2729fcf3ce44SJohn Forte 	ts = (uint16_t)((npname1 >> 16) + 1);
2730fcf3ce44SJohn Forte 	t2 = ts * key850;
2731fcf3ce44SJohn Forte 	ts = (uint16_t)(npname0 + 1);
2732fcf3ce44SJohn Forte 	t3 = ts * key850;
2733fcf3ce44SJohn Forte 	ts = (uint16_t)((npname0 >> 16) + 1);
2734fcf3ce44SJohn Forte 	t4 = ts * key850;
2735fcf3ce44SJohn Forte 	theKey = SEED + t1 + t2 + t3 + t4;
2736fcf3ce44SJohn Forte 
2737fcf3ce44SJohn Forte 	return (theKey);
2738fcf3ce44SJohn Forte 
2739*82527734SSukumar Swaminathan } /* emlxs_get_key() */
2740291a2b48SSukumar Swaminathan 
2741291a2b48SSukumar Swaminathan 
2742291a2b48SSukumar Swaminathan extern void
2743291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba)
2744291a2b48SSukumar Swaminathan {
2745291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2746291a2b48SSukumar Swaminathan 	uint32_t i;
2747291a2b48SSukumar Swaminathan 
2748291a2b48SSukumar Swaminathan 	/* Display firmware library one time */
2749*82527734SSukumar Swaminathan 	for (i = 0; i < emlxs_fw_count; i++) {
2750291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
2751291a2b48SSukumar Swaminathan 		    emlxs_fw_table[i].label);
2752291a2b48SSukumar Swaminathan 	}
2753291a2b48SSukumar Swaminathan 
2754291a2b48SSukumar Swaminathan 	return;
2755291a2b48SSukumar Swaminathan 
2756*82527734SSukumar Swaminathan } /* emlxs_fw_show() */
2757291a2b48SSukumar Swaminathan 
2758291a2b48SSukumar Swaminathan 
2759291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
2760*82527734SSukumar Swaminathan extern void
2761291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2762291a2b48SSukumar Swaminathan {
2763291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2764291a2b48SSukumar Swaminathan 	int (*emlxs_fw_get)(emlxs_firmware_t *);
2765291a2b48SSukumar Swaminathan 	int err;
2766291a2b48SSukumar Swaminathan 
2767291a2b48SSukumar Swaminathan 	/* Make sure image is unloaded and image buffer pointer is clear */
2768291a2b48SSukumar Swaminathan 	emlxs_fw_unload(hba, fw);
2769291a2b48SSukumar Swaminathan 
2770291a2b48SSukumar Swaminathan 	err = 0;
2771291a2b48SSukumar Swaminathan 	hba->fw_modhandle =
2772291a2b48SSukumar Swaminathan 	    ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
2773291a2b48SSukumar Swaminathan 	if (!hba->fw_modhandle) {
2774291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2775291a2b48SSukumar Swaminathan 		    "Unable to load firmware module. error=%d", err);
2776291a2b48SSukumar Swaminathan 
2777291a2b48SSukumar Swaminathan 		return;
2778291a2b48SSukumar Swaminathan 	} else {
2779291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2780291a2b48SSukumar Swaminathan 		    "Firmware module loaded.");
2781291a2b48SSukumar Swaminathan 	}
2782291a2b48SSukumar Swaminathan 
2783291a2b48SSukumar Swaminathan 	err = 0;
2784291a2b48SSukumar Swaminathan 	emlxs_fw_get =
2785291a2b48SSukumar Swaminathan 	    (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err);
2786291a2b48SSukumar Swaminathan 	if ((void *)emlxs_fw_get == NULL) {
2787291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2788291a2b48SSukumar Swaminathan 		    "emlxs_fw_get not present. error=%d", err);
2789291a2b48SSukumar Swaminathan 
2790291a2b48SSukumar Swaminathan 		emlxs_fw_unload(hba, fw);
2791291a2b48SSukumar Swaminathan 		return;
2792291a2b48SSukumar Swaminathan 	}
2793291a2b48SSukumar Swaminathan 
2794291a2b48SSukumar Swaminathan 	if (emlxs_fw_get(fw)) {
2795291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2796291a2b48SSukumar Swaminathan 		    "Invalid firmware image module found. %s", fw->label);
2797291a2b48SSukumar Swaminathan 
2798291a2b48SSukumar Swaminathan 		emlxs_fw_unload(hba, fw);
2799291a2b48SSukumar Swaminathan 		return;
2800291a2b48SSukumar Swaminathan 	}
2801291a2b48SSukumar Swaminathan 
2802291a2b48SSukumar Swaminathan 	return;
2803291a2b48SSukumar Swaminathan 
2804*82527734SSukumar Swaminathan } /* emlxs_fw_load() */
2805291a2b48SSukumar Swaminathan 
2806291a2b48SSukumar Swaminathan 
2807*82527734SSukumar Swaminathan extern void
2808291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2809291a2b48SSukumar Swaminathan {
2810291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
2811291a2b48SSukumar Swaminathan 
2812291a2b48SSukumar Swaminathan 	/* Clear the firmware image */
2813291a2b48SSukumar Swaminathan 	fw->image = NULL;
2814291a2b48SSukumar Swaminathan 	fw->size = 0;
2815291a2b48SSukumar Swaminathan 
2816291a2b48SSukumar Swaminathan 	if (hba->fw_modhandle) {
2817291a2b48SSukumar Swaminathan 		/* Close the module */
2818291a2b48SSukumar Swaminathan 		(void) ddi_modclose(hba->fw_modhandle);
2819291a2b48SSukumar Swaminathan 		hba->fw_modhandle = NULL;
2820291a2b48SSukumar Swaminathan 
2821291a2b48SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2822291a2b48SSukumar Swaminathan 		    "Firmware module unloaded.");
2823291a2b48SSukumar Swaminathan 	}
2824291a2b48SSukumar Swaminathan 
2825291a2b48SSukumar Swaminathan 	return;
2826291a2b48SSukumar Swaminathan 
2827*82527734SSukumar Swaminathan } /* emlxs_fw_unload() */
2828291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
2829