/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c
C | 2838 lines | 1935 code | 556 blank | 347 comment | 472 complexity | 1a0264f2a4fca20c3eef54eb84eaf7fe MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, LGPL-2.0, 0BSD, AGPL-3.0, GPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0
- /*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
- /*
- * Copyright 2010 Emulex. All rights reserved.
- * Use is subject to license terms.
- */
- #define EMLXS_FW_TABLE_DEF
- #define EMLXS_MODEL_DEF
- #include <emlxs.h>
- /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
- EMLXS_MSG_DEF(EMLXS_HBA_C);
- static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
- IOCBQ *iocbq);
- static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
- #ifdef MSI_SUPPORT
- uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
- {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
- uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
- {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
- EMLXS_MSI0_MASK8};
- #endif /* MSI_SUPPORT */
- emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
- int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
- emlxs_table_t emlxs_pci_cap[] = {
- {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
- {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
- {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
- {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
- {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
- {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
- {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
- {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
- {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
- {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
- {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
- {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
- {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
- {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
- {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
- {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
- {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
- {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
- {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
- }; /* emlxs_pci_cap */
- emlxs_table_t emlxs_ring_table[] = {
- {FC_FCP_RING, "FCP Ring"},
- {FC_IP_RING, "IP Ring"},
- {FC_ELS_RING, "ELS Ring"},
- {FC_CT_RING, "CT Ring"}
- }; /* emlxs_ring_table */
- emlxs_table_t emlxs_ffstate_table[] = {
- {0, "NULL"},
- {FC_ERROR, "ERROR"},
- {FC_KILLED, "KILLED"},
- {FC_WARM_START, "WARM_START"},
- {FC_INIT_START, "INIT_START"},
- {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
- {FC_INIT_REV, "INIT_REV"},
- {FC_INIT_CFGPORT, "INIT_CFGPORT"},
- {FC_INIT_CFGRING, "INIT_CFGRING"},
- {FC_INIT_INITLINK, "INIT_INITLINK"},
- {FC_LINK_DOWN, "LINK_DOWN"},
- {FC_LINK_UP, "LINK_UP"},
- {FC_CLEAR_LA, "CLEAR_LA"},
- {FC_READY, "READY"}
- }; /* emlxs_ffstate_table */
- #ifdef MSI_SUPPORT
- /* EMLXS_INTR_INIT */
- int32_t
- emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
- {
- emlxs_port_t *port = &PPORT;
- int32_t pass = 0;
- int32_t type = 0;
- char s_type[16];
- int32_t types;
- int32_t count;
- int32_t nintrs;
- int32_t mode;
- int32_t actual;
- int32_t new_actual;
- int32_t i;
- int32_t ret;
- ddi_intr_handle_t *htable = NULL;
- ddi_intr_handle_t *new_htable = NULL;
- uint32_t *intr_pri = NULL;
- int32_t *intr_cap = NULL;
- int32_t hilevel_pri;
- emlxs_config_t *cfg = &CFG;
- char buf[64];
- if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
- return (emlxs_intx_init(hba, max));
- }
- if (hba->intr_flags & EMLXS_MSI_INITED) {
- return (DDI_SUCCESS);
- }
- /* Set max interrupt count if not specified */
- if (max == 0) {
- if ((cfg[CFG_MSI_MODE].current == 2) ||
- (cfg[CFG_MSI_MODE].current == 3)) {
- max = EMLXS_MSI_MAX_INTRS;
- } else {
- max = 1;
- }
- }
- /* Filter max interrupt count with adapter model specification */
- if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
- max = hba->model_info.intr_limit;
- }
- /* Get the available interrupt types from the kernel */
- types = 0;
- ret = ddi_intr_get_supported_types(hba->dip, &types);
- if ((ret != DDI_SUCCESS)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
- /* Default to fixed type */
- types = DDI_INTR_TYPE_FIXED;
- }
- /* Check if fixed interrupts are being forced */
- if (cfg[CFG_MSI_MODE].current == 0) {
- types &= DDI_INTR_TYPE_FIXED;
- }
- /* Check if MSI interrupts are being forced */
- else if ((cfg[CFG_MSI_MODE].current == 1) ||
- (cfg[CFG_MSI_MODE].current == 2)) {
- types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
- }
- begin:
- /* Set interrupt type and interrupt count */
- type = 0;
- /* Check if MSIX is fully supported */
- if ((types & DDI_INTR_TYPE_MSIX) &&
- (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
- /* Get the max interrupt count from the adapter */
- nintrs = 0;
- ret =
- ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
- &nintrs);
- if (ret == DDI_SUCCESS && nintrs) {
- type = DDI_INTR_TYPE_MSIX;
- (void) strcpy(s_type, "TYPE_MSIX");
- goto initialize;
- }
- }
- /* Check if MSI is fully supported */
- if ((types & DDI_INTR_TYPE_MSI) &&
- (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
- /* Get the max interrupt count from the adapter */
- nintrs = 0;
- ret =
- ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
- if (ret == DDI_SUCCESS && nintrs) {
- type = DDI_INTR_TYPE_MSI;
- (void) strcpy(s_type, "TYPE_MSI");
- goto initialize;
- }
- }
- /* Check if fixed interrupts are fully supported */
- if ((types & DDI_INTR_TYPE_FIXED) &&
- (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
- /* Get the max interrupt count from the adapter */
- nintrs = 0;
- ret =
- ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
- &nintrs);
- if (ret == DDI_SUCCESS) {
- type = DDI_INTR_TYPE_FIXED;
- (void) strcpy(s_type, "TYPE_FIXED");
- goto initialize;
- }
- }
- goto init_failed;
- initialize:
- pass++;
- mode = 0;
- actual = 0;
- htable = NULL;
- intr_pri = NULL;
- intr_cap = NULL;
- hilevel_pri = 0;
- if (pass == 1) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
- cfg[CFG_MSI_MODE].current, types, nintrs);
- }
- /* Validate interrupt count */
- count = min(nintrs, max);
- if (count >= 8) {
- count = 8;
- } else if (count >= 4) {
- count = 4;
- } else if (count >= 2) {
- count = 2;
- } else {
- count = 1;
- }
- /* Allocate an array of interrupt handles */
- htable =
- kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
- KM_SLEEP);
- /* Allocate 'count' interrupts */
- ret =
- ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
- &actual, DDI_INTR_ALLOC_NORMAL);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
- if ((ret != DDI_SUCCESS) || (actual == 0)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: Unable to allocate interrupts. error=%d", ret);
- actual = 0;
- goto init_failed;
- }
- if (actual != count) {
- /* Validate actual count */
- if (actual >= 8) {
- new_actual = 8;
- } else if (actual >= 4) {
- new_actual = 4;
- } else if (actual >= 2) {
- new_actual = 2;
- } else {
- new_actual = 1;
- }
- if (new_actual < actual) {
- /* Free extra handles */
- for (i = new_actual; i < actual; i++) {
- (void) ddi_intr_free(htable[i]);
- }
- actual = new_actual;
- }
- /* Allocate a new array of interrupt handles */
- new_htable =
- kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
- KM_SLEEP);
- /* Copy old array to new array */
- bcopy((uint8_t *)htable, (uint8_t *)new_htable,
- (actual * sizeof (ddi_intr_handle_t)));
- /* Free the old array */
- kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
- htable = new_htable;
- count = actual;
- }
- /* Allocate interrupt priority table */
- intr_pri =
- (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
- KM_SLEEP);
- /* Allocate interrupt capability table */
- intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
- /* Get minimum hilevel priority */
- hilevel_pri = ddi_intr_get_hilevel_pri();
- /* Fill the priority and capability tables */
- for (i = 0; i < count; ++i) {
- ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: ddi_intr_get_pri(%d) failed. "
- "handle=%p ret=%d",
- i, &htable[i], ret);
- /* Clean up the interrupts */
- goto init_failed;
- }
- if (intr_pri[i] >= hilevel_pri) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: Interrupt(%d) level too high. "
- "pri=0x%x hilevel=0x%x",
- i, intr_pri[i], hilevel_pri);
- /* Clean up the interrupts */
- goto init_failed;
- }
- ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: ddi_intr_get_cap(%d) failed. "
- "handle=%p ret=%d",
- i, &htable[i], ret);
- /* Clean up the interrupts */
- goto init_failed;
- }
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
- intr_cap[i], intr_pri[i], hilevel_pri);
- }
- /* Set mode */
- switch (count) {
- case 8:
- mode = EMLXS_MSI_MODE8;
- break;
- case 4:
- mode = EMLXS_MSI_MODE4;
- break;
- case 2:
- mode = EMLXS_MSI_MODE2;
- break;
- default:
- mode = EMLXS_MSI_MODE1;
- }
- /* Save the info */
- hba->intr_htable = htable;
- hba->intr_count = count;
- hba->intr_pri = intr_pri;
- hba->intr_cap = intr_cap;
- hba->intr_type = type;
- hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
- hba->intr_mask = emlxs_msi_mask[mode];
- hba->intr_cond = 0;
- /* Adjust number of channels based on intr_count */
- if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
- hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
- }
- for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
- hba->intr_map[i] = emlxs_msi_map[mode][i];
- hba->intr_cond |= emlxs_msi_map[mode][i];
- (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
- hba->ddiinst, i);
- mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
- DDI_INTR_PRI(hba->intr_arg));
- }
- /* Set flag to indicate support */
- hba->intr_flags |= EMLXS_MSI_INITED;
- /* Create the interrupt threads */
- for (i = 0; i < hba->chan_count; i++) {
- (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
- hba->ddiinst, i);
- mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
- DDI_INTR_PRI(hba->intr_arg));
- emlxs_thread_create(hba, &hba->chan[i].intr_thread);
- }
- return (DDI_SUCCESS);
- init_failed:
- if (intr_cap) {
- kmem_free(intr_cap, (count * sizeof (int32_t)));
- }
- if (intr_pri) {
- kmem_free(intr_pri, (count * sizeof (int32_t)));
- }
- if (htable) {
- /* Process the interrupt handlers */
- for (i = 0; i < actual; i++) {
- /* Free the handle[i] */
- (void) ddi_intr_free(htable[i]);
- }
- kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
- }
- /* Initialize */
- hba->intr_htable = NULL;
- hba->intr_count = 0;
- hba->intr_pri = NULL;
- hba->intr_cap = NULL;
- hba->intr_type = 0;
- hba->intr_arg = NULL;
- hba->intr_cond = 0;
- bzero(hba->intr_map, sizeof (hba->intr_map));
- bzero(hba->intr_lock, sizeof (hba->intr_lock));
- if (type == DDI_INTR_TYPE_MSIX) {
- types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
- goto begin;
- } else if (type == DDI_INTR_TYPE_MSI) {
- types &= DDI_INTR_TYPE_FIXED;
- goto begin;
- }
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "MSI: Unable to initialize interrupts");
- return (DDI_FAILURE);
- } /* emlxs_msi_init() */
- /* EMLXS_INTR_UNINIT */
- int32_t
- emlxs_msi_uninit(emlxs_hba_t *hba)
- {
- uint32_t count;
- int32_t i;
- ddi_intr_handle_t *htable;
- uint32_t *intr_pri;
- int32_t *intr_cap;
- int32_t ret;
- if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
- return (emlxs_intx_uninit(hba));
- }
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- * "MSI: emlxs_msi_uninit called. flags=%x",
- * hba->intr_flags);
- */
- /* Make sure interrupts have been removed first */
- if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
- ret = emlxs_msi_remove(hba);
- if (ret != DDI_SUCCESS) {
- return (ret);
- }
- }
- /* Check if the interrupts are still initialized */
- if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
- return (DDI_SUCCESS);
- }
- hba->intr_flags &= ~EMLXS_MSI_INITED;
- /* Get handle table parameters */
- htable = hba->intr_htable;
- count = hba->intr_count;
- intr_pri = hba->intr_pri;
- intr_cap = hba->intr_cap;
- /* Clean up */
- hba->intr_count = 0;
- hba->intr_htable = NULL;
- hba->intr_pri = NULL;
- hba->intr_cap = NULL;
- hba->intr_type = 0;
- hba->intr_arg = NULL;
- hba->intr_cond = 0;
- bzero(hba->intr_map, sizeof (hba->intr_map));
- if (intr_cap) {
- kmem_free(intr_cap, (count * sizeof (int32_t)));
- }
- if (intr_pri) {
- kmem_free(intr_pri, (count * sizeof (int32_t)));
- }
- if (htable) {
- /* Process the interrupt handlers */
- for (i = 0; i < count; ++i) {
- /* Free the handle[i] */
- ret = ddi_intr_free(htable[i]);
- }
- kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
- }
- /* Destroy the intr locks */
- for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
- mutex_destroy(&hba->intr_lock[i]);
- }
- /* Destroy the interrupt threads */
- for (i = 0; i < hba->chan_count; i++) {
- emlxs_thread_destroy(&hba->chan[i].intr_thread);
- mutex_destroy(&hba->chan[i].rsp_lock);
- }
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- * "MSI: emlxs_msi_uninit done. flags=%x",
- * hba->intr_flags);
- */
- return (DDI_SUCCESS);
- } /* emlxs_msi_uninit() */
- /* EMLXS_INTR_ADD */
- int32_t
- emlxs_msi_add(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- int32_t count;
- int32_t i;
- int32_t ret;
- ddi_intr_handle_t *htable = NULL;
- int32_t *intr_cap = NULL;
- if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
- return (emlxs_intx_add(hba));
- }
- /* Check if interrupts have already been added */
- if (hba->intr_flags & EMLXS_MSI_ADDED) {
- return (DDI_SUCCESS);
- }
- /* Check if interrupts have been initialized */
- if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
- ret = emlxs_msi_init(hba, 0);
- if (ret != DDI_SUCCESS) {
- return (ret);
- }
- }
- /* Get handle table parameters */
- htable = hba->intr_htable;
- count = hba->intr_count;
- intr_cap = hba->intr_cap;
- /* Add the interrupt handlers */
- for (i = 0; i < count; ++i) {
- /* add handler for handle[i] */
- ret =
- ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
- (char *)hba, (char *)((unsigned long)i));
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "MSI: ddi_intr_add_handler(%d) failed. "
- "handle=%p ret=%d",
- i, &htable[i], ret);
- /* Process the remaining interrupt handlers */
- while (i) {
- /* Decrement i */
- i--;
- /* Remove the handler */
- ret = ddi_intr_remove_handler(htable[i]);
- }
- return (DDI_FAILURE);
- }
- }
- /* Enable the interrupts */
- if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
- ret = ddi_intr_block_enable(htable, count);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
- count, ret);
- for (i = 0; i < count; ++i) {
- ret = ddi_intr_enable(htable[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_init_debug_msg,
- "MSI: ddi_intr_enable(%d) failed. "
- "ret=%d",
- i, ret);
- }
- }
- }
- } else {
- for (i = 0; i < count; ++i) {
- ret = ddi_intr_enable(htable[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_init_debug_msg,
- "MSI: ddi_intr_enable(%d) failed. ret=%d",
- i, ret);
- }
- }
- }
- /* Set flag to indicate support */
- hba->intr_flags |= EMLXS_MSI_ADDED;
- return (DDI_SUCCESS);
- } /* emlxs_msi_add() */
- /* EMLXS_INTR_REMOVE */
- int32_t
- emlxs_msi_remove(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- uint32_t count;
- int32_t i;
- ddi_intr_handle_t *htable;
- int32_t *intr_cap;
- int32_t ret;
- if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
- return (emlxs_intx_remove(hba));
- }
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- * "MSI: emlxs_msi_remove called. flags=%x",
- * hba->intr_flags);
- */
- /* Check if interrupts have already been removed */
- if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
- return (DDI_SUCCESS);
- }
- hba->intr_flags &= ~EMLXS_MSI_ADDED;
- /* Disable all adapter interrupts */
- EMLXS_SLI_DISABLE_INTR(hba, 0);
- /* Get handle table parameters */
- htable = hba->intr_htable;
- count = hba->intr_count;
- intr_cap = hba->intr_cap;
- /* Disable the interrupts */
- if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
- ret = ddi_intr_block_disable(htable, count);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
- count, ret);
- for (i = 0; i < count; i++) {
- ret = ddi_intr_disable(htable[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_init_debug_msg,
- "MSI: ddi_intr_disable(%d) failed. "
- "ret=%d",
- i, ret);
- }
- }
- }
- } else {
- for (i = 0; i < count; i++) {
- ret = ddi_intr_disable(htable[i]);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_init_debug_msg,
- "MSI: ddi_intr_disable(%d) failed. ret=%d",
- i, ret);
- }
- }
- }
- /* Process the interrupt handlers */
- for (i = 0; i < count; i++) {
- /* Remove the handler */
- ret = ddi_intr_remove_handler(htable[i]);
- }
- return (DDI_SUCCESS);
- } /* emlxs_msi_remove() */
- #endif /* MSI_SUPPORT */
- /* EMLXS_INTR_INIT */
- /* ARGSUSED */
- int32_t
- emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
- {
- emlxs_port_t *port = &PPORT;
- emlxs_config_t *cfg = &CFG;
- int32_t ret;
- uint32_t i;
- char buf[64];
- /* Check if interrupts have already been initialized */
- if (hba->intr_flags & EMLXS_INTX_INITED) {
- return (DDI_SUCCESS);
- }
- /* Check if adapter is flagged for INTX support */
- if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "INTX: %s does not support INTX. flags=0x%x",
- hba->model_info.model, hba->model_info.flags);
- return (DDI_FAILURE);
- }
- /*
- * Interrupt number '0' is a high-level interrupt. This driver
- * does not support having its interrupts mapped above scheduler
- * priority; i.e., we always expect to be able to call general
- * kernel routines that may invoke the scheduler.
- */
- if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "INTX: High-level interrupt not supported.");
- return (DDI_FAILURE);
- }
- /* Get an iblock cookie */
- ret =
- ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
- (ddi_iblock_cookie_t *)&hba->intr_arg);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
- return (ret);
- }
- hba->intr_flags |= EMLXS_INTX_INITED;
- hba->intr_count = 1;
- /* Adjust number of channels based on intr_count */
- if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
- hba->chan_count = cfg[CFG_NUM_WQ].current;
- }
- /* Create the interrupt threads */
- for (i = 0; i < hba->chan_count; i++) {
- (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
- hba->ddiinst, i);
- mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
- DDI_INTR_PRI(hba->intr_arg));
- emlxs_thread_create(hba, &hba->chan[i].intr_thread);
- }
- return (DDI_SUCCESS);
- } /* emlxs_intx_init() */
- /* EMLXS_INTR_UNINIT */
- int32_t
- emlxs_intx_uninit(emlxs_hba_t *hba)
- {
- int32_t ret;
- uint32_t i;
- /* Make sure interrupts have been removed */
- if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
- ret = emlxs_intx_remove(hba);
- if (ret != DDI_SUCCESS) {
- return (ret);
- }
- }
- /* Check if the interrupts are still initialized */
- if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
- return (DDI_SUCCESS);
- }
- hba->intr_flags &= ~EMLXS_INTX_INITED;
- hba->intr_arg = NULL;
- /* Create the interrupt threads */
- for (i = 0; i < hba->chan_count; i++) {
- emlxs_thread_destroy(&hba->chan[i].intr_thread);
- mutex_destroy(&hba->chan[i].rsp_lock);
- }
- return (DDI_SUCCESS);
- } /* emlxs_intx_uninit() */
- /*
- * This is the legacy method for adding interrupts in Solaris
- * EMLXS_INTR_ADD
- */
- int32_t
- emlxs_intx_add(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- int32_t ret;
- /* Check if interrupts have already been added */
- if (hba->intr_flags & EMLXS_INTX_ADDED) {
- return (DDI_SUCCESS);
- }
- /* Check if interrupts have been initialized */
- if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
- ret = emlxs_intx_init(hba, 0);
- if (ret != DDI_SUCCESS) {
- return (ret);
- }
- }
- /* add intrrupt handler routine */
- ret = ddi_add_intr((void *)hba->dip,
- (uint_t)EMLXS_INUMBER,
- (ddi_iblock_cookie_t *)&hba->intr_arg,
- (ddi_idevice_cookie_t *)0,
- (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
- if (ret != DDI_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
- "INTX: ddi_add_intr failed. ret=%d", ret);
- return (ret);
- }
- hba->intr_flags |= EMLXS_INTX_ADDED;
- return (DDI_SUCCESS);
- } /* emlxs_intx_add() */
- /* EMLXS_INTR_REMOVE */
- int32_t
- emlxs_intx_remove(emlxs_hba_t *hba)
- {
- /* Check if interrupts have already been removed */
- if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
- return (DDI_SUCCESS);
- }
- hba->intr_flags &= ~EMLXS_INTX_ADDED;
- /* Diable all adapter interrupts */
- EMLXS_SLI_DISABLE_INTR(hba, 0);
- /* Remove the interrupt */
- (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
- hba->intr_arg);
- return (DDI_SUCCESS);
- } /* emlxs_intx_remove() */
- extern void
- emlxs_process_link_speed(emlxs_hba_t *hba)
- {
- emlxs_vpd_t *vpd;
- emlxs_config_t *cfg;
- char *cptr;
- uint32_t hi;
- /*
- * This routine modifies the link-speed config parameter entry
- * based on adapter capabilities
- */
- vpd = &VPD;
- cfg = &hba->config[CFG_LINK_SPEED];
- cptr = cfg->help;
- (void) strcpy(cptr, "Select link speed. [0=Auto");
- cptr += 26;
- hi = 0;
- if (vpd->link_speed & LMT_1GB_CAPABLE) {
- (void) strcpy(cptr, ", 1=1Gb");
- cptr += 7;
- hi = 1;
- }
- if (vpd->link_speed & LMT_2GB_CAPABLE) {
- (void) strcpy(cptr, ", 2=2Gb");
- cptr += 7;
- hi = 2;
- }
- if (vpd->link_speed & LMT_4GB_CAPABLE) {
- (void) strcpy(cptr, ", 4=4Gb");
- cptr += 7;
- hi = 4;
- }
- if (vpd->link_speed & LMT_8GB_CAPABLE) {
- (void) strcpy(cptr, ", 8=8Gb");
- cptr += 7;
- hi = 8;
- }
- if (vpd->link_speed & LMT_10GB_CAPABLE) {
- (void) strcpy(cptr, ", 10=10Gb");
- cptr += 9;
- hi = 10;
- }
- (void) strcpy(cptr, "]");
- cfg->hi = hi;
- /* Now revalidate the current parameter setting */
- cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
- return;
- } /* emlxs_process_link_speed() */
- /*
- * emlxs_parse_vpd()
- *
- * This routine will parse the VPD data
- */
- extern int
- emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
- {
- emlxs_port_t *port = &PPORT;
- char tag[3];
- uint8_t lenlo, lenhi;
- uint32_t n;
- uint16_t block_size;
- uint32_t block_index = 0;
- uint8_t sub_size;
- uint32_t sub_index;
- int32_t finished = 0;
- int32_t index = 0;
- char buffer[128];
- emlxs_vpd_t *vpd;
- vpd = &VPD;
- while (!finished && (block_index < size)) {
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "block_index = %x", block_index);
- */
- switch (vpd_buf[block_index]) {
- case 0x82:
- index = block_index;
- index += 1;
- lenlo = vpd_buf[index];
- index += 1;
- lenhi = vpd_buf[index];
- index += 1;
- block_index = index;
- block_size = ((((uint16_t)lenhi) << 8) + lenlo);
- block_index += block_size;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "block_size = %x", block_size);
- */
- n = sizeof (buffer);
- bzero(buffer, n);
- bcopy(&vpd_buf[index], buffer,
- (block_size < (n - 1)) ? block_size : (n - 1));
- (void) strcpy(vpd->id, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
- vpd->id);
- break;
- case 0x90:
- index = block_index;
- index += 1;
- lenlo = vpd_buf[index];
- index += 1;
- lenhi = vpd_buf[index];
- index += 1;
- block_index = index;
- sub_index = index;
- block_size = ((((uint16_t)lenhi) << 8) + lenlo);
- block_index += block_size;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "block_size = %x", block_size);
- */
- /* Scan for sub-blocks */
- while ((sub_index < block_index) &&
- (sub_index < size)) {
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "sub_index = %x", sub_index);
- */
- index = sub_index;
- tag[0] = vpd_buf[index++];
- tag[1] = vpd_buf[index++];
- tag[2] = 0;
- sub_size = vpd_buf[index++];
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "sub_size = %x", sub_size);
- */
- sub_index = (index + sub_size);
- n = sizeof (buffer);
- bzero(buffer, n);
- bcopy(&vpd_buf[index], buffer,
- (sub_size < (n - 1)) ? sub_size : (n - 1));
- /*
- * Look for Engineering Change (EC)
- */
- if (strcmp(tag, "EC") == 0) {
- (void) strcpy(vpd->eng_change, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "EC: %s",
- vpd->eng_change);
- }
- /*
- * Look for Manufacturer (MN)
- */
- else if (strcmp(tag, "MN") == 0) {
- (void) strcpy(vpd->manufacturer,
- buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "MN: %s",
- vpd->manufacturer);
- }
- /*
- * Look for Serial Number (SN)
- */
- else if (strcmp(tag, "SN") == 0) {
- (void) strcpy(vpd->serial_num, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "SN: %s",
- vpd->serial_num);
- /* Validate the serial number */
- if (strncmp(buffer, "FFFFFFFFFF", 10) ==
- 0 ||
- strncmp(buffer, "0000000000", 10) ==
- 0) {
- vpd->serial_num[0] = 0;
- }
- }
- /*
- * Look for Part Number (PN)
- */
- else if (strcmp(tag, "PN") == 0) {
- (void) strcpy(vpd->part_num, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "PN: %s",
- vpd->part_num);
- }
- /*
- * Look for (V0)
- */
- else if (strcmp(tag, "V0") == 0) {
- /* Not used */
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "V0: %s", buffer);
- }
- /*
- * Look for model description (V1)
- */
- else if (strcmp(tag, "V1") == 0) {
- (void) strcpy(vpd->model_desc, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Desc: %s",
- vpd->model_desc);
- }
- /*
- * Look for model (V2)
- */
- else if (strcmp(tag, "V2") == 0) {
- (void) strcpy(vpd->model, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Model: %s",
- vpd->model);
- }
- /*
- * Look for program type (V3)
- */
- else if (strcmp(tag, "V3") == 0) {
- (void) strcpy(vpd->prog_types, buffer);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Prog Types: %s",
- vpd->prog_types);
- }
- /*
- * Look for port number (V4)
- */
- else if (strcmp(tag, "V4") == 0) {
- (void) strcpy(vpd->port_num, buffer);
- vpd->port_index =
- emlxs_strtol(vpd->port_num, 10);
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Port: %s",
- (vpd->port_num[0]) ? vpd->
- port_num : "not applicable");
- }
- /*
- * Look for checksum (RV)
- */
- else if (strcmp(tag, "RV") == 0) {
- /* Not used */
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Checksum: 0x%x",
- buffer[0]);
- }
- else {
- /* Generic */
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_vpd_msg, "Tag: %s: %s",
- tag, buffer);
- }
- }
- break;
- case 0x78:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
- finished = 1;
- break;
- default:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- "Unknown block: %x %x %x %x %x %x %x %x",
- vpd_buf[index], vpd_buf[index + 1],
- vpd_buf[index + 2], vpd_buf[index + 3],
- vpd_buf[index + 4], vpd_buf[index + 5],
- vpd_buf[index + 6], vpd_buf[index + 7]);
- return (0);
- }
- }
- return (1);
- } /* emlxs_parse_vpd */
- /*
- * emlxs_parse_fcoe()
- *
- * This routine will parse the VPD data
- */
- extern int
- emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
- {
- emlxs_port_t *port = &PPORT;
- tlv_fcoe_t *fcoelist;
- tlv_fcfconnectlist_t *fcflist;
- int i;
- /* Validate the config region 23 signature */
- if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
- (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
- return (0);
- }
- /* Search the config region 23, for FCOE Parameters record */
- i = 4;
- while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
- i += fcoep[i+1] * sizeof (uint32_t) + 2;
- }
- if (*(fcoep+i) == 0xA0) {
- fcoelist = (tlv_fcoe_t *)(fcoep+i);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- "Found FCOE Params (A0):%d x%x",
- fcoelist->length, fcoelist->fip_flags);
- bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
- sizeof (tlv_fcoe_t));
- }
- /* Search the config region 23, for FCF record */
- i = 4;
- while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
- i += fcoep[i+1] * sizeof (uint32_t) + 2;
- }
- if (*(fcoep+i) == 0xA1) {
- fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- "Found FCF ConnectList (A1):%d", fcflist->length);
- bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
- sizeof (tlv_fcfconnectlist_t));
- }
- return (1);
- } /* emlxs_parse_fcoe */
- extern void
- emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
- {
- if (vpd->rBit) {
- switch (hba->sli_mode) {
- case EMLXS_HBA_SLI4_MODE:
- (void) strcpy(vpd->fw_version, vpd->sli4FwName);
- (void) strcpy(vpd->fw_label, vpd->sli4FwLabel);
- break;
- case EMLXS_HBA_SLI3_MODE:
- (void) strcpy(vpd->fw_version, vpd->sli3FwName);
- (void) strcpy(vpd->fw_label, vpd->sli3FwLabel);
- break;
- case EMLXS_HBA_SLI2_MODE:
- (void) strcpy(vpd->fw_version, vpd->sli2FwName);
- (void) strcpy(vpd->fw_label, vpd->sli2FwLabel);
- break;
- case EMLXS_HBA_SLI1_MODE:
- (void) strcpy(vpd->fw_version, vpd->sli1FwName);
- (void) strcpy(vpd->fw_label, vpd->sli1FwLabel);
- break;
- default:
- (void) strcpy(vpd->fw_version, "unknown");
- (void) strcpy(vpd->fw_label, vpd->fw_version);
- }
- } else {
- emlxs_decode_version(vpd->smFwRev, vpd->fw_version);
- (void) strcpy(vpd->fw_label, vpd->fw_version);
- }
- return;
- } /* emlxs_decode_firmware_rev() */
- extern void
- emlxs_decode_version(uint32_t version, char *buffer)
- {
- uint32_t b1, b2, b3, b4;
- char c;
- b1 = (version & 0x0000f000) >> 12;
- b2 = (version & 0x00000f00) >> 8;
- b3 = (version & 0x000000c0) >> 6;
- b4 = (version & 0x00000030) >> 4;
- if (b1 == 0 && b2 == 0) {
- (void) sprintf(buffer, "none");
- return;
- }
- c = 0;
- switch (b4) {
- case 0:
- c = 'n';
- break;
- case 1:
- c = 'a';
- break;
- case 2:
- c = 'b';
- break;
- case 3:
- if ((version & 0x0000000f)) {
- c = 'x';
- }
- break;
- }
- b4 = (version & 0x0000000f);
- if (c == 0) {
- (void) sprintf(buffer, "%d.%d%d", b1, b2, b3);
- } else {
- (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4);
- }
- return;
- } /* emlxs_decode_version() */
- extern void
- emlxs_decode_label(char *label, char *buffer, int bige)
- {
- uint32_t i;
- char name[16];
- bcopy(label, name, sizeof (name));
- /* bige is TRUE if the data format is big endian */
- if (bige) {
- /* Data format big Endian */
- LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
- for (i = 0; i < sizeof (name); i++) {
- if (name[i] == 0x20) {
- name[i] = 0;
- }
- }
- } else {
- /* Data format little Endian */
- BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
- for (i = 0; i < sizeof (name); i++) {
- if (name[i] == 0x20) {
- name[i] = 0;
- }
- }
- }
- (void) strcpy(buffer, name);
- return;
- } /* emlxs_decode_label() */
- extern uint32_t
- emlxs_strtol(char *str, uint32_t base)
- {
- uint32_t value = 0;
- char *ptr;
- uint32_t factor = 1;
- uint32_t digits;
- if (*str == 0) {
- return (0);
- }
- if (base != 10 && base != 16) {
- return (0);
- }
- /* Get max digits of value */
- digits = (base == 10) ? 9 : 8;
- /* Position pointer to end of string */
- ptr = str + strlen(str);
- /* Process string backwards */
- while ((ptr-- > str) && digits) {
- /* check for base 10 numbers */
- if (*ptr >= '0' && *ptr <= '9') {
- value += ((uint32_t)(*ptr - '0')) * factor;
- factor *= base;
- digits--;
- } else if (base == 16) {
- /* Check for base 16 numbers */
- if (*ptr >= 'a' && *ptr <= 'f') {
- value +=
- ((uint32_t)(*ptr - 'a') + 10) * factor;
- factor *= base;
- digits--;
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- value +=
- ((uint32_t)(*ptr - 'A') + 10) * factor;
- factor *= base;
- digits--;
- } else if (factor > 1) {
- break;
- }
- } else if (factor > 1) {
- break;
- }
- }
- return (value);
- } /* emlxs_strtol() */
- extern uint64_t
- emlxs_strtoll(char *str, uint32_t base)
- {
- uint64_t value = 0;
- char *ptr;
- uint32_t factor = 1;
- uint32_t digits;
- if (*str == 0) {
- return (0);
- }
- if (base != 10 && base != 16) {
- return (0);
- }
- /* Get max digits of value */
- digits = (base == 10) ? 19 : 16;
- /* Position pointer to end of string */
- ptr = str + strlen(str);
- /* Process string backwards */
- while ((ptr-- > str) && digits) {
- /* check for base 10 numbers */
- if (*ptr >= '0' && *ptr <= '9') {
- value += ((uint32_t)(*ptr - '0')) * factor;
- factor *= base;
- digits--;
- } else if (base == 16) {
- /* Check for base 16 numbers */
- if (*ptr >= 'a' && *ptr <= 'f') {
- value +=
- ((uint32_t)(*ptr - 'a') + 10) * factor;
- factor *= base;
- digits--;
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- value +=
- ((uint32_t)(*ptr - 'A') + 10) * factor;
- factor *= base;
- digits--;
- } else if (factor > 1) {
- break;
- }
- } else if (factor > 1) {
- break;
- }
- }
- return (value);
- } /* emlxs_strtoll() */
- extern void
- emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
- {
- emlxs_port_t *port = &PPORT;
- uint32_t i;
- char *ptr;
- emlxs_model_t *model;
- char types_buffer[256];
- char *types;
- bcopy(prog_types, types_buffer, 256);
- types = types_buffer;
- model = &hba->model_info;
- while (*types) {
- if (strncmp(types, "T2:", 3) == 0) {
- bzero(model->pt_2, sizeof (model->pt_2));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_2[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "T3:", 3) == 0) {
- bzero(model->pt_3, sizeof (model->pt_3));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_3[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "T6:", 3) == 0) {
- bzero(model->pt_6, sizeof (model->pt_6));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_6[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- model->pt_6[i] = 0;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "T7:", 3) == 0) {
- bzero(model->pt_7, sizeof (model->pt_7));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_7[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- model->pt_7[i] = 0;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "TA:", 3) == 0) {
- bzero(model->pt_A, sizeof (model->pt_A));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_A[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "TB:", 3) == 0) {
- bzero(model->pt_B, sizeof (model->pt_B));
- types += 3;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_B[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "TFF:", 4) == 0) {
- bzero(model->pt_FF, sizeof (model->pt_FF));
- types += 4;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_FF[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else if (strncmp(types, "T20:", 4) == 0) {
- bzero(model->pt_20, sizeof (model->pt_20));
- types += 4;
- i = 0;
- while (*types && *types != 'T') {
- /* Null terminate the next value */
- ptr = types;
- while (*ptr && (*ptr != ','))
- ptr++;
- *ptr = 0;
- /* Save the value */
- model->pt_20[i++] =
- (uint8_t)emlxs_strtol(types, 16);
- model->pt_20[i] = 0;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
- */
- /* Move the str pointer */
- types = ptr + 1;
- }
- } else {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
- "Unknown prog type string = %s", types);
- break;
- }
- }
- return;
- } /* emlxs_parse_prog_types() */
- extern void
- emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types)
- {
- uint32_t i;
- uint32_t found = 0;
- char buffer[256];
- bzero(prog_types, 256);
- /* Rebuild the prog type string */
- if (hba->model_info.pt_2[0]) {
- (void) strcat(prog_types, "T2:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_2[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_3[0]) {
- (void) strcat(prog_types, "T3:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_3[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_6[0]) {
- (void) strcat(prog_types, "T6:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_6[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_7[0]) {
- (void) strcat(prog_types, "T7:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_7[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_A[0]) {
- (void) strcat(prog_types, "TA:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_A[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_B[0]) {
- (void) strcat(prog_types, "TB:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_B[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_20[0]) {
- (void) strcat(prog_types, "T20:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_20[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (hba->model_info.pt_FF[0]) {
- (void) strcat(prog_types, "TFF:");
- found = 1;
- i = 0;
- while (hba->model_info.pt_FF[i] && i < 8) {
- (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]);
- (void) strcat(prog_types, buffer);
- i++;
- }
- }
- if (found) {
- /* Terminate at the last comma in string */
- prog_types[(strlen(prog_types) - 1)] = 0;
- }
- return;
- } /* emlxs_build_prog_types() */
- extern uint32_t
- emlxs_init_adapter_info(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- uint32_t pci_id;
- uint32_t cache_line;
- uint32_t channels;
- uint16_t device_id;
- uint16_t ssdid;
- uint32_t i;
- uint32_t found = 0;
- int32_t *prop;
- uint32_t num_prop;
- if (hba->bus_type == SBUS_FC) {
- if (hba->pci_acc_handle == NULL) {
- bcopy(&emlxs_sbus_model[0], &hba->model_info,
- sizeof (emlxs_model_t));
- hba->model_info.device_id = 0;
- return (0);
- }
- /* Read the PCI device id */
- pci_id =
- ddi_get32(hba->pci_acc_handle,
- (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
- device_id = (uint16_t)(pci_id >> 16);
- /* Find matching adapter model */
- for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
- if (emlxs_sbus_model[i].device_id == device_id) {
- bcopy(&emlxs_sbus_model[i], &hba->model_info,
- sizeof (emlxs_model_t));
- found = 1;
- break;
- }
- }
- /* If not found then use the unknown model */
- if (!found) {
- bcopy(&emlxs_sbus_model[0], &hba->model_info,
- sizeof (emlxs_model_t));
- hba->model_info.device_id = device_id;
- return (0);
- }
- } else { /* PCI model */
- if (hba->pci_acc_handle == NULL) {
- bcopy(&emlxs_pci_model[0], &hba->model_info,
- sizeof (emlxs_model_t));
- hba->model_info.device_id = 0;
- return (0);
- }
- /* Read the PCI device id */
- device_id =
- ddi_get16(hba->pci_acc_handle,
- (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
- /* Read the PCI Subsystem id */
- ssdid =
- ddi_get16(hba->pci_acc_handle,
- (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
- if (ssdid == 0 || ssdid == 0xffff) {
- ssdid = device_id;
- }
- /* Read the Cache Line reg */
- cache_line =
- ddi_get32(hba->pci_acc_handle,
- (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
- /* Check for the multifunction bit being set */
- if ((cache_line & 0x00ff0000) == 0x00800000) {
- channels = 2;
- } else {
- channels = 1;
- }
- /* If device ids are unique, then use them for search */
- if (device_id != ssdid) {
- if (channels > 1) {
- /*
- * Find matching adapter model using
- * device_id, ssdid and channels
- */
- for (i = 1; i < emlxs_pci_model_count; i++) {
- if (emlxs_pci_model[i].device_id ==
- device_id &&
- emlxs_pci_model[i].ssdid == ssdid &&
- emlxs_pci_model[i].channels ==
- channels) {
- bcopy(&emlxs_pci_model[i],
- &hba->model_info,
- sizeof (emlxs_model_t));
- found = 1;
- break;
- }
- }
- } else {
- /*
- * Find matching adapter model using
- * device_id and ssdid
- */
- for (i = 1; i < emlxs_pci_model_count; i++) {
- if (emlxs_pci_model[i].device_id ==
- device_id &&
- emlxs_pci_model[i].ssdid == ssdid) {
- bcopy(&emlxs_pci_model[i],
- &hba->model_info,
- sizeof (emlxs_model_t));
- found = 1;
- break;
- }
- }
- }
- }
- /* If adapter not found, try again */
- if (!found) {
- /* Find matching adapter model */
- for (i = 1; i < emlxs_pci_model_count; i++) {
- if (emlxs_pci_model[i].device_id == device_id &&
- emlxs_pci_model[i].channels == channels) {
- bcopy(&emlxs_pci_model[i],
- &hba->model_info,
- sizeof (emlxs_model_t));
- found = 1;
- break;
- }
- }
- }
- /* If adapter not found, try one last time */
- if (!found) {
- /* Find matching adapter model */
- for (i = 1; i < emlxs_pci_model_count; i++) {
- if (emlxs_pci_model[i].device_id == device_id) {
- bcopy(&emlxs_pci_model[i],
- &hba->model_info,
- sizeof (emlxs_model_t));
- found = 1;
- break;
- }
- }
- }
- /* If not found, set adapter to unknown */
- if (!found) {
- bcopy(&emlxs_pci_model[0], &hba->model_info,
- sizeof (emlxs_model_t));
- hba->model_info.device_id = device_id;
- hba->model_info.ssdid = ssdid;
- return (0);
- }
- #ifndef SATURN_MSI_SUPPORT
- /*
- * This will disable MSI support for Saturn adapter's
- * due to a PCI bus issue
- */
- if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
- hba->model_info.flags &=
- ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
- }
- #endif /* !SATURN_MSI_SUPPORT */
- /* Scan the PCI capabilities */
- emlxs_pci_cap_offsets(hba);
- #ifdef MSI_SUPPORT
- /* Verify MSI support */
- if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
- !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
- hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
- }
- /* Verify MSI-X support */
- if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
- !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
- hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
- }
- #endif /* MSI_SUPPORT */
- }
- if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
- "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
- /* Parse the property for PCI function, device and bus no. */
- hba->pci_function_number =
- (uint8_t)((prop[0] & 0x00000700) >> 8);
- hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);
- hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16);
- ddi_prop_free((void *)prop);
- }
- if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
- hba->sli_api = emlxs_sli4_api;
- } else {
- hba->sli_api = emlxs_sli3_api;
- }
- #ifdef FMA_SUPPORT
- if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
- != DDI_FM_OK) {
- EMLXS_MSGF(EMLXS_CONTEXT,
- &emlxs_invalid_access_handle_msg, NULL);
- return (0);
- }
- #endif /* FMA_SUPPORT */
- return (1);
- } /* emlxs_init_adapter_info() */
- /* ARGSUSED */
- static void
- emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
- {
- emlxs_port_t *port = &PPORT;
- IOCB *iocb;
- uint32_t *w;
- int i, j;
- iocb = &iocbq->iocb;
- if (iocb->ULPSTATUS != 0) {
- return;
- }
- switch (iocb->un.astat.EventCode) {
- case 0x0100: /* Temp Warning */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
- "Adapter is very hot (%d °C). Take corrective action.",
- iocb->ULPCONTEXT);
- hba->temperature = iocb->ULPCONTEXT;
- emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
- break;
- case 0x0101: /* Temp Safe */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
- "Adapter temperature now safe (%d °C).",
- iocb->ULPCONTEXT);
- hba->temperature = iocb->ULPCONTEXT;
- emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
- break;
- default:
- w = (uint32_t *)iocb;
- for (i = 0, j = 0; i < 8; i++, j += 2) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
- "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
- w[j + 1]);
- }
- emlxs_log_async_event(port, iocb);
- }
- return;
- } /* emlxs_handle_async_event() */
- /* ARGSUSED */
- extern void
- emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
- {
- emlxs_port_t *port = &PPORT;
- /* Attempt a link reset to recover */
- (void) emlxs_reset(port, FC_FCA_LINK_RESET);
- return;
- } /* emlxs_reset_link_thread() */
- /* ARGSUSED */
- extern void
- emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
- {
- emlxs_port_t *port = &PPORT;
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
- /* Attempt a full hardware reset to recover */
- if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
- EMLXS_STATE_CHANGE(hba, FC_ERROR);
- emlxs_shutdown_thread(hba, arg1, arg2);
- }
- return;
- } /* emlxs_restart_thread() */
- /* ARGSUSED */
- extern void
- emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
- {
- emlxs_port_t *port = &PPORT;
- mutex_enter(&EMLXS_PORT_LOCK);
- if (hba->flag & FC_SHUTDOWN) {
- mutex_exit(&EMLXS_PORT_LOCK);
- return;
- }
- hba->flag |= FC_SHUTDOWN;
- mutex_exit(&EMLXS_PORT_LOCK);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
- "Shutting down...");
- /* Take adapter offline and leave it there */
- (void) emlxs_offline(hba);
- if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
- /*
- * Dump is not defined for SLI4, so just
- * reset the HBA for now.
- */
- EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
- } else {
- if (hba->flag & FC_OVERTEMP_EVENT) {
- emlxs_log_temp_event(port, 0x01,
- hba->temperature);
- } else {
- emlxs_log_dump_event(port, NULL, 0);
- }
- }
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
- return;
- } /* emlxs_shutdown_thread() */
- /* ARGSUSED */
- extern void
- emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
- {
- IOCBQ *iocbq;
- IOCBQ *rsp_head;
- /*
- * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
- * "emlxs_proc_channel: channel=%d", cp->channelno);
- */
- mutex_enter(&cp->rsp_lock);
- while ((rsp_head = cp->rsp_head) != NULL) {
- cp->rsp_head = NULL;
- cp->rsp_tail = NULL;
- mutex_exit(&cp->rsp_lock);
- while ((iocbq = rsp_head) != NULL) {
- rsp_head = (IOCBQ *) iocbq->next;
- emlxs_proc_channel_event(hba, cp, iocbq);
- }
- mutex_enter(&cp->rsp_lock);
- }
- mutex_exit(&cp->rsp_lock);
- EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
- return;
- } /* emlxs_proc_channel() */
- /*
- * Called from SLI ring event routines to process a rsp ring IOCB.
- */
- void
- emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
- {
- emlxs_port_t *port = &PPORT;
- char buffer[MAX_MSG_DATA + 1];
- IOCB *iocb;
- emlxs_buf_t *sbp;
- iocb = &iocbq->iocb;
- #ifdef DEBUG_CMPL_IOCB
- emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
- #endif
- sbp = (emlxs_buf_t *)iocbq->sbp;
- if (sbp) {
- if (!(sbp->pkt_flags & PACKET_VALID) ||
- (sbp->pkt_flags & (PACKET_ULP_OWNED |
- PACKET_IN_COMPLETION))) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
- "Duplicate: iocb=%p cmd=%x status=%x "
- "error=%x iotag=%x context=%x info=%x",
- iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
- iocbq->iocb.ULPSTATUS,
- (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
- (uint16_t)iocbq->iocb.ULPIOTAG,
- (uint16_t)iocbq->iocb.ULPCONTEXT,
- (uint8_t)iocbq->iocb.ULPRSVDBYTE);
- /* Drop this IO immediately */
- return;
- }
- if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
- /*
- * If the packet is tagged for timeout then set the
- * return codes appropriately
- */
- iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
- iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
- } else if (sbp->pkt_flags &
- (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
- /*
- * If the packet is tagged for abort then set the
- * return codes appropriately
- */
- iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
- iocb->un.grsp.perr.statLocalError =
- IOERR_ABORT_REQUESTED;
- }
- }
- /* Check for IOCB local error */
- if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
- "Local reject. ringno=%d iocb=%p cmd=%x "
- "iotag=%x context=%x info=%x error=%x",
- cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
- (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
- (uint8_t)iocb->ULPRSVDBYTE,
- (uint8_t)iocb->un.grsp.perr.statLocalError);
- }
- switch (iocb->ULPCOMMAND) {
- /* RING 0 FCP commands */
- case CMD_FCP_ICMND_CR:
- case CMD_FCP_ICMND_CX:
- case CMD_FCP_IREAD_CR:
- case CMD_FCP_IREAD_CX:
- case CMD_FCP_IWRITE_CR:
- case CMD_FCP_IWRITE_CX:
- case CMD_FCP_ICMND64_CR:
- case CMD_FCP_ICMND64_CX:
- case CMD_FCP_IREAD64_CR:
- case CMD_FCP_IREAD64_CX:
- case CMD_FCP_IWRITE64_CR:
- case CMD_FCP_IWRITE64_CX:
- emlxs_handle_fcp_event(hba, cp, iocbq);
- break;
- #ifdef SFCT_SUPPORT
- case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */
- case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */
- case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */
- case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */
- case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */
- case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */
- (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
- break;
- #endif /* SFCT_SUPPORT */
- /* RING 1 IP commands */
- case CMD_XMIT_BCAST_CN:
- case CMD_XMIT_BCAST_CX:
- case CMD_XMIT_BCAST64_CN:
- case CMD_XMIT_BCAST64_CX:
- (void) emlxs_ip_handle_event(hba, cp, iocbq);
- break;
- case CMD_XMIT_SEQUENCE_CX:
- case CMD_XMIT_SEQUENCE_CR:
- case CMD_XMIT_SEQUENCE64_CX:
- case CMD_XMIT_SEQUENCE64_CR:
- switch (iocb->un.rcvseq64.w5.hcsw.Type) {
- case FC_TYPE_IS8802_SNAP:
- (void) emlxs_ip_handle_event(hba, cp, iocbq);
- break;
- case FC_TYPE_FC_SERVICES:
- (void) emlxs_ct_handle_event(hba, cp, iocbq);
- break;
- default:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
- "cmd=%x type=%x status=%x iotag=%x context=%x ",
- iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
- iocb->ULPSTATUS, iocb->ULPIOTAG,
- iocb->ULPCONTEXT);
- }
- break;
- case CMD_RCV_SEQUENCE_CX:
- case CMD_RCV_SEQUENCE64_CX:
- case CMD_RCV_SEQ64_CX:
- case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */
- case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */
- case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */
- if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
- (void) emlxs_handle_rcv_seq(hba, cp, iocbq);
- }
- break;
- case CMD_RCV_SEQ_LIST64_CX:
- (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
- break;
- case CMD_CREATE_XRI_CR:
- case CMD_CREATE_XRI_CX:
- (void) emlxs_handle_create_xri(hba, cp, iocbq);
- break;
- /* RING 2 ELS commands */
- case CMD_ELS_REQUEST_CR:
- case CMD_ELS_REQUEST_CX:
- case CMD_XMIT_ELS_RSP_CX:
- case CMD_ELS_REQUEST64_CR:
- case CMD_ELS_REQUEST64_CX:
- case CMD_XMIT_ELS_RSP64_CX:
- (void) emlxs_els_handle_event(hba, cp, iocbq);
- break;
- /* RING 3 CT commands */
- case CMD_GEN_REQUEST64_CR:
- case CMD_GEN_REQUEST64_CX:
- switch (iocb->un.rcvseq64.w5.hcsw.Type) {
- #ifdef MENLO_SUPPORT
- case EMLXS_MENLO_TYPE:
- (void) emlxs_menlo_handle_event(hba, cp, iocbq);
- break;
- #endif /* MENLO_SUPPORT */
- case FC_TYPE_FC_SERVICES:
- (void) emlxs_ct_handle_event(hba, cp, iocbq);
- break;
- default:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
- "cmd=%x type=%x status=%x iotag=%x context=%x ",
- iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
- iocb->ULPSTATUS, iocb->ULPIOTAG,
- iocb->ULPCONTEXT);
- }
- break;
- case CMD_ABORT_XRI_CN: /* Abort fcp command */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
- "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
- (uint32_t)iocb->un.acxri.abortContextTag,
- (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
- iocb->un.acxri.parm);
- #ifdef SFCT_SUPPORT
- if (port->tgt_mode) {
- (void) emlxs_fct_handle_abort(hba, cp, iocbq);
- }
- #endif /* SFCT_SUPPORT */
- break;
- case CMD_ABORT_XRI_CX: /* Abort command */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
- "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
- (uint32_t)iocb->un.acxri.abortContextTag,
- (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
- iocb->un.acxri.parm, iocbq->sbp);
- #ifdef SFCT_SUPPORT
- if (port->tgt_mode) {
- (void) emlxs_fct_handle_abort(hba, cp, iocbq);
- }
- #endif /* SFCT_SUPPORT */
- break;
- case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
- "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x",
- (uint32_t)iocb->un.acxri.abortContextTag,
- (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
- iocb->un.acxri.parm);
- #ifdef SFCT_SUPPORT
- if (port->tgt_mode) {
- (void) emlxs_fct_handle_abort(hba, cp, iocbq);
- }
- #endif /* SFCT_SUPPORT */
- break;
- case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
- "CLOSE_XRI_CN: rpi=%d iotag=%x status=%x parm=%x",
- (uint32_t)iocb->un.acxri.abortContextTag,
- (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
- iocb->un.acxri.parm);
- #ifdef SFCT_SUPPORT
- if (port->tgt_mode) {
- (void) emlxs_fct_handle_abort(hba, cp, iocbq);
- }
- #endif /* SFCT_SUPPORT */
- break;
- case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
- "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p",
- (uint32_t)iocb->un.acxri.abortContextTag,
- (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
- iocb->un.acxri.parm, iocbq->sbp);
- #ifdef SFCT_SUPPORT
- if (port->tgt_mode) {
- (void) emlxs_fct_handle_abort(hba, cp, iocbq);
- }
- #endif /* SFCT_SUPPORT */
- break;
- case CMD_ADAPTER_MSG:
- /* Allows debug adapter firmware messages to print on host */
- bzero(buffer, sizeof (buffer));
- bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
- break;
- case CMD_QUE_RING_LIST64_CN:
- case CMD_QUE_RING_BUF64_CN:
- break;
- case CMD_ASYNC_STATUS:
- emlxs_handle_async_event(hba, cp, iocbq);
- break;
- default:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
- "cmd=%x status=%x iotag=%x context=%x", iocb->ULPCOMMAND,
- iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
- break;
- } /* switch(entry->ULPCOMMAND) */
- return;
- } /* emlxs_proc_channel_event() */
- extern char *
- emlxs_ffstate_xlate(uint32_t state)
- {
- static char buffer[32];
- uint32_t i;
- uint32_t count;
- count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
- for (i = 0; i < count; i++) {
- if (state == emlxs_ffstate_table[i].code) {
- return (emlxs_ffstate_table[i].string);
- }
- }
- (void) sprintf(buffer, "state=0x%x", state);
- return (buffer);
- } /* emlxs_ffstate_xlate() */
- extern char *
- emlxs_ring_xlate(uint32_t ringno)
- {
- static char buffer[32];
- uint32_t i;
- uint32_t count;
- count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
- for (i = 0; i < count; i++) {
- if (ringno == emlxs_ring_table[i].code) {
- return (emlxs_ring_table[i].string);
- }
- }
- (void) sprintf(buffer, "ring=0x%x", ringno);
- return (buffer);
- } /* emlxs_ring_xlate() */
- extern char *
- emlxs_pci_cap_xlate(uint32_t id)
- {
- static char buffer[32];
- uint32_t i;
- uint32_t count;
- count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
- for (i = 0; i < count; i++) {
- if (id == emlxs_pci_cap[i].code) {
- return (emlxs_pci_cap[i].string);
- }
- }
- (void) sprintf(buffer, "PCI_CAP_ID_%02X", id);
- return (buffer);
- } /* emlxs_pci_cap_xlate() */
- extern void
- emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
- {
- emlxs_port_t *port = &PPORT;
- MAILBOXQ *mbq;
- MAILBOX *mb;
- emlxs_config_t *cfg;
- uint32_t value;
- cfg = &CFG;
- xlate:
- switch (cfg[CFG_PCI_MAX_READ].current) {
- case 512:
- value = 0;
- break;
- case 1024:
- value = 1;
- break;
- case 2048:
- value = 2;
- break;
- case 4096:
- value = 3;
- break;
- default:
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
- cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
- cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
- goto xlate;
- }
- if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "PCI_MAX_READ: Unable to allocate mailbox buffer.");
- return;
- }
- mb = (MAILBOX *)mbq;
- emlxs_mb_set_var(hba, mbq, 0x00100506, value);
- if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
- if (verbose || (mb->mbxStatus != 0x12)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "PCI_MAX_READ: Unable to update. "
- "status=%x value=%d (%d bytes)",
- mb->mbxStatus, value,
- cfg[CFG_PCI_MAX_READ].current);
- }
- } else {
- if (verbose &&
- (cfg[CFG_PCI_MAX_READ].current !=
- cfg[CFG_PCI_MAX_READ].def)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "PCI_MAX_READ: Updated. %d bytes",
- cfg[CFG_PCI_MAX_READ].current);
- }
- }
- emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
- return;
- } /* emlxs_pcix_mxr_update */
- extern uint32_t
- emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
- {
- emlxs_port_t *port = &PPORT;
- MAILBOX *mb = (MAILBOX *)mbq;
- uint32_t npname0, npname1;
- uint32_t tmpkey, theKey;
- uint16_t key850;
- uint32_t t1, t2, t3, t4;
- uint32_t ts;
- #define SEED 0x876EDC21
- /* This key is only used currently for SBUS adapters */
- if (hba->bus_type != SBUS_FC) {
- return (0);
- }
- tmpkey = mb->un.varWords[30];
- EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
- emlxs_mb_read_nv(hba, mbq);
- if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
- mb->mbxStatus);
- return (0);
- }
- npname0 = mb->un.varRDnvp.portname[0];
- npname1 = mb->un.varRDnvp.portname[1];
- key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
- ts = (uint16_t)(npname1 + 1);
- t1 = ts * key850;
- ts = (uint16_t)((npname1 >> 16) + 1);
- t2 = ts * key850;
- ts = (uint16_t)(npname0 + 1);
- t3 = ts * key850;
- ts = (uint16_t)((npname0 >> 16) + 1);
- t4 = ts * key850;
- theKey = SEED + t1 + t2 + t3 + t4;
- return (theKey);
- } /* emlxs_get_key() */
- extern void
- emlxs_fw_show(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- uint32_t i;
- /* Display firmware library one time */
- for (i = 0; i < emlxs_fw_count; i++) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
- emlxs_fw_table[i].label);
- }
- return;
- } /* emlxs_fw_show() */
- #ifdef MODFW_SUPPORT
- extern void
- emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
- {
- emlxs_port_t *port = &PPORT;
- int (*emlxs_fw_get)(emlxs_firmware_t *);
- int err;
- /* Make sure image is unloaded and image buffer pointer is clear */
- emlxs_fw_unload(hba, fw);
- err = 0;
- hba->fw_modhandle =
- ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
- if (!hba->fw_modhandle) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "Unable to load firmware module. error=%d", err);
- return;
- } else {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
- "Firmware module loaded.");
- }
- err = 0;
- emlxs_fw_get =
- (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err);
- if ((void *)emlxs_fw_get == NULL) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "emlxs_fw_get not present. error=%d", err);
- emlxs_fw_unload(hba, fw);
- return;
- }
- if (emlxs_fw_get(fw)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
- "Invalid firmware image module found. %s", fw->label);
- emlxs_fw_unload(hba, fw);
- return;
- }
- return;
- } /* emlxs_fw_load() */
- extern void
- emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
- {
- emlxs_port_t *port = &PPORT;
- /* Clear the firmware image */
- fw->image = NULL;
- fw->size = 0;
- if (hba->fw_modhandle) {
- /* Close the module */
- (void) ddi_modclose(hba->fw_modhandle);
- hba->fw_modhandle = NULL;
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
- "Firmware module unloaded.");
- }
- return;
- } /* emlxs_fw_unload() */
- #endif /* MODFW_SUPPORT */
- static void
- emlxs_pci_cap_offsets(emlxs_hba_t *hba)
- {
- emlxs_port_t *port = &PPORT;
- uint8_t offset;
- uint8_t id;
- bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
- /* Read first offset */
- offset = ddi_get8(hba->pci_acc_handle,
- (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER));
- offset &= PCI_CAP_PTR_MASK;
- while (offset >= PCI_CAP_PTR_OFF) {
- /* Read the next cap id */
- id = ddi_get8(hba->pci_acc_handle,
- (uint8_t *)(hba->pci_addr + offset));
- if (id < PCI_CAP_MAX_PTR) {
- hba->pci_cap_offset[id] = offset;
- }
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
- "%s: offset=0x%x",
- emlxs_pci_cap_xlate(id), offset);
- /* Read next offset */
- offset = ddi_get8(hba->pci_acc_handle,
- (uint8_t *)(hba->pci_addr + offset + PCI_CAP_NEXT_PTR));
- offset &= PCI_CAP_PTR_MASK;
- }
- return;
- } /* emlxs_pci_cap_offsets() */