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