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