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