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 * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 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 /* 23*291a2b48SSukumar Swaminathan * Copyright 2009 Emulex. All rights reserved. 24fcf3ce44SJohn Forte * Use is subject to License terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 27*291a2b48SSukumar Swaminathan #define EMLXS_FW_TABLE_DEF 28fcf3ce44SJohn Forte #define EMLXS_MODEL_DEF 29fcf3ce44SJohn Forte 30*291a2b48SSukumar Swaminathan #include <emlxs.h> 31fcf3ce44SJohn Forte 32fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_HBA_C); 34fcf3ce44SJohn Forte 35fcf3ce44SJohn Forte static uint32_t emlxs_decode_biu_rev(uint32_t rev); 36fcf3ce44SJohn Forte static uint32_t emlxs_decode_endec_rev(uint32_t rev); 37fcf3ce44SJohn Forte static void emlxs_parse_prog_types(emlxs_hba_t *hba, char *types); 38*291a2b48SSukumar Swaminathan static int32_t emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd, 39*291a2b48SSukumar Swaminathan uint32_t size); 40fcf3ce44SJohn Forte static void emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types); 41*291a2b48SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, 42*291a2b48SSukumar Swaminathan IOCBQ *iocbq); 43fcf3ce44SJohn Forte static void emlxs_process_link_speed(emlxs_hba_t *hba); 44fcf3ce44SJohn Forte static void emlxs_decode_label(char *label, char *buffer); 45fcf3ce44SJohn Forte 46*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 47*291a2b48SSukumar Swaminathan static void emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw); 48*291a2b48SSukumar Swaminathan static void emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw); 49*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 50*291a2b48SSukumar Swaminathan 51fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 52fcf3ce44SJohn Forte uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 53*291a2b48SSukumar Swaminathan {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; 54fcf3ce44SJohn Forte uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 55*291a2b48SSukumar Swaminathan {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4, 56*291a2b48SSukumar Swaminathan EMLXS_MSI0_MASK8}; 57*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 58fcf3ce44SJohn Forte 59fcf3ce44SJohn Forte 60fcf3ce44SJohn Forte static uint32_t emlxs_disable_traffic_cop = 1; 61fcf3ce44SJohn Forte 62*291a2b48SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = { 63fcf3ce44SJohn Forte {FC_FCP_RING, "FCP Ring"}, 64fcf3ce44SJohn Forte {FC_IP_RING, "IP Ring"}, 65fcf3ce44SJohn Forte {FC_ELS_RING, "ELS Ring"}, 66fcf3ce44SJohn Forte {FC_CT_RING, "CT Ring"} 67fcf3ce44SJohn Forte 68*291a2b48SSukumar Swaminathan }; /* emlxs_ring_table */ 69fcf3ce44SJohn Forte 70fcf3ce44SJohn Forte 71*291a2b48SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = { 72fcf3ce44SJohn Forte {0, "NULL"}, 73fcf3ce44SJohn Forte {FC_ERROR, "ERROR"}, 74fcf3ce44SJohn Forte {FC_KILLED, "KILLED"}, 75fcf3ce44SJohn Forte {FC_WARM_START, "WARM_START"}, 76fcf3ce44SJohn Forte {FC_INIT_START, "INIT_START"}, 77fcf3ce44SJohn Forte {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 78fcf3ce44SJohn Forte {FC_INIT_REV, "INIT_REV"}, 79fcf3ce44SJohn Forte {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 80fcf3ce44SJohn Forte {FC_INIT_CFGRING, "INIT_CFGRING"}, 81fcf3ce44SJohn Forte {FC_INIT_INITLINK, "INIT_INITLINK"}, 82fcf3ce44SJohn Forte {FC_LINK_DOWN, "LINK_DOWN"}, 83fcf3ce44SJohn Forte {FC_LINK_UP, "LINK_UP"}, 84fcf3ce44SJohn Forte {FC_CLEAR_LA, "CLEAR_LA"}, 85fcf3ce44SJohn Forte {FC_READY, "READY"} 86fcf3ce44SJohn Forte 87*291a2b48SSukumar Swaminathan }; /* emlxs_ffstate_table */ 88fcf3ce44SJohn Forte 89fcf3ce44SJohn Forte 90fcf3ce44SJohn Forte /* 91*291a2b48SSukumar Swaminathan * emlxs_ffinit() 92fcf3ce44SJohn Forte * 93fcf3ce44SJohn Forte * This routine will start initialization of the FireFly Chipset 94fcf3ce44SJohn Forte */ 95fcf3ce44SJohn Forte extern int 96fcf3ce44SJohn Forte emlxs_ffinit(emlxs_hba_t *hba) 97fcf3ce44SJohn Forte { 98fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 99fcf3ce44SJohn Forte emlxs_config_t *cfg; 100fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 101fcf3ce44SJohn Forte MAILBOX *mb; 102fcf3ce44SJohn Forte RING *rp; 103fcf3ce44SJohn Forte MATCHMAP *mp; 104fcf3ce44SJohn Forte MATCHMAP *mp1; 105fcf3ce44SJohn Forte uint8_t *inptr; 106fcf3ce44SJohn Forte uint8_t *outptr; 107fcf3ce44SJohn Forte uint32_t status; 108fcf3ce44SJohn Forte uint32_t i; 109fcf3ce44SJohn Forte uint32_t j; 110fcf3ce44SJohn Forte uint32_t read_rev_reset; 111fcf3ce44SJohn Forte uint32_t key = 0; 112fcf3ce44SJohn Forte uint32_t fw_check; 113fcf3ce44SJohn Forte uint32_t rval; 114fcf3ce44SJohn Forte uint32_t offset; 115fcf3ce44SJohn Forte uint8_t vpd_data[DMP_VPD_SIZE]; 116fcf3ce44SJohn Forte uint32_t MaxRbusSize; 117fcf3ce44SJohn Forte uint32_t MaxIbusSize; 118fcf3ce44SJohn Forte uint32_t sli_mode; 119*291a2b48SSukumar Swaminathan uint32_t sli_mode_mask; 120fcf3ce44SJohn Forte 121fcf3ce44SJohn Forte cfg = &CFG; 122fcf3ce44SJohn Forte vpd = &VPD; 123fcf3ce44SJohn Forte mb = 0; 124fcf3ce44SJohn Forte MaxRbusSize = 0; 125fcf3ce44SJohn Forte MaxIbusSize = 0; 126fcf3ce44SJohn Forte read_rev_reset = 0; 127*291a2b48SSukumar Swaminathan 128*291a2b48SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 129*291a2b48SSukumar Swaminathan (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba, 130*291a2b48SSukumar Swaminathan hba->sbus_csr_addr)); 131*291a2b48SSukumar Swaminathan } 132fcf3ce44SJohn Forte 133fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 134fcf3ce44SJohn Forte /* Initialize sli mode based on configuration parameter */ 135fcf3ce44SJohn Forte switch (cfg[CFG_SLI_MODE].current) { 136fcf3ce44SJohn Forte case 2: /* SLI2 mode */ 137*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 138*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 139*291a2b48SSukumar Swaminathan break; 140*291a2b48SSukumar Swaminathan 141*291a2b48SSukumar Swaminathan case 3: /* SLI3 mode */ 142*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 143*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 144fcf3ce44SJohn Forte break; 145fcf3ce44SJohn Forte 146fcf3ce44SJohn Forte case 0: /* Best available */ 147fcf3ce44SJohn Forte case 1: /* Best available */ 148fcf3ce44SJohn Forte default: 149*291a2b48SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 150*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI4_MODE; 151*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI4_MASK; 152*291a2b48SSukumar Swaminathan } else if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) { 153*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 154*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 155*291a2b48SSukumar Swaminathan } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) { 156*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 157*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 158*291a2b48SSukumar Swaminathan } 159*291a2b48SSukumar Swaminathan } 160*291a2b48SSukumar Swaminathan /* SBUS adapters only available in SLI2 */ 161*291a2b48SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 162*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 163*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 164fcf3ce44SJohn Forte } 165*291a2b48SSukumar Swaminathan 166*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */ 167fcf3ce44SJohn Forte 168fcf3ce44SJohn Forte /* Set the fw_check flag */ 169fcf3ce44SJohn Forte fw_check = cfg[CFG_FW_CHECK].current; 170fcf3ce44SJohn Forte 171fcf3ce44SJohn Forte hba->mbox_queue_flag = 0; 172fcf3ce44SJohn Forte hba->hc_copy = 0; 173fcf3ce44SJohn Forte hba->fc_edtov = FF_DEF_EDTOV; 174fcf3ce44SJohn Forte hba->fc_ratov = FF_DEF_RATOV; 175fcf3ce44SJohn Forte hba->fc_altov = FF_DEF_ALTOV; 176fcf3ce44SJohn Forte hba->fc_arbtov = FF_DEF_ARBTOV; 177fcf3ce44SJohn Forte 178fcf3ce44SJohn Forte reset: 179fcf3ce44SJohn Forte 180fcf3ce44SJohn Forte /* Reset and initialize the adapter */ 181*291a2b48SSukumar Swaminathan if (emlxs_sli_online(hba)) { 182fcf3ce44SJohn Forte return (EIO); 183fcf3ce44SJohn Forte } 184*291a2b48SSukumar Swaminathan 185*291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT 186*291a2b48SSukumar Swaminathan /* Access handle validation */ 187*291a2b48SSukumar Swaminathan if (hba->fm_caps & DDI_FM_ACCCHK_CAPABLE) { 188*291a2b48SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba->pci_acc_handle) 189*291a2b48SSukumar Swaminathan != DDI_FM_OK) || 190*291a2b48SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba->slim_acc_handle) 191*291a2b48SSukumar Swaminathan != DDI_FM_OK) || 192*291a2b48SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba->csr_acc_handle) 193*291a2b48SSukumar Swaminathan != DDI_FM_OK)) { 194*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 195*291a2b48SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 196*291a2b48SSukumar Swaminathan return (EIO); 197*291a2b48SSukumar Swaminathan } 198*291a2b48SSukumar Swaminathan } 199*291a2b48SSukumar Swaminathan #endif /* FMA_SUPPORT */ 200*291a2b48SSukumar Swaminathan 201fcf3ce44SJohn Forte /* 202fcf3ce44SJohn Forte * Allocate some memory for buffers 203fcf3ce44SJohn Forte */ 204fcf3ce44SJohn Forte if (emlxs_mem_alloc_buffer(hba) == 0) { 205fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 206fcf3ce44SJohn Forte "Unable to allocate memory buffers."); 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 209fcf3ce44SJohn Forte 210fcf3ce44SJohn Forte return (ENOMEM); 211fcf3ce44SJohn Forte } 212*291a2b48SSukumar Swaminathan 213fcf3ce44SJohn Forte /* 214fcf3ce44SJohn Forte * Get a buffer which will be used repeatedly for mailbox commands 215fcf3ce44SJohn Forte */ 216fcf3ce44SJohn Forte if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 217fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 218fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 219fcf3ce44SJohn Forte 220fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 221fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 222fcf3ce44SJohn Forte 223fcf3ce44SJohn Forte return (ENOMEM); 224fcf3ce44SJohn Forte } 225*291a2b48SSukumar Swaminathan 226fcf3ce44SJohn Forte /* Check for the LP9802 (This is a special case) */ 227fcf3ce44SJohn Forte /* We need to check for dual channel adapter */ 228fcf3ce44SJohn Forte if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) { 229fcf3ce44SJohn Forte /* Try to determine if this is a DC adapter */ 230fcf3ce44SJohn Forte if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 231fcf3ce44SJohn Forte if (MaxRbusSize == REDUCED_SRAM_CFG) { 232fcf3ce44SJohn Forte /* LP9802DC */ 233fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 234fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9802DC) { 235fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 236fcf3ce44SJohn Forte &hba->model_info, 237fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 238fcf3ce44SJohn Forte break; 239fcf3ce44SJohn Forte } 240fcf3ce44SJohn Forte } 241fcf3ce44SJohn Forte } else if (hba->model_info.id != LP9802) { 242fcf3ce44SJohn Forte /* LP9802 */ 243fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 244fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9802) { 245fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 246fcf3ce44SJohn Forte &hba->model_info, 247fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 248fcf3ce44SJohn Forte break; 249fcf3ce44SJohn Forte } 250fcf3ce44SJohn Forte } 251fcf3ce44SJohn Forte } 252fcf3ce44SJohn Forte } 253fcf3ce44SJohn Forte } 254*291a2b48SSukumar Swaminathan 255fcf3ce44SJohn Forte /* 256fcf3ce44SJohn Forte * Setup and issue mailbox READ REV command 257fcf3ce44SJohn Forte */ 258fcf3ce44SJohn Forte vpd->opFwRev = 0; 259fcf3ce44SJohn Forte vpd->postKernRev = 0; 260fcf3ce44SJohn Forte vpd->sli1FwRev = 0; 261fcf3ce44SJohn Forte vpd->sli2FwRev = 0; 262fcf3ce44SJohn Forte vpd->sli3FwRev = 0; 263fcf3ce44SJohn Forte vpd->sli4FwRev = 0; 264fcf3ce44SJohn Forte 265fcf3ce44SJohn Forte vpd->postKernName[0] = 0; 266fcf3ce44SJohn Forte vpd->opFwName[0] = 0; 267fcf3ce44SJohn Forte vpd->sli1FwName[0] = 0; 268fcf3ce44SJohn Forte vpd->sli2FwName[0] = 0; 269fcf3ce44SJohn Forte vpd->sli3FwName[0] = 0; 270fcf3ce44SJohn Forte vpd->sli4FwName[0] = 0; 271fcf3ce44SJohn Forte 272fcf3ce44SJohn Forte vpd->opFwLabel[0] = 0; 273fcf3ce44SJohn Forte vpd->sli1FwLabel[0] = 0; 274fcf3ce44SJohn Forte vpd->sli2FwLabel[0] = 0; 275fcf3ce44SJohn Forte vpd->sli3FwLabel[0] = 0; 276fcf3ce44SJohn Forte vpd->sli4FwLabel[0] = 0; 277fcf3ce44SJohn Forte 278fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_REV); 279fcf3ce44SJohn Forte emlxs_mb_read_rev(hba, mb, 0); 280*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 281fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 282fcf3ce44SJohn Forte "Unable to read rev. Mailbox cmd=%x status=%x", 283fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 284fcf3ce44SJohn Forte 285fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 286fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 287fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 288fcf3ce44SJohn Forte 289fcf3ce44SJohn Forte return (EIO); 290fcf3ce44SJohn Forte } 291*291a2b48SSukumar Swaminathan 292fcf3ce44SJohn Forte if (mb->un.varRdRev.rr == 0) { 293fcf3ce44SJohn Forte /* Old firmware */ 294fcf3ce44SJohn Forte if (read_rev_reset == 0) { 295fcf3ce44SJohn Forte /* Clean up */ 296fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 297fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 298fcf3ce44SJohn Forte 299fcf3ce44SJohn Forte read_rev_reset = 1; 300fcf3ce44SJohn Forte 301fcf3ce44SJohn Forte goto reset; 302fcf3ce44SJohn Forte } else { 303fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 304fcf3ce44SJohn Forte "Outdated firmware detected."); 305fcf3ce44SJohn Forte } 306fcf3ce44SJohn Forte 307fcf3ce44SJohn Forte vpd->rBit = 0; 308fcf3ce44SJohn Forte } else { 309fcf3ce44SJohn Forte if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 310fcf3ce44SJohn Forte if (read_rev_reset == 0) { 311fcf3ce44SJohn Forte /* Clean up */ 312fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 313fcf3ce44SJohn Forte (uint8_t *)mb); 314fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 315fcf3ce44SJohn Forte 316fcf3ce44SJohn Forte read_rev_reset = 1; 317fcf3ce44SJohn Forte 318fcf3ce44SJohn Forte goto reset; 319fcf3ce44SJohn Forte } else { 320fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 321fcf3ce44SJohn Forte "Non-operational firmware detected. " 322fcf3ce44SJohn Forte "type=%x", 323fcf3ce44SJohn Forte mb->un.varRdRev.un.b.ProgType); 324fcf3ce44SJohn Forte } 325fcf3ce44SJohn Forte } 326*291a2b48SSukumar Swaminathan 327fcf3ce44SJohn Forte vpd->rBit = 1; 328fcf3ce44SJohn Forte vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 329*291a2b48SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel, 330*291a2b48SSukumar Swaminathan 16); 331fcf3ce44SJohn Forte vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 332*291a2b48SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel, 333*291a2b48SSukumar Swaminathan 16); 334fcf3ce44SJohn Forte 335*291a2b48SSukumar Swaminathan /* 336*291a2b48SSukumar Swaminathan * Lets try to read the SLI3 version 337*291a2b48SSukumar Swaminathan * Setup and issue mailbox READ REV(v3) command 338*291a2b48SSukumar Swaminathan */ 339fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_REV); 340fcf3ce44SJohn Forte emlxs_mb_read_rev(hba, mb, 1); 341fcf3ce44SJohn Forte 342*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 343*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 344fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 345fcf3ce44SJohn Forte "Unable to read rev (v3). Mailbox cmd=%x status=%x", 346fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 347fcf3ce44SJohn Forte 348fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 349fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 350fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 351fcf3ce44SJohn Forte 352fcf3ce44SJohn Forte return (EIO); 353fcf3ce44SJohn Forte } 354*291a2b48SSukumar Swaminathan 355fcf3ce44SJohn Forte if (mb->un.varRdRev.rf3) { 356fcf3ce44SJohn Forte /* 357*291a2b48SSukumar Swaminathan * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; 358*291a2b48SSukumar Swaminathan * Not needed 359fcf3ce44SJohn Forte */ 360fcf3ce44SJohn Forte vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 361fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.sliFwName2, 362fcf3ce44SJohn Forte vpd->sli3FwLabel, 16); 363fcf3ce44SJohn Forte } 364fcf3ce44SJohn Forte } 365fcf3ce44SJohn Forte 366*291a2b48SSukumar Swaminathan 367*291a2b48SSukumar Swaminathan if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) { 368*291a2b48SSukumar Swaminathan if (vpd->sli2FwRev) { 369*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 370*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 371fcf3ce44SJohn Forte } else { 372fcf3ce44SJohn Forte sli_mode = 0; 373*291a2b48SSukumar Swaminathan sli_mode_mask = 0; 374fcf3ce44SJohn Forte } 375*291a2b48SSukumar Swaminathan } 376*291a2b48SSukumar Swaminathan 377*291a2b48SSukumar Swaminathan else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) { 378*291a2b48SSukumar Swaminathan if (vpd->sli3FwRev) { 379*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 380*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 381fcf3ce44SJohn Forte } else { 382fcf3ce44SJohn Forte sli_mode = 0; 383*291a2b48SSukumar Swaminathan sli_mode_mask = 0; 384fcf3ce44SJohn Forte } 385fcf3ce44SJohn Forte } 386*291a2b48SSukumar Swaminathan 387*291a2b48SSukumar Swaminathan if (!(hba->model_info.sli_mask & sli_mode_mask)) { 388fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 389fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 390fcf3ce44SJohn Forte "Firmware not available. sli-mode=%d", 391fcf3ce44SJohn Forte cfg[CFG_SLI_MODE].current); 392fcf3ce44SJohn Forte #else 393fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 394fcf3ce44SJohn Forte "Firmware not available. sli-mode=2"); 395*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */ 396fcf3ce44SJohn Forte 397fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 398fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 399fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 400fcf3ce44SJohn Forte 401fcf3ce44SJohn Forte return (EIO); 402fcf3ce44SJohn Forte } 403*291a2b48SSukumar Swaminathan 404fcf3ce44SJohn Forte /* Save information as VPD data */ 405fcf3ce44SJohn Forte vpd->postKernRev = mb->un.varRdRev.postKernRev; 406fcf3ce44SJohn Forte vpd->opFwRev = mb->un.varRdRev.opFwRev; 407fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 408fcf3ce44SJohn Forte vpd->biuRev = mb->un.varRdRev.biuRev; 409fcf3ce44SJohn Forte vpd->smRev = mb->un.varRdRev.smRev; 410fcf3ce44SJohn Forte vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 411fcf3ce44SJohn Forte vpd->endecRev = mb->un.varRdRev.endecRev; 412fcf3ce44SJohn Forte vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 413fcf3ce44SJohn Forte vpd->fcphLow = mb->un.varRdRev.fcphLow; 414fcf3ce44SJohn Forte vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 415fcf3ce44SJohn Forte vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 416fcf3ce44SJohn Forte 417fcf3ce44SJohn Forte /* Decode FW names */ 418fcf3ce44SJohn Forte emlxs_decode_version(vpd->postKernRev, vpd->postKernName); 419fcf3ce44SJohn Forte emlxs_decode_version(vpd->opFwRev, vpd->opFwName); 420fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName); 421fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName); 422fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName); 423fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName); 424fcf3ce44SJohn Forte 425fcf3ce44SJohn Forte /* Decode FW labels */ 426fcf3ce44SJohn Forte emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel); 427fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel); 428fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel); 429fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel); 430fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel); 431fcf3ce44SJohn Forte 432fcf3ce44SJohn Forte key = emlxs_get_key(hba, mb); 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte /* Get adapter VPD information */ 435fcf3ce44SJohn Forte offset = 0; 436fcf3ce44SJohn Forte bzero(vpd_data, sizeof (vpd_data)); 437fcf3ce44SJohn Forte vpd->port_index = (uint32_t)-1; 438fcf3ce44SJohn Forte 439fcf3ce44SJohn Forte while (offset < DMP_VPD_SIZE) { 440fcf3ce44SJohn Forte emlxs_mb_dump_vpd(hba, mb, offset); 441*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 442*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 443fcf3ce44SJohn Forte /* 444*291a2b48SSukumar Swaminathan * Let it go through even if failed. 445*291a2b48SSukumar Swaminathan * Not all adapter's have VPD info and thus will 446*291a2b48SSukumar Swaminathan * fail here. This is not a problem 447fcf3ce44SJohn Forte */ 448fcf3ce44SJohn Forte 449fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 450*291a2b48SSukumar Swaminathan "No VPD found. offset=%x status=%x", offset, 451*291a2b48SSukumar Swaminathan mb->mbxStatus); 452fcf3ce44SJohn Forte break; 453fcf3ce44SJohn Forte } else { 454fcf3ce44SJohn Forte if (mb->un.varDmp.ra == 1) { 455fcf3ce44SJohn Forte uint32_t *lp1, *lp2; 456fcf3ce44SJohn Forte uint32_t bsize; 457fcf3ce44SJohn Forte uint32_t wsize; 458fcf3ce44SJohn Forte 459fcf3ce44SJohn Forte /* 460fcf3ce44SJohn Forte * mb->un.varDmp.word_cnt is actually byte 461fcf3ce44SJohn Forte * count for the dump reply 462fcf3ce44SJohn Forte */ 463fcf3ce44SJohn Forte bsize = mb->un.varDmp.word_cnt; 464fcf3ce44SJohn Forte 465fcf3ce44SJohn Forte /* Stop if no data was received */ 466fcf3ce44SJohn Forte if (bsize == 0) { 467fcf3ce44SJohn Forte break; 468fcf3ce44SJohn Forte } 469*291a2b48SSukumar Swaminathan 470fcf3ce44SJohn Forte /* Check limit on byte size */ 471*291a2b48SSukumar Swaminathan bsize = (bsize > 472*291a2b48SSukumar Swaminathan (sizeof (vpd_data) - offset)) ? 473fcf3ce44SJohn Forte (sizeof (vpd_data) - offset) : bsize; 474fcf3ce44SJohn Forte 475fcf3ce44SJohn Forte /* 476fcf3ce44SJohn Forte * Convert size from bytes to words with 477fcf3ce44SJohn Forte * minimum of 1 word 478fcf3ce44SJohn Forte */ 479fcf3ce44SJohn Forte wsize = (bsize > 4) ? (bsize >> 2) : 1; 480fcf3ce44SJohn Forte 481fcf3ce44SJohn Forte /* 482fcf3ce44SJohn Forte * Transfer data into vpd_data buffer one 483fcf3ce44SJohn Forte * word at a time 484fcf3ce44SJohn Forte */ 485fcf3ce44SJohn Forte lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 486fcf3ce44SJohn Forte lp2 = (uint32_t *)&vpd_data[offset]; 487fcf3ce44SJohn Forte 488fcf3ce44SJohn Forte for (i = 0; i < wsize; i++) { 489fcf3ce44SJohn Forte status = *lp1++; 490fcf3ce44SJohn Forte *lp2++ = SWAP_LONG(status); 491fcf3ce44SJohn Forte } 492fcf3ce44SJohn Forte 493fcf3ce44SJohn Forte /* Increment total byte count saved */ 494fcf3ce44SJohn Forte offset += (wsize << 2); 495fcf3ce44SJohn Forte 496fcf3ce44SJohn Forte /* 497fcf3ce44SJohn Forte * Stop if less than a full transfer was 498fcf3ce44SJohn Forte * received 499fcf3ce44SJohn Forte */ 500fcf3ce44SJohn Forte if (wsize < DMP_VPD_DUMP_WCOUNT) { 501fcf3ce44SJohn Forte break; 502fcf3ce44SJohn Forte } 503*291a2b48SSukumar Swaminathan 504fcf3ce44SJohn Forte } else { 505*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 506*291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 507*291a2b48SSukumar Swaminathan "No VPD acknowledgment. offset=%x", 508*291a2b48SSukumar Swaminathan offset); 509fcf3ce44SJohn Forte break; 510fcf3ce44SJohn Forte } 511fcf3ce44SJohn Forte } 512fcf3ce44SJohn Forte 513fcf3ce44SJohn Forte } 514fcf3ce44SJohn Forte 515fcf3ce44SJohn Forte if (vpd_data[0]) { 516fcf3ce44SJohn Forte (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 517fcf3ce44SJohn Forte 518fcf3ce44SJohn Forte /* 519*291a2b48SSukumar Swaminathan * If there is a VPD part number, and it does not 520*291a2b48SSukumar Swaminathan * match the current default HBA model info, 521*291a2b48SSukumar Swaminathan * replace the default data with an entry that 522*291a2b48SSukumar Swaminathan * does match. 523*291a2b48SSukumar Swaminathan * 524*291a2b48SSukumar Swaminathan * After emlxs_parse_vpd model holds the VPD value 525*291a2b48SSukumar Swaminathan * for V2 and part_num hold the value for PN. These 526*291a2b48SSukumar Swaminathan * 2 values are NOT necessarily the same. 527fcf3ce44SJohn Forte */ 528fcf3ce44SJohn Forte 529*291a2b48SSukumar Swaminathan rval = 0; 530*291a2b48SSukumar Swaminathan if ((vpd->model[0] != 0) && 531*291a2b48SSukumar Swaminathan (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 532*291a2b48SSukumar Swaminathan 533*291a2b48SSukumar Swaminathan /* First scan for a V2 match */ 534*291a2b48SSukumar Swaminathan 535*291a2b48SSukumar Swaminathan for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 536*291a2b48SSukumar Swaminathan if (strcmp(&vpd->model[0], 537*291a2b48SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 538*291a2b48SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 539*291a2b48SSukumar Swaminathan &hba->model_info, 540*291a2b48SSukumar Swaminathan sizeof (emlxs_model_t)); 541*291a2b48SSukumar Swaminathan rval = 1; 542*291a2b48SSukumar Swaminathan break; 543fcf3ce44SJohn Forte } 544fcf3ce44SJohn Forte } 545fcf3ce44SJohn Forte } 546*291a2b48SSukumar Swaminathan 547*291a2b48SSukumar Swaminathan if (!rval && (vpd->part_num[0] != 0) && 548*291a2b48SSukumar Swaminathan (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 549*291a2b48SSukumar Swaminathan 550*291a2b48SSukumar Swaminathan /* Next scan for a PN match */ 551*291a2b48SSukumar Swaminathan 552*291a2b48SSukumar Swaminathan for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 553*291a2b48SSukumar Swaminathan if (strcmp(&vpd->part_num[0], 554*291a2b48SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 555*291a2b48SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 556*291a2b48SSukumar Swaminathan &hba->model_info, 557*291a2b48SSukumar Swaminathan sizeof (emlxs_model_t)); 558*291a2b48SSukumar Swaminathan break; 559fcf3ce44SJohn Forte } 560fcf3ce44SJohn Forte } 561fcf3ce44SJohn Forte } 562*291a2b48SSukumar Swaminathan 563fcf3ce44SJohn Forte /* 564*291a2b48SSukumar Swaminathan * Now lets update hba->model_info with the real 565*291a2b48SSukumar Swaminathan * VPD data, if any. 566*291a2b48SSukumar Swaminathan */ 567*291a2b48SSukumar Swaminathan 568*291a2b48SSukumar Swaminathan /* 569*291a2b48SSukumar Swaminathan * Replace the default model description with vpd data 570fcf3ce44SJohn Forte */ 571fcf3ce44SJohn Forte if (vpd->model_desc[0] != 0) { 572fcf3ce44SJohn Forte (void) strcpy(hba->model_info.model_desc, 573fcf3ce44SJohn Forte vpd->model_desc); 574fcf3ce44SJohn Forte } 575*291a2b48SSukumar Swaminathan 576fcf3ce44SJohn Forte /* Replace the default model with vpd data */ 577fcf3ce44SJohn Forte if (vpd->model[0] != 0) { 578fcf3ce44SJohn Forte (void) strcpy(hba->model_info.model, vpd->model); 579fcf3ce44SJohn Forte } 580*291a2b48SSukumar Swaminathan 581fcf3ce44SJohn Forte /* Replace the default program types with vpd data */ 582fcf3ce44SJohn Forte if (vpd->prog_types[0] != 0) { 583fcf3ce44SJohn Forte emlxs_parse_prog_types(hba, vpd->prog_types); 584fcf3ce44SJohn Forte } 585fcf3ce44SJohn Forte } 586*291a2b48SSukumar Swaminathan 587*291a2b48SSukumar Swaminathan /* 588*291a2b48SSukumar Swaminathan * Since the adapter model may have changed with the vpd data 589*291a2b48SSukumar Swaminathan * lets double check if adapter is not supported 590*291a2b48SSukumar Swaminathan */ 591fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 592fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 593*291a2b48SSukumar Swaminathan "Unsupported adapter found. " 594*291a2b48SSukumar Swaminathan "Id:%d Device id:0x%x SSDID:0x%x Model:%s", 595*291a2b48SSukumar Swaminathan hba->model_info.id, hba->model_info.device_id, 596*291a2b48SSukumar Swaminathan hba->model_info.ssdid, hba->model_info.model); 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 599fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 600fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 601fcf3ce44SJohn Forte 602fcf3ce44SJohn Forte return (EIO); 603fcf3ce44SJohn Forte } 604*291a2b48SSukumar Swaminathan 605fcf3ce44SJohn Forte /* Read the adapter's wakeup parms */ 606fcf3ce44SJohn Forte (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 607fcf3ce44SJohn Forte emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 608fcf3ce44SJohn Forte vpd->boot_version); 609fcf3ce44SJohn Forte 610fcf3ce44SJohn Forte /* Get fcode version property */ 611fcf3ce44SJohn Forte emlxs_get_fcode_version(hba); 612fcf3ce44SJohn Forte 613fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 614*291a2b48SSukumar Swaminathan "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 615*291a2b48SSukumar Swaminathan vpd->opFwRev, vpd->sli1FwRev); 616fcf3ce44SJohn Forte 617fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 618*291a2b48SSukumar Swaminathan "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 619*291a2b48SSukumar Swaminathan vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 620fcf3ce44SJohn Forte 621fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 622fcf3ce44SJohn Forte "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 623fcf3ce44SJohn Forte 624fcf3ce44SJohn Forte /* 625*291a2b48SSukumar Swaminathan * If firmware checking is enabled and the adapter model indicates 626*291a2b48SSukumar Swaminathan * a firmware image, then perform firmware version check 627fcf3ce44SJohn Forte */ 628fcf3ce44SJohn Forte if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) && 629*291a2b48SSukumar Swaminathan hba->model_info.fwid) || ((fw_check == 2) && 630*291a2b48SSukumar Swaminathan hba->model_info.fwid)) { 631*291a2b48SSukumar Swaminathan emlxs_firmware_t *fw; 632fcf3ce44SJohn Forte 633fcf3ce44SJohn Forte /* Find firmware image indicated by adapter model */ 634*291a2b48SSukumar Swaminathan fw = NULL; 635*291a2b48SSukumar Swaminathan for (i = 0; i < EMLXS_FW_COUNT; i++) { 636*291a2b48SSukumar Swaminathan if (emlxs_fw_table[i].id == hba->model_info.fwid) { 637*291a2b48SSukumar Swaminathan fw = &emlxs_fw_table[i]; 638fcf3ce44SJohn Forte break; 639fcf3ce44SJohn Forte } 640fcf3ce44SJohn Forte } 641fcf3ce44SJohn Forte 642fcf3ce44SJohn Forte /* 643fcf3ce44SJohn Forte * If the image was found, then verify current firmware 644fcf3ce44SJohn Forte * versions of adapter 645fcf3ce44SJohn Forte */ 646*291a2b48SSukumar Swaminathan if (fw) { 647*291a2b48SSukumar Swaminathan if ((vpd->postKernRev != fw->kern) || 648*291a2b48SSukumar Swaminathan (vpd->opFwRev != fw->stub) || 649*291a2b48SSukumar Swaminathan (vpd->sli1FwRev != fw->sli1) || 650*291a2b48SSukumar Swaminathan (vpd->sli2FwRev != fw->sli2) || 651*291a2b48SSukumar Swaminathan (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) || 652*291a2b48SSukumar Swaminathan (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) { 653fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 654*291a2b48SSukumar Swaminathan "Firmware update needed. " 655*291a2b48SSukumar Swaminathan "Updating. id=%d fw=%d", 656*291a2b48SSukumar Swaminathan hba->model_info.id, hba->model_info.fwid); 657fcf3ce44SJohn Forte 658*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 659*291a2b48SSukumar Swaminathan /* 660*291a2b48SSukumar Swaminathan * Load the firmware image now 661*291a2b48SSukumar Swaminathan * If MODFW_SUPPORT is not defined, the 662*291a2b48SSukumar Swaminathan * firmware image will already be defined 663*291a2b48SSukumar Swaminathan * in the emlxs_fw_table 664*291a2b48SSukumar Swaminathan */ 665*291a2b48SSukumar Swaminathan emlxs_fw_load(hba, fw); 666*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 667*291a2b48SSukumar Swaminathan 668*291a2b48SSukumar Swaminathan if (fw->image && fw->size) { 669*291a2b48SSukumar Swaminathan if (emlxs_fw_download(hba, 670*291a2b48SSukumar Swaminathan (char *)fw->image, fw->size, 0)) { 671*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 672*291a2b48SSukumar Swaminathan &emlxs_init_msg, 673*291a2b48SSukumar Swaminathan "Firmware update failed."); 674*291a2b48SSukumar Swaminathan } 675*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 676*291a2b48SSukumar Swaminathan /* 677*291a2b48SSukumar Swaminathan * Unload the firmware image from 678*291a2b48SSukumar Swaminathan * kernel memory 679*291a2b48SSukumar Swaminathan */ 680*291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 681*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 682fcf3ce44SJohn Forte 683*291a2b48SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, 684*291a2b48SSukumar Swaminathan (uint8_t *)mb); 685*291a2b48SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 686fcf3ce44SJohn Forte 687*291a2b48SSukumar Swaminathan fw_check = 0; 688*291a2b48SSukumar Swaminathan 689*291a2b48SSukumar Swaminathan goto reset; 690*291a2b48SSukumar Swaminathan } 691*291a2b48SSukumar Swaminathan 692*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 693*291a2b48SSukumar Swaminathan "Firmware image unavailable."); 694fcf3ce44SJohn Forte } 695fcf3ce44SJohn Forte } else { 696fcf3ce44SJohn Forte /* This should not happen */ 697fcf3ce44SJohn Forte 698fcf3ce44SJohn Forte /* 699fcf3ce44SJohn Forte * This means either the adapter database is not 700fcf3ce44SJohn Forte * correct or a firmware image is missing from the 701fcf3ce44SJohn Forte * compile 702fcf3ce44SJohn Forte */ 703fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 704*291a2b48SSukumar Swaminathan "Firmware image unavailable. id=%d fw=%d", 705fcf3ce44SJohn Forte hba->model_info.id, hba->model_info.fwid); 706fcf3ce44SJohn Forte } 707fcf3ce44SJohn Forte } 708*291a2b48SSukumar Swaminathan 709fcf3ce44SJohn Forte /* 710*291a2b48SSukumar Swaminathan * Add our interrupt routine to kernel's interrupt chain & enable it 711*291a2b48SSukumar Swaminathan * If MSI is enabled this will cause Solaris to program the MSI address 712*291a2b48SSukumar Swaminathan * and data registers in PCI config space 713fcf3ce44SJohn Forte */ 714fcf3ce44SJohn Forte if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 715fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 716fcf3ce44SJohn Forte "Unable to add interrupt(s)."); 717fcf3ce44SJohn Forte 718fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 719fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 720fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 721fcf3ce44SJohn Forte 722fcf3ce44SJohn Forte return (EIO); 723fcf3ce44SJohn Forte } 724fcf3ce44SJohn Forte 725fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_CFGPORT); 726fcf3ce44SJohn Forte (void) emlxs_mb_config_port(hba, mb, sli_mode, key); 727*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 728fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 729*291a2b48SSukumar Swaminathan "Unable to configure port. " 730*291a2b48SSukumar Swaminathan "Mailbox cmd=%x status=%x slimode=%d key=%x", 731*291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus, sli_mode, key); 732fcf3ce44SJohn Forte 733fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 734*291a2b48SSukumar Swaminathan for (sli_mode--; sli_mode > 0; sli_mode--) { 735*291a2b48SSukumar Swaminathan /* Check if sli_mode is supported by this adapter */ 736*291a2b48SSukumar Swaminathan if (hba->model_info.sli_mask & 737*291a2b48SSukumar Swaminathan EMLXS_SLI_MASK(sli_mode)) { 738*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI_MASK(sli_mode); 739*291a2b48SSukumar Swaminathan break; 740*291a2b48SSukumar Swaminathan } 741*291a2b48SSukumar Swaminathan } 742fcf3ce44SJohn Forte 743*291a2b48SSukumar Swaminathan if (sli_mode) { 744fcf3ce44SJohn Forte /* Clean up */ 745fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 746fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 747fcf3ce44SJohn Forte 748fcf3ce44SJohn Forte fw_check = 0; 749fcf3ce44SJohn Forte 750fcf3ce44SJohn Forte goto reset; 751fcf3ce44SJohn Forte } 752*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */ 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte hba->flag &= ~FC_SLIM2_MODE; 755fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 756fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 757fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 758fcf3ce44SJohn Forte 759fcf3ce44SJohn Forte return (EIO); 760fcf3ce44SJohn Forte } 761fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 762fcf3ce44SJohn Forte /* Check if SLI3 mode was achieved */ 763*291a2b48SSukumar Swaminathan if (mb->un.varCfgPort.rMA && 764*291a2b48SSukumar Swaminathan (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) { 765fcf3ce44SJohn Forte 766fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT 767fcf3ce44SJohn Forte if (mb->un.varCfgPort.vpi_max > 1) { 768fcf3ce44SJohn Forte hba->flag |= FC_NPIV_ENABLED; 769fcf3ce44SJohn Forte 770fcf3ce44SJohn Forte if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 771*291a2b48SSukumar Swaminathan hba->vpi_max = 772*291a2b48SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 773fcf3ce44SJohn Forte MAX_VPORTS - 1); 774fcf3ce44SJohn Forte } else { 775*291a2b48SSukumar Swaminathan hba->vpi_max = 776*291a2b48SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 777fcf3ce44SJohn Forte MAX_VPORTS_LIMITED - 1); 778fcf3ce44SJohn Forte } 779fcf3ce44SJohn Forte } 780*291a2b48SSukumar Swaminathan 781*291a2b48SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5) 782*291a2b48SSukumar Swaminathan hba->fca_tran->fca_num_npivports = 783*291a2b48SSukumar Swaminathan (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0; 784*291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */ 785*291a2b48SSukumar Swaminathan 786*291a2b48SSukumar Swaminathan #endif /* NPIV_SUPPORT */ 787fcf3ce44SJohn Forte 788fcf3ce44SJohn Forte if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 789fcf3ce44SJohn Forte hba->flag |= FC_HBQ_ENABLED; 790fcf3ce44SJohn Forte } 791*291a2b48SSukumar Swaminathan 792fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 793fcf3ce44SJohn Forte "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 794fcf3ce44SJohn Forte } else { 795fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 796fcf3ce44SJohn Forte "SLI2 mode: flag=%x", hba->flag); 797*291a2b48SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 798*291a2b48SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 799*291a2b48SSukumar Swaminathan hba->sli_mode = sli_mode; 800fcf3ce44SJohn Forte } 801*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */ 802fcf3ce44SJohn Forte 803fcf3ce44SJohn Forte /* Get and save the current firmware version (based on sli_mode) */ 804fcf3ce44SJohn Forte emlxs_decode_firmware_rev(hba, vpd); 805fcf3ce44SJohn Forte 806fcf3ce44SJohn Forte emlxs_pcix_mxr_update(hba, 0); 807fcf3ce44SJohn Forte 808fcf3ce44SJohn Forte /* 809fcf3ce44SJohn Forte * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 810fcf3ce44SJohn Forte */ 811fcf3ce44SJohn Forte mp = 0; 812fcf3ce44SJohn Forte mp1 = 0; 813*291a2b48SSukumar Swaminathan if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) || 814*291a2b48SSukumar Swaminathan ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0)) { 815fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 816fcf3ce44SJohn Forte "Unable to allocate diag buffers."); 817fcf3ce44SJohn Forte 818fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 819fcf3ce44SJohn Forte 820fcf3ce44SJohn Forte if (mp) { 821fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 822fcf3ce44SJohn Forte } 823fcf3ce44SJohn Forte if (mp1) { 824fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 825fcf3ce44SJohn Forte } 826*291a2b48SSukumar Swaminathan 827fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 828fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 829fcf3ce44SJohn Forte 830fcf3ce44SJohn Forte return (ENOMEM); 831fcf3ce44SJohn Forte } 832*291a2b48SSukumar Swaminathan 833fcf3ce44SJohn Forte bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 834fcf3ce44SJohn Forte MEM_ELSBUF_SIZE); 835fcf3ce44SJohn Forte emlxs_mpdata_sync(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 836fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 837fcf3ce44SJohn Forte 838fcf3ce44SJohn Forte bzero(mp1->virt, MEM_ELSBUF_SIZE); 839fcf3ce44SJohn Forte emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 840fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 841fcf3ce44SJohn Forte 842fcf3ce44SJohn Forte (void) emlxs_mb_run_biu_diag(hba, mb, mp->phys, mp1->phys); 843fcf3ce44SJohn Forte 844*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 845fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 846fcf3ce44SJohn Forte "Unable to run BIU diag. Mailbox cmd=%x status=%x", 847fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 848fcf3ce44SJohn Forte 849fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 850fcf3ce44SJohn Forte 851fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 852fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 853fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 854fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 855fcf3ce44SJohn Forte 856fcf3ce44SJohn Forte return (EIO); 857fcf3ce44SJohn Forte } 858*291a2b48SSukumar Swaminathan 859fcf3ce44SJohn Forte emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 860fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte outptr = mp->virt; 863fcf3ce44SJohn Forte inptr = mp1->virt; 864fcf3ce44SJohn Forte 865fcf3ce44SJohn Forte for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 866fcf3ce44SJohn Forte if (*outptr++ != *inptr++) { 867fcf3ce44SJohn Forte outptr--; 868fcf3ce44SJohn Forte inptr--; 869fcf3ce44SJohn Forte 870fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 871*291a2b48SSukumar Swaminathan "BIU diagnostic failed. " 872*291a2b48SSukumar Swaminathan "offset %x value %x should be %x.", 873*291a2b48SSukumar Swaminathan i, (uint32_t)*inptr, (uint32_t)*outptr); 874fcf3ce44SJohn Forte 875fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 876fcf3ce44SJohn Forte 877fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 878fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 879fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 880fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 881fcf3ce44SJohn Forte 882fcf3ce44SJohn Forte return (EIO); 883fcf3ce44SJohn Forte } 884fcf3ce44SJohn Forte } 885fcf3ce44SJohn Forte 886fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 887fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 888fcf3ce44SJohn Forte 889fcf3ce44SJohn Forte /* 890fcf3ce44SJohn Forte * Setup and issue mailbox CONFIGURE RING command 891fcf3ce44SJohn Forte */ 892fcf3ce44SJohn Forte for (i = 0; i < (uint32_t)hba->ring_count; i++) { 893*291a2b48SSukumar Swaminathan /* 894*291a2b48SSukumar Swaminathan * Initialize cmd/rsp ring pointers 895*291a2b48SSukumar Swaminathan */ 896*291a2b48SSukumar Swaminathan rp = &hba->ring[i]; 897*291a2b48SSukumar Swaminathan 898*291a2b48SSukumar Swaminathan rp->hba = hba; 899*291a2b48SSukumar Swaminathan rp->ringno = (uint8_t)i; 900*291a2b48SSukumar Swaminathan 901*291a2b48SSukumar Swaminathan rp->fc_iocbhd = 0; 902*291a2b48SSukumar Swaminathan rp->fc_iocbtl = 0; 903*291a2b48SSukumar Swaminathan rp->fc_cmdidx = 0; 904*291a2b48SSukumar Swaminathan rp->fc_rspidx = 0; 905*291a2b48SSukumar Swaminathan rp->fc_iotag = 1; /* Used for pkt io */ 906*291a2b48SSukumar Swaminathan rp->fc_abort_iotag = rp->max_iotag; /* Used for abort or */ 907*291a2b48SSukumar Swaminathan /* close XRI iotags */ 908fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_CFGRING); 909fcf3ce44SJohn Forte emlxs_mb_config_ring(hba, i, mb); 910*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 911*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 912fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 913*291a2b48SSukumar Swaminathan "Unable to configure ring. " 914*291a2b48SSukumar Swaminathan "Mailbox cmd=%x status=%x", 915*291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 916fcf3ce44SJohn Forte 917fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 918fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 919fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 920fcf3ce44SJohn Forte 921fcf3ce44SJohn Forte return (EIO); 922fcf3ce44SJohn Forte } 923fcf3ce44SJohn Forte } 924fcf3ce44SJohn Forte 925fcf3ce44SJohn Forte /* 926fcf3ce44SJohn Forte * Setup link timers 927fcf3ce44SJohn Forte */ 928fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_INITLINK); 929fcf3ce44SJohn Forte emlxs_mb_config_link(hba, mb); 930*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 931fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 932fcf3ce44SJohn Forte "Unable to configure link. Mailbox cmd=%x status=%x", 933fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 934fcf3ce44SJohn Forte 935fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 936fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 937fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 938fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 939fcf3ce44SJohn Forte 940fcf3ce44SJohn Forte return (EIO); 941fcf3ce44SJohn Forte } 942fcf3ce44SJohn Forte #ifdef MAX_RRDY_PATCH 943fcf3ce44SJohn Forte /* Set MAX_RRDY if one is provided */ 944fcf3ce44SJohn Forte if (cfg[CFG_MAX_RRDY].current) { 945*291a2b48SSukumar Swaminathan emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00060412, 946fcf3ce44SJohn Forte cfg[CFG_MAX_RRDY].current); 947fcf3ce44SJohn Forte 948*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 949*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 950fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 951fcf3ce44SJohn Forte "MAX_RRDY: Unable to set. status=%x value=%d", 952fcf3ce44SJohn Forte mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 953fcf3ce44SJohn Forte } else { 954fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 955fcf3ce44SJohn Forte "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 956fcf3ce44SJohn Forte } 957fcf3ce44SJohn Forte } 958*291a2b48SSukumar Swaminathan #endif /* MAX_RRDY_PATCH */ 959fcf3ce44SJohn Forte 960fcf3ce44SJohn Forte /* 961fcf3ce44SJohn Forte * We need to get login parameters for NID 962fcf3ce44SJohn Forte */ 963fcf3ce44SJohn Forte (void) emlxs_mb_read_sparam(hba, mb); 964*291a2b48SSukumar Swaminathan mp = (MATCHMAP *)(((MAILBOXQ *)mb)->bp); 965*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 966fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 967fcf3ce44SJohn Forte "Unable to read parameters. Mailbox cmd=%x status=%x", 968fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 969fcf3ce44SJohn Forte 970fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 971fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 972fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 973fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 974fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 975fcf3ce44SJohn Forte 976fcf3ce44SJohn Forte return (EIO); 977fcf3ce44SJohn Forte } 978*291a2b48SSukumar Swaminathan 979fcf3ce44SJohn Forte /* Free the buffer since we were polling */ 980fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 981fcf3ce44SJohn Forte 982fcf3ce44SJohn Forte /* If no serial number in VPD data, then use the WWPN */ 983fcf3ce44SJohn Forte if (vpd->serial_num[0] == 0) { 984fcf3ce44SJohn Forte outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 985fcf3ce44SJohn Forte for (i = 0; i < 12; i++) { 986fcf3ce44SJohn Forte status = *outptr++; 987fcf3ce44SJohn Forte j = ((status & 0xf0) >> 4); 988fcf3ce44SJohn Forte if (j <= 9) { 989fcf3ce44SJohn Forte vpd->serial_num[i] = 990fcf3ce44SJohn Forte (char)((uint8_t)'0' + (uint8_t)j); 991fcf3ce44SJohn Forte } else { 992fcf3ce44SJohn Forte vpd->serial_num[i] = 993fcf3ce44SJohn Forte (char)((uint8_t)'A' + (uint8_t)(j - 10)); 994fcf3ce44SJohn Forte } 995fcf3ce44SJohn Forte 996fcf3ce44SJohn Forte i++; 997fcf3ce44SJohn Forte j = (status & 0xf); 998fcf3ce44SJohn Forte if (j <= 9) { 999fcf3ce44SJohn Forte vpd->serial_num[i] = 1000fcf3ce44SJohn Forte (char)((uint8_t)'0' + (uint8_t)j); 1001fcf3ce44SJohn Forte } else { 1002fcf3ce44SJohn Forte vpd->serial_num[i] = 1003fcf3ce44SJohn Forte (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1004fcf3ce44SJohn Forte } 1005fcf3ce44SJohn Forte } 1006fcf3ce44SJohn Forte 1007fcf3ce44SJohn Forte /* 1008*291a2b48SSukumar Swaminathan * Set port number and port index to zero 1009fcf3ce44SJohn Forte * The WWN's are unique to each port and therefore port_num 1010*291a2b48SSukumar Swaminathan * must equal zero. This effects the hba_fru_details structure 1011*291a2b48SSukumar Swaminathan * in fca_bind_port() 1012fcf3ce44SJohn Forte */ 1013fcf3ce44SJohn Forte vpd->port_num[0] = 0; 1014fcf3ce44SJohn Forte vpd->port_index = 0; 1015fcf3ce44SJohn Forte } 1016*291a2b48SSukumar Swaminathan 1017*291a2b48SSukumar Swaminathan /* 1018*291a2b48SSukumar Swaminathan * Make first attempt to set a port index 1019*291a2b48SSukumar Swaminathan * Check if this is a multifunction adapter 1020*291a2b48SSukumar Swaminathan */ 1021fcf3ce44SJohn Forte if ((vpd->port_index == -1) && 1022fcf3ce44SJohn Forte (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 1023fcf3ce44SJohn Forte char *buffer; 1024fcf3ce44SJohn Forte int32_t i; 1025fcf3ce44SJohn Forte 1026*291a2b48SSukumar Swaminathan /* 1027*291a2b48SSukumar Swaminathan * The port address looks like this: 1028*291a2b48SSukumar Swaminathan * 1 - for port index 0 1029*291a2b48SSukumar Swaminathan * 1,1 - for port index 1 1030*291a2b48SSukumar Swaminathan * 1,2 - for port index 2 1031*291a2b48SSukumar Swaminathan */ 1032fcf3ce44SJohn Forte buffer = ddi_get_name_addr(hba->dip); 1033fcf3ce44SJohn Forte 1034fcf3ce44SJohn Forte if (buffer) { 1035fcf3ce44SJohn Forte vpd->port_index = 0; 1036fcf3ce44SJohn Forte 1037fcf3ce44SJohn Forte /* Reverse scan for a comma */ 1038fcf3ce44SJohn Forte for (i = strlen(buffer) - 1; i > 0; i--) { 1039fcf3ce44SJohn Forte if (buffer[i] == ',') { 1040fcf3ce44SJohn Forte /* Comma found - set index now */ 1041fcf3ce44SJohn Forte vpd->port_index = 1042fcf3ce44SJohn Forte emlxs_strtol(&buffer[i + 1], 10); 1043fcf3ce44SJohn Forte break; 1044fcf3ce44SJohn Forte } 1045fcf3ce44SJohn Forte } 1046fcf3ce44SJohn Forte } 1047fcf3ce44SJohn Forte } 1048*291a2b48SSukumar Swaminathan 1049fcf3ce44SJohn Forte /* Make final attempt to set a port index */ 1050fcf3ce44SJohn Forte if (vpd->port_index == -1) { 1051fcf3ce44SJohn Forte dev_info_t *p_dip; 1052fcf3ce44SJohn Forte dev_info_t *c_dip; 1053fcf3ce44SJohn Forte 1054fcf3ce44SJohn Forte p_dip = ddi_get_parent(hba->dip); 1055fcf3ce44SJohn Forte c_dip = ddi_get_child(p_dip); 1056fcf3ce44SJohn Forte 1057fcf3ce44SJohn Forte vpd->port_index = 0; 1058fcf3ce44SJohn Forte while (c_dip && (hba->dip != c_dip)) { 1059fcf3ce44SJohn Forte c_dip = ddi_get_next_sibling(c_dip); 1060fcf3ce44SJohn Forte vpd->port_index++; 1061fcf3ce44SJohn Forte } 1062fcf3ce44SJohn Forte } 1063*291a2b48SSukumar Swaminathan 1064fcf3ce44SJohn Forte if (vpd->port_num[0] == 0) { 1065fcf3ce44SJohn Forte if (hba->model_info.channels > 1) { 1066fcf3ce44SJohn Forte (void) sprintf(vpd->port_num, "%d", vpd->port_index); 1067fcf3ce44SJohn Forte } 1068fcf3ce44SJohn Forte } 1069*291a2b48SSukumar Swaminathan 1070fcf3ce44SJohn Forte if (vpd->id[0] == 0) { 1071fcf3ce44SJohn Forte (void) strcpy(vpd->id, hba->model_info.model_desc); 1072fcf3ce44SJohn Forte } 1073*291a2b48SSukumar Swaminathan 1074fcf3ce44SJohn Forte if (vpd->manufacturer[0] == 0) { 1075fcf3ce44SJohn Forte (void) strcpy(vpd->manufacturer, hba->model_info.manufacturer); 1076fcf3ce44SJohn Forte } 1077*291a2b48SSukumar Swaminathan 1078fcf3ce44SJohn Forte if (vpd->part_num[0] == 0) { 1079fcf3ce44SJohn Forte (void) strcpy(vpd->part_num, hba->model_info.model); 1080fcf3ce44SJohn Forte } 1081*291a2b48SSukumar Swaminathan 1082fcf3ce44SJohn Forte if (vpd->model_desc[0] == 0) { 1083fcf3ce44SJohn Forte (void) strcpy(vpd->model_desc, hba->model_info.model_desc); 1084fcf3ce44SJohn Forte } 1085*291a2b48SSukumar Swaminathan 1086fcf3ce44SJohn Forte if (vpd->model[0] == 0) { 1087fcf3ce44SJohn Forte (void) strcpy(vpd->model, hba->model_info.model); 1088fcf3ce44SJohn Forte } 1089*291a2b48SSukumar Swaminathan 1090fcf3ce44SJohn Forte if (vpd->prog_types[0] == 0) { 1091fcf3ce44SJohn Forte emlxs_build_prog_types(hba, vpd->prog_types); 1092fcf3ce44SJohn Forte } 1093*291a2b48SSukumar Swaminathan 1094fcf3ce44SJohn Forte /* Create the symbolic names */ 1095fcf3ce44SJohn Forte (void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s", 1096fcf3ce44SJohn Forte hba->model_info.model, hba->vpd.fw_version, emlxs_version, 1097fcf3ce44SJohn Forte (char *)utsname.nodename); 1098fcf3ce44SJohn Forte 1099fcf3ce44SJohn Forte (void) sprintf(hba->spn, 1100fcf3ce44SJohn Forte "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1101fcf3ce44SJohn Forte hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1102fcf3ce44SJohn Forte hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1103fcf3ce44SJohn Forte hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1104fcf3ce44SJohn Forte 1105fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1106fcf3ce44SJohn Forte if ((hba->sparam.portName.nameType != NAME_IEEE) || 1107fcf3ce44SJohn Forte (hba->sparam.portName.IEEEextMsn != 0) || 1108fcf3ce44SJohn Forte (hba->sparam.portName.IEEEextLsb != 0)) { 1109fcf3ce44SJohn Forte 1110fcf3ce44SJohn Forte cfg[CFG_NETWORK_ON].current = 0; 1111fcf3ce44SJohn Forte 1112fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1113fcf3ce44SJohn Forte "WWPN doesn't conform to IP profile: nameType=%x", 1114fcf3ce44SJohn Forte hba->sparam.portName.nameType); 1115fcf3ce44SJohn Forte } 1116*291a2b48SSukumar Swaminathan 1117fcf3ce44SJohn Forte /* Issue CONFIG FARP */ 1118fcf3ce44SJohn Forte emlxs_mb_config_farp(hba, mb); 1119*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1120*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 1121fcf3ce44SJohn Forte /* 1122fcf3ce44SJohn Forte * Let it go through even if failed. 1123fcf3ce44SJohn Forte */ 1124fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1125*291a2b48SSukumar Swaminathan "Unable to configure FARP. " 1126*291a2b48SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1127*291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1128fcf3ce44SJohn Forte } 1129fcf3ce44SJohn Forte } 1130fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 1131fcf3ce44SJohn Forte /* Configure MSI map if required */ 1132fcf3ce44SJohn Forte if (hba->intr_count > 1) { 1133fcf3ce44SJohn Forte emlxs_mb_config_msix(hba, mb, hba->intr_map, hba->intr_count); 1134fcf3ce44SJohn Forte 1135*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) == 1136*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 1137fcf3ce44SJohn Forte goto msi_configured; 1138fcf3ce44SJohn Forte } 1139*291a2b48SSukumar Swaminathan 1140fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1141fcf3ce44SJohn Forte "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 1142fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1143fcf3ce44SJohn Forte 1144fcf3ce44SJohn Forte emlxs_mb_config_msi(hba, mb, hba->intr_map, hba->intr_count); 1145fcf3ce44SJohn Forte 1146*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) == 1147*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 1148fcf3ce44SJohn Forte goto msi_configured; 1149fcf3ce44SJohn Forte } 1150*291a2b48SSukumar Swaminathan 1151*291a2b48SSukumar Swaminathan 1152fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1153fcf3ce44SJohn Forte "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 1154fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1155fcf3ce44SJohn Forte 1156fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1157fcf3ce44SJohn Forte "Attempting single interrupt mode..."); 1158fcf3ce44SJohn Forte 1159fcf3ce44SJohn Forte /* First cleanup old interrupts */ 1160fcf3ce44SJohn Forte (void) emlxs_msi_remove(hba); 1161fcf3ce44SJohn Forte (void) emlxs_msi_uninit(hba); 1162fcf3ce44SJohn Forte 1163fcf3ce44SJohn Forte status = emlxs_msi_init(hba, 1); 1164fcf3ce44SJohn Forte 1165fcf3ce44SJohn Forte if (status != DDI_SUCCESS) { 1166fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1167fcf3ce44SJohn Forte "Unable to initialize interrupt. status=%d", 1168fcf3ce44SJohn Forte status); 1169fcf3ce44SJohn Forte 1170fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1171fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1172fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1173fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte return (EIO); 1176fcf3ce44SJohn Forte } 1177*291a2b48SSukumar Swaminathan 1178fcf3ce44SJohn Forte /* 1179*291a2b48SSukumar Swaminathan * Reset adapter - The adapter needs to be reset because 1180*291a2b48SSukumar Swaminathan * the bus cannot handle the MSI change without handshaking 1181*291a2b48SSukumar Swaminathan * with the adapter again 1182fcf3ce44SJohn Forte */ 1183fcf3ce44SJohn Forte 1184fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1185fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1186fcf3ce44SJohn Forte fw_check = 0; 1187fcf3ce44SJohn Forte goto reset; 1188fcf3ce44SJohn Forte } 1189*291a2b48SSukumar Swaminathan 1190fcf3ce44SJohn Forte msi_configured: 1191fcf3ce44SJohn Forte 1192*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte /* 1195fcf3ce44SJohn Forte * We always disable the firmware traffic cop feature 1196fcf3ce44SJohn Forte */ 1197fcf3ce44SJohn Forte if (emlxs_disable_traffic_cop) { 1198*291a2b48SSukumar Swaminathan emlxs_disable_tc(hba, (MAILBOX *)mb); 1199*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1200*291a2b48SSukumar Swaminathan MBX_SUCCESS) { 1201fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1202*291a2b48SSukumar Swaminathan "Unable to disable traffic cop. " 1203*291a2b48SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1204*291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1205fcf3ce44SJohn Forte 1206fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1207fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1208fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1209fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1210fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1211fcf3ce44SJohn Forte 1212fcf3ce44SJohn Forte return (EIO); 1213fcf3ce44SJohn Forte } 1214fcf3ce44SJohn Forte } 1215*291a2b48SSukumar Swaminathan 1216*291a2b48SSukumar Swaminathan emlxs_mb_read_config(hba, (MAILBOX *)mb); 1217*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1218fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1219fcf3ce44SJohn Forte "Unable to read configuration. Mailbox cmd=%x status=%x", 1220fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1221fcf3ce44SJohn Forte 1222fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1223fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1224fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1225fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1226fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1227fcf3ce44SJohn Forte 1228fcf3ce44SJohn Forte return (EIO); 1229fcf3ce44SJohn Forte } 1230*291a2b48SSukumar Swaminathan 1231fcf3ce44SJohn Forte /* Save the link speed capabilities */ 1232fcf3ce44SJohn Forte vpd->link_speed = mb->un.varRdConfig.lmt; 1233fcf3ce44SJohn Forte emlxs_process_link_speed(hba); 1234fcf3ce44SJohn Forte 1235fcf3ce44SJohn Forte /* Set the io throttle */ 1236fcf3ce44SJohn Forte hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 1237fcf3ce44SJohn Forte 1238fcf3ce44SJohn Forte /* Set the max node count */ 1239fcf3ce44SJohn Forte if (cfg[CFG_NUM_NODES].current > 0) { 1240fcf3ce44SJohn Forte hba->max_nodes = 1241*291a2b48SSukumar Swaminathan min(cfg[CFG_NUM_NODES].current, 1242*291a2b48SSukumar Swaminathan mb->un.varRdConfig.max_rpi); 1243fcf3ce44SJohn Forte } else { 1244fcf3ce44SJohn Forte hba->max_nodes = mb->un.varRdConfig.max_rpi; 1245fcf3ce44SJohn Forte } 1246fcf3ce44SJohn Forte 1247*291a2b48SSukumar Swaminathan /* Register for async events */ 1248*291a2b48SSukumar Swaminathan emlxs_mb_async_event(hba, mb); 1249*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1250*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1251*291a2b48SSukumar Swaminathan "Async events disabled. Mailbox status=%x", 1252*291a2b48SSukumar Swaminathan mb->mbxStatus); 1253*291a2b48SSukumar Swaminathan } else { 1254*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1255*291a2b48SSukumar Swaminathan "Async events enabled."); 1256*291a2b48SSukumar Swaminathan hba->flag |= FC_ASYNC_EVENTS; 1257*291a2b48SSukumar Swaminathan } 1258fcf3ce44SJohn Forte 1259*291a2b48SSukumar Swaminathan emlxs_ffstate_change(hba, FC_LINK_DOWN); 1260fcf3ce44SJohn Forte 1261*291a2b48SSukumar Swaminathan emlxs_intr_initialize(hba); 1262fcf3ce44SJohn Forte 1263fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 1264fcf3ce44SJohn Forte 1265fcf3ce44SJohn Forte if (hba->flag & FC_HBQ_ENABLED) { 1266fcf3ce44SJohn Forte if (hba->tgt_mode) { 1267fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 1268fcf3ce44SJohn Forte return (ENOMEM); 1269fcf3ce44SJohn Forte } 1270fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1271fcf3ce44SJohn Forte "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1272fcf3ce44SJohn Forte } 1273*291a2b48SSukumar Swaminathan 1274fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1275fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 1276fcf3ce44SJohn Forte return (ENOMEM); 1277fcf3ce44SJohn Forte } 1278fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1279fcf3ce44SJohn Forte "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1280fcf3ce44SJohn Forte } 1281*291a2b48SSukumar Swaminathan 1282fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 1283fcf3ce44SJohn Forte return (ENOMEM); 1284fcf3ce44SJohn Forte } 1285fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1286fcf3ce44SJohn Forte "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1287fcf3ce44SJohn Forte 1288fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 1289fcf3ce44SJohn Forte return (ENOMEM); 1290fcf3ce44SJohn Forte } 1291fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1292fcf3ce44SJohn Forte "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1293fcf3ce44SJohn Forte } else 1294*291a2b48SSukumar Swaminathan #endif /* SLI3_SUPPORT */ 1295fcf3ce44SJohn Forte { 1296fcf3ce44SJohn Forte if (hba->tgt_mode) { 1297fcf3ce44SJohn Forte /* Post the FCT unsol buffers */ 1298fcf3ce44SJohn Forte rp = &hba->ring[FC_FCT_RING]; 1299fcf3ce44SJohn Forte for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 1300fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1301fcf3ce44SJohn Forte } 1302fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1303fcf3ce44SJohn Forte "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1304fcf3ce44SJohn Forte } 1305*291a2b48SSukumar Swaminathan 1306fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1307fcf3ce44SJohn Forte /* Post the IP unsol buffers */ 1308fcf3ce44SJohn Forte rp = &hba->ring[FC_IP_RING]; 1309fcf3ce44SJohn Forte for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 1310fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1311fcf3ce44SJohn Forte } 1312fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1313fcf3ce44SJohn Forte "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1314fcf3ce44SJohn Forte } 1315*291a2b48SSukumar Swaminathan 1316fcf3ce44SJohn Forte /* Post the ELS unsol buffers */ 1317fcf3ce44SJohn Forte rp = &hba->ring[FC_ELS_RING]; 1318fcf3ce44SJohn Forte for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 1319fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1320fcf3ce44SJohn Forte } 1321fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1322fcf3ce44SJohn Forte "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1323fcf3ce44SJohn Forte 1324fcf3ce44SJohn Forte 1325fcf3ce44SJohn Forte /* Post the CT unsol buffers */ 1326fcf3ce44SJohn Forte rp = &hba->ring[FC_CT_RING]; 1327fcf3ce44SJohn Forte for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 1328fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1329fcf3ce44SJohn Forte } 1330fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1331fcf3ce44SJohn Forte "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1332fcf3ce44SJohn Forte } 1333fcf3ce44SJohn Forte 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte /* 1336*291a2b48SSukumar Swaminathan * Setup and issue mailbox INITIALIZE LINK command At this point, 1337*291a2b48SSukumar Swaminathan * the interrupt will be generated by the HW 1338fcf3ce44SJohn Forte */ 1339*291a2b48SSukumar Swaminathan emlxs_mb_init_link(hba, 1340*291a2b48SSukumar Swaminathan mb, cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1341fcf3ce44SJohn Forte 1342*291a2b48SSukumar Swaminathan rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0); 1343fcf3ce44SJohn Forte 1344fcf3ce44SJohn Forte if (rval != MBX_SUCCESS && rval != MBX_BUSY) { 1345fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1346fcf3ce44SJohn Forte "Unable to initialize link. Mailbox cmd=%x status=%x", 1347fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1348fcf3ce44SJohn Forte 1349fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1350fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1351fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1352fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1353fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1354fcf3ce44SJohn Forte 1355fcf3ce44SJohn Forte return (EIO); 1356fcf3ce44SJohn Forte } 1357*291a2b48SSukumar Swaminathan 1358fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1359fcf3ce44SJohn Forte 1360fcf3ce44SJohn Forte /* 1361fcf3ce44SJohn Forte * Enable link attention interrupt 1362fcf3ce44SJohn Forte */ 1363*291a2b48SSukumar Swaminathan emlxs_enable_latt(hba); 1364fcf3ce44SJohn Forte 1365fcf3ce44SJohn Forte /* Wait for link to come up */ 1366fcf3ce44SJohn Forte i = cfg[CFG_LINKUP_DELAY].current; 1367fcf3ce44SJohn Forte while (i && (hba->state < FC_LINK_UP)) { 1368fcf3ce44SJohn Forte /* Check for hardware error */ 1369fcf3ce44SJohn Forte if (hba->state == FC_ERROR) { 1370fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1371fcf3ce44SJohn Forte "Adapter error.", mb->mbxCommand, mb->mbxStatus); 1372fcf3ce44SJohn Forte 1373fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1374fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1375fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1376fcf3ce44SJohn Forte 1377fcf3ce44SJohn Forte return (EIO); 1378fcf3ce44SJohn Forte } 1379*291a2b48SSukumar Swaminathan 1380fcf3ce44SJohn Forte DELAYMS(1000); 1381fcf3ce44SJohn Forte i--; 1382fcf3ce44SJohn Forte } 1383fcf3ce44SJohn Forte 1384fcf3ce44SJohn Forte out: 1385fcf3ce44SJohn Forte 1386fcf3ce44SJohn Forte /* 1387fcf3ce44SJohn Forte * The leadvile driver will now handle the FLOGI at the driver level 1388fcf3ce44SJohn Forte */ 1389fcf3ce44SJohn Forte 1390fcf3ce44SJohn Forte return (0); 1391*291a2b48SSukumar Swaminathan } /* emlxs_ffinit() */ 1392fcf3ce44SJohn Forte 1393fcf3ce44SJohn Forte 1394fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 1395fcf3ce44SJohn Forte 1396fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 1397fcf3ce44SJohn Forte int32_t 1398fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 1399fcf3ce44SJohn Forte { 1400fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1401fcf3ce44SJohn Forte int32_t pass = 0; 1402fcf3ce44SJohn Forte int32_t type = 0; 1403fcf3ce44SJohn Forte char s_type[16]; 1404fcf3ce44SJohn Forte int32_t types; 1405fcf3ce44SJohn Forte int32_t count; 1406fcf3ce44SJohn Forte int32_t nintrs; 1407fcf3ce44SJohn Forte int32_t mode; 1408fcf3ce44SJohn Forte int32_t actual; 1409fcf3ce44SJohn Forte int32_t new_actual; 1410fcf3ce44SJohn Forte int32_t i; 1411fcf3ce44SJohn Forte int32_t ret; 1412fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 1413fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL; 1414fcf3ce44SJohn Forte uint32_t *intr_pri = NULL; 1415fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 1416fcf3ce44SJohn Forte int32_t hilevel_pri; 1417fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1418fcf3ce44SJohn Forte char buf[64]; 1419fcf3ce44SJohn Forte 1420fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1421fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max)); 1422fcf3ce44SJohn Forte } 1423*291a2b48SSukumar Swaminathan 1424fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) { 1425fcf3ce44SJohn Forte return (DDI_SUCCESS); 1426fcf3ce44SJohn Forte } 1427*291a2b48SSukumar Swaminathan 1428fcf3ce44SJohn Forte /* Set max interrupt count if not specified */ 1429fcf3ce44SJohn Forte if (max == 0) { 1430fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) || 1431fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) { 1432fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS; 1433fcf3ce44SJohn Forte } else { 1434fcf3ce44SJohn Forte max = 1; 1435fcf3ce44SJohn Forte } 1436fcf3ce44SJohn Forte } 1437*291a2b48SSukumar Swaminathan 1438fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */ 1439fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 1440fcf3ce44SJohn Forte max = hba->model_info.intr_limit; 1441fcf3ce44SJohn Forte } 1442*291a2b48SSukumar Swaminathan 1443fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */ 1444fcf3ce44SJohn Forte types = 0; 1445fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types); 1446fcf3ce44SJohn Forte 1447fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) { 1448fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1449fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 1450fcf3ce44SJohn Forte 1451fcf3ce44SJohn Forte /* Default to fixed type */ 1452fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED; 1453fcf3ce44SJohn Forte } 1454*291a2b48SSukumar Swaminathan 1455fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */ 1456fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) { 1457fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 1458fcf3ce44SJohn Forte } 1459*291a2b48SSukumar Swaminathan 1460fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */ 1461fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) || 1462fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) { 1463fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1464fcf3ce44SJohn Forte } 1465*291a2b48SSukumar Swaminathan 1466fcf3ce44SJohn Forte begin: 1467fcf3ce44SJohn Forte 1468fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */ 1469fcf3ce44SJohn Forte type = 0; 1470fcf3ce44SJohn Forte 1471fcf3ce44SJohn Forte /* Check if MSIX is fully supported */ 1472fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) && 1473fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 1474fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1475fcf3ce44SJohn Forte nintrs = 0; 1476fcf3ce44SJohn Forte ret = 1477*291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, 1478*291a2b48SSukumar Swaminathan &nintrs); 1479fcf3ce44SJohn Forte 1480fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 1481fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX; 1482fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSIX"); 1483fcf3ce44SJohn Forte goto initialize; 1484fcf3ce44SJohn Forte } 1485fcf3ce44SJohn Forte } 1486*291a2b48SSukumar Swaminathan 1487fcf3ce44SJohn Forte /* Check if MSI is fully supported */ 1488fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) && 1489fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 1490fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1491fcf3ce44SJohn Forte nintrs = 0; 1492*291a2b48SSukumar Swaminathan ret = 1493*291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 1494fcf3ce44SJohn Forte 1495fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 1496fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI; 1497fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSI"); 1498fcf3ce44SJohn Forte goto initialize; 1499fcf3ce44SJohn Forte } 1500fcf3ce44SJohn Forte } 1501*291a2b48SSukumar Swaminathan 1502fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */ 1503fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) && 1504fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 1505fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1506fcf3ce44SJohn Forte nintrs = 0; 1507fcf3ce44SJohn Forte ret = 1508*291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, 1509*291a2b48SSukumar Swaminathan &nintrs); 1510fcf3ce44SJohn Forte 1511fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) { 1512fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED; 1513fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_FIXED"); 1514fcf3ce44SJohn Forte goto initialize; 1515fcf3ce44SJohn Forte } 1516fcf3ce44SJohn Forte } 1517*291a2b48SSukumar Swaminathan 1518fcf3ce44SJohn Forte goto init_failed; 1519fcf3ce44SJohn Forte 1520fcf3ce44SJohn Forte 1521fcf3ce44SJohn Forte initialize: 1522fcf3ce44SJohn Forte 1523fcf3ce44SJohn Forte pass++; 1524fcf3ce44SJohn Forte mode = 0; 1525fcf3ce44SJohn Forte actual = 0; 1526fcf3ce44SJohn Forte htable = NULL; 1527fcf3ce44SJohn Forte intr_pri = NULL; 1528fcf3ce44SJohn Forte intr_cap = NULL; 1529fcf3ce44SJohn Forte hilevel_pri = 0; 1530fcf3ce44SJohn Forte 1531fcf3ce44SJohn Forte if (pass == 1) { 1532fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1533*291a2b48SSukumar Swaminathan "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type, 1534*291a2b48SSukumar Swaminathan cfg[CFG_MSI_MODE].current, types, nintrs); 1535fcf3ce44SJohn Forte } 1536*291a2b48SSukumar Swaminathan 1537fcf3ce44SJohn Forte /* Validate interrupt count */ 1538fcf3ce44SJohn Forte count = min(nintrs, max); 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte if (count >= 8) { 1541fcf3ce44SJohn Forte count = 8; 1542fcf3ce44SJohn Forte } else if (count >= 4) { 1543fcf3ce44SJohn Forte count = 4; 1544fcf3ce44SJohn Forte } else if (count >= 2) { 1545fcf3ce44SJohn Forte count = 2; 1546fcf3ce44SJohn Forte } else { 1547fcf3ce44SJohn Forte count = 1; 1548fcf3ce44SJohn Forte } 1549fcf3ce44SJohn Forte 1550fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */ 1551fcf3ce44SJohn Forte htable = 1552*291a2b48SSukumar Swaminathan kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), 1553*291a2b48SSukumar Swaminathan KM_SLEEP); 1554fcf3ce44SJohn Forte 1555fcf3ce44SJohn Forte if (htable == NULL) { 1556fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1557fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt handle table"); 1558fcf3ce44SJohn Forte 1559fcf3ce44SJohn Forte goto init_failed; 1560fcf3ce44SJohn Forte } 1561*291a2b48SSukumar Swaminathan 1562fcf3ce44SJohn Forte /* Allocate 'count' interrupts */ 1563*291a2b48SSukumar Swaminathan ret = 1564*291a2b48SSukumar Swaminathan ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 1565fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL); 1566fcf3ce44SJohn Forte 1567fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1568fcf3ce44SJohn Forte "MSI: %s: count=%d actual=%d", s_type, count, actual); 1569fcf3ce44SJohn Forte 1570fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) { 1571fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1572fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret); 1573fcf3ce44SJohn Forte 1574fcf3ce44SJohn Forte goto init_failed; 1575fcf3ce44SJohn Forte } 1576*291a2b48SSukumar Swaminathan 1577fcf3ce44SJohn Forte if (actual != count) { 1578fcf3ce44SJohn Forte /* Validate actual count */ 1579fcf3ce44SJohn Forte if (actual >= 8) { 1580fcf3ce44SJohn Forte new_actual = 8; 1581fcf3ce44SJohn Forte } else if (actual >= 4) { 1582fcf3ce44SJohn Forte new_actual = 4; 1583fcf3ce44SJohn Forte } else if (actual >= 2) { 1584fcf3ce44SJohn Forte new_actual = 2; 1585fcf3ce44SJohn Forte } else { 1586fcf3ce44SJohn Forte new_actual = 1; 1587fcf3ce44SJohn Forte } 1588fcf3ce44SJohn Forte 1589fcf3ce44SJohn Forte if (new_actual < actual) { 1590fcf3ce44SJohn Forte /* Free extra handles */ 1591fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) { 1592fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 1593fcf3ce44SJohn Forte } 1594fcf3ce44SJohn Forte 1595fcf3ce44SJohn Forte actual = new_actual; 1596fcf3ce44SJohn Forte } 1597*291a2b48SSukumar Swaminathan 1598fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */ 1599fcf3ce44SJohn Forte new_htable = 1600fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 1601fcf3ce44SJohn Forte KM_SLEEP); 1602fcf3ce44SJohn Forte 1603fcf3ce44SJohn Forte if (new_htable == NULL) { 1604fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1605*291a2b48SSukumar Swaminathan "MSI: Unable to allocate new " 1606*291a2b48SSukumar Swaminathan "interrupt handle table"); 1607fcf3ce44SJohn Forte 1608fcf3ce44SJohn Forte goto init_failed; 1609fcf3ce44SJohn Forte } 1610*291a2b48SSukumar Swaminathan 1611fcf3ce44SJohn Forte /* Copy old array to new array */ 1612fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable, 1613fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t))); 1614fcf3ce44SJohn Forte 1615fcf3ce44SJohn Forte /* Free the old array */ 1616fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1617fcf3ce44SJohn Forte 1618fcf3ce44SJohn Forte htable = new_htable; 1619fcf3ce44SJohn Forte count = actual; 1620fcf3ce44SJohn Forte } 1621*291a2b48SSukumar Swaminathan 1622fcf3ce44SJohn Forte /* Allocate interrupt priority table */ 1623fcf3ce44SJohn Forte intr_pri = 1624fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 1625fcf3ce44SJohn Forte KM_SLEEP); 1626fcf3ce44SJohn Forte 1627fcf3ce44SJohn Forte if (intr_pri == NULL) { 1628fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1629fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt priority table"); 1630fcf3ce44SJohn Forte 1631fcf3ce44SJohn Forte goto init_failed; 1632fcf3ce44SJohn Forte } 1633*291a2b48SSukumar Swaminathan 1634fcf3ce44SJohn Forte /* Allocate interrupt capability table */ 1635fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 1636fcf3ce44SJohn Forte 1637fcf3ce44SJohn Forte if (intr_cap == NULL) { 1638fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1639fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt capability table"); 1640fcf3ce44SJohn Forte 1641fcf3ce44SJohn Forte goto init_failed; 1642fcf3ce44SJohn Forte } 1643*291a2b48SSukumar Swaminathan 1644fcf3ce44SJohn Forte /* Get minimum hilevel priority */ 1645fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri(); 1646fcf3ce44SJohn Forte 1647fcf3ce44SJohn Forte /* Fill the priority and capability tables */ 1648fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1649fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 1650fcf3ce44SJohn Forte 1651fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1652fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1653fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. " 1654*291a2b48SSukumar Swaminathan "handle=%p ret=%d", 1655*291a2b48SSukumar Swaminathan i, &htable[i], ret); 1656fcf3ce44SJohn Forte 1657fcf3ce44SJohn Forte /* Clean up the interrupts */ 1658fcf3ce44SJohn Forte goto init_failed; 1659fcf3ce44SJohn Forte } 1660*291a2b48SSukumar Swaminathan 1661fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) { 1662fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1663fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. " 1664fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x", 1665fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri); 1666fcf3ce44SJohn Forte 1667fcf3ce44SJohn Forte /* Clean up the interrupts */ 1668fcf3ce44SJohn Forte goto init_failed; 1669fcf3ce44SJohn Forte } 1670*291a2b48SSukumar Swaminathan 1671fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 1672fcf3ce44SJohn Forte 1673fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1674fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1675*291a2b48SSukumar Swaminathan "MSI: ddi_intr_get_cap(%d) failed. " 1676*291a2b48SSukumar Swaminathan "handle=%p ret=%d", 1677*291a2b48SSukumar Swaminathan i, &htable[i], ret); 1678fcf3ce44SJohn Forte 1679fcf3ce44SJohn Forte /* Clean up the interrupts */ 1680fcf3ce44SJohn Forte goto init_failed; 1681fcf3ce44SJohn Forte } 1682*291a2b48SSukumar Swaminathan 1683fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1684*291a2b48SSukumar Swaminathan "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i, 1685*291a2b48SSukumar Swaminathan intr_cap[i], intr_pri[i], hilevel_pri); 1686fcf3ce44SJohn Forte 1687fcf3ce44SJohn Forte } 1688fcf3ce44SJohn Forte 1689fcf3ce44SJohn Forte /* Set mode */ 1690fcf3ce44SJohn Forte switch (count) { 1691fcf3ce44SJohn Forte case 8: 1692fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8; 1693fcf3ce44SJohn Forte break; 1694fcf3ce44SJohn Forte 1695fcf3ce44SJohn Forte case 4: 1696fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4; 1697fcf3ce44SJohn Forte break; 1698fcf3ce44SJohn Forte 1699fcf3ce44SJohn Forte case 2: 1700fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2; 1701fcf3ce44SJohn Forte break; 1702fcf3ce44SJohn Forte 1703fcf3ce44SJohn Forte default: 1704fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1; 1705fcf3ce44SJohn Forte } 1706fcf3ce44SJohn Forte 1707fcf3ce44SJohn Forte /* Save the info */ 1708fcf3ce44SJohn Forte hba->intr_htable = htable; 1709fcf3ce44SJohn Forte hba->intr_count = count; 1710fcf3ce44SJohn Forte hba->intr_pri = intr_pri; 1711fcf3ce44SJohn Forte hba->intr_cap = intr_cap; 1712fcf3ce44SJohn Forte hba->intr_type = type; 1713*291a2b48SSukumar Swaminathan hba->intr_arg = (void *)((unsigned long)intr_pri[0]); 1714fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode]; 1715fcf3ce44SJohn Forte 1716fcf3ce44SJohn Forte hba->intr_cond = 0; 1717fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1718fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i]; 1719fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i]; 1720fcf3ce44SJohn Forte 1721fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, 1722fcf3ce44SJohn Forte hba->ddiinst, i); 1723fcf3ce44SJohn Forte mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, 1724*291a2b48SSukumar Swaminathan (void *)hba->intr_arg); 1725fcf3ce44SJohn Forte } 1726fcf3ce44SJohn Forte 1727fcf3ce44SJohn Forte /* Set flag to indicate support */ 1728fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED; 1729fcf3ce44SJohn Forte 1730fcf3ce44SJohn Forte /* Create the interrupt threads */ 1731fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 1732fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 1733fcf3ce44SJohn Forte hba->ddiinst, i); 1734fcf3ce44SJohn Forte mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 1735*291a2b48SSukumar Swaminathan (void *)hba->intr_arg); 1736fcf3ce44SJohn Forte 1737fcf3ce44SJohn Forte emlxs_thread_create(hba, &hba->ring[i].intr_thread); 1738fcf3ce44SJohn Forte } 1739fcf3ce44SJohn Forte 1740fcf3ce44SJohn Forte return (DDI_SUCCESS); 1741fcf3ce44SJohn Forte 1742fcf3ce44SJohn Forte 1743fcf3ce44SJohn Forte init_failed: 1744fcf3ce44SJohn Forte 1745fcf3ce44SJohn Forte if (intr_cap) { 1746fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 1747fcf3ce44SJohn Forte } 1748*291a2b48SSukumar Swaminathan 1749fcf3ce44SJohn Forte if (intr_pri) { 1750fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 1751fcf3ce44SJohn Forte } 1752*291a2b48SSukumar Swaminathan 1753fcf3ce44SJohn Forte if (htable) { 1754fcf3ce44SJohn Forte /* Process the interrupt handlers */ 1755fcf3ce44SJohn Forte for (i = 0; i < actual; i++) { 1756fcf3ce44SJohn Forte /* Free the handle[i] */ 1757fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 1758fcf3ce44SJohn Forte } 1759fcf3ce44SJohn Forte 1760fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1761fcf3ce44SJohn Forte } 1762*291a2b48SSukumar Swaminathan 1763fcf3ce44SJohn Forte /* Initialize */ 1764fcf3ce44SJohn Forte hba->intr_htable = NULL; 1765fcf3ce44SJohn Forte hba->intr_count = 0; 1766fcf3ce44SJohn Forte hba->intr_pri = NULL; 1767fcf3ce44SJohn Forte hba->intr_cap = NULL; 1768fcf3ce44SJohn Forte hba->intr_type = 0; 1769fcf3ce44SJohn Forte hba->intr_arg = NULL; 1770fcf3ce44SJohn Forte hba->intr_cond = 0; 1771fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 1772fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock)); 1773fcf3ce44SJohn Forte 1774fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) { 1775fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1776fcf3ce44SJohn Forte goto begin; 1777fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) { 1778fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 1779fcf3ce44SJohn Forte goto begin; 1780fcf3ce44SJohn Forte } 1781*291a2b48SSukumar Swaminathan 1782fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1783fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts"); 1784fcf3ce44SJohn Forte 1785fcf3ce44SJohn Forte return (DDI_FAILURE); 1786fcf3ce44SJohn Forte 1787fcf3ce44SJohn Forte 1788*291a2b48SSukumar Swaminathan } /* emlxs_msi_init() */ 1789fcf3ce44SJohn Forte 1790fcf3ce44SJohn Forte 1791fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 1792fcf3ce44SJohn Forte int32_t 1793fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba) 1794fcf3ce44SJohn Forte { 1795fcf3ce44SJohn Forte uint32_t count; 1796fcf3ce44SJohn Forte int32_t i; 1797fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 1798fcf3ce44SJohn Forte uint32_t *intr_pri; 1799fcf3ce44SJohn Forte int32_t *intr_cap; 1800fcf3ce44SJohn Forte int32_t ret; 1801fcf3ce44SJohn Forte 1802fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1803fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba)); 1804fcf3ce44SJohn Forte } 1805*291a2b48SSukumar Swaminathan 1806fcf3ce44SJohn Forte /* 1807*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1808*291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_uninit called. flags=%x", 1809*291a2b48SSukumar Swaminathan * hba->intr_flags); 1810fcf3ce44SJohn Forte */ 1811fcf3ce44SJohn Forte 1812fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */ 1813fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 1814fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba); 1815fcf3ce44SJohn Forte 1816fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1817fcf3ce44SJohn Forte return (ret); 1818fcf3ce44SJohn Forte } 1819fcf3ce44SJohn Forte } 1820*291a2b48SSukumar Swaminathan 1821fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 1822fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1823fcf3ce44SJohn Forte return (DDI_SUCCESS); 1824fcf3ce44SJohn Forte } 1825fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED; 1826fcf3ce44SJohn Forte 1827fcf3ce44SJohn Forte /* Get handle table parameters */ 1828fcf3ce44SJohn Forte htable = hba->intr_htable; 1829fcf3ce44SJohn Forte count = hba->intr_count; 1830fcf3ce44SJohn Forte intr_pri = hba->intr_pri; 1831fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 1832fcf3ce44SJohn Forte 1833fcf3ce44SJohn Forte /* Clean up */ 1834fcf3ce44SJohn Forte hba->intr_count = 0; 1835fcf3ce44SJohn Forte hba->intr_htable = NULL; 1836fcf3ce44SJohn Forte hba->intr_pri = NULL; 1837fcf3ce44SJohn Forte hba->intr_cap = NULL; 1838fcf3ce44SJohn Forte hba->intr_type = 0; 1839fcf3ce44SJohn Forte hba->intr_arg = NULL; 1840fcf3ce44SJohn Forte hba->intr_cond = 0; 1841fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte if (intr_cap) { 1844fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 1845fcf3ce44SJohn Forte } 1846*291a2b48SSukumar Swaminathan 1847fcf3ce44SJohn Forte if (intr_pri) { 1848fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 1849fcf3ce44SJohn Forte } 1850*291a2b48SSukumar Swaminathan 1851fcf3ce44SJohn Forte if (htable) { 1852fcf3ce44SJohn Forte /* Process the interrupt handlers */ 1853fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1854fcf3ce44SJohn Forte /* Free the handle[i] */ 1855*291a2b48SSukumar Swaminathan ret = ddi_intr_free(htable[i]); 1856fcf3ce44SJohn Forte } 1857fcf3ce44SJohn Forte 1858fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1859fcf3ce44SJohn Forte } 1860*291a2b48SSukumar Swaminathan 1861fcf3ce44SJohn Forte /* Destroy the intr locks */ 1862fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1863fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]); 1864fcf3ce44SJohn Forte } 1865fcf3ce44SJohn Forte 1866fcf3ce44SJohn Forte /* Destroy the interrupt threads */ 1867fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 1868fcf3ce44SJohn Forte emlxs_thread_destroy(&hba->ring[i].intr_thread); 1869fcf3ce44SJohn Forte mutex_destroy(&hba->ring[i].rsp_lock); 1870fcf3ce44SJohn Forte } 1871fcf3ce44SJohn Forte 1872fcf3ce44SJohn Forte /* 1873*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1874*291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_uninit done. flags=%x", 1875*291a2b48SSukumar Swaminathan * hba->intr_flags); 1876fcf3ce44SJohn Forte */ 1877fcf3ce44SJohn Forte 1878fcf3ce44SJohn Forte return (DDI_SUCCESS); 1879fcf3ce44SJohn Forte 1880*291a2b48SSukumar Swaminathan } /* emlxs_msi_uninit() */ 1881fcf3ce44SJohn Forte 1882fcf3ce44SJohn Forte 1883fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */ 1884fcf3ce44SJohn Forte int32_t 1885fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba) 1886fcf3ce44SJohn Forte { 1887fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1888fcf3ce44SJohn Forte int32_t count; 1889fcf3ce44SJohn Forte int32_t i; 1890fcf3ce44SJohn Forte int32_t ret; 1891fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 1892fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 1893fcf3ce44SJohn Forte 1894fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1895fcf3ce44SJohn Forte return (emlxs_intx_add(hba)); 1896fcf3ce44SJohn Forte } 1897*291a2b48SSukumar Swaminathan 1898fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 1899fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) { 1900fcf3ce44SJohn Forte return (DDI_SUCCESS); 1901fcf3ce44SJohn Forte } 1902*291a2b48SSukumar Swaminathan 1903fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 1904fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1905fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0); 1906fcf3ce44SJohn Forte 1907fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1908fcf3ce44SJohn Forte return (ret); 1909fcf3ce44SJohn Forte } 1910fcf3ce44SJohn Forte } 1911*291a2b48SSukumar Swaminathan 1912fcf3ce44SJohn Forte /* Get handle table parameters */ 1913fcf3ce44SJohn Forte htable = hba->intr_htable; 1914fcf3ce44SJohn Forte count = hba->intr_count; 1915fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 1916fcf3ce44SJohn Forte 1917fcf3ce44SJohn Forte /* Add the interrupt handlers */ 1918fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1919fcf3ce44SJohn Forte /* add handler for handle[i] */ 1920*291a2b48SSukumar Swaminathan ret = 1921*291a2b48SSukumar Swaminathan ddi_intr_add_handler(htable[i], emlxs_sli_msi_intr, 1922*291a2b48SSukumar Swaminathan (char *)hba, (char *)((unsigned long)i)); 1923fcf3ce44SJohn Forte 1924fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1925fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1926*291a2b48SSukumar Swaminathan "MSI: ddi_intr_add_handler(%d) failed. " 1927*291a2b48SSukumar Swaminathan "handle=%p ret=%d", 1928*291a2b48SSukumar Swaminathan i, &htable[i], ret); 1929fcf3ce44SJohn Forte 1930fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */ 1931fcf3ce44SJohn Forte while (i) { 1932fcf3ce44SJohn Forte /* Decrement i */ 1933fcf3ce44SJohn Forte i--; 1934fcf3ce44SJohn Forte 1935fcf3ce44SJohn Forte /* Remove the handler */ 1936fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 1937fcf3ce44SJohn Forte 1938fcf3ce44SJohn Forte } 1939fcf3ce44SJohn Forte 1940fcf3ce44SJohn Forte return (DDI_FAILURE); 1941fcf3ce44SJohn Forte } 1942fcf3ce44SJohn Forte } 1943fcf3ce44SJohn Forte 1944fcf3ce44SJohn Forte /* Enable the interrupts */ 1945fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 1946fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count); 1947fcf3ce44SJohn Forte 1948fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1949fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1950fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 1951fcf3ce44SJohn Forte count, ret); 1952fcf3ce44SJohn Forte 1953fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1954fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 1955fcf3ce44SJohn Forte 1956fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1957fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1958fcf3ce44SJohn Forte &emlxs_init_debug_msg, 1959fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. " 1960*291a2b48SSukumar Swaminathan "ret=%d", 1961*291a2b48SSukumar Swaminathan i, ret); 1962fcf3ce44SJohn Forte } 1963fcf3ce44SJohn Forte } 1964fcf3ce44SJohn Forte } 1965fcf3ce44SJohn Forte } else { 1966fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1967fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 1968fcf3ce44SJohn Forte 1969fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1970*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1971*291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 1972fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d", 1973fcf3ce44SJohn Forte i, ret); 1974fcf3ce44SJohn Forte } 1975fcf3ce44SJohn Forte } 1976fcf3ce44SJohn Forte } 1977fcf3ce44SJohn Forte 1978fcf3ce44SJohn Forte 1979fcf3ce44SJohn Forte /* Set flag to indicate support */ 1980fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED; 1981fcf3ce44SJohn Forte 1982fcf3ce44SJohn Forte return (DDI_SUCCESS); 1983fcf3ce44SJohn Forte 1984*291a2b48SSukumar Swaminathan } /* emlxs_msi_add() */ 1985fcf3ce44SJohn Forte 1986fcf3ce44SJohn Forte 1987fcf3ce44SJohn Forte 1988fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 1989fcf3ce44SJohn Forte int32_t 1990fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba) 1991fcf3ce44SJohn Forte { 1992fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1993fcf3ce44SJohn Forte uint32_t count; 1994fcf3ce44SJohn Forte int32_t i; 1995fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 1996fcf3ce44SJohn Forte int32_t *intr_cap; 1997fcf3ce44SJohn Forte int32_t ret; 1998fcf3ce44SJohn Forte 1999fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 2000fcf3ce44SJohn Forte return (emlxs_intx_remove(hba)); 2001fcf3ce44SJohn Forte } 2002*291a2b48SSukumar Swaminathan 2003fcf3ce44SJohn Forte /* 2004*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2005*291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_remove called. flags=%x", 2006*291a2b48SSukumar Swaminathan * hba->intr_flags); 2007fcf3ce44SJohn Forte */ 2008fcf3ce44SJohn Forte 2009fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 2010fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 2011fcf3ce44SJohn Forte return (DDI_SUCCESS); 2012fcf3ce44SJohn Forte } 2013fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED; 2014fcf3ce44SJohn Forte 2015fcf3ce44SJohn Forte /* Disable all adapter interrupts */ 2016*291a2b48SSukumar Swaminathan emlxs_disable_intr(hba, 0); 2017fcf3ce44SJohn Forte 2018fcf3ce44SJohn Forte /* Get handle table parameters */ 2019fcf3ce44SJohn Forte htable = hba->intr_htable; 2020fcf3ce44SJohn Forte count = hba->intr_count; 2021fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 2022fcf3ce44SJohn Forte 2023fcf3ce44SJohn Forte /* Disable the interrupts */ 2024fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 2025fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count); 2026fcf3ce44SJohn Forte 2027fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2028fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2029fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 2030fcf3ce44SJohn Forte count, ret); 2031fcf3ce44SJohn Forte 2032fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2033fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 2034fcf3ce44SJohn Forte 2035fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2036fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2037fcf3ce44SJohn Forte &emlxs_init_debug_msg, 2038fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. " 2039*291a2b48SSukumar Swaminathan "ret=%d", 2040*291a2b48SSukumar Swaminathan i, ret); 2041fcf3ce44SJohn Forte } 2042fcf3ce44SJohn Forte } 2043fcf3ce44SJohn Forte } 2044fcf3ce44SJohn Forte } else { 2045fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2046fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 2047fcf3ce44SJohn Forte 2048fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2049*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 2050*291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 2051fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d", 2052fcf3ce44SJohn Forte i, ret); 2053fcf3ce44SJohn Forte } 2054fcf3ce44SJohn Forte } 2055fcf3ce44SJohn Forte } 2056fcf3ce44SJohn Forte 2057fcf3ce44SJohn Forte /* Process the interrupt handlers */ 2058fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2059fcf3ce44SJohn Forte /* Remove the handler */ 2060fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 2061fcf3ce44SJohn Forte 2062fcf3ce44SJohn Forte 2063fcf3ce44SJohn Forte } 2064fcf3ce44SJohn Forte 2065fcf3ce44SJohn Forte return (DDI_SUCCESS); 2066fcf3ce44SJohn Forte 2067*291a2b48SSukumar Swaminathan } /* emlxs_msi_remove() */ 2068fcf3ce44SJohn Forte 2069fcf3ce44SJohn Forte 2070*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 2071fcf3ce44SJohn Forte 2072fcf3ce44SJohn Forte 2073fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 2074fcf3ce44SJohn Forte /* ARGSUSED */ 2075fcf3ce44SJohn Forte int32_t 2076fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 2077fcf3ce44SJohn Forte { 2078fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2079fcf3ce44SJohn Forte int32_t ret; 2080fcf3ce44SJohn Forte uint32_t i; 2081fcf3ce44SJohn Forte char buf[64]; 2082fcf3ce44SJohn Forte 2083fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */ 2084fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) { 2085fcf3ce44SJohn Forte return (DDI_SUCCESS); 2086fcf3ce44SJohn Forte } 2087*291a2b48SSukumar Swaminathan 2088fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */ 2089fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 2090fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2091fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x", 2092fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags); 2093fcf3ce44SJohn Forte 2094fcf3ce44SJohn Forte return (DDI_FAILURE); 2095fcf3ce44SJohn Forte } 2096*291a2b48SSukumar Swaminathan 2097fcf3ce44SJohn Forte /* 2098*291a2b48SSukumar Swaminathan * Interrupt number '0' is a high-level interrupt. This driver 2099*291a2b48SSukumar Swaminathan * does not support having its interrupts mapped above scheduler 2100*291a2b48SSukumar Swaminathan * priority; i.e., we always expect to be able to call general 2101*291a2b48SSukumar Swaminathan * kernel routines that may invoke the scheduler. 2102fcf3ce44SJohn Forte */ 2103fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 2104fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2105fcf3ce44SJohn Forte "INTX: High-level interrupt not supported."); 2106fcf3ce44SJohn Forte 2107fcf3ce44SJohn Forte return (DDI_FAILURE); 2108fcf3ce44SJohn Forte } 2109*291a2b48SSukumar Swaminathan 2110fcf3ce44SJohn Forte /* Get an iblock cookie */ 2111*291a2b48SSukumar Swaminathan ret = 2112*291a2b48SSukumar Swaminathan ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 2113fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg); 2114fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2115fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2116fcf3ce44SJohn Forte "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 2117fcf3ce44SJohn Forte 2118fcf3ce44SJohn Forte return (ret); 2119fcf3ce44SJohn Forte } 2120*291a2b48SSukumar Swaminathan 2121fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_INITED; 2122fcf3ce44SJohn Forte 2123fcf3ce44SJohn Forte /* Create the interrupt threads */ 2124fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 2125fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 2126fcf3ce44SJohn Forte hba->ddiinst, i); 2127fcf3ce44SJohn Forte mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 2128fcf3ce44SJohn Forte (void *)hba->intr_arg); 2129fcf3ce44SJohn Forte 2130fcf3ce44SJohn Forte emlxs_thread_create(hba, &hba->ring[i].intr_thread); 2131fcf3ce44SJohn Forte } 2132fcf3ce44SJohn Forte 2133fcf3ce44SJohn Forte return (DDI_SUCCESS); 2134fcf3ce44SJohn Forte 2135*291a2b48SSukumar Swaminathan } /* emlxs_intx_init() */ 2136fcf3ce44SJohn Forte 2137fcf3ce44SJohn Forte 2138fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 2139fcf3ce44SJohn Forte int32_t 2140fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba) 2141fcf3ce44SJohn Forte { 2142fcf3ce44SJohn Forte int32_t ret; 2143fcf3ce44SJohn Forte uint32_t i; 2144fcf3ce44SJohn Forte 2145fcf3ce44SJohn Forte /* Make sure interrupts have been removed */ 2146fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 2147fcf3ce44SJohn Forte ret = emlxs_intx_remove(hba); 2148fcf3ce44SJohn Forte 2149fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2150fcf3ce44SJohn Forte return (ret); 2151fcf3ce44SJohn Forte } 2152fcf3ce44SJohn Forte } 2153*291a2b48SSukumar Swaminathan 2154fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 2155fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2156fcf3ce44SJohn Forte return (DDI_SUCCESS); 2157fcf3ce44SJohn Forte } 2158fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_INITED; 2159fcf3ce44SJohn Forte 2160fcf3ce44SJohn Forte hba->intr_arg = NULL; 2161fcf3ce44SJohn Forte 2162fcf3ce44SJohn Forte /* Create the interrupt threads */ 2163fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 2164fcf3ce44SJohn Forte emlxs_thread_destroy(&hba->ring[i].intr_thread); 2165fcf3ce44SJohn Forte mutex_destroy(&hba->ring[i].rsp_lock); 2166fcf3ce44SJohn Forte } 2167fcf3ce44SJohn Forte 2168fcf3ce44SJohn Forte return (DDI_SUCCESS); 2169fcf3ce44SJohn Forte 2170*291a2b48SSukumar Swaminathan } /* emlxs_intx_uninit() */ 2171fcf3ce44SJohn Forte 2172fcf3ce44SJohn Forte 2173*291a2b48SSukumar Swaminathan /* 2174*291a2b48SSukumar Swaminathan * This is the legacy method for adding interrupts in Solaris 2175*291a2b48SSukumar Swaminathan * EMLXS_INTR_ADD 2176*291a2b48SSukumar Swaminathan */ 2177fcf3ce44SJohn Forte int32_t 2178fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba) 2179fcf3ce44SJohn Forte { 2180fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2181fcf3ce44SJohn Forte int32_t ret; 2182fcf3ce44SJohn Forte 2183fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 2184fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_ADDED) { 2185fcf3ce44SJohn Forte return (DDI_SUCCESS); 2186fcf3ce44SJohn Forte } 2187*291a2b48SSukumar Swaminathan 2188fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 2189fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2190fcf3ce44SJohn Forte ret = emlxs_intx_init(hba, 0); 2191fcf3ce44SJohn Forte 2192fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2193fcf3ce44SJohn Forte return (ret); 2194fcf3ce44SJohn Forte } 2195fcf3ce44SJohn Forte } 2196*291a2b48SSukumar Swaminathan 2197fcf3ce44SJohn Forte /* add intrrupt handler routine */ 2198*291a2b48SSukumar Swaminathan ret = ddi_add_intr((void *)hba->dip, 2199*291a2b48SSukumar Swaminathan (uint_t)EMLXS_INUMBER, 2200*291a2b48SSukumar Swaminathan (ddi_iblock_cookie_t *)&hba->intr_arg, 2201*291a2b48SSukumar Swaminathan (ddi_idevice_cookie_t *)0, 2202*291a2b48SSukumar Swaminathan (uint_t(*)())emlxs_sli_intx_intr, (caddr_t)hba); 2203fcf3ce44SJohn Forte 2204fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2205fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 2206fcf3ce44SJohn Forte "INTX: ddi_add_intr failed. ret=%d", ret); 2207fcf3ce44SJohn Forte 2208fcf3ce44SJohn Forte return (ret); 2209fcf3ce44SJohn Forte } 2210*291a2b48SSukumar Swaminathan 2211fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_ADDED; 2212fcf3ce44SJohn Forte 2213fcf3ce44SJohn Forte return (DDI_SUCCESS); 2214fcf3ce44SJohn Forte 2215*291a2b48SSukumar Swaminathan } /* emlxs_intx_add() */ 2216fcf3ce44SJohn Forte 2217fcf3ce44SJohn Forte 2218fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 2219fcf3ce44SJohn Forte int32_t 2220fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba) 2221fcf3ce44SJohn Forte { 2222fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 2223fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 2224fcf3ce44SJohn Forte return (DDI_SUCCESS); 2225fcf3ce44SJohn Forte } 2226fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_ADDED; 2227fcf3ce44SJohn Forte 2228fcf3ce44SJohn Forte /* Diable all adapter interrupts */ 2229*291a2b48SSukumar Swaminathan emlxs_disable_intr(hba, 0); 2230fcf3ce44SJohn Forte 2231fcf3ce44SJohn Forte /* Remove the interrupt */ 2232fcf3ce44SJohn Forte (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 2233fcf3ce44SJohn Forte hba->intr_arg); 2234fcf3ce44SJohn Forte 2235fcf3ce44SJohn Forte return (DDI_SUCCESS); 2236fcf3ce44SJohn Forte 2237*291a2b48SSukumar Swaminathan } /* emlxs_intx_remove() */ 2238fcf3ce44SJohn Forte 2239fcf3ce44SJohn Forte 2240fcf3ce44SJohn Forte static void 2241fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba) 2242fcf3ce44SJohn Forte { 2243fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 2244fcf3ce44SJohn Forte emlxs_config_t *cfg; 2245fcf3ce44SJohn Forte char *cptr; 2246fcf3ce44SJohn Forte uint32_t hi; 2247fcf3ce44SJohn Forte 2248fcf3ce44SJohn Forte /* 2249*291a2b48SSukumar Swaminathan * This routine modifies the link-speed config parameter entry 2250*291a2b48SSukumar Swaminathan * based on adapter capabilities 2251fcf3ce44SJohn Forte */ 2252fcf3ce44SJohn Forte vpd = &VPD; 2253fcf3ce44SJohn Forte cfg = &hba->config[CFG_LINK_SPEED]; 2254fcf3ce44SJohn Forte 2255fcf3ce44SJohn Forte cptr = cfg->help; 2256fcf3ce44SJohn Forte (void) strcpy(cptr, "Select link speed. [0=Auto"); 2257fcf3ce44SJohn Forte cptr += 26; 2258fcf3ce44SJohn Forte hi = 0; 2259fcf3ce44SJohn Forte 2260fcf3ce44SJohn Forte if (vpd->link_speed & LMT_1GB_CAPABLE) { 2261fcf3ce44SJohn Forte (void) strcpy(cptr, ", 1=1Gb"); 2262fcf3ce44SJohn Forte cptr += 7; 2263fcf3ce44SJohn Forte hi = 1; 2264fcf3ce44SJohn Forte } 2265*291a2b48SSukumar Swaminathan 2266fcf3ce44SJohn Forte if (vpd->link_speed & LMT_2GB_CAPABLE) { 2267fcf3ce44SJohn Forte (void) strcpy(cptr, ", 2=2Gb"); 2268fcf3ce44SJohn Forte cptr += 7; 2269fcf3ce44SJohn Forte hi = 2; 2270fcf3ce44SJohn Forte } 2271*291a2b48SSukumar Swaminathan 2272fcf3ce44SJohn Forte if (vpd->link_speed & LMT_4GB_CAPABLE) { 2273fcf3ce44SJohn Forte (void) strcpy(cptr, ", 4=4Gb"); 2274fcf3ce44SJohn Forte cptr += 7; 2275fcf3ce44SJohn Forte hi = 4; 2276fcf3ce44SJohn Forte } 2277*291a2b48SSukumar Swaminathan 2278fcf3ce44SJohn Forte if (vpd->link_speed & LMT_8GB_CAPABLE) { 2279fcf3ce44SJohn Forte (void) strcpy(cptr, ", 8=8Gb"); 2280fcf3ce44SJohn Forte cptr += 7; 2281fcf3ce44SJohn Forte hi = 8; 2282fcf3ce44SJohn Forte } 2283*291a2b48SSukumar Swaminathan 2284fcf3ce44SJohn Forte if (vpd->link_speed & LMT_10GB_CAPABLE) { 2285fcf3ce44SJohn Forte (void) strcpy(cptr, ", 10=10Gb"); 2286fcf3ce44SJohn Forte cptr += 9; 2287fcf3ce44SJohn Forte hi = 10; 2288fcf3ce44SJohn Forte } 2289*291a2b48SSukumar Swaminathan 2290fcf3ce44SJohn Forte (void) strcpy(cptr, "]"); 2291fcf3ce44SJohn Forte cfg->hi = hi; 2292fcf3ce44SJohn Forte 2293fcf3ce44SJohn Forte /* Now revalidate the current parameter setting */ 2294fcf3ce44SJohn Forte cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 2295fcf3ce44SJohn Forte 2296fcf3ce44SJohn Forte return; 2297fcf3ce44SJohn Forte 2298*291a2b48SSukumar Swaminathan } /* emlxs_process_link_speed() */ 2299fcf3ce44SJohn Forte 2300fcf3ce44SJohn Forte 2301fcf3ce44SJohn Forte /* 2302*291a2b48SSukumar Swaminathan * emlxs_parse_vpd() 2303fcf3ce44SJohn Forte * 2304fcf3ce44SJohn Forte * This routine will parse the VPD data 2305fcf3ce44SJohn Forte */ 2306fcf3ce44SJohn Forte extern int 2307fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 2308fcf3ce44SJohn Forte { 2309fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2310fcf3ce44SJohn Forte char tag[3]; 2311fcf3ce44SJohn Forte uint8_t lenlo, lenhi; 2312fcf3ce44SJohn Forte uint32_t n; 2313fcf3ce44SJohn Forte uint16_t block_size; 2314fcf3ce44SJohn Forte uint32_t block_index = 0; 2315fcf3ce44SJohn Forte uint8_t sub_size; 2316fcf3ce44SJohn Forte uint32_t sub_index; 2317fcf3ce44SJohn Forte int32_t finished = 0; 2318fcf3ce44SJohn Forte int32_t index = 0; 2319fcf3ce44SJohn Forte char buffer[128]; 2320fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 2321fcf3ce44SJohn Forte 2322fcf3ce44SJohn Forte vpd = &VPD; 2323fcf3ce44SJohn Forte 2324fcf3ce44SJohn Forte 2325fcf3ce44SJohn Forte while (!finished && (block_index < size)) { 2326fcf3ce44SJohn Forte /* 2327*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2328*291a2b48SSukumar Swaminathan * "block_index = %x", block_index); 2329fcf3ce44SJohn Forte */ 2330fcf3ce44SJohn Forte 2331fcf3ce44SJohn Forte switch (vpd_buf[block_index]) { 2332fcf3ce44SJohn Forte case 0x82: 2333fcf3ce44SJohn Forte index = block_index; 2334fcf3ce44SJohn Forte index += 1; 2335fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 2336fcf3ce44SJohn Forte index += 1; 2337fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 2338fcf3ce44SJohn Forte index += 1; 2339fcf3ce44SJohn Forte block_index = index; 2340fcf3ce44SJohn Forte 2341fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2342fcf3ce44SJohn Forte block_index += block_size; 2343fcf3ce44SJohn Forte 2344fcf3ce44SJohn Forte /* 2345fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2346*291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 2347fcf3ce44SJohn Forte */ 2348fcf3ce44SJohn Forte 2349fcf3ce44SJohn Forte n = sizeof (buffer); 2350fcf3ce44SJohn Forte bzero(buffer, n); 2351fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 2352fcf3ce44SJohn Forte (block_size < (n - 1)) ? block_size : (n - 1)); 2353fcf3ce44SJohn Forte 2354fcf3ce44SJohn Forte (void) strcpy(vpd->id, buffer); 2355*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s", 2356*291a2b48SSukumar Swaminathan vpd->id); 2357fcf3ce44SJohn Forte 2358fcf3ce44SJohn Forte break; 2359fcf3ce44SJohn Forte 2360fcf3ce44SJohn Forte case 0x90: 2361fcf3ce44SJohn Forte index = block_index; 2362fcf3ce44SJohn Forte index += 1; 2363fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 2364fcf3ce44SJohn Forte index += 1; 2365fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 2366fcf3ce44SJohn Forte index += 1; 2367fcf3ce44SJohn Forte block_index = index; 2368fcf3ce44SJohn Forte sub_index = index; 2369fcf3ce44SJohn Forte 2370fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2371fcf3ce44SJohn Forte block_index += block_size; 2372fcf3ce44SJohn Forte 2373fcf3ce44SJohn Forte /* 2374fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2375*291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 2376fcf3ce44SJohn Forte */ 2377fcf3ce44SJohn Forte 2378fcf3ce44SJohn Forte /* Scan for sub-blocks */ 2379fcf3ce44SJohn Forte while ((sub_index < block_index) && 2380fcf3ce44SJohn Forte (sub_index < size)) { 2381fcf3ce44SJohn Forte /* 2382fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2383*291a2b48SSukumar Swaminathan * "sub_index = %x", sub_index); 2384fcf3ce44SJohn Forte */ 2385fcf3ce44SJohn Forte 2386fcf3ce44SJohn Forte index = sub_index; 2387fcf3ce44SJohn Forte tag[0] = vpd_buf[index++]; 2388fcf3ce44SJohn Forte tag[1] = vpd_buf[index++]; 2389fcf3ce44SJohn Forte tag[2] = 0; 2390fcf3ce44SJohn Forte sub_size = vpd_buf[index++]; 2391fcf3ce44SJohn Forte 2392fcf3ce44SJohn Forte /* 2393fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2394*291a2b48SSukumar Swaminathan * "sub_size = %x", sub_size); 2395fcf3ce44SJohn Forte */ 2396fcf3ce44SJohn Forte 2397fcf3ce44SJohn Forte sub_index = (index + sub_size); 2398fcf3ce44SJohn Forte 2399fcf3ce44SJohn Forte n = sizeof (buffer); 2400fcf3ce44SJohn Forte bzero(buffer, n); 2401fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 2402fcf3ce44SJohn Forte (sub_size < (n - 1)) ? sub_size : (n - 1)); 2403fcf3ce44SJohn Forte 2404fcf3ce44SJohn Forte /* 2405fcf3ce44SJohn Forte * Look for Engineering Change (EC) 2406fcf3ce44SJohn Forte */ 2407fcf3ce44SJohn Forte if (strcmp(tag, "EC") == 0) { 2408fcf3ce44SJohn Forte (void) strcpy(vpd->eng_change, buffer); 2409fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2410*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "EC: %s", 2411*291a2b48SSukumar Swaminathan vpd->eng_change); 2412fcf3ce44SJohn Forte } 2413fcf3ce44SJohn Forte /* 2414fcf3ce44SJohn Forte * Look for Manufacturer (MN) 2415fcf3ce44SJohn Forte */ 2416fcf3ce44SJohn Forte else if (strcmp(tag, "MN") == 0) { 2417fcf3ce44SJohn Forte (void) strcpy(vpd->manufacturer, 2418fcf3ce44SJohn Forte buffer); 2419fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2420*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "MN: %s", 2421*291a2b48SSukumar Swaminathan vpd->manufacturer); 2422fcf3ce44SJohn Forte } 2423fcf3ce44SJohn Forte /* 2424fcf3ce44SJohn Forte * Look for Serial Number (SN) 2425fcf3ce44SJohn Forte */ 2426fcf3ce44SJohn Forte else if (strcmp(tag, "SN") == 0) { 2427fcf3ce44SJohn Forte (void) strcpy(vpd->serial_num, buffer); 2428fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2429*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "SN: %s", 2430*291a2b48SSukumar Swaminathan vpd->serial_num); 2431fcf3ce44SJohn Forte 2432fcf3ce44SJohn Forte /* Validate the serial number */ 2433*291a2b48SSukumar Swaminathan if (strncmp(buffer, "FFFFFFFFFF", 10) == 2434*291a2b48SSukumar Swaminathan 0 || 2435*291a2b48SSukumar Swaminathan strncmp(buffer, "0000000000", 10) == 2436*291a2b48SSukumar Swaminathan 0) { 2437fcf3ce44SJohn Forte vpd->serial_num[0] = 0; 2438fcf3ce44SJohn Forte } 2439fcf3ce44SJohn Forte } 2440fcf3ce44SJohn Forte /* 2441fcf3ce44SJohn Forte * Look for Part Number (PN) 2442fcf3ce44SJohn Forte */ 2443fcf3ce44SJohn Forte else if (strcmp(tag, "PN") == 0) { 2444fcf3ce44SJohn Forte (void) strcpy(vpd->part_num, buffer); 2445fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2446*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "PN: %s", 2447*291a2b48SSukumar Swaminathan vpd->part_num); 2448fcf3ce44SJohn Forte } 2449fcf3ce44SJohn Forte /* 2450fcf3ce44SJohn Forte * Look for (V0) 2451fcf3ce44SJohn Forte */ 2452fcf3ce44SJohn Forte else if (strcmp(tag, "V0") == 0) { 2453fcf3ce44SJohn Forte /* Not used */ 2454fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2455*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "V0: %s", buffer); 2456fcf3ce44SJohn Forte } 2457fcf3ce44SJohn Forte /* 2458fcf3ce44SJohn Forte * Look for model description (V1) 2459fcf3ce44SJohn Forte */ 2460fcf3ce44SJohn Forte else if (strcmp(tag, "V1") == 0) { 2461fcf3ce44SJohn Forte (void) strcpy(vpd->model_desc, buffer); 2462fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2463*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Desc: %s", 2464*291a2b48SSukumar Swaminathan vpd->model_desc); 2465fcf3ce44SJohn Forte } 2466fcf3ce44SJohn Forte /* 2467fcf3ce44SJohn Forte * Look for model (V2) 2468fcf3ce44SJohn Forte */ 2469fcf3ce44SJohn Forte else if (strcmp(tag, "V2") == 0) { 2470fcf3ce44SJohn Forte (void) strcpy(vpd->model, buffer); 2471fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2472*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Model: %s", 2473*291a2b48SSukumar Swaminathan vpd->model); 2474fcf3ce44SJohn Forte } 2475fcf3ce44SJohn Forte /* 2476fcf3ce44SJohn Forte * Look for program type (V3) 2477fcf3ce44SJohn Forte */ 2478fcf3ce44SJohn Forte 2479fcf3ce44SJohn Forte else if (strcmp(tag, "V3") == 0) { 2480fcf3ce44SJohn Forte (void) strcpy(vpd->prog_types, buffer); 2481fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2482*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Prog Types: %s", 2483*291a2b48SSukumar Swaminathan vpd->prog_types); 2484fcf3ce44SJohn Forte } 2485fcf3ce44SJohn Forte /* 2486fcf3ce44SJohn Forte * Look for port number (V4) 2487fcf3ce44SJohn Forte */ 2488fcf3ce44SJohn Forte else if (strcmp(tag, "V4") == 0) { 2489fcf3ce44SJohn Forte (void) strcpy(vpd->port_num, buffer); 2490fcf3ce44SJohn Forte vpd->port_index = 2491fcf3ce44SJohn Forte emlxs_strtol(vpd->port_num, 10); 2492fcf3ce44SJohn Forte 2493fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2494*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Port: %s", 2495*291a2b48SSukumar Swaminathan (vpd->port_num[0]) ? vpd-> 2496*291a2b48SSukumar Swaminathan port_num : "not applicable"); 2497fcf3ce44SJohn Forte } 2498fcf3ce44SJohn Forte /* 2499fcf3ce44SJohn Forte * Look for checksum (RV) 2500fcf3ce44SJohn Forte */ 2501fcf3ce44SJohn Forte else if (strcmp(tag, "RV") == 0) { 2502fcf3ce44SJohn Forte /* Not used */ 2503fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2504*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Checksum: 0x%x", 2505*291a2b48SSukumar Swaminathan buffer[0]); 2506*291a2b48SSukumar Swaminathan } 2507*291a2b48SSukumar Swaminathan 2508*291a2b48SSukumar Swaminathan else { 2509fcf3ce44SJohn Forte /* Generic */ 2510fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2511*291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Tag: %s: %s", 2512*291a2b48SSukumar Swaminathan tag, buffer); 2513fcf3ce44SJohn Forte } 2514fcf3ce44SJohn Forte } 2515fcf3ce44SJohn Forte 2516fcf3ce44SJohn Forte break; 2517fcf3ce44SJohn Forte 2518fcf3ce44SJohn Forte case 0x78: 2519fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 2520fcf3ce44SJohn Forte finished = 1; 2521fcf3ce44SJohn Forte break; 2522fcf3ce44SJohn Forte 2523fcf3ce44SJohn Forte default: 2524fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2525fcf3ce44SJohn Forte "Unknown block: %x %x %x %x %x %x %x %x", 2526fcf3ce44SJohn Forte vpd_buf[index], vpd_buf[index + 1], 2527fcf3ce44SJohn Forte vpd_buf[index + 2], vpd_buf[index + 3], 2528fcf3ce44SJohn Forte vpd_buf[index + 4], vpd_buf[index + 5], 2529fcf3ce44SJohn Forte vpd_buf[index + 6], vpd_buf[index + 7]); 2530fcf3ce44SJohn Forte return (0); 2531fcf3ce44SJohn Forte } 2532fcf3ce44SJohn Forte } 2533fcf3ce44SJohn Forte 2534fcf3ce44SJohn Forte return (1); 2535fcf3ce44SJohn Forte 2536*291a2b48SSukumar Swaminathan } /* emlxs_parse_vpd */ 2537fcf3ce44SJohn Forte 2538fcf3ce44SJohn Forte 2539fcf3ce44SJohn Forte 2540fcf3ce44SJohn Forte static uint32_t 2541fcf3ce44SJohn Forte emlxs_decode_biu_rev(uint32_t rev) 2542fcf3ce44SJohn Forte { 2543fcf3ce44SJohn Forte return (rev & 0xf); 2544*291a2b48SSukumar Swaminathan } /* End emlxs_decode_biu_rev */ 2545fcf3ce44SJohn Forte 2546fcf3ce44SJohn Forte 2547fcf3ce44SJohn Forte static uint32_t 2548fcf3ce44SJohn Forte emlxs_decode_endec_rev(uint32_t rev) 2549fcf3ce44SJohn Forte { 2550fcf3ce44SJohn Forte return ((rev >> 28) & 0xf); 2551*291a2b48SSukumar Swaminathan } /* End emlxs_decode_endec_rev */ 2552fcf3ce44SJohn Forte 2553fcf3ce44SJohn Forte 2554fcf3ce44SJohn Forte extern void 2555fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 2556fcf3ce44SJohn Forte { 2557fcf3ce44SJohn Forte if (vpd->rBit) { 2558fcf3ce44SJohn Forte switch (hba->sli_mode) { 2559*291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI4_MODE: 2560fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli4FwName); 2561fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli4FwLabel); 2562fcf3ce44SJohn Forte break; 2563*291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI3_MODE: 2564fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli3FwName); 2565fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli3FwLabel); 2566fcf3ce44SJohn Forte break; 2567*291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI2_MODE: 2568fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli2FwName); 2569fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli2FwLabel); 2570fcf3ce44SJohn Forte break; 2571*291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI1_MODE: 2572fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli1FwName); 2573fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli1FwLabel); 2574fcf3ce44SJohn Forte break; 2575fcf3ce44SJohn Forte default: 2576fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, "unknown"); 2577fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 2578fcf3ce44SJohn Forte } 2579fcf3ce44SJohn Forte } else { 2580fcf3ce44SJohn Forte emlxs_decode_version(vpd->smFwRev, vpd->fw_version); 2581fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 2582fcf3ce44SJohn Forte } 2583fcf3ce44SJohn Forte 2584fcf3ce44SJohn Forte return; 2585fcf3ce44SJohn Forte 2586*291a2b48SSukumar Swaminathan } /* emlxs_decode_firmware_rev() */ 2587fcf3ce44SJohn Forte 2588fcf3ce44SJohn Forte 2589fcf3ce44SJohn Forte 2590fcf3ce44SJohn Forte extern void 2591fcf3ce44SJohn Forte emlxs_decode_version(uint32_t version, char *buffer) 2592fcf3ce44SJohn Forte { 2593fcf3ce44SJohn Forte uint32_t b1, b2, b3, b4; 2594fcf3ce44SJohn Forte char c; 2595fcf3ce44SJohn Forte 2596fcf3ce44SJohn Forte b1 = (version & 0x0000f000) >> 12; 2597fcf3ce44SJohn Forte b2 = (version & 0x00000f00) >> 8; 2598fcf3ce44SJohn Forte b3 = (version & 0x000000c0) >> 6; 2599fcf3ce44SJohn Forte b4 = (version & 0x00000030) >> 4; 2600fcf3ce44SJohn Forte 2601fcf3ce44SJohn Forte if (b1 == 0 && b2 == 0) { 2602fcf3ce44SJohn Forte (void) sprintf(buffer, "none"); 2603fcf3ce44SJohn Forte return; 2604fcf3ce44SJohn Forte } 2605*291a2b48SSukumar Swaminathan 2606fcf3ce44SJohn Forte c = 0; 2607fcf3ce44SJohn Forte switch (b4) { 2608fcf3ce44SJohn Forte case 0: 2609fcf3ce44SJohn Forte c = 'n'; 2610fcf3ce44SJohn Forte break; 2611fcf3ce44SJohn Forte case 1: 2612fcf3ce44SJohn Forte c = 'a'; 2613fcf3ce44SJohn Forte break; 2614fcf3ce44SJohn Forte case 2: 2615fcf3ce44SJohn Forte c = 'b'; 2616fcf3ce44SJohn Forte break; 2617fcf3ce44SJohn Forte case 3: 2618fcf3ce44SJohn Forte if ((version & 0x0000000f)) { 2619fcf3ce44SJohn Forte c = 'x'; 2620fcf3ce44SJohn Forte } 2621fcf3ce44SJohn Forte break; 2622fcf3ce44SJohn Forte 2623fcf3ce44SJohn Forte } 2624fcf3ce44SJohn Forte b4 = (version & 0x0000000f); 2625fcf3ce44SJohn Forte 2626fcf3ce44SJohn Forte if (c == 0) { 2627fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d", b1, b2, b3); 2628fcf3ce44SJohn Forte } else { 2629fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4); 2630fcf3ce44SJohn Forte } 2631fcf3ce44SJohn Forte 2632fcf3ce44SJohn Forte return; 2633fcf3ce44SJohn Forte 2634*291a2b48SSukumar Swaminathan } /* emlxs_decode_version() */ 2635fcf3ce44SJohn Forte 2636fcf3ce44SJohn Forte 2637fcf3ce44SJohn Forte static void 2638fcf3ce44SJohn Forte emlxs_decode_label(char *label, char *buffer) 2639fcf3ce44SJohn Forte { 2640fcf3ce44SJohn Forte uint32_t i; 2641fcf3ce44SJohn Forte char name[16]; 2642fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN 2643fcf3ce44SJohn Forte uint32_t *wptr; 2644fcf3ce44SJohn Forte uint32_t word; 2645*291a2b48SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */ 2646fcf3ce44SJohn Forte 2647fcf3ce44SJohn Forte bcopy(label, name, 16); 2648fcf3ce44SJohn Forte 2649fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN 2650fcf3ce44SJohn Forte wptr = (uint32_t *)name; 2651fcf3ce44SJohn Forte for (i = 0; i < 3; i++) { 2652fcf3ce44SJohn Forte word = *wptr; 2653fcf3ce44SJohn Forte word = SWAP_DATA32(word); 2654fcf3ce44SJohn Forte *wptr++ = word; 2655fcf3ce44SJohn Forte } 2656*291a2b48SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */ 2657fcf3ce44SJohn Forte 2658fcf3ce44SJohn Forte for (i = 0; i < 16; i++) { 2659fcf3ce44SJohn Forte if (name[i] == 0x20) { 2660fcf3ce44SJohn Forte name[i] = 0; 2661fcf3ce44SJohn Forte } 2662fcf3ce44SJohn Forte } 2663fcf3ce44SJohn Forte 2664fcf3ce44SJohn Forte (void) strcpy(buffer, name); 2665fcf3ce44SJohn Forte 2666fcf3ce44SJohn Forte return; 2667fcf3ce44SJohn Forte 2668*291a2b48SSukumar Swaminathan } /* emlxs_decode_label() */ 2669fcf3ce44SJohn Forte 2670fcf3ce44SJohn Forte 2671fcf3ce44SJohn Forte extern uint32_t 2672fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base) 2673fcf3ce44SJohn Forte { 2674fcf3ce44SJohn Forte uint32_t value = 0; 2675fcf3ce44SJohn Forte char *ptr; 2676fcf3ce44SJohn Forte uint32_t factor = 1; 2677fcf3ce44SJohn Forte uint32_t digits; 2678fcf3ce44SJohn Forte 2679fcf3ce44SJohn Forte if (*str == 0) { 2680fcf3ce44SJohn Forte return (0); 2681fcf3ce44SJohn Forte } 2682*291a2b48SSukumar Swaminathan 2683fcf3ce44SJohn Forte if (base != 10 && base != 16) { 2684fcf3ce44SJohn Forte return (0); 2685fcf3ce44SJohn Forte } 2686*291a2b48SSukumar Swaminathan 2687fcf3ce44SJohn Forte /* Get max digits of value */ 2688fcf3ce44SJohn Forte digits = (base == 10) ? 9 : 8; 2689fcf3ce44SJohn Forte 2690fcf3ce44SJohn Forte /* Position pointer to end of string */ 2691fcf3ce44SJohn Forte ptr = str + strlen(str); 2692fcf3ce44SJohn Forte 2693fcf3ce44SJohn Forte /* Process string backwards */ 2694fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 2695fcf3ce44SJohn Forte /* check for base 10 numbers */ 2696fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 2697fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 2698fcf3ce44SJohn Forte factor *= base; 2699fcf3ce44SJohn Forte digits--; 2700fcf3ce44SJohn Forte } else if (base == 16) { 2701fcf3ce44SJohn Forte /* Check for base 16 numbers */ 2702fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 2703*291a2b48SSukumar Swaminathan value += 2704*291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 2705fcf3ce44SJohn Forte factor *= base; 2706fcf3ce44SJohn Forte digits--; 2707fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 2708*291a2b48SSukumar Swaminathan value += 2709*291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 2710fcf3ce44SJohn Forte factor *= base; 2711fcf3ce44SJohn Forte digits--; 2712fcf3ce44SJohn Forte } else if (factor > 1) { 2713fcf3ce44SJohn Forte break; 2714fcf3ce44SJohn Forte } 2715fcf3ce44SJohn Forte } else if (factor > 1) { 2716fcf3ce44SJohn Forte break; 2717fcf3ce44SJohn Forte } 2718fcf3ce44SJohn Forte } 2719fcf3ce44SJohn Forte 2720fcf3ce44SJohn Forte return (value); 2721fcf3ce44SJohn Forte 2722*291a2b48SSukumar Swaminathan } /* emlxs_strtol() */ 2723fcf3ce44SJohn Forte 2724fcf3ce44SJohn Forte 2725fcf3ce44SJohn Forte extern uint64_t 2726fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base) 2727fcf3ce44SJohn Forte { 2728fcf3ce44SJohn Forte uint64_t value = 0; 2729fcf3ce44SJohn Forte char *ptr; 2730fcf3ce44SJohn Forte uint32_t factor = 1; 2731fcf3ce44SJohn Forte uint32_t digits; 2732fcf3ce44SJohn Forte 2733fcf3ce44SJohn Forte if (*str == 0) { 2734fcf3ce44SJohn Forte return (0); 2735fcf3ce44SJohn Forte } 2736*291a2b48SSukumar Swaminathan 2737fcf3ce44SJohn Forte if (base != 10 && base != 16) { 2738fcf3ce44SJohn Forte return (0); 2739fcf3ce44SJohn Forte } 2740*291a2b48SSukumar Swaminathan 2741fcf3ce44SJohn Forte /* Get max digits of value */ 2742fcf3ce44SJohn Forte digits = (base == 10) ? 19 : 16; 2743fcf3ce44SJohn Forte 2744fcf3ce44SJohn Forte /* Position pointer to end of string */ 2745fcf3ce44SJohn Forte ptr = str + strlen(str); 2746fcf3ce44SJohn Forte 2747fcf3ce44SJohn Forte /* Process string backwards */ 2748fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 2749fcf3ce44SJohn Forte /* check for base 10 numbers */ 2750fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 2751fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 2752fcf3ce44SJohn Forte factor *= base; 2753fcf3ce44SJohn Forte digits--; 2754fcf3ce44SJohn Forte } else if (base == 16) { 2755fcf3ce44SJohn Forte /* Check for base 16 numbers */ 2756fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 2757*291a2b48SSukumar Swaminathan value += 2758*291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 2759fcf3ce44SJohn Forte factor *= base; 2760fcf3ce44SJohn Forte digits--; 2761fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 2762*291a2b48SSukumar Swaminathan value += 2763*291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 2764fcf3ce44SJohn Forte factor *= base; 2765fcf3ce44SJohn Forte digits--; 2766fcf3ce44SJohn Forte } else if (factor > 1) { 2767fcf3ce44SJohn Forte break; 2768fcf3ce44SJohn Forte } 2769fcf3ce44SJohn Forte } else if (factor > 1) { 2770fcf3ce44SJohn Forte break; 2771fcf3ce44SJohn Forte } 2772fcf3ce44SJohn Forte } 2773fcf3ce44SJohn Forte 2774fcf3ce44SJohn Forte return (value); 2775fcf3ce44SJohn Forte 2776*291a2b48SSukumar Swaminathan } /* emlxs_strtoll() */ 2777fcf3ce44SJohn Forte 2778fcf3ce44SJohn Forte static void 2779fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 2780fcf3ce44SJohn Forte { 2781fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2782fcf3ce44SJohn Forte uint32_t i; 2783fcf3ce44SJohn Forte char *ptr; 2784fcf3ce44SJohn Forte emlxs_model_t *model; 2785fcf3ce44SJohn Forte char types_buffer[256]; 2786fcf3ce44SJohn Forte char *types; 2787fcf3ce44SJohn Forte 2788fcf3ce44SJohn Forte bcopy(prog_types, types_buffer, 256); 2789fcf3ce44SJohn Forte types = types_buffer; 2790fcf3ce44SJohn Forte 2791fcf3ce44SJohn Forte model = &hba->model_info; 2792fcf3ce44SJohn Forte 2793fcf3ce44SJohn Forte while (*types) { 2794fcf3ce44SJohn Forte if (strncmp(types, "T2:", 3) == 0) { 2795fcf3ce44SJohn Forte bzero(model->pt_2, sizeof (model->pt_2)); 2796fcf3ce44SJohn Forte types += 3; 2797fcf3ce44SJohn Forte 2798fcf3ce44SJohn Forte i = 0; 2799fcf3ce44SJohn Forte while (*types && *types != 'T') { 2800fcf3ce44SJohn Forte /* Null terminate the next value */ 2801fcf3ce44SJohn Forte ptr = types; 2802fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2803fcf3ce44SJohn Forte ptr++; 2804fcf3ce44SJohn Forte *ptr = 0; 2805fcf3ce44SJohn Forte 2806fcf3ce44SJohn Forte /* Save the value */ 2807fcf3ce44SJohn Forte model->pt_2[i++] = 2808fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2809fcf3ce44SJohn Forte 2810fcf3ce44SJohn Forte /* 2811fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2812fcf3ce44SJohn Forte * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 2813fcf3ce44SJohn Forte */ 2814fcf3ce44SJohn Forte 2815fcf3ce44SJohn Forte /* Move the str pointer */ 2816fcf3ce44SJohn Forte types = ptr + 1; 2817fcf3ce44SJohn Forte } 2818fcf3ce44SJohn Forte 2819fcf3ce44SJohn Forte } else if (strncmp(types, "T3:", 3) == 0) { 2820fcf3ce44SJohn Forte bzero(model->pt_3, sizeof (model->pt_3)); 2821fcf3ce44SJohn Forte types += 3; 2822fcf3ce44SJohn Forte 2823fcf3ce44SJohn Forte i = 0; 2824fcf3ce44SJohn Forte while (*types && *types != 'T') { 2825fcf3ce44SJohn Forte /* Null terminate the next value */ 2826fcf3ce44SJohn Forte ptr = types; 2827fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2828fcf3ce44SJohn Forte ptr++; 2829fcf3ce44SJohn Forte *ptr = 0; 2830fcf3ce44SJohn Forte 2831fcf3ce44SJohn Forte /* Save the value */ 2832fcf3ce44SJohn Forte model->pt_3[i++] = 2833fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2834fcf3ce44SJohn Forte 2835fcf3ce44SJohn Forte /* 2836fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2837fcf3ce44SJohn Forte * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 2838fcf3ce44SJohn Forte */ 2839fcf3ce44SJohn Forte 2840fcf3ce44SJohn Forte /* Move the str pointer */ 2841fcf3ce44SJohn Forte types = ptr + 1; 2842fcf3ce44SJohn Forte } 2843fcf3ce44SJohn Forte } else if (strncmp(types, "T6:", 3) == 0) { 2844fcf3ce44SJohn Forte bzero(model->pt_6, sizeof (model->pt_6)); 2845fcf3ce44SJohn Forte types += 3; 2846fcf3ce44SJohn Forte 2847fcf3ce44SJohn Forte i = 0; 2848fcf3ce44SJohn Forte while (*types && *types != 'T') { 2849fcf3ce44SJohn Forte /* Null terminate the next value */ 2850fcf3ce44SJohn Forte ptr = types; 2851fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2852fcf3ce44SJohn Forte ptr++; 2853fcf3ce44SJohn Forte *ptr = 0; 2854fcf3ce44SJohn Forte 2855fcf3ce44SJohn Forte /* Save the value */ 2856fcf3ce44SJohn Forte model->pt_6[i++] = 2857fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2858fcf3ce44SJohn Forte model->pt_6[i] = 0; 2859fcf3ce44SJohn Forte 2860fcf3ce44SJohn Forte /* 2861fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2862fcf3ce44SJohn Forte * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 2863fcf3ce44SJohn Forte */ 2864fcf3ce44SJohn Forte 2865fcf3ce44SJohn Forte /* Move the str pointer */ 2866fcf3ce44SJohn Forte types = ptr + 1; 2867fcf3ce44SJohn Forte } 2868fcf3ce44SJohn Forte } else if (strncmp(types, "T7:", 3) == 0) { 2869fcf3ce44SJohn Forte bzero(model->pt_7, sizeof (model->pt_7)); 2870fcf3ce44SJohn Forte types += 3; 2871fcf3ce44SJohn Forte 2872fcf3ce44SJohn Forte i = 0; 2873fcf3ce44SJohn Forte while (*types && *types != 'T') { 2874fcf3ce44SJohn Forte /* Null terminate the next value */ 2875fcf3ce44SJohn Forte ptr = types; 2876fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2877fcf3ce44SJohn Forte ptr++; 2878fcf3ce44SJohn Forte *ptr = 0; 2879fcf3ce44SJohn Forte 2880fcf3ce44SJohn Forte /* Save the value */ 2881fcf3ce44SJohn Forte model->pt_7[i++] = 2882fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2883fcf3ce44SJohn Forte model->pt_7[i] = 0; 2884fcf3ce44SJohn Forte 2885fcf3ce44SJohn Forte /* 2886fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2887fcf3ce44SJohn Forte * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 2888fcf3ce44SJohn Forte */ 2889fcf3ce44SJohn Forte 2890fcf3ce44SJohn Forte /* Move the str pointer */ 2891fcf3ce44SJohn Forte types = ptr + 1; 2892fcf3ce44SJohn Forte } 2893fcf3ce44SJohn Forte } else if (strncmp(types, "TA:", 3) == 0) { 2894fcf3ce44SJohn Forte bzero(model->pt_A, sizeof (model->pt_A)); 2895fcf3ce44SJohn Forte types += 3; 2896fcf3ce44SJohn Forte 2897fcf3ce44SJohn Forte i = 0; 2898fcf3ce44SJohn Forte while (*types && *types != 'T') { 2899fcf3ce44SJohn Forte /* Null terminate the next value */ 2900fcf3ce44SJohn Forte ptr = types; 2901fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2902fcf3ce44SJohn Forte ptr++; 2903fcf3ce44SJohn Forte *ptr = 0; 2904fcf3ce44SJohn Forte 2905fcf3ce44SJohn Forte /* Save the value */ 2906fcf3ce44SJohn Forte model->pt_A[i++] = 2907fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2908fcf3ce44SJohn Forte 2909fcf3ce44SJohn Forte /* 2910fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2911fcf3ce44SJohn Forte * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]); 2912fcf3ce44SJohn Forte */ 2913fcf3ce44SJohn Forte 2914fcf3ce44SJohn Forte /* Move the str pointer */ 2915fcf3ce44SJohn Forte types = ptr + 1; 2916fcf3ce44SJohn Forte } 2917fcf3ce44SJohn Forte } else if (strncmp(types, "TB:", 3) == 0) { 2918fcf3ce44SJohn Forte bzero(model->pt_B, sizeof (model->pt_B)); 2919fcf3ce44SJohn Forte types += 3; 2920fcf3ce44SJohn Forte 2921fcf3ce44SJohn Forte i = 0; 2922fcf3ce44SJohn Forte while (*types && *types != 'T') { 2923fcf3ce44SJohn Forte /* Null terminate the next value */ 2924fcf3ce44SJohn Forte ptr = types; 2925fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2926fcf3ce44SJohn Forte ptr++; 2927fcf3ce44SJohn Forte *ptr = 0; 2928fcf3ce44SJohn Forte 2929fcf3ce44SJohn Forte /* Save the value */ 2930fcf3ce44SJohn Forte model->pt_B[i++] = 2931fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2932fcf3ce44SJohn Forte 2933fcf3ce44SJohn Forte /* 2934fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2935fcf3ce44SJohn Forte * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 2936fcf3ce44SJohn Forte */ 2937fcf3ce44SJohn Forte 2938fcf3ce44SJohn Forte /* Move the str pointer */ 2939fcf3ce44SJohn Forte types = ptr + 1; 2940fcf3ce44SJohn Forte } 2941fcf3ce44SJohn Forte } else if (strncmp(types, "TFF:", 4) == 0) { 2942fcf3ce44SJohn Forte bzero(model->pt_FF, sizeof (model->pt_FF)); 2943fcf3ce44SJohn Forte types += 4; 2944fcf3ce44SJohn Forte 2945fcf3ce44SJohn Forte i = 0; 2946fcf3ce44SJohn Forte while (*types && *types != 'T') { 2947fcf3ce44SJohn Forte /* Null terminate the next value */ 2948fcf3ce44SJohn Forte ptr = types; 2949fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2950fcf3ce44SJohn Forte ptr++; 2951fcf3ce44SJohn Forte *ptr = 0; 2952fcf3ce44SJohn Forte 2953fcf3ce44SJohn Forte /* Save the value */ 2954fcf3ce44SJohn Forte model->pt_FF[i++] = 2955fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2956fcf3ce44SJohn Forte 2957fcf3ce44SJohn Forte /* 2958fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2959fcf3ce44SJohn Forte * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 2960fcf3ce44SJohn Forte */ 2961fcf3ce44SJohn Forte 2962*291a2b48SSukumar Swaminathan /* Move the str pointer */ 2963*291a2b48SSukumar Swaminathan types = ptr + 1; 2964*291a2b48SSukumar Swaminathan } 2965*291a2b48SSukumar Swaminathan } else if (strncmp(types, "T20:", 4) == 0) { 2966*291a2b48SSukumar Swaminathan bzero(model->pt_20, sizeof (model->pt_20)); 2967*291a2b48SSukumar Swaminathan types += 4; 2968*291a2b48SSukumar Swaminathan 2969*291a2b48SSukumar Swaminathan i = 0; 2970*291a2b48SSukumar Swaminathan while (*types && *types != 'T') { 2971*291a2b48SSukumar Swaminathan /* Null terminate the next value */ 2972*291a2b48SSukumar Swaminathan ptr = types; 2973*291a2b48SSukumar Swaminathan while (*ptr && (*ptr != ',')) 2974*291a2b48SSukumar Swaminathan ptr++; 2975*291a2b48SSukumar Swaminathan *ptr = 0; 2976*291a2b48SSukumar Swaminathan 2977*291a2b48SSukumar Swaminathan /* Save the value */ 2978*291a2b48SSukumar Swaminathan model->pt_20[i++] = 2979*291a2b48SSukumar Swaminathan (uint8_t)emlxs_strtol(types, 16); 2980*291a2b48SSukumar Swaminathan model->pt_20[i] = 0; 2981*291a2b48SSukumar Swaminathan 2982*291a2b48SSukumar Swaminathan /* 2983*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2984*291a2b48SSukumar Swaminathan * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]); 2985*291a2b48SSukumar Swaminathan */ 2986*291a2b48SSukumar Swaminathan 2987fcf3ce44SJohn Forte /* Move the str pointer */ 2988fcf3ce44SJohn Forte types = ptr + 1; 2989fcf3ce44SJohn Forte } 2990fcf3ce44SJohn Forte } else { 2991fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2992fcf3ce44SJohn Forte "Unknown prog type string = %s", types); 2993fcf3ce44SJohn Forte break; 2994fcf3ce44SJohn Forte } 2995fcf3ce44SJohn Forte } 2996fcf3ce44SJohn Forte 2997fcf3ce44SJohn Forte return; 2998fcf3ce44SJohn Forte 2999*291a2b48SSukumar Swaminathan } /* emlxs_parse_prog_types() */ 3000fcf3ce44SJohn Forte 3001fcf3ce44SJohn Forte 3002fcf3ce44SJohn Forte static void 3003fcf3ce44SJohn Forte emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types) 3004fcf3ce44SJohn Forte { 3005fcf3ce44SJohn Forte uint32_t i; 3006fcf3ce44SJohn Forte uint32_t found = 0; 3007fcf3ce44SJohn Forte char buffer[256]; 3008fcf3ce44SJohn Forte 3009fcf3ce44SJohn Forte bzero(prog_types, 256); 3010fcf3ce44SJohn Forte 3011fcf3ce44SJohn Forte /* Rebuild the prog type string */ 3012fcf3ce44SJohn Forte if (hba->model_info.pt_2[0]) { 3013fcf3ce44SJohn Forte (void) strcat(prog_types, "T2:"); 3014fcf3ce44SJohn Forte found = 1; 3015fcf3ce44SJohn Forte 3016fcf3ce44SJohn Forte i = 0; 3017fcf3ce44SJohn Forte while (hba->model_info.pt_2[i] && i < 8) { 3018fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]); 3019fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3020fcf3ce44SJohn Forte i++; 3021fcf3ce44SJohn Forte } 3022fcf3ce44SJohn Forte } 3023*291a2b48SSukumar Swaminathan 3024fcf3ce44SJohn Forte if (hba->model_info.pt_3[0]) { 3025fcf3ce44SJohn Forte (void) strcat(prog_types, "T3:"); 3026fcf3ce44SJohn Forte found = 1; 3027fcf3ce44SJohn Forte 3028fcf3ce44SJohn Forte i = 0; 3029fcf3ce44SJohn Forte while (hba->model_info.pt_3[i] && i < 8) { 3030fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]); 3031fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3032fcf3ce44SJohn Forte i++; 3033fcf3ce44SJohn Forte 3034fcf3ce44SJohn Forte } 3035fcf3ce44SJohn Forte } 3036*291a2b48SSukumar Swaminathan 3037fcf3ce44SJohn Forte if (hba->model_info.pt_6[0]) { 3038fcf3ce44SJohn Forte (void) strcat(prog_types, "T6:"); 3039fcf3ce44SJohn Forte found = 1; 3040fcf3ce44SJohn Forte 3041fcf3ce44SJohn Forte i = 0; 3042fcf3ce44SJohn Forte while (hba->model_info.pt_6[i] && i < 8) { 3043fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]); 3044fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3045fcf3ce44SJohn Forte i++; 3046fcf3ce44SJohn Forte } 3047fcf3ce44SJohn Forte } 3048*291a2b48SSukumar Swaminathan 3049fcf3ce44SJohn Forte if (hba->model_info.pt_7[0]) { 3050fcf3ce44SJohn Forte (void) strcat(prog_types, "T7:"); 3051fcf3ce44SJohn Forte found = 1; 3052fcf3ce44SJohn Forte 3053fcf3ce44SJohn Forte i = 0; 3054fcf3ce44SJohn Forte while (hba->model_info.pt_7[i] && i < 8) { 3055fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]); 3056fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3057fcf3ce44SJohn Forte i++; 3058fcf3ce44SJohn Forte } 3059fcf3ce44SJohn Forte } 3060*291a2b48SSukumar Swaminathan 3061fcf3ce44SJohn Forte if (hba->model_info.pt_A[0]) { 3062fcf3ce44SJohn Forte (void) strcat(prog_types, "TA:"); 3063fcf3ce44SJohn Forte found = 1; 3064fcf3ce44SJohn Forte 3065fcf3ce44SJohn Forte i = 0; 3066fcf3ce44SJohn Forte while (hba->model_info.pt_A[i] && i < 8) { 3067fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]); 3068fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3069fcf3ce44SJohn Forte i++; 3070fcf3ce44SJohn Forte } 3071fcf3ce44SJohn Forte } 3072*291a2b48SSukumar Swaminathan 3073*291a2b48SSukumar Swaminathan 3074fcf3ce44SJohn Forte if (hba->model_info.pt_B[0]) { 3075fcf3ce44SJohn Forte (void) strcat(prog_types, "TB:"); 3076fcf3ce44SJohn Forte found = 1; 3077fcf3ce44SJohn Forte 3078fcf3ce44SJohn Forte i = 0; 3079fcf3ce44SJohn Forte while (hba->model_info.pt_B[i] && i < 8) { 3080fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]); 3081fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3082fcf3ce44SJohn Forte i++; 3083fcf3ce44SJohn Forte } 3084fcf3ce44SJohn Forte } 3085*291a2b48SSukumar Swaminathan 3086*291a2b48SSukumar Swaminathan if (hba->model_info.pt_20[0]) { 3087*291a2b48SSukumar Swaminathan (void) strcat(prog_types, "T20:"); 3088*291a2b48SSukumar Swaminathan found = 1; 3089*291a2b48SSukumar Swaminathan 3090*291a2b48SSukumar Swaminathan i = 0; 3091*291a2b48SSukumar Swaminathan while (hba->model_info.pt_20[i] && i < 8) { 3092*291a2b48SSukumar Swaminathan (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]); 3093*291a2b48SSukumar Swaminathan (void) strcat(prog_types, buffer); 3094*291a2b48SSukumar Swaminathan i++; 3095*291a2b48SSukumar Swaminathan } 3096*291a2b48SSukumar Swaminathan } 3097*291a2b48SSukumar Swaminathan 3098fcf3ce44SJohn Forte if (hba->model_info.pt_FF[0]) { 3099fcf3ce44SJohn Forte (void) strcat(prog_types, "TFF:"); 3100fcf3ce44SJohn Forte found = 1; 3101fcf3ce44SJohn Forte 3102fcf3ce44SJohn Forte i = 0; 3103fcf3ce44SJohn Forte while (hba->model_info.pt_FF[i] && i < 8) { 3104fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]); 3105fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3106fcf3ce44SJohn Forte i++; 3107fcf3ce44SJohn Forte } 3108fcf3ce44SJohn Forte } 3109*291a2b48SSukumar Swaminathan 3110fcf3ce44SJohn Forte if (found) { 3111fcf3ce44SJohn Forte /* Terminate at the last comma in string */ 3112fcf3ce44SJohn Forte prog_types[(strlen(prog_types) - 1)] = 0; 3113fcf3ce44SJohn Forte } 3114*291a2b48SSukumar Swaminathan 3115fcf3ce44SJohn Forte return; 3116fcf3ce44SJohn Forte 3117*291a2b48SSukumar Swaminathan } /* emlxs_build_prog_types() */ 3118fcf3ce44SJohn Forte 3119fcf3ce44SJohn Forte 3120fcf3ce44SJohn Forte 3121fcf3ce44SJohn Forte 3122fcf3ce44SJohn Forte extern uint32_t 3123fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba) 3124fcf3ce44SJohn Forte { 3125fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3126fcf3ce44SJohn Forte uint32_t pci_id; 3127fcf3ce44SJohn Forte uint32_t cache_line; 3128fcf3ce44SJohn Forte uint32_t channels; 3129fcf3ce44SJohn Forte uint16_t device_id; 3130fcf3ce44SJohn Forte uint16_t ssdid; 3131fcf3ce44SJohn Forte uint32_t i; 3132fcf3ce44SJohn Forte uint32_t found = 0; 3133fcf3ce44SJohn Forte 3134fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3135fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 3136fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 3137fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3138fcf3ce44SJohn Forte 3139fcf3ce44SJohn Forte hba->model_info.device_id = 0; 3140fcf3ce44SJohn Forte 3141fcf3ce44SJohn Forte return (0); 3142fcf3ce44SJohn Forte } 3143*291a2b48SSukumar Swaminathan 3144fcf3ce44SJohn Forte /* Read the PCI device id */ 3145*291a2b48SSukumar Swaminathan pci_id = 3146*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3147fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 3148fcf3ce44SJohn Forte device_id = (uint16_t)(pci_id >> 16); 3149fcf3ce44SJohn Forte 3150fcf3ce44SJohn Forte /* Find matching adapter model */ 3151fcf3ce44SJohn Forte for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 3152fcf3ce44SJohn Forte if (emlxs_sbus_model[i].device_id == device_id) { 3153fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[i], &hba->model_info, 3154fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3155fcf3ce44SJohn Forte found = 1; 3156fcf3ce44SJohn Forte break; 3157fcf3ce44SJohn Forte } 3158fcf3ce44SJohn Forte } 3159fcf3ce44SJohn Forte 3160fcf3ce44SJohn Forte /* If not found then use the unknown model */ 3161fcf3ce44SJohn Forte if (!found) { 3162fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 3163fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3164fcf3ce44SJohn Forte 3165fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 3166fcf3ce44SJohn Forte 3167fcf3ce44SJohn Forte return (0); 3168fcf3ce44SJohn Forte } 3169fcf3ce44SJohn Forte } else { /* PCI model */ 3170*291a2b48SSukumar Swaminathan 3171fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 3172fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 3173fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3174fcf3ce44SJohn Forte 3175fcf3ce44SJohn Forte hba->model_info.device_id = 0; 3176fcf3ce44SJohn Forte 3177fcf3ce44SJohn Forte return (0); 3178fcf3ce44SJohn Forte } 3179*291a2b48SSukumar Swaminathan 3180fcf3ce44SJohn Forte /* Read the PCI device id */ 3181*291a2b48SSukumar Swaminathan device_id = 3182*291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 3183fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 3184fcf3ce44SJohn Forte 3185fcf3ce44SJohn Forte /* Read the PCI Subsystem id */ 3186*291a2b48SSukumar Swaminathan ssdid = 3187*291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 3188fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 3189fcf3ce44SJohn Forte 3190fcf3ce44SJohn Forte if (ssdid == 0 || ssdid == 0xffff) { 3191fcf3ce44SJohn Forte ssdid = device_id; 3192fcf3ce44SJohn Forte } 3193*291a2b48SSukumar Swaminathan 3194fcf3ce44SJohn Forte /* Read the Cache Line reg */ 3195*291a2b48SSukumar Swaminathan cache_line = 3196*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3197fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 3198fcf3ce44SJohn Forte 3199fcf3ce44SJohn Forte /* Check for the multifunction bit being set */ 3200fcf3ce44SJohn Forte if ((cache_line & 0x00ff0000) == 0x00800000) { 3201fcf3ce44SJohn Forte channels = 2; 3202fcf3ce44SJohn Forte } else { 3203fcf3ce44SJohn Forte channels = 1; 3204fcf3ce44SJohn Forte } 3205fcf3ce44SJohn Forte 3206fcf3ce44SJohn Forte /* If device ids are unique, then use them for search */ 3207fcf3ce44SJohn Forte if (device_id != ssdid) { 3208fcf3ce44SJohn Forte if (channels > 1) { 3209fcf3ce44SJohn Forte /* 3210fcf3ce44SJohn Forte * Find matching adapter model using 3211fcf3ce44SJohn Forte * device_id, ssdid and channels 3212fcf3ce44SJohn Forte */ 3213fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3214*291a2b48SSukumar Swaminathan if (emlxs_pci_model[i].device_id == 3215*291a2b48SSukumar Swaminathan device_id && 3216*291a2b48SSukumar Swaminathan emlxs_pci_model[i].ssdid == ssdid && 3217*291a2b48SSukumar Swaminathan emlxs_pci_model[i].channels == 3218*291a2b48SSukumar Swaminathan channels) { 3219fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3220fcf3ce44SJohn Forte &hba->model_info, 3221fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3222fcf3ce44SJohn Forte found = 1; 3223fcf3ce44SJohn Forte break; 3224fcf3ce44SJohn Forte } 3225fcf3ce44SJohn Forte } 3226fcf3ce44SJohn Forte } else { 3227fcf3ce44SJohn Forte /* 3228fcf3ce44SJohn Forte * Find matching adapter model using 3229fcf3ce44SJohn Forte * device_id and ssdid 3230fcf3ce44SJohn Forte */ 3231fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3232*291a2b48SSukumar Swaminathan if (emlxs_pci_model[i].device_id == 3233*291a2b48SSukumar Swaminathan device_id && 3234*291a2b48SSukumar Swaminathan emlxs_pci_model[i].ssdid == ssdid) { 3235fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3236fcf3ce44SJohn Forte &hba->model_info, 3237fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3238fcf3ce44SJohn Forte found = 1; 3239fcf3ce44SJohn Forte break; 3240fcf3ce44SJohn Forte } 3241fcf3ce44SJohn Forte } 3242fcf3ce44SJohn Forte } 3243fcf3ce44SJohn Forte } 3244*291a2b48SSukumar Swaminathan 3245fcf3ce44SJohn Forte /* If adapter not found, try again */ 3246fcf3ce44SJohn Forte if (!found) { 3247fcf3ce44SJohn Forte /* Find matching adapter model */ 3248fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3249fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id && 3250fcf3ce44SJohn Forte emlxs_pci_model[i].channels == channels) { 3251fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3252fcf3ce44SJohn Forte &hba->model_info, 3253fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3254fcf3ce44SJohn Forte found = 1; 3255fcf3ce44SJohn Forte break; 3256fcf3ce44SJohn Forte } 3257fcf3ce44SJohn Forte } 3258fcf3ce44SJohn Forte } 3259*291a2b48SSukumar Swaminathan 3260fcf3ce44SJohn Forte /* If adapter not found, try one last time */ 3261fcf3ce44SJohn Forte if (!found) { 3262fcf3ce44SJohn Forte /* Find matching adapter model */ 3263fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3264fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id) { 3265fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3266fcf3ce44SJohn Forte &hba->model_info, 3267fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3268fcf3ce44SJohn Forte found = 1; 3269fcf3ce44SJohn Forte break; 3270fcf3ce44SJohn Forte } 3271fcf3ce44SJohn Forte } 3272fcf3ce44SJohn Forte } 3273*291a2b48SSukumar Swaminathan 3274fcf3ce44SJohn Forte /* If not found, set adapter to unknown */ 3275fcf3ce44SJohn Forte if (!found) { 3276fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 3277fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3278fcf3ce44SJohn Forte 3279fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 3280fcf3ce44SJohn Forte hba->model_info.ssdid = ssdid; 3281fcf3ce44SJohn Forte 3282fcf3ce44SJohn Forte return (0); 3283fcf3ce44SJohn Forte } 3284fcf3ce44SJohn Forte 3285fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT 3286fcf3ce44SJohn Forte /* 3287*291a2b48SSukumar Swaminathan * This will disable MSI support for Saturn adapter's 3288*291a2b48SSukumar Swaminathan * due to a PCI bus issue 3289fcf3ce44SJohn Forte */ 3290fcf3ce44SJohn Forte if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 3291fcf3ce44SJohn Forte hba->model_info.flags &= 3292fcf3ce44SJohn Forte ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 3293fcf3ce44SJohn Forte } 3294*291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */ 3295fcf3ce44SJohn Forte 3296fcf3ce44SJohn Forte 3297fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 3298fcf3ce44SJohn Forte /* Verify MSI support */ 3299fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { 3300fcf3ce44SJohn Forte uint32_t offset; 3301fcf3ce44SJohn Forte uint32_t reg; 3302fcf3ce44SJohn Forte 3303fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 3304*291a2b48SSukumar Swaminathan offset = 3305*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3306fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3307fcf3ce44SJohn Forte offset &= 0xff; 3308fcf3ce44SJohn Forte 3309fcf3ce44SJohn Forte while (offset) { 3310*291a2b48SSukumar Swaminathan reg = 3311*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3312fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 3313fcf3ce44SJohn Forte 3314fcf3ce44SJohn Forte if ((reg & 0xff) == MSI_CAP_ID) { 3315fcf3ce44SJohn Forte break; 3316fcf3ce44SJohn Forte } 3317fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 3318fcf3ce44SJohn Forte } 3319fcf3ce44SJohn Forte 3320fcf3ce44SJohn Forte if (offset) { 3321fcf3ce44SJohn Forte hba->msi_cap_offset = offset + 2; 3322fcf3ce44SJohn Forte } else { 3323fcf3ce44SJohn Forte hba->msi_cap_offset = 0; 3324fcf3ce44SJohn Forte hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 3325fcf3ce44SJohn Forte 3326*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3327*291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 3328fcf3ce44SJohn Forte "MSI: control_reg capability not found!"); 3329fcf3ce44SJohn Forte } 3330fcf3ce44SJohn Forte } 3331*291a2b48SSukumar Swaminathan 3332fcf3ce44SJohn Forte /* Verify MSI-X support */ 3333fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { 3334fcf3ce44SJohn Forte uint32_t offset; 3335fcf3ce44SJohn Forte uint32_t reg; 3336fcf3ce44SJohn Forte 3337fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 3338*291a2b48SSukumar Swaminathan offset = 3339*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3340fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3341fcf3ce44SJohn Forte offset &= 0xff; 3342fcf3ce44SJohn Forte 3343fcf3ce44SJohn Forte while (offset) { 3344*291a2b48SSukumar Swaminathan reg = 3345*291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 3346fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 3347fcf3ce44SJohn Forte 3348fcf3ce44SJohn Forte if ((reg & 0xff) == MSIX_CAP_ID) { 3349fcf3ce44SJohn Forte break; 3350fcf3ce44SJohn Forte } 3351fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 3352fcf3ce44SJohn Forte } 3353fcf3ce44SJohn Forte 3354fcf3ce44SJohn Forte if (offset) { 3355fcf3ce44SJohn Forte hba->msix_cap_offset = offset; 3356fcf3ce44SJohn Forte } else { 3357fcf3ce44SJohn Forte hba->msix_cap_offset = 0; 3358*291a2b48SSukumar Swaminathan hba->model_info.flags &= 3359*291a2b48SSukumar Swaminathan ~EMLXS_MSIX_SUPPORTED; 3360fcf3ce44SJohn Forte 3361*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3362*291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 3363fcf3ce44SJohn Forte "MSIX: control_reg capability not found!"); 3364fcf3ce44SJohn Forte } 3365fcf3ce44SJohn Forte } 3366*291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 3367*291a2b48SSukumar Swaminathan 3368*291a2b48SSukumar Swaminathan } 3369fcf3ce44SJohn Forte 3370*291a2b48SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 3371*291a2b48SSukumar Swaminathan return (0); 3372fcf3ce44SJohn Forte } 3373fcf3ce44SJohn Forte 3374*291a2b48SSukumar Swaminathan /* For now we just support SLI2 and SLI3 */ 3375*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_map_hdw = emlxs_sli3_map_hdw; 3376*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_unmap_hdw = emlxs_sli3_unmap_hdw; 3377*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_online = emlxs_sli3_online; 3378*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_offline = emlxs_sli3_offline; 3379*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_hba_reset = emlxs_sli3_hba_reset; 3380*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_issue_iocb_cmd = emlxs_sli3_issue_iocb_cmd; 3381*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_issue_mbox_cmd = emlxs_sli3_issue_mbox_cmd; 3382*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3383*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_prep_fct_iocb = emlxs_sli3_prep_fct_iocb; 3384*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3385*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_prep_fcp_iocb = emlxs_sli3_prep_fcp_iocb; 3386*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_prep_ip_iocb = emlxs_sli3_prep_ip_iocb; 3387*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_prep_els_iocb = emlxs_sli3_prep_els_iocb; 3388*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_prep_ct_iocb = emlxs_sli3_prep_ct_iocb; 3389*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_poll_intr = emlxs_sli3_poll_intr; 3390*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_intx_intr = emlxs_sli3_intx_intr; 3391*291a2b48SSukumar Swaminathan hba->emlxs_sli_api_msi_intr = emlxs_sli3_msi_intr; 3392fcf3ce44SJohn Forte return (1); 3393fcf3ce44SJohn Forte 3394*291a2b48SSukumar Swaminathan } /* emlxs_init_adapter_info() */ 3395fcf3ce44SJohn Forte 3396fcf3ce44SJohn Forte 3397*291a2b48SSukumar Swaminathan /* ARGSUSED */ 3398*291a2b48SSukumar Swaminathan static void 3399*291a2b48SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 3400fcf3ce44SJohn Forte { 3401*291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 3402*291a2b48SSukumar Swaminathan IOCB *iocb; 3403*291a2b48SSukumar Swaminathan uint32_t *w; 3404*291a2b48SSukumar Swaminathan int i, j; 3405fcf3ce44SJohn Forte 3406*291a2b48SSukumar Swaminathan iocb = &iocbq->iocb; 3407fcf3ce44SJohn Forte 3408*291a2b48SSukumar Swaminathan if (iocb->ulpStatus != 0) { 3409*291a2b48SSukumar Swaminathan return; 3410fcf3ce44SJohn Forte } 3411fcf3ce44SJohn Forte 3412*291a2b48SSukumar Swaminathan switch (iocb->un.astat.EventCode) { 3413*291a2b48SSukumar Swaminathan case 0x0100: /* Temp Warning */ 3414*291a2b48SSukumar Swaminathan 3415*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 3416*291a2b48SSukumar Swaminathan "Adapter is very hot (%d �C). Take corrective action.", 3417*291a2b48SSukumar Swaminathan iocb->ulpContext); 3418fcf3ce44SJohn Forte 3419*291a2b48SSukumar Swaminathan emlxs_log_temp_event(port, 0x02, iocb->ulpContext); 3420fcf3ce44SJohn Forte 3421*291a2b48SSukumar Swaminathan break; 3422fcf3ce44SJohn Forte 3423fcf3ce44SJohn Forte 3424*291a2b48SSukumar Swaminathan case 0x0101: /* Temp Safe */ 3425fcf3ce44SJohn Forte 3426*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 3427*291a2b48SSukumar Swaminathan "Adapter temperature now safe (%d �C).", 3428*291a2b48SSukumar Swaminathan iocb->ulpContext); 3429fcf3ce44SJohn Forte 3430*291a2b48SSukumar Swaminathan emlxs_log_temp_event(port, 0x03, iocb->ulpContext); 3431fcf3ce44SJohn Forte 3432*291a2b48SSukumar Swaminathan break; 3433fcf3ce44SJohn Forte 3434*291a2b48SSukumar Swaminathan default: 3435fcf3ce44SJohn Forte 3436*291a2b48SSukumar Swaminathan w = (uint32_t *)iocb; 3437*291a2b48SSukumar Swaminathan for (i = 0, j = 0; i < 8; i++, j += 2) { 3438*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg, 3439*291a2b48SSukumar Swaminathan "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1, 3440*291a2b48SSukumar Swaminathan w[j + 1]); 3441*291a2b48SSukumar Swaminathan } 3442fcf3ce44SJohn Forte 3443*291a2b48SSukumar Swaminathan emlxs_log_async_event(port, iocb); 3444fcf3ce44SJohn Forte } 3445fcf3ce44SJohn Forte 3446fcf3ce44SJohn Forte return; 3447fcf3ce44SJohn Forte 3448*291a2b48SSukumar Swaminathan } /* emlxs_handle_async_event() */ 3449fcf3ce44SJohn Forte 3450fcf3ce44SJohn Forte 3451*291a2b48SSukumar Swaminathan extern void 3452*291a2b48SSukumar Swaminathan emlxs_reset_link_thread(void *arg) 3453fcf3ce44SJohn Forte { 3454*291a2b48SSukumar Swaminathan emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3455*291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 3456fcf3ce44SJohn Forte 3457*291a2b48SSukumar Swaminathan /* Attempt a link reset to recover */ 3458*291a2b48SSukumar Swaminathan (void) emlxs_reset(port, FC_FCA_LINK_RESET); 3459fcf3ce44SJohn Forte 3460*291a2b48SSukumar Swaminathan thread_exit(); 3461fcf3ce44SJohn Forte 3462*291a2b48SSukumar Swaminathan } /* emlxs_reset_link_thread() */ 3463fcf3ce44SJohn Forte 3464fcf3ce44SJohn Forte 3465fcf3ce44SJohn Forte extern void 3466fcf3ce44SJohn Forte emlxs_restart_thread(void *arg) 3467fcf3ce44SJohn Forte { 3468fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3469fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3470fcf3ce44SJohn Forte 3471fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 3472fcf3ce44SJohn Forte 3473fcf3ce44SJohn Forte /* Attempt a full hardware reset to recover */ 3474fcf3ce44SJohn Forte if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 3475fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 3476fcf3ce44SJohn Forte 3477*291a2b48SSukumar Swaminathan thread_create(NULL, 0, emlxs_shutdown_thread, (char *)hba, 0, 3478*291a2b48SSukumar Swaminathan &p0, TS_RUN, v.v_maxsyspri - 2); 3479fcf3ce44SJohn Forte } 3480fcf3ce44SJohn Forte 3481*291a2b48SSukumar Swaminathan thread_exit(); 3482*291a2b48SSukumar Swaminathan 3483*291a2b48SSukumar Swaminathan } /* emlxs_restart_thread() */ 3484fcf3ce44SJohn Forte 3485fcf3ce44SJohn Forte 3486fcf3ce44SJohn Forte extern void 3487fcf3ce44SJohn Forte emlxs_shutdown_thread(void *arg) 3488fcf3ce44SJohn Forte { 3489fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3490fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3491fcf3ce44SJohn Forte 3492fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3493fcf3ce44SJohn Forte if (hba->flag & FC_SHUTDOWN) { 3494fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3495*291a2b48SSukumar Swaminathan thread_exit(); 3496fcf3ce44SJohn Forte } 3497fcf3ce44SJohn Forte hba->flag |= FC_SHUTDOWN; 3498fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3499fcf3ce44SJohn Forte 3500*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 3501*291a2b48SSukumar Swaminathan "Shutting down..."); 3502fcf3ce44SJohn Forte 3503fcf3ce44SJohn Forte /* Take adapter offline and leave it there */ 3504fcf3ce44SJohn Forte (void) emlxs_offline(hba); 3505fcf3ce44SJohn Forte 3506fcf3ce44SJohn Forte /* Log a dump event */ 3507fcf3ce44SJohn Forte emlxs_log_dump_event(port, NULL, 0); 3508fcf3ce44SJohn Forte 3509fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 3510fcf3ce44SJohn Forte 3511*291a2b48SSukumar Swaminathan thread_exit(); 3512fcf3ce44SJohn Forte 3513*291a2b48SSukumar Swaminathan } /* emlxs_shutdown_thread() */ 3514fcf3ce44SJohn Forte 3515fcf3ce44SJohn Forte 3516fcf3ce44SJohn Forte /* ARGSUSED */ 3517fcf3ce44SJohn Forte extern void 3518fcf3ce44SJohn Forte emlxs_proc_ring(emlxs_hba_t *hba, RING *rp, void *arg2) 3519fcf3ce44SJohn Forte { 3520fcf3ce44SJohn Forte IOCBQ *iocbq; 3521fcf3ce44SJohn Forte IOCBQ *rsp_head; 3522fcf3ce44SJohn Forte 3523fcf3ce44SJohn Forte /* 3524*291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3525*291a2b48SSukumar Swaminathan * "emlxs_proc_ring: ringo=%d", rp->ringno); 3526fcf3ce44SJohn Forte */ 3527fcf3ce44SJohn Forte 3528fcf3ce44SJohn Forte mutex_enter(&rp->rsp_lock); 3529fcf3ce44SJohn Forte 3530fcf3ce44SJohn Forte while ((rsp_head = rp->rsp_head) != NULL) { 3531fcf3ce44SJohn Forte rp->rsp_head = NULL; 3532fcf3ce44SJohn Forte rp->rsp_tail = NULL; 3533fcf3ce44SJohn Forte 3534fcf3ce44SJohn Forte mutex_exit(&rp->rsp_lock); 3535fcf3ce44SJohn Forte 3536fcf3ce44SJohn Forte while ((iocbq = rsp_head) != NULL) { 3537fcf3ce44SJohn Forte rsp_head = (IOCBQ *) iocbq->next; 3538fcf3ce44SJohn Forte 3539fcf3ce44SJohn Forte emlxs_proc_ring_event(hba, rp, iocbq); 3540fcf3ce44SJohn Forte } 3541fcf3ce44SJohn Forte 3542fcf3ce44SJohn Forte mutex_enter(&rp->rsp_lock); 3543fcf3ce44SJohn Forte } 3544fcf3ce44SJohn Forte 3545fcf3ce44SJohn Forte mutex_exit(&rp->rsp_lock); 3546fcf3ce44SJohn Forte 3547*291a2b48SSukumar Swaminathan emlxs_sli_issue_iocb_cmd(hba, rp, 0); 3548fcf3ce44SJohn Forte 3549fcf3ce44SJohn Forte return; 3550fcf3ce44SJohn Forte 3551*291a2b48SSukumar Swaminathan } /* emlxs_proc_ring() */ 3552fcf3ce44SJohn Forte 3553fcf3ce44SJohn Forte 3554fcf3ce44SJohn Forte /* 3555*291a2b48SSukumar Swaminathan * Called from SLI ring event routines to process a rsp ring IOCB. 3556fcf3ce44SJohn Forte */ 3557*291a2b48SSukumar Swaminathan void 3558fcf3ce44SJohn Forte emlxs_proc_ring_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 3559fcf3ce44SJohn Forte { 3560fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3561fcf3ce44SJohn Forte char buffer[MAX_MSG_DATA + 1]; 3562fcf3ce44SJohn Forte IOCB *iocb; 3563fcf3ce44SJohn Forte 3564fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3565fcf3ce44SJohn Forte 3566fcf3ce44SJohn Forte /* Check for IOCB local error */ 3567fcf3ce44SJohn Forte if (iocb->ulpStatus == IOSTAT_LOCAL_REJECT) { 3568fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 3569*291a2b48SSukumar Swaminathan "Local reject. ringno=%d iocb=%p cmd=%x " 3570*291a2b48SSukumar Swaminathan "iotag=%x context=%x info=%x error=%x", 3571fcf3ce44SJohn Forte rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 3572fcf3ce44SJohn Forte (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 3573fcf3ce44SJohn Forte (uint8_t)iocb->ulpRsvdByte, 3574fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 3575fcf3ce44SJohn Forte } else if (iocb->ulpStatus == IOSTAT_ILLEGAL_FRAME_RCVD) { 3576fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 3577*291a2b48SSukumar Swaminathan "Illegal frame. ringno=%d iocb=%p cmd=%x " 3578*291a2b48SSukumar Swaminathan "iotag=%x context=%x info=%x error=%x", 3579fcf3ce44SJohn Forte rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 3580fcf3ce44SJohn Forte (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 3581fcf3ce44SJohn Forte (uint8_t)iocb->ulpRsvdByte, 3582fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 3583fcf3ce44SJohn Forte } 3584*291a2b48SSukumar Swaminathan 3585fcf3ce44SJohn Forte switch (iocb->ulpCommand) { 3586fcf3ce44SJohn Forte /* RING 0 FCP commands */ 3587fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR: 3588fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX: 3589fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR: 3590fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX: 3591fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR: 3592fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX: 3593fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR: 3594fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX: 3595fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR: 3596fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX: 3597fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR: 3598fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX: 3599*291a2b48SSukumar Swaminathan emlxs_handle_fcp_event(hba, rp, iocbq); 3600fcf3ce44SJohn Forte break; 3601fcf3ce44SJohn Forte 3602fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 3603*291a2b48SSukumar Swaminathan case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 3604fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 3605fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 3606fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 3607*291a2b48SSukumar Swaminathan case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 3608*291a2b48SSukumar Swaminathan case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 3609fcf3ce44SJohn Forte (void) emlxs_fct_handle_fcp_event(hba, rp, iocbq); 3610fcf3ce44SJohn Forte break; 3611*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3612fcf3ce44SJohn Forte 3613fcf3ce44SJohn Forte /* RING 1 IP commands */ 3614fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN: 3615fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX: 3616fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN: 3617fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX: 3618fcf3ce44SJohn Forte (void) emlxs_ip_handle_event(hba, rp, iocbq); 3619fcf3ce44SJohn Forte break; 3620fcf3ce44SJohn Forte 3621fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX: 3622fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR: 3623fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX: 3624fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR: 3625fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 3626fcf3ce44SJohn Forte case FC_TYPE_IS8802_SNAP: 3627fcf3ce44SJohn Forte (void) emlxs_ip_handle_event(hba, rp, iocbq); 3628fcf3ce44SJohn Forte break; 3629fcf3ce44SJohn Forte 3630fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 3631fcf3ce44SJohn Forte (void) emlxs_ct_handle_event(hba, rp, iocbq); 3632fcf3ce44SJohn Forte break; 3633fcf3ce44SJohn Forte 3634fcf3ce44SJohn Forte default: 3635fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3636fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 3637fcf3ce44SJohn Forte iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 3638*291a2b48SSukumar Swaminathan iocb->ulpStatus, iocb->ulpIoTag, 3639*291a2b48SSukumar Swaminathan iocb->ulpContext); 3640fcf3ce44SJohn Forte } 3641fcf3ce44SJohn Forte break; 3642fcf3ce44SJohn Forte 3643fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE_CX: 3644fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE64_CX: 3645fcf3ce44SJohn Forte case CMD_RCV_SEQ64_CX: 3646fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 3647fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 3648*291a2b48SSukumar Swaminathan case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 3649fcf3ce44SJohn Forte (void) emlxs_handle_rcv_seq(hba, rp, iocbq); 3650fcf3ce44SJohn Forte break; 3651fcf3ce44SJohn Forte 3652fcf3ce44SJohn Forte case CMD_RCV_SEQ_LIST64_CX: 3653fcf3ce44SJohn Forte (void) emlxs_ip_handle_rcv_seq_list(hba, rp, iocbq); 3654fcf3ce44SJohn Forte break; 3655fcf3ce44SJohn Forte 3656fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR: 3657fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX: 3658fcf3ce44SJohn Forte (void) emlxs_handle_create_xri(hba, rp, iocbq); 3659fcf3ce44SJohn Forte break; 3660fcf3ce44SJohn Forte 3661fcf3ce44SJohn Forte /* RING 2 ELS commands */ 3662fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR: 3663fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX: 3664fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX: 3665fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR: 3666fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX: 3667fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX: 3668fcf3ce44SJohn Forte (void) emlxs_els_handle_event(hba, rp, iocbq); 3669fcf3ce44SJohn Forte break; 3670fcf3ce44SJohn Forte 3671fcf3ce44SJohn Forte /* RING 3 CT commands */ 3672fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR: 3673fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX: 3674fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 3675fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 3676fcf3ce44SJohn Forte case EMLXS_MENLO_TYPE: 3677fcf3ce44SJohn Forte (void) emlxs_menlo_handle_event(hba, rp, iocbq); 3678fcf3ce44SJohn Forte break; 3679*291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 3680fcf3ce44SJohn Forte 3681fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 3682fcf3ce44SJohn Forte (void) emlxs_ct_handle_event(hba, rp, iocbq); 3683fcf3ce44SJohn Forte break; 3684fcf3ce44SJohn Forte 3685fcf3ce44SJohn Forte default: 3686fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3687fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 3688fcf3ce44SJohn Forte iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 3689*291a2b48SSukumar Swaminathan iocb->ulpStatus, iocb->ulpIoTag, 3690*291a2b48SSukumar Swaminathan iocb->ulpContext); 3691fcf3ce44SJohn Forte } 3692fcf3ce44SJohn Forte break; 3693fcf3ce44SJohn Forte 3694fcf3ce44SJohn Forte case CMD_ABORT_XRI_CN: /* Abort fcp command */ 3695fcf3ce44SJohn Forte 3696fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3697fcf3ce44SJohn Forte "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 3698fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 3699*291a2b48SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3700*291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 3701fcf3ce44SJohn Forte 3702*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3703*291a2b48SSukumar Swaminathan if (port->tgt_mode) { 3704*291a2b48SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3705*291a2b48SSukumar Swaminathan } 3706*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3707fcf3ce44SJohn Forte break; 3708fcf3ce44SJohn Forte 3709fcf3ce44SJohn Forte case CMD_ABORT_XRI_CX: /* Abort command */ 3710fcf3ce44SJohn Forte 3711fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3712*291a2b48SSukumar Swaminathan "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 3713fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 3714*291a2b48SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3715*291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 3716fcf3ce44SJohn Forte 3717*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3718*291a2b48SSukumar Swaminathan if (port->tgt_mode) { 3719*291a2b48SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3720*291a2b48SSukumar Swaminathan } 3721*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3722fcf3ce44SJohn Forte break; 3723fcf3ce44SJohn Forte 3724fcf3ce44SJohn Forte case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 3725fcf3ce44SJohn Forte 3726fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3727fcf3ce44SJohn Forte "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x", 3728fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 3729*291a2b48SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3730*291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 3731fcf3ce44SJohn Forte 3732*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3733*291a2b48SSukumar Swaminathan if (port->tgt_mode) { 3734*291a2b48SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3735*291a2b48SSukumar Swaminathan } 3736*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3737fcf3ce44SJohn Forte break; 3738fcf3ce44SJohn Forte 3739fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 3740fcf3ce44SJohn Forte 3741fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3742fcf3ce44SJohn Forte "CLOSE_XRI_CR: rpi=%d iotag=%x status=%x parm=%x", 3743fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 3744*291a2b48SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3745*291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 3746fcf3ce44SJohn Forte 3747*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3748*291a2b48SSukumar Swaminathan if (port->tgt_mode) { 3749*291a2b48SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3750*291a2b48SSukumar Swaminathan } 3751*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3752fcf3ce44SJohn Forte break; 3753fcf3ce44SJohn Forte 3754fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 3755fcf3ce44SJohn Forte 3756fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3757*291a2b48SSukumar Swaminathan "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 3758fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 3759*291a2b48SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3760*291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 3761fcf3ce44SJohn Forte 3762*291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3763*291a2b48SSukumar Swaminathan if (port->tgt_mode) { 3764*291a2b48SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3765*291a2b48SSukumar Swaminathan } 3766*291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3767fcf3ce44SJohn Forte break; 3768fcf3ce44SJohn Forte 3769fcf3ce44SJohn Forte case CMD_ADAPTER_MSG: 3770fcf3ce44SJohn Forte /* Allows debug adapter firmware messages to print on host */ 3771fcf3ce44SJohn Forte bzero(buffer, sizeof (buffer)); 3772fcf3ce44SJohn Forte bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 3773fcf3ce44SJohn Forte 3774fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 3775fcf3ce44SJohn Forte 3776fcf3ce44SJohn Forte break; 3777fcf3ce44SJohn Forte 3778fcf3ce44SJohn Forte case CMD_QUE_RING_LIST64_CN: 3779fcf3ce44SJohn Forte case CMD_QUE_RING_BUF64_CN: 3780fcf3ce44SJohn Forte break; 3781fcf3ce44SJohn Forte 3782fcf3ce44SJohn Forte case CMD_ASYNC_STATUS: 3783*291a2b48SSukumar Swaminathan emlxs_handle_async_event(hba, rp, iocbq); 3784fcf3ce44SJohn Forte break; 3785fcf3ce44SJohn Forte 3786fcf3ce44SJohn Forte default: 3787fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3788*291a2b48SSukumar Swaminathan "cmd=%x status=%x iotag=%x context=%x", iocb->ulpCommand, 3789*291a2b48SSukumar Swaminathan iocb->ulpStatus, iocb->ulpIoTag, iocb->ulpContext); 3790fcf3ce44SJohn Forte 3791fcf3ce44SJohn Forte break; 3792fcf3ce44SJohn Forte } /* switch(entry->ulpCommand) */ 3793fcf3ce44SJohn Forte 3794fcf3ce44SJohn Forte return; 3795fcf3ce44SJohn Forte 3796*291a2b48SSukumar Swaminathan } /* emlxs_proc_ring_event() */ 3797fcf3ce44SJohn Forte 3798fcf3ce44SJohn Forte 3799fcf3ce44SJohn Forte 3800*291a2b48SSukumar Swaminathan extern char * 3801*291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state) 3802fcf3ce44SJohn Forte { 3803*291a2b48SSukumar Swaminathan static char buffer[32]; 3804*291a2b48SSukumar Swaminathan uint32_t i; 3805*291a2b48SSukumar Swaminathan uint32_t count; 3806fcf3ce44SJohn Forte 3807*291a2b48SSukumar Swaminathan count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 3808*291a2b48SSukumar Swaminathan for (i = 0; i < count; i++) { 3809*291a2b48SSukumar Swaminathan if (state == emlxs_ffstate_table[i].code) { 3810*291a2b48SSukumar Swaminathan return (emlxs_ffstate_table[i].string); 3811fcf3ce44SJohn Forte } 3812fcf3ce44SJohn Forte } 3813fcf3ce44SJohn Forte 3814*291a2b48SSukumar Swaminathan (void) sprintf(buffer, "state=0x%x", state); 3815*291a2b48SSukumar Swaminathan return (buffer); 3816fcf3ce44SJohn Forte 3817*291a2b48SSukumar Swaminathan } /* emlxs_ffstate_xlate() */ 3818fcf3ce44SJohn Forte 3819fcf3ce44SJohn Forte 3820fcf3ce44SJohn Forte extern char * 3821fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno) 3822fcf3ce44SJohn Forte { 3823fcf3ce44SJohn Forte static char buffer[32]; 3824fcf3ce44SJohn Forte uint32_t i; 3825fcf3ce44SJohn Forte uint32_t count; 3826fcf3ce44SJohn Forte 3827fcf3ce44SJohn Forte count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 3828fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 3829fcf3ce44SJohn Forte if (ringno == emlxs_ring_table[i].code) { 3830fcf3ce44SJohn Forte return (emlxs_ring_table[i].string); 3831fcf3ce44SJohn Forte } 3832fcf3ce44SJohn Forte } 3833fcf3ce44SJohn Forte 3834fcf3ce44SJohn Forte (void) sprintf(buffer, "ring=0x%x", ringno); 3835fcf3ce44SJohn Forte return (buffer); 3836fcf3ce44SJohn Forte 3837*291a2b48SSukumar Swaminathan } /* emlxs_ring_xlate() */ 3838fcf3ce44SJohn Forte 3839fcf3ce44SJohn Forte 3840fcf3ce44SJohn Forte 3841fcf3ce44SJohn Forte extern void 3842fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 3843fcf3ce44SJohn Forte { 3844fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3845fcf3ce44SJohn Forte MAILBOX *mb; 3846fcf3ce44SJohn Forte emlxs_config_t *cfg; 3847fcf3ce44SJohn Forte uint32_t value; 3848fcf3ce44SJohn Forte 3849fcf3ce44SJohn Forte cfg = &CFG; 3850fcf3ce44SJohn Forte 3851fcf3ce44SJohn Forte xlate: 3852fcf3ce44SJohn Forte 3853fcf3ce44SJohn Forte switch (cfg[CFG_PCI_MAX_READ].current) { 3854fcf3ce44SJohn Forte case 512: 3855fcf3ce44SJohn Forte value = 0; 3856fcf3ce44SJohn Forte break; 3857fcf3ce44SJohn Forte 3858fcf3ce44SJohn Forte case 1024: 3859fcf3ce44SJohn Forte value = 1; 3860fcf3ce44SJohn Forte break; 3861fcf3ce44SJohn Forte 3862fcf3ce44SJohn Forte case 2048: 3863fcf3ce44SJohn Forte value = 2; 3864fcf3ce44SJohn Forte break; 3865fcf3ce44SJohn Forte 3866fcf3ce44SJohn Forte case 4096: 3867fcf3ce44SJohn Forte value = 3; 3868fcf3ce44SJohn Forte break; 3869fcf3ce44SJohn Forte 3870fcf3ce44SJohn Forte default: 3871fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3872fcf3ce44SJohn Forte "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 3873fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 3874fcf3ce44SJohn Forte 3875fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 3876fcf3ce44SJohn Forte goto xlate; 3877fcf3ce44SJohn Forte } 3878fcf3ce44SJohn Forte 3879*291a2b48SSukumar Swaminathan if ((mb = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 3880fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3881fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to allocate mailbox buffer."); 3882fcf3ce44SJohn Forte return; 3883fcf3ce44SJohn Forte } 3884fcf3ce44SJohn Forte 3885*291a2b48SSukumar Swaminathan emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00100506, value); 3886*291a2b48SSukumar Swaminathan 3887*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 3888fcf3ce44SJohn Forte if (verbose || (mb->mbxStatus != 0x12)) { 3889fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3890*291a2b48SSukumar Swaminathan "PCI_MAX_READ: Unable to update. " 3891*291a2b48SSukumar Swaminathan "status=%x value=%d (%d bytes)", 3892*291a2b48SSukumar Swaminathan mb->mbxStatus, value, 3893fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 3894fcf3ce44SJohn Forte } 3895fcf3ce44SJohn Forte } else { 3896*291a2b48SSukumar Swaminathan if (verbose && 3897*291a2b48SSukumar Swaminathan (cfg[CFG_PCI_MAX_READ].current != 3898fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].def)) { 3899fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3900fcf3ce44SJohn Forte "PCI_MAX_READ: Updated. %d bytes", 3901fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 3902fcf3ce44SJohn Forte } 3903fcf3ce44SJohn Forte } 3904fcf3ce44SJohn Forte 3905fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 3906fcf3ce44SJohn Forte 3907fcf3ce44SJohn Forte return; 3908fcf3ce44SJohn Forte 3909*291a2b48SSukumar Swaminathan } /* emlxs_pcix_mxr_update */ 3910fcf3ce44SJohn Forte 3911fcf3ce44SJohn Forte 3912fcf3ce44SJohn Forte 3913fcf3ce44SJohn Forte extern uint32_t 3914fcf3ce44SJohn Forte emlxs_get_key(emlxs_hba_t *hba, MAILBOX *mb) 3915fcf3ce44SJohn Forte { 3916fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3917fcf3ce44SJohn Forte uint32_t npname0, npname1; 3918fcf3ce44SJohn Forte uint32_t tmpkey, theKey; 3919fcf3ce44SJohn Forte uint16_t key850; 3920fcf3ce44SJohn Forte uint32_t t1, t2, t3, t4; 3921fcf3ce44SJohn Forte uint32_t ts; 3922fcf3ce44SJohn Forte 3923fcf3ce44SJohn Forte #define SEED 0x876EDC21 3924fcf3ce44SJohn Forte 3925fcf3ce44SJohn Forte /* This key is only used currently for SBUS adapters */ 3926fcf3ce44SJohn Forte if (hba->bus_type != SBUS_FC) { 3927fcf3ce44SJohn Forte return (0); 3928fcf3ce44SJohn Forte } 3929*291a2b48SSukumar Swaminathan 3930fcf3ce44SJohn Forte tmpkey = mb->un.varWords[30]; 3931fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_NVPARAMS); 3932fcf3ce44SJohn Forte 3933fcf3ce44SJohn Forte emlxs_mb_read_nv(hba, mb); 3934*291a2b48SSukumar Swaminathan if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 3935fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3936*291a2b48SSukumar Swaminathan "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand, 3937*291a2b48SSukumar Swaminathan mb->mbxStatus); 3938fcf3ce44SJohn Forte 3939fcf3ce44SJohn Forte return (0); 3940fcf3ce44SJohn Forte } 3941fcf3ce44SJohn Forte npname0 = mb->un.varRDnvp.portname[0]; 3942fcf3ce44SJohn Forte npname1 = mb->un.varRDnvp.portname[1]; 3943fcf3ce44SJohn Forte 3944fcf3ce44SJohn Forte key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 3945fcf3ce44SJohn Forte ts = (uint16_t)(npname1 + 1); 3946fcf3ce44SJohn Forte t1 = ts * key850; 3947fcf3ce44SJohn Forte ts = (uint16_t)((npname1 >> 16) + 1); 3948fcf3ce44SJohn Forte t2 = ts * key850; 3949fcf3ce44SJohn Forte ts = (uint16_t)(npname0 + 1); 3950fcf3ce44SJohn Forte t3 = ts * key850; 3951fcf3ce44SJohn Forte ts = (uint16_t)((npname0 >> 16) + 1); 3952fcf3ce44SJohn Forte t4 = ts * key850; 3953fcf3ce44SJohn Forte theKey = SEED + t1 + t2 + t3 + t4; 3954fcf3ce44SJohn Forte 3955fcf3ce44SJohn Forte return (theKey); 3956fcf3ce44SJohn Forte 3957*291a2b48SSukumar Swaminathan } /* emlxs_get_key() */ 3958*291a2b48SSukumar Swaminathan 3959*291a2b48SSukumar Swaminathan 3960*291a2b48SSukumar Swaminathan extern void 3961*291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba) 3962*291a2b48SSukumar Swaminathan { 3963*291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 3964*291a2b48SSukumar Swaminathan uint32_t i; 3965*291a2b48SSukumar Swaminathan 3966*291a2b48SSukumar Swaminathan /* Display firmware library one time */ 3967*291a2b48SSukumar Swaminathan for (i = 0; i < EMLXS_FW_COUNT; i++) { 3968*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s", 3969*291a2b48SSukumar Swaminathan emlxs_fw_table[i].label); 3970*291a2b48SSukumar Swaminathan } 3971*291a2b48SSukumar Swaminathan 3972*291a2b48SSukumar Swaminathan return; 3973*291a2b48SSukumar Swaminathan 3974*291a2b48SSukumar Swaminathan } /* emlxs_fw_show() */ 3975*291a2b48SSukumar Swaminathan 3976*291a2b48SSukumar Swaminathan 3977*291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 3978*291a2b48SSukumar Swaminathan static void 3979*291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw) 3980*291a2b48SSukumar Swaminathan { 3981*291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 3982*291a2b48SSukumar Swaminathan int (*emlxs_fw_get)(emlxs_firmware_t *); 3983*291a2b48SSukumar Swaminathan int err; 3984*291a2b48SSukumar Swaminathan 3985*291a2b48SSukumar Swaminathan /* Make sure image is unloaded and image buffer pointer is clear */ 3986*291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 3987*291a2b48SSukumar Swaminathan 3988*291a2b48SSukumar Swaminathan err = 0; 3989*291a2b48SSukumar Swaminathan hba->fw_modhandle = 3990*291a2b48SSukumar Swaminathan ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err); 3991*291a2b48SSukumar Swaminathan if (!hba->fw_modhandle) { 3992*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 3993*291a2b48SSukumar Swaminathan "Unable to load firmware module. error=%d", err); 3994*291a2b48SSukumar Swaminathan 3995*291a2b48SSukumar Swaminathan return; 3996*291a2b48SSukumar Swaminathan } else { 3997*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 3998*291a2b48SSukumar Swaminathan "Firmware module loaded."); 3999*291a2b48SSukumar Swaminathan } 4000*291a2b48SSukumar Swaminathan 4001*291a2b48SSukumar Swaminathan err = 0; 4002*291a2b48SSukumar Swaminathan emlxs_fw_get = 4003*291a2b48SSukumar Swaminathan (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err); 4004*291a2b48SSukumar Swaminathan if ((void *)emlxs_fw_get == NULL) { 4005*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 4006*291a2b48SSukumar Swaminathan "emlxs_fw_get not present. error=%d", err); 4007*291a2b48SSukumar Swaminathan 4008*291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 4009*291a2b48SSukumar Swaminathan return; 4010*291a2b48SSukumar Swaminathan } 4011*291a2b48SSukumar Swaminathan 4012*291a2b48SSukumar Swaminathan if (emlxs_fw_get(fw)) { 4013*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 4014*291a2b48SSukumar Swaminathan "Invalid firmware image module found. %s", fw->label); 4015*291a2b48SSukumar Swaminathan 4016*291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 4017*291a2b48SSukumar Swaminathan return; 4018*291a2b48SSukumar Swaminathan } 4019*291a2b48SSukumar Swaminathan 4020*291a2b48SSukumar Swaminathan return; 4021*291a2b48SSukumar Swaminathan 4022*291a2b48SSukumar Swaminathan } /* emlxs_fw_load() */ 4023*291a2b48SSukumar Swaminathan 4024*291a2b48SSukumar Swaminathan 4025*291a2b48SSukumar Swaminathan static void 4026*291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) 4027*291a2b48SSukumar Swaminathan { 4028*291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4029*291a2b48SSukumar Swaminathan 4030*291a2b48SSukumar Swaminathan /* Clear the firmware image */ 4031*291a2b48SSukumar Swaminathan fw->image = NULL; 4032*291a2b48SSukumar Swaminathan fw->size = 0; 4033*291a2b48SSukumar Swaminathan 4034*291a2b48SSukumar Swaminathan if (hba->fw_modhandle) { 4035*291a2b48SSukumar Swaminathan /* Close the module */ 4036*291a2b48SSukumar Swaminathan (void) ddi_modclose(hba->fw_modhandle); 4037*291a2b48SSukumar Swaminathan hba->fw_modhandle = NULL; 4038*291a2b48SSukumar Swaminathan 4039*291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 4040*291a2b48SSukumar Swaminathan "Firmware module unloaded."); 4041*291a2b48SSukumar Swaminathan } 4042*291a2b48SSukumar Swaminathan 4043*291a2b48SSukumar Swaminathan return; 4044*291a2b48SSukumar Swaminathan 4045*291a2b48SSukumar Swaminathan } /* emlxs_fw_unload() */ 4046*291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 4047