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