1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #define	EMLXS_FW_TABLE_DEF
29 #define	EMLXS_MODEL_DEF
30 
31 #include <emlxs.h>
32 
33 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34 EMLXS_MSG_DEF(EMLXS_HBA_C);
35 
36 
37 static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
38     IOCBQ *iocbq);
39 
40 static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
41 
42 #ifdef MSI_SUPPORT
43 uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
44 	{EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
45 uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
46 	{EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
47 	EMLXS_MSI0_MASK8};
48 #endif /* MSI_SUPPORT */
49 
50 emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
51 int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
52 
53 emlxs_table_t emlxs_pci_cap[] = {
54 	{PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
55 	{PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
56 	{PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
57 	{PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
58 	{PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
59 	{PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
60 	{PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
61 	{PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
62 	{PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
63 	{PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
64 	{PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
65 	{PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
66 	{PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
67 	{PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
68 	{PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
69 	{PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
70 	{PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
71 	{PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
72 	{PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
73 
74 }; /* emlxs_pci_cap */
75 
76 emlxs_table_t emlxs_ring_table[] = {
77 	{FC_FCP_RING, "FCP Ring"},
78 	{FC_IP_RING, "IP  Ring"},
79 	{FC_ELS_RING, "ELS Ring"},
80 	{FC_CT_RING, "CT  Ring"}
81 
82 }; /* emlxs_ring_table */
83 
84 emlxs_table_t emlxs_ffstate_table[] = {
85 	{0, "NULL"},
86 	{FC_ERROR, "ERROR"},
87 	{FC_KILLED, "KILLED"},
88 	{FC_WARM_START, "WARM_START"},
89 	{FC_INIT_START, "INIT_START"},
90 	{FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
91 	{FC_INIT_REV, "INIT_REV"},
92 	{FC_INIT_CFGPORT, "INIT_CFGPORT"},
93 	{FC_INIT_CFGRING, "INIT_CFGRING"},
94 	{FC_INIT_INITLINK, "INIT_INITLINK"},
95 	{FC_LINK_DOWN, "LINK_DOWN"},
96 	{FC_LINK_UP, "LINK_UP"},
97 	{FC_CLEAR_LA, "CLEAR_LA"},
98 	{FC_READY, "READY"}
99 
100 }; /* emlxs_ffstate_table */
101 
102 
103 #ifdef MSI_SUPPORT
104 /* EMLXS_INTR_INIT */
105 int32_t
106 emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
107 {
108 	emlxs_port_t *port = &PPORT;
109 	int32_t pass = 0;
110 	int32_t type = 0;
111 	char s_type[16];
112 	int32_t types;
113 	int32_t count;
114 	int32_t nintrs;
115 	int32_t mode;
116 	int32_t actual;
117 	int32_t new_actual;
118 	int32_t i;
119 	int32_t ret;
120 	ddi_intr_handle_t *htable = NULL;
121 	ddi_intr_handle_t *new_htable = NULL;
122 	uint32_t *intr_pri = NULL;
123 	int32_t *intr_cap = NULL;
124 	int32_t hilevel_pri;
125 	emlxs_config_t *cfg = &CFG;
126 	char buf[64];
127 
128 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
129 		return (emlxs_intx_init(hba, max));
130 	}
131 
132 	if (hba->intr_flags & EMLXS_MSI_INITED) {
133 		return (DDI_SUCCESS);
134 	}
135 
136 	/* Set max interrupt count if not specified */
137 	if (max == 0) {
138 		if ((cfg[CFG_MSI_MODE].current == 2) ||
139 		    (cfg[CFG_MSI_MODE].current == 3)) {
140 			max = EMLXS_MSI_MAX_INTRS;
141 		} else {
142 			max = 1;
143 		}
144 	}
145 
146 	/* Filter max interrupt count with adapter model specification */
147 	if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
148 		max = hba->model_info.intr_limit;
149 	}
150 
151 	/* Get the available interrupt types from the kernel */
152 	types = 0;
153 	ret = ddi_intr_get_supported_types(hba->dip, &types);
154 
155 	if ((ret != DDI_SUCCESS)) {
156 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
157 		    "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
158 
159 		/* Default to fixed type */
160 		types = DDI_INTR_TYPE_FIXED;
161 	}
162 
163 	/* Check if fixed interrupts are being forced */
164 	if (cfg[CFG_MSI_MODE].current == 0) {
165 		types &= DDI_INTR_TYPE_FIXED;
166 	}
167 
168 	/* Check if MSI interrupts are being forced */
169 	else if ((cfg[CFG_MSI_MODE].current == 1) ||
170 	    (cfg[CFG_MSI_MODE].current == 2)) {
171 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
172 	}
173 
174 begin:
175 
176 	/* Set interrupt type and interrupt count */
177 	type = 0;
178 
179 	/* Check if MSIX is fully supported */
180 	if ((types & DDI_INTR_TYPE_MSIX) &&
181 	    (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
182 		/* Get the max interrupt count from the adapter */
183 		nintrs = 0;
184 		ret =
185 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
186 		    &nintrs);
187 
188 		if (ret == DDI_SUCCESS && nintrs) {
189 			type = DDI_INTR_TYPE_MSIX;
190 			(void) strcpy(s_type, "TYPE_MSIX");
191 			goto initialize;
192 		}
193 	}
194 
195 	/* Check if MSI is fully supported */
196 	if ((types & DDI_INTR_TYPE_MSI) &&
197 	    (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
198 		/* Get the max interrupt count from the adapter */
199 		nintrs = 0;
200 		ret =
201 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
202 
203 		if (ret == DDI_SUCCESS && nintrs) {
204 			type = DDI_INTR_TYPE_MSI;
205 			(void) strcpy(s_type, "TYPE_MSI");
206 			goto initialize;
207 		}
208 	}
209 
210 	/* Check if fixed interrupts are fully supported */
211 	if ((types & DDI_INTR_TYPE_FIXED) &&
212 	    (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
213 		/* Get the max interrupt count from the adapter */
214 		nintrs = 0;
215 		ret =
216 		    ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
217 		    &nintrs);
218 
219 		if (ret == DDI_SUCCESS) {
220 			type = DDI_INTR_TYPE_FIXED;
221 			(void) strcpy(s_type, "TYPE_FIXED");
222 			goto initialize;
223 		}
224 	}
225 
226 	goto init_failed;
227 
228 
229 initialize:
230 
231 	pass++;
232 	mode = 0;
233 	actual = 0;
234 	htable = NULL;
235 	intr_pri = NULL;
236 	intr_cap = NULL;
237 	hilevel_pri = 0;
238 
239 	if (pass == 1) {
240 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
241 		    "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
242 		    cfg[CFG_MSI_MODE].current, types, nintrs);
243 	}
244 
245 	/* Validate interrupt count */
246 	count = min(nintrs, max);
247 
248 	if (count >= 8) {
249 		count = 8;
250 	} else if (count >= 4) {
251 		count = 4;
252 	} else if (count >= 2) {
253 		count = 2;
254 	} else {
255 		count = 1;
256 	}
257 
258 	/* Allocate an array of interrupt handles */
259 	htable =
260 	    kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
261 	    KM_SLEEP);
262 
263 	/* Allocate 'count' interrupts */
264 	ret =
265 	    ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
266 	    &actual, DDI_INTR_ALLOC_NORMAL);
267 
268 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
269 	    "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
270 
271 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
272 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
273 		    "MSI: Unable to allocate interrupts. error=%d", ret);
274 
275 		actual = 0;
276 		goto init_failed;
277 	}
278 
279 	if (actual != count) {
280 		/* Validate actual count */
281 		if (actual >= 8) {
282 			new_actual = 8;
283 		} else if (actual >= 4) {
284 			new_actual = 4;
285 		} else if (actual >= 2) {
286 			new_actual = 2;
287 		} else {
288 			new_actual = 1;
289 		}
290 
291 		if (new_actual < actual) {
292 			/* Free extra handles */
293 			for (i = new_actual; i < actual; i++) {
294 				(void) ddi_intr_free(htable[i]);
295 			}
296 
297 			actual = new_actual;
298 		}
299 
300 		/* Allocate a new array of interrupt handles */
301 		new_htable =
302 		    kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
303 		    KM_SLEEP);
304 
305 		/* Copy old array to new array */
306 		bcopy((uint8_t *)htable, (uint8_t *)new_htable,
307 		    (actual * sizeof (ddi_intr_handle_t)));
308 
309 		/* Free the old array */
310 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
311 
312 		htable = new_htable;
313 		count = actual;
314 	}
315 
316 	/* Allocate interrupt priority table */
317 	intr_pri =
318 	    (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
319 	    KM_SLEEP);
320 
321 	/* Allocate interrupt capability table */
322 	intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
323 
324 	/* Get minimum hilevel priority */
325 	hilevel_pri = ddi_intr_get_hilevel_pri();
326 
327 	/* Fill the priority and capability tables */
328 	for (i = 0; i < count; ++i) {
329 		ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
330 
331 		if (ret != DDI_SUCCESS) {
332 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
333 			    "MSI: ddi_intr_get_pri(%d) failed. "
334 			    "handle=%p ret=%d",
335 			    i, &htable[i], ret);
336 
337 			/* Clean up the interrupts */
338 			goto init_failed;
339 		}
340 
341 		if (intr_pri[i] >= hilevel_pri) {
342 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
343 			    "MSI: Interrupt(%d) level too high. "
344 			    "pri=0x%x hilevel=0x%x",
345 			    i, intr_pri[i], hilevel_pri);
346 
347 			/* Clean up the interrupts */
348 			goto init_failed;
349 		}
350 
351 		ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
352 
353 		if (ret != DDI_SUCCESS) {
354 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
355 			    "MSI: ddi_intr_get_cap(%d) failed. "
356 			    "handle=%p ret=%d",
357 			    i, &htable[i], ret);
358 
359 			/* Clean up the interrupts */
360 			goto init_failed;
361 		}
362 
363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
364 		    "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
365 		    intr_cap[i], intr_pri[i], hilevel_pri);
366 
367 	}
368 
369 	/* Set mode */
370 	switch (count) {
371 	case 8:
372 		mode = EMLXS_MSI_MODE8;
373 		break;
374 
375 	case 4:
376 		mode = EMLXS_MSI_MODE4;
377 		break;
378 
379 	case 2:
380 		mode = EMLXS_MSI_MODE2;
381 		break;
382 
383 	default:
384 		mode = EMLXS_MSI_MODE1;
385 	}
386 
387 	/* Save the info */
388 	hba->intr_htable = htable;
389 	hba->intr_count = count;
390 	hba->intr_pri = intr_pri;
391 	hba->intr_cap = intr_cap;
392 	hba->intr_type = type;
393 	hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
394 	hba->intr_mask = emlxs_msi_mask[mode];
395 
396 	hba->intr_cond = 0;
397 
398 	/* Adjust number of channels based on intr_count */
399 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
400 		hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
401 	}
402 
403 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
404 		hba->intr_map[i] = emlxs_msi_map[mode][i];
405 		hba->intr_cond |= emlxs_msi_map[mode][i];
406 
407 		(void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
408 		    hba->ddiinst, i);
409 		mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
410 		    DDI_INTR_PRI(hba->intr_arg));
411 	}
412 
413 	/* Set flag to indicate support */
414 	hba->intr_flags |= EMLXS_MSI_INITED;
415 
416 	/* Create the interrupt threads */
417 	for (i = 0; i < hba->chan_count; i++) {
418 		(void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
419 		    hba->ddiinst, i);
420 		mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
421 		    DDI_INTR_PRI(hba->intr_arg));
422 
423 		emlxs_thread_create(hba, &hba->chan[i].intr_thread);
424 	}
425 
426 	return (DDI_SUCCESS);
427 
428 init_failed:
429 
430 	if (intr_cap) {
431 		kmem_free(intr_cap, (count * sizeof (int32_t)));
432 	}
433 
434 	if (intr_pri) {
435 		kmem_free(intr_pri, (count * sizeof (int32_t)));
436 	}
437 
438 	if (htable) {
439 		/* Process the interrupt handlers */
440 		for (i = 0; i < actual; i++) {
441 			/* Free the handle[i] */
442 			(void) ddi_intr_free(htable[i]);
443 		}
444 
445 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
446 	}
447 
448 	/* Initialize */
449 	hba->intr_htable = NULL;
450 	hba->intr_count = 0;
451 	hba->intr_pri = NULL;
452 	hba->intr_cap = NULL;
453 	hba->intr_type = 0;
454 	hba->intr_arg = NULL;
455 	hba->intr_cond = 0;
456 	bzero(hba->intr_map, sizeof (hba->intr_map));
457 	bzero(hba->intr_lock, sizeof (hba->intr_lock));
458 
459 	if (type == DDI_INTR_TYPE_MSIX) {
460 		types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
461 		goto begin;
462 	} else if (type == DDI_INTR_TYPE_MSI) {
463 		types &= DDI_INTR_TYPE_FIXED;
464 		goto begin;
465 	}
466 
467 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
468 	    "MSI: Unable to initialize interrupts");
469 
470 	return (DDI_FAILURE);
471 
472 
473 } /* emlxs_msi_init() */
474 
475 
476 /* EMLXS_INTR_UNINIT */
477 int32_t
478 emlxs_msi_uninit(emlxs_hba_t *hba)
479 {
480 	uint32_t count;
481 	int32_t i;
482 	ddi_intr_handle_t *htable;
483 	uint32_t *intr_pri;
484 	int32_t *intr_cap;
485 	int32_t ret;
486 
487 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
488 		return (emlxs_intx_uninit(hba));
489 	}
490 
491 	/*
492 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
493 	 *    "MSI: emlxs_msi_uninit called. flags=%x",
494 	 *    hba->intr_flags);
495 	 */
496 
497 	/* Make sure interrupts have been removed first */
498 	if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
499 		ret = emlxs_msi_remove(hba);
500 
501 		if (ret != DDI_SUCCESS) {
502 			return (ret);
503 		}
504 	}
505 
506 	/* Check if the interrupts are still initialized */
507 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
508 		return (DDI_SUCCESS);
509 	}
510 	hba->intr_flags &= ~EMLXS_MSI_INITED;
511 
512 	/* Get handle table parameters */
513 	htable = hba->intr_htable;
514 	count = hba->intr_count;
515 	intr_pri = hba->intr_pri;
516 	intr_cap = hba->intr_cap;
517 
518 	/* Clean up */
519 	hba->intr_count = 0;
520 	hba->intr_htable = NULL;
521 	hba->intr_pri = NULL;
522 	hba->intr_cap = NULL;
523 	hba->intr_type = 0;
524 	hba->intr_arg = NULL;
525 	hba->intr_cond = 0;
526 	bzero(hba->intr_map, sizeof (hba->intr_map));
527 
528 	if (intr_cap) {
529 		kmem_free(intr_cap, (count * sizeof (int32_t)));
530 	}
531 
532 	if (intr_pri) {
533 		kmem_free(intr_pri, (count * sizeof (int32_t)));
534 	}
535 
536 	if (htable) {
537 		/* Process the interrupt handlers */
538 		for (i = 0; i < count; ++i) {
539 			/* Free the handle[i] */
540 			ret = ddi_intr_free(htable[i]);
541 		}
542 
543 		kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
544 	}
545 
546 	/* Destroy the intr locks */
547 	for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
548 		mutex_destroy(&hba->intr_lock[i]);
549 	}
550 
551 	/* Destroy the interrupt threads */
552 	for (i = 0; i < hba->chan_count; i++) {
553 		emlxs_thread_destroy(&hba->chan[i].intr_thread);
554 		mutex_destroy(&hba->chan[i].rsp_lock);
555 	}
556 
557 	/*
558 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
559 	 *    "MSI: emlxs_msi_uninit done. flags=%x",
560 	 *    hba->intr_flags);
561 	 */
562 
563 	return (DDI_SUCCESS);
564 
565 } /* emlxs_msi_uninit() */
566 
567 
568 /* EMLXS_INTR_ADD */
569 int32_t
570 emlxs_msi_add(emlxs_hba_t *hba)
571 {
572 	emlxs_port_t *port = &PPORT;
573 	int32_t count;
574 	int32_t i;
575 	int32_t ret;
576 	ddi_intr_handle_t *htable = NULL;
577 	int32_t *intr_cap = NULL;
578 
579 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
580 		return (emlxs_intx_add(hba));
581 	}
582 
583 	/* Check if interrupts have already been added */
584 	if (hba->intr_flags & EMLXS_MSI_ADDED) {
585 		return (DDI_SUCCESS);
586 	}
587 
588 	/* Check if interrupts have been initialized */
589 	if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
590 		ret = emlxs_msi_init(hba, 0);
591 
592 		if (ret != DDI_SUCCESS) {
593 			return (ret);
594 		}
595 	}
596 
597 	/* Get handle table parameters */
598 	htable = hba->intr_htable;
599 	count = hba->intr_count;
600 	intr_cap = hba->intr_cap;
601 
602 	/* Add the interrupt handlers */
603 	for (i = 0; i < count; ++i) {
604 		/* add handler for handle[i] */
605 		ret =
606 		    ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
607 		    (char *)hba, (char *)((unsigned long)i));
608 
609 		if (ret != DDI_SUCCESS) {
610 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
611 			    "MSI: ddi_intr_add_handler(%d) failed. "
612 			    "handle=%p ret=%d",
613 			    i, &htable[i], ret);
614 
615 			/* Process the remaining interrupt handlers */
616 			while (i) {
617 				/* Decrement i */
618 				i--;
619 
620 				/* Remove the handler */
621 				ret = ddi_intr_remove_handler(htable[i]);
622 
623 			}
624 
625 			return (DDI_FAILURE);
626 		}
627 	}
628 
629 	/* Enable the interrupts */
630 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
631 		ret = ddi_intr_block_enable(htable, count);
632 
633 		if (ret != DDI_SUCCESS) {
634 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
635 			    "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
636 			    count, ret);
637 
638 			for (i = 0; i < count; ++i) {
639 				ret = ddi_intr_enable(htable[i]);
640 
641 				if (ret != DDI_SUCCESS) {
642 					EMLXS_MSGF(EMLXS_CONTEXT,
643 					    &emlxs_init_debug_msg,
644 					    "MSI: ddi_intr_enable(%d) failed. "
645 					    "ret=%d",
646 					    i, ret);
647 				}
648 			}
649 		}
650 	} else {
651 		for (i = 0; i < count; ++i) {
652 			ret = ddi_intr_enable(htable[i]);
653 
654 			if (ret != DDI_SUCCESS) {
655 				EMLXS_MSGF(EMLXS_CONTEXT,
656 				    &emlxs_init_debug_msg,
657 				    "MSI: ddi_intr_enable(%d) failed. ret=%d",
658 				    i, ret);
659 			}
660 		}
661 	}
662 
663 
664 	/* Set flag to indicate support */
665 	hba->intr_flags |= EMLXS_MSI_ADDED;
666 
667 	return (DDI_SUCCESS);
668 
669 } /* emlxs_msi_add() */
670 
671 
672 
673 /* EMLXS_INTR_REMOVE */
674 int32_t
675 emlxs_msi_remove(emlxs_hba_t *hba)
676 {
677 	emlxs_port_t *port = &PPORT;
678 	uint32_t count;
679 	int32_t i;
680 	ddi_intr_handle_t *htable;
681 	int32_t *intr_cap;
682 	int32_t ret;
683 
684 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
685 		return (emlxs_intx_remove(hba));
686 	}
687 
688 	/*
689 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
690 	 *    "MSI: emlxs_msi_remove called. flags=%x",
691 	 *    hba->intr_flags);
692 	 */
693 
694 	/* Check if interrupts have already been removed */
695 	if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
696 		return (DDI_SUCCESS);
697 	}
698 	hba->intr_flags &= ~EMLXS_MSI_ADDED;
699 
700 	/* Disable all adapter interrupts */
701 	EMLXS_SLI_DISABLE_INTR(hba, 0);
702 
703 	/* Get handle table parameters */
704 	htable = hba->intr_htable;
705 	count = hba->intr_count;
706 	intr_cap = hba->intr_cap;
707 
708 	/* Disable the interrupts */
709 	if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
710 		ret = ddi_intr_block_disable(htable, count);
711 
712 		if (ret != DDI_SUCCESS) {
713 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
714 			    "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
715 			    count, ret);
716 
717 			for (i = 0; i < count; i++) {
718 				ret = ddi_intr_disable(htable[i]);
719 
720 				if (ret != DDI_SUCCESS) {
721 					EMLXS_MSGF(EMLXS_CONTEXT,
722 					    &emlxs_init_debug_msg,
723 					    "MSI: ddi_intr_disable(%d) failed. "
724 					    "ret=%d",
725 					    i, ret);
726 				}
727 			}
728 		}
729 	} else {
730 		for (i = 0; i < count; i++) {
731 			ret = ddi_intr_disable(htable[i]);
732 
733 			if (ret != DDI_SUCCESS) {
734 				EMLXS_MSGF(EMLXS_CONTEXT,
735 				    &emlxs_init_debug_msg,
736 				    "MSI: ddi_intr_disable(%d) failed. ret=%d",
737 				    i, ret);
738 			}
739 		}
740 	}
741 
742 	/* Process the interrupt handlers */
743 	for (i = 0; i < count; i++) {
744 		/* Remove the handler */
745 		ret = ddi_intr_remove_handler(htable[i]);
746 
747 
748 	}
749 
750 	return (DDI_SUCCESS);
751 
752 } /* emlxs_msi_remove() */
753 
754 #endif /* MSI_SUPPORT */
755 
756 
757 /* EMLXS_INTR_INIT */
758 /* ARGSUSED */
759 int32_t
760 emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
761 {
762 	emlxs_port_t *port = &PPORT;
763 	emlxs_config_t *cfg = &CFG;
764 	int32_t ret;
765 	uint32_t i;
766 	char buf[64];
767 
768 	/* Check if interrupts have already been initialized */
769 	if (hba->intr_flags & EMLXS_INTX_INITED) {
770 		return (DDI_SUCCESS);
771 	}
772 
773 	/* Check if adapter is flagged for INTX support */
774 	if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
776 		    "INTX: %s does not support INTX.  flags=0x%x",
777 		    hba->model_info.model, hba->model_info.flags);
778 
779 		return (DDI_FAILURE);
780 	}
781 
782 	/*
783 	 * Interrupt number '0' is a high-level interrupt. This driver
784 	 * does not support having its interrupts mapped above scheduler
785 	 * priority; i.e., we always expect to be able to call general
786 	 * kernel routines that may invoke the scheduler.
787 	 */
788 	if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
790 		    "INTX: High-level interrupt not supported.");
791 
792 		return (DDI_FAILURE);
793 	}
794 
795 	/* Get an iblock cookie */
796 	ret =
797 	    ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
798 	    (ddi_iblock_cookie_t *)&hba->intr_arg);
799 	if (ret != DDI_SUCCESS) {
800 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
801 		    "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
802 
803 		return (ret);
804 	}
805 
806 	hba->intr_flags |= EMLXS_INTX_INITED;
807 
808 	hba->intr_count = 1;
809 	/* Adjust number of channels based on intr_count */
810 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
811 		hba->chan_count = cfg[CFG_NUM_WQ].current;
812 	}
813 
814 	/* Create the interrupt threads */
815 	for (i = 0; i < hba->chan_count; i++) {
816 		(void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
817 		    hba->ddiinst, i);
818 		mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
819 		    DDI_INTR_PRI(hba->intr_arg));
820 
821 		emlxs_thread_create(hba, &hba->chan[i].intr_thread);
822 	}
823 
824 	return (DDI_SUCCESS);
825 
826 } /* emlxs_intx_init() */
827 
828 
829 /* EMLXS_INTR_UNINIT */
830 int32_t
831 emlxs_intx_uninit(emlxs_hba_t *hba)
832 {
833 	int32_t ret;
834 	uint32_t i;
835 
836 	/* Make sure interrupts have been removed */
837 	if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
838 		ret = emlxs_intx_remove(hba);
839 
840 		if (ret != DDI_SUCCESS) {
841 			return (ret);
842 		}
843 	}
844 
845 	/* Check if the interrupts are still initialized */
846 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
847 		return (DDI_SUCCESS);
848 	}
849 	hba->intr_flags &= ~EMLXS_INTX_INITED;
850 
851 	hba->intr_arg = NULL;
852 
853 	/* Create the interrupt threads */
854 	for (i = 0; i < hba->chan_count; i++) {
855 		emlxs_thread_destroy(&hba->chan[i].intr_thread);
856 		mutex_destroy(&hba->chan[i].rsp_lock);
857 	}
858 
859 	return (DDI_SUCCESS);
860 
861 } /* emlxs_intx_uninit() */
862 
863 
864 /*
865  * This is the legacy method for adding interrupts in Solaris
866  * EMLXS_INTR_ADD
867  */
868 int32_t
869 emlxs_intx_add(emlxs_hba_t *hba)
870 {
871 	emlxs_port_t *port = &PPORT;
872 	int32_t ret;
873 
874 	/* Check if interrupts have already been added */
875 	if (hba->intr_flags & EMLXS_INTX_ADDED) {
876 		return (DDI_SUCCESS);
877 	}
878 
879 	/* Check if interrupts have been initialized */
880 	if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
881 		ret = emlxs_intx_init(hba, 0);
882 
883 		if (ret != DDI_SUCCESS) {
884 			return (ret);
885 		}
886 	}
887 
888 	/* add intrrupt handler routine */
889 	ret = ddi_add_intr((void *)hba->dip,
890 	    (uint_t)EMLXS_INUMBER,
891 	    (ddi_iblock_cookie_t *)&hba->intr_arg,
892 	    (ddi_idevice_cookie_t *)0,
893 	    (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
894 
895 	if (ret != DDI_SUCCESS) {
896 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
897 		    "INTX: ddi_add_intr failed. ret=%d", ret);
898 
899 		return (ret);
900 	}
901 
902 	hba->intr_flags |= EMLXS_INTX_ADDED;
903 
904 	return (DDI_SUCCESS);
905 
906 } /* emlxs_intx_add() */
907 
908 
909 /* EMLXS_INTR_REMOVE */
910 int32_t
911 emlxs_intx_remove(emlxs_hba_t *hba)
912 {
913 	/* Check if interrupts have already been removed */
914 	if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
915 		return (DDI_SUCCESS);
916 	}
917 	hba->intr_flags &= ~EMLXS_INTX_ADDED;
918 
919 	/* Diable all adapter interrupts */
920 	EMLXS_SLI_DISABLE_INTR(hba, 0);
921 
922 	/* Remove the interrupt */
923 	(void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
924 	    hba->intr_arg);
925 
926 	return (DDI_SUCCESS);
927 
928 } /* emlxs_intx_remove() */
929 
930 
931 extern void
932 emlxs_process_link_speed(emlxs_hba_t *hba)
933 {
934 	emlxs_vpd_t *vpd;
935 	emlxs_config_t *cfg;
936 	char *cptr;
937 	uint32_t hi;
938 
939 	/*
940 	 * This routine modifies the link-speed config parameter entry
941 	 * based on adapter capabilities
942 	 */
943 	vpd = &VPD;
944 	cfg = &hba->config[CFG_LINK_SPEED];
945 
946 	cptr = cfg->help;
947 	(void) strcpy(cptr, "Select link speed. [0=Auto");
948 	cptr += 26;
949 	hi = 0;
950 
951 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
952 		(void) strcpy(cptr, ", 1=1Gb");
953 		cptr += 7;
954 		hi = 1;
955 	}
956 
957 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
958 		(void) strcpy(cptr, ", 2=2Gb");
959 		cptr += 7;
960 		hi = 2;
961 	}
962 
963 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
964 		(void) strcpy(cptr, ", 4=4Gb");
965 		cptr += 7;
966 		hi = 4;
967 	}
968 
969 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
970 		(void) strcpy(cptr, ", 8=8Gb");
971 		cptr += 7;
972 		hi = 8;
973 	}
974 
975 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
976 		(void) strcpy(cptr, ", 10=10Gb");
977 		cptr += 9;
978 		hi = 10;
979 	}
980 
981 	(void) strcpy(cptr, "]");
982 	cfg->hi = hi;
983 
984 	/* Now revalidate the current parameter setting */
985 	cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
986 
987 	return;
988 
989 } /* emlxs_process_link_speed() */
990 
991 
992 /*
993  * emlxs_parse_vpd()
994  *
995  * This routine will parse the VPD data
996  */
997 extern int
998 emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
999 {
1000 	emlxs_port_t *port = &PPORT;
1001 	char tag[3];
1002 	uint8_t lenlo, lenhi;
1003 	uint32_t n;
1004 	uint16_t block_size;
1005 	uint32_t block_index = 0;
1006 	uint8_t sub_size;
1007 	uint32_t sub_index;
1008 	int32_t finished = 0;
1009 	int32_t index = 0;
1010 	char buffer[128];
1011 	emlxs_vpd_t *vpd;
1012 
1013 	vpd = &VPD;
1014 
1015 
1016 	while (!finished && (block_index < size)) {
1017 		/*
1018 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1019 		 *    "block_index = %x", block_index);
1020 		 */
1021 
1022 		switch (vpd_buf[block_index]) {
1023 		case 0x82:
1024 			index = block_index;
1025 			index += 1;
1026 			lenlo = vpd_buf[index];
1027 			index += 1;
1028 			lenhi = vpd_buf[index];
1029 			index += 1;
1030 			block_index = index;
1031 
1032 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1033 			block_index += block_size;
1034 
1035 			/*
1036 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1037 			 *    "block_size = %x", block_size);
1038 			 */
1039 
1040 			n = sizeof (buffer);
1041 			bzero(buffer, n);
1042 			bcopy(&vpd_buf[index], buffer,
1043 			    (block_size < (n - 1)) ? block_size : (n - 1));
1044 
1045 			(void) strcpy(vpd->id, buffer);
1046 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
1047 			    vpd->id);
1048 
1049 			break;
1050 
1051 		case 0x90:
1052 			index = block_index;
1053 			index += 1;
1054 			lenlo = vpd_buf[index];
1055 			index += 1;
1056 			lenhi = vpd_buf[index];
1057 			index += 1;
1058 			block_index = index;
1059 			sub_index = index;
1060 
1061 			block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1062 			block_index += block_size;
1063 
1064 			/*
1065 			 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1066 			 *    "block_size = %x", block_size);
1067 			 */
1068 
1069 			/* Scan for sub-blocks */
1070 			while ((sub_index < block_index) &&
1071 			    (sub_index < size)) {
1072 				/*
1073 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1074 				 *    "sub_index = %x", sub_index);
1075 				 */
1076 
1077 				index = sub_index;
1078 				tag[0] = vpd_buf[index++];
1079 				tag[1] = vpd_buf[index++];
1080 				tag[2] = 0;
1081 				sub_size = vpd_buf[index++];
1082 
1083 				/*
1084 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1085 				 *    "sub_size = %x", sub_size);
1086 				 */
1087 
1088 				sub_index = (index + sub_size);
1089 
1090 				n = sizeof (buffer);
1091 				bzero(buffer, n);
1092 				bcopy(&vpd_buf[index], buffer,
1093 				    (sub_size < (n - 1)) ? sub_size : (n - 1));
1094 
1095 				/*
1096 				 * Look for Engineering Change (EC)
1097 				 */
1098 				if (strcmp(tag, "EC") == 0) {
1099 					(void) strcpy(vpd->eng_change, buffer);
1100 					EMLXS_MSGF(EMLXS_CONTEXT,
1101 					    &emlxs_vpd_msg, "EC: %s",
1102 					    vpd->eng_change);
1103 				}
1104 				/*
1105 				 * Look for Manufacturer (MN)
1106 				 */
1107 				else if (strcmp(tag, "MN") == 0) {
1108 					(void) strcpy(vpd->manufacturer,
1109 					    buffer);
1110 					EMLXS_MSGF(EMLXS_CONTEXT,
1111 					    &emlxs_vpd_msg, "MN: %s",
1112 					    vpd->manufacturer);
1113 				}
1114 				/*
1115 				 * Look for Serial Number (SN)
1116 				 */
1117 				else if (strcmp(tag, "SN") == 0) {
1118 					(void) strcpy(vpd->serial_num, buffer);
1119 					EMLXS_MSGF(EMLXS_CONTEXT,
1120 					    &emlxs_vpd_msg, "SN: %s",
1121 					    vpd->serial_num);
1122 
1123 					/* Validate the serial number */
1124 					if (strncmp(buffer, "FFFFFFFFFF", 10) ==
1125 					    0 ||
1126 					    strncmp(buffer, "0000000000", 10) ==
1127 					    0) {
1128 						vpd->serial_num[0] = 0;
1129 					}
1130 				}
1131 				/*
1132 				 * Look for Part Number (PN)
1133 				 */
1134 				else if (strcmp(tag, "PN") == 0) {
1135 					(void) strcpy(vpd->part_num, buffer);
1136 					EMLXS_MSGF(EMLXS_CONTEXT,
1137 					    &emlxs_vpd_msg, "PN: %s",
1138 					    vpd->part_num);
1139 				}
1140 				/*
1141 				 * Look for (V0)
1142 				 */
1143 				else if (strcmp(tag, "V0") == 0) {
1144 					/* Not used */
1145 					EMLXS_MSGF(EMLXS_CONTEXT,
1146 					    &emlxs_vpd_msg, "V0: %s", buffer);
1147 				}
1148 				/*
1149 				 * Look for model description (V1)
1150 				 */
1151 				else if (strcmp(tag, "V1") == 0) {
1152 					(void) strcpy(vpd->model_desc, buffer);
1153 					EMLXS_MSGF(EMLXS_CONTEXT,
1154 					    &emlxs_vpd_msg, "Desc: %s",
1155 					    vpd->model_desc);
1156 				}
1157 				/*
1158 				 * Look for model (V2)
1159 				 */
1160 				else if (strcmp(tag, "V2") == 0) {
1161 					(void) strcpy(vpd->model, buffer);
1162 					EMLXS_MSGF(EMLXS_CONTEXT,
1163 					    &emlxs_vpd_msg, "Model: %s",
1164 					    vpd->model);
1165 				}
1166 				/*
1167 				 * Look for program type (V3)
1168 				 */
1169 
1170 				else if (strcmp(tag, "V3") == 0) {
1171 					(void) strcpy(vpd->prog_types, buffer);
1172 					EMLXS_MSGF(EMLXS_CONTEXT,
1173 					    &emlxs_vpd_msg, "Prog Types: %s",
1174 					    vpd->prog_types);
1175 				}
1176 				/*
1177 				 * Look for port number (V4)
1178 				 */
1179 				else if (strcmp(tag, "V4") == 0) {
1180 					(void) strcpy(vpd->port_num, buffer);
1181 					vpd->port_index =
1182 					    emlxs_strtol(vpd->port_num, 10);
1183 
1184 					EMLXS_MSGF(EMLXS_CONTEXT,
1185 					    &emlxs_vpd_msg, "Port: %s",
1186 					    (vpd->port_num[0]) ? vpd->
1187 					    port_num : "not applicable");
1188 				}
1189 				/*
1190 				 * Look for checksum (RV)
1191 				 */
1192 				else if (strcmp(tag, "RV") == 0) {
1193 					/* Not used */
1194 					EMLXS_MSGF(EMLXS_CONTEXT,
1195 					    &emlxs_vpd_msg, "Checksum: 0x%x",
1196 					    buffer[0]);
1197 				}
1198 
1199 				else {
1200 					/* Generic */
1201 					EMLXS_MSGF(EMLXS_CONTEXT,
1202 					    &emlxs_vpd_msg, "Tag: %s: %s",
1203 					    tag, buffer);
1204 				}
1205 			}
1206 
1207 			break;
1208 
1209 		case 0x78:
1210 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
1211 			finished = 1;
1212 			break;
1213 
1214 		default:
1215 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1216 			    "Unknown block: %x %x %x %x %x %x %x %x",
1217 			    vpd_buf[index], vpd_buf[index + 1],
1218 			    vpd_buf[index + 2], vpd_buf[index + 3],
1219 			    vpd_buf[index + 4], vpd_buf[index + 5],
1220 			    vpd_buf[index + 6], vpd_buf[index + 7]);
1221 			return (0);
1222 		}
1223 	}
1224 
1225 	return (1);
1226 
1227 } /* emlxs_parse_vpd */
1228 
1229 
1230 /*
1231  * emlxs_parse_fcoe()
1232  *
1233  * This routine will parse the VPD data
1234  */
1235 extern int
1236 emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
1237 {
1238 	emlxs_port_t *port = &PPORT;
1239 	tlv_fcoe_t *fcoelist;
1240 	tlv_fcfconnectlist_t *fcflist;
1241 	int i;
1242 
1243 	/* Validate the config region 23 signature */
1244 	if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
1245 	    (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
1246 		return (0);
1247 	}
1248 
1249 	/* Search the config region 23, for FCOE Parameters record */
1250 	i = 4;
1251 	while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
1252 		i += fcoep[i+1] * sizeof (uint32_t) + 2;
1253 	}
1254 
1255 	if (*(fcoep+i) == 0xA0) {
1256 		fcoelist = (tlv_fcoe_t *)(fcoep+i);
1257 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1258 		    "Found FCOE Params (A0):%d  x%x",
1259 		    fcoelist->length, fcoelist->fip_flags);
1260 		bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
1261 		    sizeof (tlv_fcoe_t));
1262 	}
1263 
1264 
1265 	/* Search the config region 23, for FCF record */
1266 	i = 4;
1267 	while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
1268 		i += fcoep[i+1] * sizeof (uint32_t) + 2;
1269 	}
1270 
1271 	if (*(fcoep+i) == 0xA1) {
1272 		fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
1273 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1274 		    "Found FCF ConnectList (A1):%d", fcflist->length);
1275 		bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
1276 		    sizeof (tlv_fcfconnectlist_t));
1277 	}
1278 
1279 	return (1);
1280 
1281 } /* emlxs_parse_fcoe */
1282 
1283 
1284 extern void
1285 emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1286 {
1287 	if (vpd->rBit) {
1288 		switch (hba->sli_mode) {
1289 		case EMLXS_HBA_SLI4_MODE:
1290 			(void) strcpy(vpd->fw_version, vpd->sli4FwName);
1291 			(void) strcpy(vpd->fw_label, vpd->sli4FwLabel);
1292 			break;
1293 		case EMLXS_HBA_SLI3_MODE:
1294 			(void) strcpy(vpd->fw_version, vpd->sli3FwName);
1295 			(void) strcpy(vpd->fw_label, vpd->sli3FwLabel);
1296 			break;
1297 		case EMLXS_HBA_SLI2_MODE:
1298 			(void) strcpy(vpd->fw_version, vpd->sli2FwName);
1299 			(void) strcpy(vpd->fw_label, vpd->sli2FwLabel);
1300 			break;
1301 		case EMLXS_HBA_SLI1_MODE:
1302 			(void) strcpy(vpd->fw_version, vpd->sli1FwName);
1303 			(void) strcpy(vpd->fw_label, vpd->sli1FwLabel);
1304 			break;
1305 		default:
1306 			(void) strcpy(vpd->fw_version, "unknown");
1307 			(void) strcpy(vpd->fw_label, vpd->fw_version);
1308 		}
1309 	} else {
1310 		emlxs_decode_version(vpd->smFwRev, vpd->fw_version);
1311 		(void) strcpy(vpd->fw_label, vpd->fw_version);
1312 	}
1313 
1314 	return;
1315 
1316 } /* emlxs_decode_firmware_rev() */
1317 
1318 
1319 
1320 extern void
1321 emlxs_decode_version(uint32_t version, char *buffer)
1322 {
1323 	uint32_t b1, b2, b3, b4;
1324 	char c;
1325 
1326 	b1 = (version & 0x0000f000) >> 12;
1327 	b2 = (version & 0x00000f00) >> 8;
1328 	b3 = (version & 0x000000c0) >> 6;
1329 	b4 = (version & 0x00000030) >> 4;
1330 
1331 	if (b1 == 0 && b2 == 0) {
1332 		(void) sprintf(buffer, "none");
1333 		return;
1334 	}
1335 
1336 	c = 0;
1337 	switch (b4) {
1338 	case 0:
1339 		c = 'n';
1340 		break;
1341 	case 1:
1342 		c = 'a';
1343 		break;
1344 	case 2:
1345 		c = 'b';
1346 		break;
1347 	case 3:
1348 		if ((version & 0x0000000f)) {
1349 			c = 'x';
1350 		}
1351 		break;
1352 
1353 	}
1354 	b4 = (version & 0x0000000f);
1355 
1356 	if (c == 0) {
1357 		(void) sprintf(buffer, "%d.%d%d", b1, b2, b3);
1358 	} else {
1359 		(void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4);
1360 	}
1361 
1362 	return;
1363 
1364 } /* emlxs_decode_version() */
1365 
1366 
1367 extern void
1368 emlxs_decode_label(char *label, char *buffer, int bige)
1369 {
1370 	uint32_t i;
1371 	char name[16];
1372 
1373 	bcopy(label, name, sizeof (name));
1374 	/* bige is TRUE if the data format is big endian */
1375 
1376 	if (bige) {
1377 		/* Data format big Endian */
1378 		LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1379 
1380 		for (i = 0; i < sizeof (name); i++) {
1381 			if (name[i] == 0x20) {
1382 				name[i] = 0;
1383 			}
1384 		}
1385 	} else {
1386 		/* Data format little Endian */
1387 		BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1388 
1389 		for (i = 0; i < sizeof (name); i++) {
1390 			if (name[i] == 0x20) {
1391 				name[i] = 0;
1392 			}
1393 		}
1394 	}
1395 
1396 	(void) strcpy(buffer, name);
1397 
1398 	return;
1399 
1400 } /* emlxs_decode_label() */
1401 
1402 
1403 extern uint32_t
1404 emlxs_strtol(char *str, uint32_t base)
1405 {
1406 	uint32_t value = 0;
1407 	char *ptr;
1408 	uint32_t factor = 1;
1409 	uint32_t digits;
1410 
1411 	if (*str == 0) {
1412 		return (0);
1413 	}
1414 
1415 	if (base != 10 && base != 16) {
1416 		return (0);
1417 	}
1418 
1419 	/* Get max digits of value */
1420 	digits = (base == 10) ? 9 : 8;
1421 
1422 	/* Position pointer to end of string */
1423 	ptr = str + strlen(str);
1424 
1425 	/* Process string backwards */
1426 	while ((ptr-- > str) && digits) {
1427 		/* check for base 10 numbers */
1428 		if (*ptr >= '0' && *ptr <= '9') {
1429 			value += ((uint32_t)(*ptr - '0')) * factor;
1430 			factor *= base;
1431 			digits--;
1432 		} else if (base == 16) {
1433 			/* Check for base 16 numbers */
1434 			if (*ptr >= 'a' && *ptr <= 'f') {
1435 				value +=
1436 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
1437 				factor *= base;
1438 				digits--;
1439 			} else if (*ptr >= 'A' && *ptr <= 'F') {
1440 				value +=
1441 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
1442 				factor *= base;
1443 				digits--;
1444 			} else if (factor > 1) {
1445 				break;
1446 			}
1447 		} else if (factor > 1) {
1448 			break;
1449 		}
1450 	}
1451 
1452 	return (value);
1453 
1454 } /* emlxs_strtol() */
1455 
1456 
1457 extern uint64_t
1458 emlxs_strtoll(char *str, uint32_t base)
1459 {
1460 	uint64_t value = 0;
1461 	char *ptr;
1462 	uint32_t factor = 1;
1463 	uint32_t digits;
1464 
1465 	if (*str == 0) {
1466 		return (0);
1467 	}
1468 
1469 	if (base != 10 && base != 16) {
1470 		return (0);
1471 	}
1472 
1473 	/* Get max digits of value */
1474 	digits = (base == 10) ? 19 : 16;
1475 
1476 	/* Position pointer to end of string */
1477 	ptr = str + strlen(str);
1478 
1479 	/* Process string backwards */
1480 	while ((ptr-- > str) && digits) {
1481 		/* check for base 10 numbers */
1482 		if (*ptr >= '0' && *ptr <= '9') {
1483 			value += ((uint32_t)(*ptr - '0')) * factor;
1484 			factor *= base;
1485 			digits--;
1486 		} else if (base == 16) {
1487 			/* Check for base 16 numbers */
1488 			if (*ptr >= 'a' && *ptr <= 'f') {
1489 				value +=
1490 				    ((uint32_t)(*ptr - 'a') + 10) * factor;
1491 				factor *= base;
1492 				digits--;
1493 			} else if (*ptr >= 'A' && *ptr <= 'F') {
1494 				value +=
1495 				    ((uint32_t)(*ptr - 'A') + 10) * factor;
1496 				factor *= base;
1497 				digits--;
1498 			} else if (factor > 1) {
1499 				break;
1500 			}
1501 		} else if (factor > 1) {
1502 			break;
1503 		}
1504 	}
1505 
1506 	return (value);
1507 
1508 } /* emlxs_strtoll() */
1509 
1510 extern void
1511 emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
1512 {
1513 	emlxs_port_t *port = &PPORT;
1514 	uint32_t i;
1515 	char *ptr;
1516 	emlxs_model_t *model;
1517 	char types_buffer[256];
1518 	char *types;
1519 
1520 	bcopy(prog_types, types_buffer, 256);
1521 	types = types_buffer;
1522 
1523 	model = &hba->model_info;
1524 
1525 	while (*types) {
1526 		if (strncmp(types, "T2:", 3) == 0) {
1527 			bzero(model->pt_2, sizeof (model->pt_2));
1528 			types += 3;
1529 
1530 			i = 0;
1531 			while (*types && *types != 'T') {
1532 				/* Null terminate the next value */
1533 				ptr = types;
1534 				while (*ptr && (*ptr != ','))
1535 					ptr++;
1536 				*ptr = 0;
1537 
1538 				/* Save the value */
1539 				model->pt_2[i++] =
1540 				    (uint8_t)emlxs_strtol(types, 16);
1541 
1542 				/*
1543 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1544 				 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
1545 				 */
1546 
1547 				/* Move the str pointer */
1548 				types = ptr + 1;
1549 			}
1550 
1551 		} else if (strncmp(types, "T3:", 3) == 0) {
1552 			bzero(model->pt_3, sizeof (model->pt_3));
1553 			types += 3;
1554 
1555 			i = 0;
1556 			while (*types && *types != 'T') {
1557 				/* Null terminate the next value */
1558 				ptr = types;
1559 				while (*ptr && (*ptr != ','))
1560 					ptr++;
1561 				*ptr = 0;
1562 
1563 				/* Save the value */
1564 				model->pt_3[i++] =
1565 				    (uint8_t)emlxs_strtol(types, 16);
1566 
1567 				/*
1568 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1569 				 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
1570 				 */
1571 
1572 				/* Move the str pointer */
1573 				types = ptr + 1;
1574 			}
1575 		} else if (strncmp(types, "T6:", 3) == 0) {
1576 			bzero(model->pt_6, sizeof (model->pt_6));
1577 			types += 3;
1578 
1579 			i = 0;
1580 			while (*types && *types != 'T') {
1581 				/* Null terminate the next value */
1582 				ptr = types;
1583 				while (*ptr && (*ptr != ','))
1584 					ptr++;
1585 				*ptr = 0;
1586 
1587 				/* Save the value */
1588 				model->pt_6[i++] =
1589 				    (uint8_t)emlxs_strtol(types, 16);
1590 				model->pt_6[i] = 0;
1591 
1592 				/*
1593 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1594 				 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
1595 				 */
1596 
1597 				/* Move the str pointer */
1598 				types = ptr + 1;
1599 			}
1600 		} else if (strncmp(types, "T7:", 3) == 0) {
1601 			bzero(model->pt_7, sizeof (model->pt_7));
1602 			types += 3;
1603 
1604 			i = 0;
1605 			while (*types && *types != 'T') {
1606 				/* Null terminate the next value */
1607 				ptr = types;
1608 				while (*ptr && (*ptr != ','))
1609 					ptr++;
1610 				*ptr = 0;
1611 
1612 				/* Save the value */
1613 				model->pt_7[i++] =
1614 				    (uint8_t)emlxs_strtol(types, 16);
1615 				model->pt_7[i] = 0;
1616 
1617 				/*
1618 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1619 				 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
1620 				 */
1621 
1622 				/* Move the str pointer */
1623 				types = ptr + 1;
1624 			}
1625 		} else if (strncmp(types, "TA:", 3) == 0) {
1626 			bzero(model->pt_A, sizeof (model->pt_A));
1627 			types += 3;
1628 
1629 			i = 0;
1630 			while (*types && *types != 'T') {
1631 				/* Null terminate the next value */
1632 				ptr = types;
1633 				while (*ptr && (*ptr != ','))
1634 					ptr++;
1635 				*ptr = 0;
1636 
1637 				/* Save the value */
1638 				model->pt_A[i++] =
1639 				    (uint8_t)emlxs_strtol(types, 16);
1640 
1641 				/*
1642 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1643 				 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
1644 				 */
1645 
1646 				/* Move the str pointer */
1647 				types = ptr + 1;
1648 			}
1649 		} else if (strncmp(types, "TB:", 3) == 0) {
1650 			bzero(model->pt_B, sizeof (model->pt_B));
1651 			types += 3;
1652 
1653 			i = 0;
1654 			while (*types && *types != 'T') {
1655 				/* Null terminate the next value */
1656 				ptr = types;
1657 				while (*ptr && (*ptr != ','))
1658 					ptr++;
1659 				*ptr = 0;
1660 
1661 				/* Save the value */
1662 				model->pt_B[i++] =
1663 				    (uint8_t)emlxs_strtol(types, 16);
1664 
1665 				/*
1666 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1667 				 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
1668 				 */
1669 
1670 				/* Move the str pointer */
1671 				types = ptr + 1;
1672 			}
1673 		} else if (strncmp(types, "TFF:", 4) == 0) {
1674 			bzero(model->pt_FF, sizeof (model->pt_FF));
1675 			types += 4;
1676 
1677 			i = 0;
1678 			while (*types && *types != 'T') {
1679 				/* Null terminate the next value */
1680 				ptr = types;
1681 				while (*ptr && (*ptr != ','))
1682 					ptr++;
1683 				*ptr = 0;
1684 
1685 				/* Save the value */
1686 				model->pt_FF[i++] =
1687 				    (uint8_t)emlxs_strtol(types, 16);
1688 
1689 				/*
1690 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1691 				 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
1692 				 */
1693 
1694 				/* Move the str pointer */
1695 				types = ptr + 1;
1696 			}
1697 		} else if (strncmp(types, "T20:", 4) == 0) {
1698 			bzero(model->pt_20, sizeof (model->pt_20));
1699 			types += 4;
1700 
1701 			i = 0;
1702 			while (*types && *types != 'T') {
1703 				/* Null terminate the next value */
1704 				ptr = types;
1705 				while (*ptr && (*ptr != ','))
1706 					ptr++;
1707 				*ptr = 0;
1708 
1709 				/* Save the value */
1710 				model->pt_20[i++] =
1711 				    (uint8_t)emlxs_strtol(types, 16);
1712 				model->pt_20[i] = 0;
1713 
1714 				/*
1715 				 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1716 				 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
1717 				 */
1718 
1719 				/* Move the str pointer */
1720 				types = ptr + 1;
1721 			}
1722 		} else {
1723 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1724 			    "Unknown prog type string = %s", types);
1725 			break;
1726 		}
1727 	}
1728 
1729 	return;
1730 
1731 } /* emlxs_parse_prog_types() */
1732 
1733 
1734 extern void
1735 emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types)
1736 {
1737 	uint32_t i;
1738 	uint32_t found = 0;
1739 	char buffer[256];
1740 
1741 	bzero(prog_types, 256);
1742 
1743 	/* Rebuild the prog type string */
1744 	if (hba->model_info.pt_2[0]) {
1745 		(void) strcat(prog_types, "T2:");
1746 		found = 1;
1747 
1748 		i = 0;
1749 		while (hba->model_info.pt_2[i] && i < 8) {
1750 			(void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]);
1751 			(void) strcat(prog_types, buffer);
1752 			i++;
1753 		}
1754 	}
1755 
1756 	if (hba->model_info.pt_3[0]) {
1757 		(void) strcat(prog_types, "T3:");
1758 		found = 1;
1759 
1760 		i = 0;
1761 		while (hba->model_info.pt_3[i] && i < 8) {
1762 			(void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]);
1763 			(void) strcat(prog_types, buffer);
1764 			i++;
1765 
1766 		}
1767 	}
1768 
1769 	if (hba->model_info.pt_6[0]) {
1770 		(void) strcat(prog_types, "T6:");
1771 		found = 1;
1772 
1773 		i = 0;
1774 		while (hba->model_info.pt_6[i] && i < 8) {
1775 			(void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]);
1776 			(void) strcat(prog_types, buffer);
1777 			i++;
1778 		}
1779 	}
1780 
1781 	if (hba->model_info.pt_7[0]) {
1782 		(void) strcat(prog_types, "T7:");
1783 		found = 1;
1784 
1785 		i = 0;
1786 		while (hba->model_info.pt_7[i] && i < 8) {
1787 			(void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]);
1788 			(void) strcat(prog_types, buffer);
1789 			i++;
1790 		}
1791 	}
1792 
1793 	if (hba->model_info.pt_A[0]) {
1794 		(void) strcat(prog_types, "TA:");
1795 		found = 1;
1796 
1797 		i = 0;
1798 		while (hba->model_info.pt_A[i] && i < 8) {
1799 			(void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]);
1800 			(void) strcat(prog_types, buffer);
1801 			i++;
1802 		}
1803 	}
1804 
1805 
1806 	if (hba->model_info.pt_B[0]) {
1807 		(void) strcat(prog_types, "TB:");
1808 		found = 1;
1809 
1810 		i = 0;
1811 		while (hba->model_info.pt_B[i] && i < 8) {
1812 			(void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]);
1813 			(void) strcat(prog_types, buffer);
1814 			i++;
1815 		}
1816 	}
1817 
1818 	if (hba->model_info.pt_20[0]) {
1819 		(void) strcat(prog_types, "T20:");
1820 		found = 1;
1821 
1822 		i = 0;
1823 		while (hba->model_info.pt_20[i] && i < 8) {
1824 			(void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]);
1825 			(void) strcat(prog_types, buffer);
1826 			i++;
1827 		}
1828 	}
1829 
1830 	if (hba->model_info.pt_FF[0]) {
1831 		(void) strcat(prog_types, "TFF:");
1832 		found = 1;
1833 
1834 		i = 0;
1835 		while (hba->model_info.pt_FF[i] && i < 8) {
1836 			(void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]);
1837 			(void) strcat(prog_types, buffer);
1838 			i++;
1839 		}
1840 	}
1841 
1842 	if (found) {
1843 		/* Terminate at the last comma in string */
1844 		prog_types[(strlen(prog_types) - 1)] = 0;
1845 	}
1846 
1847 	return;
1848 
1849 } /* emlxs_build_prog_types() */
1850 
1851 
1852 
1853 
1854 extern uint32_t
1855 emlxs_init_adapter_info(emlxs_hba_t *hba)
1856 {
1857 	emlxs_port_t *port = &PPORT;
1858 	uint32_t pci_id;
1859 	uint32_t cache_line;
1860 	uint32_t channels;
1861 	uint16_t device_id;
1862 	uint16_t ssdid;
1863 	uint32_t i;
1864 	uint32_t found = 0;
1865 	int32_t *prop;
1866 	uint32_t num_prop;
1867 
1868 	if (hba->bus_type == SBUS_FC) {
1869 		if (hba->pci_acc_handle == NULL) {
1870 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
1871 			    sizeof (emlxs_model_t));
1872 
1873 			hba->model_info.device_id = 0;
1874 
1875 			return (0);
1876 		}
1877 
1878 		/* Read the PCI device id */
1879 		pci_id =
1880 		    ddi_get32(hba->pci_acc_handle,
1881 		    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
1882 		device_id = (uint16_t)(pci_id >> 16);
1883 
1884 		/* Find matching adapter model */
1885 		for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
1886 			if (emlxs_sbus_model[i].device_id == device_id) {
1887 				bcopy(&emlxs_sbus_model[i], &hba->model_info,
1888 				    sizeof (emlxs_model_t));
1889 				found = 1;
1890 				break;
1891 			}
1892 		}
1893 
1894 		/* If not found then use the unknown model */
1895 		if (!found) {
1896 			bcopy(&emlxs_sbus_model[0], &hba->model_info,
1897 			    sizeof (emlxs_model_t));
1898 
1899 			hba->model_info.device_id = device_id;
1900 
1901 			return (0);
1902 		}
1903 	} else {	/* PCI model */
1904 
1905 		if (hba->pci_acc_handle == NULL) {
1906 			bcopy(&emlxs_pci_model[0], &hba->model_info,
1907 			    sizeof (emlxs_model_t));
1908 
1909 			hba->model_info.device_id = 0;
1910 
1911 			return (0);
1912 		}
1913 
1914 		/* Read the PCI device id */
1915 		device_id =
1916 		    ddi_get16(hba->pci_acc_handle,
1917 		    (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
1918 
1919 		/* Read the PCI Subsystem id */
1920 		ssdid =
1921 		    ddi_get16(hba->pci_acc_handle,
1922 		    (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
1923 
1924 		if (ssdid == 0 || ssdid == 0xffff) {
1925 			ssdid = device_id;
1926 		}
1927 
1928 		/* Read the Cache Line reg */
1929 		cache_line =
1930 		    ddi_get32(hba->pci_acc_handle,
1931 		    (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
1932 
1933 		/* Check for the multifunction bit being set */
1934 		if ((cache_line & 0x00ff0000) == 0x00800000) {
1935 			channels = 2;
1936 		} else {
1937 			channels = 1;
1938 		}
1939 
1940 		/* If device ids are unique, then use them for search */
1941 		if (device_id != ssdid) {
1942 			if (channels > 1) {
1943 				/*
1944 				 * Find matching adapter model using
1945 				 * device_id, ssdid and channels
1946 				 */
1947 				for (i = 1; i < emlxs_pci_model_count; i++) {
1948 					if (emlxs_pci_model[i].device_id ==
1949 					    device_id &&
1950 					    emlxs_pci_model[i].ssdid == ssdid &&
1951 					    emlxs_pci_model[i].channels ==
1952 					    channels) {
1953 						bcopy(&emlxs_pci_model[i],
1954 						    &hba->model_info,
1955 						    sizeof (emlxs_model_t));
1956 						found = 1;
1957 						break;
1958 					}
1959 				}
1960 			} else {
1961 				/*
1962 				 * Find matching adapter model using
1963 				 * device_id and ssdid
1964 				 */
1965 				for (i = 1; i < emlxs_pci_model_count; i++) {
1966 					if (emlxs_pci_model[i].device_id ==
1967 					    device_id &&
1968 					    emlxs_pci_model[i].ssdid == ssdid) {
1969 						bcopy(&emlxs_pci_model[i],
1970 						    &hba->model_info,
1971 						    sizeof (emlxs_model_t));
1972 						found = 1;
1973 						break;
1974 					}
1975 				}
1976 			}
1977 		}
1978 
1979 		/* If adapter not found, try again */
1980 		if (!found) {
1981 			/* Find matching adapter model */
1982 			for (i = 1; i < emlxs_pci_model_count; i++) {
1983 				if (emlxs_pci_model[i].device_id == device_id &&
1984 				    emlxs_pci_model[i].channels == channels) {
1985 					bcopy(&emlxs_pci_model[i],
1986 					    &hba->model_info,
1987 					    sizeof (emlxs_model_t));
1988 					found = 1;
1989 					break;
1990 				}
1991 			}
1992 		}
1993 
1994 		/* If adapter not found, try one last time */
1995 		if (!found) {
1996 			/* Find matching adapter model */
1997 			for (i = 1; i < emlxs_pci_model_count; i++) {
1998 				if (emlxs_pci_model[i].device_id == device_id) {
1999 					bcopy(&emlxs_pci_model[i],
2000 					    &hba->model_info,
2001 					    sizeof (emlxs_model_t));
2002 					found = 1;
2003 					break;
2004 				}
2005 			}
2006 		}
2007 
2008 		/* If not found, set adapter to unknown */
2009 		if (!found) {
2010 			bcopy(&emlxs_pci_model[0], &hba->model_info,
2011 			    sizeof (emlxs_model_t));
2012 
2013 			hba->model_info.device_id = device_id;
2014 			hba->model_info.ssdid = ssdid;
2015 
2016 			return (0);
2017 		}
2018 
2019 #ifndef SATURN_MSI_SUPPORT
2020 		/*
2021 		 * This will disable MSI support for Saturn adapter's
2022 		 * due to a PCI bus issue
2023 		 */
2024 		if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2025 			hba->model_info.flags &=
2026 			    ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2027 		}
2028 #endif /* !SATURN_MSI_SUPPORT */
2029 
2030 		/* Scan the PCI capabilities */
2031 		emlxs_pci_cap_offsets(hba);
2032 
2033 #ifdef MSI_SUPPORT
2034 		/* Verify MSI support */
2035 		if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
2036 		    !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
2037 			hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2038 		}
2039 
2040 		/* Verify MSI-X support */
2041 		if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
2042 		    !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
2043 			hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
2044 		}
2045 #endif /* MSI_SUPPORT */
2046 	}
2047 
2048 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2049 	    "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
2050 		/* Parse the property for PCI function, device and bus no. */
2051 		hba->pci_function_number =
2052 		    (uint8_t)((prop[0] & 0x00000700) >> 8);
2053 		hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);
2054 		hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16);
2055 		ddi_prop_free((void *)prop);
2056 	}
2057 
2058 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
2059 		hba->sli_api = emlxs_sli4_api;
2060 	} else {
2061 		hba->sli_api = emlxs_sli3_api;
2062 	}
2063 
2064 #ifdef FMA_SUPPORT
2065 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
2066 	    != DDI_FM_OK) {
2067 		EMLXS_MSGF(EMLXS_CONTEXT,
2068 		    &emlxs_invalid_access_handle_msg, NULL);
2069 		return (0);
2070 	}
2071 #endif  /* FMA_SUPPORT */
2072 
2073 	return (1);
2074 
2075 } /* emlxs_init_adapter_info()  */
2076 
2077 
2078 /* ARGSUSED */
2079 static void
2080 emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2081 {
2082 	emlxs_port_t *port = &PPORT;
2083 	IOCB *iocb;
2084 	uint32_t *w;
2085 	int i, j;
2086 
2087 	iocb = &iocbq->iocb;
2088 
2089 	if (iocb->ULPSTATUS != 0) {
2090 		return;
2091 	}
2092 
2093 	switch (iocb->un.astat.EventCode) {
2094 	case 0x0100:	/* Temp Warning */
2095 
2096 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
2097 		    "Adapter is very hot (%d �C). Take corrective action.",
2098 		    iocb->ULPCONTEXT);
2099 
2100 		hba->temperature = iocb->ULPCONTEXT;
2101 		emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
2102 
2103 
2104 		break;
2105 
2106 
2107 	case 0x0101:	/* Temp Safe */
2108 
2109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
2110 		    "Adapter temperature now safe (%d �C).",
2111 		    iocb->ULPCONTEXT);
2112 
2113 		hba->temperature = iocb->ULPCONTEXT;
2114 		emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
2115 
2116 		break;
2117 
2118 	default:
2119 
2120 		w = (uint32_t *)iocb;
2121 		for (i = 0, j = 0; i < 8; i++, j += 2) {
2122 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
2123 			    "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
2124 			    w[j + 1]);
2125 		}
2126 
2127 		emlxs_log_async_event(port, iocb);
2128 	}
2129 
2130 	return;
2131 
2132 } /* emlxs_handle_async_event() */
2133 
2134 
2135 /* ARGSUSED */
2136 extern void
2137 emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2138 {
2139 	emlxs_port_t *port = &PPORT;
2140 
2141 	/* Attempt a link reset to recover */
2142 	(void) emlxs_reset(port, FC_FCA_LINK_RESET);
2143 
2144 	return;
2145 
2146 } /* emlxs_reset_link_thread() */
2147 
2148 
2149 /* ARGSUSED */
2150 extern void
2151 emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2152 {
2153 	emlxs_port_t *port = &PPORT;
2154 
2155 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
2156 
2157 	/* Attempt a full hardware reset to recover */
2158 	if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
2159 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
2160 
2161 		emlxs_shutdown_thread(hba, arg1, arg2);
2162 	}
2163 
2164 	return;
2165 
2166 } /* emlxs_restart_thread() */
2167 
2168 
2169 /* ARGSUSED */
2170 extern void
2171 emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2172 {
2173 	emlxs_port_t *port = &PPORT;
2174 
2175 	mutex_enter(&EMLXS_PORT_LOCK);
2176 	if (hba->flag & FC_SHUTDOWN) {
2177 		mutex_exit(&EMLXS_PORT_LOCK);
2178 		return;
2179 	}
2180 	hba->flag |= FC_SHUTDOWN;
2181 	mutex_exit(&EMLXS_PORT_LOCK);
2182 
2183 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
2184 	    "Shutting down...");
2185 
2186 	/* Take adapter offline and leave it there */
2187 	(void) emlxs_offline(hba);
2188 
2189 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2190 		/*
2191 		 * Dump is not defined for SLI4, so just
2192 		 * reset the HBA for now.
2193 		 */
2194 		EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
2195 
2196 	} else {
2197 		if (hba->flag & FC_OVERTEMP_EVENT) {
2198 			emlxs_log_temp_event(port, 0x01,
2199 			    hba->temperature);
2200 		} else {
2201 			emlxs_log_dump_event(port, NULL, 0);
2202 		}
2203 	}
2204 
2205 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
2206 
2207 	return;
2208 
2209 } /* emlxs_shutdown_thread() */
2210 
2211 
2212 /* ARGSUSED */
2213 extern void
2214 emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
2215 {
2216 	IOCBQ *iocbq;
2217 	IOCBQ *rsp_head;
2218 
2219 	/*
2220 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2221 	 * "emlxs_proc_channel: channel=%d", cp->channelno);
2222 	 */
2223 
2224 	mutex_enter(&cp->rsp_lock);
2225 
2226 	while ((rsp_head = cp->rsp_head) != NULL) {
2227 		cp->rsp_head = NULL;
2228 		cp->rsp_tail = NULL;
2229 
2230 		mutex_exit(&cp->rsp_lock);
2231 
2232 		while ((iocbq = rsp_head) != NULL) {
2233 			rsp_head = (IOCBQ *) iocbq->next;
2234 
2235 			emlxs_proc_channel_event(hba, cp, iocbq);
2236 		}
2237 
2238 		mutex_enter(&cp->rsp_lock);
2239 	}
2240 
2241 	mutex_exit(&cp->rsp_lock);
2242 
2243 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
2244 
2245 	return;
2246 
2247 } /* emlxs_proc_channel() */
2248 
2249 
2250 /*
2251  * Called from SLI ring event routines to process a rsp ring IOCB.
2252  */
2253 void
2254 emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2255 {
2256 	emlxs_port_t *port = &PPORT;
2257 	char buffer[MAX_MSG_DATA + 1];
2258 	IOCB *iocb;
2259 	emlxs_buf_t *sbp;
2260 
2261 	iocb = &iocbq->iocb;
2262 
2263 #ifdef DEBUG_CMPL_IOCB
2264 	emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2265 #endif
2266 
2267 	sbp = (emlxs_buf_t *)iocbq->sbp;
2268 	if (sbp) {
2269 		if (!(sbp->pkt_flags & PACKET_VALID) ||
2270 		    (sbp->pkt_flags & (PACKET_ULP_OWNED |
2271 		    PACKET_IN_COMPLETION))) {
2272 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
2273 			    "Duplicate: iocb=%p cmd=%x status=%x "
2274 			    "error=%x iotag=%x context=%x info=%x",
2275 			    iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
2276 			    iocbq->iocb.ULPSTATUS,
2277 			    (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
2278 			    (uint16_t)iocbq->iocb.ULPIOTAG,
2279 			    (uint16_t)iocbq->iocb.ULPCONTEXT,
2280 			    (uint8_t)iocbq->iocb.ULPRSVDBYTE);
2281 
2282 			/* Drop this IO immediately */
2283 			return;
2284 		}
2285 
2286 		if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
2287 			/*
2288 			 * If the packet is tagged for timeout then set the
2289 			 * return codes appropriately
2290 			 */
2291 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2292 			iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
2293 		} else if (sbp->pkt_flags &
2294 		    (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
2295 			/*
2296 			 * If the packet is tagged for abort then set the
2297 			 * return codes appropriately
2298 			 */
2299 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2300 			iocb->un.grsp.perr.statLocalError =
2301 			    IOERR_ABORT_REQUESTED;
2302 		}
2303 	}
2304 
2305 	/* Check for IOCB local error */
2306 	if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
2307 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
2308 		    "Local reject. ringno=%d iocb=%p cmd=%x "
2309 		    "iotag=%x context=%x info=%x error=%x",
2310 		    cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
2311 		    (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
2312 		    (uint8_t)iocb->ULPRSVDBYTE,
2313 		    (uint8_t)iocb->un.grsp.perr.statLocalError);
2314 	}
2315 
2316 	switch (iocb->ULPCOMMAND) {
2317 		/* RING 0 FCP commands */
2318 	case CMD_FCP_ICMND_CR:
2319 	case CMD_FCP_ICMND_CX:
2320 	case CMD_FCP_IREAD_CR:
2321 	case CMD_FCP_IREAD_CX:
2322 	case CMD_FCP_IWRITE_CR:
2323 	case CMD_FCP_IWRITE_CX:
2324 	case CMD_FCP_ICMND64_CR:
2325 	case CMD_FCP_ICMND64_CX:
2326 	case CMD_FCP_IREAD64_CR:
2327 	case CMD_FCP_IREAD64_CX:
2328 	case CMD_FCP_IWRITE64_CR:
2329 	case CMD_FCP_IWRITE64_CX:
2330 		emlxs_handle_fcp_event(hba, cp, iocbq);
2331 		break;
2332 
2333 #ifdef SFCT_SUPPORT
2334 	case CMD_FCP_TSEND_CX:		/* FCP_TARGET IOCB command */
2335 	case CMD_FCP_TSEND64_CX:	/* FCP_TARGET IOCB command */
2336 	case CMD_FCP_TRECEIVE_CX:	/* FCP_TARGET IOCB command */
2337 	case CMD_FCP_TRECEIVE64_CX:	/* FCP_TARGET IOCB command */
2338 	case CMD_FCP_TRSP_CX:		/* FCP_TARGET IOCB command */
2339 	case CMD_FCP_TRSP64_CX:		/* FCP_TARGET IOCB command */
2340 		(void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
2341 		break;
2342 #endif /* SFCT_SUPPORT */
2343 
2344 		/* RING 1 IP commands */
2345 	case CMD_XMIT_BCAST_CN:
2346 	case CMD_XMIT_BCAST_CX:
2347 	case CMD_XMIT_BCAST64_CN:
2348 	case CMD_XMIT_BCAST64_CX:
2349 		(void) emlxs_ip_handle_event(hba, cp, iocbq);
2350 		break;
2351 
2352 	case CMD_XMIT_SEQUENCE_CX:
2353 	case CMD_XMIT_SEQUENCE_CR:
2354 	case CMD_XMIT_SEQUENCE64_CX:
2355 	case CMD_XMIT_SEQUENCE64_CR:
2356 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2357 		case FC_TYPE_IS8802_SNAP:
2358 			(void) emlxs_ip_handle_event(hba, cp, iocbq);
2359 			break;
2360 
2361 		case FC_TYPE_FC_SERVICES:
2362 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2363 			break;
2364 
2365 		default:
2366 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2367 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
2368 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2369 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2370 			    iocb->ULPCONTEXT);
2371 		}
2372 		break;
2373 
2374 	case CMD_RCV_SEQUENCE_CX:
2375 	case CMD_RCV_SEQUENCE64_CX:
2376 	case CMD_RCV_SEQ64_CX:
2377 	case CMD_RCV_ELS_REQ_CX:	/* Unsolicited ELS frame  */
2378 	case CMD_RCV_ELS_REQ64_CX:	/* Unsolicited ELS frame  */
2379 	case CMD_RCV_ELS64_CX:		/* Unsolicited ELS frame  */
2380 		if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
2381 			(void) emlxs_handle_rcv_seq(hba, cp, iocbq);
2382 		}
2383 		break;
2384 
2385 	case CMD_RCV_SEQ_LIST64_CX:
2386 		(void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
2387 		break;
2388 
2389 	case CMD_CREATE_XRI_CR:
2390 	case CMD_CREATE_XRI_CX:
2391 		(void) emlxs_handle_create_xri(hba, cp, iocbq);
2392 		break;
2393 
2394 		/* RING 2 ELS commands */
2395 	case CMD_ELS_REQUEST_CR:
2396 	case CMD_ELS_REQUEST_CX:
2397 	case CMD_XMIT_ELS_RSP_CX:
2398 	case CMD_ELS_REQUEST64_CR:
2399 	case CMD_ELS_REQUEST64_CX:
2400 	case CMD_XMIT_ELS_RSP64_CX:
2401 		(void) emlxs_els_handle_event(hba, cp, iocbq);
2402 		break;
2403 
2404 		/* RING 3 CT commands */
2405 	case CMD_GEN_REQUEST64_CR:
2406 	case CMD_GEN_REQUEST64_CX:
2407 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2408 #ifdef MENLO_SUPPORT
2409 		case EMLXS_MENLO_TYPE:
2410 			(void) emlxs_menlo_handle_event(hba, cp, iocbq);
2411 			break;
2412 #endif /* MENLO_SUPPORT */
2413 
2414 		case FC_TYPE_FC_SERVICES:
2415 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2416 			break;
2417 
2418 		default:
2419 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2420 			    "cmd=%x type=%x status=%x iotag=%x context=%x ",
2421 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2422 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2423 			    iocb->ULPCONTEXT);
2424 		}
2425 		break;
2426 
2427 	case CMD_ABORT_XRI_CN:	/* Abort fcp command */
2428 
2429 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2430 		    "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
2431 		    (uint32_t)iocb->un.acxri.abortContextTag,
2432 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2433 		    iocb->un.acxri.parm);
2434 
2435 #ifdef SFCT_SUPPORT
2436 		if (port->tgt_mode) {
2437 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2438 		}
2439 #endif /* SFCT_SUPPORT */
2440 		break;
2441 
2442 	case CMD_ABORT_XRI_CX:	/* Abort command */
2443 
2444 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2445 		    "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
2446 		    (uint32_t)iocb->un.acxri.abortContextTag,
2447 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2448 		    iocb->un.acxri.parm, iocbq->sbp);
2449 
2450 #ifdef SFCT_SUPPORT
2451 		if (port->tgt_mode) {
2452 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2453 		}
2454 #endif /* SFCT_SUPPORT */
2455 		break;
2456 
2457 	case CMD_XRI_ABORTED_CX:	/* Handle ABORT condition */
2458 
2459 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2460 		    "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x",
2461 		    (uint32_t)iocb->un.acxri.abortContextTag,
2462 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2463 		    iocb->un.acxri.parm);
2464 
2465 #ifdef SFCT_SUPPORT
2466 		if (port->tgt_mode) {
2467 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2468 		}
2469 #endif /* SFCT_SUPPORT */
2470 		break;
2471 
2472 	case CMD_CLOSE_XRI_CN:	/* Handle CLOSE condition */
2473 
2474 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2475 		    "CLOSE_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
2476 		    (uint32_t)iocb->un.acxri.abortContextTag,
2477 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2478 		    iocb->un.acxri.parm);
2479 
2480 #ifdef SFCT_SUPPORT
2481 		if (port->tgt_mode) {
2482 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2483 		}
2484 #endif /* SFCT_SUPPORT */
2485 		break;
2486 
2487 	case CMD_CLOSE_XRI_CX:	/* Handle CLOSE condition */
2488 
2489 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2490 		    "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
2491 		    (uint32_t)iocb->un.acxri.abortContextTag,
2492 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2493 		    iocb->un.acxri.parm, iocbq->sbp);
2494 
2495 #ifdef SFCT_SUPPORT
2496 		if (port->tgt_mode) {
2497 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2498 		}
2499 #endif /* SFCT_SUPPORT */
2500 		break;
2501 
2502 	case CMD_ADAPTER_MSG:
2503 		/* Allows debug adapter firmware messages to print on host */
2504 		bzero(buffer, sizeof (buffer));
2505 		bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
2506 
2507 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
2508 
2509 		break;
2510 
2511 	case CMD_QUE_RING_LIST64_CN:
2512 	case CMD_QUE_RING_BUF64_CN:
2513 		break;
2514 
2515 	case CMD_ASYNC_STATUS:
2516 		emlxs_handle_async_event(hba, cp, iocbq);
2517 		break;
2518 
2519 	default:
2520 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2521 		    "cmd=%x status=%x iotag=%x context=%x", iocb->ULPCOMMAND,
2522 		    iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
2523 
2524 		break;
2525 	}	/* switch(entry->ULPCOMMAND) */
2526 
2527 	return;
2528 
2529 } /* emlxs_proc_channel_event() */
2530 
2531 
2532 extern char *
2533 emlxs_ffstate_xlate(uint32_t state)
2534 {
2535 	static char buffer[32];
2536 	uint32_t i;
2537 	uint32_t count;
2538 
2539 	count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
2540 	for (i = 0; i < count; i++) {
2541 		if (state == emlxs_ffstate_table[i].code) {
2542 			return (emlxs_ffstate_table[i].string);
2543 		}
2544 	}
2545 
2546 	(void) sprintf(buffer, "state=0x%x", state);
2547 	return (buffer);
2548 
2549 } /* emlxs_ffstate_xlate() */
2550 
2551 
2552 extern char *
2553 emlxs_ring_xlate(uint32_t ringno)
2554 {
2555 	static char buffer[32];
2556 	uint32_t i;
2557 	uint32_t count;
2558 
2559 	count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
2560 	for (i = 0; i < count; i++) {
2561 		if (ringno == emlxs_ring_table[i].code) {
2562 			return (emlxs_ring_table[i].string);
2563 		}
2564 	}
2565 
2566 	(void) sprintf(buffer, "ring=0x%x", ringno);
2567 	return (buffer);
2568 
2569 } /* emlxs_ring_xlate() */
2570 
2571 
2572 extern char *
2573 emlxs_pci_cap_xlate(uint32_t id)
2574 {
2575 	static char buffer[32];
2576 	uint32_t i;
2577 	uint32_t count;
2578 
2579 	count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
2580 	for (i = 0; i < count; i++) {
2581 		if (id == emlxs_pci_cap[i].code) {
2582 			return (emlxs_pci_cap[i].string);
2583 		}
2584 	}
2585 
2586 	(void) sprintf(buffer, "PCI_CAP_ID_%02X", id);
2587 	return (buffer);
2588 
2589 } /* emlxs_pci_cap_xlate() */
2590 
2591 
2592 extern void
2593 emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2594 {
2595 	emlxs_port_t *port = &PPORT;
2596 	MAILBOXQ *mbq;
2597 	MAILBOX *mb;
2598 	emlxs_config_t *cfg;
2599 	uint32_t value;
2600 
2601 	cfg = &CFG;
2602 
2603 xlate:
2604 
2605 	switch (cfg[CFG_PCI_MAX_READ].current) {
2606 	case 512:
2607 		value = 0;
2608 		break;
2609 
2610 	case 1024:
2611 		value = 1;
2612 		break;
2613 
2614 	case 2048:
2615 		value = 2;
2616 		break;
2617 
2618 	case 4096:
2619 		value = 3;
2620 		break;
2621 
2622 	default:
2623 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2624 		    "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
2625 		    cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
2626 
2627 		cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
2628 		goto xlate;
2629 	}
2630 
2631 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
2632 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2633 		    "PCI_MAX_READ: Unable to allocate mailbox buffer.");
2634 		return;
2635 	}
2636 	mb = (MAILBOX *)mbq;
2637 
2638 	emlxs_mb_set_var(hba, mbq, 0x00100506, value);
2639 
2640 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2641 		if (verbose || (mb->mbxStatus != 0x12)) {
2642 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2643 			    "PCI_MAX_READ: Unable to update. "
2644 			    "status=%x value=%d (%d bytes)",
2645 			    mb->mbxStatus, value,
2646 			    cfg[CFG_PCI_MAX_READ].current);
2647 		}
2648 	} else {
2649 		if (verbose &&
2650 		    (cfg[CFG_PCI_MAX_READ].current !=
2651 		    cfg[CFG_PCI_MAX_READ].def)) {
2652 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2653 			    "PCI_MAX_READ: Updated. %d bytes",
2654 			    cfg[CFG_PCI_MAX_READ].current);
2655 		}
2656 	}
2657 
2658 	emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2659 
2660 	return;
2661 
2662 } /* emlxs_pcix_mxr_update */
2663 
2664 
2665 
2666 extern uint32_t
2667 emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
2668 {
2669 	emlxs_port_t *port = &PPORT;
2670 	MAILBOX *mb = (MAILBOX *)mbq;
2671 	uint32_t npname0, npname1;
2672 	uint32_t tmpkey, theKey;
2673 	uint16_t key850;
2674 	uint32_t t1, t2, t3, t4;
2675 	uint32_t ts;
2676 
2677 #define	SEED 0x876EDC21
2678 
2679 	/* This key is only used currently for SBUS adapters */
2680 	if (hba->bus_type != SBUS_FC) {
2681 		return (0);
2682 	}
2683 
2684 	tmpkey = mb->un.varWords[30];
2685 	EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
2686 
2687 	emlxs_mb_read_nv(hba, mbq);
2688 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2689 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2690 		    "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
2691 		    mb->mbxStatus);
2692 
2693 		return (0);
2694 	}
2695 	npname0 = mb->un.varRDnvp.portname[0];
2696 	npname1 = mb->un.varRDnvp.portname[1];
2697 
2698 	key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
2699 	ts = (uint16_t)(npname1 + 1);
2700 	t1 = ts * key850;
2701 	ts = (uint16_t)((npname1 >> 16) + 1);
2702 	t2 = ts * key850;
2703 	ts = (uint16_t)(npname0 + 1);
2704 	t3 = ts * key850;
2705 	ts = (uint16_t)((npname0 >> 16) + 1);
2706 	t4 = ts * key850;
2707 	theKey = SEED + t1 + t2 + t3 + t4;
2708 
2709 	return (theKey);
2710 
2711 } /* emlxs_get_key() */
2712 
2713 
2714 extern void
2715 emlxs_fw_show(emlxs_hba_t *hba)
2716 {
2717 	emlxs_port_t *port = &PPORT;
2718 	uint32_t i;
2719 
2720 	/* Display firmware library one time */
2721 	for (i = 0; i < emlxs_fw_count; i++) {
2722 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
2723 		    emlxs_fw_table[i].label);
2724 	}
2725 
2726 	return;
2727 
2728 } /* emlxs_fw_show() */
2729 
2730 
2731 #ifdef MODFW_SUPPORT
2732 extern void
2733 emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2734 {
2735 	emlxs_port_t *port = &PPORT;
2736 	int (*emlxs_fw_get)(emlxs_firmware_t *);
2737 	int err;
2738 
2739 	/* Make sure image is unloaded and image buffer pointer is clear */
2740 	emlxs_fw_unload(hba, fw);
2741 
2742 	err = 0;
2743 	hba->fw_modhandle =
2744 	    ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
2745 	if (!hba->fw_modhandle) {
2746 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2747 		    "Unable to load firmware module. error=%d", err);
2748 
2749 		return;
2750 	} else {
2751 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2752 		    "Firmware module loaded.");
2753 	}
2754 
2755 	err = 0;
2756 	emlxs_fw_get =
2757 	    (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err);
2758 	if ((void *)emlxs_fw_get == NULL) {
2759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2760 		    "emlxs_fw_get not present. error=%d", err);
2761 
2762 		emlxs_fw_unload(hba, fw);
2763 		return;
2764 	}
2765 
2766 	if (emlxs_fw_get(fw)) {
2767 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2768 		    "Invalid firmware image module found. %s", fw->label);
2769 
2770 		emlxs_fw_unload(hba, fw);
2771 		return;
2772 	}
2773 
2774 	return;
2775 
2776 } /* emlxs_fw_load() */
2777 
2778 
2779 extern void
2780 emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2781 {
2782 	emlxs_port_t *port = &PPORT;
2783 
2784 	/* Clear the firmware image */
2785 	fw->image = NULL;
2786 	fw->size = 0;
2787 
2788 	if (hba->fw_modhandle) {
2789 		/* Close the module */
2790 		(void) ddi_modclose(hba->fw_modhandle);
2791 		hba->fw_modhandle = NULL;
2792 
2793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2794 		    "Firmware module unloaded.");
2795 	}
2796 
2797 	return;
2798 
2799 } /* emlxs_fw_unload() */
2800 #endif /* MODFW_SUPPORT */
2801 
2802 
2803 static void
2804 emlxs_pci_cap_offsets(emlxs_hba_t *hba)
2805 {
2806 	emlxs_port_t *port = &PPORT;
2807 	uint8_t	offset;
2808 	uint8_t	id;
2809 
2810 	bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
2811 
2812 	/* Read first offset */
2813 	offset = ddi_get8(hba->pci_acc_handle,
2814 	    (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER));
2815 	offset &= PCI_CAP_PTR_MASK;
2816 
2817 	while (offset >= PCI_CAP_PTR_OFF) {
2818 		/* Read the next cap id */
2819 		id = ddi_get8(hba->pci_acc_handle,
2820 		    (uint8_t *)(hba->pci_addr + offset));
2821 
2822 		if (id < PCI_CAP_MAX_PTR) {
2823 			hba->pci_cap_offset[id] = offset;
2824 		}
2825 
2826 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2827 		    "%s: offset=0x%x",
2828 		    emlxs_pci_cap_xlate(id), offset);
2829 
2830 		/* Read next offset */
2831 		offset = ddi_get8(hba->pci_acc_handle,
2832 		    (uint8_t *)(hba->pci_addr + offset + PCI_CAP_NEXT_PTR));
2833 		offset &= PCI_CAP_PTR_MASK;
2834 	}
2835 
2836 	return;
2837 
2838 } /* emlxs_pci_cap_offsets() */
2839