emlxs_hba.c (82527734) emlxs_hba.c (a9800beb)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 6 unchanged lines hidden (view full) ---

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/*
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 6 unchanged lines hidden (view full) ---

15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Emulex. All rights reserved.
23 * Copyright 2010 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28#define EMLXS_FW_TABLE_DEF
29#define EMLXS_MODEL_DEF
30
31#include <emlxs.h>
32
33/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34EMLXS_MSG_DEF(EMLXS_HBA_C);
35
24 * Use is subject to license terms.
25 */
26
27
28#define EMLXS_FW_TABLE_DEF
29#define EMLXS_MODEL_DEF
30
31#include <emlxs.h>
32
33/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34EMLXS_MSG_DEF(EMLXS_HBA_C);
35
36static uint32_t emlxs_decode_biu_rev(uint32_t rev);
37static uint32_t emlxs_decode_endec_rev(uint32_t rev);
36
38static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
39 IOCBQ *iocbq);
40
37static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
38 IOCBQ *iocbq);
39
40static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
41
41#ifdef MSI_SUPPORT
42uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
43 {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
44uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
45 {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
46 EMLXS_MSI0_MASK8};
47#endif /* MSI_SUPPORT */
48
49emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
50int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
51
42#ifdef MSI_SUPPORT
43uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
44 {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
45uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
46 {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
47 EMLXS_MSI0_MASK8};
48#endif /* MSI_SUPPORT */
49
50emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
51int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
52
53emlxs_table_t emlxs_pci_cap[] = {
54 {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
55 {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
56 {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
57 {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
58 {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
59 {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
60 {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
61 {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
62 {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
63 {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
64 {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
65 {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
66 {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
67 {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
68 {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
69 {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
70 {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
71 {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
72 {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
73
74}; /* emlxs_pci_cap */
75
52emlxs_table_t emlxs_ring_table[] = {
53 {FC_FCP_RING, "FCP Ring"},
54 {FC_IP_RING, "IP Ring"},
55 {FC_ELS_RING, "ELS Ring"},
56 {FC_CT_RING, "CT Ring"}
57
58}; /* emlxs_ring_table */
59
76emlxs_table_t emlxs_ring_table[] = {
77 {FC_FCP_RING, "FCP Ring"},
78 {FC_IP_RING, "IP Ring"},
79 {FC_ELS_RING, "ELS Ring"},
80 {FC_CT_RING, "CT Ring"}
81
82}; /* emlxs_ring_table */
83
60
61emlxs_table_t emlxs_ffstate_table[] = {
62 {0, "NULL"},
63 {FC_ERROR, "ERROR"},
64 {FC_KILLED, "KILLED"},
65 {FC_WARM_START, "WARM_START"},
66 {FC_INIT_START, "INIT_START"},
67 {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
68 {FC_INIT_REV, "INIT_REV"},

--- 175 unchanged lines hidden (view full) ---

244
245 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
246 "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
247
248 if ((ret != DDI_SUCCESS) || (actual == 0)) {
249 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
250 "MSI: Unable to allocate interrupts. error=%d", ret);
251
84emlxs_table_t emlxs_ffstate_table[] = {
85 {0, "NULL"},
86 {FC_ERROR, "ERROR"},
87 {FC_KILLED, "KILLED"},
88 {FC_WARM_START, "WARM_START"},
89 {FC_INIT_START, "INIT_START"},
90 {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
91 {FC_INIT_REV, "INIT_REV"},

--- 175 unchanged lines hidden (view full) ---

267
268 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
269 "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
270
271 if ((ret != DDI_SUCCESS) || (actual == 0)) {
272 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
273 "MSI: Unable to allocate interrupts. error=%d", ret);
274
275 actual = 0;
252 goto init_failed;
253 }
254
255 if (actual != count) {
256 /* Validate actual count */
257 if (actual >= 8) {
258 new_actual = 8;
259 } else if (actual >= 4) {

--- 118 unchanged lines hidden (view full) ---

378
379 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
380 hba->intr_map[i] = emlxs_msi_map[mode][i];
381 hba->intr_cond |= emlxs_msi_map[mode][i];
382
383 (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
384 hba->ddiinst, i);
385 mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
276 goto init_failed;
277 }
278
279 if (actual != count) {
280 /* Validate actual count */
281 if (actual >= 8) {
282 new_actual = 8;
283 } else if (actual >= 4) {

--- 118 unchanged lines hidden (view full) ---

402
403 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
404 hba->intr_map[i] = emlxs_msi_map[mode][i];
405 hba->intr_cond |= emlxs_msi_map[mode][i];
406
407 (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
408 hba->ddiinst, i);
409 mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
386 (void *)hba->intr_arg);
410 DDI_INTR_PRI(hba->intr_arg));
387 }
388
389 /* Set flag to indicate support */
390 hba->intr_flags |= EMLXS_MSI_INITED;
391
392 /* Create the interrupt threads */
393 for (i = 0; i < hba->chan_count; i++) {
394 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
395 hba->ddiinst, i);
396 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
411 }
412
413 /* Set flag to indicate support */
414 hba->intr_flags |= EMLXS_MSI_INITED;
415
416 /* Create the interrupt threads */
417 for (i = 0; i < hba->chan_count; i++) {
418 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
419 hba->ddiinst, i);
420 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
397 (void *)hba->intr_arg);
421 DDI_INTR_PRI(hba->intr_arg));
398
399 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
400 }
401
402 return (DDI_SUCCESS);
403
404init_failed:
405

--- 381 unchanged lines hidden (view full) ---

787 hba->chan_count = cfg[CFG_NUM_WQ].current;
788 }
789
790 /* Create the interrupt threads */
791 for (i = 0; i < hba->chan_count; i++) {
792 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
793 hba->ddiinst, i);
794 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
422
423 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
424 }
425
426 return (DDI_SUCCESS);
427
428init_failed:
429

--- 381 unchanged lines hidden (view full) ---

811 hba->chan_count = cfg[CFG_NUM_WQ].current;
812 }
813
814 /* Create the interrupt threads */
815 for (i = 0; i < hba->chan_count; i++) {
816 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
817 hba->ddiinst, i);
818 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
795 (void *)hba->intr_arg);
819 DDI_INTR_PRI(hba->intr_arg));
796
797 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
798 }
799
800 return (DDI_SUCCESS);
801
802} /* emlxs_intx_init() */
803

--- 448 unchanged lines hidden (view full) ---

1252 sizeof (tlv_fcfconnectlist_t));
1253 }
1254
1255 return (1);
1256
1257} /* emlxs_parse_fcoe */
1258
1259
820
821 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
822 }
823
824 return (DDI_SUCCESS);
825
826} /* emlxs_intx_init() */
827

--- 448 unchanged lines hidden (view full) ---

1276 sizeof (tlv_fcfconnectlist_t));
1277 }
1278
1279 return (1);
1280
1281} /* emlxs_parse_fcoe */
1282
1283
1260
1261static uint32_t
1262emlxs_decode_biu_rev(uint32_t rev)
1263{
1264 return (rev & 0xf);
1265} /* End emlxs_decode_biu_rev */
1266
1267
1268static uint32_t
1269emlxs_decode_endec_rev(uint32_t rev)
1270{
1271 return ((rev >> 28) & 0xf);
1272} /* End emlxs_decode_endec_rev */
1273
1274
1275extern void
1276emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1277{
1278 if (vpd->rBit) {
1279 switch (hba->sli_mode) {
1280 case EMLXS_HBA_SLI4_MODE:
1281 (void) strcpy(vpd->fw_version, vpd->sli4FwName);
1282 (void) strcpy(vpd->fw_label, vpd->sli4FwLabel);

--- 730 unchanged lines hidden (view full) ---

2013 * due to a PCI bus issue
2014 */
2015 if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2016 hba->model_info.flags &=
2017 ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2018 }
2019#endif /* !SATURN_MSI_SUPPORT */
2020
1284extern void
1285emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1286{
1287 if (vpd->rBit) {
1288 switch (hba->sli_mode) {
1289 case EMLXS_HBA_SLI4_MODE:
1290 (void) strcpy(vpd->fw_version, vpd->sli4FwName);
1291 (void) strcpy(vpd->fw_label, vpd->sli4FwLabel);

--- 730 unchanged lines hidden (view full) ---

2022 * due to a PCI bus issue
2023 */
2024 if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2025 hba->model_info.flags &=
2026 ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2027 }
2028#endif /* !SATURN_MSI_SUPPORT */
2029
2030 /* Scan the PCI capabilities */
2031 emlxs_pci_cap_offsets(hba);
2021
2022#ifdef MSI_SUPPORT
2023 /* Verify MSI support */
2032
2033#ifdef MSI_SUPPORT
2034 /* Verify MSI support */
2024 if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) {
2025 uint32_t offset;
2026 uint32_t reg;
2027
2028 /* Scan for MSI capabilities register */
2029 offset =
2030 ddi_get32(hba->pci_acc_handle,
2031 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
2032 offset &= 0xff;
2033
2034 while (offset) {
2035 reg =
2036 ddi_get32(hba->pci_acc_handle,
2037 (uint32_t *)(hba->pci_addr + offset));
2038
2039 if ((reg & 0xff) == MSI_CAP_ID) {
2040 break;
2041 }
2042 offset = (reg >> 8) & 0xff;
2043 }
2044
2045 if (offset) {
2046 hba->msi_cap_offset = offset + 2;
2047 } else {
2048 hba->msi_cap_offset = 0;
2049 hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2050
2051 EMLXS_MSGF(EMLXS_CONTEXT,
2052 &emlxs_init_debug_msg,
2053 "MSI: control_reg capability not found!");
2054 }
2035 if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
2036 !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
2037 hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2055 }
2056
2057 /* Verify MSI-X support */
2038 }
2039
2040 /* Verify MSI-X support */
2058 if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) {
2059 uint32_t offset;
2060 uint32_t reg;
2061
2062 /* Scan for MSI capabilities register */
2063 offset =
2064 ddi_get32(hba->pci_acc_handle,
2065 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER));
2066 offset &= 0xff;
2067
2068 while (offset) {
2069 reg =
2070 ddi_get32(hba->pci_acc_handle,
2071 (uint32_t *)(hba->pci_addr + offset));
2072
2073 if ((reg & 0xff) == MSIX_CAP_ID) {
2074 break;
2075 }
2076 offset = (reg >> 8) & 0xff;
2077 }
2078
2079 if (offset) {
2080 hba->msix_cap_offset = offset;
2081 } else {
2082 hba->msix_cap_offset = 0;
2083 hba->model_info.flags &=
2084 ~EMLXS_MSIX_SUPPORTED;
2085
2086 EMLXS_MSGF(EMLXS_CONTEXT,
2087 &emlxs_init_debug_msg,
2088 "MSIX: control_reg capability not found!");
2089 }
2041 if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
2042 !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
2043 hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
2090 }
2091#endif /* MSI_SUPPORT */
2044 }
2045#endif /* MSI_SUPPORT */
2092
2093 }
2094
2095 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2096 "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
2097 /* Parse the property for PCI function, device and bus no. */
2098 hba->pci_function_number =
2099 (uint8_t)((prop[0] & 0x00000700) >> 8);
2100 hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);

--- 202 unchanged lines hidden (view full) ---

2303 emlxs_port_t *port = &PPORT;
2304 char buffer[MAX_MSG_DATA + 1];
2305 IOCB *iocb;
2306 emlxs_buf_t *sbp;
2307
2308 iocb = &iocbq->iocb;
2309
2310#ifdef DEBUG_CMPL_IOCB
2046 }
2047
2048 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2049 "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
2050 /* Parse the property for PCI function, device and bus no. */
2051 hba->pci_function_number =
2052 (uint8_t)((prop[0] & 0x00000700) >> 8);
2053 hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);

--- 202 unchanged lines hidden (view full) ---

2256 emlxs_port_t *port = &PPORT;
2257 char buffer[MAX_MSG_DATA + 1];
2258 IOCB *iocb;
2259 emlxs_buf_t *sbp;
2260
2261 iocb = &iocbq->iocb;
2262
2263#ifdef DEBUG_CMPL_IOCB
2311 emlxs_data_dump(hba, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2264 emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2312#endif
2313
2314 sbp = (emlxs_buf_t *)iocbq->sbp;
2315 if (sbp) {
2316 if (!(sbp->pkt_flags & PACKET_VALID) ||
2317 (sbp->pkt_flags & (PACKET_ULP_OWNED |
2318 PACKET_IN_COMPLETION))) {
2319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,

--- 291 unchanged lines hidden (view full) ---

2611 }
2612
2613 (void) sprintf(buffer, "ring=0x%x", ringno);
2614 return (buffer);
2615
2616} /* emlxs_ring_xlate() */
2617
2618
2265#endif
2266
2267 sbp = (emlxs_buf_t *)iocbq->sbp;
2268 if (sbp) {
2269 if (!(sbp->pkt_flags & PACKET_VALID) ||
2270 (sbp->pkt_flags & (PACKET_ULP_OWNED |
2271 PACKET_IN_COMPLETION))) {
2272 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,

--- 291 unchanged lines hidden (view full) ---

2564 }
2565
2566 (void) sprintf(buffer, "ring=0x%x", ringno);
2567 return (buffer);
2568
2569} /* emlxs_ring_xlate() */
2570
2571
2572extern char *
2573emlxs_pci_cap_xlate(uint32_t id)
2574{
2575 static char buffer[32];
2576 uint32_t i;
2577 uint32_t count;
2619
2578
2579 count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
2580 for (i = 0; i < count; i++) {
2581 if (id == emlxs_pci_cap[i].code) {
2582 return (emlxs_pci_cap[i].string);
2583 }
2584 }
2585
2586 (void) sprintf(buffer, "PCI_CAP_ID_%02X", id);
2587 return (buffer);
2588
2589} /* emlxs_pci_cap_xlate() */
2590
2591
2620extern void
2621emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2622{
2623 emlxs_port_t *port = &PPORT;
2624 MAILBOXQ *mbq;
2625 MAILBOX *mb;
2626 emlxs_config_t *cfg;
2627 uint32_t value;

--- 50 unchanged lines hidden (view full) ---

2678 (cfg[CFG_PCI_MAX_READ].current !=
2679 cfg[CFG_PCI_MAX_READ].def)) {
2680 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2681 "PCI_MAX_READ: Updated. %d bytes",
2682 cfg[CFG_PCI_MAX_READ].current);
2683 }
2684 }
2685
2592extern void
2593emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2594{
2595 emlxs_port_t *port = &PPORT;
2596 MAILBOXQ *mbq;
2597 MAILBOX *mb;
2598 emlxs_config_t *cfg;
2599 uint32_t value;

--- 50 unchanged lines hidden (view full) ---

2650 (cfg[CFG_PCI_MAX_READ].current !=
2651 cfg[CFG_PCI_MAX_READ].def)) {
2652 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2653 "PCI_MAX_READ: Updated. %d bytes",
2654 cfg[CFG_PCI_MAX_READ].current);
2655 }
2656 }
2657
2686 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
2658 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2687
2688 return;
2689
2690} /* emlxs_pcix_mxr_update */
2691
2692
2693
2694extern uint32_t

