1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 88f23e9faSHans Rosenfeld * You can obtain a copy of the license at 98f23e9faSHans Rosenfeld * http://www.opensource.org/licenses/cddl1.txt. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22fcf3ce44SJohn Forte /* 238f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25*a3170057SPaul Winder * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 26*a3170057SPaul Winder * Copyright 2020 RackTop Systems, Inc. 27fcf3ce44SJohn Forte */ 28fcf3ce44SJohn Forte 2982527734SSukumar Swaminathan #define EMLXS_FW_TABLE_DEF 3082527734SSukumar Swaminathan #define EMLXS_MODEL_DEF 31fcf3ce44SJohn Forte 3282527734SSukumar Swaminathan #include <emlxs.h> 33fcf3ce44SJohn Forte 3482527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 3582527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_HBA_C); 36fcf3ce44SJohn Forte 37a9800bebSGarrett D'Amore 3882527734SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, 3982527734SSukumar Swaminathan IOCBQ *iocbq); 40291a2b48SSukumar Swaminathan 41a9800bebSGarrett D'Amore static void emlxs_pci_cap_offsets(emlxs_hba_t *hba); 42a9800bebSGarrett D'Amore 43fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 4482527734SSukumar Swaminathan uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 4582527734SSukumar Swaminathan {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; 4682527734SSukumar Swaminathan uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 4782527734SSukumar Swaminathan {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4, 4882527734SSukumar Swaminathan EMLXS_MSI0_MASK8}; 49291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 50fcf3ce44SJohn Forte 5182527734SSukumar Swaminathan emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE; 5282527734SSukumar Swaminathan int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t); 53291a2b48SSukumar Swaminathan 54a9800bebSGarrett D'Amore emlxs_table_t emlxs_pci_cap[] = { 55a9800bebSGarrett D'Amore {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"}, 56a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"}, 57a9800bebSGarrett D'Amore {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"}, 58a9800bebSGarrett D'Amore {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"}, 59a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"}, 60a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"}, 61a9800bebSGarrett D'Amore {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"}, 62a9800bebSGarrett D'Amore {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"}, 63a9800bebSGarrett D'Amore {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"}, 64a9800bebSGarrett D'Amore {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"}, 65a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"}, 66a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"}, 67a9800bebSGarrett D'Amore {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"}, 68a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"}, 69a9800bebSGarrett D'Amore {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"}, 70a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"}, 71a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"}, 72a9800bebSGarrett D'Amore {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"}, 73a9800bebSGarrett D'Amore {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"} 74a9800bebSGarrett D'Amore 75a9800bebSGarrett D'Amore }; /* emlxs_pci_cap */ 76a9800bebSGarrett D'Amore 778f23e9faSHans Rosenfeld emlxs_table_t emlxs_pci_ecap[] = { 788f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_AER, "PCIE_EXT_CAP_ID_AER"}, 798f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC, "PCIE_EXT_CAP_ID_VC"}, 808f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_SER, "PCIE_EXT_CAP_ID_SER"}, 818f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_PWR_BUDGET, "PCIE_EXT_CAP_ID_PWR_BUDGET"}, 828f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_LINK_DECL, "PCIE_EXT_CAP_ID_RC_LINK_DECL"}, 838f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "PCIE_EXT_CAP_ID_RC_INT_LINKCTRL"}, 848f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_EVNT_CEA, "PCIE_EXT_CAP_ID_RC_EVNT_CEA"}, 858f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_MFVC, "PCIE_EXT_CAP_ID_MFVC"}, 868f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC_WITH_MFVC, "PCIE_EXT_CAP_ID_VC_WITH_MFVC"}, 878f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RCRB, "PCIE_EXT_CAP_ID_RCRB"}, 888f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VS, "PCIE_EXT_CAP_ID_VS"}, 898f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_CAC, "PCIE_EXT_CAP_ID_CAC"}, 908f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ACS, "PCIE_EXT_CAP_ID_ACS"}, 918f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ARI, "PCIE_EXT_CAP_ID_ARI"}, 928f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ATS, "PCIE_EXT_CAP_ID_ATS"}, 938f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SRIOV, "PCI_EXT_CAP_ID_SRIOV"}, 948f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_TPH, "PCI_EXT_CAP_ID_TPH"}, 958f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SEC_PCI, "PCI_EXT_CAP_ID_SEC_PCI"} 968f23e9faSHans Rosenfeld 978f23e9faSHans Rosenfeld }; /* emlxs_pci_ecap */ 988f23e9faSHans Rosenfeld 998f23e9faSHans Rosenfeld 10082527734SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = { 10182527734SSukumar Swaminathan {FC_FCP_RING, "FCP Ring"}, 10282527734SSukumar Swaminathan {FC_IP_RING, "IP Ring"}, 10382527734SSukumar Swaminathan {FC_ELS_RING, "ELS Ring"}, 10482527734SSukumar Swaminathan {FC_CT_RING, "CT Ring"} 105291a2b48SSukumar Swaminathan 10682527734SSukumar Swaminathan }; /* emlxs_ring_table */ 107fcf3ce44SJohn Forte 10882527734SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = { 10982527734SSukumar Swaminathan {0, "NULL"}, 11082527734SSukumar Swaminathan {FC_ERROR, "ERROR"}, 11182527734SSukumar Swaminathan {FC_KILLED, "KILLED"}, 11282527734SSukumar Swaminathan {FC_WARM_START, "WARM_START"}, 11382527734SSukumar Swaminathan {FC_INIT_START, "INIT_START"}, 11482527734SSukumar Swaminathan {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 11582527734SSukumar Swaminathan {FC_INIT_REV, "INIT_REV"}, 11682527734SSukumar Swaminathan {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 11782527734SSukumar Swaminathan {FC_INIT_CFGRING, "INIT_CFGRING"}, 11882527734SSukumar Swaminathan {FC_INIT_INITLINK, "INIT_INITLINK"}, 11982527734SSukumar Swaminathan {FC_LINK_DOWN, "LINK_DOWN"}, 12082527734SSukumar Swaminathan {FC_LINK_UP, "LINK_UP"}, 12182527734SSukumar Swaminathan {FC_CLEAR_LA, "CLEAR_LA"}, 12282527734SSukumar Swaminathan {FC_READY, "READY"} 123fcf3ce44SJohn Forte 12482527734SSukumar Swaminathan }; /* emlxs_ffstate_table */ 125fcf3ce44SJohn Forte 126fcf3ce44SJohn Forte 127fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 128fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 129fcf3ce44SJohn Forte int32_t 130fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 131fcf3ce44SJohn Forte { 132fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 133fcf3ce44SJohn Forte int32_t pass = 0; 134fcf3ce44SJohn Forte int32_t type = 0; 135fcf3ce44SJohn Forte char s_type[16]; 136fcf3ce44SJohn Forte int32_t types; 137fcf3ce44SJohn Forte int32_t count; 138fcf3ce44SJohn Forte int32_t nintrs; 139fcf3ce44SJohn Forte int32_t mode; 140fcf3ce44SJohn Forte int32_t actual; 141fcf3ce44SJohn Forte int32_t new_actual; 142fcf3ce44SJohn Forte int32_t i; 143fcf3ce44SJohn Forte int32_t ret; 144fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 145fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL; 146fcf3ce44SJohn Forte uint32_t *intr_pri = NULL; 147fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 148fcf3ce44SJohn Forte int32_t hilevel_pri; 149fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 150fcf3ce44SJohn Forte 151fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 152fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max)); 153fcf3ce44SJohn Forte } 154291a2b48SSukumar Swaminathan 155fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) { 156fcf3ce44SJohn Forte return (DDI_SUCCESS); 157fcf3ce44SJohn Forte } 158291a2b48SSukumar Swaminathan 159fcf3ce44SJohn Forte /* Set max interrupt count if not specified */ 160fcf3ce44SJohn Forte if (max == 0) { 161fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) || 162fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) { 163fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS; 164fcf3ce44SJohn Forte } else { 165fcf3ce44SJohn Forte max = 1; 166fcf3ce44SJohn Forte } 167fcf3ce44SJohn Forte } 168291a2b48SSukumar Swaminathan 169fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */ 170fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 171fcf3ce44SJohn Forte max = hba->model_info.intr_limit; 172fcf3ce44SJohn Forte } 173291a2b48SSukumar Swaminathan 174fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */ 175fcf3ce44SJohn Forte types = 0; 176fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types); 177fcf3ce44SJohn Forte 178fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) { 179fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 180fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 181fcf3ce44SJohn Forte 182fcf3ce44SJohn Forte /* Default to fixed type */ 183fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED; 184fcf3ce44SJohn Forte } 185291a2b48SSukumar Swaminathan 186fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */ 187fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) { 188fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 189fcf3ce44SJohn Forte } 190291a2b48SSukumar Swaminathan 191fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */ 192fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) || 193fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) { 194fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 195fcf3ce44SJohn Forte } 196291a2b48SSukumar Swaminathan 197fcf3ce44SJohn Forte begin: 198fcf3ce44SJohn Forte 199fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */ 200fcf3ce44SJohn Forte type = 0; 201fcf3ce44SJohn Forte 202fcf3ce44SJohn Forte /* Check if MSIX is fully supported */ 203fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) && 204fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 205fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 206fcf3ce44SJohn Forte nintrs = 0; 207fcf3ce44SJohn Forte ret = 208291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, 209291a2b48SSukumar Swaminathan &nintrs); 210fcf3ce44SJohn Forte 211fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 212fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX; 2138f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSIX", sizeof (s_type)); 214fcf3ce44SJohn Forte goto initialize; 215fcf3ce44SJohn Forte } 216fcf3ce44SJohn Forte } 217291a2b48SSukumar Swaminathan 218fcf3ce44SJohn Forte /* Check if MSI is fully supported */ 219fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) && 220fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 221fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 222fcf3ce44SJohn Forte nintrs = 0; 223291a2b48SSukumar Swaminathan ret = 224291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 225fcf3ce44SJohn Forte 226fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 227fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI; 2288f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSI", sizeof (s_type)); 229fcf3ce44SJohn Forte goto initialize; 230fcf3ce44SJohn Forte } 231fcf3ce44SJohn Forte } 232291a2b48SSukumar Swaminathan 233fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */ 234fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) && 235fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 236fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 237fcf3ce44SJohn Forte nintrs = 0; 238fcf3ce44SJohn Forte ret = 239291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, 240291a2b48SSukumar Swaminathan &nintrs); 241fcf3ce44SJohn Forte 242fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) { 243fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED; 2448f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_FIXED", sizeof (s_type)); 245fcf3ce44SJohn Forte goto initialize; 246fcf3ce44SJohn Forte } 247fcf3ce44SJohn Forte } 248291a2b48SSukumar Swaminathan 249fcf3ce44SJohn Forte goto init_failed; 250fcf3ce44SJohn Forte 251fcf3ce44SJohn Forte 252fcf3ce44SJohn Forte initialize: 253fcf3ce44SJohn Forte 254fcf3ce44SJohn Forte pass++; 255fcf3ce44SJohn Forte mode = 0; 256fcf3ce44SJohn Forte actual = 0; 257fcf3ce44SJohn Forte htable = NULL; 258fcf3ce44SJohn Forte intr_pri = NULL; 259fcf3ce44SJohn Forte intr_cap = NULL; 260fcf3ce44SJohn Forte hilevel_pri = 0; 261fcf3ce44SJohn Forte 262fcf3ce44SJohn Forte if (pass == 1) { 263fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 264291a2b48SSukumar Swaminathan "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type, 265291a2b48SSukumar Swaminathan cfg[CFG_MSI_MODE].current, types, nintrs); 266fcf3ce44SJohn Forte } 267291a2b48SSukumar Swaminathan 268fcf3ce44SJohn Forte /* Validate interrupt count */ 269fcf3ce44SJohn Forte count = min(nintrs, max); 270fcf3ce44SJohn Forte 271fcf3ce44SJohn Forte if (count >= 8) { 272fcf3ce44SJohn Forte count = 8; 273fcf3ce44SJohn Forte } else if (count >= 4) { 274fcf3ce44SJohn Forte count = 4; 275fcf3ce44SJohn Forte } else if (count >= 2) { 276fcf3ce44SJohn Forte count = 2; 277fcf3ce44SJohn Forte } else { 278fcf3ce44SJohn Forte count = 1; 279fcf3ce44SJohn Forte } 280fcf3ce44SJohn Forte 281fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */ 282fcf3ce44SJohn Forte htable = 283291a2b48SSukumar Swaminathan kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), 284291a2b48SSukumar Swaminathan KM_SLEEP); 285fcf3ce44SJohn Forte 286fcf3ce44SJohn Forte /* Allocate 'count' interrupts */ 287291a2b48SSukumar Swaminathan ret = 288291a2b48SSukumar Swaminathan ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 289fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL); 290fcf3ce44SJohn Forte 291fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 29282527734SSukumar Swaminathan "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret); 293fcf3ce44SJohn Forte 294fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) { 295fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 296fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret); 297fcf3ce44SJohn Forte 298a9800bebSGarrett D'Amore actual = 0; 299fcf3ce44SJohn Forte goto init_failed; 300fcf3ce44SJohn Forte } 301291a2b48SSukumar Swaminathan 302fcf3ce44SJohn Forte if (actual != count) { 303fcf3ce44SJohn Forte /* Validate actual count */ 304fcf3ce44SJohn Forte if (actual >= 8) { 305fcf3ce44SJohn Forte new_actual = 8; 306fcf3ce44SJohn Forte } else if (actual >= 4) { 307fcf3ce44SJohn Forte new_actual = 4; 308fcf3ce44SJohn Forte } else if (actual >= 2) { 309fcf3ce44SJohn Forte new_actual = 2; 310fcf3ce44SJohn Forte } else { 311fcf3ce44SJohn Forte new_actual = 1; 312fcf3ce44SJohn Forte } 313fcf3ce44SJohn Forte 314fcf3ce44SJohn Forte if (new_actual < actual) { 315fcf3ce44SJohn Forte /* Free extra handles */ 316fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) { 317fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 318fcf3ce44SJohn Forte } 319fcf3ce44SJohn Forte 320fcf3ce44SJohn Forte actual = new_actual; 321fcf3ce44SJohn Forte } 322291a2b48SSukumar Swaminathan 323fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */ 324fcf3ce44SJohn Forte new_htable = 325fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 326fcf3ce44SJohn Forte KM_SLEEP); 327fcf3ce44SJohn Forte 328fcf3ce44SJohn Forte /* Copy old array to new array */ 329fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable, 330fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t))); 331fcf3ce44SJohn Forte 332fcf3ce44SJohn Forte /* Free the old array */ 333fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 334fcf3ce44SJohn Forte 335fcf3ce44SJohn Forte htable = new_htable; 336fcf3ce44SJohn Forte count = actual; 337fcf3ce44SJohn Forte } 338291a2b48SSukumar Swaminathan 339fcf3ce44SJohn Forte /* Allocate interrupt priority table */ 340fcf3ce44SJohn Forte intr_pri = 341fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 342fcf3ce44SJohn Forte KM_SLEEP); 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte /* Allocate interrupt capability table */ 345fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 346fcf3ce44SJohn Forte 347fcf3ce44SJohn Forte /* Get minimum hilevel priority */ 348fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri(); 349fcf3ce44SJohn Forte 350fcf3ce44SJohn Forte /* Fill the priority and capability tables */ 351fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 352fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 353fcf3ce44SJohn Forte 354fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 355fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 356fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. " 357291a2b48SSukumar Swaminathan "handle=%p ret=%d", 358291a2b48SSukumar Swaminathan i, &htable[i], ret); 359fcf3ce44SJohn Forte 360fcf3ce44SJohn Forte /* Clean up the interrupts */ 361fcf3ce44SJohn Forte goto init_failed; 362fcf3ce44SJohn Forte } 363291a2b48SSukumar Swaminathan 364fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) { 365fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 366fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. " 367fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x", 368fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri); 369fcf3ce44SJohn Forte 370fcf3ce44SJohn Forte /* Clean up the interrupts */ 371fcf3ce44SJohn Forte goto init_failed; 372fcf3ce44SJohn Forte } 373291a2b48SSukumar Swaminathan 374fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 375fcf3ce44SJohn Forte 376fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 377fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 378291a2b48SSukumar Swaminathan "MSI: ddi_intr_get_cap(%d) failed. " 379291a2b48SSukumar Swaminathan "handle=%p ret=%d", 380291a2b48SSukumar Swaminathan i, &htable[i], ret); 381fcf3ce44SJohn Forte 382fcf3ce44SJohn Forte /* Clean up the interrupts */ 383fcf3ce44SJohn Forte goto init_failed; 384fcf3ce44SJohn Forte } 385291a2b48SSukumar Swaminathan 386fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 387291a2b48SSukumar Swaminathan "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i, 388291a2b48SSukumar Swaminathan intr_cap[i], intr_pri[i], hilevel_pri); 389fcf3ce44SJohn Forte 390fcf3ce44SJohn Forte } 391fcf3ce44SJohn Forte 392fcf3ce44SJohn Forte /* Set mode */ 393fcf3ce44SJohn Forte switch (count) { 394fcf3ce44SJohn Forte case 8: 395fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8; 396fcf3ce44SJohn Forte break; 397fcf3ce44SJohn Forte 398fcf3ce44SJohn Forte case 4: 399fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4; 400fcf3ce44SJohn Forte break; 401fcf3ce44SJohn Forte 402fcf3ce44SJohn Forte case 2: 403fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2; 404fcf3ce44SJohn Forte break; 405fcf3ce44SJohn Forte 406fcf3ce44SJohn Forte default: 407fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1; 408fcf3ce44SJohn Forte } 409fcf3ce44SJohn Forte 410fcf3ce44SJohn Forte /* Save the info */ 411fcf3ce44SJohn Forte hba->intr_htable = htable; 412fcf3ce44SJohn Forte hba->intr_count = count; 413fcf3ce44SJohn Forte hba->intr_pri = intr_pri; 414fcf3ce44SJohn Forte hba->intr_cap = intr_cap; 415fcf3ce44SJohn Forte hba->intr_type = type; 416291a2b48SSukumar Swaminathan hba->intr_arg = (void *)((unsigned long)intr_pri[0]); 417fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode]; 418fcf3ce44SJohn Forte 419fcf3ce44SJohn Forte hba->intr_cond = 0; 42082527734SSukumar Swaminathan 42182527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */ 42282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 42382527734SSukumar Swaminathan hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current; 42482527734SSukumar Swaminathan } 42582527734SSukumar Swaminathan 426fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 427fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i]; 428fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i]; 429fcf3ce44SJohn Forte 4308f23e9faSHans Rosenfeld mutex_init(&hba->intr_lock[i], NULL, MUTEX_DRIVER, 431a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg)); 432fcf3ce44SJohn Forte } 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte /* Set flag to indicate support */ 435fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED; 436fcf3ce44SJohn Forte 437fcf3ce44SJohn Forte /* Create the interrupt threads */ 43882527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 4398f23e9faSHans Rosenfeld mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER, 440a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg)); 441fcf3ce44SJohn Forte 44282527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread); 443fcf3ce44SJohn Forte } 444fcf3ce44SJohn Forte 445fcf3ce44SJohn Forte return (DDI_SUCCESS); 446fcf3ce44SJohn Forte 447fcf3ce44SJohn Forte init_failed: 448fcf3ce44SJohn Forte 449fcf3ce44SJohn Forte if (intr_cap) { 450fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 451fcf3ce44SJohn Forte } 452291a2b48SSukumar Swaminathan 453fcf3ce44SJohn Forte if (intr_pri) { 454fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 455fcf3ce44SJohn Forte } 456291a2b48SSukumar Swaminathan 457fcf3ce44SJohn Forte if (htable) { 458fcf3ce44SJohn Forte /* Process the interrupt handlers */ 459fcf3ce44SJohn Forte for (i = 0; i < actual; i++) { 460fcf3ce44SJohn Forte /* Free the handle[i] */ 461fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 462fcf3ce44SJohn Forte } 463fcf3ce44SJohn Forte 464fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 465fcf3ce44SJohn Forte } 466291a2b48SSukumar Swaminathan 467fcf3ce44SJohn Forte /* Initialize */ 468fcf3ce44SJohn Forte hba->intr_htable = NULL; 469fcf3ce44SJohn Forte hba->intr_count = 0; 470fcf3ce44SJohn Forte hba->intr_pri = NULL; 471fcf3ce44SJohn Forte hba->intr_cap = NULL; 472fcf3ce44SJohn Forte hba->intr_type = 0; 473fcf3ce44SJohn Forte hba->intr_arg = NULL; 474fcf3ce44SJohn Forte hba->intr_cond = 0; 475fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 476fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock)); 477fcf3ce44SJohn Forte 478fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) { 479fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 480fcf3ce44SJohn Forte goto begin; 481fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) { 482fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 483fcf3ce44SJohn Forte goto begin; 484fcf3ce44SJohn Forte } 485291a2b48SSukumar Swaminathan 486fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 487fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts"); 488fcf3ce44SJohn Forte 489fcf3ce44SJohn Forte return (DDI_FAILURE); 490fcf3ce44SJohn Forte 491fcf3ce44SJohn Forte 49282527734SSukumar Swaminathan } /* emlxs_msi_init() */ 493fcf3ce44SJohn Forte 494fcf3ce44SJohn Forte 495fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 496fcf3ce44SJohn Forte int32_t 497fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba) 498fcf3ce44SJohn Forte { 499fcf3ce44SJohn Forte uint32_t count; 500fcf3ce44SJohn Forte int32_t i; 501fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 502fcf3ce44SJohn Forte uint32_t *intr_pri; 503fcf3ce44SJohn Forte int32_t *intr_cap; 504fcf3ce44SJohn Forte int32_t ret; 505fcf3ce44SJohn Forte 506fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 507fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba)); 508fcf3ce44SJohn Forte } 509291a2b48SSukumar Swaminathan 510fcf3ce44SJohn Forte /* 511291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5128f23e9faSHans Rosenfeld * "MSI: msi_uninit called. flags=%x", 513291a2b48SSukumar Swaminathan * hba->intr_flags); 514fcf3ce44SJohn Forte */ 515fcf3ce44SJohn Forte 516fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */ 517fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 518fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba); 519fcf3ce44SJohn Forte 520fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 521fcf3ce44SJohn Forte return (ret); 522fcf3ce44SJohn Forte } 523fcf3ce44SJohn Forte } 524291a2b48SSukumar Swaminathan 525fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 526fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 527fcf3ce44SJohn Forte return (DDI_SUCCESS); 528fcf3ce44SJohn Forte } 529fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED; 530fcf3ce44SJohn Forte 531fcf3ce44SJohn Forte /* Get handle table parameters */ 532fcf3ce44SJohn Forte htable = hba->intr_htable; 533fcf3ce44SJohn Forte count = hba->intr_count; 534fcf3ce44SJohn Forte intr_pri = hba->intr_pri; 535fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 536fcf3ce44SJohn Forte 537fcf3ce44SJohn Forte /* Clean up */ 538fcf3ce44SJohn Forte hba->intr_count = 0; 539fcf3ce44SJohn Forte hba->intr_htable = NULL; 540fcf3ce44SJohn Forte hba->intr_pri = NULL; 541fcf3ce44SJohn Forte hba->intr_cap = NULL; 542fcf3ce44SJohn Forte hba->intr_type = 0; 543fcf3ce44SJohn Forte hba->intr_arg = NULL; 544fcf3ce44SJohn Forte hba->intr_cond = 0; 545fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 546fcf3ce44SJohn Forte 547fcf3ce44SJohn Forte if (intr_cap) { 548fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 549fcf3ce44SJohn Forte } 550291a2b48SSukumar Swaminathan 551fcf3ce44SJohn Forte if (intr_pri) { 552fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 553fcf3ce44SJohn Forte } 554291a2b48SSukumar Swaminathan 555fcf3ce44SJohn Forte if (htable) { 556fcf3ce44SJohn Forte /* Process the interrupt handlers */ 557fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 558fcf3ce44SJohn Forte /* Free the handle[i] */ 559291a2b48SSukumar Swaminathan ret = ddi_intr_free(htable[i]); 560fcf3ce44SJohn Forte } 561fcf3ce44SJohn Forte 562fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 563fcf3ce44SJohn Forte } 564291a2b48SSukumar Swaminathan 565fcf3ce44SJohn Forte /* Destroy the intr locks */ 566fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 567fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]); 568fcf3ce44SJohn Forte } 569fcf3ce44SJohn Forte 570fcf3ce44SJohn Forte /* Destroy the interrupt threads */ 57182527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 57282527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread); 57382527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock); 574fcf3ce44SJohn Forte } 575fcf3ce44SJohn Forte 576fcf3ce44SJohn Forte /* 577291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5788f23e9faSHans Rosenfeld * "MSI: msi_uninit done. flags=%x", 579291a2b48SSukumar Swaminathan * hba->intr_flags); 580fcf3ce44SJohn Forte */ 581fcf3ce44SJohn Forte 582fcf3ce44SJohn Forte return (DDI_SUCCESS); 583fcf3ce44SJohn Forte 58482527734SSukumar Swaminathan } /* emlxs_msi_uninit() */ 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte 587fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */ 588fcf3ce44SJohn Forte int32_t 589fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba) 590fcf3ce44SJohn Forte { 591fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 592fcf3ce44SJohn Forte int32_t count; 593fcf3ce44SJohn Forte int32_t i; 594fcf3ce44SJohn Forte int32_t ret; 595fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 596fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 599fcf3ce44SJohn Forte return (emlxs_intx_add(hba)); 600fcf3ce44SJohn Forte } 601291a2b48SSukumar Swaminathan 602fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 603fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) { 604fcf3ce44SJohn Forte return (DDI_SUCCESS); 605fcf3ce44SJohn Forte } 606291a2b48SSukumar Swaminathan 607fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 608fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 609fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0); 610fcf3ce44SJohn Forte 611fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 612fcf3ce44SJohn Forte return (ret); 613fcf3ce44SJohn Forte } 614fcf3ce44SJohn Forte } 615291a2b48SSukumar Swaminathan 616fcf3ce44SJohn Forte /* Get handle table parameters */ 617fcf3ce44SJohn Forte htable = hba->intr_htable; 618fcf3ce44SJohn Forte count = hba->intr_count; 619fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 620fcf3ce44SJohn Forte 621fcf3ce44SJohn Forte /* Add the interrupt handlers */ 622fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 623fcf3ce44SJohn Forte /* add handler for handle[i] */ 624291a2b48SSukumar Swaminathan ret = 62582527734SSukumar Swaminathan ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR, 626291a2b48SSukumar Swaminathan (char *)hba, (char *)((unsigned long)i)); 627fcf3ce44SJohn Forte 628fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 629fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 630291a2b48SSukumar Swaminathan "MSI: ddi_intr_add_handler(%d) failed. " 631291a2b48SSukumar Swaminathan "handle=%p ret=%d", 632291a2b48SSukumar Swaminathan i, &htable[i], ret); 633fcf3ce44SJohn Forte 634fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */ 635fcf3ce44SJohn Forte while (i) { 636fcf3ce44SJohn Forte /* Decrement i */ 637fcf3ce44SJohn Forte i--; 638fcf3ce44SJohn Forte 639fcf3ce44SJohn Forte /* Remove the handler */ 640fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 641fcf3ce44SJohn Forte 642fcf3ce44SJohn Forte } 643fcf3ce44SJohn Forte 644fcf3ce44SJohn Forte return (DDI_FAILURE); 645fcf3ce44SJohn Forte } 646fcf3ce44SJohn Forte } 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte /* Enable the interrupts */ 649fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 650fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count); 651fcf3ce44SJohn Forte 652fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 653fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 654fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 655fcf3ce44SJohn Forte count, ret); 656fcf3ce44SJohn Forte 657fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 658fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 659fcf3ce44SJohn Forte 660fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 661fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 662fcf3ce44SJohn Forte &emlxs_init_debug_msg, 663fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. " 664291a2b48SSukumar Swaminathan "ret=%d", 665291a2b48SSukumar Swaminathan i, ret); 666fcf3ce44SJohn Forte } 667fcf3ce44SJohn Forte } 668fcf3ce44SJohn Forte } 669fcf3ce44SJohn Forte } else { 670fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 671fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 672fcf3ce44SJohn Forte 673fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 674291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 675291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 676fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d", 677fcf3ce44SJohn Forte i, ret); 678fcf3ce44SJohn Forte } 679fcf3ce44SJohn Forte } 680fcf3ce44SJohn Forte } 681fcf3ce44SJohn Forte 682fcf3ce44SJohn Forte 683fcf3ce44SJohn Forte /* Set flag to indicate support */ 684fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED; 685fcf3ce44SJohn Forte 686fcf3ce44SJohn Forte return (DDI_SUCCESS); 687fcf3ce44SJohn Forte 68882527734SSukumar Swaminathan } /* emlxs_msi_add() */ 689fcf3ce44SJohn Forte 690fcf3ce44SJohn Forte 691fcf3ce44SJohn Forte 692fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 693fcf3ce44SJohn Forte int32_t 694fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba) 695fcf3ce44SJohn Forte { 696fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 697fcf3ce44SJohn Forte uint32_t count; 698fcf3ce44SJohn Forte int32_t i; 699fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 700fcf3ce44SJohn Forte int32_t *intr_cap; 701fcf3ce44SJohn Forte int32_t ret; 702fcf3ce44SJohn Forte 703fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 704fcf3ce44SJohn Forte return (emlxs_intx_remove(hba)); 705fcf3ce44SJohn Forte } 706291a2b48SSukumar Swaminathan 707fcf3ce44SJohn Forte /* 708291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 7098f23e9faSHans Rosenfeld * "MSI: msi_remove called. flags=%x", 710291a2b48SSukumar Swaminathan * hba->intr_flags); 711fcf3ce44SJohn Forte */ 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 714fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 715fcf3ce44SJohn Forte return (DDI_SUCCESS); 716fcf3ce44SJohn Forte } 717fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED; 718fcf3ce44SJohn Forte 719fcf3ce44SJohn Forte /* Disable all adapter interrupts */ 72082527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 721fcf3ce44SJohn Forte 722fcf3ce44SJohn Forte /* Get handle table parameters */ 723fcf3ce44SJohn Forte htable = hba->intr_htable; 724fcf3ce44SJohn Forte count = hba->intr_count; 725fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 726fcf3ce44SJohn Forte 727fcf3ce44SJohn Forte /* Disable the interrupts */ 728fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 729fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count); 730fcf3ce44SJohn Forte 731fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 732fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 733fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 734fcf3ce44SJohn Forte count, ret); 735fcf3ce44SJohn Forte 736fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 737fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 738fcf3ce44SJohn Forte 739fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 740fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 741fcf3ce44SJohn Forte &emlxs_init_debug_msg, 742fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. " 743291a2b48SSukumar Swaminathan "ret=%d", 744291a2b48SSukumar Swaminathan i, ret); 745fcf3ce44SJohn Forte } 746fcf3ce44SJohn Forte } 747fcf3ce44SJohn Forte } 748fcf3ce44SJohn Forte } else { 749fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 750fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 751fcf3ce44SJohn Forte 752fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 753291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 754291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 755fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d", 756fcf3ce44SJohn Forte i, ret); 757fcf3ce44SJohn Forte } 758fcf3ce44SJohn Forte } 759fcf3ce44SJohn Forte } 760fcf3ce44SJohn Forte 761fcf3ce44SJohn Forte /* Process the interrupt handlers */ 762fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 763fcf3ce44SJohn Forte /* Remove the handler */ 764fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 765fcf3ce44SJohn Forte 766fcf3ce44SJohn Forte 767fcf3ce44SJohn Forte } 768fcf3ce44SJohn Forte 769fcf3ce44SJohn Forte return (DDI_SUCCESS); 770fcf3ce44SJohn Forte 77182527734SSukumar Swaminathan } /* emlxs_msi_remove() */ 772fcf3ce44SJohn Forte 773291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 774fcf3ce44SJohn Forte 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 777fcf3ce44SJohn Forte /* ARGSUSED */ 778fcf3ce44SJohn Forte int32_t 779fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 780fcf3ce44SJohn Forte { 781fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 78282527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 783fcf3ce44SJohn Forte int32_t ret; 784fcf3ce44SJohn Forte uint32_t i; 785fcf3ce44SJohn Forte 786fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */ 787fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) { 788fcf3ce44SJohn Forte return (DDI_SUCCESS); 789fcf3ce44SJohn Forte } 790291a2b48SSukumar Swaminathan 791fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */ 792fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 793fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 794fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x", 795fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags); 796fcf3ce44SJohn Forte 797fcf3ce44SJohn Forte return (DDI_FAILURE); 798fcf3ce44SJohn Forte } 799291a2b48SSukumar Swaminathan 800fcf3ce44SJohn Forte /* 801291a2b48SSukumar Swaminathan * Interrupt number '0' is a high-level interrupt. This driver 802291a2b48SSukumar Swaminathan * does not support having its interrupts mapped above scheduler 803291a2b48SSukumar Swaminathan * priority; i.e., we always expect to be able to call general 804291a2b48SSukumar Swaminathan * kernel routines that may invoke the scheduler. 805fcf3ce44SJohn Forte */ 806fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 807fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 808fcf3ce44SJohn Forte "INTX: High-level interrupt not supported."); 809fcf3ce44SJohn Forte 810fcf3ce44SJohn Forte return (DDI_FAILURE); 811fcf3ce44SJohn Forte } 812291a2b48SSukumar Swaminathan 813fcf3ce44SJohn Forte /* Get an iblock cookie */ 814291a2b48SSukumar Swaminathan ret = 815291a2b48SSukumar Swaminathan ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 816fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg); 817fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 818fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 819fcf3ce44SJohn Forte "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 820fcf3ce44SJohn Forte 821fcf3ce44SJohn Forte return (ret); 822fcf3ce44SJohn Forte } 823291a2b48SSukumar Swaminathan 824fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_INITED; 825fcf3ce44SJohn Forte 82682527734SSukumar Swaminathan hba->intr_count = 1; 82782527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */ 82882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 82982527734SSukumar Swaminathan hba->chan_count = cfg[CFG_NUM_WQ].current; 83082527734SSukumar Swaminathan } 83182527734SSukumar Swaminathan 832fcf3ce44SJohn Forte /* Create the interrupt threads */ 83382527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 8348f23e9faSHans Rosenfeld mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER, 835a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg)); 836fcf3ce44SJohn Forte 83782527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread); 838fcf3ce44SJohn Forte } 839fcf3ce44SJohn Forte 840fcf3ce44SJohn Forte return (DDI_SUCCESS); 841fcf3ce44SJohn Forte 84282527734SSukumar Swaminathan } /* emlxs_intx_init() */ 843fcf3ce44SJohn Forte 844fcf3ce44SJohn Forte 845fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 846fcf3ce44SJohn Forte int32_t 847fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba) 848fcf3ce44SJohn Forte { 849fcf3ce44SJohn Forte int32_t ret; 850fcf3ce44SJohn Forte uint32_t i; 851fcf3ce44SJohn Forte 852fcf3ce44SJohn Forte /* Make sure interrupts have been removed */ 853fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 854fcf3ce44SJohn Forte ret = emlxs_intx_remove(hba); 855fcf3ce44SJohn Forte 856fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 857fcf3ce44SJohn Forte return (ret); 858fcf3ce44SJohn Forte } 859fcf3ce44SJohn Forte } 860291a2b48SSukumar Swaminathan 861fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 862fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 863fcf3ce44SJohn Forte return (DDI_SUCCESS); 864fcf3ce44SJohn Forte } 865fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_INITED; 866fcf3ce44SJohn Forte 867fcf3ce44SJohn Forte hba->intr_arg = NULL; 868fcf3ce44SJohn Forte 869fcf3ce44SJohn Forte /* Create the interrupt threads */ 87082527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 87182527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread); 87282527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock); 873fcf3ce44SJohn Forte } 874fcf3ce44SJohn Forte 875fcf3ce44SJohn Forte return (DDI_SUCCESS); 876fcf3ce44SJohn Forte 87782527734SSukumar Swaminathan } /* emlxs_intx_uninit() */ 878fcf3ce44SJohn Forte 879fcf3ce44SJohn Forte 880291a2b48SSukumar Swaminathan /* 881291a2b48SSukumar Swaminathan * This is the legacy method for adding interrupts in Solaris 882291a2b48SSukumar Swaminathan * EMLXS_INTR_ADD 883291a2b48SSukumar Swaminathan */ 884fcf3ce44SJohn Forte int32_t 885fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba) 886fcf3ce44SJohn Forte { 887fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 888fcf3ce44SJohn Forte int32_t ret; 889fcf3ce44SJohn Forte 890fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 891fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_ADDED) { 892fcf3ce44SJohn Forte return (DDI_SUCCESS); 893fcf3ce44SJohn Forte } 894291a2b48SSukumar Swaminathan 895fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 896fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 897fcf3ce44SJohn Forte ret = emlxs_intx_init(hba, 0); 898fcf3ce44SJohn Forte 899fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 900fcf3ce44SJohn Forte return (ret); 901fcf3ce44SJohn Forte } 902fcf3ce44SJohn Forte } 903291a2b48SSukumar Swaminathan 904fcf3ce44SJohn Forte /* add intrrupt handler routine */ 905291a2b48SSukumar Swaminathan ret = ddi_add_intr((void *)hba->dip, 906291a2b48SSukumar Swaminathan (uint_t)EMLXS_INUMBER, 907291a2b48SSukumar Swaminathan (ddi_iblock_cookie_t *)&hba->intr_arg, 908291a2b48SSukumar Swaminathan (ddi_idevice_cookie_t *)0, 90982527734SSukumar Swaminathan (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba); 910fcf3ce44SJohn Forte 911fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 912fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 913fcf3ce44SJohn Forte "INTX: ddi_add_intr failed. ret=%d", ret); 914fcf3ce44SJohn Forte 915fcf3ce44SJohn Forte return (ret); 916fcf3ce44SJohn Forte } 917291a2b48SSukumar Swaminathan 918fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_ADDED; 919fcf3ce44SJohn Forte 920fcf3ce44SJohn Forte return (DDI_SUCCESS); 921fcf3ce44SJohn Forte 92282527734SSukumar Swaminathan } /* emlxs_intx_add() */ 923fcf3ce44SJohn Forte 924fcf3ce44SJohn Forte 925fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 926fcf3ce44SJohn Forte int32_t 927fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba) 928fcf3ce44SJohn Forte { 929fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 930fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 931fcf3ce44SJohn Forte return (DDI_SUCCESS); 932fcf3ce44SJohn Forte } 933fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_ADDED; 934fcf3ce44SJohn Forte 935fcf3ce44SJohn Forte /* Diable all adapter interrupts */ 93682527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 937fcf3ce44SJohn Forte 938fcf3ce44SJohn Forte /* Remove the interrupt */ 939fcf3ce44SJohn Forte (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 940fcf3ce44SJohn Forte hba->intr_arg); 941fcf3ce44SJohn Forte 942fcf3ce44SJohn Forte return (DDI_SUCCESS); 943fcf3ce44SJohn Forte 94482527734SSukumar Swaminathan } /* emlxs_intx_remove() */ 945fcf3ce44SJohn Forte 946fcf3ce44SJohn Forte 94782527734SSukumar Swaminathan extern void 948fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba) 949fcf3ce44SJohn Forte { 950fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 951fcf3ce44SJohn Forte emlxs_config_t *cfg; 952fcf3ce44SJohn Forte uint32_t hi; 953fcf3ce44SJohn Forte 954fcf3ce44SJohn Forte /* 955291a2b48SSukumar Swaminathan * This routine modifies the link-speed config parameter entry 956291a2b48SSukumar Swaminathan * based on adapter capabilities 957fcf3ce44SJohn Forte */ 958fcf3ce44SJohn Forte vpd = &VPD; 959fcf3ce44SJohn Forte cfg = &hba->config[CFG_LINK_SPEED]; 960fcf3ce44SJohn Forte 9618f23e9faSHans Rosenfeld (void) strlcpy(cfg->help, "Select link speed. [0=Auto", 9628f23e9faSHans Rosenfeld EMLXS_CFG_HELP_SIZE); 963fcf3ce44SJohn Forte hi = 0; 964fcf3ce44SJohn Forte 965fcf3ce44SJohn Forte if (vpd->link_speed & LMT_1GB_CAPABLE) { 9668f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 1=1Gb", EMLXS_CFG_HELP_SIZE); 967fcf3ce44SJohn Forte hi = 1; 968fcf3ce44SJohn Forte } 969291a2b48SSukumar Swaminathan 970fcf3ce44SJohn Forte if (vpd->link_speed & LMT_2GB_CAPABLE) { 9718f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 2=2Gb", EMLXS_CFG_HELP_SIZE); 972fcf3ce44SJohn Forte hi = 2; 973fcf3ce44SJohn Forte } 974291a2b48SSukumar Swaminathan 975fcf3ce44SJohn Forte if (vpd->link_speed & LMT_4GB_CAPABLE) { 9768f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 4=4Gb", EMLXS_CFG_HELP_SIZE); 977fcf3ce44SJohn Forte hi = 4; 978fcf3ce44SJohn Forte } 979291a2b48SSukumar Swaminathan 980fcf3ce44SJohn Forte if (vpd->link_speed & LMT_8GB_CAPABLE) { 9818f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 8=8Gb", EMLXS_CFG_HELP_SIZE); 982fcf3ce44SJohn Forte hi = 8; 983fcf3ce44SJohn Forte } 984291a2b48SSukumar Swaminathan 985fcf3ce44SJohn Forte if (vpd->link_speed & LMT_10GB_CAPABLE) { 9868f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 10=10Gb", EMLXS_CFG_HELP_SIZE); 987fcf3ce44SJohn Forte hi = 10; 988fcf3ce44SJohn Forte } 989291a2b48SSukumar Swaminathan 9908f23e9faSHans Rosenfeld if (vpd->link_speed & LMT_16GB_CAPABLE) { 9918f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 16=16Gb", EMLXS_CFG_HELP_SIZE); 9928f23e9faSHans Rosenfeld hi = 16; 9938f23e9faSHans Rosenfeld } 9948f23e9faSHans Rosenfeld 995*a3170057SPaul Winder if (vpd->link_speed & LMT_32GB_CAPABLE) { 996*a3170057SPaul Winder (void) strlcat(cfg->help, ", 32=32Gb", EMLXS_CFG_HELP_SIZE); 997*a3170057SPaul Winder hi = 32; 998*a3170057SPaul Winder } 999*a3170057SPaul Winder 10008f23e9faSHans Rosenfeld (void) strlcat(cfg->help, "]", EMLXS_CFG_HELP_SIZE); 1001fcf3ce44SJohn Forte cfg->hi = hi; 1002fcf3ce44SJohn Forte 1003fcf3ce44SJohn Forte /* Now revalidate the current parameter setting */ 1004fcf3ce44SJohn Forte cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte return; 1007fcf3ce44SJohn Forte 100882527734SSukumar Swaminathan } /* emlxs_process_link_speed() */ 1009fcf3ce44SJohn Forte 1010fcf3ce44SJohn Forte 1011fcf3ce44SJohn Forte /* 1012291a2b48SSukumar Swaminathan * emlxs_parse_vpd() 1013fcf3ce44SJohn Forte * 1014fcf3ce44SJohn Forte * This routine will parse the VPD data 1015fcf3ce44SJohn Forte */ 1016fcf3ce44SJohn Forte extern int 1017fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 1018fcf3ce44SJohn Forte { 1019fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1020fcf3ce44SJohn Forte char tag[3]; 1021fcf3ce44SJohn Forte uint8_t lenlo, lenhi; 1022fcf3ce44SJohn Forte uint32_t n; 1023fcf3ce44SJohn Forte uint16_t block_size; 1024fcf3ce44SJohn Forte uint32_t block_index = 0; 1025fcf3ce44SJohn Forte uint8_t sub_size; 1026fcf3ce44SJohn Forte uint32_t sub_index; 1027fcf3ce44SJohn Forte int32_t finished = 0; 1028fcf3ce44SJohn Forte int32_t index = 0; 1029fcf3ce44SJohn Forte char buffer[128]; 1030fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 1031fcf3ce44SJohn Forte 1032fcf3ce44SJohn Forte vpd = &VPD; 1033fcf3ce44SJohn Forte 1034fcf3ce44SJohn Forte 1035fcf3ce44SJohn Forte while (!finished && (block_index < size)) { 1036fcf3ce44SJohn Forte /* 1037291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1038291a2b48SSukumar Swaminathan * "block_index = %x", block_index); 1039fcf3ce44SJohn Forte */ 1040fcf3ce44SJohn Forte 1041fcf3ce44SJohn Forte switch (vpd_buf[block_index]) { 1042fcf3ce44SJohn Forte case 0x82: 1043fcf3ce44SJohn Forte index = block_index; 1044fcf3ce44SJohn Forte index += 1; 1045fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 1046fcf3ce44SJohn Forte index += 1; 1047fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 1048fcf3ce44SJohn Forte index += 1; 1049fcf3ce44SJohn Forte block_index = index; 1050fcf3ce44SJohn Forte 1051fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1052fcf3ce44SJohn Forte block_index += block_size; 1053fcf3ce44SJohn Forte 1054fcf3ce44SJohn Forte /* 1055fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1056291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 1057fcf3ce44SJohn Forte */ 1058fcf3ce44SJohn Forte 1059fcf3ce44SJohn Forte n = sizeof (buffer); 1060fcf3ce44SJohn Forte bzero(buffer, n); 1061fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 1062fcf3ce44SJohn Forte (block_size < (n - 1)) ? block_size : (n - 1)); 1063fcf3ce44SJohn Forte 10648f23e9faSHans Rosenfeld (void) strncpy(vpd->id, buffer, (sizeof (vpd->id)-1)); 1065291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s", 1066291a2b48SSukumar Swaminathan vpd->id); 1067fcf3ce44SJohn Forte 1068fcf3ce44SJohn Forte break; 1069fcf3ce44SJohn Forte 1070fcf3ce44SJohn Forte case 0x90: 1071fcf3ce44SJohn Forte index = block_index; 1072fcf3ce44SJohn Forte index += 1; 1073fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 1074fcf3ce44SJohn Forte index += 1; 1075fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 1076fcf3ce44SJohn Forte index += 1; 1077fcf3ce44SJohn Forte block_index = index; 1078fcf3ce44SJohn Forte sub_index = index; 1079fcf3ce44SJohn Forte 1080fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1081fcf3ce44SJohn Forte block_index += block_size; 1082fcf3ce44SJohn Forte 1083fcf3ce44SJohn Forte /* 1084fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1085291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 1086fcf3ce44SJohn Forte */ 1087fcf3ce44SJohn Forte 1088fcf3ce44SJohn Forte /* Scan for sub-blocks */ 1089fcf3ce44SJohn Forte while ((sub_index < block_index) && 1090fcf3ce44SJohn Forte (sub_index < size)) { 1091fcf3ce44SJohn Forte /* 1092fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1093291a2b48SSukumar Swaminathan * "sub_index = %x", sub_index); 1094fcf3ce44SJohn Forte */ 1095fcf3ce44SJohn Forte 1096fcf3ce44SJohn Forte index = sub_index; 1097fcf3ce44SJohn Forte tag[0] = vpd_buf[index++]; 1098fcf3ce44SJohn Forte tag[1] = vpd_buf[index++]; 1099fcf3ce44SJohn Forte tag[2] = 0; 1100fcf3ce44SJohn Forte sub_size = vpd_buf[index++]; 1101fcf3ce44SJohn Forte 1102fcf3ce44SJohn Forte /* 1103fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1104291a2b48SSukumar Swaminathan * "sub_size = %x", sub_size); 1105fcf3ce44SJohn Forte */ 1106fcf3ce44SJohn Forte 1107fcf3ce44SJohn Forte sub_index = (index + sub_size); 1108fcf3ce44SJohn Forte 1109fcf3ce44SJohn Forte n = sizeof (buffer); 1110fcf3ce44SJohn Forte bzero(buffer, n); 1111fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 1112fcf3ce44SJohn Forte (sub_size < (n - 1)) ? sub_size : (n - 1)); 1113fcf3ce44SJohn Forte 1114fcf3ce44SJohn Forte /* 1115fcf3ce44SJohn Forte * Look for Engineering Change (EC) 1116fcf3ce44SJohn Forte */ 1117fcf3ce44SJohn Forte if (strcmp(tag, "EC") == 0) { 11188f23e9faSHans Rosenfeld (void) strncpy(vpd->eng_change, buffer, 11198f23e9faSHans Rosenfeld (sizeof (vpd->eng_change)-1)); 1120fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1121291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "EC: %s", 1122291a2b48SSukumar Swaminathan vpd->eng_change); 1123fcf3ce44SJohn Forte } 1124fcf3ce44SJohn Forte /* 1125fcf3ce44SJohn Forte * Look for Manufacturer (MN) 1126fcf3ce44SJohn Forte */ 1127fcf3ce44SJohn Forte else if (strcmp(tag, "MN") == 0) { 11288f23e9faSHans Rosenfeld (void) strncpy(vpd->manufacturer, 11298f23e9faSHans Rosenfeld buffer, 11308f23e9faSHans Rosenfeld (sizeof (vpd->manufacturer)-1)); 1131fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1132291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "MN: %s", 1133291a2b48SSukumar Swaminathan vpd->manufacturer); 1134fcf3ce44SJohn Forte } 1135fcf3ce44SJohn Forte /* 1136fcf3ce44SJohn Forte * Look for Serial Number (SN) 1137fcf3ce44SJohn Forte */ 1138fcf3ce44SJohn Forte else if (strcmp(tag, "SN") == 0) { 11398f23e9faSHans Rosenfeld (void) strncpy(vpd->serial_num, buffer, 11408f23e9faSHans Rosenfeld (sizeof (vpd->serial_num)-1)); 1141fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1142291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "SN: %s", 1143291a2b48SSukumar Swaminathan vpd->serial_num); 1144fcf3ce44SJohn Forte 1145fcf3ce44SJohn Forte /* Validate the serial number */ 1146291a2b48SSukumar Swaminathan if (strncmp(buffer, "FFFFFFFFFF", 10) == 1147291a2b48SSukumar Swaminathan 0 || 1148291a2b48SSukumar Swaminathan strncmp(buffer, "0000000000", 10) == 1149291a2b48SSukumar Swaminathan 0) { 1150fcf3ce44SJohn Forte vpd->serial_num[0] = 0; 1151fcf3ce44SJohn Forte } 1152fcf3ce44SJohn Forte } 1153fcf3ce44SJohn Forte /* 1154fcf3ce44SJohn Forte * Look for Part Number (PN) 1155fcf3ce44SJohn Forte */ 1156fcf3ce44SJohn Forte else if (strcmp(tag, "PN") == 0) { 11578f23e9faSHans Rosenfeld (void) strncpy(vpd->part_num, buffer, 11588f23e9faSHans Rosenfeld (sizeof (vpd->part_num)-1)); 1159fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1160291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "PN: %s", 1161291a2b48SSukumar Swaminathan vpd->part_num); 1162fcf3ce44SJohn Forte } 1163fcf3ce44SJohn Forte /* 1164fcf3ce44SJohn Forte * Look for (V0) 1165fcf3ce44SJohn Forte */ 1166fcf3ce44SJohn Forte else if (strcmp(tag, "V0") == 0) { 1167fcf3ce44SJohn Forte /* Not used */ 1168fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1169291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "V0: %s", buffer); 1170fcf3ce44SJohn Forte } 1171fcf3ce44SJohn Forte /* 1172fcf3ce44SJohn Forte * Look for model description (V1) 1173fcf3ce44SJohn Forte */ 1174fcf3ce44SJohn Forte else if (strcmp(tag, "V1") == 0) { 11758f23e9faSHans Rosenfeld (void) strncpy(vpd->model_desc, buffer, 11768f23e9faSHans Rosenfeld (sizeof (vpd->model_desc)-1)); 1177fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1178291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Desc: %s", 1179291a2b48SSukumar Swaminathan vpd->model_desc); 1180fcf3ce44SJohn Forte } 1181fcf3ce44SJohn Forte /* 1182fcf3ce44SJohn Forte * Look for model (V2) 1183fcf3ce44SJohn Forte */ 1184fcf3ce44SJohn Forte else if (strcmp(tag, "V2") == 0) { 11858f23e9faSHans Rosenfeld (void) strncpy(vpd->model, buffer, 11868f23e9faSHans Rosenfeld (sizeof (vpd->model)-1)); 1187fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1188291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Model: %s", 1189291a2b48SSukumar Swaminathan vpd->model); 1190fcf3ce44SJohn Forte } 1191fcf3ce44SJohn Forte /* 1192fcf3ce44SJohn Forte * Look for program type (V3) 1193fcf3ce44SJohn Forte */ 1194fcf3ce44SJohn Forte 1195fcf3ce44SJohn Forte else if (strcmp(tag, "V3") == 0) { 11968f23e9faSHans Rosenfeld (void) strncpy(vpd->prog_types, 11978f23e9faSHans Rosenfeld buffer, 11988f23e9faSHans Rosenfeld (sizeof (vpd->prog_types)-1)); 1199fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1200291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Prog Types: %s", 1201291a2b48SSukumar Swaminathan vpd->prog_types); 1202fcf3ce44SJohn Forte } 1203fcf3ce44SJohn Forte /* 1204fcf3ce44SJohn Forte * Look for port number (V4) 1205fcf3ce44SJohn Forte */ 1206fcf3ce44SJohn Forte else if (strcmp(tag, "V4") == 0) { 12078f23e9faSHans Rosenfeld (void) strncpy(vpd->port_num, buffer, 12088f23e9faSHans Rosenfeld (sizeof (vpd->port_num)-1)); 1209fcf3ce44SJohn Forte vpd->port_index = 1210fcf3ce44SJohn Forte emlxs_strtol(vpd->port_num, 10); 1211fcf3ce44SJohn Forte 1212fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1213291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Port: %s", 1214291a2b48SSukumar Swaminathan (vpd->port_num[0]) ? vpd-> 1215291a2b48SSukumar Swaminathan port_num : "not applicable"); 1216fcf3ce44SJohn Forte } 1217fcf3ce44SJohn Forte /* 1218fcf3ce44SJohn Forte * Look for checksum (RV) 1219fcf3ce44SJohn Forte */ 1220fcf3ce44SJohn Forte else if (strcmp(tag, "RV") == 0) { 1221fcf3ce44SJohn Forte /* Not used */ 1222fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1223291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Checksum: 0x%x", 1224291a2b48SSukumar Swaminathan buffer[0]); 1225291a2b48SSukumar Swaminathan } 1226291a2b48SSukumar Swaminathan 1227291a2b48SSukumar Swaminathan else { 1228fcf3ce44SJohn Forte /* Generic */ 1229fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1230291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Tag: %s: %s", 1231291a2b48SSukumar Swaminathan tag, buffer); 1232fcf3ce44SJohn Forte } 1233fcf3ce44SJohn Forte } 1234fcf3ce44SJohn Forte 1235fcf3ce44SJohn Forte break; 1236fcf3ce44SJohn Forte 1237fcf3ce44SJohn Forte case 0x78: 1238fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 1239fcf3ce44SJohn Forte finished = 1; 1240fcf3ce44SJohn Forte break; 1241fcf3ce44SJohn Forte 1242fcf3ce44SJohn Forte default: 1243fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1244fcf3ce44SJohn Forte "Unknown block: %x %x %x %x %x %x %x %x", 1245fcf3ce44SJohn Forte vpd_buf[index], vpd_buf[index + 1], 1246fcf3ce44SJohn Forte vpd_buf[index + 2], vpd_buf[index + 3], 1247fcf3ce44SJohn Forte vpd_buf[index + 4], vpd_buf[index + 5], 1248fcf3ce44SJohn Forte vpd_buf[index + 6], vpd_buf[index + 7]); 1249fcf3ce44SJohn Forte return (0); 1250fcf3ce44SJohn Forte } 1251fcf3ce44SJohn Forte } 1252fcf3ce44SJohn Forte 1253fcf3ce44SJohn Forte return (1); 1254fcf3ce44SJohn Forte 125582527734SSukumar Swaminathan } /* emlxs_parse_vpd */ 125682527734SSukumar Swaminathan 125782527734SSukumar Swaminathan 125882527734SSukumar Swaminathan /* 125982527734SSukumar Swaminathan * emlxs_parse_fcoe() 126082527734SSukumar Swaminathan * 126182527734SSukumar Swaminathan * This routine will parse the VPD data 126282527734SSukumar Swaminathan */ 126382527734SSukumar Swaminathan extern int 126482527734SSukumar Swaminathan emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size) 126582527734SSukumar Swaminathan { 126682527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 126782527734SSukumar Swaminathan tlv_fcoe_t *fcoelist; 126882527734SSukumar Swaminathan tlv_fcfconnectlist_t *fcflist; 126982527734SSukumar Swaminathan int i; 12708f23e9faSHans Rosenfeld uint32_t flags; 12718f23e9faSHans Rosenfeld uint32_t entry_count; 12728f23e9faSHans Rosenfeld char FabricName[32]; 12738f23e9faSHans Rosenfeld char SwitchName[32]; 127482527734SSukumar Swaminathan 127582527734SSukumar Swaminathan /* Validate the config region 23 signature */ 127682527734SSukumar Swaminathan if ((*fcoep != 'R') || (*(fcoep+1) != 'G') || 127782527734SSukumar Swaminathan (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) { 127882527734SSukumar Swaminathan return (0); 127982527734SSukumar Swaminathan } 128082527734SSukumar Swaminathan 128182527734SSukumar Swaminathan /* Search the config region 23, for FCOE Parameters record */ 128282527734SSukumar Swaminathan i = 4; 128382527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) { 128482527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2; 128582527734SSukumar Swaminathan } 128682527734SSukumar Swaminathan 128782527734SSukumar Swaminathan if (*(fcoep+i) == 0xA0) { 128882527734SSukumar Swaminathan fcoelist = (tlv_fcoe_t *)(fcoep+i); 128982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 129082527734SSukumar Swaminathan "Found FCOE Params (A0):%d x%x", 129182527734SSukumar Swaminathan fcoelist->length, fcoelist->fip_flags); 129282527734SSukumar Swaminathan bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE, 129382527734SSukumar Swaminathan sizeof (tlv_fcoe_t)); 129482527734SSukumar Swaminathan } 129582527734SSukumar Swaminathan 129682527734SSukumar Swaminathan 129782527734SSukumar Swaminathan /* Search the config region 23, for FCF record */ 129882527734SSukumar Swaminathan i = 4; 129982527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) { 130082527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2; 130182527734SSukumar Swaminathan } 130282527734SSukumar Swaminathan 130382527734SSukumar Swaminathan if (*(fcoep+i) == 0xA1) { 130482527734SSukumar Swaminathan fcflist = (tlv_fcfconnectlist_t *)(fcoep+i); 130582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 130682527734SSukumar Swaminathan "Found FCF ConnectList (A1):%d", fcflist->length); 13078f23e9faSHans Rosenfeld 130882527734SSukumar Swaminathan bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF, 130982527734SSukumar Swaminathan sizeof (tlv_fcfconnectlist_t)); 13108f23e9faSHans Rosenfeld 13118f23e9faSHans Rosenfeld /* Display the list */ 13128f23e9faSHans Rosenfeld entry_count = (hba->sli.sli4.cfgFCF.length * 13138f23e9faSHans Rosenfeld sizeof (uint32_t)) / sizeof (tlv_fcfconnectentry_t); 13148f23e9faSHans Rosenfeld 13158f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 13168f23e9faSHans Rosenfeld "FCF List: %d entries", entry_count); 13178f23e9faSHans Rosenfeld 13188f23e9faSHans Rosenfeld for (i = 0; i < entry_count; i++) { 13198f23e9faSHans Rosenfeld flags = *(uint32_t *)&hba->sli.sli4.cfgFCF.entry[i]; 13208f23e9faSHans Rosenfeld (void) emlxs_wwn_xlate(FabricName, sizeof (FabricName), 13218f23e9faSHans Rosenfeld hba->sli.sli4.cfgFCF.entry[i].FabricName); 13228f23e9faSHans Rosenfeld (void) emlxs_wwn_xlate(SwitchName, sizeof (SwitchName), 13238f23e9faSHans Rosenfeld hba->sli.sli4.cfgFCF.entry[i].SwitchName); 13248f23e9faSHans Rosenfeld 13258f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 13268f23e9faSHans Rosenfeld "FCF List:%02d %08x %s %s", 13278f23e9faSHans Rosenfeld i, flags, FabricName, SwitchName); 13288f23e9faSHans Rosenfeld } 132982527734SSukumar Swaminathan } 133082527734SSukumar Swaminathan 133182527734SSukumar Swaminathan return (1); 133282527734SSukumar Swaminathan 133382527734SSukumar Swaminathan } /* emlxs_parse_fcoe */ 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte 1336fcf3ce44SJohn Forte extern void 1337fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 1338fcf3ce44SJohn Forte { 1339fcf3ce44SJohn Forte if (vpd->rBit) { 1340fcf3ce44SJohn Forte switch (hba->sli_mode) { 1341291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI4_MODE: 13428f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli4FwName, 13438f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1)); 13448f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli4FwLabel, 13458f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1346fcf3ce44SJohn Forte break; 1347291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI3_MODE: 13488f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli3FwName, 13498f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1)); 13508f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli3FwLabel, 13518f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1352fcf3ce44SJohn Forte break; 1353291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI2_MODE: 13548f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli2FwName, 13558f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1)); 13568f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli2FwLabel, 13578f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1358fcf3ce44SJohn Forte break; 1359291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI1_MODE: 13608f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli1FwName, 13618f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1)); 13628f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli1FwLabel, 13638f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1364fcf3ce44SJohn Forte break; 1365fcf3ce44SJohn Forte default: 13668f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, "unknown", 13678f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1)); 13688f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->fw_version, 13698f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1370fcf3ce44SJohn Forte } 1371fcf3ce44SJohn Forte } else { 13728f23e9faSHans Rosenfeld emlxs_decode_version(vpd->smFwRev, vpd->fw_version, 13738f23e9faSHans Rosenfeld sizeof (vpd->fw_version)); 13748f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->fw_version, 13758f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1)); 1376fcf3ce44SJohn Forte } 1377fcf3ce44SJohn Forte 1378fcf3ce44SJohn Forte return; 1379fcf3ce44SJohn Forte 138082527734SSukumar Swaminathan } /* emlxs_decode_firmware_rev() */ 1381fcf3ce44SJohn Forte 1382fcf3ce44SJohn Forte 1383fcf3ce44SJohn Forte 1384fcf3ce44SJohn Forte extern void 13858f23e9faSHans Rosenfeld emlxs_decode_version(uint32_t version, char *buffer, size_t len) 1386fcf3ce44SJohn Forte { 1387fcf3ce44SJohn Forte uint32_t b1, b2, b3, b4; 1388fcf3ce44SJohn Forte char c; 1389fcf3ce44SJohn Forte 1390fcf3ce44SJohn Forte b1 = (version & 0x0000f000) >> 12; 1391fcf3ce44SJohn Forte b2 = (version & 0x00000f00) >> 8; 1392fcf3ce44SJohn Forte b3 = (version & 0x000000c0) >> 6; 1393fcf3ce44SJohn Forte b4 = (version & 0x00000030) >> 4; 1394fcf3ce44SJohn Forte 1395fcf3ce44SJohn Forte if (b1 == 0 && b2 == 0) { 13968f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "none"); 1397fcf3ce44SJohn Forte return; 1398fcf3ce44SJohn Forte } 1399291a2b48SSukumar Swaminathan 1400fcf3ce44SJohn Forte c = 0; 1401fcf3ce44SJohn Forte switch (b4) { 1402fcf3ce44SJohn Forte case 0: 1403fcf3ce44SJohn Forte c = 'n'; 1404fcf3ce44SJohn Forte break; 1405fcf3ce44SJohn Forte case 1: 1406fcf3ce44SJohn Forte c = 'a'; 1407fcf3ce44SJohn Forte break; 1408fcf3ce44SJohn Forte case 2: 1409fcf3ce44SJohn Forte c = 'b'; 1410fcf3ce44SJohn Forte break; 1411fcf3ce44SJohn Forte case 3: 1412fcf3ce44SJohn Forte if ((version & 0x0000000f)) { 1413fcf3ce44SJohn Forte c = 'x'; 1414fcf3ce44SJohn Forte } 1415fcf3ce44SJohn Forte break; 1416fcf3ce44SJohn Forte 1417fcf3ce44SJohn Forte } 1418fcf3ce44SJohn Forte b4 = (version & 0x0000000f); 1419fcf3ce44SJohn Forte 1420fcf3ce44SJohn Forte if (c == 0) { 14218f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "%d.%d%d", b1, b2, b3); 1422fcf3ce44SJohn Forte } else { 14238f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "%d.%d%d%c%d", b1, b2, b3, c, b4); 1424fcf3ce44SJohn Forte } 1425fcf3ce44SJohn Forte 1426fcf3ce44SJohn Forte return; 1427fcf3ce44SJohn Forte 142882527734SSukumar Swaminathan } /* emlxs_decode_version() */ 1429fcf3ce44SJohn Forte 1430fcf3ce44SJohn Forte 143182527734SSukumar Swaminathan extern void 14328f23e9faSHans Rosenfeld emlxs_decode_label(char *label, char *buffer, int bige, size_t len) 1433fcf3ce44SJohn Forte { 1434fcf3ce44SJohn Forte uint32_t i; 1435fcf3ce44SJohn Forte char name[16]; 1436fcf3ce44SJohn Forte 14378f23e9faSHans Rosenfeld bzero(name, sizeof (name)); 14388f23e9faSHans Rosenfeld bcopy(label, name, MIN(sizeof (name), len)); 143982527734SSukumar Swaminathan /* bige is TRUE if the data format is big endian */ 1440fcf3ce44SJohn Forte 144182527734SSukumar Swaminathan if (bige) { 144282527734SSukumar Swaminathan /* Data format big Endian */ 144382527734SSukumar Swaminathan LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 144482527734SSukumar Swaminathan 144582527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) { 144682527734SSukumar Swaminathan if (name[i] == 0x20) { 144782527734SSukumar Swaminathan name[i] = 0; 144882527734SSukumar Swaminathan } 144982527734SSukumar Swaminathan } 145082527734SSukumar Swaminathan } else { 145182527734SSukumar Swaminathan /* Data format little Endian */ 145282527734SSukumar Swaminathan BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 1453fcf3ce44SJohn Forte 145482527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) { 145582527734SSukumar Swaminathan if (name[i] == 0x20) { 145682527734SSukumar Swaminathan name[i] = 0; 145782527734SSukumar Swaminathan } 1458fcf3ce44SJohn Forte } 1459fcf3ce44SJohn Forte } 1460fcf3ce44SJohn Forte 14618f23e9faSHans Rosenfeld (void) strlcpy(buffer, name, len); 1462fcf3ce44SJohn Forte 1463fcf3ce44SJohn Forte return; 1464fcf3ce44SJohn Forte 146582527734SSukumar Swaminathan } /* emlxs_decode_label() */ 1466fcf3ce44SJohn Forte 1467fcf3ce44SJohn Forte 1468fcf3ce44SJohn Forte extern uint32_t 1469fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base) 1470fcf3ce44SJohn Forte { 1471fcf3ce44SJohn Forte uint32_t value = 0; 1472fcf3ce44SJohn Forte char *ptr; 1473fcf3ce44SJohn Forte uint32_t factor = 1; 1474fcf3ce44SJohn Forte uint32_t digits; 1475fcf3ce44SJohn Forte 1476fcf3ce44SJohn Forte if (*str == 0) { 1477fcf3ce44SJohn Forte return (0); 1478fcf3ce44SJohn Forte } 1479291a2b48SSukumar Swaminathan 1480fcf3ce44SJohn Forte if (base != 10 && base != 16) { 1481fcf3ce44SJohn Forte return (0); 1482fcf3ce44SJohn Forte } 1483291a2b48SSukumar Swaminathan 1484fcf3ce44SJohn Forte /* Get max digits of value */ 1485fcf3ce44SJohn Forte digits = (base == 10) ? 9 : 8; 1486fcf3ce44SJohn Forte 1487fcf3ce44SJohn Forte /* Position pointer to end of string */ 1488fcf3ce44SJohn Forte ptr = str + strlen(str); 1489fcf3ce44SJohn Forte 1490fcf3ce44SJohn Forte /* Process string backwards */ 1491fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 1492fcf3ce44SJohn Forte /* check for base 10 numbers */ 1493fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 1494fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 1495fcf3ce44SJohn Forte factor *= base; 1496fcf3ce44SJohn Forte digits--; 1497fcf3ce44SJohn Forte } else if (base == 16) { 1498fcf3ce44SJohn Forte /* Check for base 16 numbers */ 1499fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 1500291a2b48SSukumar Swaminathan value += 1501291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 1502fcf3ce44SJohn Forte factor *= base; 1503fcf3ce44SJohn Forte digits--; 1504fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 1505291a2b48SSukumar Swaminathan value += 1506291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 1507fcf3ce44SJohn Forte factor *= base; 1508fcf3ce44SJohn Forte digits--; 1509fcf3ce44SJohn Forte } else if (factor > 1) { 1510fcf3ce44SJohn Forte break; 1511fcf3ce44SJohn Forte } 1512fcf3ce44SJohn Forte } else if (factor > 1) { 1513fcf3ce44SJohn Forte break; 1514fcf3ce44SJohn Forte } 1515fcf3ce44SJohn Forte } 1516fcf3ce44SJohn Forte 1517fcf3ce44SJohn Forte return (value); 1518fcf3ce44SJohn Forte 151982527734SSukumar Swaminathan } /* emlxs_strtol() */ 1520fcf3ce44SJohn Forte 1521fcf3ce44SJohn Forte 1522fcf3ce44SJohn Forte extern uint64_t 1523fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base) 1524fcf3ce44SJohn Forte { 1525fcf3ce44SJohn Forte uint64_t value = 0; 1526fcf3ce44SJohn Forte char *ptr; 1527fcf3ce44SJohn Forte uint32_t factor = 1; 1528fcf3ce44SJohn Forte uint32_t digits; 1529fcf3ce44SJohn Forte 1530fcf3ce44SJohn Forte if (*str == 0) { 1531fcf3ce44SJohn Forte return (0); 1532fcf3ce44SJohn Forte } 1533291a2b48SSukumar Swaminathan 1534fcf3ce44SJohn Forte if (base != 10 && base != 16) { 1535fcf3ce44SJohn Forte return (0); 1536fcf3ce44SJohn Forte } 1537291a2b48SSukumar Swaminathan 1538fcf3ce44SJohn Forte /* Get max digits of value */ 1539fcf3ce44SJohn Forte digits = (base == 10) ? 19 : 16; 1540fcf3ce44SJohn Forte 1541fcf3ce44SJohn Forte /* Position pointer to end of string */ 1542fcf3ce44SJohn Forte ptr = str + strlen(str); 1543fcf3ce44SJohn Forte 1544fcf3ce44SJohn Forte /* Process string backwards */ 1545fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 1546fcf3ce44SJohn Forte /* check for base 10 numbers */ 1547fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 1548fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 1549fcf3ce44SJohn Forte factor *= base; 1550fcf3ce44SJohn Forte digits--; 1551fcf3ce44SJohn Forte } else if (base == 16) { 1552fcf3ce44SJohn Forte /* Check for base 16 numbers */ 1553fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 1554291a2b48SSukumar Swaminathan value += 1555291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 1556fcf3ce44SJohn Forte factor *= base; 1557fcf3ce44SJohn Forte digits--; 1558fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 1559291a2b48SSukumar Swaminathan value += 1560291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 1561fcf3ce44SJohn Forte factor *= base; 1562fcf3ce44SJohn Forte digits--; 1563fcf3ce44SJohn Forte } else if (factor > 1) { 1564fcf3ce44SJohn Forte break; 1565fcf3ce44SJohn Forte } 1566fcf3ce44SJohn Forte } else if (factor > 1) { 1567fcf3ce44SJohn Forte break; 1568fcf3ce44SJohn Forte } 1569fcf3ce44SJohn Forte } 1570fcf3ce44SJohn Forte 1571fcf3ce44SJohn Forte return (value); 1572fcf3ce44SJohn Forte 157382527734SSukumar Swaminathan } /* emlxs_strtoll() */ 1574fcf3ce44SJohn Forte 157582527734SSukumar Swaminathan extern void 1576fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 1577fcf3ce44SJohn Forte { 1578fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1579fcf3ce44SJohn Forte uint32_t i; 1580fcf3ce44SJohn Forte char *ptr; 1581fcf3ce44SJohn Forte emlxs_model_t *model; 1582fcf3ce44SJohn Forte char types_buffer[256]; 1583fcf3ce44SJohn Forte char *types; 1584fcf3ce44SJohn Forte 1585fcf3ce44SJohn Forte bcopy(prog_types, types_buffer, 256); 1586fcf3ce44SJohn Forte types = types_buffer; 1587fcf3ce44SJohn Forte 1588fcf3ce44SJohn Forte model = &hba->model_info; 1589fcf3ce44SJohn Forte 1590fcf3ce44SJohn Forte while (*types) { 1591fcf3ce44SJohn Forte if (strncmp(types, "T2:", 3) == 0) { 1592fcf3ce44SJohn Forte bzero(model->pt_2, sizeof (model->pt_2)); 1593fcf3ce44SJohn Forte types += 3; 1594fcf3ce44SJohn Forte 1595fcf3ce44SJohn Forte i = 0; 1596fcf3ce44SJohn Forte while (*types && *types != 'T') { 1597fcf3ce44SJohn Forte /* Null terminate the next value */ 1598fcf3ce44SJohn Forte ptr = types; 1599fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1600fcf3ce44SJohn Forte ptr++; 1601fcf3ce44SJohn Forte *ptr = 0; 1602fcf3ce44SJohn Forte 1603fcf3ce44SJohn Forte /* Save the value */ 1604fcf3ce44SJohn Forte model->pt_2[i++] = 1605fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1606fcf3ce44SJohn Forte 1607fcf3ce44SJohn Forte /* 1608fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1609fcf3ce44SJohn Forte * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 1610fcf3ce44SJohn Forte */ 1611fcf3ce44SJohn Forte 1612fcf3ce44SJohn Forte /* Move the str pointer */ 1613fcf3ce44SJohn Forte types = ptr + 1; 1614fcf3ce44SJohn Forte } 1615fcf3ce44SJohn Forte 1616fcf3ce44SJohn Forte } else if (strncmp(types, "T3:", 3) == 0) { 1617fcf3ce44SJohn Forte bzero(model->pt_3, sizeof (model->pt_3)); 1618fcf3ce44SJohn Forte types += 3; 1619fcf3ce44SJohn Forte 1620fcf3ce44SJohn Forte i = 0; 1621fcf3ce44SJohn Forte while (*types && *types != 'T') { 1622fcf3ce44SJohn Forte /* Null terminate the next value */ 1623fcf3ce44SJohn Forte ptr = types; 1624fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1625fcf3ce44SJohn Forte ptr++; 1626fcf3ce44SJohn Forte *ptr = 0; 1627fcf3ce44SJohn Forte 1628fcf3ce44SJohn Forte /* Save the value */ 1629fcf3ce44SJohn Forte model->pt_3[i++] = 1630fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1631fcf3ce44SJohn Forte 1632fcf3ce44SJohn Forte /* 1633fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1634fcf3ce44SJohn Forte * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 1635fcf3ce44SJohn Forte */ 1636fcf3ce44SJohn Forte 1637fcf3ce44SJohn Forte /* Move the str pointer */ 1638fcf3ce44SJohn Forte types = ptr + 1; 1639fcf3ce44SJohn Forte } 1640fcf3ce44SJohn Forte } else if (strncmp(types, "T6:", 3) == 0) { 1641fcf3ce44SJohn Forte bzero(model->pt_6, sizeof (model->pt_6)); 1642fcf3ce44SJohn Forte types += 3; 1643fcf3ce44SJohn Forte 1644fcf3ce44SJohn Forte i = 0; 1645fcf3ce44SJohn Forte while (*types && *types != 'T') { 1646fcf3ce44SJohn Forte /* Null terminate the next value */ 1647fcf3ce44SJohn Forte ptr = types; 1648fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1649fcf3ce44SJohn Forte ptr++; 1650fcf3ce44SJohn Forte *ptr = 0; 1651fcf3ce44SJohn Forte 1652fcf3ce44SJohn Forte /* Save the value */ 1653fcf3ce44SJohn Forte model->pt_6[i++] = 1654fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1655fcf3ce44SJohn Forte model->pt_6[i] = 0; 1656fcf3ce44SJohn Forte 1657fcf3ce44SJohn Forte /* 1658fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1659fcf3ce44SJohn Forte * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 1660fcf3ce44SJohn Forte */ 1661fcf3ce44SJohn Forte 1662fcf3ce44SJohn Forte /* Move the str pointer */ 1663fcf3ce44SJohn Forte types = ptr + 1; 1664fcf3ce44SJohn Forte } 1665fcf3ce44SJohn Forte } else if (strncmp(types, "T7:", 3) == 0) { 1666fcf3ce44SJohn Forte bzero(model->pt_7, sizeof (model->pt_7)); 1667fcf3ce44SJohn Forte types += 3; 1668fcf3ce44SJohn Forte 1669fcf3ce44SJohn Forte i = 0; 1670fcf3ce44SJohn Forte while (*types && *types != 'T') { 1671fcf3ce44SJohn Forte /* Null terminate the next value */ 1672fcf3ce44SJohn Forte ptr = types; 1673fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1674fcf3ce44SJohn Forte ptr++; 1675fcf3ce44SJohn Forte *ptr = 0; 1676fcf3ce44SJohn Forte 1677fcf3ce44SJohn Forte /* Save the value */ 1678fcf3ce44SJohn Forte model->pt_7[i++] = 1679fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1680fcf3ce44SJohn Forte model->pt_7[i] = 0; 1681fcf3ce44SJohn Forte 1682fcf3ce44SJohn Forte /* 1683fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1684fcf3ce44SJohn Forte * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 1685fcf3ce44SJohn Forte */ 1686fcf3ce44SJohn Forte 1687fcf3ce44SJohn Forte /* Move the str pointer */ 1688fcf3ce44SJohn Forte types = ptr + 1; 1689fcf3ce44SJohn Forte } 1690fcf3ce44SJohn Forte } else if (strncmp(types, "TA:", 3) == 0) { 1691fcf3ce44SJohn Forte bzero(model->pt_A, sizeof (model->pt_A)); 1692fcf3ce44SJohn Forte types += 3; 1693fcf3ce44SJohn Forte 1694fcf3ce44SJohn Forte i = 0; 1695fcf3ce44SJohn Forte while (*types && *types != 'T') { 1696fcf3ce44SJohn Forte /* Null terminate the next value */ 1697fcf3ce44SJohn Forte ptr = types; 1698fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1699fcf3ce44SJohn Forte ptr++; 1700fcf3ce44SJohn Forte *ptr = 0; 1701fcf3ce44SJohn Forte 1702fcf3ce44SJohn Forte /* Save the value */ 1703fcf3ce44SJohn Forte model->pt_A[i++] = 1704fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1705fcf3ce44SJohn Forte 1706fcf3ce44SJohn Forte /* 1707fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1708fcf3ce44SJohn Forte * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]); 1709fcf3ce44SJohn Forte */ 1710fcf3ce44SJohn Forte 1711fcf3ce44SJohn Forte /* Move the str pointer */ 1712fcf3ce44SJohn Forte types = ptr + 1; 1713fcf3ce44SJohn Forte } 1714fcf3ce44SJohn Forte } else if (strncmp(types, "TB:", 3) == 0) { 1715fcf3ce44SJohn Forte bzero(model->pt_B, sizeof (model->pt_B)); 1716fcf3ce44SJohn Forte types += 3; 1717fcf3ce44SJohn Forte 1718fcf3ce44SJohn Forte i = 0; 1719fcf3ce44SJohn Forte while (*types && *types != 'T') { 1720fcf3ce44SJohn Forte /* Null terminate the next value */ 1721fcf3ce44SJohn Forte ptr = types; 1722fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1723fcf3ce44SJohn Forte ptr++; 1724fcf3ce44SJohn Forte *ptr = 0; 1725fcf3ce44SJohn Forte 1726fcf3ce44SJohn Forte /* Save the value */ 1727fcf3ce44SJohn Forte model->pt_B[i++] = 1728fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1729fcf3ce44SJohn Forte 1730fcf3ce44SJohn Forte /* 1731fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1732fcf3ce44SJohn Forte * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 1733fcf3ce44SJohn Forte */ 1734fcf3ce44SJohn Forte 1735fcf3ce44SJohn Forte /* Move the str pointer */ 1736fcf3ce44SJohn Forte types = ptr + 1; 1737fcf3ce44SJohn Forte } 1738fcf3ce44SJohn Forte } else if (strncmp(types, "TFF:", 4) == 0) { 1739fcf3ce44SJohn Forte bzero(model->pt_FF, sizeof (model->pt_FF)); 1740fcf3ce44SJohn Forte types += 4; 1741fcf3ce44SJohn Forte 1742fcf3ce44SJohn Forte i = 0; 1743fcf3ce44SJohn Forte while (*types && *types != 'T') { 1744fcf3ce44SJohn Forte /* Null terminate the next value */ 1745fcf3ce44SJohn Forte ptr = types; 1746fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1747fcf3ce44SJohn Forte ptr++; 1748fcf3ce44SJohn Forte *ptr = 0; 1749fcf3ce44SJohn Forte 1750fcf3ce44SJohn Forte /* Save the value */ 1751fcf3ce44SJohn Forte model->pt_FF[i++] = 1752fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1753fcf3ce44SJohn Forte 1754fcf3ce44SJohn Forte /* 1755fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1756fcf3ce44SJohn Forte * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 1757fcf3ce44SJohn Forte */ 1758fcf3ce44SJohn Forte 1759291a2b48SSukumar Swaminathan /* Move the str pointer */ 1760291a2b48SSukumar Swaminathan types = ptr + 1; 1761291a2b48SSukumar Swaminathan } 1762291a2b48SSukumar Swaminathan } else if (strncmp(types, "T20:", 4) == 0) { 1763291a2b48SSukumar Swaminathan bzero(model->pt_20, sizeof (model->pt_20)); 1764291a2b48SSukumar Swaminathan types += 4; 1765291a2b48SSukumar Swaminathan 1766291a2b48SSukumar Swaminathan i = 0; 1767291a2b48SSukumar Swaminathan while (*types && *types != 'T') { 1768291a2b48SSukumar Swaminathan /* Null terminate the next value */ 1769291a2b48SSukumar Swaminathan ptr = types; 1770291a2b48SSukumar Swaminathan while (*ptr && (*ptr != ',')) 1771291a2b48SSukumar Swaminathan ptr++; 1772291a2b48SSukumar Swaminathan *ptr = 0; 1773291a2b48SSukumar Swaminathan 1774291a2b48SSukumar Swaminathan /* Save the value */ 1775291a2b48SSukumar Swaminathan model->pt_20[i++] = 1776291a2b48SSukumar Swaminathan (uint8_t)emlxs_strtol(types, 16); 1777291a2b48SSukumar Swaminathan model->pt_20[i] = 0; 1778291a2b48SSukumar Swaminathan 1779291a2b48SSukumar Swaminathan /* 1780291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1781291a2b48SSukumar Swaminathan * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]); 1782291a2b48SSukumar Swaminathan */ 1783291a2b48SSukumar Swaminathan 1784fcf3ce44SJohn Forte /* Move the str pointer */ 1785fcf3ce44SJohn Forte types = ptr + 1; 1786fcf3ce44SJohn Forte } 1787fcf3ce44SJohn Forte } else { 1788fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1789fcf3ce44SJohn Forte "Unknown prog type string = %s", types); 1790fcf3ce44SJohn Forte break; 1791fcf3ce44SJohn Forte } 1792fcf3ce44SJohn Forte } 1793fcf3ce44SJohn Forte 1794fcf3ce44SJohn Forte return; 1795fcf3ce44SJohn Forte 179682527734SSukumar Swaminathan } /* emlxs_parse_prog_types() */ 1797fcf3ce44SJohn Forte 1798fcf3ce44SJohn Forte 179982527734SSukumar Swaminathan extern void 18008f23e9faSHans Rosenfeld emlxs_build_prog_types(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 1801fcf3ce44SJohn Forte { 1802fcf3ce44SJohn Forte uint32_t i; 1803fcf3ce44SJohn Forte uint32_t found = 0; 1804fcf3ce44SJohn Forte char buffer[256]; 1805fcf3ce44SJohn Forte 18068f23e9faSHans Rosenfeld bzero(vpd->prog_types, sizeof (vpd->prog_types)); 1807fcf3ce44SJohn Forte 1808fcf3ce44SJohn Forte /* Rebuild the prog type string */ 1809fcf3ce44SJohn Forte if (hba->model_info.pt_2[0]) { 18108f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T2:", 18118f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1812fcf3ce44SJohn Forte found = 1; 1813fcf3ce44SJohn Forte 1814fcf3ce44SJohn Forte i = 0; 18158f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_2[i])) { 18168f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18178f23e9faSHans Rosenfeld hba->model_info.pt_2[i]); 18188f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18198f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1820fcf3ce44SJohn Forte i++; 1821fcf3ce44SJohn Forte } 1822fcf3ce44SJohn Forte } 1823291a2b48SSukumar Swaminathan 1824fcf3ce44SJohn Forte if (hba->model_info.pt_3[0]) { 18258f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T3:", 18268f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1827fcf3ce44SJohn Forte found = 1; 1828fcf3ce44SJohn Forte 1829fcf3ce44SJohn Forte i = 0; 18308f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_3[i])) { 18318f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18328f23e9faSHans Rosenfeld hba->model_info.pt_3[i]); 18338f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18348f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1835fcf3ce44SJohn Forte i++; 1836fcf3ce44SJohn Forte 1837fcf3ce44SJohn Forte } 1838fcf3ce44SJohn Forte } 1839291a2b48SSukumar Swaminathan 1840fcf3ce44SJohn Forte if (hba->model_info.pt_6[0]) { 18418f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T6:", 18428f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1843fcf3ce44SJohn Forte found = 1; 1844fcf3ce44SJohn Forte 1845fcf3ce44SJohn Forte i = 0; 18468f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_6[i])) { 18478f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18488f23e9faSHans Rosenfeld hba->model_info.pt_6[i]); 18498f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18508f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1851fcf3ce44SJohn Forte i++; 1852fcf3ce44SJohn Forte } 1853fcf3ce44SJohn Forte } 1854291a2b48SSukumar Swaminathan 1855fcf3ce44SJohn Forte if (hba->model_info.pt_7[0]) { 18568f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T7:", 18578f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1858fcf3ce44SJohn Forte found = 1; 1859fcf3ce44SJohn Forte 1860fcf3ce44SJohn Forte i = 0; 18618f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_7[i])) { 18628f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18638f23e9faSHans Rosenfeld hba->model_info.pt_7[i]); 18648f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18658f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1866fcf3ce44SJohn Forte i++; 1867fcf3ce44SJohn Forte } 1868fcf3ce44SJohn Forte } 1869291a2b48SSukumar Swaminathan 1870fcf3ce44SJohn Forte if (hba->model_info.pt_A[0]) { 18718f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TA:", 18728f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1873fcf3ce44SJohn Forte found = 1; 1874fcf3ce44SJohn Forte 1875fcf3ce44SJohn Forte i = 0; 18768f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_A[i])) { 18778f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18788f23e9faSHans Rosenfeld hba->model_info.pt_A[i]); 18798f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18808f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1881fcf3ce44SJohn Forte i++; 1882fcf3ce44SJohn Forte } 1883fcf3ce44SJohn Forte } 1884291a2b48SSukumar Swaminathan 1885291a2b48SSukumar Swaminathan 1886fcf3ce44SJohn Forte if (hba->model_info.pt_B[0]) { 18878f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TB:", 18888f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1889fcf3ce44SJohn Forte found = 1; 1890fcf3ce44SJohn Forte 1891fcf3ce44SJohn Forte i = 0; 18928f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_B[i])) { 18938f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 18948f23e9faSHans Rosenfeld hba->model_info.pt_B[i]); 18958f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 18968f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1897fcf3ce44SJohn Forte i++; 1898fcf3ce44SJohn Forte } 1899fcf3ce44SJohn Forte } 1900291a2b48SSukumar Swaminathan 1901291a2b48SSukumar Swaminathan if (hba->model_info.pt_20[0]) { 19028f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T20:", 19038f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1904291a2b48SSukumar Swaminathan found = 1; 1905291a2b48SSukumar Swaminathan 1906291a2b48SSukumar Swaminathan i = 0; 19078f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_20[i])) { 19088f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 19098f23e9faSHans Rosenfeld hba->model_info.pt_20[i]); 19108f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 19118f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1912291a2b48SSukumar Swaminathan i++; 1913291a2b48SSukumar Swaminathan } 1914291a2b48SSukumar Swaminathan } 1915291a2b48SSukumar Swaminathan 1916fcf3ce44SJohn Forte if (hba->model_info.pt_FF[0]) { 19178f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TFF:", 19188f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1919fcf3ce44SJohn Forte found = 1; 1920fcf3ce44SJohn Forte 1921fcf3ce44SJohn Forte i = 0; 19228f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_FF[i])) { 19238f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,", 19248f23e9faSHans Rosenfeld hba->model_info.pt_FF[i]); 19258f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer, 19268f23e9faSHans Rosenfeld sizeof (vpd->prog_types)); 1927fcf3ce44SJohn Forte i++; 1928fcf3ce44SJohn Forte } 1929fcf3ce44SJohn Forte } 1930291a2b48SSukumar Swaminathan 1931fcf3ce44SJohn Forte if (found) { 1932fcf3ce44SJohn Forte /* Terminate at the last comma in string */ 19338f23e9faSHans Rosenfeld vpd->prog_types[(strlen(vpd->prog_types) - 1)] = 0; 1934fcf3ce44SJohn Forte } 1935291a2b48SSukumar Swaminathan 1936fcf3ce44SJohn Forte return; 1937fcf3ce44SJohn Forte 193882527734SSukumar Swaminathan } /* emlxs_build_prog_types() */ 1939fcf3ce44SJohn Forte 1940fcf3ce44SJohn Forte 1941fcf3ce44SJohn Forte extern uint32_t 1942fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba) 1943fcf3ce44SJohn Forte { 1944fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1945fcf3ce44SJohn Forte uint32_t pci_id; 1946fcf3ce44SJohn Forte uint32_t cache_line; 1947fcf3ce44SJohn Forte uint32_t channels; 1948*a3170057SPaul Winder uint16_t vendor_id; 1949fcf3ce44SJohn Forte uint16_t device_id; 1950fcf3ce44SJohn Forte uint16_t ssdid; 1951fcf3ce44SJohn Forte uint32_t i; 1952fcf3ce44SJohn Forte uint32_t found = 0; 195382527734SSukumar Swaminathan int32_t *prop; 195482527734SSukumar Swaminathan uint32_t num_prop; 1955fcf3ce44SJohn Forte 1956fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 1957fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 1958fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 1959fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1960fcf3ce44SJohn Forte 1961*a3170057SPaul Winder hba->model_info.vendor_id = 0; 1962fcf3ce44SJohn Forte hba->model_info.device_id = 0; 1963fcf3ce44SJohn Forte 1964fcf3ce44SJohn Forte return (0); 1965fcf3ce44SJohn Forte } 1966291a2b48SSukumar Swaminathan 1967fcf3ce44SJohn Forte /* Read the PCI device id */ 1968291a2b48SSukumar Swaminathan pci_id = 1969291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 1970fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 1971*a3170057SPaul Winder vendor_id = (uint16_t)pci_id; 1972fcf3ce44SJohn Forte device_id = (uint16_t)(pci_id >> 16); 1973fcf3ce44SJohn Forte 1974fcf3ce44SJohn Forte /* Find matching adapter model */ 1975fcf3ce44SJohn Forte for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 1976*a3170057SPaul Winder if (emlxs_sbus_model[i].vendor_id == vendor_id && 1977*a3170057SPaul Winder emlxs_sbus_model[i].device_id == device_id) { 1978fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[i], &hba->model_info, 1979fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1980fcf3ce44SJohn Forte found = 1; 1981fcf3ce44SJohn Forte break; 1982fcf3ce44SJohn Forte } 1983fcf3ce44SJohn Forte } 1984fcf3ce44SJohn Forte 1985fcf3ce44SJohn Forte /* If not found then use the unknown model */ 1986fcf3ce44SJohn Forte if (!found) { 1987fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 1988fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1989fcf3ce44SJohn Forte 1990*a3170057SPaul Winder hba->model_info.vendor_id = vendor_id; 1991fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 1992fcf3ce44SJohn Forte 1993fcf3ce44SJohn Forte return (0); 1994fcf3ce44SJohn Forte } 1995fcf3ce44SJohn Forte } else { /* PCI model */ 1996291a2b48SSukumar Swaminathan 1997fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 1998fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 1999fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 2000fcf3ce44SJohn Forte 2001*a3170057SPaul Winder hba->model_info.vendor_id = 0; 2002fcf3ce44SJohn Forte hba->model_info.device_id = 0; 2003fcf3ce44SJohn Forte 2004fcf3ce44SJohn Forte return (0); 2005fcf3ce44SJohn Forte } 2006291a2b48SSukumar Swaminathan 2007*a3170057SPaul Winder /* Read the PCI vendor and device id */ 2008*a3170057SPaul Winder vendor_id = 2009*a3170057SPaul Winder ddi_get16(hba->pci_acc_handle, 2010*a3170057SPaul Winder (uint16_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 2011*a3170057SPaul Winder 2012291a2b48SSukumar Swaminathan device_id = 2013291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 2014fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 2015fcf3ce44SJohn Forte 2016fcf3ce44SJohn Forte /* Read the PCI Subsystem id */ 2017291a2b48SSukumar Swaminathan ssdid = 2018291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 2019fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 2020fcf3ce44SJohn Forte 2021fcf3ce44SJohn Forte if (ssdid == 0 || ssdid == 0xffff) { 2022fcf3ce44SJohn Forte ssdid = device_id; 2023fcf3ce44SJohn Forte } 2024291a2b48SSukumar Swaminathan 2025fcf3ce44SJohn Forte /* Read the Cache Line reg */ 2026291a2b48SSukumar Swaminathan cache_line = 2027291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 2028fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 2029fcf3ce44SJohn Forte 2030*a3170057SPaul Winder EMLXS_MSGF(EMLXS_CONTEXT, 2031*a3170057SPaul Winder &emlxs_init_debug_msg, "Device IDs: %x/%x/%x/%x", 2032*a3170057SPaul Winder vendor_id, device_id, ssdid, cache_line); 2033*a3170057SPaul Winder 2034fcf3ce44SJohn Forte /* Check for the multifunction bit being set */ 2035fcf3ce44SJohn Forte if ((cache_line & 0x00ff0000) == 0x00800000) { 20368f23e9faSHans Rosenfeld channels = EMLXS_MULTI_CHANNEL; 2037fcf3ce44SJohn Forte } else { 20388f23e9faSHans Rosenfeld channels = EMLXS_SINGLE_CHANNEL; 2039fcf3ce44SJohn Forte } 2040fcf3ce44SJohn Forte 2041fcf3ce44SJohn Forte /* If device ids are unique, then use them for search */ 2042fcf3ce44SJohn Forte if (device_id != ssdid) { 20438f23e9faSHans Rosenfeld /* 20448f23e9faSHans Rosenfeld * Find matching adapter model using 2045*a3170057SPaul Winder * vendor_id, device_id, ssdid, and channels 20468f23e9faSHans Rosenfeld */ 20478f23e9faSHans Rosenfeld for (i = 1; i < emlxs_pci_model_count; i++) { 2048*a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id && 2049*a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id && 20508f23e9faSHans Rosenfeld emlxs_pci_model[i].ssdid == ssdid && 20518f23e9faSHans Rosenfeld emlxs_pci_model[i].channels == 20528f23e9faSHans Rosenfeld channels) { 20538f23e9faSHans Rosenfeld bcopy(&emlxs_pci_model[i], 20548f23e9faSHans Rosenfeld &hba->model_info, 20558f23e9faSHans Rosenfeld sizeof (emlxs_model_t)); 20568f23e9faSHans Rosenfeld found = 1; 20578f23e9faSHans Rosenfeld break; 2058fcf3ce44SJohn Forte } 2059fcf3ce44SJohn Forte } 2060fcf3ce44SJohn Forte } 2061291a2b48SSukumar Swaminathan 2062fcf3ce44SJohn Forte /* If adapter not found, try again */ 2063fcf3ce44SJohn Forte if (!found) { 20648f23e9faSHans Rosenfeld /* 20658f23e9faSHans Rosenfeld * Find matching adapter model using 2066*a3170057SPaul Winder * vendor_id, device_id and channels 20678f23e9faSHans Rosenfeld */ 206882527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 2069*a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id && 2070*a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id && 2071fcf3ce44SJohn Forte emlxs_pci_model[i].channels == channels) { 2072fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 2073fcf3ce44SJohn Forte &hba->model_info, 2074fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 2075fcf3ce44SJohn Forte found = 1; 2076fcf3ce44SJohn Forte break; 2077fcf3ce44SJohn Forte } 2078fcf3ce44SJohn Forte } 2079fcf3ce44SJohn Forte } 2080291a2b48SSukumar Swaminathan 2081fcf3ce44SJohn Forte /* If adapter not found, try one last time */ 2082fcf3ce44SJohn Forte if (!found) { 20838f23e9faSHans Rosenfeld /* 20848f23e9faSHans Rosenfeld * Find matching adapter model using 2085*a3170057SPaul Winder * vendor_id and device_id only 20868f23e9faSHans Rosenfeld */ 208782527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 2088*a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id && 2089*a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id) { 2090fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 2091fcf3ce44SJohn Forte &hba->model_info, 2092fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 2093fcf3ce44SJohn Forte found = 1; 2094fcf3ce44SJohn Forte break; 2095fcf3ce44SJohn Forte } 2096fcf3ce44SJohn Forte } 2097fcf3ce44SJohn Forte } 2098291a2b48SSukumar Swaminathan 2099fcf3ce44SJohn Forte /* If not found, set adapter to unknown */ 2100fcf3ce44SJohn Forte if (!found) { 2101fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 2102fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 2103fcf3ce44SJohn Forte 2104*a3170057SPaul Winder hba->model_info.vendor_id = vendor_id; 2105fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 2106fcf3ce44SJohn Forte hba->model_info.ssdid = ssdid; 2107fcf3ce44SJohn Forte 2108fcf3ce44SJohn Forte return (0); 2109fcf3ce44SJohn Forte } 2110fcf3ce44SJohn Forte 2111fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT 2112fcf3ce44SJohn Forte /* 2113291a2b48SSukumar Swaminathan * This will disable MSI support for Saturn adapter's 2114291a2b48SSukumar Swaminathan * due to a PCI bus issue 2115fcf3ce44SJohn Forte */ 2116fcf3ce44SJohn Forte if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 2117fcf3ce44SJohn Forte hba->model_info.flags &= 2118fcf3ce44SJohn Forte ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 2119fcf3ce44SJohn Forte } 2120291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */ 2121fcf3ce44SJohn Forte 2122a9800bebSGarrett D'Amore /* Scan the PCI capabilities */ 2123a9800bebSGarrett D'Amore emlxs_pci_cap_offsets(hba); 2124fcf3ce44SJohn Forte 2125fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 2126fcf3ce44SJohn Forte /* Verify MSI support */ 2127a9800bebSGarrett D'Amore if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) && 2128a9800bebSGarrett D'Amore !hba->pci_cap_offset[PCI_CAP_ID_MSI]) { 2129a9800bebSGarrett D'Amore hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 2130fcf3ce44SJohn Forte } 2131291a2b48SSukumar Swaminathan 2132fcf3ce44SJohn Forte /* Verify MSI-X support */ 2133a9800bebSGarrett D'Amore if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) && 2134a9800bebSGarrett D'Amore !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) { 2135a9800bebSGarrett D'Amore hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED; 2136fcf3ce44SJohn Forte } 2137291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 21388f23e9faSHans Rosenfeld 21398f23e9faSHans Rosenfeld /* Set the sli_intf value */ 21408f23e9faSHans Rosenfeld if (hba->pci_cap_offset[PCI_CAP_ID_VS]) { 21418f23e9faSHans Rosenfeld /* Save the SLI_INTF register, this contains */ 21428f23e9faSHans Rosenfeld /* information about the BAR register layout */ 21438f23e9faSHans Rosenfeld /* and other HBA information. */ 21448f23e9faSHans Rosenfeld hba->sli_intf = 21458f23e9faSHans Rosenfeld ddi_get32(hba->pci_acc_handle, 21468f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr + 21478f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS] + 21488f23e9faSHans Rosenfeld PCI_VS_SLI_INTF_OFFSET)); 21498f23e9faSHans Rosenfeld 21508f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 21518f23e9faSHans Rosenfeld &emlxs_init_debug_msg, "PCI_CAP_ID_VS: " 21528f23e9faSHans Rosenfeld "SLI_INTF:%08x", 21538f23e9faSHans Rosenfeld hba->sli_intf); 21548f23e9faSHans Rosenfeld 21558f23e9faSHans Rosenfeld /* Check validity */ 21568f23e9faSHans Rosenfeld if ((hba->sli_intf & SLI_INTF_VALID_MASK) != 21578f23e9faSHans Rosenfeld SLI_INTF_VALID) { 21588f23e9faSHans Rosenfeld hba->sli_intf = 0; 21598f23e9faSHans Rosenfeld } 21608f23e9faSHans Rosenfeld } 2161291a2b48SSukumar Swaminathan } 2162fcf3ce44SJohn Forte 216382527734SSukumar Swaminathan if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0, 216482527734SSukumar Swaminathan "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) { 216582527734SSukumar Swaminathan /* Parse the property for PCI function, device and bus no. */ 216682527734SSukumar Swaminathan hba->pci_function_number = 216782527734SSukumar Swaminathan (uint8_t)((prop[0] & 0x00000700) >> 8); 21688f23e9faSHans Rosenfeld hba->pci_device_number = 21698f23e9faSHans Rosenfeld (uint8_t)((prop[0] & 0x0000f800) >> 11); 217082527734SSukumar Swaminathan hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16); 217182527734SSukumar Swaminathan ddi_prop_free((void *)prop); 217282527734SSukumar Swaminathan } 217382527734SSukumar Swaminathan 21748f23e9faSHans Rosenfeld switch (hba->sli_intf & SLI_INTF_SLI_REV_MASK) { 21758f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_NONE: /* Legacy support */ 21768f23e9faSHans Rosenfeld if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 21778f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli4_api; 21788f23e9faSHans Rosenfeld } else { 21798f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli3_api; 21808f23e9faSHans Rosenfeld } 21818f23e9faSHans Rosenfeld break; 21828f23e9faSHans Rosenfeld 21838f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_3: 21848f23e9faSHans Rosenfeld if (!(hba->model_info.sli_mask & EMLXS_SLI3_MASK)) { 21858f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 21868f23e9faSHans Rosenfeld &emlxs_init_failed_msg, 21878f23e9faSHans Rosenfeld "Adapter does not support SLI3 interface. " 21888f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x", 21898f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask); 21908f23e9faSHans Rosenfeld return (0); 21918f23e9faSHans Rosenfeld } 219282527734SSukumar Swaminathan hba->sli_api = emlxs_sli3_api; 21938f23e9faSHans Rosenfeld break; 21948f23e9faSHans Rosenfeld 21958f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_4: 21968f23e9faSHans Rosenfeld if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) { 21978f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 21988f23e9faSHans Rosenfeld &emlxs_init_failed_msg, 21998f23e9faSHans Rosenfeld "Adapter does not support SLI4 interface. " 22008f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x", 22018f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask); 22028f23e9faSHans Rosenfeld return (0); 22038f23e9faSHans Rosenfeld } 22048f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli4_api; 22058f23e9faSHans Rosenfeld break; 22068f23e9faSHans Rosenfeld 22078f23e9faSHans Rosenfeld default: 22088f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 22098f23e9faSHans Rosenfeld &emlxs_init_failed_msg, 22108f23e9faSHans Rosenfeld "Invalid SLI interface specified. " 22118f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x", 22128f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask); 22138f23e9faSHans Rosenfeld return (0); 221482527734SSukumar Swaminathan } 221582527734SSukumar Swaminathan 22164baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 22174baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 22184baa2c25SSukumar Swaminathan != DDI_FM_OK) { 22194baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 22204baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 22214baa2c25SSukumar Swaminathan return (0); 22224baa2c25SSukumar Swaminathan } 22234baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 22244baa2c25SSukumar Swaminathan 2225fcf3ce44SJohn Forte return (1); 2226fcf3ce44SJohn Forte 222782527734SSukumar Swaminathan } /* emlxs_init_adapter_info() */ 2228fcf3ce44SJohn Forte 2229fcf3ce44SJohn Forte 2230291a2b48SSukumar Swaminathan /* ARGSUSED */ 2231291a2b48SSukumar Swaminathan static void 223282527734SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2233fcf3ce44SJohn Forte { 2234291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2235291a2b48SSukumar Swaminathan IOCB *iocb; 2236291a2b48SSukumar Swaminathan uint32_t *w; 2237291a2b48SSukumar Swaminathan int i, j; 2238fcf3ce44SJohn Forte 2239291a2b48SSukumar Swaminathan iocb = &iocbq->iocb; 2240fcf3ce44SJohn Forte 224182527734SSukumar Swaminathan if (iocb->ULPSTATUS != 0) { 2242291a2b48SSukumar Swaminathan return; 2243fcf3ce44SJohn Forte } 2244fcf3ce44SJohn Forte 2245291a2b48SSukumar Swaminathan switch (iocb->un.astat.EventCode) { 2246291a2b48SSukumar Swaminathan case 0x0100: /* Temp Warning */ 2247291a2b48SSukumar Swaminathan 2248291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 2249291a2b48SSukumar Swaminathan "Adapter is very hot (%d �C). Take corrective action.", 225082527734SSukumar Swaminathan iocb->ULPCONTEXT); 225182527734SSukumar Swaminathan 225282527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT; 225382527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT); 2254fcf3ce44SJohn Forte 2255fcf3ce44SJohn Forte 2256291a2b48SSukumar Swaminathan break; 2257fcf3ce44SJohn Forte 2258fcf3ce44SJohn Forte 2259291a2b48SSukumar Swaminathan case 0x0101: /* Temp Safe */ 2260fcf3ce44SJohn Forte 2261291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 2262291a2b48SSukumar Swaminathan "Adapter temperature now safe (%d �C).", 226382527734SSukumar Swaminathan iocb->ULPCONTEXT); 2264fcf3ce44SJohn Forte 226582527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT; 226682527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT); 2267fcf3ce44SJohn Forte 2268291a2b48SSukumar Swaminathan break; 2269fcf3ce44SJohn Forte 2270291a2b48SSukumar Swaminathan default: 2271fcf3ce44SJohn Forte 2272291a2b48SSukumar Swaminathan w = (uint32_t *)iocb; 2273291a2b48SSukumar Swaminathan for (i = 0, j = 0; i < 8; i++, j += 2) { 2274291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg, 2275291a2b48SSukumar Swaminathan "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1, 2276291a2b48SSukumar Swaminathan w[j + 1]); 2277291a2b48SSukumar Swaminathan } 2278fcf3ce44SJohn Forte 2279291a2b48SSukumar Swaminathan emlxs_log_async_event(port, iocb); 2280fcf3ce44SJohn Forte } 2281fcf3ce44SJohn Forte 2282fcf3ce44SJohn Forte return; 2283fcf3ce44SJohn Forte 228482527734SSukumar Swaminathan } /* emlxs_handle_async_event() */ 2285fcf3ce44SJohn Forte 2286fcf3ce44SJohn Forte 2287bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2288291a2b48SSukumar Swaminathan extern void 2289bb63f56eSSukumar Swaminathan emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2290fcf3ce44SJohn Forte { 2291291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2292fcf3ce44SJohn Forte 2293291a2b48SSukumar Swaminathan /* Attempt a link reset to recover */ 2294291a2b48SSukumar Swaminathan (void) emlxs_reset(port, FC_FCA_LINK_RESET); 2295fcf3ce44SJohn Forte 2296bb63f56eSSukumar Swaminathan return; 2297fcf3ce44SJohn Forte 229882527734SSukumar Swaminathan } /* emlxs_reset_link_thread() */ 2299fcf3ce44SJohn Forte 2300fcf3ce44SJohn Forte 2301bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2302fcf3ce44SJohn Forte extern void 2303bb63f56eSSukumar Swaminathan emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2304fcf3ce44SJohn Forte { 2305fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2306fcf3ce44SJohn Forte 2307fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 2308fcf3ce44SJohn Forte 2309fcf3ce44SJohn Forte /* Attempt a full hardware reset to recover */ 2310fcf3ce44SJohn Forte if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 231182527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 2312fcf3ce44SJohn Forte 231382527734SSukumar Swaminathan emlxs_shutdown_thread(hba, arg1, arg2); 2314fcf3ce44SJohn Forte } 2315fcf3ce44SJohn Forte 2316bb63f56eSSukumar Swaminathan return; 2317291a2b48SSukumar Swaminathan 231882527734SSukumar Swaminathan } /* emlxs_restart_thread() */ 2319fcf3ce44SJohn Forte 2320fcf3ce44SJohn Forte 2321bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2322fcf3ce44SJohn Forte extern void 2323bb63f56eSSukumar Swaminathan emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2324fcf3ce44SJohn Forte { 2325fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2326fcf3ce44SJohn Forte 2327fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 2328fcf3ce44SJohn Forte if (hba->flag & FC_SHUTDOWN) { 2329fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2330bb63f56eSSukumar Swaminathan return; 2331fcf3ce44SJohn Forte } 2332fcf3ce44SJohn Forte hba->flag |= FC_SHUTDOWN; 2333fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2334fcf3ce44SJohn Forte 2335291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 2336291a2b48SSukumar Swaminathan "Shutting down..."); 2337fcf3ce44SJohn Forte 2338fcf3ce44SJohn Forte /* Take adapter offline and leave it there */ 23398f23e9faSHans Rosenfeld (void) emlxs_offline(hba, 0); 2340fcf3ce44SJohn Forte 234182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 234282527734SSukumar Swaminathan /* 234382527734SSukumar Swaminathan * Dump is not defined for SLI4, so just 234482527734SSukumar Swaminathan * reset the HBA for now. 234582527734SSukumar Swaminathan */ 234682527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 234782527734SSukumar Swaminathan 234882527734SSukumar Swaminathan } else { 234982527734SSukumar Swaminathan if (hba->flag & FC_OVERTEMP_EVENT) { 235082527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x01, 235182527734SSukumar Swaminathan hba->temperature); 235282527734SSukumar Swaminathan } else { 235382527734SSukumar Swaminathan emlxs_log_dump_event(port, NULL, 0); 235482527734SSukumar Swaminathan } 235582527734SSukumar Swaminathan } 2356fcf3ce44SJohn Forte 2357fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 2358fcf3ce44SJohn Forte 2359bb63f56eSSukumar Swaminathan return; 2360fcf3ce44SJohn Forte 236182527734SSukumar Swaminathan } /* emlxs_shutdown_thread() */ 2362fcf3ce44SJohn Forte 2363fcf3ce44SJohn Forte 2364fcf3ce44SJohn Forte /* ARGSUSED */ 2365fcf3ce44SJohn Forte extern void 236682527734SSukumar Swaminathan emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2) 2367fcf3ce44SJohn Forte { 2368fcf3ce44SJohn Forte IOCBQ *iocbq; 2369fcf3ce44SJohn Forte IOCBQ *rsp_head; 2370fcf3ce44SJohn Forte 2371fcf3ce44SJohn Forte /* 2372291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 23738f23e9faSHans Rosenfeld * "proc_channel: channel=%d", cp->channelno); 2374fcf3ce44SJohn Forte */ 2375fcf3ce44SJohn Forte 237682527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 2377fcf3ce44SJohn Forte 237882527734SSukumar Swaminathan while ((rsp_head = cp->rsp_head) != NULL) { 237982527734SSukumar Swaminathan cp->rsp_head = NULL; 238082527734SSukumar Swaminathan cp->rsp_tail = NULL; 2381fcf3ce44SJohn Forte 238282527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 2383fcf3ce44SJohn Forte 2384fcf3ce44SJohn Forte while ((iocbq = rsp_head) != NULL) { 2385fcf3ce44SJohn Forte rsp_head = (IOCBQ *) iocbq->next; 2386fcf3ce44SJohn Forte 238782527734SSukumar Swaminathan emlxs_proc_channel_event(hba, cp, iocbq); 2388fcf3ce44SJohn Forte } 2389fcf3ce44SJohn Forte 239082527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 2391fcf3ce44SJohn Forte } 2392fcf3ce44SJohn Forte 239382527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 2394fcf3ce44SJohn Forte 239582527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0); 2396fcf3ce44SJohn Forte 2397fcf3ce44SJohn Forte return; 2398fcf3ce44SJohn Forte 239982527734SSukumar Swaminathan } /* emlxs_proc_channel() */ 2400fcf3ce44SJohn Forte 2401fcf3ce44SJohn Forte 2402fcf3ce44SJohn Forte /* 2403291a2b48SSukumar Swaminathan * Called from SLI ring event routines to process a rsp ring IOCB. 2404fcf3ce44SJohn Forte */ 2405291a2b48SSukumar Swaminathan void 240682527734SSukumar Swaminathan emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2407fcf3ce44SJohn Forte { 2408fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2409fcf3ce44SJohn Forte char buffer[MAX_MSG_DATA + 1]; 2410fcf3ce44SJohn Forte IOCB *iocb; 241182527734SSukumar Swaminathan emlxs_buf_t *sbp; 24128f23e9faSHans Rosenfeld fc_packet_t *pkt; 2413fcf3ce44SJohn Forte 2414fcf3ce44SJohn Forte iocb = &iocbq->iocb; 2415fcf3ce44SJohn Forte 241682527734SSukumar Swaminathan #ifdef DEBUG_CMPL_IOCB 2417a9800bebSGarrett D'Amore emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0); 241882527734SSukumar Swaminathan #endif 241982527734SSukumar Swaminathan 242082527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 242182527734SSukumar Swaminathan if (sbp) { 242282527734SSukumar Swaminathan if (!(sbp->pkt_flags & PACKET_VALID) || 242382527734SSukumar Swaminathan (sbp->pkt_flags & (PACKET_ULP_OWNED | 242482527734SSukumar Swaminathan PACKET_IN_COMPLETION))) { 242582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 242682527734SSukumar Swaminathan "Duplicate: iocb=%p cmd=%x status=%x " 24278f23e9faSHans Rosenfeld "error=%x iotag=%d context=%x info=%x", 242882527734SSukumar Swaminathan iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 242982527734SSukumar Swaminathan iocbq->iocb.ULPSTATUS, 243082527734SSukumar Swaminathan (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 243182527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPIOTAG, 243282527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPCONTEXT, 243382527734SSukumar Swaminathan (uint8_t)iocbq->iocb.ULPRSVDBYTE); 243482527734SSukumar Swaminathan 243582527734SSukumar Swaminathan /* Drop this IO immediately */ 243682527734SSukumar Swaminathan return; 243782527734SSukumar Swaminathan } 243882527734SSukumar Swaminathan 243982527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TIMEOUT) { 244082527734SSukumar Swaminathan /* 244182527734SSukumar Swaminathan * If the packet is tagged for timeout then set the 244282527734SSukumar Swaminathan * return codes appropriately 244382527734SSukumar Swaminathan */ 244482527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 244582527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT; 244682527734SSukumar Swaminathan } else if (sbp->pkt_flags & 244782527734SSukumar Swaminathan (PACKET_IN_FLUSH | PACKET_IN_ABORT)) { 244882527734SSukumar Swaminathan /* 244982527734SSukumar Swaminathan * If the packet is tagged for abort then set the 245082527734SSukumar Swaminathan * return codes appropriately 245182527734SSukumar Swaminathan */ 245282527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 245382527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError = 245482527734SSukumar Swaminathan IOERR_ABORT_REQUESTED; 245582527734SSukumar Swaminathan } 245682527734SSukumar Swaminathan } 245782527734SSukumar Swaminathan 2458fcf3ce44SJohn Forte /* Check for IOCB local error */ 245982527734SSukumar Swaminathan if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) { 2460fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 2461291a2b48SSukumar Swaminathan "Local reject. ringno=%d iocb=%p cmd=%x " 24628f23e9faSHans Rosenfeld "iotag=%d context=%x info=%x error=%x", 246382527734SSukumar Swaminathan cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND, 246482527734SSukumar Swaminathan (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT, 246582527734SSukumar Swaminathan (uint8_t)iocb->ULPRSVDBYTE, 2466fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 2467fcf3ce44SJohn Forte } 2468291a2b48SSukumar Swaminathan 246982527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 2470fcf3ce44SJohn Forte /* RING 0 FCP commands */ 2471fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR: 2472fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX: 2473fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR: 2474fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX: 2475fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR: 2476fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX: 2477fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR: 2478fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX: 2479fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR: 2480fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX: 2481fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR: 2482fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX: 248382527734SSukumar Swaminathan emlxs_handle_fcp_event(hba, cp, iocbq); 2484fcf3ce44SJohn Forte break; 2485fcf3ce44SJohn Forte 2486fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 2487291a2b48SSukumar Swaminathan case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 2488fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 2489fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 2490fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 2491291a2b48SSukumar Swaminathan case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 2492291a2b48SSukumar Swaminathan case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 24938f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 24948f23e9faSHans Rosenfeld (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq); 24958f23e9faSHans Rosenfeld } 2496fcf3ce44SJohn Forte break; 2497291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2498fcf3ce44SJohn Forte 2499fcf3ce44SJohn Forte /* RING 1 IP commands */ 2500fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN: 2501fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX: 2502fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN: 2503fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX: 250482527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq); 2505fcf3ce44SJohn Forte break; 2506fcf3ce44SJohn Forte 2507fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX: 2508fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR: 2509fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX: 2510fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR: 2511fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2512fcf3ce44SJohn Forte case FC_TYPE_IS8802_SNAP: 251382527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq); 2514fcf3ce44SJohn Forte break; 2515fcf3ce44SJohn Forte 2516fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 251782527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq); 2518fcf3ce44SJohn Forte break; 2519fcf3ce44SJohn Forte 2520fcf3ce44SJohn Forte default: 2521fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 25228f23e9faSHans Rosenfeld "cmd=%x type=%x status=%x iotag=%d context=%x ", 252382527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 252482527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, 252582527734SSukumar Swaminathan iocb->ULPCONTEXT); 2526fcf3ce44SJohn Forte } 2527fcf3ce44SJohn Forte break; 2528fcf3ce44SJohn Forte 2529fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE_CX: 2530fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE64_CX: 2531fcf3ce44SJohn Forte case CMD_RCV_SEQ64_CX: 2532fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 2533fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 2534291a2b48SSukumar Swaminathan case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 253582527734SSukumar Swaminathan if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 253682527734SSukumar Swaminathan (void) emlxs_handle_rcv_seq(hba, cp, iocbq); 253782527734SSukumar Swaminathan } 2538fcf3ce44SJohn Forte break; 2539fcf3ce44SJohn Forte 2540fcf3ce44SJohn Forte case CMD_RCV_SEQ_LIST64_CX: 254182527734SSukumar Swaminathan (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq); 2542fcf3ce44SJohn Forte break; 2543fcf3ce44SJohn Forte 2544fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR: 2545fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX: 254682527734SSukumar Swaminathan (void) emlxs_handle_create_xri(hba, cp, iocbq); 2547fcf3ce44SJohn Forte break; 2548fcf3ce44SJohn Forte 2549fcf3ce44SJohn Forte /* RING 2 ELS commands */ 2550fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR: 2551fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX: 2552fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX: 2553fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR: 2554fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX: 2555fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX: 255682527734SSukumar Swaminathan (void) emlxs_els_handle_event(hba, cp, iocbq); 2557fcf3ce44SJohn Forte break; 2558fcf3ce44SJohn Forte 2559fcf3ce44SJohn Forte /* RING 3 CT commands */ 2560fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR: 2561fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX: 2562fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2563fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 2564fcf3ce44SJohn Forte case EMLXS_MENLO_TYPE: 256582527734SSukumar Swaminathan (void) emlxs_menlo_handle_event(hba, cp, iocbq); 2566fcf3ce44SJohn Forte break; 2567291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 2568fcf3ce44SJohn Forte 2569fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 257082527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq); 2571fcf3ce44SJohn Forte break; 2572fcf3ce44SJohn Forte 2573fcf3ce44SJohn Forte default: 2574fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 25758f23e9faSHans Rosenfeld "cmd=%x type=%x status=%x iotag=%d context=%x ", 257682527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 257782527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, 257882527734SSukumar Swaminathan iocb->ULPCONTEXT); 2579fcf3ce44SJohn Forte } 2580fcf3ce44SJohn Forte break; 2581fcf3ce44SJohn Forte 2582fcf3ce44SJohn Forte case CMD_ABORT_XRI_CN: /* Abort fcp command */ 2583fcf3ce44SJohn Forte 2584fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 25858f23e9faSHans Rosenfeld "ABORT_XRI_CN: rpi=%d iotag=%d status=%x parm=%x", 2586fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 258782527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2588291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2589fcf3ce44SJohn Forte 2590291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 25918f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 259282527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2593291a2b48SSukumar Swaminathan } 2594291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2595fcf3ce44SJohn Forte break; 2596fcf3ce44SJohn Forte 2597fcf3ce44SJohn Forte case CMD_ABORT_XRI_CX: /* Abort command */ 2598fcf3ce44SJohn Forte 2599fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 26008f23e9faSHans Rosenfeld "ABORT_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p", 2601fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 260282527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2603291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 2604fcf3ce44SJohn Forte 2605291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 26068f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 260782527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2608291a2b48SSukumar Swaminathan } 2609291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2610fcf3ce44SJohn Forte break; 2611fcf3ce44SJohn Forte 2612fcf3ce44SJohn Forte case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 2613fcf3ce44SJohn Forte 2614fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 26158f23e9faSHans Rosenfeld "XRI_ABORTED_CX: rpi=%d iotag=%d status=%x parm=%x", 2616fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 261782527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2618291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2619fcf3ce44SJohn Forte 2620291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 26218f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 262282527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2623291a2b48SSukumar Swaminathan } 2624291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2625fcf3ce44SJohn Forte break; 2626fcf3ce44SJohn Forte 2627fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 2628fcf3ce44SJohn Forte 2629fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 26308f23e9faSHans Rosenfeld "CLOSE_XRI_CN: rpi=%d iotag=%d status=%x parm=%x", 2631fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 263282527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2633291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2634fcf3ce44SJohn Forte 2635291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 26368f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 263782527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2638291a2b48SSukumar Swaminathan } 2639291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2640fcf3ce44SJohn Forte break; 2641fcf3ce44SJohn Forte 2642fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 2643fcf3ce44SJohn Forte 2644fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 26458f23e9faSHans Rosenfeld "CLOSE_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p", 2646fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 264782527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2648291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 2649fcf3ce44SJohn Forte 2650291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 26518f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 265282527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2653291a2b48SSukumar Swaminathan } 2654291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2655fcf3ce44SJohn Forte break; 2656fcf3ce44SJohn Forte 2657fcf3ce44SJohn Forte case CMD_ADAPTER_MSG: 2658fcf3ce44SJohn Forte /* Allows debug adapter firmware messages to print on host */ 2659fcf3ce44SJohn Forte bzero(buffer, sizeof (buffer)); 2660fcf3ce44SJohn Forte bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 2661fcf3ce44SJohn Forte 2662fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 2663fcf3ce44SJohn Forte 2664fcf3ce44SJohn Forte break; 2665fcf3ce44SJohn Forte 2666fcf3ce44SJohn Forte case CMD_QUE_RING_LIST64_CN: 2667fcf3ce44SJohn Forte case CMD_QUE_RING_BUF64_CN: 2668fcf3ce44SJohn Forte break; 2669fcf3ce44SJohn Forte 2670fcf3ce44SJohn Forte case CMD_ASYNC_STATUS: 267182527734SSukumar Swaminathan emlxs_handle_async_event(hba, cp, iocbq); 2672fcf3ce44SJohn Forte break; 2673fcf3ce44SJohn Forte 26748f23e9faSHans Rosenfeld case CMD_XMIT_BLS_RSP64_CX: 26758f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 26768f23e9faSHans Rosenfeld "CMD_XMIT_BLS_RSP64_CX: sbp = %p", sbp); 26778f23e9faSHans Rosenfeld 26788f23e9faSHans Rosenfeld /* 26798f23e9faSHans Rosenfeld * The exchange should have been already freed in the wqe_cmpl 26808f23e9faSHans Rosenfeld * so just free up the pkt here. 26818f23e9faSHans Rosenfeld */ 26828f23e9faSHans Rosenfeld pkt = PRIV2PKT(sbp); 26838f23e9faSHans Rosenfeld emlxs_pkt_free(pkt); 26848f23e9faSHans Rosenfeld break; 26858f23e9faSHans Rosenfeld 2686fcf3ce44SJohn Forte default: 26878f23e9faSHans Rosenfeld if (iocb->ULPCOMMAND == 0) { 26888f23e9faSHans Rosenfeld break; 26898f23e9faSHans Rosenfeld } 26908f23e9faSHans Rosenfeld 2691fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 26928f23e9faSHans Rosenfeld "cmd=%x status=%x iotag=%d context=%x", iocb->ULPCOMMAND, 269382527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT); 2694fcf3ce44SJohn Forte 2695fcf3ce44SJohn Forte break; 269682527734SSukumar Swaminathan } /* switch(entry->ULPCOMMAND) */ 2697fcf3ce44SJohn Forte 2698fcf3ce44SJohn Forte return; 2699fcf3ce44SJohn Forte 270082527734SSukumar Swaminathan } /* emlxs_proc_channel_event() */ 2701fcf3ce44SJohn Forte 2702fcf3ce44SJohn Forte 2703291a2b48SSukumar Swaminathan extern char * 2704291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state) 2705fcf3ce44SJohn Forte { 2706291a2b48SSukumar Swaminathan static char buffer[32]; 2707291a2b48SSukumar Swaminathan uint32_t i; 2708291a2b48SSukumar Swaminathan uint32_t count; 2709fcf3ce44SJohn Forte 2710291a2b48SSukumar Swaminathan count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 2711291a2b48SSukumar Swaminathan for (i = 0; i < count; i++) { 2712291a2b48SSukumar Swaminathan if (state == emlxs_ffstate_table[i].code) { 2713291a2b48SSukumar Swaminathan return (emlxs_ffstate_table[i].string); 2714fcf3ce44SJohn Forte } 2715fcf3ce44SJohn Forte } 2716fcf3ce44SJohn Forte 27178f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state); 2718291a2b48SSukumar Swaminathan return (buffer); 2719fcf3ce44SJohn Forte 272082527734SSukumar Swaminathan } /* emlxs_ffstate_xlate() */ 2721fcf3ce44SJohn Forte 2722fcf3ce44SJohn Forte 2723fcf3ce44SJohn Forte extern char * 2724fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno) 2725fcf3ce44SJohn Forte { 2726fcf3ce44SJohn Forte static char buffer[32]; 2727fcf3ce44SJohn Forte uint32_t i; 2728fcf3ce44SJohn Forte uint32_t count; 2729fcf3ce44SJohn Forte 2730fcf3ce44SJohn Forte count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 2731fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2732fcf3ce44SJohn Forte if (ringno == emlxs_ring_table[i].code) { 2733fcf3ce44SJohn Forte return (emlxs_ring_table[i].string); 2734fcf3ce44SJohn Forte } 2735fcf3ce44SJohn Forte } 2736fcf3ce44SJohn Forte 27378f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "ring=0x%x", ringno); 2738fcf3ce44SJohn Forte return (buffer); 2739fcf3ce44SJohn Forte 274082527734SSukumar Swaminathan } /* emlxs_ring_xlate() */ 2741fcf3ce44SJohn Forte 2742fcf3ce44SJohn Forte 2743a9800bebSGarrett D'Amore extern char * 2744a9800bebSGarrett D'Amore emlxs_pci_cap_xlate(uint32_t id) 2745a9800bebSGarrett D'Amore { 2746a9800bebSGarrett D'Amore static char buffer[32]; 2747a9800bebSGarrett D'Amore uint32_t i; 2748a9800bebSGarrett D'Amore uint32_t count; 2749a9800bebSGarrett D'Amore 2750a9800bebSGarrett D'Amore count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t); 2751a9800bebSGarrett D'Amore for (i = 0; i < count; i++) { 2752a9800bebSGarrett D'Amore if (id == emlxs_pci_cap[i].code) { 2753a9800bebSGarrett D'Amore return (emlxs_pci_cap[i].string); 2754a9800bebSGarrett D'Amore } 2755a9800bebSGarrett D'Amore } 2756a9800bebSGarrett D'Amore 27578f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "PCI_CAP_ID_%02X", id); 2758a9800bebSGarrett D'Amore return (buffer); 2759a9800bebSGarrett D'Amore 2760a9800bebSGarrett D'Amore } /* emlxs_pci_cap_xlate() */ 2761a9800bebSGarrett D'Amore 2762fcf3ce44SJohn Forte 27638f23e9faSHans Rosenfeld extern char * 27648f23e9faSHans Rosenfeld emlxs_pci_ecap_xlate(uint32_t id) 27658f23e9faSHans Rosenfeld { 27668f23e9faSHans Rosenfeld static char buffer[32]; 27678f23e9faSHans Rosenfeld uint32_t i; 27688f23e9faSHans Rosenfeld uint32_t count; 27698f23e9faSHans Rosenfeld 27708f23e9faSHans Rosenfeld count = sizeof (emlxs_pci_ecap) / sizeof (emlxs_table_t); 27718f23e9faSHans Rosenfeld for (i = 0; i < count; i++) { 27728f23e9faSHans Rosenfeld if (id == emlxs_pci_ecap[i].code) { 27738f23e9faSHans Rosenfeld return (emlxs_pci_ecap[i].string); 27748f23e9faSHans Rosenfeld } 27758f23e9faSHans Rosenfeld } 27768f23e9faSHans Rosenfeld 27778f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "PCI_EXT_CAP_ID_%02X", id); 27788f23e9faSHans Rosenfeld return (buffer); 27798f23e9faSHans Rosenfeld 27808f23e9faSHans Rosenfeld } /* emlxs_pci_ecap_xlate() */ 27818f23e9faSHans Rosenfeld 27828f23e9faSHans Rosenfeld 2783fcf3ce44SJohn Forte extern void 2784fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 2785fcf3ce44SJohn Forte { 2786fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 278782527734SSukumar Swaminathan MAILBOXQ *mbq; 2788fcf3ce44SJohn Forte MAILBOX *mb; 2789fcf3ce44SJohn Forte emlxs_config_t *cfg; 2790fcf3ce44SJohn Forte uint32_t value; 2791fcf3ce44SJohn Forte 2792fcf3ce44SJohn Forte cfg = &CFG; 2793fcf3ce44SJohn Forte 2794fcf3ce44SJohn Forte xlate: 2795fcf3ce44SJohn Forte 2796fcf3ce44SJohn Forte switch (cfg[CFG_PCI_MAX_READ].current) { 2797fcf3ce44SJohn Forte case 512: 2798fcf3ce44SJohn Forte value = 0; 2799fcf3ce44SJohn Forte break; 2800fcf3ce44SJohn Forte 2801fcf3ce44SJohn Forte case 1024: 2802fcf3ce44SJohn Forte value = 1; 2803fcf3ce44SJohn Forte break; 2804fcf3ce44SJohn Forte 2805fcf3ce44SJohn Forte case 2048: 2806fcf3ce44SJohn Forte value = 2; 2807fcf3ce44SJohn Forte break; 2808fcf3ce44SJohn Forte 2809fcf3ce44SJohn Forte case 4096: 2810fcf3ce44SJohn Forte value = 3; 2811fcf3ce44SJohn Forte break; 2812fcf3ce44SJohn Forte 2813fcf3ce44SJohn Forte default: 2814fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2815fcf3ce44SJohn Forte "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 2816fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 2817fcf3ce44SJohn Forte 2818fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 2819fcf3ce44SJohn Forte goto xlate; 2820fcf3ce44SJohn Forte } 2821fcf3ce44SJohn Forte 28228f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), 28238f23e9faSHans Rosenfeld KM_SLEEP)) == 0) { 2824fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2825fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to allocate mailbox buffer."); 2826fcf3ce44SJohn Forte return; 2827fcf3ce44SJohn Forte } 282882527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 2829fcf3ce44SJohn Forte 283082527734SSukumar Swaminathan emlxs_mb_set_var(hba, mbq, 0x00100506, value); 2831291a2b48SSukumar Swaminathan 283282527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2833fcf3ce44SJohn Forte if (verbose || (mb->mbxStatus != 0x12)) { 2834fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2835291a2b48SSukumar Swaminathan "PCI_MAX_READ: Unable to update. " 2836291a2b48SSukumar Swaminathan "status=%x value=%d (%d bytes)", 2837291a2b48SSukumar Swaminathan mb->mbxStatus, value, 2838fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 2839fcf3ce44SJohn Forte } 2840fcf3ce44SJohn Forte } else { 2841291a2b48SSukumar Swaminathan if (verbose && 2842291a2b48SSukumar Swaminathan (cfg[CFG_PCI_MAX_READ].current != 2843fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].def)) { 2844fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2845fcf3ce44SJohn Forte "PCI_MAX_READ: Updated. %d bytes", 2846fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 2847fcf3ce44SJohn Forte } 2848fcf3ce44SJohn Forte } 2849fcf3ce44SJohn Forte 28508f23e9faSHans Rosenfeld (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 2851fcf3ce44SJohn Forte 2852fcf3ce44SJohn Forte return; 2853fcf3ce44SJohn Forte 285482527734SSukumar Swaminathan } /* emlxs_pcix_mxr_update */ 2855fcf3ce44SJohn Forte 2856fcf3ce44SJohn Forte 2857fcf3ce44SJohn Forte 2858fcf3ce44SJohn Forte extern uint32_t 285982527734SSukumar Swaminathan emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq) 2860fcf3ce44SJohn Forte { 2861fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 286282527734SSukumar Swaminathan MAILBOX *mb = (MAILBOX *)mbq; 2863fcf3ce44SJohn Forte uint32_t npname0, npname1; 2864fcf3ce44SJohn Forte uint32_t tmpkey, theKey; 2865fcf3ce44SJohn Forte uint16_t key850; 2866fcf3ce44SJohn Forte uint32_t t1, t2, t3, t4; 2867fcf3ce44SJohn Forte uint32_t ts; 2868fcf3ce44SJohn Forte 2869fcf3ce44SJohn Forte #define SEED 0x876EDC21 2870fcf3ce44SJohn Forte 2871fcf3ce44SJohn Forte /* This key is only used currently for SBUS adapters */ 2872fcf3ce44SJohn Forte if (hba->bus_type != SBUS_FC) { 2873fcf3ce44SJohn Forte return (0); 2874fcf3ce44SJohn Forte } 2875291a2b48SSukumar Swaminathan 2876fcf3ce44SJohn Forte tmpkey = mb->un.varWords[30]; 287782527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS); 2878fcf3ce44SJohn Forte 287982527734SSukumar Swaminathan emlxs_mb_read_nv(hba, mbq); 288082527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2881fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2882291a2b48SSukumar Swaminathan "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand, 2883291a2b48SSukumar Swaminathan mb->mbxStatus); 2884fcf3ce44SJohn Forte 2885fcf3ce44SJohn Forte return (0); 2886fcf3ce44SJohn Forte } 2887fcf3ce44SJohn Forte npname0 = mb->un.varRDnvp.portname[0]; 2888fcf3ce44SJohn Forte npname1 = mb->un.varRDnvp.portname[1]; 2889fcf3ce44SJohn Forte 2890fcf3ce44SJohn Forte key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 2891fcf3ce44SJohn Forte ts = (uint16_t)(npname1 + 1); 2892fcf3ce44SJohn Forte t1 = ts * key850; 2893fcf3ce44SJohn Forte ts = (uint16_t)((npname1 >> 16) + 1); 2894fcf3ce44SJohn Forte t2 = ts * key850; 2895fcf3ce44SJohn Forte ts = (uint16_t)(npname0 + 1); 2896fcf3ce44SJohn Forte t3 = ts * key850; 2897fcf3ce44SJohn Forte ts = (uint16_t)((npname0 >> 16) + 1); 2898fcf3ce44SJohn Forte t4 = ts * key850; 2899fcf3ce44SJohn Forte theKey = SEED + t1 + t2 + t3 + t4; 2900fcf3ce44SJohn Forte 2901fcf3ce44SJohn Forte return (theKey); 2902fcf3ce44SJohn Forte 290382527734SSukumar Swaminathan } /* emlxs_get_key() */ 2904291a2b48SSukumar Swaminathan 2905291a2b48SSukumar Swaminathan 2906291a2b48SSukumar Swaminathan extern void 2907291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba) 2908291a2b48SSukumar Swaminathan { 2909291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2910291a2b48SSukumar Swaminathan uint32_t i; 2911291a2b48SSukumar Swaminathan 2912291a2b48SSukumar Swaminathan /* Display firmware library one time */ 291382527734SSukumar Swaminathan for (i = 0; i < emlxs_fw_count; i++) { 2914291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s", 2915291a2b48SSukumar Swaminathan emlxs_fw_table[i].label); 2916291a2b48SSukumar Swaminathan } 2917291a2b48SSukumar Swaminathan 2918291a2b48SSukumar Swaminathan return; 2919291a2b48SSukumar Swaminathan 292082527734SSukumar Swaminathan } /* emlxs_fw_show() */ 2921291a2b48SSukumar Swaminathan 2922291a2b48SSukumar Swaminathan 2923291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 292482527734SSukumar Swaminathan extern void 2925291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2926291a2b48SSukumar Swaminathan { 2927291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2928291a2b48SSukumar Swaminathan int (*emlxs_fw_get)(emlxs_firmware_t *); 2929291a2b48SSukumar Swaminathan int err; 29308f23e9faSHans Rosenfeld char name[64]; 2931291a2b48SSukumar Swaminathan 2932291a2b48SSukumar Swaminathan /* Make sure image is unloaded and image buffer pointer is clear */ 2933291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2934291a2b48SSukumar Swaminathan 2935291a2b48SSukumar Swaminathan err = 0; 2936291a2b48SSukumar Swaminathan hba->fw_modhandle = 2937291a2b48SSukumar Swaminathan ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err); 2938291a2b48SSukumar Swaminathan if (!hba->fw_modhandle) { 2939291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2940291a2b48SSukumar Swaminathan "Unable to load firmware module. error=%d", err); 2941291a2b48SSukumar Swaminathan 2942291a2b48SSukumar Swaminathan return; 2943291a2b48SSukumar Swaminathan } else { 2944291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2945291a2b48SSukumar Swaminathan "Firmware module loaded."); 2946291a2b48SSukumar Swaminathan } 2947291a2b48SSukumar Swaminathan 29488f23e9faSHans Rosenfeld (void) snprintf(name, sizeof (name), "%s_fw_get", DRIVER_NAME); 2949291a2b48SSukumar Swaminathan err = 0; 2950291a2b48SSukumar Swaminathan emlxs_fw_get = 29518f23e9faSHans Rosenfeld (int (*)())ddi_modsym(hba->fw_modhandle, name, &err); 2952291a2b48SSukumar Swaminathan if ((void *)emlxs_fw_get == NULL) { 2953291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 29548f23e9faSHans Rosenfeld "%s not present. error=%d", name, err); 2955291a2b48SSukumar Swaminathan 2956291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2957291a2b48SSukumar Swaminathan return; 2958291a2b48SSukumar Swaminathan } 2959291a2b48SSukumar Swaminathan 2960291a2b48SSukumar Swaminathan if (emlxs_fw_get(fw)) { 2961291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2962291a2b48SSukumar Swaminathan "Invalid firmware image module found. %s", fw->label); 2963291a2b48SSukumar Swaminathan 2964291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2965291a2b48SSukumar Swaminathan return; 2966291a2b48SSukumar Swaminathan } 2967291a2b48SSukumar Swaminathan 2968291a2b48SSukumar Swaminathan return; 2969291a2b48SSukumar Swaminathan 297082527734SSukumar Swaminathan } /* emlxs_fw_load() */ 2971291a2b48SSukumar Swaminathan 2972291a2b48SSukumar Swaminathan 297382527734SSukumar Swaminathan extern void 2974291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2975291a2b48SSukumar Swaminathan { 2976291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2977291a2b48SSukumar Swaminathan 2978291a2b48SSukumar Swaminathan /* Clear the firmware image */ 2979291a2b48SSukumar Swaminathan fw->image = NULL; 2980291a2b48SSukumar Swaminathan fw->size = 0; 2981291a2b48SSukumar Swaminathan 2982291a2b48SSukumar Swaminathan if (hba->fw_modhandle) { 2983291a2b48SSukumar Swaminathan /* Close the module */ 2984291a2b48SSukumar Swaminathan (void) ddi_modclose(hba->fw_modhandle); 2985291a2b48SSukumar Swaminathan hba->fw_modhandle = NULL; 2986291a2b48SSukumar Swaminathan 2987291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2988291a2b48SSukumar Swaminathan "Firmware module unloaded."); 2989291a2b48SSukumar Swaminathan } 2990291a2b48SSukumar Swaminathan 2991291a2b48SSukumar Swaminathan return; 2992291a2b48SSukumar Swaminathan 299382527734SSukumar Swaminathan } /* emlxs_fw_unload() */ 2994291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 2995a9800bebSGarrett D'Amore 2996a9800bebSGarrett D'Amore 2997a9800bebSGarrett D'Amore static void 2998a9800bebSGarrett D'Amore emlxs_pci_cap_offsets(emlxs_hba_t *hba) 2999a9800bebSGarrett D'Amore { 3000a9800bebSGarrett D'Amore emlxs_port_t *port = &PPORT; 30018f23e9faSHans Rosenfeld uint32_t reg; 3002a9800bebSGarrett D'Amore uint8_t offset; 30038f23e9faSHans Rosenfeld uint8_t next; 3004a9800bebSGarrett D'Amore uint8_t id; 30058f23e9faSHans Rosenfeld uint16_t eoffset; 30068f23e9faSHans Rosenfeld uint16_t enext; 30078f23e9faSHans Rosenfeld uint8_t eversion; 30088f23e9faSHans Rosenfeld uint16_t eid; 30098f23e9faSHans Rosenfeld 30108f23e9faSHans Rosenfeld /* Read PCI capbabilities */ 3011a9800bebSGarrett D'Amore 3012a9800bebSGarrett D'Amore bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset)); 3013a9800bebSGarrett D'Amore 3014a9800bebSGarrett D'Amore /* Read first offset */ 30158f23e9faSHans Rosenfeld offset = PCI_CAP_POINTER; 3016a9800bebSGarrett D'Amore offset = ddi_get8(hba->pci_acc_handle, 30178f23e9faSHans Rosenfeld (uint8_t *)(hba->pci_addr + offset)); 3018a9800bebSGarrett D'Amore 3019a9800bebSGarrett D'Amore while (offset >= PCI_CAP_PTR_OFF) { 30208f23e9faSHans Rosenfeld /* Read the cap */ 30218f23e9faSHans Rosenfeld reg = ddi_get32(hba->pci_acc_handle, 30228f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr + offset)); 30238f23e9faSHans Rosenfeld 30248f23e9faSHans Rosenfeld id = ((reg >> PCI_CAP_ID_SHIFT) & PCI_CAP_ID_MASK); 30258f23e9faSHans Rosenfeld next = ((reg >> PCI_CAP_NEXT_PTR_SHIFT) & 30268f23e9faSHans Rosenfeld PCI_CAP_NEXT_PTR_MASK); 3027a9800bebSGarrett D'Amore 30288f23e9faSHans Rosenfeld if ((id < PCI_CAP_MAX_PTR) && 30298f23e9faSHans Rosenfeld (hba->pci_cap_offset[id] == 0)) { 3030a9800bebSGarrett D'Amore hba->pci_cap_offset[id] = offset; 3031a9800bebSGarrett D'Amore } 3032a9800bebSGarrett D'Amore 3033a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 30348f23e9faSHans Rosenfeld "%s: offset=0x%x next=0x%x", 30358f23e9faSHans Rosenfeld emlxs_pci_cap_xlate(id), offset, next); 30368f23e9faSHans Rosenfeld 30378f23e9faSHans Rosenfeld offset = next; 30388f23e9faSHans Rosenfeld } 30398f23e9faSHans Rosenfeld 30408f23e9faSHans Rosenfeld /* Workaround for BE adapters */ 30418f23e9faSHans Rosenfeld if ((hba->pci_cap_offset[PCI_CAP_ID_VS] == 0) && 30428f23e9faSHans Rosenfeld (hba->model_info.chip & EMLXS_BE_CHIPS)) { 30438f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS] = 0x54; 30448f23e9faSHans Rosenfeld 30458f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 30468f23e9faSHans Rosenfeld "%s: offset=0x%x Added.", 30478f23e9faSHans Rosenfeld emlxs_pci_cap_xlate(PCI_CAP_ID_VS), 30488f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS]); 30498f23e9faSHans Rosenfeld } 30508f23e9faSHans Rosenfeld 30518f23e9faSHans Rosenfeld if (! hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) { 30528f23e9faSHans Rosenfeld /* It's not a PCIE adapter. */ 30538f23e9faSHans Rosenfeld return; 30548f23e9faSHans Rosenfeld } 30558f23e9faSHans Rosenfeld 30568f23e9faSHans Rosenfeld /* Read PCI Extended capbabilities */ 30578f23e9faSHans Rosenfeld 30588f23e9faSHans Rosenfeld bzero(hba->pci_ecap_offset, sizeof (hba->pci_ecap_offset)); 30598f23e9faSHans Rosenfeld 30608f23e9faSHans Rosenfeld /* Set first offset */ 30618f23e9faSHans Rosenfeld eoffset = PCIE_EXT_CAP; 30628f23e9faSHans Rosenfeld 30638f23e9faSHans Rosenfeld while (eoffset >= PCIE_EXT_CAP) { 30648f23e9faSHans Rosenfeld /* Read the cap */ 30658f23e9faSHans Rosenfeld reg = ddi_get32(hba->pci_acc_handle, 30668f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr + eoffset)); 30678f23e9faSHans Rosenfeld 30688f23e9faSHans Rosenfeld eid = ((reg >> PCIE_EXT_CAP_ID_SHIFT) & PCIE_EXT_CAP_ID_MASK); 30698f23e9faSHans Rosenfeld eversion = ((reg >> PCIE_EXT_CAP_VER_SHIFT) & 30708f23e9faSHans Rosenfeld PCIE_EXT_CAP_VER_MASK); 30718f23e9faSHans Rosenfeld enext = ((reg >> PCIE_EXT_CAP_NEXT_PTR_SHIFT) & 30728f23e9faSHans Rosenfeld PCIE_EXT_CAP_NEXT_PTR_MASK); 30738f23e9faSHans Rosenfeld 30748f23e9faSHans Rosenfeld if ((eid < PCI_EXT_CAP_MAX_PTR) && 30758f23e9faSHans Rosenfeld (hba->pci_ecap_offset[eid] == 0)) { 30768f23e9faSHans Rosenfeld hba->pci_ecap_offset[eid] = eoffset; 30778f23e9faSHans Rosenfeld } 30788f23e9faSHans Rosenfeld 30798f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 30808f23e9faSHans Rosenfeld "%s: offset=0x%x version=0x%x next=0x%x", 30818f23e9faSHans Rosenfeld emlxs_pci_ecap_xlate(eid), 30828f23e9faSHans Rosenfeld eoffset, eversion, enext); 3083a9800bebSGarrett D'Amore 30848f23e9faSHans Rosenfeld eoffset = enext; 3085a9800bebSGarrett D'Amore } 3086a9800bebSGarrett D'Amore 3087a9800bebSGarrett D'Amore return; 3088a9800bebSGarrett D'Amore 3089a9800bebSGarrett D'Amore } /* emlxs_pci_cap_offsets() */ 3090