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 */
35 EMLXS_MSG_DEF(EMLXS_HBA_C);
36 
37 
38 static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
39     IOCBQ *iocbq);
40 
41 static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
42 
43 #ifdef MSI_SUPPORT
44 uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
45 	{EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
46 uint32_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 
51 emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
52 int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
53 
54 emlxs_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 
77 emlxs_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 
100 emlxs_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 
108 emlxs_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 */
129 int32_t
emlxs_msi_init(emlxs_hba_t * hba,uint32_t max)130 emlxs_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 
197 begin:
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 
252 initialize:
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 
447 init_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 */
496 int32_t
emlxs_msi_uninit(emlxs_hba_t * hba)497 emlxs_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 */
588 int32_t
emlxs_msi_add(emlxs_hba_t * hba)589 emlxs_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 */
693 int32_t
emlxs_msi_remove(emlxs_hba_t * hba)694 emlxs_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 */
778 int32_t
emlxs_intx_init(emlxs_hba_t * hba,uint32_t max)779 emlxs_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 */
846 int32_t
emlxs_intx_uninit(emlxs_hba_t * hba)847 emlxs_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  */
884 int32_t
emlxs_intx_add(emlxs_hba_t * hba)885 emlxs_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 */
926 int32_t
emlxs_intx_remove(emlxs_hba_t * hba)927 emlxs_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 
947 extern void
emlxs_process_link_speed(emlxs_hba_t * hba)948 emlxs_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  */
1016 extern int
emlxs_parse_vpd(emlxs_hba_t * hba,uint8_t * vpd_buf,uint32_t size)1017 emlxs_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  */
1263 extern int
emlxs_parse_fcoe(emlxs_hba_t * hba,uint8_t * fcoep,uint32_t size)1264 emlxs_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 
1336 extern void
emlxs_decode_firmware_rev(emlxs_hba_t * hba,emlxs_vpd_t * vpd)1337 emlxs_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 
1384 extern void
emlxs_decode_version(uint32_t version,char * buffer,size_t len)1385 emlxs_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 
1431 extern void
emlxs_decode_label(char * label,char * buffer,int bige,size_t len)1432 emlxs_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 
1468 extern uint32_t
emlxs_strtol(char * str,uint32_t base)1469 emlxs_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 
1522 extern uint64_t
emlxs_strtoll(char * str,uint32_t base)1523 emlxs_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 
1575 extern void
emlxs_parse_prog_types(emlxs_hba_t * hba,char * prog_types)1576 emlxs_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 
1799 extern void
emlxs_build_prog_types(emlxs_hba_t * hba,emlxs_vpd_t * vpd)1800 emlxs_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 
1941 extern uint32_t
emlxs_init_adapter_info(emlxs_hba_t * hba)1942 emlxs_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 	pci_regspec_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", (int **)&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)PCI_REG_FUNC_G(prop[0].pci_phys_hi);
2168 		hba->pci_device_number =
2169 		    (uint8_t)PCI_REG_DEV_G(prop[0].pci_phys_hi);
2170 		hba->pci_bus_number =
2171 		    (uint8_t)PCI_REG_BUS_G(prop[0].pci_phys_hi);
2172 		ddi_prop_free((void *)prop);
2173 	}
2174 
2175 	switch (hba->sli_intf & SLI_INTF_SLI_REV_MASK) {
2176 	case SLI_INTF_SLI_REV_NONE: /* Legacy support */
2177 		if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
2178 			hba->sli_api = emlxs_sli4_api;
2179 		} else {
2180 			hba->sli_api = emlxs_sli3_api;
2181 		}
2182 		break;
2183 
2184 	case SLI_INTF_SLI_REV_3:
2185 		if (!(hba->model_info.sli_mask & EMLXS_SLI3_MASK)) {
2186 			EMLXS_MSGF(EMLXS_CONTEXT,
2187 			    &emlxs_init_failed_msg,
2188 			    "Adapter does not support SLI3 interface. "
2189 			    "sli_intf=%08x sli_mask=%08x",
2190 			    hba->sli_intf, hba->model_info.sli_mask);
2191 			return (0);
2192 		}
2193 		hba->sli_api = emlxs_sli3_api;
2194 		break;
2195 
2196 	case SLI_INTF_SLI_REV_4:
2197 		if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
2198 			EMLXS_MSGF(EMLXS_CONTEXT,
2199 			    &emlxs_init_failed_msg,
2200 			    "Adapter does not support SLI4 interface. "
2201 			    "sli_intf=%08x sli_mask=%08x",
2202 			    hba->sli_intf, hba->model_info.sli_mask);
2203 			return (0);
2204 		}
2205 		hba->sli_api = emlxs_sli4_api;
2206 		break;
2207 
2208 	default:
2209 		EMLXS_MSGF(EMLXS_CONTEXT,
2210 		    &emlxs_init_failed_msg,
2211 		    "Invalid SLI interface specified. "
2212 		    "sli_intf=%08x sli_mask=%08x",
2213 		    hba->sli_intf, hba->model_info.sli_mask);
2214 		return (0);
2215 	}
2216 
2217 #ifdef FMA_SUPPORT
2218 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
2219 	    != DDI_FM_OK) {
2220 		EMLXS_MSGF(EMLXS_CONTEXT,
2221 		    &emlxs_invalid_access_handle_msg, NULL);
2222 		return (0);
2223 	}
2224 #endif  /* FMA_SUPPORT */
2225 
2226 	return (1);
2227 
2228 } /* emlxs_init_adapter_info()  */
2229 
2230 
2231 /* ARGSUSED */
2232 static void
emlxs_handle_async_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)2233 emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2234 {
2235 	emlxs_port_t *port = &PPORT;
2236 	IOCB *iocb;
2237 	uint32_t *w;
2238 	int i, j;
2239 
2240 	iocb = &iocbq->iocb;
2241 
2242 	if (iocb->ULPSTATUS != 0) {
2243 		return;
2244 	}
2245 
2246 	switch (iocb->un.astat.EventCode) {
2247 	case 0x0100:	/* Temp Warning */
2248 
2249 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
2250 		    "Adapter is very hot (%d �C). Take corrective action.",
2251 		    iocb->ULPCONTEXT);
2252 
2253 		hba->temperature = iocb->ULPCONTEXT;
2254 		emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
2255 
2256 
2257 		break;
2258 
2259 
2260 	case 0x0101:	/* Temp Safe */
2261 
2262 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
2263 		    "Adapter temperature now safe (%d �C).",
2264 		    iocb->ULPCONTEXT);
2265 
2266 		hba->temperature = iocb->ULPCONTEXT;
2267 		emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
2268 
2269 		break;
2270 
2271 	default:
2272 
2273 		w = (uint32_t *)iocb;
2274 		for (i = 0, j = 0; i < 8; i++, j += 2) {
2275 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
2276 			    "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
2277 			    w[j + 1]);
2278 		}
2279 
2280 		emlxs_log_async_event(port, iocb);
2281 	}
2282 
2283 	return;
2284 
2285 } /* emlxs_handle_async_event() */
2286 
2287 
2288 /* ARGSUSED */
2289 extern void
emlxs_reset_link_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2290 emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2291 {
2292 	emlxs_port_t *port = &PPORT;
2293 
2294 	/* Attempt a link reset to recover */
2295 	(void) emlxs_reset(port, FC_FCA_LINK_RESET);
2296 
2297 	return;
2298 
2299 } /* emlxs_reset_link_thread() */
2300 
2301 
2302 /* ARGSUSED */
2303 extern void
emlxs_restart_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2304 emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2305 {
2306 	emlxs_port_t *port = &PPORT;
2307 
2308 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
2309 
2310 	/* Attempt a full hardware reset to recover */
2311 	if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
2312 		EMLXS_STATE_CHANGE(hba, FC_ERROR);
2313 
2314 		emlxs_shutdown_thread(hba, arg1, arg2);
2315 	}
2316 
2317 	return;
2318 
2319 } /* emlxs_restart_thread() */
2320 
2321 
2322 /* ARGSUSED */
2323 extern void
emlxs_shutdown_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2324 emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2325 {
2326 	emlxs_port_t *port = &PPORT;
2327 
2328 	mutex_enter(&EMLXS_PORT_LOCK);
2329 	if (hba->flag & FC_SHUTDOWN) {
2330 		mutex_exit(&EMLXS_PORT_LOCK);
2331 		return;
2332 	}
2333 	hba->flag |= FC_SHUTDOWN;
2334 	mutex_exit(&EMLXS_PORT_LOCK);
2335 
2336 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
2337 	    "Shutting down...");
2338 
2339 	/* Take adapter offline and leave it there */
2340 	(void) emlxs_offline(hba, 0);
2341 
2342 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2343 		/*
2344 		 * Dump is not defined for SLI4, so just
2345 		 * reset the HBA for now.
2346 		 */
2347 		EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
2348 
2349 	} else {
2350 		if (hba->flag & FC_OVERTEMP_EVENT) {
2351 			emlxs_log_temp_event(port, 0x01,
2352 			    hba->temperature);
2353 		} else {
2354 			emlxs_log_dump_event(port, NULL, 0);
2355 		}
2356 	}
2357 
2358 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
2359 
2360 	return;
2361 
2362 } /* emlxs_shutdown_thread() */
2363 
2364 
2365 /* ARGSUSED */
2366 extern void
emlxs_proc_channel(emlxs_hba_t * hba,CHANNEL * cp,void * arg2)2367 emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
2368 {
2369 	IOCBQ *iocbq;
2370 	IOCBQ *rsp_head;
2371 
2372 	/*
2373 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2374 	 * "proc_channel: channel=%d", cp->channelno);
2375 	 */
2376 
2377 	mutex_enter(&cp->rsp_lock);
2378 
2379 	while ((rsp_head = cp->rsp_head) != NULL) {
2380 		cp->rsp_head = NULL;
2381 		cp->rsp_tail = NULL;
2382 
2383 		mutex_exit(&cp->rsp_lock);
2384 
2385 		while ((iocbq = rsp_head) != NULL) {
2386 			rsp_head = (IOCBQ *) iocbq->next;
2387 
2388 			emlxs_proc_channel_event(hba, cp, iocbq);
2389 		}
2390 
2391 		mutex_enter(&cp->rsp_lock);
2392 	}
2393 
2394 	mutex_exit(&cp->rsp_lock);
2395 
2396 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
2397 
2398 	return;
2399 
2400 } /* emlxs_proc_channel() */
2401 
2402 
2403 /*
2404  * Called from SLI ring event routines to process a rsp ring IOCB.
2405  */
2406 void
emlxs_proc_channel_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)2407 emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2408 {
2409 	emlxs_port_t *port = &PPORT;
2410 	char buffer[MAX_MSG_DATA + 1];
2411 	IOCB *iocb;
2412 	emlxs_buf_t *sbp;
2413 	fc_packet_t *pkt;
2414 
2415 	iocb = &iocbq->iocb;
2416 
2417 #ifdef DEBUG_CMPL_IOCB
2418 	emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2419 #endif
2420 
2421 	sbp = (emlxs_buf_t *)iocbq->sbp;
2422 	if (sbp) {
2423 		if (!(sbp->pkt_flags & PACKET_VALID) ||
2424 		    (sbp->pkt_flags & (PACKET_ULP_OWNED |
2425 		    PACKET_IN_COMPLETION))) {
2426 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
2427 			    "Duplicate: iocb=%p cmd=%x status=%x "
2428 			    "error=%x iotag=%d context=%x info=%x",
2429 			    iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
2430 			    iocbq->iocb.ULPSTATUS,
2431 			    (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
2432 			    (uint16_t)iocbq->iocb.ULPIOTAG,
2433 			    (uint16_t)iocbq->iocb.ULPCONTEXT,
2434 			    (uint8_t)iocbq->iocb.ULPRSVDBYTE);
2435 
2436 			/* Drop this IO immediately */
2437 			return;
2438 		}
2439 
2440 		if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
2441 			/*
2442 			 * If the packet is tagged for timeout then set the
2443 			 * return codes appropriately
2444 			 */
2445 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2446 			iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
2447 		} else if (sbp->pkt_flags &
2448 		    (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
2449 			/*
2450 			 * If the packet is tagged for abort then set the
2451 			 * return codes appropriately
2452 			 */
2453 			iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2454 			iocb->un.grsp.perr.statLocalError =
2455 			    IOERR_ABORT_REQUESTED;
2456 		}
2457 	}
2458 
2459 	/* Check for IOCB local error */
2460 	if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
2461 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
2462 		    "Local reject. ringno=%d iocb=%p cmd=%x "
2463 		    "iotag=%d context=%x info=%x error=%x",
2464 		    cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
2465 		    (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
2466 		    (uint8_t)iocb->ULPRSVDBYTE,
2467 		    (uint8_t)iocb->un.grsp.perr.statLocalError);
2468 	}
2469 
2470 	switch (iocb->ULPCOMMAND) {
2471 		/* RING 0 FCP commands */
2472 	case CMD_FCP_ICMND_CR:
2473 	case CMD_FCP_ICMND_CX:
2474 	case CMD_FCP_IREAD_CR:
2475 	case CMD_FCP_IREAD_CX:
2476 	case CMD_FCP_IWRITE_CR:
2477 	case CMD_FCP_IWRITE_CX:
2478 	case CMD_FCP_ICMND64_CR:
2479 	case CMD_FCP_ICMND64_CX:
2480 	case CMD_FCP_IREAD64_CR:
2481 	case CMD_FCP_IREAD64_CX:
2482 	case CMD_FCP_IWRITE64_CR:
2483 	case CMD_FCP_IWRITE64_CX:
2484 		emlxs_handle_fcp_event(hba, cp, iocbq);
2485 		break;
2486 
2487 #ifdef SFCT_SUPPORT
2488 	case CMD_FCP_TSEND_CX:		/* FCP_TARGET IOCB command */
2489 	case CMD_FCP_TSEND64_CX:	/* FCP_TARGET IOCB command */
2490 	case CMD_FCP_TRECEIVE_CX:	/* FCP_TARGET IOCB command */
2491 	case CMD_FCP_TRECEIVE64_CX:	/* FCP_TARGET IOCB command */
2492 	case CMD_FCP_TRSP_CX:		/* FCP_TARGET IOCB command */
2493 	case CMD_FCP_TRSP64_CX:		/* FCP_TARGET IOCB command */
2494 		if (port->mode == MODE_TARGET) {
2495 			(void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
2496 		}
2497 		break;
2498 #endif /* SFCT_SUPPORT */
2499 
2500 		/* RING 1 IP commands */
2501 	case CMD_XMIT_BCAST_CN:
2502 	case CMD_XMIT_BCAST_CX:
2503 	case CMD_XMIT_BCAST64_CN:
2504 	case CMD_XMIT_BCAST64_CX:
2505 		(void) emlxs_ip_handle_event(hba, cp, iocbq);
2506 		break;
2507 
2508 	case CMD_XMIT_SEQUENCE_CX:
2509 	case CMD_XMIT_SEQUENCE_CR:
2510 	case CMD_XMIT_SEQUENCE64_CX:
2511 	case CMD_XMIT_SEQUENCE64_CR:
2512 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2513 		case FC_TYPE_IS8802_SNAP:
2514 			(void) emlxs_ip_handle_event(hba, cp, iocbq);
2515 			break;
2516 
2517 		case FC_TYPE_FC_SERVICES:
2518 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2519 			break;
2520 
2521 		default:
2522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2523 			    "cmd=%x type=%x status=%x iotag=%d context=%x ",
2524 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2525 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2526 			    iocb->ULPCONTEXT);
2527 		}
2528 		break;
2529 
2530 	case CMD_RCV_SEQUENCE_CX:
2531 	case CMD_RCV_SEQUENCE64_CX:
2532 	case CMD_RCV_SEQ64_CX:
2533 	case CMD_RCV_ELS_REQ_CX:	/* Unsolicited ELS frame  */
2534 	case CMD_RCV_ELS_REQ64_CX:	/* Unsolicited ELS frame  */
2535 	case CMD_RCV_ELS64_CX:		/* Unsolicited ELS frame  */
2536 		if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
2537 			(void) emlxs_handle_rcv_seq(hba, cp, iocbq);
2538 		}
2539 		break;
2540 
2541 	case CMD_RCV_SEQ_LIST64_CX:
2542 		(void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
2543 		break;
2544 
2545 	case CMD_CREATE_XRI_CR:
2546 	case CMD_CREATE_XRI_CX:
2547 		(void) emlxs_handle_create_xri(hba, cp, iocbq);
2548 		break;
2549 
2550 		/* RING 2 ELS commands */
2551 	case CMD_ELS_REQUEST_CR:
2552 	case CMD_ELS_REQUEST_CX:
2553 	case CMD_XMIT_ELS_RSP_CX:
2554 	case CMD_ELS_REQUEST64_CR:
2555 	case CMD_ELS_REQUEST64_CX:
2556 	case CMD_XMIT_ELS_RSP64_CX:
2557 		(void) emlxs_els_handle_event(hba, cp, iocbq);
2558 		break;
2559 
2560 		/* RING 3 CT commands */
2561 	case CMD_GEN_REQUEST64_CR:
2562 	case CMD_GEN_REQUEST64_CX:
2563 		switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2564 #ifdef MENLO_SUPPORT
2565 		case EMLXS_MENLO_TYPE:
2566 			(void) emlxs_menlo_handle_event(hba, cp, iocbq);
2567 			break;
2568 #endif /* MENLO_SUPPORT */
2569 
2570 		case FC_TYPE_FC_SERVICES:
2571 			(void) emlxs_ct_handle_event(hba, cp, iocbq);
2572 			break;
2573 
2574 		default:
2575 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2576 			    "cmd=%x type=%x status=%x iotag=%d context=%x ",
2577 			    iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2578 			    iocb->ULPSTATUS, iocb->ULPIOTAG,
2579 			    iocb->ULPCONTEXT);
2580 		}
2581 		break;
2582 
2583 	case CMD_ABORT_XRI_CN:	/* Abort fcp command */
2584 
2585 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2586 		    "ABORT_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2587 		    (uint32_t)iocb->un.acxri.abortContextTag,
2588 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2589 		    iocb->un.acxri.parm);
2590 
2591 #ifdef SFCT_SUPPORT
2592 		if (port->mode == MODE_TARGET) {
2593 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2594 		}
2595 #endif /* SFCT_SUPPORT */
2596 		break;
2597 
2598 	case CMD_ABORT_XRI_CX:	/* Abort command */
2599 
2600 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2601 		    "ABORT_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2602 		    (uint32_t)iocb->un.acxri.abortContextTag,
2603 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2604 		    iocb->un.acxri.parm, iocbq->sbp);
2605 
2606 #ifdef SFCT_SUPPORT
2607 		if (port->mode == MODE_TARGET) {
2608 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2609 		}
2610 #endif /* SFCT_SUPPORT */
2611 		break;
2612 
2613 	case CMD_XRI_ABORTED_CX:	/* Handle ABORT condition */
2614 
2615 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2616 		    "XRI_ABORTED_CX: rpi=%d iotag=%d status=%x parm=%x",
2617 		    (uint32_t)iocb->un.acxri.abortContextTag,
2618 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2619 		    iocb->un.acxri.parm);
2620 
2621 #ifdef SFCT_SUPPORT
2622 		if (port->mode == MODE_TARGET) {
2623 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2624 		}
2625 #endif /* SFCT_SUPPORT */
2626 		break;
2627 
2628 	case CMD_CLOSE_XRI_CN:	/* Handle CLOSE condition */
2629 
2630 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2631 		    "CLOSE_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2632 		    (uint32_t)iocb->un.acxri.abortContextTag,
2633 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2634 		    iocb->un.acxri.parm);
2635 
2636 #ifdef SFCT_SUPPORT
2637 		if (port->mode == MODE_TARGET) {
2638 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2639 		}
2640 #endif /* SFCT_SUPPORT */
2641 		break;
2642 
2643 	case CMD_CLOSE_XRI_CX:	/* Handle CLOSE condition */
2644 
2645 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2646 		    "CLOSE_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2647 		    (uint32_t)iocb->un.acxri.abortContextTag,
2648 		    (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2649 		    iocb->un.acxri.parm, iocbq->sbp);
2650 
2651 #ifdef SFCT_SUPPORT
2652 		if (port->mode == MODE_TARGET) {
2653 			(void) emlxs_fct_handle_abort(hba, cp, iocbq);
2654 		}
2655 #endif /* SFCT_SUPPORT */
2656 		break;
2657 
2658 	case CMD_ADAPTER_MSG:
2659 		/* Allows debug adapter firmware messages to print on host */
2660 		bzero(buffer, sizeof (buffer));
2661 		bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
2662 
2663 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
2664 
2665 		break;
2666 
2667 	case CMD_QUE_RING_LIST64_CN:
2668 	case CMD_QUE_RING_BUF64_CN:
2669 		break;
2670 
2671 	case CMD_ASYNC_STATUS:
2672 		emlxs_handle_async_event(hba, cp, iocbq);
2673 		break;
2674 
2675 	case CMD_XMIT_BLS_RSP64_CX:
2676 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2677 		    "CMD_XMIT_BLS_RSP64_CX: sbp = %p", sbp);
2678 
2679 		/*
2680 		 * The exchange should have been already freed in the wqe_cmpl
2681 		 * so just free up the pkt here.
2682 		 */
2683 		pkt = PRIV2PKT(sbp);
2684 		emlxs_pkt_free(pkt);
2685 		break;
2686 
2687 	default:
2688 		if (iocb->ULPCOMMAND == 0) {
2689 			break;
2690 		}
2691 
2692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2693 		    "cmd=%x status=%x iotag=%d context=%x", iocb->ULPCOMMAND,
2694 		    iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
2695 
2696 		break;
2697 	}	/* switch(entry->ULPCOMMAND) */
2698 
2699 	return;
2700 
2701 } /* emlxs_proc_channel_event() */
2702 
2703 
2704 extern char *
emlxs_ffstate_xlate(uint32_t state)2705 emlxs_ffstate_xlate(uint32_t state)
2706 {
2707 	static char buffer[32];
2708 	uint32_t i;
2709 	uint32_t count;
2710 
2711 	count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
2712 	for (i = 0; i < count; i++) {
2713 		if (state == emlxs_ffstate_table[i].code) {
2714 			return (emlxs_ffstate_table[i].string);
2715 		}
2716 	}
2717 
2718 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2719 	return (buffer);
2720 
2721 } /* emlxs_ffstate_xlate() */
2722 
2723 
2724 extern char *
emlxs_ring_xlate(uint32_t ringno)2725 emlxs_ring_xlate(uint32_t ringno)
2726 {
2727 	static char buffer[32];
2728 	uint32_t i;
2729 	uint32_t count;
2730 
2731 	count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
2732 	for (i = 0; i < count; i++) {
2733 		if (ringno == emlxs_ring_table[i].code) {
2734 			return (emlxs_ring_table[i].string);
2735 		}
2736 	}
2737 
2738 	(void) snprintf(buffer, sizeof (buffer), "ring=0x%x", ringno);
2739 	return (buffer);
2740 
2741 } /* emlxs_ring_xlate() */
2742 
2743 
2744 extern char *
emlxs_pci_cap_xlate(uint32_t id)2745 emlxs_pci_cap_xlate(uint32_t id)
2746 {
2747 	static char buffer[32];
2748 	uint32_t i;
2749 	uint32_t count;
2750 
2751 	count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
2752 	for (i = 0; i < count; i++) {
2753 		if (id == emlxs_pci_cap[i].code) {
2754 			return (emlxs_pci_cap[i].string);
2755 		}
2756 	}
2757 
2758 	(void) snprintf(buffer, sizeof (buffer), "PCI_CAP_ID_%02X", id);
2759 	return (buffer);
2760 
2761 } /* emlxs_pci_cap_xlate() */
2762 
2763 
2764 extern char *
emlxs_pci_ecap_xlate(uint32_t id)2765 emlxs_pci_ecap_xlate(uint32_t id)
2766 {
2767 	static char buffer[32];
2768 	uint32_t i;
2769 	uint32_t count;
2770 
2771 	count = sizeof (emlxs_pci_ecap) / sizeof (emlxs_table_t);
2772 	for (i = 0; i < count; i++) {
2773 		if (id == emlxs_pci_ecap[i].code) {
2774 			return (emlxs_pci_ecap[i].string);
2775 		}
2776 	}
2777 
2778 	(void) snprintf(buffer, sizeof (buffer), "PCI_EXT_CAP_ID_%02X", id);
2779 	return (buffer);
2780 
2781 } /* emlxs_pci_ecap_xlate() */
2782 
2783 
2784 extern void
emlxs_pcix_mxr_update(emlxs_hba_t * hba,uint32_t verbose)2785 emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2786 {
2787 	emlxs_port_t *port = &PPORT;
2788 	MAILBOXQ *mbq;
2789 	MAILBOX *mb;
2790 	emlxs_config_t *cfg;
2791 	uint32_t value;
2792 
2793 	cfg = &CFG;
2794 
2795 xlate:
2796 
2797 	switch (cfg[CFG_PCI_MAX_READ].current) {
2798 	case 512:
2799 		value = 0;
2800 		break;
2801 
2802 	case 1024:
2803 		value = 1;
2804 		break;
2805 
2806 	case 2048:
2807 		value = 2;
2808 		break;
2809 
2810 	case 4096:
2811 		value = 3;
2812 		break;
2813 
2814 	default:
2815 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2816 		    "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
2817 		    cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
2818 
2819 		cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
2820 		goto xlate;
2821 	}
2822 
2823 	if ((mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)),
2824 	    KM_SLEEP)) == 0) {
2825 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2826 		    "PCI_MAX_READ: Unable to allocate mailbox buffer.");
2827 		return;
2828 	}
2829 	mb = (MAILBOX *)mbq;
2830 
2831 	emlxs_mb_set_var(hba, mbq, 0x00100506, value);
2832 
2833 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2834 		if (verbose || (mb->mbxStatus != 0x12)) {
2835 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2836 			    "PCI_MAX_READ: Unable to update. "
2837 			    "status=%x value=%d (%d bytes)",
2838 			    mb->mbxStatus, value,
2839 			    cfg[CFG_PCI_MAX_READ].current);
2840 		}
2841 	} else {
2842 		if (verbose &&
2843 		    (cfg[CFG_PCI_MAX_READ].current !=
2844 		    cfg[CFG_PCI_MAX_READ].def)) {
2845 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2846 			    "PCI_MAX_READ: Updated. %d bytes",
2847 			    cfg[CFG_PCI_MAX_READ].current);
2848 		}
2849 	}
2850 
2851 	(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
2852 
2853 	return;
2854 
2855 } /* emlxs_pcix_mxr_update */
2856 
2857 
2858 
2859 extern uint32_t
emlxs_get_key(emlxs_hba_t * hba,MAILBOXQ * mbq)2860 emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
2861 {
2862 	emlxs_port_t *port = &PPORT;
2863 	MAILBOX *mb = (MAILBOX *)mbq;
2864 	uint32_t npname0, npname1;
2865 	uint32_t tmpkey, theKey;
2866 	uint16_t key850;
2867 	uint32_t t1, t2, t3, t4;
2868 	uint32_t ts;
2869 
2870 #define	SEED 0x876EDC21
2871 
2872 	/* This key is only used currently for SBUS adapters */
2873 	if (hba->bus_type != SBUS_FC) {
2874 		return (0);
2875 	}
2876 
2877 	tmpkey = mb->un.varWords[30];
2878 	EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
2879 
2880 	emlxs_mb_read_nv(hba, mbq);
2881 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2882 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2883 		    "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
2884 		    mb->mbxStatus);
2885 
2886 		return (0);
2887 	}
2888 	npname0 = mb->un.varRDnvp.portname[0];
2889 	npname1 = mb->un.varRDnvp.portname[1];
2890 
2891 	key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
2892 	ts = (uint16_t)(npname1 + 1);
2893 	t1 = ts * key850;
2894 	ts = (uint16_t)((npname1 >> 16) + 1);
2895 	t2 = ts * key850;
2896 	ts = (uint16_t)(npname0 + 1);
2897 	t3 = ts * key850;
2898 	ts = (uint16_t)((npname0 >> 16) + 1);
2899 	t4 = ts * key850;
2900 	theKey = SEED + t1 + t2 + t3 + t4;
2901 
2902 	return (theKey);
2903 
2904 } /* emlxs_get_key() */
2905 
2906 
2907 extern void
emlxs_fw_show(emlxs_hba_t * hba)2908 emlxs_fw_show(emlxs_hba_t *hba)
2909 {
2910 	emlxs_port_t *port = &PPORT;
2911 	uint32_t i;
2912 
2913 	/* Display firmware library one time */
2914 	for (i = 0; i < emlxs_fw_count; i++) {
2915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
2916 		    emlxs_fw_table[i].label);
2917 	}
2918 
2919 	return;
2920 
2921 } /* emlxs_fw_show() */
2922 
2923 
2924 #ifdef MODFW_SUPPORT
2925 extern void
emlxs_fw_load(emlxs_hba_t * hba,emlxs_firmware_t * fw)2926 emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2927 {
2928 	emlxs_port_t *port = &PPORT;
2929 	int (*emlxs_fw_get)(emlxs_firmware_t *);
2930 	int err;
2931 	char name[64];
2932 
2933 	/* Make sure image is unloaded and image buffer pointer is clear */
2934 	emlxs_fw_unload(hba, fw);
2935 
2936 	err = 0;
2937 	hba->fw_modhandle =
2938 	    ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
2939 	if (!hba->fw_modhandle) {
2940 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2941 		    "Unable to load firmware module. error=%d", err);
2942 
2943 		return;
2944 	} else {
2945 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2946 		    "Firmware module loaded.");
2947 	}
2948 
2949 	(void) snprintf(name, sizeof (name), "%s_fw_get", DRIVER_NAME);
2950 	err = 0;
2951 	emlxs_fw_get =
2952 	    (int (*)())ddi_modsym(hba->fw_modhandle, name, &err);
2953 	if ((void *)emlxs_fw_get == NULL) {
2954 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2955 		    "%s not present. error=%d", name, err);
2956 
2957 		emlxs_fw_unload(hba, fw);
2958 		return;
2959 	}
2960 
2961 	if (emlxs_fw_get(fw)) {
2962 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2963 		    "Invalid firmware image module found. %s", fw->label);
2964 
2965 		emlxs_fw_unload(hba, fw);
2966 		return;
2967 	}
2968 
2969 	return;
2970 
2971 } /* emlxs_fw_load() */
2972 
2973 
2974 extern void
emlxs_fw_unload(emlxs_hba_t * hba,emlxs_firmware_t * fw)2975 emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2976 {
2977 	emlxs_port_t *port = &PPORT;
2978 
2979 	/* Clear the firmware image */
2980 	fw->image = NULL;
2981 	fw->size = 0;
2982 
2983 	if (hba->fw_modhandle) {
2984 		/* Close the module */
2985 		(void) ddi_modclose(hba->fw_modhandle);
2986 		hba->fw_modhandle = NULL;
2987 
2988 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2989 		    "Firmware module unloaded.");
2990 	}
2991 
2992 	return;
2993 
2994 } /* emlxs_fw_unload() */
2995 #endif /* MODFW_SUPPORT */
2996 
2997 
2998 static void
emlxs_pci_cap_offsets(emlxs_hba_t * hba)2999 emlxs_pci_cap_offsets(emlxs_hba_t *hba)
3000 {
3001 	emlxs_port_t *port = &PPORT;
3002 	uint32_t reg;
3003 	uint8_t	offset;
3004 	uint8_t	next;
3005 	uint8_t	id;
3006 	uint16_t eoffset;
3007 	uint16_t enext;
3008 	uint8_t eversion;
3009 	uint16_t eid;
3010 
3011 	/* Read PCI capbabilities */
3012 
3013 	bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
3014 
3015 	/* Read first offset */
3016 	offset = PCI_CAP_POINTER;
3017 	offset = ddi_get8(hba->pci_acc_handle,
3018 	    (uint8_t *)(hba->pci_addr + offset));
3019 
3020 	while (offset >= PCI_CAP_PTR_OFF) {
3021 		/* Read the cap */
3022 		reg = ddi_get32(hba->pci_acc_handle,
3023 		    (uint32_t *)(hba->pci_addr + offset));
3024 
3025 		id = ((reg >> PCI_CAP_ID_SHIFT) & PCI_CAP_ID_MASK);
3026 		next = ((reg >> PCI_CAP_NEXT_PTR_SHIFT) &
3027 		    PCI_CAP_NEXT_PTR_MASK);
3028 
3029 		if ((id < PCI_CAP_MAX_PTR) &&
3030 		    (hba->pci_cap_offset[id] == 0)) {
3031 			hba->pci_cap_offset[id] = offset;
3032 		}
3033 
3034 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3035 		    "%s: offset=0x%x next=0x%x",
3036 		    emlxs_pci_cap_xlate(id), offset, next);
3037 
3038 		offset = next;
3039 	}
3040 
3041 	/* Workaround for BE adapters */
3042 	if ((hba->pci_cap_offset[PCI_CAP_ID_VS] == 0) &&
3043 	    (hba->model_info.chip & EMLXS_BE_CHIPS)) {
3044 		hba->pci_cap_offset[PCI_CAP_ID_VS] = 0x54;
3045 
3046 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3047 		    "%s: offset=0x%x  Added.",
3048 		    emlxs_pci_cap_xlate(PCI_CAP_ID_VS),
3049 		    hba->pci_cap_offset[PCI_CAP_ID_VS]);
3050 	}
3051 
3052 	if (! hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) {
3053 		/* It's not a PCIE adapter. */
3054 		return;
3055 	}
3056 
3057 	/* Read PCI Extended capbabilities */
3058 
3059 	bzero(hba->pci_ecap_offset, sizeof (hba->pci_ecap_offset));
3060 
3061 	/* Set first offset */
3062 	eoffset = PCIE_EXT_CAP;
3063 
3064 	while (eoffset >= PCIE_EXT_CAP) {
3065 		/* Read the cap */
3066 		reg = ddi_get32(hba->pci_acc_handle,
3067 		    (uint32_t *)(hba->pci_addr + eoffset));
3068 
3069 		eid = ((reg >> PCIE_EXT_CAP_ID_SHIFT) & PCIE_EXT_CAP_ID_MASK);
3070 		eversion = ((reg >> PCIE_EXT_CAP_VER_SHIFT) &
3071 		    PCIE_EXT_CAP_VER_MASK);
3072 		enext = ((reg >> PCIE_EXT_CAP_NEXT_PTR_SHIFT) &
3073 		    PCIE_EXT_CAP_NEXT_PTR_MASK);
3074 
3075 		if ((eid < PCI_EXT_CAP_MAX_PTR) &&
3076 		    (hba->pci_ecap_offset[eid] == 0)) {
3077 			hba->pci_ecap_offset[eid] = eoffset;
3078 		}
3079 
3080 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3081 		    "%s: offset=0x%x version=0x%x next=0x%x",
3082 		    emlxs_pci_ecap_xlate(eid),
3083 		    eoffset, eversion, enext);
3084 
3085 		eoffset = enext;
3086 	}
3087 
3088 	return;
3089 
3090 } /* emlxs_pci_cap_offsets() */
3091