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