--- 126 unchanged lines hidden (view full) ---

2821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2822 "Firmware module unloaded.");
2823 }
2824
2825 return;
2826
2827} /* emlxs_fw_unload() */
2828#endif /* MODFW_SUPPORT */
2659
2660 return;
2661
2662} /* emlxs_pcix_mxr_update */
2663
2664
2665
2666extern uint32_t

--- 126 unchanged lines hidden (view full) ---

2793 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2794 "Firmware module unloaded.");
2795 }
2796
2797 return;
2798
2799} /* emlxs_fw_unload() */
2800#endif /* MODFW_SUPPORT */
2801
2802
2803static void
2804emlxs_pci_cap_offsets(emlxs_hba_t *hba)
2805{
2806 emlxs_port_t *port = &PPORT;
2807 uint8_t offset;
2808 uint8_t id;
2809
2810 bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
2811
2812 /* Read first offset */
2813 offset = ddi_get8(hba->pci_acc_handle,
2814 (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER));
2815 offset &= PCI_CAP_PTR_MASK;
2816
2817 while (offset >= PCI_CAP_PTR_OFF) {
2818 /* Read the next cap id */
2819 id = ddi_get8(hba->pci_acc_handle,
2820 (uint8_t *)(hba->pci_addr + offset));
2821
2822 if (id < PCI_CAP_MAX_PTR) {
2823 hba->pci_cap_offset[id] = offset;
2824 }
2825
2826 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2827 "%s: offset=0x%x",
2828 emlxs_pci_cap_xlate(id), offset);
2829
2830 /* Read next offset */
2831 offset = ddi_get8(hba->pci_acc_handle,
2832 (uint8_t *)(hba->pci_addr + offset + PCI_CAP_NEXT_PTR));
2833 offset &= PCI_CAP_PTR_MASK;
2834 }
2835
2836 return;
2837
2838} /* emlxs_pci_cap_offsets() */