1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte 22*fcf3ce44SJohn Forte /* 23*fcf3ce44SJohn Forte * Copyright 2008 Emulex. All rights reserved. 24*fcf3ce44SJohn Forte * Use is subject to License terms. 25*fcf3ce44SJohn Forte */ 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte #define EMLXS_MODEL_DEF 29*fcf3ce44SJohn Forte 30*fcf3ce44SJohn Forte #include "emlxs.h" 31*fcf3ce44SJohn Forte 32*fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33*fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_HBA_C); 34*fcf3ce44SJohn Forte 35*fcf3ce44SJohn Forte static void emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy); 36*fcf3ce44SJohn Forte static uint32_t emlxs_get_attention(emlxs_hba_t *hba, uint32_t msgid); 37*fcf3ce44SJohn Forte static void emlxs_handle_link_event(emlxs_hba_t *hba); 38*fcf3ce44SJohn Forte static void emlxs_handle_ring_event(emlxs_hba_t *hba, int32_t ring, 39*fcf3ce44SJohn Forte uint32_t ha_copy); 40*fcf3ce44SJohn Forte static uint32_t emlxs_decode_biu_rev(uint32_t rev); 41*fcf3ce44SJohn Forte static uint32_t emlxs_decode_endec_rev(uint32_t rev); 42*fcf3ce44SJohn Forte static void emlxs_parse_prog_types(emlxs_hba_t *hba, char *types); 43*fcf3ce44SJohn Forte static int32_t emlxs_hba_init(emlxs_hba_t *hba); 44*fcf3ce44SJohn Forte static int32_t emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd, uint32_t size); 45*fcf3ce44SJohn Forte static void emlxs_proc_ring_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 46*fcf3ce44SJohn Forte static void emlxs_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 47*fcf3ce44SJohn Forte static void emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types); 48*fcf3ce44SJohn Forte static void emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 49*fcf3ce44SJohn Forte static void emlxs_process_link_speed(emlxs_hba_t *hba); 50*fcf3ce44SJohn Forte static int emlxs_handle_rcv_seq(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 51*fcf3ce44SJohn Forte static void emlxs_decode_label(char *label, char *buffer); 52*fcf3ce44SJohn Forte 53*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 54*fcf3ce44SJohn Forte static uint32_t emlxs_msi_intr(char *arg1, char *arg2); 55*fcf3ce44SJohn Forte uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 56*fcf3ce44SJohn Forte { 57*fcf3ce44SJohn Forte EMLXS_MSI_MAP1, 58*fcf3ce44SJohn Forte EMLXS_MSI_MAP2, 59*fcf3ce44SJohn Forte EMLXS_MSI_MAP4, 60*fcf3ce44SJohn Forte EMLXS_MSI_MAP8 61*fcf3ce44SJohn Forte }; 62*fcf3ce44SJohn Forte uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 63*fcf3ce44SJohn Forte { 64*fcf3ce44SJohn Forte EMLXS_MSI0_MASK1, 65*fcf3ce44SJohn Forte EMLXS_MSI0_MASK2, 66*fcf3ce44SJohn Forte EMLXS_MSI0_MASK4, 67*fcf3ce44SJohn Forte EMLXS_MSI0_MASK8 68*fcf3ce44SJohn Forte }; 69*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 70*fcf3ce44SJohn Forte 71*fcf3ce44SJohn Forte static int32_t emlxs_intx_intr(char *arg); 72*fcf3ce44SJohn Forte 73*fcf3ce44SJohn Forte 74*fcf3ce44SJohn Forte static uint32_t emlxs_disable_traffic_cop = 1; 75*fcf3ce44SJohn Forte 76*fcf3ce44SJohn Forte emlxs_table_t emlxs_ring_table[] = 77*fcf3ce44SJohn Forte { 78*fcf3ce44SJohn Forte {FC_FCP_RING, "FCP Ring"}, 79*fcf3ce44SJohn Forte {FC_IP_RING, "IP Ring"}, 80*fcf3ce44SJohn Forte {FC_ELS_RING, "ELS Ring"}, 81*fcf3ce44SJohn Forte {FC_CT_RING, "CT Ring"} 82*fcf3ce44SJohn Forte 83*fcf3ce44SJohn Forte }; /* emlxs_ring_table */ 84*fcf3ce44SJohn Forte 85*fcf3ce44SJohn Forte 86*fcf3ce44SJohn Forte emlxs_table_t emlxs_ffstate_table[] = 87*fcf3ce44SJohn Forte { 88*fcf3ce44SJohn Forte {0, "NULL"}, 89*fcf3ce44SJohn Forte {FC_ERROR, "ERROR"}, 90*fcf3ce44SJohn Forte {FC_KILLED, "KILLED"}, 91*fcf3ce44SJohn Forte {FC_WARM_START, "WARM_START"}, 92*fcf3ce44SJohn Forte {FC_INIT_START, "INIT_START"}, 93*fcf3ce44SJohn Forte {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 94*fcf3ce44SJohn Forte {FC_INIT_REV, "INIT_REV"}, 95*fcf3ce44SJohn Forte {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 96*fcf3ce44SJohn Forte {FC_INIT_CFGRING, "INIT_CFGRING"}, 97*fcf3ce44SJohn Forte {FC_INIT_INITLINK, "INIT_INITLINK"}, 98*fcf3ce44SJohn Forte {FC_LINK_DOWN, "LINK_DOWN"}, 99*fcf3ce44SJohn Forte {FC_LINK_UP, "LINK_UP"}, 100*fcf3ce44SJohn Forte {FC_CLEAR_LA, "CLEAR_LA"}, 101*fcf3ce44SJohn Forte {FC_READY, "READY"} 102*fcf3ce44SJohn Forte 103*fcf3ce44SJohn Forte }; /* emlxs_ffstate_table */ 104*fcf3ce44SJohn Forte 105*fcf3ce44SJohn Forte 106*fcf3ce44SJohn Forte 107*fcf3ce44SJohn Forte /* 108*fcf3ce44SJohn Forte * 109*fcf3ce44SJohn Forte * emlxs_ffinit 110*fcf3ce44SJohn Forte * This routine will start initialization of the FireFly Chipset 111*fcf3ce44SJohn Forte * 112*fcf3ce44SJohn Forte */ 113*fcf3ce44SJohn Forte extern int 114*fcf3ce44SJohn Forte emlxs_ffinit(emlxs_hba_t *hba) 115*fcf3ce44SJohn Forte { 116*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 117*fcf3ce44SJohn Forte emlxs_config_t *cfg; 118*fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 119*fcf3ce44SJohn Forte MAILBOX *mb; 120*fcf3ce44SJohn Forte RING *rp; 121*fcf3ce44SJohn Forte MATCHMAP *mp; 122*fcf3ce44SJohn Forte MATCHMAP *mp1; 123*fcf3ce44SJohn Forte uint8_t *inptr; 124*fcf3ce44SJohn Forte uint8_t *outptr; 125*fcf3ce44SJohn Forte uint32_t status; 126*fcf3ce44SJohn Forte uint32_t i; 127*fcf3ce44SJohn Forte uint32_t j; 128*fcf3ce44SJohn Forte uint32_t read_rev_reset; 129*fcf3ce44SJohn Forte uint32_t key = 0; 130*fcf3ce44SJohn Forte uint32_t fw_check; 131*fcf3ce44SJohn Forte uint32_t rval; 132*fcf3ce44SJohn Forte uint32_t offset; 133*fcf3ce44SJohn Forte uint8_t vpd_data[DMP_VPD_SIZE]; 134*fcf3ce44SJohn Forte uint32_t MaxRbusSize; 135*fcf3ce44SJohn Forte uint32_t MaxIbusSize; 136*fcf3ce44SJohn Forte uint32_t sli_mode; 137*fcf3ce44SJohn Forte 138*fcf3ce44SJohn Forte cfg = &CFG; 139*fcf3ce44SJohn Forte vpd = &VPD; 140*fcf3ce44SJohn Forte mb = 0; 141*fcf3ce44SJohn Forte MaxRbusSize = 0; 142*fcf3ce44SJohn Forte MaxIbusSize = 0; 143*fcf3ce44SJohn Forte read_rev_reset = 0; 144*fcf3ce44SJohn Forte sli_mode = 2; 145*fcf3ce44SJohn Forte 146*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 147*fcf3ce44SJohn Forte /* Initialize sli mode based on configuration parameter */ 148*fcf3ce44SJohn Forte switch (cfg[CFG_SLI_MODE].current) { 149*fcf3ce44SJohn Forte case 2: /* SLI2 mode */ 150*fcf3ce44SJohn Forte sli_mode = 2; 151*fcf3ce44SJohn Forte break; 152*fcf3ce44SJohn Forte 153*fcf3ce44SJohn Forte case 0: /* Best available */ 154*fcf3ce44SJohn Forte case 1: /* Best available */ 155*fcf3ce44SJohn Forte case 3: /* SLI3 mode */ 156*fcf3ce44SJohn Forte default: 157*fcf3ce44SJohn Forte /* SBUS adapters only available in SLI2 */ 158*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 159*fcf3ce44SJohn Forte sli_mode = 2; 160*fcf3ce44SJohn Forte } else { 161*fcf3ce44SJohn Forte sli_mode = 3; 162*fcf3ce44SJohn Forte } 163*fcf3ce44SJohn Forte break; 164*fcf3ce44SJohn Forte } 165*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 166*fcf3ce44SJohn Forte 167*fcf3ce44SJohn Forte /* Set the fw_check flag */ 168*fcf3ce44SJohn Forte fw_check = cfg[CFG_FW_CHECK].current; 169*fcf3ce44SJohn Forte 170*fcf3ce44SJohn Forte hba->mbox_queue_flag = 0; 171*fcf3ce44SJohn Forte hba->hc_copy = 0; 172*fcf3ce44SJohn Forte hba->fc_edtov = FF_DEF_EDTOV; 173*fcf3ce44SJohn Forte hba->fc_ratov = FF_DEF_RATOV; 174*fcf3ce44SJohn Forte hba->fc_altov = FF_DEF_ALTOV; 175*fcf3ce44SJohn Forte hba->fc_arbtov = FF_DEF_ARBTOV; 176*fcf3ce44SJohn Forte 177*fcf3ce44SJohn Forte reset: 178*fcf3ce44SJohn Forte 179*fcf3ce44SJohn Forte /* Reset and initialize the adapter */ 180*fcf3ce44SJohn Forte if (emlxs_hba_init(hba)) { 181*fcf3ce44SJohn Forte return (EIO); 182*fcf3ce44SJohn Forte } 183*fcf3ce44SJohn Forte /* 184*fcf3ce44SJohn Forte * Allocate some memory for buffers 185*fcf3ce44SJohn Forte */ 186*fcf3ce44SJohn Forte if (emlxs_mem_alloc_buffer(hba) == 0) { 187*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 188*fcf3ce44SJohn Forte "Unable to allocate memory buffers."); 189*fcf3ce44SJohn Forte 190*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 191*fcf3ce44SJohn Forte 192*fcf3ce44SJohn Forte return (ENOMEM); 193*fcf3ce44SJohn Forte } 194*fcf3ce44SJohn Forte /* 195*fcf3ce44SJohn Forte * Get a buffer which will be used repeatedly for mailbox commands 196*fcf3ce44SJohn Forte */ 197*fcf3ce44SJohn Forte if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 198*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 199*fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 200*fcf3ce44SJohn Forte 201*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 202*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 203*fcf3ce44SJohn Forte 204*fcf3ce44SJohn Forte return (ENOMEM); 205*fcf3ce44SJohn Forte } 206*fcf3ce44SJohn Forte /* Check for the LP9802 (This is a special case) */ 207*fcf3ce44SJohn Forte /* We need to check for dual channel adapter */ 208*fcf3ce44SJohn Forte if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) { 209*fcf3ce44SJohn Forte /* Try to determine if this is a DC adapter */ 210*fcf3ce44SJohn Forte if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 211*fcf3ce44SJohn Forte if (MaxRbusSize == REDUCED_SRAM_CFG) { 212*fcf3ce44SJohn Forte /* LP9802DC */ 213*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 214*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9802DC) { 215*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 216*fcf3ce44SJohn Forte &hba->model_info, 217*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 218*fcf3ce44SJohn Forte break; 219*fcf3ce44SJohn Forte } 220*fcf3ce44SJohn Forte } 221*fcf3ce44SJohn Forte } else if (hba->model_info.id != LP9802) { 222*fcf3ce44SJohn Forte /* LP9802 */ 223*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 224*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9802) { 225*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 226*fcf3ce44SJohn Forte &hba->model_info, 227*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 228*fcf3ce44SJohn Forte break; 229*fcf3ce44SJohn Forte } 230*fcf3ce44SJohn Forte } 231*fcf3ce44SJohn Forte } 232*fcf3ce44SJohn Forte } 233*fcf3ce44SJohn Forte } 234*fcf3ce44SJohn Forte /* 235*fcf3ce44SJohn Forte * Setup and issue mailbox READ REV command 236*fcf3ce44SJohn Forte */ 237*fcf3ce44SJohn Forte vpd->opFwRev = 0; 238*fcf3ce44SJohn Forte vpd->postKernRev = 0; 239*fcf3ce44SJohn Forte vpd->sli1FwRev = 0; 240*fcf3ce44SJohn Forte vpd->sli2FwRev = 0; 241*fcf3ce44SJohn Forte vpd->sli3FwRev = 0; 242*fcf3ce44SJohn Forte vpd->sli4FwRev = 0; 243*fcf3ce44SJohn Forte 244*fcf3ce44SJohn Forte vpd->postKernName[0] = 0; 245*fcf3ce44SJohn Forte vpd->opFwName[0] = 0; 246*fcf3ce44SJohn Forte vpd->sli1FwName[0] = 0; 247*fcf3ce44SJohn Forte vpd->sli2FwName[0] = 0; 248*fcf3ce44SJohn Forte vpd->sli3FwName[0] = 0; 249*fcf3ce44SJohn Forte vpd->sli4FwName[0] = 0; 250*fcf3ce44SJohn Forte 251*fcf3ce44SJohn Forte vpd->opFwLabel[0] = 0; 252*fcf3ce44SJohn Forte vpd->sli1FwLabel[0] = 0; 253*fcf3ce44SJohn Forte vpd->sli2FwLabel[0] = 0; 254*fcf3ce44SJohn Forte vpd->sli3FwLabel[0] = 0; 255*fcf3ce44SJohn Forte vpd->sli4FwLabel[0] = 0; 256*fcf3ce44SJohn Forte 257*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_REV); 258*fcf3ce44SJohn Forte emlxs_mb_read_rev(hba, mb, 0); 259*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 260*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 261*fcf3ce44SJohn Forte "Unable to read rev. Mailbox cmd=%x status=%x", 262*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 263*fcf3ce44SJohn Forte 264*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 265*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 266*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 267*fcf3ce44SJohn Forte 268*fcf3ce44SJohn Forte return (EIO); 269*fcf3ce44SJohn Forte } 270*fcf3ce44SJohn Forte if (mb->un.varRdRev.rr == 0) { 271*fcf3ce44SJohn Forte /* Old firmware */ 272*fcf3ce44SJohn Forte if (read_rev_reset == 0) { 273*fcf3ce44SJohn Forte /* Clean up */ 274*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 275*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 276*fcf3ce44SJohn Forte 277*fcf3ce44SJohn Forte read_rev_reset = 1; 278*fcf3ce44SJohn Forte 279*fcf3ce44SJohn Forte goto reset; 280*fcf3ce44SJohn Forte } else { 281*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 282*fcf3ce44SJohn Forte "Outdated firmware detected."); 283*fcf3ce44SJohn Forte } 284*fcf3ce44SJohn Forte 285*fcf3ce44SJohn Forte vpd->rBit = 0; 286*fcf3ce44SJohn Forte } else { 287*fcf3ce44SJohn Forte if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 288*fcf3ce44SJohn Forte if (read_rev_reset == 0) { 289*fcf3ce44SJohn Forte /* Clean up */ 290*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 291*fcf3ce44SJohn Forte (uint8_t *)mb); 292*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 293*fcf3ce44SJohn Forte 294*fcf3ce44SJohn Forte read_rev_reset = 1; 295*fcf3ce44SJohn Forte 296*fcf3ce44SJohn Forte goto reset; 297*fcf3ce44SJohn Forte } else { 298*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 299*fcf3ce44SJohn Forte "Non-operational firmware detected. " 300*fcf3ce44SJohn Forte "type=%x", 301*fcf3ce44SJohn Forte mb->un.varRdRev.un.b.ProgType); 302*fcf3ce44SJohn Forte } 303*fcf3ce44SJohn Forte } 304*fcf3ce44SJohn Forte vpd->rBit = 1; 305*fcf3ce44SJohn Forte vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 306*fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.sliFwName1, 307*fcf3ce44SJohn Forte vpd->sli1FwLabel, 16); 308*fcf3ce44SJohn Forte vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 309*fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.sliFwName2, 310*fcf3ce44SJohn Forte vpd->sli2FwLabel, 16); 311*fcf3ce44SJohn Forte 312*fcf3ce44SJohn Forte /* Lets try to read the SLI3 version */ 313*fcf3ce44SJohn Forte /* Setup and issue mailbox READ REV(v3) command */ 314*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_REV); 315*fcf3ce44SJohn Forte emlxs_mb_read_rev(hba, mb, 1); 316*fcf3ce44SJohn Forte 317*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 318*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 319*fcf3ce44SJohn Forte "Unable to read rev (v3). Mailbox cmd=%x status=%x", 320*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 321*fcf3ce44SJohn Forte 322*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 323*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 324*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 325*fcf3ce44SJohn Forte 326*fcf3ce44SJohn Forte return (EIO); 327*fcf3ce44SJohn Forte } 328*fcf3ce44SJohn Forte if (mb->un.varRdRev.rf3) { 329*fcf3ce44SJohn Forte /* 330*fcf3ce44SJohn Forte * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; Not 331*fcf3ce44SJohn Forte * needed 332*fcf3ce44SJohn Forte */ 333*fcf3ce44SJohn Forte vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 334*fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.sliFwName2, 335*fcf3ce44SJohn Forte vpd->sli3FwLabel, 16); 336*fcf3ce44SJohn Forte } 337*fcf3ce44SJohn Forte } 338*fcf3ce44SJohn Forte 339*fcf3ce44SJohn Forte /* Check sli mode against available firmware levels */ 340*fcf3ce44SJohn Forte if ((sli_mode == 4) && (vpd->sli4FwRev == 0)) { 341*fcf3ce44SJohn Forte if (vpd->sli3FwRev) { 342*fcf3ce44SJohn Forte sli_mode = 3; 343*fcf3ce44SJohn Forte } else if (vpd->sli2FwRev) { 344*fcf3ce44SJohn Forte sli_mode = 2; 345*fcf3ce44SJohn Forte } else { 346*fcf3ce44SJohn Forte sli_mode = 0; 347*fcf3ce44SJohn Forte } 348*fcf3ce44SJohn Forte } else if ((sli_mode == 3) && (vpd->sli3FwRev == 0)) { 349*fcf3ce44SJohn Forte if (vpd->sli4FwRev) { 350*fcf3ce44SJohn Forte sli_mode = 4; 351*fcf3ce44SJohn Forte } else if (vpd->sli2FwRev) { 352*fcf3ce44SJohn Forte sli_mode = 2; 353*fcf3ce44SJohn Forte } else { 354*fcf3ce44SJohn Forte sli_mode = 0; 355*fcf3ce44SJohn Forte } 356*fcf3ce44SJohn Forte } else if ((sli_mode == 2) && (vpd->sli2FwRev == 0)) { 357*fcf3ce44SJohn Forte if (vpd->sli4FwRev) { 358*fcf3ce44SJohn Forte sli_mode = 4; 359*fcf3ce44SJohn Forte } else if (vpd->sli3FwRev) { 360*fcf3ce44SJohn Forte sli_mode = 3; 361*fcf3ce44SJohn Forte } else { 362*fcf3ce44SJohn Forte sli_mode = 0; 363*fcf3ce44SJohn Forte } 364*fcf3ce44SJohn Forte } 365*fcf3ce44SJohn Forte if (sli_mode == 0) { 366*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 367*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 368*fcf3ce44SJohn Forte "Firmware not available. sli-mode=%d", 369*fcf3ce44SJohn Forte cfg[CFG_SLI_MODE].current); 370*fcf3ce44SJohn Forte #else 371*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 372*fcf3ce44SJohn Forte "Firmware not available. sli-mode=2"); 373*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 374*fcf3ce44SJohn Forte 375*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 376*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 377*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 378*fcf3ce44SJohn Forte 379*fcf3ce44SJohn Forte return (EIO); 380*fcf3ce44SJohn Forte } 381*fcf3ce44SJohn Forte /* Save information as VPD data */ 382*fcf3ce44SJohn Forte vpd->postKernRev = mb->un.varRdRev.postKernRev; 383*fcf3ce44SJohn Forte vpd->opFwRev = mb->un.varRdRev.opFwRev; 384*fcf3ce44SJohn Forte bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 385*fcf3ce44SJohn Forte vpd->biuRev = mb->un.varRdRev.biuRev; 386*fcf3ce44SJohn Forte vpd->smRev = mb->un.varRdRev.smRev; 387*fcf3ce44SJohn Forte vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 388*fcf3ce44SJohn Forte vpd->endecRev = mb->un.varRdRev.endecRev; 389*fcf3ce44SJohn Forte vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 390*fcf3ce44SJohn Forte vpd->fcphLow = mb->un.varRdRev.fcphLow; 391*fcf3ce44SJohn Forte vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 392*fcf3ce44SJohn Forte vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 393*fcf3ce44SJohn Forte 394*fcf3ce44SJohn Forte /* Decode FW names */ 395*fcf3ce44SJohn Forte emlxs_decode_version(vpd->postKernRev, vpd->postKernName); 396*fcf3ce44SJohn Forte emlxs_decode_version(vpd->opFwRev, vpd->opFwName); 397*fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName); 398*fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName); 399*fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName); 400*fcf3ce44SJohn Forte emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName); 401*fcf3ce44SJohn Forte 402*fcf3ce44SJohn Forte /* Decode FW labels */ 403*fcf3ce44SJohn Forte emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel); 404*fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel); 405*fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel); 406*fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel); 407*fcf3ce44SJohn Forte emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel); 408*fcf3ce44SJohn Forte 409*fcf3ce44SJohn Forte key = emlxs_get_key(hba, mb); 410*fcf3ce44SJohn Forte 411*fcf3ce44SJohn Forte /* Get adapter VPD information */ 412*fcf3ce44SJohn Forte offset = 0; 413*fcf3ce44SJohn Forte bzero(vpd_data, sizeof (vpd_data)); 414*fcf3ce44SJohn Forte vpd->port_index = (uint32_t)-1; 415*fcf3ce44SJohn Forte 416*fcf3ce44SJohn Forte while (offset < DMP_VPD_SIZE) { 417*fcf3ce44SJohn Forte emlxs_mb_dump_vpd(hba, mb, offset); 418*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 419*fcf3ce44SJohn Forte /* 420*fcf3ce44SJohn Forte * Let it go through even if failed.* 421*fcf3ce44SJohn Forte */ 422*fcf3ce44SJohn Forte /* 423*fcf3ce44SJohn Forte * Not all adapter's have VPD info and thus will fail 424*fcf3ce44SJohn Forte * here 425*fcf3ce44SJohn Forte */ 426*fcf3ce44SJohn Forte /* This is not a problem */ 427*fcf3ce44SJohn Forte 428*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 429*fcf3ce44SJohn Forte "No VPD found. offset=%x status=%x", 430*fcf3ce44SJohn Forte offset, mb->mbxStatus); 431*fcf3ce44SJohn Forte break; 432*fcf3ce44SJohn Forte } else { 433*fcf3ce44SJohn Forte if (mb->un.varDmp.ra == 1) { 434*fcf3ce44SJohn Forte uint32_t *lp1, *lp2; 435*fcf3ce44SJohn Forte uint32_t bsize; 436*fcf3ce44SJohn Forte uint32_t wsize; 437*fcf3ce44SJohn Forte 438*fcf3ce44SJohn Forte /* 439*fcf3ce44SJohn Forte * mb->un.varDmp.word_cnt is actually byte 440*fcf3ce44SJohn Forte * count for the dump reply 441*fcf3ce44SJohn Forte */ 442*fcf3ce44SJohn Forte bsize = mb->un.varDmp.word_cnt; 443*fcf3ce44SJohn Forte 444*fcf3ce44SJohn Forte /* Stop if no data was received */ 445*fcf3ce44SJohn Forte if (bsize == 0) { 446*fcf3ce44SJohn Forte break; 447*fcf3ce44SJohn Forte } 448*fcf3ce44SJohn Forte /* Check limit on byte size */ 449*fcf3ce44SJohn Forte bsize = (bsize > (sizeof (vpd_data) - offset)) ? 450*fcf3ce44SJohn Forte (sizeof (vpd_data) - offset) : bsize; 451*fcf3ce44SJohn Forte 452*fcf3ce44SJohn Forte /* 453*fcf3ce44SJohn Forte * Convert size from bytes to words with 454*fcf3ce44SJohn Forte * minimum of 1 word 455*fcf3ce44SJohn Forte */ 456*fcf3ce44SJohn Forte wsize = (bsize > 4) ? (bsize >> 2) : 1; 457*fcf3ce44SJohn Forte 458*fcf3ce44SJohn Forte /* 459*fcf3ce44SJohn Forte * Transfer data into vpd_data buffer one 460*fcf3ce44SJohn Forte * word at a time 461*fcf3ce44SJohn Forte */ 462*fcf3ce44SJohn Forte lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 463*fcf3ce44SJohn Forte lp2 = (uint32_t *)&vpd_data[offset]; 464*fcf3ce44SJohn Forte 465*fcf3ce44SJohn Forte for (i = 0; i < wsize; i++) { 466*fcf3ce44SJohn Forte status = *lp1++; 467*fcf3ce44SJohn Forte *lp2++ = SWAP_LONG(status); 468*fcf3ce44SJohn Forte } 469*fcf3ce44SJohn Forte 470*fcf3ce44SJohn Forte /* Increment total byte count saved */ 471*fcf3ce44SJohn Forte offset += (wsize << 2); 472*fcf3ce44SJohn Forte 473*fcf3ce44SJohn Forte /* 474*fcf3ce44SJohn Forte * Stop if less than a full transfer was 475*fcf3ce44SJohn Forte * received 476*fcf3ce44SJohn Forte */ 477*fcf3ce44SJohn Forte if (wsize < DMP_VPD_DUMP_WCOUNT) { 478*fcf3ce44SJohn Forte break; 479*fcf3ce44SJohn Forte } 480*fcf3ce44SJohn Forte } else { 481*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 482*fcf3ce44SJohn Forte "No VPD acknowledgment. offset=%x", offset); 483*fcf3ce44SJohn Forte break; 484*fcf3ce44SJohn Forte } 485*fcf3ce44SJohn Forte } 486*fcf3ce44SJohn Forte 487*fcf3ce44SJohn Forte } 488*fcf3ce44SJohn Forte 489*fcf3ce44SJohn Forte if (vpd_data[0]) { 490*fcf3ce44SJohn Forte 491*fcf3ce44SJohn Forte (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 492*fcf3ce44SJohn Forte 493*fcf3ce44SJohn Forte /* 494*fcf3ce44SJohn Forte * Some adapter models require the vpd data to identify the 495*fcf3ce44SJohn Forte * exact model 496*fcf3ce44SJohn Forte */ 497*fcf3ce44SJohn Forte 498*fcf3ce44SJohn Forte /* 499*fcf3ce44SJohn Forte * Check if vpd->part_num is now defined and the LP8000 500*fcf3ce44SJohn Forte * adapter (This is a special case) 501*fcf3ce44SJohn Forte */ 502*fcf3ce44SJohn Forte /* We need to look for LP8000DC */ 503*fcf3ce44SJohn Forte if ((hba->model_info.device_id == PCI_DEVICE_ID_LP8000) && 504*fcf3ce44SJohn Forte (vpd->part_num[0] != 0)) { 505*fcf3ce44SJohn Forte if (strncmp(vpd->part_num, "LP8000DC", 8) == 0) { 506*fcf3ce44SJohn Forte /* LP8000DC */ 507*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 508*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP8000DC) { 509*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 510*fcf3ce44SJohn Forte &hba->model_info, 511*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 512*fcf3ce44SJohn Forte break; 513*fcf3ce44SJohn Forte } 514*fcf3ce44SJohn Forte } 515*fcf3ce44SJohn Forte } else if (hba->model_info.id != LP8000) { 516*fcf3ce44SJohn Forte /* LP8000 */ 517*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 518*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP8000) { 519*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 520*fcf3ce44SJohn Forte &hba->model_info, 521*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 522*fcf3ce44SJohn Forte break; 523*fcf3ce44SJohn Forte } 524*fcf3ce44SJohn Forte } 525*fcf3ce44SJohn Forte } 526*fcf3ce44SJohn Forte } 527*fcf3ce44SJohn Forte /* PCI_DEVICE_ID_LP8000 */ 528*fcf3ce44SJohn Forte /* 529*fcf3ce44SJohn Forte * Check if vpd->part_num is now defined and the LP9002L 530*fcf3ce44SJohn Forte * adapter (This is a special case) 531*fcf3ce44SJohn Forte */ 532*fcf3ce44SJohn Forte /* 533*fcf3ce44SJohn Forte * We need to look for LP9002C, LP9002DC, and the LP9402DC 534*fcf3ce44SJohn Forte * adapters 535*fcf3ce44SJohn Forte */ 536*fcf3ce44SJohn Forte else if ((hba->model_info.device_id == PCI_DEVICE_ID_LP9002L) && 537*fcf3ce44SJohn Forte (vpd->part_num[0] != 0)) { 538*fcf3ce44SJohn Forte if (strncmp(vpd->part_num, "LP9002C", 7) == 0) { 539*fcf3ce44SJohn Forte /* LP9002C */ 540*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 541*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9002C) { 542*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 543*fcf3ce44SJohn Forte &hba->model_info, 544*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 545*fcf3ce44SJohn Forte break; 546*fcf3ce44SJohn Forte } 547*fcf3ce44SJohn Forte } 548*fcf3ce44SJohn Forte } else if (strncmp(vpd->part_num, "LP9002DC", 8) == 0) { 549*fcf3ce44SJohn Forte /* LP9002DC */ 550*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 551*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9002DC) { 552*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 553*fcf3ce44SJohn Forte &hba->model_info, 554*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 555*fcf3ce44SJohn Forte break; 556*fcf3ce44SJohn Forte } 557*fcf3ce44SJohn Forte } 558*fcf3ce44SJohn Forte } else if (strncmp(vpd->part_num, "LP9402DC", 8) == 0) { 559*fcf3ce44SJohn Forte /* LP9402DC */ 560*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 561*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9402DC) { 562*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 563*fcf3ce44SJohn Forte &hba->model_info, 564*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 565*fcf3ce44SJohn Forte break; 566*fcf3ce44SJohn Forte } 567*fcf3ce44SJohn Forte } 568*fcf3ce44SJohn Forte } else if (hba->model_info.id != LP9002L) { 569*fcf3ce44SJohn Forte /* LP9002 */ 570*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 571*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP9002L) { 572*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 573*fcf3ce44SJohn Forte &hba->model_info, 574*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 575*fcf3ce44SJohn Forte break; 576*fcf3ce44SJohn Forte } 577*fcf3ce44SJohn Forte } 578*fcf3ce44SJohn Forte } 579*fcf3ce44SJohn Forte } 580*fcf3ce44SJohn Forte /* PCI_DEVICE_ID_LP9002 */ 581*fcf3ce44SJohn Forte /* 582*fcf3ce44SJohn Forte * We need the vpd->part_num to decern between the LP10000DC 583*fcf3ce44SJohn Forte * and LP10000ExDC 584*fcf3ce44SJohn Forte */ 585*fcf3ce44SJohn Forte else if ((hba->model_info.device_id == PCI_DEVICE_ID_LP10000) && 586*fcf3ce44SJohn Forte (vpd->part_num[0] != 0)) { 587*fcf3ce44SJohn Forte if (strncmp(vpd->part_num, "LP10000DC", 9) == 0) { 588*fcf3ce44SJohn Forte /* LP10000DC */ 589*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 590*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == 591*fcf3ce44SJohn Forte LP10000DC) { 592*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 593*fcf3ce44SJohn Forte &hba->model_info, 594*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 595*fcf3ce44SJohn Forte break; 596*fcf3ce44SJohn Forte } 597*fcf3ce44SJohn Forte } 598*fcf3ce44SJohn Forte } else if (strncmp(vpd->part_num, "LP10000ExDC", 11) 599*fcf3ce44SJohn Forte == 0) { 600*fcf3ce44SJohn Forte /* LP10000ExDC */ 601*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 602*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == 603*fcf3ce44SJohn Forte LP10000ExDC) { 604*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 605*fcf3ce44SJohn Forte &hba->model_info, 606*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 607*fcf3ce44SJohn Forte break; 608*fcf3ce44SJohn Forte } 609*fcf3ce44SJohn Forte } 610*fcf3ce44SJohn Forte } else if (hba->model_info.id != LP10000) { 611*fcf3ce44SJohn Forte /* LP10000 */ 612*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 613*fcf3ce44SJohn Forte if (emlxs_pci_model[i].id == LP10000) { 614*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 615*fcf3ce44SJohn Forte &hba->model_info, 616*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 617*fcf3ce44SJohn Forte break; 618*fcf3ce44SJohn Forte } 619*fcf3ce44SJohn Forte } 620*fcf3ce44SJohn Forte } 621*fcf3ce44SJohn Forte } /* PCI_DEVICE_ID_LP10000 */ 622*fcf3ce44SJohn Forte /* Replace the default model description with vpd data */ 623*fcf3ce44SJohn Forte if (vpd->model_desc[0] != 0) { 624*fcf3ce44SJohn Forte (void) strcpy(hba->model_info.model_desc, 625*fcf3ce44SJohn Forte vpd->model_desc); 626*fcf3ce44SJohn Forte } 627*fcf3ce44SJohn Forte /* Replace the default model with vpd data */ 628*fcf3ce44SJohn Forte if (vpd->model[0] != 0) { 629*fcf3ce44SJohn Forte (void) strcpy(hba->model_info.model, vpd->model); 630*fcf3ce44SJohn Forte } 631*fcf3ce44SJohn Forte /* Replace the default program types with vpd data */ 632*fcf3ce44SJohn Forte if (vpd->prog_types[0] != 0) { 633*fcf3ce44SJohn Forte emlxs_parse_prog_types(hba, vpd->prog_types); 634*fcf3ce44SJohn Forte } 635*fcf3ce44SJohn Forte } 636*fcf3ce44SJohn Forte /* Since the adapter model may have changed with the vpd data */ 637*fcf3ce44SJohn Forte /* lets double check if adapter is not supported */ 638*fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 639*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 640*fcf3ce44SJohn Forte "Unsupported adapter found. Id:%d Device id:0x%x " 641*fcf3ce44SJohn Forte "SSDID:0x%x Model:%s", hba->model_info.id, 642*fcf3ce44SJohn Forte hba->model_info.device_id, hba->model_info.ssdid, 643*fcf3ce44SJohn Forte hba->model_info.model); 644*fcf3ce44SJohn Forte 645*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 646*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 647*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 648*fcf3ce44SJohn Forte 649*fcf3ce44SJohn Forte return (EIO); 650*fcf3ce44SJohn Forte } 651*fcf3ce44SJohn Forte /* Read the adapter's wakeup parms */ 652*fcf3ce44SJohn Forte (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 653*fcf3ce44SJohn Forte emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 654*fcf3ce44SJohn Forte vpd->boot_version); 655*fcf3ce44SJohn Forte 656*fcf3ce44SJohn Forte /* Get fcode version property */ 657*fcf3ce44SJohn Forte emlxs_get_fcode_version(hba); 658*fcf3ce44SJohn Forte 659*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 660*fcf3ce44SJohn Forte "Firmware: kern=%08x stub=%08x sli1=%08x", 661*fcf3ce44SJohn Forte vpd->postKernRev, vpd->opFwRev, vpd->sli1FwRev); 662*fcf3ce44SJohn Forte 663*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 664*fcf3ce44SJohn Forte "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", 665*fcf3ce44SJohn Forte vpd->sli2FwRev, vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 666*fcf3ce44SJohn Forte 667*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 668*fcf3ce44SJohn Forte "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 669*fcf3ce44SJohn Forte 670*fcf3ce44SJohn Forte /* 671*fcf3ce44SJohn Forte * If firmware checking is enabled and the adapter model indicates a 672*fcf3ce44SJohn Forte * firmware image, 673*fcf3ce44SJohn Forte */ 674*fcf3ce44SJohn Forte /* then perform firmware version check */ 675*fcf3ce44SJohn Forte if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) && 676*fcf3ce44SJohn Forte hba->model_info.fwid) || 677*fcf3ce44SJohn Forte ((fw_check == 2) && hba->model_info.fwid)) { 678*fcf3ce44SJohn Forte emlxs_image_t *image; 679*fcf3ce44SJohn Forte 680*fcf3ce44SJohn Forte /* Find firmware image indicated by adapter model */ 681*fcf3ce44SJohn Forte image = NULL; 682*fcf3ce44SJohn Forte for (i = 0; i < EMLXS_IMAGE_COUNT; i++) { 683*fcf3ce44SJohn Forte if (emlxs_fw_image[i].id == hba->model_info.fwid) { 684*fcf3ce44SJohn Forte image = &emlxs_fw_image[i]; 685*fcf3ce44SJohn Forte break; 686*fcf3ce44SJohn Forte } 687*fcf3ce44SJohn Forte } 688*fcf3ce44SJohn Forte 689*fcf3ce44SJohn Forte /* 690*fcf3ce44SJohn Forte * If the image was found, then verify current firmware 691*fcf3ce44SJohn Forte * versions of adapter 692*fcf3ce44SJohn Forte */ 693*fcf3ce44SJohn Forte if (image) { 694*fcf3ce44SJohn Forte if ((vpd->postKernRev != image->kern) || 695*fcf3ce44SJohn Forte (vpd->opFwRev != image->stub) || 696*fcf3ce44SJohn Forte (vpd->sli1FwRev != image->sli1) || 697*fcf3ce44SJohn Forte (vpd->sli2FwRev != image->sli2) || 698*fcf3ce44SJohn Forte (image->sli3 && (vpd->sli3FwRev != image->sli3)) || 699*fcf3ce44SJohn Forte (image->sli4 && (vpd->sli4FwRev != image->sli4))) { 700*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 701*fcf3ce44SJohn Forte "Firmware update needed. Updating... " 702*fcf3ce44SJohn Forte "(id=%d fw=%d)", hba->model_info.id, 703*fcf3ce44SJohn Forte hba->model_info.fwid); 704*fcf3ce44SJohn Forte 705*fcf3ce44SJohn Forte if (emlxs_fw_download(hba, 706*fcf3ce44SJohn Forte (char *)image->buffer, image->size, 0)) { 707*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 708*fcf3ce44SJohn Forte &emlxs_init_failed_msg, 709*fcf3ce44SJohn Forte "Firmware update failed."); 710*fcf3ce44SJohn Forte } 711*fcf3ce44SJohn Forte /* Clean up */ 712*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 713*fcf3ce44SJohn Forte (uint8_t *)mb); 714*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 715*fcf3ce44SJohn Forte 716*fcf3ce44SJohn Forte fw_check = 0; 717*fcf3ce44SJohn Forte 718*fcf3ce44SJohn Forte goto reset; 719*fcf3ce44SJohn Forte } 720*fcf3ce44SJohn Forte } else { 721*fcf3ce44SJohn Forte /* This should not happen */ 722*fcf3ce44SJohn Forte 723*fcf3ce44SJohn Forte /* 724*fcf3ce44SJohn Forte * This means either the adapter database is not 725*fcf3ce44SJohn Forte * correct or a firmware image is missing from the 726*fcf3ce44SJohn Forte * compile 727*fcf3ce44SJohn Forte */ 728*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 729*fcf3ce44SJohn Forte "Driver firmware image unavailable. (id=%d fw=%d)", 730*fcf3ce44SJohn Forte hba->model_info.id, hba->model_info.fwid); 731*fcf3ce44SJohn Forte } 732*fcf3ce44SJohn Forte 733*fcf3ce44SJohn Forte } 734*fcf3ce44SJohn Forte /* Add our interrupt routine to kernel's interrupt chain & enable it */ 735*fcf3ce44SJohn Forte /* 736*fcf3ce44SJohn Forte * If MSI is enabled this will cause Solaris to program the MSI 737*fcf3ce44SJohn Forte * address 738*fcf3ce44SJohn Forte */ 739*fcf3ce44SJohn Forte /* and data registers in PCI config space */ 740*fcf3ce44SJohn Forte if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 741*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 742*fcf3ce44SJohn Forte "Unable to add interrupt(s)."); 743*fcf3ce44SJohn Forte 744*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 745*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 746*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 747*fcf3ce44SJohn Forte 748*fcf3ce44SJohn Forte return (EIO); 749*fcf3ce44SJohn Forte } 750*fcf3ce44SJohn Forte /* 751*fcf3ce44SJohn Forte * Initialize cmd/rsp ring pointers 752*fcf3ce44SJohn Forte */ 753*fcf3ce44SJohn Forte for (i = 0; i < (uint32_t)hba->ring_count; i++) { 754*fcf3ce44SJohn Forte rp = &hba->ring[i]; 755*fcf3ce44SJohn Forte 756*fcf3ce44SJohn Forte rp->hba = hba; 757*fcf3ce44SJohn Forte rp->ringno = (uint8_t)i; 758*fcf3ce44SJohn Forte 759*fcf3ce44SJohn Forte rp->fc_iocbhd = 0; 760*fcf3ce44SJohn Forte rp->fc_iocbtl = 0; 761*fcf3ce44SJohn Forte rp->fc_cmdidx = 0; 762*fcf3ce44SJohn Forte rp->fc_rspidx = 0; 763*fcf3ce44SJohn Forte /* Used for pkt io */ 764*fcf3ce44SJohn Forte rp->fc_iotag = 1; 765*fcf3ce44SJohn Forte /* Used for abort or close XRI iotags */ 766*fcf3ce44SJohn Forte rp->fc_abort_iotag = rp->max_iotag; 767*fcf3ce44SJohn Forte 768*fcf3ce44SJohn Forte } 769*fcf3ce44SJohn Forte 770*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_CFGPORT); 771*fcf3ce44SJohn Forte (void) emlxs_mb_config_port(hba, mb, sli_mode, key); 772*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 773*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 774*fcf3ce44SJohn Forte "Unable to configure port. Mailbox cmd=%x status=%x " 775*fcf3ce44SJohn Forte "slimode=%d key=%x", mb->mbxCommand, mb->mbxStatus, 776*fcf3ce44SJohn Forte sli_mode, key); 777*fcf3ce44SJohn Forte 778*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 779*fcf3ce44SJohn Forte /* Try to fall back to SLI2 if possible */ 780*fcf3ce44SJohn Forte if (sli_mode >= 3) { 781*fcf3ce44SJohn Forte sli_mode = 2; 782*fcf3ce44SJohn Forte 783*fcf3ce44SJohn Forte /* Clean up */ 784*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 785*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 786*fcf3ce44SJohn Forte 787*fcf3ce44SJohn Forte fw_check = 0; 788*fcf3ce44SJohn Forte 789*fcf3ce44SJohn Forte goto reset; 790*fcf3ce44SJohn Forte } 791*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 792*fcf3ce44SJohn Forte 793*fcf3ce44SJohn Forte hba->flag &= ~FC_SLIM2_MODE; 794*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 795*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 796*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 797*fcf3ce44SJohn Forte 798*fcf3ce44SJohn Forte return (EIO); 799*fcf3ce44SJohn Forte } 800*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 801*fcf3ce44SJohn Forte /* Check if SLI3 mode was achieved */ 802*fcf3ce44SJohn Forte if (mb->un.varCfgPort.rMA && (mb->un.varCfgPort.sli_mode == 3)) { 803*fcf3ce44SJohn Forte hba->sli_mode = 3; 804*fcf3ce44SJohn Forte 805*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT 806*fcf3ce44SJohn Forte if (mb->un.varCfgPort.vpi_max > 1) { 807*fcf3ce44SJohn Forte hba->flag |= FC_NPIV_ENABLED; 808*fcf3ce44SJohn Forte 809*fcf3ce44SJohn Forte if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 810*fcf3ce44SJohn Forte hba->vpi_max = min(mb->un.varCfgPort.vpi_max, 811*fcf3ce44SJohn Forte MAX_VPORTS - 1); 812*fcf3ce44SJohn Forte } else { 813*fcf3ce44SJohn Forte hba->vpi_max = min(mb->un.varCfgPort.vpi_max, 814*fcf3ce44SJohn Forte MAX_VPORTS_LIMITED - 1); 815*fcf3ce44SJohn Forte } 816*fcf3ce44SJohn Forte } 817*fcf3ce44SJohn Forte #endif /* NPIV_SUPPORT */ 818*fcf3ce44SJohn Forte 819*fcf3ce44SJohn Forte if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 820*fcf3ce44SJohn Forte hba->flag |= FC_HBQ_ENABLED; 821*fcf3ce44SJohn Forte } 822*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 823*fcf3ce44SJohn Forte "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 824*fcf3ce44SJohn Forte } else { 825*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 826*fcf3ce44SJohn Forte "SLI2 mode: flag=%x", hba->flag); 827*fcf3ce44SJohn Forte } 828*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 829*fcf3ce44SJohn Forte 830*fcf3ce44SJohn Forte /* Get and save the current firmware version (based on sli_mode) */ 831*fcf3ce44SJohn Forte emlxs_decode_firmware_rev(hba, vpd); 832*fcf3ce44SJohn Forte 833*fcf3ce44SJohn Forte emlxs_pcix_mxr_update(hba, 0); 834*fcf3ce44SJohn Forte 835*fcf3ce44SJohn Forte /* 836*fcf3ce44SJohn Forte * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 837*fcf3ce44SJohn Forte */ 838*fcf3ce44SJohn Forte mp = 0; 839*fcf3ce44SJohn Forte mp1 = 0; 840*fcf3ce44SJohn Forte if (((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) || 841*fcf3ce44SJohn Forte ((mp1 = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0)) { 842*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 843*fcf3ce44SJohn Forte "Unable to allocate diag buffers."); 844*fcf3ce44SJohn Forte 845*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 846*fcf3ce44SJohn Forte 847*fcf3ce44SJohn Forte if (mp) { 848*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 849*fcf3ce44SJohn Forte } 850*fcf3ce44SJohn Forte if (mp1) { 851*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 852*fcf3ce44SJohn Forte } 853*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 854*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 855*fcf3ce44SJohn Forte 856*fcf3ce44SJohn Forte return (ENOMEM); 857*fcf3ce44SJohn Forte } 858*fcf3ce44SJohn Forte bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 859*fcf3ce44SJohn Forte MEM_ELSBUF_SIZE); 860*fcf3ce44SJohn Forte emlxs_mpdata_sync(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 861*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 862*fcf3ce44SJohn Forte 863*fcf3ce44SJohn Forte bzero(mp1->virt, MEM_ELSBUF_SIZE); 864*fcf3ce44SJohn Forte emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 865*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 866*fcf3ce44SJohn Forte 867*fcf3ce44SJohn Forte (void) emlxs_mb_run_biu_diag(hba, mb, mp->phys, mp1->phys); 868*fcf3ce44SJohn Forte 869*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 870*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 871*fcf3ce44SJohn Forte "Unable to run BIU diag. Mailbox cmd=%x status=%x", 872*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 873*fcf3ce44SJohn Forte 874*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 875*fcf3ce44SJohn Forte 876*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 877*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 878*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 879*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 880*fcf3ce44SJohn Forte 881*fcf3ce44SJohn Forte return (EIO); 882*fcf3ce44SJohn Forte } 883*fcf3ce44SJohn Forte emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 884*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 885*fcf3ce44SJohn Forte 886*fcf3ce44SJohn Forte outptr = mp->virt; 887*fcf3ce44SJohn Forte inptr = mp1->virt; 888*fcf3ce44SJohn Forte 889*fcf3ce44SJohn Forte for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 890*fcf3ce44SJohn Forte if (*outptr++ != *inptr++) { 891*fcf3ce44SJohn Forte outptr--; 892*fcf3ce44SJohn Forte inptr--; 893*fcf3ce44SJohn Forte 894*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 895*fcf3ce44SJohn Forte "BIU diagnostic failed. offset %x value %x " 896*fcf3ce44SJohn Forte "should be %x.", i, (uint32_t)*inptr, 897*fcf3ce44SJohn Forte (uint32_t)*outptr); 898*fcf3ce44SJohn Forte 899*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 900*fcf3ce44SJohn Forte 901*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 902*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 903*fcf3ce44SJohn Forte 904*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 905*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 906*fcf3ce44SJohn Forte 907*fcf3ce44SJohn Forte return (EIO); 908*fcf3ce44SJohn Forte } 909*fcf3ce44SJohn Forte } 910*fcf3ce44SJohn Forte 911*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 912*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 913*fcf3ce44SJohn Forte 914*fcf3ce44SJohn Forte /* 915*fcf3ce44SJohn Forte * Setup and issue mailbox CONFIGURE RING command 916*fcf3ce44SJohn Forte */ 917*fcf3ce44SJohn Forte for (i = 0; i < (uint32_t)hba->ring_count; i++) { 918*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_CFGRING); 919*fcf3ce44SJohn Forte emlxs_mb_config_ring(hba, i, mb); 920*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 921*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 922*fcf3ce44SJohn Forte "Unable to configure ring. Mailbox cmd=%x " 923*fcf3ce44SJohn Forte "status=%x", mb->mbxCommand, mb->mbxStatus); 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 926*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 927*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 928*fcf3ce44SJohn Forte 929*fcf3ce44SJohn Forte return (EIO); 930*fcf3ce44SJohn Forte } 931*fcf3ce44SJohn Forte } 932*fcf3ce44SJohn Forte 933*fcf3ce44SJohn Forte /* 934*fcf3ce44SJohn Forte * Setup link timers 935*fcf3ce44SJohn Forte */ 936*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_INITLINK); 937*fcf3ce44SJohn Forte emlxs_mb_config_link(hba, mb); 938*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 939*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 940*fcf3ce44SJohn Forte "Unable to configure link. Mailbox cmd=%x status=%x", 941*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 942*fcf3ce44SJohn Forte 943*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 944*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 945*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 946*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 947*fcf3ce44SJohn Forte 948*fcf3ce44SJohn Forte return (EIO); 949*fcf3ce44SJohn Forte } 950*fcf3ce44SJohn Forte #ifdef MAX_RRDY_PATCH 951*fcf3ce44SJohn Forte /* Set MAX_RRDY if one is provided */ 952*fcf3ce44SJohn Forte if (cfg[CFG_MAX_RRDY].current) { 953*fcf3ce44SJohn Forte emlxs_mb_set_var(hba, (MAILBOX *) mb, 0x00060412, 954*fcf3ce44SJohn Forte cfg[CFG_MAX_RRDY].current); 955*fcf3ce44SJohn Forte 956*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 957*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 958*fcf3ce44SJohn Forte "MAX_RRDY: Unable to set. status=%x value=%d", 959*fcf3ce44SJohn Forte mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 960*fcf3ce44SJohn Forte } else { 961*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 962*fcf3ce44SJohn Forte "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 963*fcf3ce44SJohn Forte } 964*fcf3ce44SJohn Forte } 965*fcf3ce44SJohn Forte #endif /* MAX_RRDY_PATCH */ 966*fcf3ce44SJohn Forte 967*fcf3ce44SJohn Forte /* 968*fcf3ce44SJohn Forte * We need to get login parameters for NID 969*fcf3ce44SJohn Forte */ 970*fcf3ce44SJohn Forte (void) emlxs_mb_read_sparam(hba, mb); 971*fcf3ce44SJohn Forte mp = (MATCHMAP *) (((MAILBOXQ *)mb)->bp); 972*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 973*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 974*fcf3ce44SJohn Forte "Unable to read parameters. Mailbox cmd=%x status=%x", 975*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 976*fcf3ce44SJohn Forte 977*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 978*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 979*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 980*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 981*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 982*fcf3ce44SJohn Forte 983*fcf3ce44SJohn Forte return (EIO); 984*fcf3ce44SJohn Forte } 985*fcf3ce44SJohn Forte /* Free the buffer since we were polling */ 986*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 987*fcf3ce44SJohn Forte 988*fcf3ce44SJohn Forte /* If no serial number in VPD data, then use the WWPN */ 989*fcf3ce44SJohn Forte if (vpd->serial_num[0] == 0) { 990*fcf3ce44SJohn Forte outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 991*fcf3ce44SJohn Forte for (i = 0; i < 12; i++) { 992*fcf3ce44SJohn Forte status = *outptr++; 993*fcf3ce44SJohn Forte j = ((status & 0xf0) >> 4); 994*fcf3ce44SJohn Forte if (j <= 9) { 995*fcf3ce44SJohn Forte vpd->serial_num[i] = 996*fcf3ce44SJohn Forte (char)((uint8_t)'0' + (uint8_t)j); 997*fcf3ce44SJohn Forte } else { 998*fcf3ce44SJohn Forte vpd->serial_num[i] = 999*fcf3ce44SJohn Forte (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1000*fcf3ce44SJohn Forte } 1001*fcf3ce44SJohn Forte 1002*fcf3ce44SJohn Forte i++; 1003*fcf3ce44SJohn Forte j = (status & 0xf); 1004*fcf3ce44SJohn Forte if (j <= 9) { 1005*fcf3ce44SJohn Forte vpd->serial_num[i] = 1006*fcf3ce44SJohn Forte (char)((uint8_t)'0' + (uint8_t)j); 1007*fcf3ce44SJohn Forte } else { 1008*fcf3ce44SJohn Forte vpd->serial_num[i] = 1009*fcf3ce44SJohn Forte (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1010*fcf3ce44SJohn Forte } 1011*fcf3ce44SJohn Forte } 1012*fcf3ce44SJohn Forte 1013*fcf3ce44SJohn Forte /* Set port number and port index to zero */ 1014*fcf3ce44SJohn Forte /* 1015*fcf3ce44SJohn Forte * The WWN's are unique to each port and therefore port_num 1016*fcf3ce44SJohn Forte * must equal zero 1017*fcf3ce44SJohn Forte */ 1018*fcf3ce44SJohn Forte /* 1019*fcf3ce44SJohn Forte * This effects the hba_fru_details structure in 1020*fcf3ce44SJohn Forte * fca_bind_port() 1021*fcf3ce44SJohn Forte */ 1022*fcf3ce44SJohn Forte vpd->port_num[0] = 0; 1023*fcf3ce44SJohn Forte vpd->port_index = 0; 1024*fcf3ce44SJohn Forte } 1025*fcf3ce44SJohn Forte /* Make first attempt to set a port index */ 1026*fcf3ce44SJohn Forte /* Check if this is a multifunction adapter */ 1027*fcf3ce44SJohn Forte if ((vpd->port_index == -1) && 1028*fcf3ce44SJohn Forte (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 1029*fcf3ce44SJohn Forte char *buffer; 1030*fcf3ce44SJohn Forte int32_t i; 1031*fcf3ce44SJohn Forte 1032*fcf3ce44SJohn Forte /* The port address looks like this: */ 1033*fcf3ce44SJohn Forte /* 1 - for port index 0 */ 1034*fcf3ce44SJohn Forte /* 1,1 - for port index 1 */ 1035*fcf3ce44SJohn Forte /* 1,2 - for port index 2 */ 1036*fcf3ce44SJohn Forte buffer = ddi_get_name_addr(hba->dip); 1037*fcf3ce44SJohn Forte 1038*fcf3ce44SJohn Forte if (buffer) { 1039*fcf3ce44SJohn Forte vpd->port_index = 0; 1040*fcf3ce44SJohn Forte 1041*fcf3ce44SJohn Forte /* Reverse scan for a comma */ 1042*fcf3ce44SJohn Forte for (i = strlen(buffer) - 1; i > 0; i--) { 1043*fcf3ce44SJohn Forte if (buffer[i] == ',') { 1044*fcf3ce44SJohn Forte /* Comma found - set index now */ 1045*fcf3ce44SJohn Forte vpd->port_index = 1046*fcf3ce44SJohn Forte emlxs_strtol(&buffer[i + 1], 10); 1047*fcf3ce44SJohn Forte break; 1048*fcf3ce44SJohn Forte } 1049*fcf3ce44SJohn Forte } 1050*fcf3ce44SJohn Forte } 1051*fcf3ce44SJohn Forte } 1052*fcf3ce44SJohn Forte /* Make final attempt to set a port index */ 1053*fcf3ce44SJohn Forte if (vpd->port_index == -1) { 1054*fcf3ce44SJohn Forte dev_info_t *p_dip; 1055*fcf3ce44SJohn Forte dev_info_t *c_dip; 1056*fcf3ce44SJohn Forte 1057*fcf3ce44SJohn Forte p_dip = ddi_get_parent(hba->dip); 1058*fcf3ce44SJohn Forte c_dip = ddi_get_child(p_dip); 1059*fcf3ce44SJohn Forte 1060*fcf3ce44SJohn Forte vpd->port_index = 0; 1061*fcf3ce44SJohn Forte while (c_dip && (hba->dip != c_dip)) { 1062*fcf3ce44SJohn Forte c_dip = ddi_get_next_sibling(c_dip); 1063*fcf3ce44SJohn Forte vpd->port_index++; 1064*fcf3ce44SJohn Forte } 1065*fcf3ce44SJohn Forte } 1066*fcf3ce44SJohn Forte if (vpd->port_num[0] == 0) { 1067*fcf3ce44SJohn Forte if (hba->model_info.channels > 1) { 1068*fcf3ce44SJohn Forte (void) sprintf(vpd->port_num, "%d", vpd->port_index); 1069*fcf3ce44SJohn Forte } 1070*fcf3ce44SJohn Forte } 1071*fcf3ce44SJohn Forte if (vpd->id[0] == 0) { 1072*fcf3ce44SJohn Forte (void) strcpy(vpd->id, hba->model_info.model_desc); 1073*fcf3ce44SJohn Forte } 1074*fcf3ce44SJohn Forte if (vpd->manufacturer[0] == 0) { 1075*fcf3ce44SJohn Forte (void) strcpy(vpd->manufacturer, hba->model_info.manufacturer); 1076*fcf3ce44SJohn Forte } 1077*fcf3ce44SJohn Forte if (vpd->part_num[0] == 0) { 1078*fcf3ce44SJohn Forte (void) strcpy(vpd->part_num, hba->model_info.model); 1079*fcf3ce44SJohn Forte } 1080*fcf3ce44SJohn Forte if (vpd->model_desc[0] == 0) { 1081*fcf3ce44SJohn Forte (void) strcpy(vpd->model_desc, hba->model_info.model_desc); 1082*fcf3ce44SJohn Forte } 1083*fcf3ce44SJohn Forte if (vpd->model[0] == 0) { 1084*fcf3ce44SJohn Forte (void) strcpy(vpd->model, hba->model_info.model); 1085*fcf3ce44SJohn Forte } 1086*fcf3ce44SJohn Forte if (vpd->prog_types[0] == 0) { 1087*fcf3ce44SJohn Forte emlxs_build_prog_types(hba, vpd->prog_types); 1088*fcf3ce44SJohn Forte } 1089*fcf3ce44SJohn Forte /* Create the symbolic names */ 1090*fcf3ce44SJohn Forte (void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s", 1091*fcf3ce44SJohn Forte hba->model_info.model, hba->vpd.fw_version, emlxs_version, 1092*fcf3ce44SJohn Forte (char *)utsname.nodename); 1093*fcf3ce44SJohn Forte 1094*fcf3ce44SJohn Forte (void) sprintf(hba->spn, 1095*fcf3ce44SJohn Forte "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1096*fcf3ce44SJohn Forte hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1097*fcf3ce44SJohn Forte hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1098*fcf3ce44SJohn Forte hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1099*fcf3ce44SJohn Forte 1100*fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1101*fcf3ce44SJohn Forte if ((hba->sparam.portName.nameType != NAME_IEEE) || 1102*fcf3ce44SJohn Forte (hba->sparam.portName.IEEEextMsn != 0) || 1103*fcf3ce44SJohn Forte (hba->sparam.portName.IEEEextLsb != 0)) { 1104*fcf3ce44SJohn Forte 1105*fcf3ce44SJohn Forte cfg[CFG_NETWORK_ON].current = 0; 1106*fcf3ce44SJohn Forte 1107*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1108*fcf3ce44SJohn Forte "WWPN doesn't conform to IP profile: nameType=%x", 1109*fcf3ce44SJohn Forte hba->sparam.portName.nameType); 1110*fcf3ce44SJohn Forte } 1111*fcf3ce44SJohn Forte /* Issue CONFIG FARP */ 1112*fcf3ce44SJohn Forte emlxs_mb_config_farp(hba, mb); 1113*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1114*fcf3ce44SJohn Forte /* 1115*fcf3ce44SJohn Forte * Let it go through even if failed. 1116*fcf3ce44SJohn Forte */ 1117*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1118*fcf3ce44SJohn Forte "Unable to configure FARP. Mailbox cmd=%x " 1119*fcf3ce44SJohn Forte "status=%x", mb->mbxCommand, mb->mbxStatus); 1120*fcf3ce44SJohn Forte } 1121*fcf3ce44SJohn Forte } 1122*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 1123*fcf3ce44SJohn Forte /* Configure MSI map if required */ 1124*fcf3ce44SJohn Forte if (hba->intr_count > 1) { 1125*fcf3ce44SJohn Forte emlxs_mb_config_msix(hba, mb, hba->intr_map, hba->intr_count); 1126*fcf3ce44SJohn Forte 1127*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) == MBX_SUCCESS) { 1128*fcf3ce44SJohn Forte goto msi_configured; 1129*fcf3ce44SJohn Forte } 1130*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1131*fcf3ce44SJohn Forte "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 1132*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1133*fcf3ce44SJohn Forte 1134*fcf3ce44SJohn Forte emlxs_mb_config_msi(hba, mb, hba->intr_map, hba->intr_count); 1135*fcf3ce44SJohn Forte 1136*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) == MBX_SUCCESS) { 1137*fcf3ce44SJohn Forte goto msi_configured; 1138*fcf3ce44SJohn Forte } 1139*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1140*fcf3ce44SJohn Forte "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 1141*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1142*fcf3ce44SJohn Forte 1143*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1144*fcf3ce44SJohn Forte "Attempting single interrupt mode..."); 1145*fcf3ce44SJohn Forte 1146*fcf3ce44SJohn Forte /* First cleanup old interrupts */ 1147*fcf3ce44SJohn Forte (void) emlxs_msi_remove(hba); 1148*fcf3ce44SJohn Forte (void) emlxs_msi_uninit(hba); 1149*fcf3ce44SJohn Forte 1150*fcf3ce44SJohn Forte status = emlxs_msi_init(hba, 1); 1151*fcf3ce44SJohn Forte 1152*fcf3ce44SJohn Forte if (status != DDI_SUCCESS) { 1153*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1154*fcf3ce44SJohn Forte "Unable to initialize interrupt. status=%d", 1155*fcf3ce44SJohn Forte status); 1156*fcf3ce44SJohn Forte 1157*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1158*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1159*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1160*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1161*fcf3ce44SJohn Forte 1162*fcf3ce44SJohn Forte return (EIO); 1163*fcf3ce44SJohn Forte } 1164*fcf3ce44SJohn Forte /* 1165*fcf3ce44SJohn Forte * Reset adapter - The adapter needs to be reset because the 1166*fcf3ce44SJohn Forte * bus cannot handle the MSI change without handshaking with 1167*fcf3ce44SJohn Forte * the adapter again 1168*fcf3ce44SJohn Forte */ 1169*fcf3ce44SJohn Forte 1170*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1171*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1172*fcf3ce44SJohn Forte fw_check = 0; 1173*fcf3ce44SJohn Forte goto reset; 1174*fcf3ce44SJohn Forte } 1175*fcf3ce44SJohn Forte msi_configured: 1176*fcf3ce44SJohn Forte 1177*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 1178*fcf3ce44SJohn Forte 1179*fcf3ce44SJohn Forte /* 1180*fcf3ce44SJohn Forte * We always disable the firmware traffic cop feature 1181*fcf3ce44SJohn Forte */ 1182*fcf3ce44SJohn Forte if (emlxs_disable_traffic_cop) { 1183*fcf3ce44SJohn Forte emlxs_disable_tc(hba, (MAILBOX *) mb); 1184*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1185*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1186*fcf3ce44SJohn Forte "Unable to disable traffic cop. Mailbox cmd=%x " 1187*fcf3ce44SJohn Forte "status=%x", mb->mbxCommand, mb->mbxStatus); 1188*fcf3ce44SJohn Forte 1189*fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1190*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1191*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1192*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1193*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1194*fcf3ce44SJohn Forte 1195*fcf3ce44SJohn Forte return (EIO); 1196*fcf3ce44SJohn Forte } 1197*fcf3ce44SJohn Forte } 1198*fcf3ce44SJohn Forte emlxs_mb_read_config(hba, (MAILBOX *) mb); 1199*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1200*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1201*fcf3ce44SJohn Forte "Unable to read configuration. Mailbox cmd=%x status=%x", 1202*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1203*fcf3ce44SJohn Forte 1204*fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1205*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1206*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1207*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1208*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1209*fcf3ce44SJohn Forte 1210*fcf3ce44SJohn Forte return (EIO); 1211*fcf3ce44SJohn Forte } 1212*fcf3ce44SJohn Forte /* Save the link speed capabilities */ 1213*fcf3ce44SJohn Forte vpd->link_speed = mb->un.varRdConfig.lmt; 1214*fcf3ce44SJohn Forte emlxs_process_link_speed(hba); 1215*fcf3ce44SJohn Forte 1216*fcf3ce44SJohn Forte /* Set the io throttle */ 1217*fcf3ce44SJohn Forte hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 1218*fcf3ce44SJohn Forte 1219*fcf3ce44SJohn Forte /* Set the max node count */ 1220*fcf3ce44SJohn Forte if (cfg[CFG_NUM_NODES].current > 0) { 1221*fcf3ce44SJohn Forte hba->max_nodes = 1222*fcf3ce44SJohn Forte min(cfg[CFG_NUM_NODES].current, mb->un.varRdConfig.max_rpi); 1223*fcf3ce44SJohn Forte } else { 1224*fcf3ce44SJohn Forte hba->max_nodes = mb->un.varRdConfig.max_rpi; 1225*fcf3ce44SJohn Forte } 1226*fcf3ce44SJohn Forte 1227*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_LINK_DOWN); 1228*fcf3ce44SJohn Forte 1229*fcf3ce44SJohn Forte /* Enable mailbox, error attention interrupts */ 1230*fcf3ce44SJohn Forte status = (uint32_t)(HC_MBINT_ENA | HC_ERINT_ENA); 1231*fcf3ce44SJohn Forte 1232*fcf3ce44SJohn Forte /* Enable ring interrupts */ 1233*fcf3ce44SJohn Forte if (hba->ring_count >= 4) { 1234*fcf3ce44SJohn Forte status |= (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA | 1235*fcf3ce44SJohn Forte HC_R0INT_ENA); 1236*fcf3ce44SJohn Forte } else if (hba->ring_count == 3) { 1237*fcf3ce44SJohn Forte status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA); 1238*fcf3ce44SJohn Forte } else if (hba->ring_count == 2) { 1239*fcf3ce44SJohn Forte status |= (HC_R1INT_ENA | HC_R0INT_ENA); 1240*fcf3ce44SJohn Forte } else if (hba->ring_count == 1) { 1241*fcf3ce44SJohn Forte status |= (HC_R0INT_ENA); 1242*fcf3ce44SJohn Forte } 1243*fcf3ce44SJohn Forte hba->hc_copy = status; 1244*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 1245*fcf3ce44SJohn Forte 1246*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 1247*fcf3ce44SJohn Forte 1248*fcf3ce44SJohn Forte if (hba->flag & FC_HBQ_ENABLED) { 1249*fcf3ce44SJohn Forte if (hba->tgt_mode) { 1250*fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 1251*fcf3ce44SJohn Forte return (ENOMEM); 1252*fcf3ce44SJohn Forte } 1253*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1254*fcf3ce44SJohn Forte "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1255*fcf3ce44SJohn Forte } 1256*fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1257*fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 1258*fcf3ce44SJohn Forte return (ENOMEM); 1259*fcf3ce44SJohn Forte } 1260*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1261*fcf3ce44SJohn Forte "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1262*fcf3ce44SJohn Forte } 1263*fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 1264*fcf3ce44SJohn Forte return (ENOMEM); 1265*fcf3ce44SJohn Forte } 1266*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1267*fcf3ce44SJohn Forte "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1268*fcf3ce44SJohn Forte 1269*fcf3ce44SJohn Forte if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 1270*fcf3ce44SJohn Forte return (ENOMEM); 1271*fcf3ce44SJohn Forte } 1272*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1273*fcf3ce44SJohn Forte "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1274*fcf3ce44SJohn Forte } else 1275*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 1276*fcf3ce44SJohn Forte { 1277*fcf3ce44SJohn Forte if (hba->tgt_mode) { 1278*fcf3ce44SJohn Forte /* Post the FCT unsol buffers */ 1279*fcf3ce44SJohn Forte rp = &hba->ring[FC_FCT_RING]; 1280*fcf3ce44SJohn Forte for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 1281*fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1282*fcf3ce44SJohn Forte } 1283*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1284*fcf3ce44SJohn Forte "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1285*fcf3ce44SJohn Forte } 1286*fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 1287*fcf3ce44SJohn Forte /* Post the IP unsol buffers */ 1288*fcf3ce44SJohn Forte rp = &hba->ring[FC_IP_RING]; 1289*fcf3ce44SJohn Forte for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 1290*fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1291*fcf3ce44SJohn Forte } 1292*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1293*fcf3ce44SJohn Forte "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1294*fcf3ce44SJohn Forte } 1295*fcf3ce44SJohn Forte /* Post the ELS unsol buffers */ 1296*fcf3ce44SJohn Forte rp = &hba->ring[FC_ELS_RING]; 1297*fcf3ce44SJohn Forte for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 1298*fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1299*fcf3ce44SJohn Forte } 1300*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1301*fcf3ce44SJohn Forte "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1302*fcf3ce44SJohn Forte 1303*fcf3ce44SJohn Forte 1304*fcf3ce44SJohn Forte /* Post the CT unsol buffers */ 1305*fcf3ce44SJohn Forte rp = &hba->ring[FC_CT_RING]; 1306*fcf3ce44SJohn Forte for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 1307*fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 2); 1308*fcf3ce44SJohn Forte } 1309*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1310*fcf3ce44SJohn Forte "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1311*fcf3ce44SJohn Forte } 1312*fcf3ce44SJohn Forte 1313*fcf3ce44SJohn Forte /* Register for async events */ 1314*fcf3ce44SJohn Forte emlxs_mb_async_event(hba, mb); 1315*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1316*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1317*fcf3ce44SJohn Forte "Async events disabled. Mailbox status=%x", mb->mbxStatus); 1318*fcf3ce44SJohn Forte } else { 1319*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1320*fcf3ce44SJohn Forte "Async events enabled."); 1321*fcf3ce44SJohn Forte hba->flag |= FC_ASYNC_EVENTS; 1322*fcf3ce44SJohn Forte } 1323*fcf3ce44SJohn Forte 1324*fcf3ce44SJohn Forte 1325*fcf3ce44SJohn Forte /* 1326*fcf3ce44SJohn Forte * Setup and issue mailbox INITIALIZE LINK command At this point, the 1327*fcf3ce44SJohn Forte * interrupt will be generated by the HW 1328*fcf3ce44SJohn Forte */ 1329*fcf3ce44SJohn Forte emlxs_mb_init_link(hba, mb, cfg[CFG_TOPOLOGY].current, 1330*fcf3ce44SJohn Forte cfg[CFG_LINK_SPEED].current); 1331*fcf3ce44SJohn Forte 1332*fcf3ce44SJohn Forte rval = emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0); 1333*fcf3ce44SJohn Forte 1334*fcf3ce44SJohn Forte if (rval != MBX_SUCCESS && rval != MBX_BUSY) { 1335*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1336*fcf3ce44SJohn Forte "Unable to initialize link. Mailbox cmd=%x status=%x", 1337*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 1338*fcf3ce44SJohn Forte 1339*fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1340*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 1341*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1342*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1343*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1344*fcf3ce44SJohn Forte 1345*fcf3ce44SJohn Forte return (EIO); 1346*fcf3ce44SJohn Forte } 1347*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1348*fcf3ce44SJohn Forte 1349*fcf3ce44SJohn Forte /* 1350*fcf3ce44SJohn Forte * Enable link attention interrupt 1351*fcf3ce44SJohn Forte */ 1352*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1353*fcf3ce44SJohn Forte hba->hc_copy |= HC_LAINT_ENA; 1354*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 1355*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1356*fcf3ce44SJohn Forte 1357*fcf3ce44SJohn Forte 1358*fcf3ce44SJohn Forte /* Wait for link to come up */ 1359*fcf3ce44SJohn Forte i = cfg[CFG_LINKUP_DELAY].current; 1360*fcf3ce44SJohn Forte while (i && (hba->state < FC_LINK_UP)) { 1361*fcf3ce44SJohn Forte /* Check for hardware error */ 1362*fcf3ce44SJohn Forte if (hba->state == FC_ERROR) { 1363*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1364*fcf3ce44SJohn Forte "Adapter error.", mb->mbxCommand, mb->mbxStatus); 1365*fcf3ce44SJohn Forte 1366*fcf3ce44SJohn Forte (void) EMLXS_INTR_REMOVE(hba); 1367*fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1368*fcf3ce44SJohn Forte (void) emlxs_mem_free_buffer(hba); 1369*fcf3ce44SJohn Forte 1370*fcf3ce44SJohn Forte return (EIO); 1371*fcf3ce44SJohn Forte } 1372*fcf3ce44SJohn Forte DELAYMS(1000); 1373*fcf3ce44SJohn Forte i--; 1374*fcf3ce44SJohn Forte } 1375*fcf3ce44SJohn Forte 1376*fcf3ce44SJohn Forte out: 1377*fcf3ce44SJohn Forte 1378*fcf3ce44SJohn Forte /* 1379*fcf3ce44SJohn Forte * The leadvile driver will now handle the FLOGI at the driver level 1380*fcf3ce44SJohn Forte */ 1381*fcf3ce44SJohn Forte 1382*fcf3ce44SJohn Forte return (0); 1383*fcf3ce44SJohn Forte 1384*fcf3ce44SJohn Forte } /* emlxs_ffinit() */ 1385*fcf3ce44SJohn Forte 1386*fcf3ce44SJohn Forte 1387*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 1388*fcf3ce44SJohn Forte 1389*fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 1390*fcf3ce44SJohn Forte int32_t 1391*fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 1392*fcf3ce44SJohn Forte { 1393*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1394*fcf3ce44SJohn Forte int32_t pass = 0; 1395*fcf3ce44SJohn Forte int32_t type = 0; 1396*fcf3ce44SJohn Forte char s_type[16]; 1397*fcf3ce44SJohn Forte int32_t types; 1398*fcf3ce44SJohn Forte int32_t count; 1399*fcf3ce44SJohn Forte int32_t nintrs; 1400*fcf3ce44SJohn Forte int32_t mode; 1401*fcf3ce44SJohn Forte int32_t actual; 1402*fcf3ce44SJohn Forte int32_t new_actual; 1403*fcf3ce44SJohn Forte int32_t i; 1404*fcf3ce44SJohn Forte int32_t ret; 1405*fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 1406*fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL; 1407*fcf3ce44SJohn Forte uint32_t *intr_pri = NULL; 1408*fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 1409*fcf3ce44SJohn Forte int32_t hilevel_pri; 1410*fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1411*fcf3ce44SJohn Forte char buf[64]; 1412*fcf3ce44SJohn Forte 1413*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1414*fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max)); 1415*fcf3ce44SJohn Forte } 1416*fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) { 1417*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1418*fcf3ce44SJohn Forte } 1419*fcf3ce44SJohn Forte /* Set max interrupt count if not specified */ 1420*fcf3ce44SJohn Forte if (max == 0) { 1421*fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) || 1422*fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) { 1423*fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS; 1424*fcf3ce44SJohn Forte } else { 1425*fcf3ce44SJohn Forte max = 1; 1426*fcf3ce44SJohn Forte } 1427*fcf3ce44SJohn Forte } 1428*fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */ 1429*fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 1430*fcf3ce44SJohn Forte max = hba->model_info.intr_limit; 1431*fcf3ce44SJohn Forte } 1432*fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */ 1433*fcf3ce44SJohn Forte types = 0; 1434*fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types); 1435*fcf3ce44SJohn Forte 1436*fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) { 1437*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1438*fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 1439*fcf3ce44SJohn Forte 1440*fcf3ce44SJohn Forte /* Default to fixed type */ 1441*fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED; 1442*fcf3ce44SJohn Forte } 1443*fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */ 1444*fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) { 1445*fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 1446*fcf3ce44SJohn Forte } 1447*fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */ 1448*fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) || 1449*fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) { 1450*fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1451*fcf3ce44SJohn Forte } 1452*fcf3ce44SJohn Forte begin: 1453*fcf3ce44SJohn Forte 1454*fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */ 1455*fcf3ce44SJohn Forte type = 0; 1456*fcf3ce44SJohn Forte 1457*fcf3ce44SJohn Forte /* Check if MSIX is fully supported */ 1458*fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) && 1459*fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 1460*fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1461*fcf3ce44SJohn Forte nintrs = 0; 1462*fcf3ce44SJohn Forte ret = 1463*fcf3ce44SJohn Forte ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, &nintrs); 1464*fcf3ce44SJohn Forte 1465*fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 1466*fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX; 1467*fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSIX"); 1468*fcf3ce44SJohn Forte goto initialize; 1469*fcf3ce44SJohn Forte } 1470*fcf3ce44SJohn Forte } 1471*fcf3ce44SJohn Forte /* Check if MSI is fully supported */ 1472*fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) && 1473*fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 1474*fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1475*fcf3ce44SJohn Forte nintrs = 0; 1476*fcf3ce44SJohn Forte ret = ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 1477*fcf3ce44SJohn Forte 1478*fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 1479*fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI; 1480*fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSI"); 1481*fcf3ce44SJohn Forte goto initialize; 1482*fcf3ce44SJohn Forte } 1483*fcf3ce44SJohn Forte } 1484*fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */ 1485*fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) && 1486*fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 1487*fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 1488*fcf3ce44SJohn Forte nintrs = 0; 1489*fcf3ce44SJohn Forte ret = 1490*fcf3ce44SJohn Forte ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, &nintrs); 1491*fcf3ce44SJohn Forte 1492*fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) { 1493*fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED; 1494*fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_FIXED"); 1495*fcf3ce44SJohn Forte goto initialize; 1496*fcf3ce44SJohn Forte } 1497*fcf3ce44SJohn Forte } 1498*fcf3ce44SJohn Forte goto init_failed; 1499*fcf3ce44SJohn Forte 1500*fcf3ce44SJohn Forte 1501*fcf3ce44SJohn Forte initialize: 1502*fcf3ce44SJohn Forte 1503*fcf3ce44SJohn Forte pass++; 1504*fcf3ce44SJohn Forte mode = 0; 1505*fcf3ce44SJohn Forte actual = 0; 1506*fcf3ce44SJohn Forte htable = NULL; 1507*fcf3ce44SJohn Forte intr_pri = NULL; 1508*fcf3ce44SJohn Forte intr_cap = NULL; 1509*fcf3ce44SJohn Forte hilevel_pri = 0; 1510*fcf3ce44SJohn Forte 1511*fcf3ce44SJohn Forte if (pass == 1) { 1512*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1513*fcf3ce44SJohn Forte "MSI: %s: mode=%d types=0x%x nintrs=%d", 1514*fcf3ce44SJohn Forte s_type, cfg[CFG_MSI_MODE].current, types, nintrs); 1515*fcf3ce44SJohn Forte } 1516*fcf3ce44SJohn Forte /* Validate interrupt count */ 1517*fcf3ce44SJohn Forte count = min(nintrs, max); 1518*fcf3ce44SJohn Forte 1519*fcf3ce44SJohn Forte if (count >= 8) { 1520*fcf3ce44SJohn Forte count = 8; 1521*fcf3ce44SJohn Forte } else if (count >= 4) { 1522*fcf3ce44SJohn Forte count = 4; 1523*fcf3ce44SJohn Forte } else if (count >= 2) { 1524*fcf3ce44SJohn Forte count = 2; 1525*fcf3ce44SJohn Forte } else { 1526*fcf3ce44SJohn Forte count = 1; 1527*fcf3ce44SJohn Forte } 1528*fcf3ce44SJohn Forte 1529*fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */ 1530*fcf3ce44SJohn Forte htable = 1531*fcf3ce44SJohn Forte kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), KM_SLEEP); 1532*fcf3ce44SJohn Forte 1533*fcf3ce44SJohn Forte if (htable == NULL) { 1534*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1535*fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt handle table"); 1536*fcf3ce44SJohn Forte 1537*fcf3ce44SJohn Forte goto init_failed; 1538*fcf3ce44SJohn Forte } 1539*fcf3ce44SJohn Forte /* Allocate 'count' interrupts */ 1540*fcf3ce44SJohn Forte ret = ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 1541*fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL); 1542*fcf3ce44SJohn Forte 1543*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1544*fcf3ce44SJohn Forte "MSI: %s: count=%d actual=%d", s_type, count, actual); 1545*fcf3ce44SJohn Forte 1546*fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) { 1547*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1548*fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret); 1549*fcf3ce44SJohn Forte 1550*fcf3ce44SJohn Forte goto init_failed; 1551*fcf3ce44SJohn Forte } 1552*fcf3ce44SJohn Forte if (actual != count) { 1553*fcf3ce44SJohn Forte /* Validate actual count */ 1554*fcf3ce44SJohn Forte if (actual >= 8) { 1555*fcf3ce44SJohn Forte new_actual = 8; 1556*fcf3ce44SJohn Forte } else if (actual >= 4) { 1557*fcf3ce44SJohn Forte new_actual = 4; 1558*fcf3ce44SJohn Forte } else if (actual >= 2) { 1559*fcf3ce44SJohn Forte new_actual = 2; 1560*fcf3ce44SJohn Forte } else { 1561*fcf3ce44SJohn Forte new_actual = 1; 1562*fcf3ce44SJohn Forte } 1563*fcf3ce44SJohn Forte 1564*fcf3ce44SJohn Forte if (new_actual < actual) { 1565*fcf3ce44SJohn Forte /* Free extra handles */ 1566*fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) { 1567*fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 1568*fcf3ce44SJohn Forte } 1569*fcf3ce44SJohn Forte 1570*fcf3ce44SJohn Forte actual = new_actual; 1571*fcf3ce44SJohn Forte } 1572*fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */ 1573*fcf3ce44SJohn Forte new_htable = 1574*fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 1575*fcf3ce44SJohn Forte KM_SLEEP); 1576*fcf3ce44SJohn Forte 1577*fcf3ce44SJohn Forte if (new_htable == NULL) { 1578*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1579*fcf3ce44SJohn Forte "MSI: Unable to allocate new interrupt handle " 1580*fcf3ce44SJohn Forte "table"); 1581*fcf3ce44SJohn Forte 1582*fcf3ce44SJohn Forte goto init_failed; 1583*fcf3ce44SJohn Forte } 1584*fcf3ce44SJohn Forte /* Copy old array to new array */ 1585*fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable, 1586*fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t))); 1587*fcf3ce44SJohn Forte 1588*fcf3ce44SJohn Forte /* Free the old array */ 1589*fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1590*fcf3ce44SJohn Forte 1591*fcf3ce44SJohn Forte htable = new_htable; 1592*fcf3ce44SJohn Forte count = actual; 1593*fcf3ce44SJohn Forte } 1594*fcf3ce44SJohn Forte /* Allocate interrupt priority table */ 1595*fcf3ce44SJohn Forte intr_pri = 1596*fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 1597*fcf3ce44SJohn Forte KM_SLEEP); 1598*fcf3ce44SJohn Forte 1599*fcf3ce44SJohn Forte if (intr_pri == NULL) { 1600*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1601*fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt priority table"); 1602*fcf3ce44SJohn Forte 1603*fcf3ce44SJohn Forte goto init_failed; 1604*fcf3ce44SJohn Forte } 1605*fcf3ce44SJohn Forte /* Allocate interrupt capability table */ 1606*fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 1607*fcf3ce44SJohn Forte 1608*fcf3ce44SJohn Forte if (intr_cap == NULL) { 1609*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1610*fcf3ce44SJohn Forte "MSI: Unable to allocate interrupt capability table"); 1611*fcf3ce44SJohn Forte 1612*fcf3ce44SJohn Forte goto init_failed; 1613*fcf3ce44SJohn Forte } 1614*fcf3ce44SJohn Forte /* Get minimum hilevel priority */ 1615*fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri(); 1616*fcf3ce44SJohn Forte 1617*fcf3ce44SJohn Forte /* Fill the priority and capability tables */ 1618*fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1619*fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 1620*fcf3ce44SJohn Forte 1621*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1622*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1623*fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. " 1624*fcf3ce44SJohn Forte "handle=%p ret=%d", i, &htable[i], ret); 1625*fcf3ce44SJohn Forte 1626*fcf3ce44SJohn Forte /* Clean up the interrupts */ 1627*fcf3ce44SJohn Forte goto init_failed; 1628*fcf3ce44SJohn Forte } 1629*fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) { 1630*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1631*fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. " 1632*fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x", 1633*fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri); 1634*fcf3ce44SJohn Forte 1635*fcf3ce44SJohn Forte /* Clean up the interrupts */ 1636*fcf3ce44SJohn Forte goto init_failed; 1637*fcf3ce44SJohn Forte } 1638*fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 1639*fcf3ce44SJohn Forte 1640*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1641*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1642*fcf3ce44SJohn Forte "MSI: ddi_intr_get_cap(%d) failed. handle=%p " 1643*fcf3ce44SJohn Forte "ret=%d", i, &htable[i], ret); 1644*fcf3ce44SJohn Forte 1645*fcf3ce44SJohn Forte /* Clean up the interrupts */ 1646*fcf3ce44SJohn Forte goto init_failed; 1647*fcf3ce44SJohn Forte } 1648*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1649*fcf3ce44SJohn Forte "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", 1650*fcf3ce44SJohn Forte s_type, i, intr_cap[i], intr_pri[i], hilevel_pri); 1651*fcf3ce44SJohn Forte 1652*fcf3ce44SJohn Forte } 1653*fcf3ce44SJohn Forte 1654*fcf3ce44SJohn Forte /* Set mode */ 1655*fcf3ce44SJohn Forte switch (count) { 1656*fcf3ce44SJohn Forte case 8: 1657*fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8; 1658*fcf3ce44SJohn Forte break; 1659*fcf3ce44SJohn Forte 1660*fcf3ce44SJohn Forte case 4: 1661*fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4; 1662*fcf3ce44SJohn Forte break; 1663*fcf3ce44SJohn Forte 1664*fcf3ce44SJohn Forte case 2: 1665*fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2; 1666*fcf3ce44SJohn Forte break; 1667*fcf3ce44SJohn Forte 1668*fcf3ce44SJohn Forte default: 1669*fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1; 1670*fcf3ce44SJohn Forte } 1671*fcf3ce44SJohn Forte 1672*fcf3ce44SJohn Forte /* Save the info */ 1673*fcf3ce44SJohn Forte hba->intr_htable = htable; 1674*fcf3ce44SJohn Forte hba->intr_count = count; 1675*fcf3ce44SJohn Forte hba->intr_pri = intr_pri; 1676*fcf3ce44SJohn Forte hba->intr_cap = intr_cap; 1677*fcf3ce44SJohn Forte hba->intr_type = type; 1678*fcf3ce44SJohn Forte hba->intr_arg = (void *)(unsigned long) intr_pri[0]; 1679*fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode]; 1680*fcf3ce44SJohn Forte 1681*fcf3ce44SJohn Forte hba->intr_cond = 0; 1682*fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1683*fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i]; 1684*fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i]; 1685*fcf3ce44SJohn Forte 1686*fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, 1687*fcf3ce44SJohn Forte hba->ddiinst, i); 1688*fcf3ce44SJohn Forte mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, 1689*fcf3ce44SJohn Forte (void *) hba->intr_arg); 1690*fcf3ce44SJohn Forte } 1691*fcf3ce44SJohn Forte 1692*fcf3ce44SJohn Forte /* Set flag to indicate support */ 1693*fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED; 1694*fcf3ce44SJohn Forte 1695*fcf3ce44SJohn Forte /* Create the interrupt threads */ 1696*fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 1697*fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 1698*fcf3ce44SJohn Forte hba->ddiinst, i); 1699*fcf3ce44SJohn Forte mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 1700*fcf3ce44SJohn Forte (void *) hba->intr_arg); 1701*fcf3ce44SJohn Forte 1702*fcf3ce44SJohn Forte emlxs_thread_create(hba, &hba->ring[i].intr_thread); 1703*fcf3ce44SJohn Forte } 1704*fcf3ce44SJohn Forte 1705*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1706*fcf3ce44SJohn Forte 1707*fcf3ce44SJohn Forte 1708*fcf3ce44SJohn Forte init_failed: 1709*fcf3ce44SJohn Forte 1710*fcf3ce44SJohn Forte if (intr_cap) { 1711*fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 1712*fcf3ce44SJohn Forte } 1713*fcf3ce44SJohn Forte if (intr_pri) { 1714*fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 1715*fcf3ce44SJohn Forte } 1716*fcf3ce44SJohn Forte if (htable) { 1717*fcf3ce44SJohn Forte /* Process the interrupt handlers */ 1718*fcf3ce44SJohn Forte for (i = 0; i < actual; i++) { 1719*fcf3ce44SJohn Forte /* Free the handle[i] */ 1720*fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 1721*fcf3ce44SJohn Forte } 1722*fcf3ce44SJohn Forte 1723*fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1724*fcf3ce44SJohn Forte } 1725*fcf3ce44SJohn Forte /* Initialize */ 1726*fcf3ce44SJohn Forte hba->intr_htable = NULL; 1727*fcf3ce44SJohn Forte hba->intr_count = 0; 1728*fcf3ce44SJohn Forte hba->intr_pri = NULL; 1729*fcf3ce44SJohn Forte hba->intr_cap = NULL; 1730*fcf3ce44SJohn Forte hba->intr_type = 0; 1731*fcf3ce44SJohn Forte hba->intr_arg = NULL; 1732*fcf3ce44SJohn Forte hba->intr_cond = 0; 1733*fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 1734*fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock)); 1735*fcf3ce44SJohn Forte 1736*fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) { 1737*fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1738*fcf3ce44SJohn Forte goto begin; 1739*fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) { 1740*fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 1741*fcf3ce44SJohn Forte goto begin; 1742*fcf3ce44SJohn Forte } 1743*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1744*fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts"); 1745*fcf3ce44SJohn Forte 1746*fcf3ce44SJohn Forte return (DDI_FAILURE); 1747*fcf3ce44SJohn Forte 1748*fcf3ce44SJohn Forte 1749*fcf3ce44SJohn Forte } /* emlxs_msi_init() */ 1750*fcf3ce44SJohn Forte 1751*fcf3ce44SJohn Forte 1752*fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 1753*fcf3ce44SJohn Forte int32_t 1754*fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba) 1755*fcf3ce44SJohn Forte { 1756*fcf3ce44SJohn Forte uint32_t count; 1757*fcf3ce44SJohn Forte int32_t i; 1758*fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 1759*fcf3ce44SJohn Forte uint32_t *intr_pri; 1760*fcf3ce44SJohn Forte int32_t *intr_cap; 1761*fcf3ce44SJohn Forte int32_t ret; 1762*fcf3ce44SJohn Forte 1763*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1764*fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba)); 1765*fcf3ce44SJohn Forte } 1766*fcf3ce44SJohn Forte /* 1767*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "MSI: 1768*fcf3ce44SJohn Forte * emlxs_msi_uninit called. flags=%x", hba->intr_flags); 1769*fcf3ce44SJohn Forte */ 1770*fcf3ce44SJohn Forte 1771*fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */ 1772*fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 1773*fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba); 1774*fcf3ce44SJohn Forte 1775*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1776*fcf3ce44SJohn Forte return (ret); 1777*fcf3ce44SJohn Forte } 1778*fcf3ce44SJohn Forte } 1779*fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 1780*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1781*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1782*fcf3ce44SJohn Forte } 1783*fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED; 1784*fcf3ce44SJohn Forte 1785*fcf3ce44SJohn Forte /* Get handle table parameters */ 1786*fcf3ce44SJohn Forte htable = hba->intr_htable; 1787*fcf3ce44SJohn Forte count = hba->intr_count; 1788*fcf3ce44SJohn Forte intr_pri = hba->intr_pri; 1789*fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 1790*fcf3ce44SJohn Forte 1791*fcf3ce44SJohn Forte /* Clean up */ 1792*fcf3ce44SJohn Forte hba->intr_count = 0; 1793*fcf3ce44SJohn Forte hba->intr_htable = NULL; 1794*fcf3ce44SJohn Forte hba->intr_pri = NULL; 1795*fcf3ce44SJohn Forte hba->intr_cap = NULL; 1796*fcf3ce44SJohn Forte hba->intr_type = 0; 1797*fcf3ce44SJohn Forte hba->intr_arg = NULL; 1798*fcf3ce44SJohn Forte hba->intr_cond = 0; 1799*fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 1800*fcf3ce44SJohn Forte 1801*fcf3ce44SJohn Forte if (intr_cap) { 1802*fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 1803*fcf3ce44SJohn Forte } 1804*fcf3ce44SJohn Forte if (intr_pri) { 1805*fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 1806*fcf3ce44SJohn Forte } 1807*fcf3ce44SJohn Forte if (htable) { 1808*fcf3ce44SJohn Forte /* Process the interrupt handlers */ 1809*fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1810*fcf3ce44SJohn Forte /* Free the handle[i] */ 1811*fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 1812*fcf3ce44SJohn Forte } 1813*fcf3ce44SJohn Forte 1814*fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1815*fcf3ce44SJohn Forte } 1816*fcf3ce44SJohn Forte /* Destroy the intr locks */ 1817*fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1818*fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]); 1819*fcf3ce44SJohn Forte } 1820*fcf3ce44SJohn Forte 1821*fcf3ce44SJohn Forte /* Destroy the interrupt threads */ 1822*fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 1823*fcf3ce44SJohn Forte emlxs_thread_destroy(&hba->ring[i].intr_thread); 1824*fcf3ce44SJohn Forte mutex_destroy(&hba->ring[i].rsp_lock); 1825*fcf3ce44SJohn Forte } 1826*fcf3ce44SJohn Forte 1827*fcf3ce44SJohn Forte /* 1828*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "MSI: 1829*fcf3ce44SJohn Forte * emlxs_msi_uninit done. flags=%x", hba->intr_flags); 1830*fcf3ce44SJohn Forte */ 1831*fcf3ce44SJohn Forte 1832*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1833*fcf3ce44SJohn Forte 1834*fcf3ce44SJohn Forte } /* emlxs_msi_uninit() */ 1835*fcf3ce44SJohn Forte 1836*fcf3ce44SJohn Forte 1837*fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */ 1838*fcf3ce44SJohn Forte int32_t 1839*fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba) 1840*fcf3ce44SJohn Forte { 1841*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1842*fcf3ce44SJohn Forte int32_t count; 1843*fcf3ce44SJohn Forte int32_t i; 1844*fcf3ce44SJohn Forte int32_t ret; 1845*fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 1846*fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 1847*fcf3ce44SJohn Forte 1848*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1849*fcf3ce44SJohn Forte return (emlxs_intx_add(hba)); 1850*fcf3ce44SJohn Forte } 1851*fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 1852*fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) { 1853*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1854*fcf3ce44SJohn Forte } 1855*fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 1856*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1857*fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0); 1858*fcf3ce44SJohn Forte 1859*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1860*fcf3ce44SJohn Forte return (ret); 1861*fcf3ce44SJohn Forte } 1862*fcf3ce44SJohn Forte } 1863*fcf3ce44SJohn Forte /* Get handle table parameters */ 1864*fcf3ce44SJohn Forte htable = hba->intr_htable; 1865*fcf3ce44SJohn Forte count = hba->intr_count; 1866*fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 1867*fcf3ce44SJohn Forte 1868*fcf3ce44SJohn Forte /* Add the interrupt handlers */ 1869*fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1870*fcf3ce44SJohn Forte /* add handler for handle[i] */ 1871*fcf3ce44SJohn Forte ret = ddi_intr_add_handler(htable[i], emlxs_msi_intr, 1872*fcf3ce44SJohn Forte (char *)hba, (char *)(unsigned long)i); 1873*fcf3ce44SJohn Forte 1874*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1875*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1876*fcf3ce44SJohn Forte "MSI: ddi_intr_add_handler(%d) failed. handle=%p " 1877*fcf3ce44SJohn Forte "ret=%d", i, &htable[i], ret); 1878*fcf3ce44SJohn Forte 1879*fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */ 1880*fcf3ce44SJohn Forte while (i) { 1881*fcf3ce44SJohn Forte /* Decrement i */ 1882*fcf3ce44SJohn Forte i--; 1883*fcf3ce44SJohn Forte 1884*fcf3ce44SJohn Forte /* Remove the handler */ 1885*fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 1886*fcf3ce44SJohn Forte 1887*fcf3ce44SJohn Forte } 1888*fcf3ce44SJohn Forte 1889*fcf3ce44SJohn Forte return (DDI_FAILURE); 1890*fcf3ce44SJohn Forte } 1891*fcf3ce44SJohn Forte } 1892*fcf3ce44SJohn Forte 1893*fcf3ce44SJohn Forte /* Enable the interrupts */ 1894*fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 1895*fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count); 1896*fcf3ce44SJohn Forte 1897*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1898*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1899*fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 1900*fcf3ce44SJohn Forte count, ret); 1901*fcf3ce44SJohn Forte 1902*fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1903*fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 1904*fcf3ce44SJohn Forte 1905*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1906*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1907*fcf3ce44SJohn Forte &emlxs_init_debug_msg, 1908*fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. " 1909*fcf3ce44SJohn Forte "ret=%d", i, ret); 1910*fcf3ce44SJohn Forte } 1911*fcf3ce44SJohn Forte } 1912*fcf3ce44SJohn Forte } 1913*fcf3ce44SJohn Forte } else { 1914*fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 1915*fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 1916*fcf3ce44SJohn Forte 1917*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1918*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1919*fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d", 1920*fcf3ce44SJohn Forte i, ret); 1921*fcf3ce44SJohn Forte } 1922*fcf3ce44SJohn Forte } 1923*fcf3ce44SJohn Forte } 1924*fcf3ce44SJohn Forte 1925*fcf3ce44SJohn Forte 1926*fcf3ce44SJohn Forte /* Set flag to indicate support */ 1927*fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED; 1928*fcf3ce44SJohn Forte 1929*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1930*fcf3ce44SJohn Forte 1931*fcf3ce44SJohn Forte } /* emlxs_msi_add() */ 1932*fcf3ce44SJohn Forte 1933*fcf3ce44SJohn Forte 1934*fcf3ce44SJohn Forte 1935*fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 1936*fcf3ce44SJohn Forte int32_t 1937*fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba) 1938*fcf3ce44SJohn Forte { 1939*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1940*fcf3ce44SJohn Forte uint32_t count; 1941*fcf3ce44SJohn Forte int32_t i; 1942*fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 1943*fcf3ce44SJohn Forte int32_t *intr_cap; 1944*fcf3ce44SJohn Forte int32_t ret; 1945*fcf3ce44SJohn Forte 1946*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1947*fcf3ce44SJohn Forte return (emlxs_intx_remove(hba)); 1948*fcf3ce44SJohn Forte } 1949*fcf3ce44SJohn Forte /* 1950*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "MSI: 1951*fcf3ce44SJohn Forte * emlxs_msi_remove called. flags=%x", hba->intr_flags); 1952*fcf3ce44SJohn Forte */ 1953*fcf3ce44SJohn Forte 1954*fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 1955*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 1956*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1957*fcf3ce44SJohn Forte } 1958*fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED; 1959*fcf3ce44SJohn Forte 1960*fcf3ce44SJohn Forte /* Disable all adapter interrupts */ 1961*fcf3ce44SJohn Forte hba->hc_copy = 0; 1962*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 1963*fcf3ce44SJohn Forte 1964*fcf3ce44SJohn Forte /* Get handle table parameters */ 1965*fcf3ce44SJohn Forte htable = hba->intr_htable; 1966*fcf3ce44SJohn Forte count = hba->intr_count; 1967*fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 1968*fcf3ce44SJohn Forte 1969*fcf3ce44SJohn Forte /* Disable the interrupts */ 1970*fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 1971*fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count); 1972*fcf3ce44SJohn Forte 1973*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1974*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1975*fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 1976*fcf3ce44SJohn Forte count, ret); 1977*fcf3ce44SJohn Forte 1978*fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 1979*fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 1980*fcf3ce44SJohn Forte 1981*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1982*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1983*fcf3ce44SJohn Forte &emlxs_init_debug_msg, 1984*fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. " 1985*fcf3ce44SJohn Forte "ret=%d", i, ret); 1986*fcf3ce44SJohn Forte } 1987*fcf3ce44SJohn Forte } 1988*fcf3ce44SJohn Forte } 1989*fcf3ce44SJohn Forte } else { 1990*fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 1991*fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 1992*fcf3ce44SJohn Forte 1993*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 1994*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1995*fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d", 1996*fcf3ce44SJohn Forte i, ret); 1997*fcf3ce44SJohn Forte } 1998*fcf3ce44SJohn Forte } 1999*fcf3ce44SJohn Forte } 2000*fcf3ce44SJohn Forte 2001*fcf3ce44SJohn Forte /* Process the interrupt handlers */ 2002*fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2003*fcf3ce44SJohn Forte /* Remove the handler */ 2004*fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 2005*fcf3ce44SJohn Forte 2006*fcf3ce44SJohn Forte 2007*fcf3ce44SJohn Forte } 2008*fcf3ce44SJohn Forte 2009*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2010*fcf3ce44SJohn Forte 2011*fcf3ce44SJohn Forte } /* emlxs_msi_remove() */ 2012*fcf3ce44SJohn Forte 2013*fcf3ce44SJohn Forte 2014*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 2015*fcf3ce44SJohn Forte 2016*fcf3ce44SJohn Forte 2017*fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 2018*fcf3ce44SJohn Forte /* ARGSUSED */ 2019*fcf3ce44SJohn Forte int32_t 2020*fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 2021*fcf3ce44SJohn Forte { 2022*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2023*fcf3ce44SJohn Forte int32_t ret; 2024*fcf3ce44SJohn Forte uint32_t i; 2025*fcf3ce44SJohn Forte char buf[64]; 2026*fcf3ce44SJohn Forte 2027*fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */ 2028*fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) { 2029*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2030*fcf3ce44SJohn Forte } 2031*fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */ 2032*fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 2033*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2034*fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x", 2035*fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags); 2036*fcf3ce44SJohn Forte 2037*fcf3ce44SJohn Forte return (DDI_FAILURE); 2038*fcf3ce44SJohn Forte } 2039*fcf3ce44SJohn Forte /* 2040*fcf3ce44SJohn Forte * Interrupt number '0' is a high-level interrupt. This driver does 2041*fcf3ce44SJohn Forte * not support having its interrupts mapped above scheduler priority; 2042*fcf3ce44SJohn Forte * i.e., we always expect to be able to call general kernel routines 2043*fcf3ce44SJohn Forte * that may invoke the scheduler. 2044*fcf3ce44SJohn Forte */ 2045*fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 2046*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2047*fcf3ce44SJohn Forte "INTX: High-level interrupt not supported."); 2048*fcf3ce44SJohn Forte 2049*fcf3ce44SJohn Forte return (DDI_FAILURE); 2050*fcf3ce44SJohn Forte } 2051*fcf3ce44SJohn Forte /* Get an iblock cookie */ 2052*fcf3ce44SJohn Forte ret = ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 2053*fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg); 2054*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2055*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2056*fcf3ce44SJohn Forte "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 2057*fcf3ce44SJohn Forte 2058*fcf3ce44SJohn Forte return (ret); 2059*fcf3ce44SJohn Forte } 2060*fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_INITED; 2061*fcf3ce44SJohn Forte 2062*fcf3ce44SJohn Forte /* Create the interrupt threads */ 2063*fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 2064*fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 2065*fcf3ce44SJohn Forte hba->ddiinst, i); 2066*fcf3ce44SJohn Forte mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 2067*fcf3ce44SJohn Forte (void *)hba->intr_arg); 2068*fcf3ce44SJohn Forte 2069*fcf3ce44SJohn Forte emlxs_thread_create(hba, &hba->ring[i].intr_thread); 2070*fcf3ce44SJohn Forte } 2071*fcf3ce44SJohn Forte 2072*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2073*fcf3ce44SJohn Forte 2074*fcf3ce44SJohn Forte } /* emlxs_intx_init() */ 2075*fcf3ce44SJohn Forte 2076*fcf3ce44SJohn Forte 2077*fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 2078*fcf3ce44SJohn Forte int32_t 2079*fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba) 2080*fcf3ce44SJohn Forte { 2081*fcf3ce44SJohn Forte int32_t ret; 2082*fcf3ce44SJohn Forte uint32_t i; 2083*fcf3ce44SJohn Forte 2084*fcf3ce44SJohn Forte /* Make sure interrupts have been removed */ 2085*fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 2086*fcf3ce44SJohn Forte ret = emlxs_intx_remove(hba); 2087*fcf3ce44SJohn Forte 2088*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2089*fcf3ce44SJohn Forte return (ret); 2090*fcf3ce44SJohn Forte } 2091*fcf3ce44SJohn Forte } 2092*fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 2093*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2094*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2095*fcf3ce44SJohn Forte } 2096*fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_INITED; 2097*fcf3ce44SJohn Forte 2098*fcf3ce44SJohn Forte hba->intr_arg = NULL; 2099*fcf3ce44SJohn Forte 2100*fcf3ce44SJohn Forte /* Create the interrupt threads */ 2101*fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 2102*fcf3ce44SJohn Forte emlxs_thread_destroy(&hba->ring[i].intr_thread); 2103*fcf3ce44SJohn Forte mutex_destroy(&hba->ring[i].rsp_lock); 2104*fcf3ce44SJohn Forte } 2105*fcf3ce44SJohn Forte 2106*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2107*fcf3ce44SJohn Forte 2108*fcf3ce44SJohn Forte } /* emlxs_intx_uninit() */ 2109*fcf3ce44SJohn Forte 2110*fcf3ce44SJohn Forte 2111*fcf3ce44SJohn Forte /* This is the legacy method for adding interrupts in Solaris */ 2112*fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */ 2113*fcf3ce44SJohn Forte int32_t 2114*fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba) 2115*fcf3ce44SJohn Forte { 2116*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2117*fcf3ce44SJohn Forte int32_t ret; 2118*fcf3ce44SJohn Forte 2119*fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 2120*fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_ADDED) { 2121*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2122*fcf3ce44SJohn Forte } 2123*fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 2124*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2125*fcf3ce44SJohn Forte ret = emlxs_intx_init(hba, 0); 2126*fcf3ce44SJohn Forte 2127*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2128*fcf3ce44SJohn Forte return (ret); 2129*fcf3ce44SJohn Forte } 2130*fcf3ce44SJohn Forte } 2131*fcf3ce44SJohn Forte /* add intrrupt handler routine */ 2132*fcf3ce44SJohn Forte ret = ddi_add_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 2133*fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg, (ddi_idevice_cookie_t *)0, 2134*fcf3ce44SJohn Forte (uint_t(*) ())emlxs_intx_intr, (caddr_t)hba); 2135*fcf3ce44SJohn Forte 2136*fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 2137*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 2138*fcf3ce44SJohn Forte "INTX: ddi_add_intr failed. ret=%d", ret); 2139*fcf3ce44SJohn Forte 2140*fcf3ce44SJohn Forte return (ret); 2141*fcf3ce44SJohn Forte } 2142*fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_ADDED; 2143*fcf3ce44SJohn Forte 2144*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2145*fcf3ce44SJohn Forte 2146*fcf3ce44SJohn Forte } /* emlxs_intx_add() */ 2147*fcf3ce44SJohn Forte 2148*fcf3ce44SJohn Forte 2149*fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 2150*fcf3ce44SJohn Forte int32_t 2151*fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba) 2152*fcf3ce44SJohn Forte { 2153*fcf3ce44SJohn Forte 2154*fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 2155*fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 2156*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2157*fcf3ce44SJohn Forte } 2158*fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_ADDED; 2159*fcf3ce44SJohn Forte 2160*fcf3ce44SJohn Forte /* Diable all adapter interrupts */ 2161*fcf3ce44SJohn Forte hba->hc_copy = 0; 2162*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 2163*fcf3ce44SJohn Forte 2164*fcf3ce44SJohn Forte /* Remove the interrupt */ 2165*fcf3ce44SJohn Forte (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 2166*fcf3ce44SJohn Forte hba->intr_arg); 2167*fcf3ce44SJohn Forte 2168*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2169*fcf3ce44SJohn Forte 2170*fcf3ce44SJohn Forte } /* emlxs_intx_remove() */ 2171*fcf3ce44SJohn Forte 2172*fcf3ce44SJohn Forte 2173*fcf3ce44SJohn Forte extern int 2174*fcf3ce44SJohn Forte emlxs_hba_init(emlxs_hba_t *hba) 2175*fcf3ce44SJohn Forte { 2176*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2177*fcf3ce44SJohn Forte emlxs_port_t *vport; 2178*fcf3ce44SJohn Forte emlxs_config_t *cfg; 2179*fcf3ce44SJohn Forte int32_t i; 2180*fcf3ce44SJohn Forte 2181*fcf3ce44SJohn Forte cfg = &CFG; 2182*fcf3ce44SJohn Forte i = 0; 2183*fcf3ce44SJohn Forte 2184*fcf3ce44SJohn Forte /* Restart the adapter */ 2185*fcf3ce44SJohn Forte if (emlxs_hba_reset(hba, 1, 0)) { 2186*fcf3ce44SJohn Forte return (1); 2187*fcf3ce44SJohn Forte } 2188*fcf3ce44SJohn Forte hba->ring_count = MAX_RINGS; /* number of rings used */ 2189*fcf3ce44SJohn Forte 2190*fcf3ce44SJohn Forte /* WARNING: There is a max of 6 ring masks allowed */ 2191*fcf3ce44SJohn Forte /* 2192*fcf3ce44SJohn Forte * RING 0 - FCP 2193*fcf3ce44SJohn Forte */ 2194*fcf3ce44SJohn Forte if (hba->tgt_mode) { 2195*fcf3ce44SJohn Forte hba->ring_masks[FC_FCP_RING] = 1; 2196*fcf3ce44SJohn Forte hba->ring_rval[i] = FC_FCP_CMND; 2197*fcf3ce44SJohn Forte hba->ring_rmask[i] = 0; 2198*fcf3ce44SJohn Forte hba->ring_tval[i] = FC_FCP_DATA; 2199*fcf3ce44SJohn Forte hba->ring_tmask[i++] = 0xFF; 2200*fcf3ce44SJohn Forte } else { 2201*fcf3ce44SJohn Forte hba->ring_masks[FC_FCP_RING] = 0; 2202*fcf3ce44SJohn Forte } 2203*fcf3ce44SJohn Forte 2204*fcf3ce44SJohn Forte hba->ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES; 2205*fcf3ce44SJohn Forte hba->ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES; 2206*fcf3ce44SJohn Forte 2207*fcf3ce44SJohn Forte /* 2208*fcf3ce44SJohn Forte * RING 1 - IP 2209*fcf3ce44SJohn Forte */ 2210*fcf3ce44SJohn Forte if (cfg[CFG_NETWORK_ON].current) { 2211*fcf3ce44SJohn Forte hba->ring_masks[FC_IP_RING] = 1; 2212*fcf3ce44SJohn Forte hba->ring_rval[i] = FC_UNSOL_DATA; /* Unsolicited Data */ 2213*fcf3ce44SJohn Forte hba->ring_rmask[i] = 0xFF; 2214*fcf3ce44SJohn Forte hba->ring_tval[i] = FC_LLC_SNAP; /* LLC/SNAP */ 2215*fcf3ce44SJohn Forte hba->ring_tmask[i++] = 0xFF; 2216*fcf3ce44SJohn Forte } else { 2217*fcf3ce44SJohn Forte hba->ring_masks[FC_IP_RING] = 0; 2218*fcf3ce44SJohn Forte } 2219*fcf3ce44SJohn Forte 2220*fcf3ce44SJohn Forte hba->ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES; 2221*fcf3ce44SJohn Forte hba->ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES; 2222*fcf3ce44SJohn Forte 2223*fcf3ce44SJohn Forte /* 2224*fcf3ce44SJohn Forte * RING 2 - ELS 2225*fcf3ce44SJohn Forte */ 2226*fcf3ce44SJohn Forte hba->ring_masks[FC_ELS_RING] = 1; 2227*fcf3ce44SJohn Forte hba->ring_rval[i] = FC_ELS_REQ; /* ELS request/response */ 2228*fcf3ce44SJohn Forte hba->ring_rmask[i] = 0xFE; 2229*fcf3ce44SJohn Forte hba->ring_tval[i] = FC_ELS_DATA; /* ELS */ 2230*fcf3ce44SJohn Forte hba->ring_tmask[i++] = 0xFF; 2231*fcf3ce44SJohn Forte 2232*fcf3ce44SJohn Forte hba->ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES; 2233*fcf3ce44SJohn Forte hba->ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES; 2234*fcf3ce44SJohn Forte 2235*fcf3ce44SJohn Forte /* 2236*fcf3ce44SJohn Forte * RING 3 - CT 2237*fcf3ce44SJohn Forte */ 2238*fcf3ce44SJohn Forte hba->ring_masks[FC_CT_RING] = 1; 2239*fcf3ce44SJohn Forte hba->ring_rval[i] = FC_UNSOL_CTL; /* CT request/response */ 2240*fcf3ce44SJohn Forte hba->ring_rmask[i] = 0xFE; 2241*fcf3ce44SJohn Forte hba->ring_tval[i] = FC_CT_TYPE; /* CT */ 2242*fcf3ce44SJohn Forte hba->ring_tmask[i++] = 0xFF; 2243*fcf3ce44SJohn Forte 2244*fcf3ce44SJohn Forte hba->ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES; 2245*fcf3ce44SJohn Forte hba->ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES; 2246*fcf3ce44SJohn Forte 2247*fcf3ce44SJohn Forte if (i > 6) { 2248*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 2249*fcf3ce44SJohn Forte "emlxs_hba_init: Too many ring masks defined. cnt=%d", i); 2250*fcf3ce44SJohn Forte return (1); 2251*fcf3ce44SJohn Forte } 2252*fcf3ce44SJohn Forte /* Initialize all the port objects */ 2253*fcf3ce44SJohn Forte hba->vpi_max = 1; 2254*fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 2255*fcf3ce44SJohn Forte vport = &VPORT(i); 2256*fcf3ce44SJohn Forte vport->hba = hba; 2257*fcf3ce44SJohn Forte vport->vpi = i; 2258*fcf3ce44SJohn Forte } 2259*fcf3ce44SJohn Forte 2260*fcf3ce44SJohn Forte /* 2261*fcf3ce44SJohn Forte * Initialize the max_node count to a default value if needed 2262*fcf3ce44SJohn Forte * This determines how many node objects we preallocate in the pool 2263*fcf3ce44SJohn Forte * The actual max_nodes will be set later based on adapter info 2264*fcf3ce44SJohn Forte */ 2265*fcf3ce44SJohn Forte if (hba->max_nodes == 0) { 2266*fcf3ce44SJohn Forte if (cfg[CFG_NUM_NODES].current > 0) { 2267*fcf3ce44SJohn Forte hba->max_nodes = cfg[CFG_NUM_NODES].current; 2268*fcf3ce44SJohn Forte } else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 2269*fcf3ce44SJohn Forte hba->max_nodes = 4096; 2270*fcf3ce44SJohn Forte } else { 2271*fcf3ce44SJohn Forte hba->max_nodes = 512; 2272*fcf3ce44SJohn Forte } 2273*fcf3ce44SJohn Forte } 2274*fcf3ce44SJohn Forte return (0); 2275*fcf3ce44SJohn Forte 2276*fcf3ce44SJohn Forte } /* emlxs_hba_init() */ 2277*fcf3ce44SJohn Forte 2278*fcf3ce44SJohn Forte 2279*fcf3ce44SJohn Forte static void 2280*fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba) 2281*fcf3ce44SJohn Forte { 2282*fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 2283*fcf3ce44SJohn Forte emlxs_config_t *cfg; 2284*fcf3ce44SJohn Forte char *cptr; 2285*fcf3ce44SJohn Forte uint32_t hi; 2286*fcf3ce44SJohn Forte 2287*fcf3ce44SJohn Forte /* 2288*fcf3ce44SJohn Forte * This routine modifies the link-speed config parameter entry based 2289*fcf3ce44SJohn Forte * on adapter capabilities 2290*fcf3ce44SJohn Forte */ 2291*fcf3ce44SJohn Forte vpd = &VPD; 2292*fcf3ce44SJohn Forte cfg = &hba->config[CFG_LINK_SPEED]; 2293*fcf3ce44SJohn Forte 2294*fcf3ce44SJohn Forte cptr = cfg->help; 2295*fcf3ce44SJohn Forte (void) strcpy(cptr, "Select link speed. [0=Auto"); 2296*fcf3ce44SJohn Forte cptr += 26; 2297*fcf3ce44SJohn Forte hi = 0; 2298*fcf3ce44SJohn Forte 2299*fcf3ce44SJohn Forte if (vpd->link_speed & LMT_1GB_CAPABLE) { 2300*fcf3ce44SJohn Forte (void) strcpy(cptr, ", 1=1Gb"); 2301*fcf3ce44SJohn Forte cptr += 7; 2302*fcf3ce44SJohn Forte hi = 1; 2303*fcf3ce44SJohn Forte } 2304*fcf3ce44SJohn Forte if (vpd->link_speed & LMT_2GB_CAPABLE) { 2305*fcf3ce44SJohn Forte (void) strcpy(cptr, ", 2=2Gb"); 2306*fcf3ce44SJohn Forte cptr += 7; 2307*fcf3ce44SJohn Forte hi = 2; 2308*fcf3ce44SJohn Forte } 2309*fcf3ce44SJohn Forte if (vpd->link_speed & LMT_4GB_CAPABLE) { 2310*fcf3ce44SJohn Forte (void) strcpy(cptr, ", 4=4Gb"); 2311*fcf3ce44SJohn Forte cptr += 7; 2312*fcf3ce44SJohn Forte hi = 4; 2313*fcf3ce44SJohn Forte } 2314*fcf3ce44SJohn Forte if (vpd->link_speed & LMT_8GB_CAPABLE) { 2315*fcf3ce44SJohn Forte (void) strcpy(cptr, ", 8=8Gb"); 2316*fcf3ce44SJohn Forte cptr += 7; 2317*fcf3ce44SJohn Forte hi = 8; 2318*fcf3ce44SJohn Forte } 2319*fcf3ce44SJohn Forte if (vpd->link_speed & LMT_10GB_CAPABLE) { 2320*fcf3ce44SJohn Forte (void) strcpy(cptr, ", 10=10Gb"); 2321*fcf3ce44SJohn Forte cptr += 9; 2322*fcf3ce44SJohn Forte hi = 10; 2323*fcf3ce44SJohn Forte } 2324*fcf3ce44SJohn Forte (void) strcpy(cptr, "]"); 2325*fcf3ce44SJohn Forte cfg->hi = hi; 2326*fcf3ce44SJohn Forte 2327*fcf3ce44SJohn Forte /* Now revalidate the current parameter setting */ 2328*fcf3ce44SJohn Forte cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 2329*fcf3ce44SJohn Forte 2330*fcf3ce44SJohn Forte return; 2331*fcf3ce44SJohn Forte 2332*fcf3ce44SJohn Forte } /* emlxs_process_link_speed() */ 2333*fcf3ce44SJohn Forte 2334*fcf3ce44SJohn Forte 2335*fcf3ce44SJohn Forte /* 2336*fcf3ce44SJohn Forte * 2337*fcf3ce44SJohn Forte * emlxs_parse_vpd 2338*fcf3ce44SJohn Forte * This routine will parse the VPD data 2339*fcf3ce44SJohn Forte * 2340*fcf3ce44SJohn Forte */ 2341*fcf3ce44SJohn Forte extern int 2342*fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 2343*fcf3ce44SJohn Forte { 2344*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2345*fcf3ce44SJohn Forte char tag[3]; 2346*fcf3ce44SJohn Forte uint8_t lenlo, lenhi; 2347*fcf3ce44SJohn Forte uint32_t n; 2348*fcf3ce44SJohn Forte uint16_t block_size; 2349*fcf3ce44SJohn Forte uint32_t block_index = 0; 2350*fcf3ce44SJohn Forte uint8_t sub_size; 2351*fcf3ce44SJohn Forte uint32_t sub_index; 2352*fcf3ce44SJohn Forte int32_t finished = 0; 2353*fcf3ce44SJohn Forte int32_t index = 0; 2354*fcf3ce44SJohn Forte char buffer[128]; 2355*fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 2356*fcf3ce44SJohn Forte emlxs_config_t *cfg; 2357*fcf3ce44SJohn Forte 2358*fcf3ce44SJohn Forte vpd = &VPD; 2359*fcf3ce44SJohn Forte cfg = &CFG; 2360*fcf3ce44SJohn Forte 2361*fcf3ce44SJohn Forte #ifdef MENLO_TEST 2362*fcf3ce44SJohn Forte /* Check if VPD is disabled Hornet adapters */ 2363*fcf3ce44SJohn Forte if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) && 2364*fcf3ce44SJohn Forte (cfg[CFG_HORNET_VPD].current == 0)) { 2365*fcf3ce44SJohn Forte return (1); 2366*fcf3ce44SJohn Forte } 2367*fcf3ce44SJohn Forte #endif /* MENLO_TEST */ 2368*fcf3ce44SJohn Forte 2369*fcf3ce44SJohn Forte 2370*fcf3ce44SJohn Forte while (!finished && (block_index < size)) { 2371*fcf3ce44SJohn Forte /* 2372*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "block_index = 2373*fcf3ce44SJohn Forte * %x", block_index); 2374*fcf3ce44SJohn Forte */ 2375*fcf3ce44SJohn Forte 2376*fcf3ce44SJohn Forte switch (vpd_buf[block_index]) { 2377*fcf3ce44SJohn Forte case 0x82: 2378*fcf3ce44SJohn Forte index = block_index; 2379*fcf3ce44SJohn Forte index += 1; 2380*fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 2381*fcf3ce44SJohn Forte index += 1; 2382*fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 2383*fcf3ce44SJohn Forte index += 1; 2384*fcf3ce44SJohn Forte block_index = index; 2385*fcf3ce44SJohn Forte 2386*fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2387*fcf3ce44SJohn Forte block_index += block_size; 2388*fcf3ce44SJohn Forte 2389*fcf3ce44SJohn Forte /* 2390*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2391*fcf3ce44SJohn Forte * "block_size = %x", block_size); 2392*fcf3ce44SJohn Forte */ 2393*fcf3ce44SJohn Forte 2394*fcf3ce44SJohn Forte n = sizeof (buffer); 2395*fcf3ce44SJohn Forte bzero(buffer, n); 2396*fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 2397*fcf3ce44SJohn Forte (block_size < (n - 1)) ? block_size : (n - 1)); 2398*fcf3ce44SJohn Forte 2399*fcf3ce44SJohn Forte (void) strcpy(vpd->id, buffer); 2400*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2401*fcf3ce44SJohn Forte "ID: %s", vpd->id); 2402*fcf3ce44SJohn Forte 2403*fcf3ce44SJohn Forte break; 2404*fcf3ce44SJohn Forte 2405*fcf3ce44SJohn Forte case 0x90: 2406*fcf3ce44SJohn Forte index = block_index; 2407*fcf3ce44SJohn Forte index += 1; 2408*fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 2409*fcf3ce44SJohn Forte index += 1; 2410*fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 2411*fcf3ce44SJohn Forte index += 1; 2412*fcf3ce44SJohn Forte block_index = index; 2413*fcf3ce44SJohn Forte sub_index = index; 2414*fcf3ce44SJohn Forte 2415*fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2416*fcf3ce44SJohn Forte block_index += block_size; 2417*fcf3ce44SJohn Forte 2418*fcf3ce44SJohn Forte /* 2419*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2420*fcf3ce44SJohn Forte * "block_size = %x", block_size); 2421*fcf3ce44SJohn Forte */ 2422*fcf3ce44SJohn Forte 2423*fcf3ce44SJohn Forte /* Scan for sub-blocks */ 2424*fcf3ce44SJohn Forte while ((sub_index < block_index) && 2425*fcf3ce44SJohn Forte (sub_index < size)) { 2426*fcf3ce44SJohn Forte /* 2427*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2428*fcf3ce44SJohn Forte * "sub_index = %x", sub_index); 2429*fcf3ce44SJohn Forte */ 2430*fcf3ce44SJohn Forte 2431*fcf3ce44SJohn Forte index = sub_index; 2432*fcf3ce44SJohn Forte tag[0] = vpd_buf[index++]; 2433*fcf3ce44SJohn Forte tag[1] = vpd_buf[index++]; 2434*fcf3ce44SJohn Forte tag[2] = 0; 2435*fcf3ce44SJohn Forte sub_size = vpd_buf[index++]; 2436*fcf3ce44SJohn Forte 2437*fcf3ce44SJohn Forte /* 2438*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2439*fcf3ce44SJohn Forte * "sub_size = %x", sub_size); 2440*fcf3ce44SJohn Forte */ 2441*fcf3ce44SJohn Forte 2442*fcf3ce44SJohn Forte sub_index = (index + sub_size); 2443*fcf3ce44SJohn Forte 2444*fcf3ce44SJohn Forte n = sizeof (buffer); 2445*fcf3ce44SJohn Forte bzero(buffer, n); 2446*fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 2447*fcf3ce44SJohn Forte (sub_size < (n - 1)) ? sub_size : (n - 1)); 2448*fcf3ce44SJohn Forte 2449*fcf3ce44SJohn Forte /* 2450*fcf3ce44SJohn Forte * Look for Engineering Change (EC) 2451*fcf3ce44SJohn Forte */ 2452*fcf3ce44SJohn Forte if (strcmp(tag, "EC") == 0) { 2453*fcf3ce44SJohn Forte (void) strcpy(vpd->eng_change, buffer); 2454*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2455*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2456*fcf3ce44SJohn Forte "EC: %s", vpd->eng_change); 2457*fcf3ce44SJohn Forte } 2458*fcf3ce44SJohn Forte /* 2459*fcf3ce44SJohn Forte * Look for Manufacturer (MN) 2460*fcf3ce44SJohn Forte */ 2461*fcf3ce44SJohn Forte else if (strcmp(tag, "MN") == 0) { 2462*fcf3ce44SJohn Forte (void) strcpy(vpd->manufacturer, 2463*fcf3ce44SJohn Forte buffer); 2464*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2465*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2466*fcf3ce44SJohn Forte "MN: %s", vpd->manufacturer); 2467*fcf3ce44SJohn Forte } 2468*fcf3ce44SJohn Forte /* 2469*fcf3ce44SJohn Forte * Look for Serial Number (SN) 2470*fcf3ce44SJohn Forte */ 2471*fcf3ce44SJohn Forte else if (strcmp(tag, "SN") == 0) { 2472*fcf3ce44SJohn Forte (void) strcpy(vpd->serial_num, buffer); 2473*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2474*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2475*fcf3ce44SJohn Forte "SN: %s", vpd->serial_num); 2476*fcf3ce44SJohn Forte 2477*fcf3ce44SJohn Forte /* Validate the serial number */ 2478*fcf3ce44SJohn Forte if ((strncmp(buffer, "FFFFFFFFFF", 2479*fcf3ce44SJohn Forte 10) == 0) || 2480*fcf3ce44SJohn Forte (strncmp(buffer, "0000000000", 2481*fcf3ce44SJohn Forte 10) == 0)) { 2482*fcf3ce44SJohn Forte vpd->serial_num[0] = 0; 2483*fcf3ce44SJohn Forte } 2484*fcf3ce44SJohn Forte } 2485*fcf3ce44SJohn Forte /* 2486*fcf3ce44SJohn Forte * Look for Part Number (PN) 2487*fcf3ce44SJohn Forte */ 2488*fcf3ce44SJohn Forte else if (strcmp(tag, "PN") == 0) { 2489*fcf3ce44SJohn Forte (void) strcpy(vpd->part_num, buffer); 2490*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2491*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2492*fcf3ce44SJohn Forte "PN: %s", vpd->part_num); 2493*fcf3ce44SJohn Forte } 2494*fcf3ce44SJohn Forte /* 2495*fcf3ce44SJohn Forte * Look for (V0) 2496*fcf3ce44SJohn Forte */ 2497*fcf3ce44SJohn Forte else if (strcmp(tag, "V0") == 0) { 2498*fcf3ce44SJohn Forte /* Not used */ 2499*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2500*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2501*fcf3ce44SJohn Forte "V0: %s", buffer); 2502*fcf3ce44SJohn Forte } 2503*fcf3ce44SJohn Forte /* 2504*fcf3ce44SJohn Forte * Look for model description (V1) 2505*fcf3ce44SJohn Forte */ 2506*fcf3ce44SJohn Forte else if (strcmp(tag, "V1") == 0) { 2507*fcf3ce44SJohn Forte (void) strcpy(vpd->model_desc, buffer); 2508*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2509*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2510*fcf3ce44SJohn Forte "Desc: %s", vpd->model_desc); 2511*fcf3ce44SJohn Forte } 2512*fcf3ce44SJohn Forte /* 2513*fcf3ce44SJohn Forte * Look for model (V2) 2514*fcf3ce44SJohn Forte */ 2515*fcf3ce44SJohn Forte else if (strcmp(tag, "V2") == 0) { 2516*fcf3ce44SJohn Forte (void) strcpy(vpd->model, buffer); 2517*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2518*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2519*fcf3ce44SJohn Forte "Model: %s", vpd->model); 2520*fcf3ce44SJohn Forte } 2521*fcf3ce44SJohn Forte /* 2522*fcf3ce44SJohn Forte * Look for program type (V3) 2523*fcf3ce44SJohn Forte */ 2524*fcf3ce44SJohn Forte 2525*fcf3ce44SJohn Forte else if (strcmp(tag, "V3") == 0) { 2526*fcf3ce44SJohn Forte (void) strcpy(vpd->prog_types, buffer); 2527*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2528*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2529*fcf3ce44SJohn Forte "Prog Types: %s", vpd->prog_types); 2530*fcf3ce44SJohn Forte } 2531*fcf3ce44SJohn Forte /* 2532*fcf3ce44SJohn Forte * Look for port number (V4) 2533*fcf3ce44SJohn Forte */ 2534*fcf3ce44SJohn Forte else if (strcmp(tag, "V4") == 0) { 2535*fcf3ce44SJohn Forte (void) strcpy(vpd->port_num, buffer); 2536*fcf3ce44SJohn Forte vpd->port_index = 2537*fcf3ce44SJohn Forte emlxs_strtol(vpd->port_num, 10); 2538*fcf3ce44SJohn Forte 2539*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2540*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2541*fcf3ce44SJohn Forte "Port: %s", 2542*fcf3ce44SJohn Forte (vpd->port_num[0]) ? 2543*fcf3ce44SJohn Forte vpd->port_num : "not applicable"); 2544*fcf3ce44SJohn Forte } 2545*fcf3ce44SJohn Forte /* 2546*fcf3ce44SJohn Forte * Look for checksum (RV) 2547*fcf3ce44SJohn Forte */ 2548*fcf3ce44SJohn Forte else if (strcmp(tag, "RV") == 0) { 2549*fcf3ce44SJohn Forte /* Not used */ 2550*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2551*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2552*fcf3ce44SJohn Forte "Checksum: 0x%x", buffer[0]); 2553*fcf3ce44SJohn Forte } else { 2554*fcf3ce44SJohn Forte /* Generic */ 2555*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 2556*fcf3ce44SJohn Forte &emlxs_vpd_msg, 2557*fcf3ce44SJohn Forte "Tag: %s: %s", tag, buffer); 2558*fcf3ce44SJohn Forte } 2559*fcf3ce44SJohn Forte } 2560*fcf3ce44SJohn Forte 2561*fcf3ce44SJohn Forte break; 2562*fcf3ce44SJohn Forte 2563*fcf3ce44SJohn Forte case 0x78: 2564*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 2565*fcf3ce44SJohn Forte finished = 1; 2566*fcf3ce44SJohn Forte break; 2567*fcf3ce44SJohn Forte 2568*fcf3ce44SJohn Forte default: 2569*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2570*fcf3ce44SJohn Forte "Unknown block: %x %x %x %x %x %x %x %x", 2571*fcf3ce44SJohn Forte vpd_buf[index], vpd_buf[index + 1], 2572*fcf3ce44SJohn Forte vpd_buf[index + 2], vpd_buf[index + 3], 2573*fcf3ce44SJohn Forte vpd_buf[index + 4], vpd_buf[index + 5], 2574*fcf3ce44SJohn Forte vpd_buf[index + 6], vpd_buf[index + 7]); 2575*fcf3ce44SJohn Forte return (0); 2576*fcf3ce44SJohn Forte } 2577*fcf3ce44SJohn Forte } 2578*fcf3ce44SJohn Forte 2579*fcf3ce44SJohn Forte return (1); 2580*fcf3ce44SJohn Forte 2581*fcf3ce44SJohn Forte } /* emlxs_parse_vpd */ 2582*fcf3ce44SJohn Forte 2583*fcf3ce44SJohn Forte 2584*fcf3ce44SJohn Forte 2585*fcf3ce44SJohn Forte static uint32_t 2586*fcf3ce44SJohn Forte emlxs_decode_biu_rev(uint32_t rev) 2587*fcf3ce44SJohn Forte { 2588*fcf3ce44SJohn Forte return (rev & 0xf); 2589*fcf3ce44SJohn Forte } /* End emlxs_decode_biu_rev */ 2590*fcf3ce44SJohn Forte 2591*fcf3ce44SJohn Forte 2592*fcf3ce44SJohn Forte static uint32_t 2593*fcf3ce44SJohn Forte emlxs_decode_endec_rev(uint32_t rev) 2594*fcf3ce44SJohn Forte { 2595*fcf3ce44SJohn Forte return ((rev >> 28) & 0xf); 2596*fcf3ce44SJohn Forte } /* End emlxs_decode_endec_rev */ 2597*fcf3ce44SJohn Forte 2598*fcf3ce44SJohn Forte 2599*fcf3ce44SJohn Forte extern void 2600*fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 2601*fcf3ce44SJohn Forte { 2602*fcf3ce44SJohn Forte if (vpd->rBit) { 2603*fcf3ce44SJohn Forte switch (hba->sli_mode) { 2604*fcf3ce44SJohn Forte case 4: 2605*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli4FwName); 2606*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli4FwLabel); 2607*fcf3ce44SJohn Forte break; 2608*fcf3ce44SJohn Forte case 3: 2609*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli3FwName); 2610*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli3FwLabel); 2611*fcf3ce44SJohn Forte break; 2612*fcf3ce44SJohn Forte case 2: 2613*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli2FwName); 2614*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli2FwLabel); 2615*fcf3ce44SJohn Forte break; 2616*fcf3ce44SJohn Forte case 1: 2617*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli1FwName); 2618*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli1FwLabel); 2619*fcf3ce44SJohn Forte break; 2620*fcf3ce44SJohn Forte default: 2621*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, "unknown"); 2622*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 2623*fcf3ce44SJohn Forte } 2624*fcf3ce44SJohn Forte } else { 2625*fcf3ce44SJohn Forte emlxs_decode_version(vpd->smFwRev, vpd->fw_version); 2626*fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 2627*fcf3ce44SJohn Forte } 2628*fcf3ce44SJohn Forte 2629*fcf3ce44SJohn Forte return; 2630*fcf3ce44SJohn Forte 2631*fcf3ce44SJohn Forte } /* emlxs_decode_firmware_rev() */ 2632*fcf3ce44SJohn Forte 2633*fcf3ce44SJohn Forte 2634*fcf3ce44SJohn Forte 2635*fcf3ce44SJohn Forte extern void 2636*fcf3ce44SJohn Forte emlxs_decode_version(uint32_t version, char *buffer) 2637*fcf3ce44SJohn Forte { 2638*fcf3ce44SJohn Forte uint32_t b1, b2, b3, b4; 2639*fcf3ce44SJohn Forte char c; 2640*fcf3ce44SJohn Forte 2641*fcf3ce44SJohn Forte b1 = (version & 0x0000f000) >> 12; 2642*fcf3ce44SJohn Forte b2 = (version & 0x00000f00) >> 8; 2643*fcf3ce44SJohn Forte b3 = (version & 0x000000c0) >> 6; 2644*fcf3ce44SJohn Forte b4 = (version & 0x00000030) >> 4; 2645*fcf3ce44SJohn Forte 2646*fcf3ce44SJohn Forte if (b1 == 0 && b2 == 0) { 2647*fcf3ce44SJohn Forte (void) sprintf(buffer, "none"); 2648*fcf3ce44SJohn Forte return; 2649*fcf3ce44SJohn Forte } 2650*fcf3ce44SJohn Forte c = 0; 2651*fcf3ce44SJohn Forte switch (b4) { 2652*fcf3ce44SJohn Forte case 0: 2653*fcf3ce44SJohn Forte c = 'n'; 2654*fcf3ce44SJohn Forte break; 2655*fcf3ce44SJohn Forte case 1: 2656*fcf3ce44SJohn Forte c = 'a'; 2657*fcf3ce44SJohn Forte break; 2658*fcf3ce44SJohn Forte case 2: 2659*fcf3ce44SJohn Forte c = 'b'; 2660*fcf3ce44SJohn Forte break; 2661*fcf3ce44SJohn Forte case 3: 2662*fcf3ce44SJohn Forte if ((version & 0x0000000f)) { 2663*fcf3ce44SJohn Forte c = 'x'; 2664*fcf3ce44SJohn Forte } 2665*fcf3ce44SJohn Forte break; 2666*fcf3ce44SJohn Forte 2667*fcf3ce44SJohn Forte } 2668*fcf3ce44SJohn Forte b4 = (version & 0x0000000f); 2669*fcf3ce44SJohn Forte 2670*fcf3ce44SJohn Forte if (c == 0) { 2671*fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d", b1, b2, b3); 2672*fcf3ce44SJohn Forte } else { 2673*fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4); 2674*fcf3ce44SJohn Forte } 2675*fcf3ce44SJohn Forte 2676*fcf3ce44SJohn Forte return; 2677*fcf3ce44SJohn Forte 2678*fcf3ce44SJohn Forte } /* emlxs_decode_version() */ 2679*fcf3ce44SJohn Forte 2680*fcf3ce44SJohn Forte 2681*fcf3ce44SJohn Forte static void 2682*fcf3ce44SJohn Forte emlxs_decode_label(char *label, char *buffer) 2683*fcf3ce44SJohn Forte { 2684*fcf3ce44SJohn Forte uint32_t i; 2685*fcf3ce44SJohn Forte char name[16]; 2686*fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN 2687*fcf3ce44SJohn Forte uint32_t *wptr; 2688*fcf3ce44SJohn Forte uint32_t word; 2689*fcf3ce44SJohn Forte #endif /* EMLXS_LITTLE_ENDIAN */ 2690*fcf3ce44SJohn Forte 2691*fcf3ce44SJohn Forte bcopy(label, name, 16); 2692*fcf3ce44SJohn Forte 2693*fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN 2694*fcf3ce44SJohn Forte wptr = (uint32_t *)name; 2695*fcf3ce44SJohn Forte for (i = 0; i < 3; i++) { 2696*fcf3ce44SJohn Forte word = *wptr; 2697*fcf3ce44SJohn Forte word = SWAP_DATA32(word); 2698*fcf3ce44SJohn Forte *wptr++ = word; 2699*fcf3ce44SJohn Forte } 2700*fcf3ce44SJohn Forte #endif /* EMLXS_LITTLE_ENDIAN */ 2701*fcf3ce44SJohn Forte 2702*fcf3ce44SJohn Forte for (i = 0; i < 16; i++) { 2703*fcf3ce44SJohn Forte if (name[i] == 0x20) { 2704*fcf3ce44SJohn Forte name[i] = 0; 2705*fcf3ce44SJohn Forte } 2706*fcf3ce44SJohn Forte } 2707*fcf3ce44SJohn Forte 2708*fcf3ce44SJohn Forte (void) strcpy(buffer, name); 2709*fcf3ce44SJohn Forte 2710*fcf3ce44SJohn Forte return; 2711*fcf3ce44SJohn Forte 2712*fcf3ce44SJohn Forte } /* emlxs_decode_label() */ 2713*fcf3ce44SJohn Forte 2714*fcf3ce44SJohn Forte 2715*fcf3ce44SJohn Forte extern uint32_t 2716*fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base) 2717*fcf3ce44SJohn Forte { 2718*fcf3ce44SJohn Forte uint32_t value = 0; 2719*fcf3ce44SJohn Forte char *ptr; 2720*fcf3ce44SJohn Forte uint32_t factor = 1; 2721*fcf3ce44SJohn Forte uint32_t digits; 2722*fcf3ce44SJohn Forte 2723*fcf3ce44SJohn Forte if (*str == 0) { 2724*fcf3ce44SJohn Forte return (0); 2725*fcf3ce44SJohn Forte } 2726*fcf3ce44SJohn Forte if (base != 10 && base != 16) { 2727*fcf3ce44SJohn Forte return (0); 2728*fcf3ce44SJohn Forte } 2729*fcf3ce44SJohn Forte /* Get max digits of value */ 2730*fcf3ce44SJohn Forte digits = (base == 10) ? 9 : 8; 2731*fcf3ce44SJohn Forte 2732*fcf3ce44SJohn Forte /* Position pointer to end of string */ 2733*fcf3ce44SJohn Forte ptr = str + strlen(str); 2734*fcf3ce44SJohn Forte 2735*fcf3ce44SJohn Forte /* Process string backwards */ 2736*fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 2737*fcf3ce44SJohn Forte /* check for base 10 numbers */ 2738*fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 2739*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 2740*fcf3ce44SJohn Forte factor *= base; 2741*fcf3ce44SJohn Forte digits--; 2742*fcf3ce44SJohn Forte } else if (base == 16) { 2743*fcf3ce44SJohn Forte /* Check for base 16 numbers */ 2744*fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 2745*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - 'a') + 10) * factor; 2746*fcf3ce44SJohn Forte factor *= base; 2747*fcf3ce44SJohn Forte digits--; 2748*fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 2749*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - 'A') + 10) * factor; 2750*fcf3ce44SJohn Forte factor *= base; 2751*fcf3ce44SJohn Forte digits--; 2752*fcf3ce44SJohn Forte } else if (factor > 1) { 2753*fcf3ce44SJohn Forte break; 2754*fcf3ce44SJohn Forte } 2755*fcf3ce44SJohn Forte } else if (factor > 1) { 2756*fcf3ce44SJohn Forte break; 2757*fcf3ce44SJohn Forte } 2758*fcf3ce44SJohn Forte } 2759*fcf3ce44SJohn Forte 2760*fcf3ce44SJohn Forte return (value); 2761*fcf3ce44SJohn Forte 2762*fcf3ce44SJohn Forte } /* emlxs_strtol() */ 2763*fcf3ce44SJohn Forte 2764*fcf3ce44SJohn Forte 2765*fcf3ce44SJohn Forte extern uint64_t 2766*fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base) 2767*fcf3ce44SJohn Forte { 2768*fcf3ce44SJohn Forte uint64_t value = 0; 2769*fcf3ce44SJohn Forte char *ptr; 2770*fcf3ce44SJohn Forte uint32_t factor = 1; 2771*fcf3ce44SJohn Forte uint32_t digits; 2772*fcf3ce44SJohn Forte 2773*fcf3ce44SJohn Forte if (*str == 0) { 2774*fcf3ce44SJohn Forte return (0); 2775*fcf3ce44SJohn Forte } 2776*fcf3ce44SJohn Forte if (base != 10 && base != 16) { 2777*fcf3ce44SJohn Forte return (0); 2778*fcf3ce44SJohn Forte } 2779*fcf3ce44SJohn Forte /* Get max digits of value */ 2780*fcf3ce44SJohn Forte digits = (base == 10) ? 19 : 16; 2781*fcf3ce44SJohn Forte 2782*fcf3ce44SJohn Forte /* Position pointer to end of string */ 2783*fcf3ce44SJohn Forte ptr = str + strlen(str); 2784*fcf3ce44SJohn Forte 2785*fcf3ce44SJohn Forte /* Process string backwards */ 2786*fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 2787*fcf3ce44SJohn Forte /* check for base 10 numbers */ 2788*fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 2789*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 2790*fcf3ce44SJohn Forte factor *= base; 2791*fcf3ce44SJohn Forte digits--; 2792*fcf3ce44SJohn Forte } else if (base == 16) { 2793*fcf3ce44SJohn Forte /* Check for base 16 numbers */ 2794*fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 2795*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - 'a') + 10) * factor; 2796*fcf3ce44SJohn Forte factor *= base; 2797*fcf3ce44SJohn Forte digits--; 2798*fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 2799*fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - 'A') + 10) * factor; 2800*fcf3ce44SJohn Forte factor *= base; 2801*fcf3ce44SJohn Forte digits--; 2802*fcf3ce44SJohn Forte } else if (factor > 1) { 2803*fcf3ce44SJohn Forte break; 2804*fcf3ce44SJohn Forte } 2805*fcf3ce44SJohn Forte } else if (factor > 1) { 2806*fcf3ce44SJohn Forte break; 2807*fcf3ce44SJohn Forte } 2808*fcf3ce44SJohn Forte } 2809*fcf3ce44SJohn Forte 2810*fcf3ce44SJohn Forte return (value); 2811*fcf3ce44SJohn Forte 2812*fcf3ce44SJohn Forte } /* emlxs_strtoll() */ 2813*fcf3ce44SJohn Forte 2814*fcf3ce44SJohn Forte static void 2815*fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 2816*fcf3ce44SJohn Forte { 2817*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2818*fcf3ce44SJohn Forte uint32_t i; 2819*fcf3ce44SJohn Forte char *ptr; 2820*fcf3ce44SJohn Forte emlxs_model_t *model; 2821*fcf3ce44SJohn Forte char types_buffer[256]; 2822*fcf3ce44SJohn Forte char *types; 2823*fcf3ce44SJohn Forte 2824*fcf3ce44SJohn Forte bcopy(prog_types, types_buffer, 256); 2825*fcf3ce44SJohn Forte types = types_buffer; 2826*fcf3ce44SJohn Forte 2827*fcf3ce44SJohn Forte model = &hba->model_info; 2828*fcf3ce44SJohn Forte 2829*fcf3ce44SJohn Forte while (*types) { 2830*fcf3ce44SJohn Forte if (strncmp(types, "T2:", 3) == 0) { 2831*fcf3ce44SJohn Forte bzero(model->pt_2, sizeof (model->pt_2)); 2832*fcf3ce44SJohn Forte types += 3; 2833*fcf3ce44SJohn Forte 2834*fcf3ce44SJohn Forte i = 0; 2835*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2836*fcf3ce44SJohn Forte /* Null terminate the next value */ 2837*fcf3ce44SJohn Forte ptr = types; 2838*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2839*fcf3ce44SJohn Forte ptr++; 2840*fcf3ce44SJohn Forte *ptr = 0; 2841*fcf3ce44SJohn Forte 2842*fcf3ce44SJohn Forte /* Save the value */ 2843*fcf3ce44SJohn Forte model->pt_2[i++] = 2844*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2845*fcf3ce44SJohn Forte 2846*fcf3ce44SJohn Forte /* 2847*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2848*fcf3ce44SJohn Forte * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 2849*fcf3ce44SJohn Forte */ 2850*fcf3ce44SJohn Forte 2851*fcf3ce44SJohn Forte /* Move the str pointer */ 2852*fcf3ce44SJohn Forte types = ptr + 1; 2853*fcf3ce44SJohn Forte } 2854*fcf3ce44SJohn Forte 2855*fcf3ce44SJohn Forte } else if (strncmp(types, "T3:", 3) == 0) { 2856*fcf3ce44SJohn Forte bzero(model->pt_3, sizeof (model->pt_3)); 2857*fcf3ce44SJohn Forte types += 3; 2858*fcf3ce44SJohn Forte 2859*fcf3ce44SJohn Forte i = 0; 2860*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2861*fcf3ce44SJohn Forte /* Null terminate the next value */ 2862*fcf3ce44SJohn Forte ptr = types; 2863*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2864*fcf3ce44SJohn Forte ptr++; 2865*fcf3ce44SJohn Forte *ptr = 0; 2866*fcf3ce44SJohn Forte 2867*fcf3ce44SJohn Forte /* Save the value */ 2868*fcf3ce44SJohn Forte model->pt_3[i++] = 2869*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2870*fcf3ce44SJohn Forte 2871*fcf3ce44SJohn Forte /* 2872*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2873*fcf3ce44SJohn Forte * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 2874*fcf3ce44SJohn Forte */ 2875*fcf3ce44SJohn Forte 2876*fcf3ce44SJohn Forte /* Move the str pointer */ 2877*fcf3ce44SJohn Forte types = ptr + 1; 2878*fcf3ce44SJohn Forte } 2879*fcf3ce44SJohn Forte } else if (strncmp(types, "T6:", 3) == 0) { 2880*fcf3ce44SJohn Forte bzero(model->pt_6, sizeof (model->pt_6)); 2881*fcf3ce44SJohn Forte types += 3; 2882*fcf3ce44SJohn Forte 2883*fcf3ce44SJohn Forte i = 0; 2884*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2885*fcf3ce44SJohn Forte /* Null terminate the next value */ 2886*fcf3ce44SJohn Forte ptr = types; 2887*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2888*fcf3ce44SJohn Forte ptr++; 2889*fcf3ce44SJohn Forte *ptr = 0; 2890*fcf3ce44SJohn Forte 2891*fcf3ce44SJohn Forte /* Save the value */ 2892*fcf3ce44SJohn Forte model->pt_6[i++] = 2893*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2894*fcf3ce44SJohn Forte model->pt_6[i] = 0; 2895*fcf3ce44SJohn Forte 2896*fcf3ce44SJohn Forte /* 2897*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2898*fcf3ce44SJohn Forte * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 2899*fcf3ce44SJohn Forte */ 2900*fcf3ce44SJohn Forte 2901*fcf3ce44SJohn Forte /* Move the str pointer */ 2902*fcf3ce44SJohn Forte types = ptr + 1; 2903*fcf3ce44SJohn Forte } 2904*fcf3ce44SJohn Forte } else if (strncmp(types, "T7:", 3) == 0) { 2905*fcf3ce44SJohn Forte bzero(model->pt_7, sizeof (model->pt_7)); 2906*fcf3ce44SJohn Forte types += 3; 2907*fcf3ce44SJohn Forte 2908*fcf3ce44SJohn Forte i = 0; 2909*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2910*fcf3ce44SJohn Forte /* Null terminate the next value */ 2911*fcf3ce44SJohn Forte ptr = types; 2912*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2913*fcf3ce44SJohn Forte ptr++; 2914*fcf3ce44SJohn Forte *ptr = 0; 2915*fcf3ce44SJohn Forte 2916*fcf3ce44SJohn Forte /* Save the value */ 2917*fcf3ce44SJohn Forte model->pt_7[i++] = 2918*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2919*fcf3ce44SJohn Forte model->pt_7[i] = 0; 2920*fcf3ce44SJohn Forte 2921*fcf3ce44SJohn Forte /* 2922*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2923*fcf3ce44SJohn Forte * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 2924*fcf3ce44SJohn Forte */ 2925*fcf3ce44SJohn Forte 2926*fcf3ce44SJohn Forte /* Move the str pointer */ 2927*fcf3ce44SJohn Forte types = ptr + 1; 2928*fcf3ce44SJohn Forte } 2929*fcf3ce44SJohn Forte } else if (strncmp(types, "TA:", 3) == 0) { 2930*fcf3ce44SJohn Forte bzero(model->pt_A, sizeof (model->pt_A)); 2931*fcf3ce44SJohn Forte types += 3; 2932*fcf3ce44SJohn Forte 2933*fcf3ce44SJohn Forte i = 0; 2934*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2935*fcf3ce44SJohn Forte /* Null terminate the next value */ 2936*fcf3ce44SJohn Forte ptr = types; 2937*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2938*fcf3ce44SJohn Forte ptr++; 2939*fcf3ce44SJohn Forte *ptr = 0; 2940*fcf3ce44SJohn Forte 2941*fcf3ce44SJohn Forte /* Save the value */ 2942*fcf3ce44SJohn Forte model->pt_A[i++] = 2943*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2944*fcf3ce44SJohn Forte 2945*fcf3ce44SJohn Forte /* 2946*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2947*fcf3ce44SJohn Forte * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]); 2948*fcf3ce44SJohn Forte */ 2949*fcf3ce44SJohn Forte 2950*fcf3ce44SJohn Forte /* Move the str pointer */ 2951*fcf3ce44SJohn Forte types = ptr + 1; 2952*fcf3ce44SJohn Forte } 2953*fcf3ce44SJohn Forte } else if (strncmp(types, "TB:", 3) == 0) { 2954*fcf3ce44SJohn Forte bzero(model->pt_B, sizeof (model->pt_B)); 2955*fcf3ce44SJohn Forte types += 3; 2956*fcf3ce44SJohn Forte 2957*fcf3ce44SJohn Forte i = 0; 2958*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2959*fcf3ce44SJohn Forte /* Null terminate the next value */ 2960*fcf3ce44SJohn Forte ptr = types; 2961*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2962*fcf3ce44SJohn Forte ptr++; 2963*fcf3ce44SJohn Forte *ptr = 0; 2964*fcf3ce44SJohn Forte 2965*fcf3ce44SJohn Forte /* Save the value */ 2966*fcf3ce44SJohn Forte model->pt_B[i++] = 2967*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2968*fcf3ce44SJohn Forte 2969*fcf3ce44SJohn Forte /* 2970*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2971*fcf3ce44SJohn Forte * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 2972*fcf3ce44SJohn Forte */ 2973*fcf3ce44SJohn Forte 2974*fcf3ce44SJohn Forte /* Move the str pointer */ 2975*fcf3ce44SJohn Forte types = ptr + 1; 2976*fcf3ce44SJohn Forte } 2977*fcf3ce44SJohn Forte } else if (strncmp(types, "TFF:", 4) == 0) { 2978*fcf3ce44SJohn Forte bzero(model->pt_FF, sizeof (model->pt_FF)); 2979*fcf3ce44SJohn Forte types += 4; 2980*fcf3ce44SJohn Forte 2981*fcf3ce44SJohn Forte i = 0; 2982*fcf3ce44SJohn Forte while (*types && *types != 'T') { 2983*fcf3ce44SJohn Forte /* Null terminate the next value */ 2984*fcf3ce44SJohn Forte ptr = types; 2985*fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 2986*fcf3ce44SJohn Forte ptr++; 2987*fcf3ce44SJohn Forte *ptr = 0; 2988*fcf3ce44SJohn Forte 2989*fcf3ce44SJohn Forte /* Save the value */ 2990*fcf3ce44SJohn Forte model->pt_FF[i++] = 2991*fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 2992*fcf3ce44SJohn Forte 2993*fcf3ce44SJohn Forte /* 2994*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2995*fcf3ce44SJohn Forte * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 2996*fcf3ce44SJohn Forte */ 2997*fcf3ce44SJohn Forte 2998*fcf3ce44SJohn Forte /* Move the str pointer */ 2999*fcf3ce44SJohn Forte types = ptr + 1; 3000*fcf3ce44SJohn Forte } 3001*fcf3ce44SJohn Forte } else { 3002*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 3003*fcf3ce44SJohn Forte "Unknown prog type string = %s", types); 3004*fcf3ce44SJohn Forte break; 3005*fcf3ce44SJohn Forte } 3006*fcf3ce44SJohn Forte } 3007*fcf3ce44SJohn Forte 3008*fcf3ce44SJohn Forte return; 3009*fcf3ce44SJohn Forte 3010*fcf3ce44SJohn Forte } /* emlxs_parse_prog_types() */ 3011*fcf3ce44SJohn Forte 3012*fcf3ce44SJohn Forte 3013*fcf3ce44SJohn Forte static void 3014*fcf3ce44SJohn Forte emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types) 3015*fcf3ce44SJohn Forte { 3016*fcf3ce44SJohn Forte uint32_t i; 3017*fcf3ce44SJohn Forte uint32_t found = 0; 3018*fcf3ce44SJohn Forte char buffer[256]; 3019*fcf3ce44SJohn Forte 3020*fcf3ce44SJohn Forte bzero(prog_types, 256); 3021*fcf3ce44SJohn Forte 3022*fcf3ce44SJohn Forte /* Rebuild the prog type string */ 3023*fcf3ce44SJohn Forte if (hba->model_info.pt_2[0]) { 3024*fcf3ce44SJohn Forte (void) strcat(prog_types, "T2:"); 3025*fcf3ce44SJohn Forte found = 1; 3026*fcf3ce44SJohn Forte 3027*fcf3ce44SJohn Forte i = 0; 3028*fcf3ce44SJohn Forte while (hba->model_info.pt_2[i] && i < 8) { 3029*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]); 3030*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3031*fcf3ce44SJohn Forte i++; 3032*fcf3ce44SJohn Forte } 3033*fcf3ce44SJohn Forte } 3034*fcf3ce44SJohn Forte if (hba->model_info.pt_3[0]) { 3035*fcf3ce44SJohn Forte (void) strcat(prog_types, "T3:"); 3036*fcf3ce44SJohn Forte found = 1; 3037*fcf3ce44SJohn Forte 3038*fcf3ce44SJohn Forte i = 0; 3039*fcf3ce44SJohn Forte while (hba->model_info.pt_3[i] && i < 8) { 3040*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]); 3041*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3042*fcf3ce44SJohn Forte i++; 3043*fcf3ce44SJohn Forte 3044*fcf3ce44SJohn Forte } 3045*fcf3ce44SJohn Forte } 3046*fcf3ce44SJohn Forte if (hba->model_info.pt_6[0]) { 3047*fcf3ce44SJohn Forte (void) strcat(prog_types, "T6:"); 3048*fcf3ce44SJohn Forte found = 1; 3049*fcf3ce44SJohn Forte 3050*fcf3ce44SJohn Forte i = 0; 3051*fcf3ce44SJohn Forte while (hba->model_info.pt_6[i] && i < 8) { 3052*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]); 3053*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3054*fcf3ce44SJohn Forte i++; 3055*fcf3ce44SJohn Forte } 3056*fcf3ce44SJohn Forte } 3057*fcf3ce44SJohn Forte if (hba->model_info.pt_7[0]) { 3058*fcf3ce44SJohn Forte (void) strcat(prog_types, "T7:"); 3059*fcf3ce44SJohn Forte found = 1; 3060*fcf3ce44SJohn Forte 3061*fcf3ce44SJohn Forte i = 0; 3062*fcf3ce44SJohn Forte while (hba->model_info.pt_7[i] && i < 8) { 3063*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]); 3064*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3065*fcf3ce44SJohn Forte i++; 3066*fcf3ce44SJohn Forte } 3067*fcf3ce44SJohn Forte } 3068*fcf3ce44SJohn Forte if (hba->model_info.pt_A[0]) { 3069*fcf3ce44SJohn Forte (void) strcat(prog_types, "TA:"); 3070*fcf3ce44SJohn Forte found = 1; 3071*fcf3ce44SJohn Forte 3072*fcf3ce44SJohn Forte i = 0; 3073*fcf3ce44SJohn Forte while (hba->model_info.pt_A[i] && i < 8) { 3074*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]); 3075*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3076*fcf3ce44SJohn Forte i++; 3077*fcf3ce44SJohn Forte } 3078*fcf3ce44SJohn Forte } 3079*fcf3ce44SJohn Forte if (hba->model_info.pt_B[0]) { 3080*fcf3ce44SJohn Forte (void) strcat(prog_types, "TB:"); 3081*fcf3ce44SJohn Forte found = 1; 3082*fcf3ce44SJohn Forte 3083*fcf3ce44SJohn Forte i = 0; 3084*fcf3ce44SJohn Forte while (hba->model_info.pt_B[i] && i < 8) { 3085*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]); 3086*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3087*fcf3ce44SJohn Forte i++; 3088*fcf3ce44SJohn Forte } 3089*fcf3ce44SJohn Forte } 3090*fcf3ce44SJohn Forte if (hba->model_info.pt_FF[0]) { 3091*fcf3ce44SJohn Forte (void) strcat(prog_types, "TFF:"); 3092*fcf3ce44SJohn Forte found = 1; 3093*fcf3ce44SJohn Forte 3094*fcf3ce44SJohn Forte i = 0; 3095*fcf3ce44SJohn Forte while (hba->model_info.pt_FF[i] && i < 8) { 3096*fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]); 3097*fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 3098*fcf3ce44SJohn Forte i++; 3099*fcf3ce44SJohn Forte } 3100*fcf3ce44SJohn Forte } 3101*fcf3ce44SJohn Forte if (found) { 3102*fcf3ce44SJohn Forte /* Terminate at the last comma in string */ 3103*fcf3ce44SJohn Forte prog_types[(strlen(prog_types) - 1)] = 0; 3104*fcf3ce44SJohn Forte } 3105*fcf3ce44SJohn Forte return; 3106*fcf3ce44SJohn Forte 3107*fcf3ce44SJohn Forte } /* emlxs_build_prog_types() */ 3108*fcf3ce44SJohn Forte 3109*fcf3ce44SJohn Forte 3110*fcf3ce44SJohn Forte 3111*fcf3ce44SJohn Forte 3112*fcf3ce44SJohn Forte extern uint32_t 3113*fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba) 3114*fcf3ce44SJohn Forte { 3115*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3116*fcf3ce44SJohn Forte emlxs_config_t *cfg; 3117*fcf3ce44SJohn Forte uint32_t pci_id; 3118*fcf3ce44SJohn Forte uint32_t cache_line; 3119*fcf3ce44SJohn Forte uint32_t channels; 3120*fcf3ce44SJohn Forte uint16_t device_id; 3121*fcf3ce44SJohn Forte uint16_t ssdid; 3122*fcf3ce44SJohn Forte uint32_t i; 3123*fcf3ce44SJohn Forte uint32_t found = 0; 3124*fcf3ce44SJohn Forte 3125*fcf3ce44SJohn Forte cfg = &CFG; 3126*fcf3ce44SJohn Forte 3127*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3128*fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 3129*fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 3130*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3131*fcf3ce44SJohn Forte 3132*fcf3ce44SJohn Forte hba->model_info.device_id = 0; 3133*fcf3ce44SJohn Forte 3134*fcf3ce44SJohn Forte return (0); 3135*fcf3ce44SJohn Forte } 3136*fcf3ce44SJohn Forte /* Read the PCI device id */ 3137*fcf3ce44SJohn Forte pci_id = ddi_get32(hba->pci_acc_handle, 3138*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 3139*fcf3ce44SJohn Forte device_id = (uint16_t)(pci_id >> 16); 3140*fcf3ce44SJohn Forte 3141*fcf3ce44SJohn Forte /* Find matching adapter model */ 3142*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 3143*fcf3ce44SJohn Forte if (emlxs_sbus_model[i].device_id == device_id) { 3144*fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[i], &hba->model_info, 3145*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3146*fcf3ce44SJohn Forte found = 1; 3147*fcf3ce44SJohn Forte break; 3148*fcf3ce44SJohn Forte } 3149*fcf3ce44SJohn Forte } 3150*fcf3ce44SJohn Forte 3151*fcf3ce44SJohn Forte /* If not found then use the unknown model */ 3152*fcf3ce44SJohn Forte if (!found) { 3153*fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 3154*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3155*fcf3ce44SJohn Forte 3156*fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 3157*fcf3ce44SJohn Forte 3158*fcf3ce44SJohn Forte return (0); 3159*fcf3ce44SJohn Forte } 3160*fcf3ce44SJohn Forte } else { /* PCI model */ 3161*fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 3162*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 3163*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3164*fcf3ce44SJohn Forte 3165*fcf3ce44SJohn Forte hba->model_info.device_id = 0; 3166*fcf3ce44SJohn Forte 3167*fcf3ce44SJohn Forte return (0); 3168*fcf3ce44SJohn Forte } 3169*fcf3ce44SJohn Forte /* Read the PCI device id */ 3170*fcf3ce44SJohn Forte device_id = ddi_get16(hba->pci_acc_handle, 3171*fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 3172*fcf3ce44SJohn Forte 3173*fcf3ce44SJohn Forte /* Read the PCI Subsystem id */ 3174*fcf3ce44SJohn Forte ssdid = ddi_get16(hba->pci_acc_handle, 3175*fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 3176*fcf3ce44SJohn Forte 3177*fcf3ce44SJohn Forte if (ssdid == 0 || ssdid == 0xffff) { 3178*fcf3ce44SJohn Forte ssdid = device_id; 3179*fcf3ce44SJohn Forte } 3180*fcf3ce44SJohn Forte /* Read the Cache Line reg */ 3181*fcf3ce44SJohn Forte cache_line = ddi_get32(hba->pci_acc_handle, 3182*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 3183*fcf3ce44SJohn Forte 3184*fcf3ce44SJohn Forte /* Check for the multifunction bit being set */ 3185*fcf3ce44SJohn Forte if ((cache_line & 0x00ff0000) == 0x00800000) { 3186*fcf3ce44SJohn Forte channels = 2; 3187*fcf3ce44SJohn Forte } else { 3188*fcf3ce44SJohn Forte channels = 1; 3189*fcf3ce44SJohn Forte } 3190*fcf3ce44SJohn Forte 3191*fcf3ce44SJohn Forte #ifdef MENLO_TEST 3192*fcf3ce44SJohn Forte /* Convert Zephyr adapters to Hornet adapters */ 3193*fcf3ce44SJohn Forte if ((device_id == PCI_DEVICE_ID_LPe11000_M4) && 3194*fcf3ce44SJohn Forte (cfg[CFG_HORNET_ID].current == 0)) { 3195*fcf3ce44SJohn Forte device_id = PCI_DEVICE_ID_LP21000_M; 3196*fcf3ce44SJohn Forte ssdid = PCI_SSDID_LP21000_M; 3197*fcf3ce44SJohn Forte } 3198*fcf3ce44SJohn Forte #endif /* MENLO_TEST */ 3199*fcf3ce44SJohn Forte 3200*fcf3ce44SJohn Forte /* If device ids are unique, then use them for search */ 3201*fcf3ce44SJohn Forte if (device_id != ssdid) { 3202*fcf3ce44SJohn Forte if (channels > 1) { 3203*fcf3ce44SJohn Forte /* 3204*fcf3ce44SJohn Forte * Find matching adapter model using 3205*fcf3ce44SJohn Forte * device_id, ssdid and channels 3206*fcf3ce44SJohn Forte */ 3207*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3208*fcf3ce44SJohn Forte if ((emlxs_pci_model[i].device_id == 3209*fcf3ce44SJohn Forte device_id) && 3210*fcf3ce44SJohn Forte (emlxs_pci_model[i].ssdid == 3211*fcf3ce44SJohn Forte ssdid) && 3212*fcf3ce44SJohn Forte (emlxs_pci_model[i].channels == 3213*fcf3ce44SJohn Forte channels)) { 3214*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3215*fcf3ce44SJohn Forte &hba->model_info, 3216*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3217*fcf3ce44SJohn Forte found = 1; 3218*fcf3ce44SJohn Forte break; 3219*fcf3ce44SJohn Forte } 3220*fcf3ce44SJohn Forte } 3221*fcf3ce44SJohn Forte } else { 3222*fcf3ce44SJohn Forte /* 3223*fcf3ce44SJohn Forte * Find matching adapter model using 3224*fcf3ce44SJohn Forte * device_id and ssdid 3225*fcf3ce44SJohn Forte */ 3226*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3227*fcf3ce44SJohn Forte if ((emlxs_pci_model[i].device_id == 3228*fcf3ce44SJohn Forte device_id) && 3229*fcf3ce44SJohn Forte (emlxs_pci_model[i].ssdid == 3230*fcf3ce44SJohn Forte ssdid)) { 3231*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3232*fcf3ce44SJohn Forte &hba->model_info, 3233*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3234*fcf3ce44SJohn Forte found = 1; 3235*fcf3ce44SJohn Forte break; 3236*fcf3ce44SJohn Forte } 3237*fcf3ce44SJohn Forte } 3238*fcf3ce44SJohn Forte } 3239*fcf3ce44SJohn Forte } 3240*fcf3ce44SJohn Forte /* If adapter not found, try again */ 3241*fcf3ce44SJohn Forte if (!found) { 3242*fcf3ce44SJohn Forte /* Find matching adapter model */ 3243*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3244*fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id && 3245*fcf3ce44SJohn Forte emlxs_pci_model[i].channels == channels) { 3246*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3247*fcf3ce44SJohn Forte &hba->model_info, 3248*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3249*fcf3ce44SJohn Forte found = 1; 3250*fcf3ce44SJohn Forte break; 3251*fcf3ce44SJohn Forte } 3252*fcf3ce44SJohn Forte } 3253*fcf3ce44SJohn Forte } 3254*fcf3ce44SJohn Forte /* If adapter not found, try one last time */ 3255*fcf3ce44SJohn Forte if (!found) { 3256*fcf3ce44SJohn Forte /* Find matching adapter model */ 3257*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3258*fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id) { 3259*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 3260*fcf3ce44SJohn Forte &hba->model_info, 3261*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3262*fcf3ce44SJohn Forte found = 1; 3263*fcf3ce44SJohn Forte break; 3264*fcf3ce44SJohn Forte } 3265*fcf3ce44SJohn Forte } 3266*fcf3ce44SJohn Forte } 3267*fcf3ce44SJohn Forte /* If not found, set adapter to unknown */ 3268*fcf3ce44SJohn Forte if (!found) { 3269*fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 3270*fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 3271*fcf3ce44SJohn Forte 3272*fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 3273*fcf3ce44SJohn Forte hba->model_info.ssdid = ssdid; 3274*fcf3ce44SJohn Forte 3275*fcf3ce44SJohn Forte return (0); 3276*fcf3ce44SJohn Forte } 3277*fcf3ce44SJohn Forte #ifdef MENLO_TEST 3278*fcf3ce44SJohn Forte /* Convert Hornet program types to Zephyr program types */ 3279*fcf3ce44SJohn Forte if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) && 3280*fcf3ce44SJohn Forte (cfg[CFG_HORNET_PTYPES].current == 0)) { 3281*fcf3ce44SJohn Forte /* 3282*fcf3ce44SJohn Forte * Find matching Zephyr card and copy Zephyr program 3283*fcf3ce44SJohn Forte * types 3284*fcf3ce44SJohn Forte */ 3285*fcf3ce44SJohn Forte for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3286*fcf3ce44SJohn Forte if ((emlxs_pci_model[i].device_id == 3287*fcf3ce44SJohn Forte PCI_DEVICE_ID_LPe11000_M4) && 3288*fcf3ce44SJohn Forte (emlxs_pci_model[i].ssdid == 3289*fcf3ce44SJohn Forte PCI_SSDID_LPe11000_M4) && 3290*fcf3ce44SJohn Forte (emlxs_pci_model[i].channels == channels)) { 3291*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_2, 3292*fcf3ce44SJohn Forte hba->model_info.pt_2, 8); 3293*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_3, 3294*fcf3ce44SJohn Forte hba->model_info.pt_3, 8); 3295*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_6, 3296*fcf3ce44SJohn Forte hba->model_info.pt_6, 8); 3297*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_7, 3298*fcf3ce44SJohn Forte hba->model_info.pt_7, 8); 3299*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_A, 3300*fcf3ce44SJohn Forte hba->model_info.pt_A, 8); 3301*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_B, 3302*fcf3ce44SJohn Forte hba->model_info.pt_B, 8); 3303*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_E, 3304*fcf3ce44SJohn Forte hba->model_info.pt_E, 8); 3305*fcf3ce44SJohn Forte bcopy(emlxs_pci_model[i].pt_FF, 3306*fcf3ce44SJohn Forte hba->model_info.pt_FF, 8); 3307*fcf3ce44SJohn Forte break; 3308*fcf3ce44SJohn Forte } 3309*fcf3ce44SJohn Forte } 3310*fcf3ce44SJohn Forte } 3311*fcf3ce44SJohn Forte #endif /* MENLO_TEST */ 3312*fcf3ce44SJohn Forte 3313*fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT 3314*fcf3ce44SJohn Forte /* 3315*fcf3ce44SJohn Forte * This will disable MSI support for Saturn adapter's due to 3316*fcf3ce44SJohn Forte * a PCI bus issue 3317*fcf3ce44SJohn Forte */ 3318*fcf3ce44SJohn Forte if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 3319*fcf3ce44SJohn Forte hba->model_info.flags &= 3320*fcf3ce44SJohn Forte ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 3321*fcf3ce44SJohn Forte } 3322*fcf3ce44SJohn Forte #endif /* !SATURN_MSI_SUPPORT */ 3323*fcf3ce44SJohn Forte 3324*fcf3ce44SJohn Forte 3325*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 3326*fcf3ce44SJohn Forte /* Verify MSI support */ 3327*fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { 3328*fcf3ce44SJohn Forte uint32_t offset; 3329*fcf3ce44SJohn Forte uint32_t reg; 3330*fcf3ce44SJohn Forte 3331*fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 3332*fcf3ce44SJohn Forte offset = ddi_get32(hba->pci_acc_handle, 3333*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3334*fcf3ce44SJohn Forte offset &= 0xff; 3335*fcf3ce44SJohn Forte 3336*fcf3ce44SJohn Forte while (offset) { 3337*fcf3ce44SJohn Forte reg = ddi_get32(hba->pci_acc_handle, 3338*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 3339*fcf3ce44SJohn Forte 3340*fcf3ce44SJohn Forte if ((reg & 0xff) == MSI_CAP_ID) { 3341*fcf3ce44SJohn Forte break; 3342*fcf3ce44SJohn Forte } 3343*fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 3344*fcf3ce44SJohn Forte } 3345*fcf3ce44SJohn Forte 3346*fcf3ce44SJohn Forte if (offset) { 3347*fcf3ce44SJohn Forte hba->msi_cap_offset = offset + 2; 3348*fcf3ce44SJohn Forte } else { 3349*fcf3ce44SJohn Forte hba->msi_cap_offset = 0; 3350*fcf3ce44SJohn Forte hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 3351*fcf3ce44SJohn Forte 3352*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3353*fcf3ce44SJohn Forte "MSI: control_reg capability not found!"); 3354*fcf3ce44SJohn Forte } 3355*fcf3ce44SJohn Forte } 3356*fcf3ce44SJohn Forte /* Verify MSI-X support */ 3357*fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { 3358*fcf3ce44SJohn Forte uint32_t offset; 3359*fcf3ce44SJohn Forte uint32_t reg; 3360*fcf3ce44SJohn Forte 3361*fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 3362*fcf3ce44SJohn Forte offset = ddi_get32(hba->pci_acc_handle, 3363*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3364*fcf3ce44SJohn Forte offset &= 0xff; 3365*fcf3ce44SJohn Forte 3366*fcf3ce44SJohn Forte while (offset) { 3367*fcf3ce44SJohn Forte reg = ddi_get32(hba->pci_acc_handle, 3368*fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 3369*fcf3ce44SJohn Forte 3370*fcf3ce44SJohn Forte if ((reg & 0xff) == MSIX_CAP_ID) { 3371*fcf3ce44SJohn Forte break; 3372*fcf3ce44SJohn Forte } 3373*fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 3374*fcf3ce44SJohn Forte } 3375*fcf3ce44SJohn Forte 3376*fcf3ce44SJohn Forte if (offset) { 3377*fcf3ce44SJohn Forte hba->msix_cap_offset = offset; 3378*fcf3ce44SJohn Forte } else { 3379*fcf3ce44SJohn Forte hba->msix_cap_offset = 0; 3380*fcf3ce44SJohn Forte hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED; 3381*fcf3ce44SJohn Forte 3382*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3383*fcf3ce44SJohn Forte "MSIX: control_reg capability not found!"); 3384*fcf3ce44SJohn Forte } 3385*fcf3ce44SJohn Forte } 3386*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 3387*fcf3ce44SJohn Forte 3388*fcf3ce44SJohn Forte } 3389*fcf3ce44SJohn Forte 3390*fcf3ce44SJohn Forte return (1); 3391*fcf3ce44SJohn Forte 3392*fcf3ce44SJohn Forte } /* emlxs_init_adapter_info() */ 3393*fcf3ce44SJohn Forte 3394*fcf3ce44SJohn Forte 3395*fcf3ce44SJohn Forte /* EMLXS_PORT_LOCK must be held when call this routine */ 3396*fcf3ce44SJohn Forte static uint32_t 3397*fcf3ce44SJohn Forte emlxs_get_attention(emlxs_hba_t *hba, uint32_t msgid) 3398*fcf3ce44SJohn Forte { 3399*fcf3ce44SJohn Forte uint32_t ha_copy = 0; 3400*fcf3ce44SJohn Forte uint32_t ha_copy2; 3401*fcf3ce44SJohn Forte uint32_t mask = hba->hc_copy; 3402*fcf3ce44SJohn Forte 3403*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 3404*fcf3ce44SJohn Forte 3405*fcf3ce44SJohn Forte read_ha_register: 3406*fcf3ce44SJohn Forte 3407*fcf3ce44SJohn Forte /* Check for default MSI interrupt */ 3408*fcf3ce44SJohn Forte if (msgid == 0) { 3409*fcf3ce44SJohn Forte /* Read host attention register to determine interrupt source */ 3410*fcf3ce44SJohn Forte ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 3411*fcf3ce44SJohn Forte 3412*fcf3ce44SJohn Forte /* Filter out MSI non-default attention bits */ 3413*fcf3ce44SJohn Forte ha_copy2 &= ~(hba->intr_cond); 3414*fcf3ce44SJohn Forte } 3415*fcf3ce44SJohn Forte /* Check for polled or fixed type interrupt */ 3416*fcf3ce44SJohn Forte else if (msgid == -1) { 3417*fcf3ce44SJohn Forte /* Read host attention register to determine interrupt source */ 3418*fcf3ce44SJohn Forte ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 3419*fcf3ce44SJohn Forte } 3420*fcf3ce44SJohn Forte /* Otherwise, assume a mapped MSI interrupt */ 3421*fcf3ce44SJohn Forte else { 3422*fcf3ce44SJohn Forte /* Convert MSI msgid to mapped attention bits */ 3423*fcf3ce44SJohn Forte ha_copy2 = hba->intr_map[msgid]; 3424*fcf3ce44SJohn Forte } 3425*fcf3ce44SJohn Forte 3426*fcf3ce44SJohn Forte #else /* !MSI_SUPPORT */ 3427*fcf3ce44SJohn Forte 3428*fcf3ce44SJohn Forte /* Read host attention register to determine interrupt source */ 3429*fcf3ce44SJohn Forte ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 3430*fcf3ce44SJohn Forte 3431*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 3432*fcf3ce44SJohn Forte 3433*fcf3ce44SJohn Forte /* Check if Hardware error interrupt is enabled */ 3434*fcf3ce44SJohn Forte if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) { 3435*fcf3ce44SJohn Forte ha_copy2 &= ~HA_ERATT; 3436*fcf3ce44SJohn Forte } 3437*fcf3ce44SJohn Forte /* Check if link interrupt is enabled */ 3438*fcf3ce44SJohn Forte if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) { 3439*fcf3ce44SJohn Forte ha_copy2 &= ~HA_LATT; 3440*fcf3ce44SJohn Forte } 3441*fcf3ce44SJohn Forte /* Check if Mailbox interrupt is enabled */ 3442*fcf3ce44SJohn Forte if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) { 3443*fcf3ce44SJohn Forte ha_copy2 &= ~HA_MBATT; 3444*fcf3ce44SJohn Forte } 3445*fcf3ce44SJohn Forte /* Check if ring0 interrupt is enabled */ 3446*fcf3ce44SJohn Forte if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) { 3447*fcf3ce44SJohn Forte ha_copy2 &= ~HA_R0ATT; 3448*fcf3ce44SJohn Forte } 3449*fcf3ce44SJohn Forte /* Check if ring1 interrupt is enabled */ 3450*fcf3ce44SJohn Forte if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) { 3451*fcf3ce44SJohn Forte ha_copy2 &= ~HA_R1ATT; 3452*fcf3ce44SJohn Forte } 3453*fcf3ce44SJohn Forte /* Check if ring2 interrupt is enabled */ 3454*fcf3ce44SJohn Forte if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) { 3455*fcf3ce44SJohn Forte ha_copy2 &= ~HA_R2ATT; 3456*fcf3ce44SJohn Forte } 3457*fcf3ce44SJohn Forte /* Check if ring3 interrupt is enabled */ 3458*fcf3ce44SJohn Forte if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) { 3459*fcf3ce44SJohn Forte ha_copy2 &= ~HA_R3ATT; 3460*fcf3ce44SJohn Forte } 3461*fcf3ce44SJohn Forte /* Accumulate attention bits */ 3462*fcf3ce44SJohn Forte ha_copy |= ha_copy2; 3463*fcf3ce44SJohn Forte 3464*fcf3ce44SJohn Forte /* Clear attentions except for error, link, and autoclear(MSIX) */ 3465*fcf3ce44SJohn Forte ha_copy2 &= ~(HA_ERATT | HA_LATT /* | hba->intr_autoClear */); 3466*fcf3ce44SJohn Forte 3467*fcf3ce44SJohn Forte if (ha_copy2) { 3468*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr), ha_copy2); 3469*fcf3ce44SJohn Forte } 3470*fcf3ce44SJohn Forte return (ha_copy); 3471*fcf3ce44SJohn Forte 3472*fcf3ce44SJohn Forte } /* emlxs_get_attention() */ 3473*fcf3ce44SJohn Forte 3474*fcf3ce44SJohn Forte 3475*fcf3ce44SJohn Forte static void 3476*fcf3ce44SJohn Forte emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy) 3477*fcf3ce44SJohn Forte { 3478*fcf3ce44SJohn Forte /* ha_copy should be pre-filtered */ 3479*fcf3ce44SJohn Forte 3480*fcf3ce44SJohn Forte /* 3481*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3482*fcf3ce44SJohn Forte * "emlxs_proc_attention: ha_copy=%x", ha_copy); 3483*fcf3ce44SJohn Forte */ 3484*fcf3ce44SJohn Forte 3485*fcf3ce44SJohn Forte if (hba->state < FC_WARM_START) { 3486*fcf3ce44SJohn Forte return; 3487*fcf3ce44SJohn Forte } 3488*fcf3ce44SJohn Forte if (!ha_copy) { 3489*fcf3ce44SJohn Forte return; 3490*fcf3ce44SJohn Forte } 3491*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3492*fcf3ce44SJohn Forte (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba, 3493*fcf3ce44SJohn Forte hba->sbus_csr_addr)); 3494*fcf3ce44SJohn Forte } 3495*fcf3ce44SJohn Forte /* Adapter error */ 3496*fcf3ce44SJohn Forte if (ha_copy & HA_ERATT) { 3497*fcf3ce44SJohn Forte HBASTATS.IntrEvent[6]++; 3498*fcf3ce44SJohn Forte emlxs_handle_ff_error(hba); 3499*fcf3ce44SJohn Forte return; 3500*fcf3ce44SJohn Forte } 3501*fcf3ce44SJohn Forte /* Mailbox interrupt */ 3502*fcf3ce44SJohn Forte if (ha_copy & HA_MBATT) { 3503*fcf3ce44SJohn Forte HBASTATS.IntrEvent[5]++; 3504*fcf3ce44SJohn Forte (void) emlxs_handle_mb_event(hba); 3505*fcf3ce44SJohn Forte } 3506*fcf3ce44SJohn Forte /* Link Attention interrupt */ 3507*fcf3ce44SJohn Forte if (ha_copy & HA_LATT) { 3508*fcf3ce44SJohn Forte HBASTATS.IntrEvent[4]++; 3509*fcf3ce44SJohn Forte emlxs_handle_link_event(hba); 3510*fcf3ce44SJohn Forte } 3511*fcf3ce44SJohn Forte /* event on ring 0 - FCP Ring */ 3512*fcf3ce44SJohn Forte if (ha_copy & HA_R0ATT) { 3513*fcf3ce44SJohn Forte HBASTATS.IntrEvent[0]++; 3514*fcf3ce44SJohn Forte emlxs_handle_ring_event(hba, 0, ha_copy); 3515*fcf3ce44SJohn Forte } 3516*fcf3ce44SJohn Forte /* event on ring 1 - IP Ring */ 3517*fcf3ce44SJohn Forte if (ha_copy & HA_R1ATT) { 3518*fcf3ce44SJohn Forte HBASTATS.IntrEvent[1]++; 3519*fcf3ce44SJohn Forte emlxs_handle_ring_event(hba, 1, ha_copy); 3520*fcf3ce44SJohn Forte } 3521*fcf3ce44SJohn Forte /* event on ring 2 - ELS Ring */ 3522*fcf3ce44SJohn Forte if (ha_copy & HA_R2ATT) { 3523*fcf3ce44SJohn Forte HBASTATS.IntrEvent[2]++; 3524*fcf3ce44SJohn Forte emlxs_handle_ring_event(hba, 2, ha_copy); 3525*fcf3ce44SJohn Forte } 3526*fcf3ce44SJohn Forte /* event on ring 3 - CT Ring */ 3527*fcf3ce44SJohn Forte if (ha_copy & HA_R3ATT) { 3528*fcf3ce44SJohn Forte HBASTATS.IntrEvent[3]++; 3529*fcf3ce44SJohn Forte emlxs_handle_ring_event(hba, 3, ha_copy); 3530*fcf3ce44SJohn Forte } 3531*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3532*fcf3ce44SJohn Forte WRITE_SBUS_CSR_REG(hba, 3533*fcf3ce44SJohn Forte FC_SHS_REG(hba, hba->sbus_csr_addr), 3534*fcf3ce44SJohn Forte SBUS_STAT_IP); 3535*fcf3ce44SJohn Forte } 3536*fcf3ce44SJohn Forte /* Set heartbeat flag to show activity */ 3537*fcf3ce44SJohn Forte hba->heartbeat_flag = 1; 3538*fcf3ce44SJohn Forte 3539*fcf3ce44SJohn Forte return; 3540*fcf3ce44SJohn Forte 3541*fcf3ce44SJohn Forte } /* emlxs_proc_attention() */ 3542*fcf3ce44SJohn Forte 3543*fcf3ce44SJohn Forte 3544*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 3545*fcf3ce44SJohn Forte 3546*fcf3ce44SJohn Forte static uint32_t 3547*fcf3ce44SJohn Forte emlxs_msi_intr(char *arg1, char *arg2) 3548*fcf3ce44SJohn Forte { 3549*fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 3550*fcf3ce44SJohn Forte uint16_t msgid; 3551*fcf3ce44SJohn Forte uint32_t hc_copy; 3552*fcf3ce44SJohn Forte uint32_t ha_copy; 3553*fcf3ce44SJohn Forte uint32_t restore = 0; 3554*fcf3ce44SJohn Forte 3555*fcf3ce44SJohn Forte /* 3556*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "emlxs_msi_intr: 3557*fcf3ce44SJohn Forte * arg1=%p arg2=%p", arg1, arg2); 3558*fcf3ce44SJohn Forte */ 3559*fcf3ce44SJohn Forte 3560*fcf3ce44SJohn Forte /* Check for legacy interrupt handling */ 3561*fcf3ce44SJohn Forte if (hba->intr_type == DDI_INTR_TYPE_FIXED) { 3562*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3563*fcf3ce44SJohn Forte 3564*fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 3565*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3566*fcf3ce44SJohn Forte 3567*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3568*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3569*fcf3ce44SJohn Forte } else { 3570*fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 3571*fcf3ce44SJohn Forte } 3572*fcf3ce44SJohn Forte } 3573*fcf3ce44SJohn Forte /* Get host attention bits */ 3574*fcf3ce44SJohn Forte ha_copy = emlxs_get_attention(hba, -1); 3575*fcf3ce44SJohn Forte 3576*fcf3ce44SJohn Forte if (ha_copy == 0) { 3577*fcf3ce44SJohn Forte if (hba->intr_unclaimed) { 3578*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3579*fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 3580*fcf3ce44SJohn Forte } 3581*fcf3ce44SJohn Forte hba->intr_unclaimed = 1; 3582*fcf3ce44SJohn Forte } else { 3583*fcf3ce44SJohn Forte hba->intr_unclaimed = 0; 3584*fcf3ce44SJohn Forte } 3585*fcf3ce44SJohn Forte 3586*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3587*fcf3ce44SJohn Forte 3588*fcf3ce44SJohn Forte /* Process the interrupt */ 3589*fcf3ce44SJohn Forte emlxs_proc_attention(hba, ha_copy); 3590*fcf3ce44SJohn Forte 3591*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3592*fcf3ce44SJohn Forte } 3593*fcf3ce44SJohn Forte /* DDI_INTR_TYPE_MSI */ 3594*fcf3ce44SJohn Forte /* DDI_INTR_TYPE_MSIX */ 3595*fcf3ce44SJohn Forte 3596*fcf3ce44SJohn Forte /* Get MSI message id */ 3597*fcf3ce44SJohn Forte msgid = (uint16_t)(unsigned long)arg2; 3598*fcf3ce44SJohn Forte 3599*fcf3ce44SJohn Forte /* Validate the message id */ 3600*fcf3ce44SJohn Forte if (msgid >= hba->intr_count) { 3601*fcf3ce44SJohn Forte msgid = 0; 3602*fcf3ce44SJohn Forte } 3603*fcf3ce44SJohn Forte mutex_enter(&EMLXS_INTR_LOCK(msgid)); 3604*fcf3ce44SJohn Forte 3605*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3606*fcf3ce44SJohn Forte 3607*fcf3ce44SJohn Forte /* Check if adapter is offline */ 3608*fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 3609*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3610*fcf3ce44SJohn Forte mutex_exit(&EMLXS_INTR_LOCK(msgid)); 3611*fcf3ce44SJohn Forte 3612*fcf3ce44SJohn Forte /* Always claim an MSI interrupt */ 3613*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3614*fcf3ce44SJohn Forte } 3615*fcf3ce44SJohn Forte /* Disable interrupts associated with this msgid */ 3616*fcf3ce44SJohn Forte if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) { 3617*fcf3ce44SJohn Forte hc_copy = hba->hc_copy & ~hba->intr_mask; 3618*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hc_copy); 3619*fcf3ce44SJohn Forte restore = 1; 3620*fcf3ce44SJohn Forte } 3621*fcf3ce44SJohn Forte /* Get host attention bits */ 3622*fcf3ce44SJohn Forte ha_copy = emlxs_get_attention(hba, msgid); 3623*fcf3ce44SJohn Forte 3624*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3625*fcf3ce44SJohn Forte 3626*fcf3ce44SJohn Forte /* Process the interrupt */ 3627*fcf3ce44SJohn Forte emlxs_proc_attention(hba, ha_copy); 3628*fcf3ce44SJohn Forte 3629*fcf3ce44SJohn Forte /* Restore interrupts */ 3630*fcf3ce44SJohn Forte if (restore) { 3631*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3632*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 3633*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3634*fcf3ce44SJohn Forte } 3635*fcf3ce44SJohn Forte mutex_exit(&EMLXS_INTR_LOCK(msgid)); 3636*fcf3ce44SJohn Forte 3637*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3638*fcf3ce44SJohn Forte 3639*fcf3ce44SJohn Forte } /* emlxs_msi_intr() */ 3640*fcf3ce44SJohn Forte 3641*fcf3ce44SJohn Forte #endif /* MSI_SUPPORT */ 3642*fcf3ce44SJohn Forte 3643*fcf3ce44SJohn Forte static int 3644*fcf3ce44SJohn Forte emlxs_intx_intr(char *arg) 3645*fcf3ce44SJohn Forte { 3646*fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3647*fcf3ce44SJohn Forte uint32_t ha_copy = 0; 3648*fcf3ce44SJohn Forte 3649*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3650*fcf3ce44SJohn Forte 3651*fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 3652*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3653*fcf3ce44SJohn Forte 3654*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 3655*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3656*fcf3ce44SJohn Forte } else { 3657*fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 3658*fcf3ce44SJohn Forte } 3659*fcf3ce44SJohn Forte } 3660*fcf3ce44SJohn Forte /* Get host attention bits */ 3661*fcf3ce44SJohn Forte ha_copy = emlxs_get_attention(hba, -1); 3662*fcf3ce44SJohn Forte 3663*fcf3ce44SJohn Forte if (ha_copy == 0) { 3664*fcf3ce44SJohn Forte if (hba->intr_unclaimed) { 3665*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3666*fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 3667*fcf3ce44SJohn Forte } 3668*fcf3ce44SJohn Forte hba->intr_unclaimed = 1; 3669*fcf3ce44SJohn Forte } else { 3670*fcf3ce44SJohn Forte hba->intr_unclaimed = 0; 3671*fcf3ce44SJohn Forte } 3672*fcf3ce44SJohn Forte 3673*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3674*fcf3ce44SJohn Forte 3675*fcf3ce44SJohn Forte /* Process the interrupt */ 3676*fcf3ce44SJohn Forte emlxs_proc_attention(hba, ha_copy); 3677*fcf3ce44SJohn Forte 3678*fcf3ce44SJohn Forte return (DDI_INTR_CLAIMED); 3679*fcf3ce44SJohn Forte 3680*fcf3ce44SJohn Forte } /* emlxs_intx_intr() */ 3681*fcf3ce44SJohn Forte 3682*fcf3ce44SJohn Forte 3683*fcf3ce44SJohn Forte /* ARGSUSED */ 3684*fcf3ce44SJohn Forte static void 3685*fcf3ce44SJohn Forte emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 3686*fcf3ce44SJohn Forte { 3687*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3688*fcf3ce44SJohn Forte IOCB *iocb; 3689*fcf3ce44SJohn Forte 3690*fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3691*fcf3ce44SJohn Forte 3692*fcf3ce44SJohn Forte if (iocb->ulpStatus != 0) { 3693*fcf3ce44SJohn Forte return; 3694*fcf3ce44SJohn Forte } 3695*fcf3ce44SJohn Forte switch (iocb->un.astat.EventCode) { 3696*fcf3ce44SJohn Forte case 0x0100: /* Temp Warning */ 3697*fcf3ce44SJohn Forte 3698*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 3699*fcf3ce44SJohn Forte "Adapter is very hot (%d �C). Take corrective action.", 3700*fcf3ce44SJohn Forte iocb->ulpContext); 3701*fcf3ce44SJohn Forte 3702*fcf3ce44SJohn Forte emlxs_log_temp_event(port, 0x02, iocb->ulpContext); 3703*fcf3ce44SJohn Forte 3704*fcf3ce44SJohn Forte break; 3705*fcf3ce44SJohn Forte 3706*fcf3ce44SJohn Forte 3707*fcf3ce44SJohn Forte case 0x0101: /* Temp Safe */ 3708*fcf3ce44SJohn Forte 3709*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 3710*fcf3ce44SJohn Forte "Adapter temperature now safe (%d �C).", 3711*fcf3ce44SJohn Forte iocb->ulpContext); 3712*fcf3ce44SJohn Forte 3713*fcf3ce44SJohn Forte emlxs_log_temp_event(port, 0x03, iocb->ulpContext); 3714*fcf3ce44SJohn Forte 3715*fcf3ce44SJohn Forte break; 3716*fcf3ce44SJohn Forte } 3717*fcf3ce44SJohn Forte 3718*fcf3ce44SJohn Forte return; 3719*fcf3ce44SJohn Forte 3720*fcf3ce44SJohn Forte } /* emlxs_handle_async_event() */ 3721*fcf3ce44SJohn Forte 3722*fcf3ce44SJohn Forte 3723*fcf3ce44SJohn Forte /* 3724*fcf3ce44SJohn Forte * emlxs_handle_ff_error 3725*fcf3ce44SJohn Forte * 3726*fcf3ce44SJohn Forte * Description: Processes a FireFly error 3727*fcf3ce44SJohn Forte * Runs at Interrupt level 3728*fcf3ce44SJohn Forte * 3729*fcf3ce44SJohn Forte */ 3730*fcf3ce44SJohn Forte extern void 3731*fcf3ce44SJohn Forte emlxs_handle_ff_error(emlxs_hba_t *hba) 3732*fcf3ce44SJohn Forte { 3733*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3734*fcf3ce44SJohn Forte uint32_t status; 3735*fcf3ce44SJohn Forte uint32_t status1; 3736*fcf3ce44SJohn Forte uint32_t status2; 3737*fcf3ce44SJohn Forte 3738*fcf3ce44SJohn Forte /* do what needs to be done, get error from STATUS REGISTER */ 3739*fcf3ce44SJohn Forte status = READ_CSR_REG(hba, FC_HS_REG(hba, hba->csr_addr)); 3740*fcf3ce44SJohn Forte 3741*fcf3ce44SJohn Forte /* Clear Chip error bit */ 3742*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr), HA_ERATT); 3743*fcf3ce44SJohn Forte 3744*fcf3ce44SJohn Forte if (status & HS_OVERTEMP) { 3745*fcf3ce44SJohn Forte status1 = READ_SLIM_ADDR(hba, 3746*fcf3ce44SJohn Forte ((volatile uint8_t *) hba->slim_addr + 0xb0)); 3747*fcf3ce44SJohn Forte 3748*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 3749*fcf3ce44SJohn Forte "Maximum adapter temperature exceeded (%d �C).", 3750*fcf3ce44SJohn Forte status1); 3751*fcf3ce44SJohn Forte 3752*fcf3ce44SJohn Forte hba->flag |= FC_OVERTEMP_EVENT; 3753*fcf3ce44SJohn Forte emlxs_log_temp_event(port, 0x01, status1); 3754*fcf3ce44SJohn Forte } else { 3755*fcf3ce44SJohn Forte status1 = READ_SLIM_ADDR(hba, 3756*fcf3ce44SJohn Forte ((volatile uint8_t *) hba->slim_addr + 0xa8)); 3757*fcf3ce44SJohn Forte status2 = READ_SLIM_ADDR(hba, 3758*fcf3ce44SJohn Forte ((volatile uint8_t *) hba->slim_addr + 0xac)); 3759*fcf3ce44SJohn Forte 3760*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 3761*fcf3ce44SJohn Forte "Host Error Attention: status=0x%x status1=0x%x " 3762*fcf3ce44SJohn Forte "status2=0x%x", status, status1, status2); 3763*fcf3ce44SJohn Forte } 3764*fcf3ce44SJohn Forte 3765*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 3766*fcf3ce44SJohn Forte 3767*fcf3ce44SJohn Forte if (status & HS_FFER6) { 3768*fcf3ce44SJohn Forte (void) thread_create(NULL, 0, emlxs_restart_thread, 3769*fcf3ce44SJohn Forte (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2); 3770*fcf3ce44SJohn Forte } else { 3771*fcf3ce44SJohn Forte (void) thread_create(NULL, 0, emlxs_shutdown_thread, 3772*fcf3ce44SJohn Forte (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2); 3773*fcf3ce44SJohn Forte } 3774*fcf3ce44SJohn Forte 3775*fcf3ce44SJohn Forte } /* emlxs_handle_ff_error() */ 3776*fcf3ce44SJohn Forte 3777*fcf3ce44SJohn Forte 3778*fcf3ce44SJohn Forte 3779*fcf3ce44SJohn Forte extern void 3780*fcf3ce44SJohn Forte emlxs_reset_link_thread(void *arg) 3781*fcf3ce44SJohn Forte { 3782*fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3783*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3784*fcf3ce44SJohn Forte 3785*fcf3ce44SJohn Forte /* Attempt a link reset to recover */ 3786*fcf3ce44SJohn Forte (void) emlxs_reset(port, FC_FCA_LINK_RESET); 3787*fcf3ce44SJohn Forte 3788*fcf3ce44SJohn Forte (void) thread_exit(); 3789*fcf3ce44SJohn Forte 3790*fcf3ce44SJohn Forte } /* emlxs_reset_link_thread() */ 3791*fcf3ce44SJohn Forte 3792*fcf3ce44SJohn Forte 3793*fcf3ce44SJohn Forte extern void 3794*fcf3ce44SJohn Forte emlxs_restart_thread(void *arg) 3795*fcf3ce44SJohn Forte { 3796*fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3797*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3798*fcf3ce44SJohn Forte 3799*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 3800*fcf3ce44SJohn Forte 3801*fcf3ce44SJohn Forte /* Attempt a full hardware reset to recover */ 3802*fcf3ce44SJohn Forte if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 3803*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 3804*fcf3ce44SJohn Forte 3805*fcf3ce44SJohn Forte (void) thread_create(NULL, 0, emlxs_shutdown_thread, 3806*fcf3ce44SJohn Forte (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2); 3807*fcf3ce44SJohn Forte } 3808*fcf3ce44SJohn Forte (void) thread_exit(); 3809*fcf3ce44SJohn Forte 3810*fcf3ce44SJohn Forte } /* emlxs_restart_thread() */ 3811*fcf3ce44SJohn Forte 3812*fcf3ce44SJohn Forte 3813*fcf3ce44SJohn Forte extern void 3814*fcf3ce44SJohn Forte emlxs_shutdown_thread(void *arg) 3815*fcf3ce44SJohn Forte { 3816*fcf3ce44SJohn Forte emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3817*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3818*fcf3ce44SJohn Forte 3819*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3820*fcf3ce44SJohn Forte if (hba->flag & FC_SHUTDOWN) { 3821*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3822*fcf3ce44SJohn Forte (void) thread_exit(); 3823*fcf3ce44SJohn Forte } 3824*fcf3ce44SJohn Forte hba->flag |= FC_SHUTDOWN; 3825*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3826*fcf3ce44SJohn Forte 3827*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Shutting down..."); 3828*fcf3ce44SJohn Forte 3829*fcf3ce44SJohn Forte /* Take adapter offline and leave it there */ 3830*fcf3ce44SJohn Forte (void) emlxs_offline(hba); 3831*fcf3ce44SJohn Forte 3832*fcf3ce44SJohn Forte /* Log a dump event */ 3833*fcf3ce44SJohn Forte emlxs_log_dump_event(port, NULL, 0); 3834*fcf3ce44SJohn Forte 3835*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 3836*fcf3ce44SJohn Forte 3837*fcf3ce44SJohn Forte (void) thread_exit(); 3838*fcf3ce44SJohn Forte 3839*fcf3ce44SJohn Forte } /* emlxs_shutdown_thread() */ 3840*fcf3ce44SJohn Forte 3841*fcf3ce44SJohn Forte 3842*fcf3ce44SJohn Forte 3843*fcf3ce44SJohn Forte /* 3844*fcf3ce44SJohn Forte * emlxs_handle_link_event 3845*fcf3ce44SJohn Forte * 3846*fcf3ce44SJohn Forte * Description: Process a Link Attention. 3847*fcf3ce44SJohn Forte * 3848*fcf3ce44SJohn Forte */ 3849*fcf3ce44SJohn Forte static void 3850*fcf3ce44SJohn Forte emlxs_handle_link_event(emlxs_hba_t *hba) 3851*fcf3ce44SJohn Forte { 3852*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3853*fcf3ce44SJohn Forte MAILBOX *mb; 3854*fcf3ce44SJohn Forte 3855*fcf3ce44SJohn Forte HBASTATS.LinkEvent++; 3856*fcf3ce44SJohn Forte 3857*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, 3858*fcf3ce44SJohn Forte "event=%x", HBASTATS.LinkEvent); 3859*fcf3ce44SJohn Forte 3860*fcf3ce44SJohn Forte 3861*fcf3ce44SJohn Forte /* Get a buffer which will be used for mailbox commands */ 3862*fcf3ce44SJohn Forte if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) { 3863*fcf3ce44SJohn Forte /* Get link attention message */ 3864*fcf3ce44SJohn Forte if (emlxs_mb_read_la(hba, mb) == 0) { 3865*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != 3866*fcf3ce44SJohn Forte MBX_BUSY) { 3867*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 3868*fcf3ce44SJohn Forte (uint8_t *)mb); 3869*fcf3ce44SJohn Forte } 3870*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 3871*fcf3ce44SJohn Forte 3872*fcf3ce44SJohn Forte 3873*fcf3ce44SJohn Forte /* 3874*fcf3ce44SJohn Forte * Clear Link Attention in HA REG 3875*fcf3ce44SJohn Forte */ 3876*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, 3877*fcf3ce44SJohn Forte FC_HA_REG(hba, hba->csr_addr), HA_LATT); 3878*fcf3ce44SJohn Forte 3879*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 3880*fcf3ce44SJohn Forte } else { 3881*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 3882*fcf3ce44SJohn Forte } 3883*fcf3ce44SJohn Forte } 3884*fcf3ce44SJohn Forte } /* emlxs_handle_link_event() */ 3885*fcf3ce44SJohn Forte 3886*fcf3ce44SJohn Forte 3887*fcf3ce44SJohn Forte /* 3888*fcf3ce44SJohn Forte * emlxs_handle_ring_event 3889*fcf3ce44SJohn Forte * 3890*fcf3ce44SJohn Forte * Description: Process a Ring Attention. 3891*fcf3ce44SJohn Forte * 3892*fcf3ce44SJohn Forte */ 3893*fcf3ce44SJohn Forte static void 3894*fcf3ce44SJohn Forte emlxs_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, uint32_t ha_copy) 3895*fcf3ce44SJohn Forte { 3896*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3897*fcf3ce44SJohn Forte RING *rp; 3898*fcf3ce44SJohn Forte IOCB *entry; 3899*fcf3ce44SJohn Forte IOCBQ *iocbq; 3900*fcf3ce44SJohn Forte IOCBQ local_iocbq; 3901*fcf3ce44SJohn Forte PGP *pgp; 3902*fcf3ce44SJohn Forte uint32_t count; 3903*fcf3ce44SJohn Forte volatile uint32_t chipatt; 3904*fcf3ce44SJohn Forte void *ioa2; 3905*fcf3ce44SJohn Forte uint32_t reg; 3906*fcf3ce44SJohn Forte off_t offset; 3907*fcf3ce44SJohn Forte IOCBQ *rsp_head = NULL; 3908*fcf3ce44SJohn Forte IOCBQ *rsp_tail = NULL; 3909*fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3910*fcf3ce44SJohn Forte 3911*fcf3ce44SJohn Forte count = 0; 3912*fcf3ce44SJohn Forte rp = &hba->ring[ring_no]; 3913*fcf3ce44SJohn Forte 3914*fcf3ce44SJohn Forte /* Isolate this ring's host attention bits */ 3915*fcf3ce44SJohn Forte /* This makes all ring attention bits equal to Ring0 attention bits */ 3916*fcf3ce44SJohn Forte reg = (ha_copy >> (ring_no * 4)) & 0x0f; 3917*fcf3ce44SJohn Forte 3918*fcf3ce44SJohn Forte /* 3919*fcf3ce44SJohn Forte * Gather iocb entries off response ring. Ensure entry is owned by 3920*fcf3ce44SJohn Forte * the host. 3921*fcf3ce44SJohn Forte */ 3922*fcf3ce44SJohn Forte pgp = (PGP *) & ((SLIM2 *) hba->slim2.virt)->mbx.us.s2.port[ring_no]; 3923*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)&(pgp->rspPutInx) - 3924*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 3925*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 3926*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 3927*fcf3ce44SJohn Forte rp->fc_port_rspidx = PCIMEM_LONG(pgp->rspPutInx); 3928*fcf3ce44SJohn Forte 3929*fcf3ce44SJohn Forte /* While ring is not empty */ 3930*fcf3ce44SJohn Forte while (rp->fc_rspidx != rp->fc_port_rspidx) { 3931*fcf3ce44SJohn Forte HBASTATS.IocbReceived[ring_no]++; 3932*fcf3ce44SJohn Forte 3933*fcf3ce44SJohn Forte /* Get the next response ring iocb */ 3934*fcf3ce44SJohn Forte entry = (IOCB *) (((char *)rp->fc_rspringaddr + 3935*fcf3ce44SJohn Forte (rp->fc_rspidx * hba->iocb_rsp_size))); 3936*fcf3ce44SJohn Forte 3937*fcf3ce44SJohn Forte /* DMA sync the response ring iocb for the adapter */ 3938*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)entry - 3939*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 3940*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 3941*fcf3ce44SJohn Forte hba->iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL); 3942*fcf3ce44SJohn Forte 3943*fcf3ce44SJohn Forte count++; 3944*fcf3ce44SJohn Forte 3945*fcf3ce44SJohn Forte /* Copy word6 and word7 to local iocb for now */ 3946*fcf3ce44SJohn Forte iocbq = &local_iocbq; 3947*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)entry + 6, (uint32_t *)iocbq + 6, 3948*fcf3ce44SJohn Forte (sizeof (uint32_t) * 2)); 3949*fcf3ce44SJohn Forte 3950*fcf3ce44SJohn Forte /* when LE is not set, entire Command has not been received */ 3951*fcf3ce44SJohn Forte if (!iocbq->iocb.ulpLe) { 3952*fcf3ce44SJohn Forte /* This should never happen */ 3953*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg, 3954*fcf3ce44SJohn Forte "ulpLE is not set. ring=%d iotag=%x cmd=%x " 3955*fcf3ce44SJohn Forte "status=%x", ring_no, iocbq->iocb.ulpIoTag, 3956*fcf3ce44SJohn Forte iocbq->iocb.ulpCommand, iocbq->iocb.ulpStatus); 3957*fcf3ce44SJohn Forte 3958*fcf3ce44SJohn Forte goto next; 3959*fcf3ce44SJohn Forte } 3960*fcf3ce44SJohn Forte switch (iocbq->iocb.ulpCommand) { 3961*fcf3ce44SJohn Forte /* Ring 0 registered commands */ 3962*fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR: 3963*fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX: 3964*fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR: 3965*fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX: 3966*fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR: 3967*fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX: 3968*fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR: 3969*fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX: 3970*fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR: 3971*fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX: 3972*fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR: 3973*fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX: 3974*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 3975*fcf3ce44SJohn Forte case CMD_FCP_TSEND_CX: 3976*fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: 3977*fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: 3978*fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: 3979*fcf3ce44SJohn Forte case CMD_FCP_TRSP_CX: 3980*fcf3ce44SJohn Forte case CMD_FCP_TRSP64_CX: 3981*fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 3982*fcf3ce44SJohn Forte 3983*fcf3ce44SJohn Forte /* Ring 1 registered commands */ 3984*fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN: 3985*fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX: 3986*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX: 3987*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR: 3988*fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN: 3989*fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX: 3990*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX: 3991*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR: 3992*fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR: 3993*fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX: 3994*fcf3ce44SJohn Forte 3995*fcf3ce44SJohn Forte /* Ring 2 registered commands */ 3996*fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR: 3997*fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX: 3998*fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX: 3999*fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR: 4000*fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX: 4001*fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX: 4002*fcf3ce44SJohn Forte 4003*fcf3ce44SJohn Forte /* Ring 3 registered commands */ 4004*fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR: 4005*fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX: 4006*fcf3ce44SJohn Forte 4007*fcf3ce44SJohn Forte sbp = emlxs_unregister_pkt(rp, iocbq->iocb.ulpIoTag, 0); 4008*fcf3ce44SJohn Forte break; 4009*fcf3ce44SJohn Forte 4010*fcf3ce44SJohn Forte default: 4011*fcf3ce44SJohn Forte sbp = NULL; 4012*fcf3ce44SJohn Forte } 4013*fcf3ce44SJohn Forte 4014*fcf3ce44SJohn Forte /* If packet is stale, then drop it. */ 4015*fcf3ce44SJohn Forte if (sbp == STALE_PACKET) { 4016*fcf3ce44SJohn Forte /* Copy entry to the local iocbq */ 4017*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)entry, (uint32_t *)iocbq, 4018*fcf3ce44SJohn Forte hba->iocb_rsp_size); 4019*fcf3ce44SJohn Forte 4020*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 4021*fcf3ce44SJohn Forte "ringno=%d iocb=%p cmd=%x status=%x error=%x " 4022*fcf3ce44SJohn Forte "iotag=%x context=%x info=%x", ring_no, iocbq, 4023*fcf3ce44SJohn Forte (uint8_t)iocbq->iocb.ulpCommand, 4024*fcf3ce44SJohn Forte iocbq->iocb.ulpStatus, 4025*fcf3ce44SJohn Forte (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 4026*fcf3ce44SJohn Forte (uint16_t)iocbq->iocb.ulpIoTag, 4027*fcf3ce44SJohn Forte (uint16_t)iocbq->iocb.ulpContext, 4028*fcf3ce44SJohn Forte (uint8_t)iocbq->iocb.ulpRsvdByte); 4029*fcf3ce44SJohn Forte 4030*fcf3ce44SJohn Forte goto next; 4031*fcf3ce44SJohn Forte } 4032*fcf3ce44SJohn Forte /* 4033*fcf3ce44SJohn Forte * If a packet was found, then queue the packet's iocb for 4034*fcf3ce44SJohn Forte * deferred processing 4035*fcf3ce44SJohn Forte */ 4036*fcf3ce44SJohn Forte else if (sbp) { 4037*fcf3ce44SJohn Forte atomic_add_32(&hba->io_active, -1); 4038*fcf3ce44SJohn Forte 4039*fcf3ce44SJohn Forte /* Copy entry to sbp's iocbq */ 4040*fcf3ce44SJohn Forte iocbq = &sbp->iocbq; 4041*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)entry, (uint32_t *)iocbq, 4042*fcf3ce44SJohn Forte hba->iocb_rsp_size); 4043*fcf3ce44SJohn Forte 4044*fcf3ce44SJohn Forte iocbq->next = NULL; 4045*fcf3ce44SJohn Forte 4046*fcf3ce44SJohn Forte /* 4047*fcf3ce44SJohn Forte * If this is NOT a polled command completion or a 4048*fcf3ce44SJohn Forte * driver allocated pkt, then defer pkt completion. 4049*fcf3ce44SJohn Forte */ 4050*fcf3ce44SJohn Forte if (!(sbp->pkt_flags & PACKET_POLLED | 4051*fcf3ce44SJohn Forte PACKET_ALLOCATED)) { 4052*fcf3ce44SJohn Forte /* Add the IOCB to the local list */ 4053*fcf3ce44SJohn Forte if (!rsp_head) { 4054*fcf3ce44SJohn Forte rsp_head = iocbq; 4055*fcf3ce44SJohn Forte } else { 4056*fcf3ce44SJohn Forte rsp_tail->next = iocbq; 4057*fcf3ce44SJohn Forte } 4058*fcf3ce44SJohn Forte 4059*fcf3ce44SJohn Forte rsp_tail = iocbq; 4060*fcf3ce44SJohn Forte 4061*fcf3ce44SJohn Forte goto next; 4062*fcf3ce44SJohn Forte } 4063*fcf3ce44SJohn Forte } else { 4064*fcf3ce44SJohn Forte /* Copy entry to the local iocbq */ 4065*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)entry, (uint32_t *)iocbq, 4066*fcf3ce44SJohn Forte hba->iocb_rsp_size); 4067*fcf3ce44SJohn Forte 4068*fcf3ce44SJohn Forte iocbq->next = NULL; 4069*fcf3ce44SJohn Forte iocbq->bp = NULL; 4070*fcf3ce44SJohn Forte iocbq->port = &PPORT; 4071*fcf3ce44SJohn Forte iocbq->ring = rp; 4072*fcf3ce44SJohn Forte iocbq->node = NULL; 4073*fcf3ce44SJohn Forte iocbq->sbp = NULL; 4074*fcf3ce44SJohn Forte iocbq->flag = 0; 4075*fcf3ce44SJohn Forte } 4076*fcf3ce44SJohn Forte 4077*fcf3ce44SJohn Forte /* process the ring event now */ 4078*fcf3ce44SJohn Forte emlxs_proc_ring_event(hba, rp, iocbq); 4079*fcf3ce44SJohn Forte 4080*fcf3ce44SJohn Forte next: 4081*fcf3ce44SJohn Forte /* Increment the driver's local response get index */ 4082*fcf3ce44SJohn Forte if (++rp->fc_rspidx >= rp->fc_numRiocb) { 4083*fcf3ce44SJohn Forte rp->fc_rspidx = 0; 4084*fcf3ce44SJohn Forte } 4085*fcf3ce44SJohn Forte } /* while(TRUE) */ 4086*fcf3ce44SJohn Forte 4087*fcf3ce44SJohn Forte if (rsp_head) { 4088*fcf3ce44SJohn Forte mutex_enter(&rp->rsp_lock); 4089*fcf3ce44SJohn Forte if (rp->rsp_head == NULL) { 4090*fcf3ce44SJohn Forte rp->rsp_head = rsp_head; 4091*fcf3ce44SJohn Forte rp->rsp_tail = rsp_tail; 4092*fcf3ce44SJohn Forte } else { 4093*fcf3ce44SJohn Forte rp->rsp_tail->next = rsp_head; 4094*fcf3ce44SJohn Forte rp->rsp_tail = rsp_tail; 4095*fcf3ce44SJohn Forte } 4096*fcf3ce44SJohn Forte mutex_exit(&rp->rsp_lock); 4097*fcf3ce44SJohn Forte 4098*fcf3ce44SJohn Forte emlxs_thread_trigger2(&rp->intr_thread, emlxs_proc_ring, rp); 4099*fcf3ce44SJohn Forte } 4100*fcf3ce44SJohn Forte /* Check if at least one response entry was processed */ 4101*fcf3ce44SJohn Forte if (count) { 4102*fcf3ce44SJohn Forte /* Update response get index for the adapter */ 4103*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 4104*fcf3ce44SJohn Forte ((SLIM2 *) hba->slim2.virt)->mbx.us.s2.host[ring_no]. 4105*fcf3ce44SJohn Forte rspGetInx = PCIMEM_LONG(rp->fc_rspidx); 4106*fcf3ce44SJohn Forte 4107*fcf3ce44SJohn Forte /* DMA sync the index for the adapter */ 4108*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)&(( 4109*fcf3ce44SJohn Forte (SLIM2 *)hba->slim2.virt)->mbx.us.s2.host[ring_no]. 4110*fcf3ce44SJohn Forte rspGetInx) - 4111*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 4112*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4113*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 4114*fcf3ce44SJohn Forte } else { 4115*fcf3ce44SJohn Forte ioa2 = (void *) ((char *)hba->slim_addr + 4116*fcf3ce44SJohn Forte hba->hgp_ring_offset + (((ring_no * 2) + 1) * 4117*fcf3ce44SJohn Forte sizeof (uint32_t))); 4118*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, (volatile uint32_t *) ioa2, 4119*fcf3ce44SJohn Forte rp->fc_rspidx); 4120*fcf3ce44SJohn Forte } 4121*fcf3ce44SJohn Forte 4122*fcf3ce44SJohn Forte if (reg & HA_R0RE_REQ) { 4123*fcf3ce44SJohn Forte /* HBASTATS.chipRingFree++; */ 4124*fcf3ce44SJohn Forte 4125*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 4126*fcf3ce44SJohn Forte 4127*fcf3ce44SJohn Forte /* Tell the adapter we serviced the ring */ 4128*fcf3ce44SJohn Forte chipatt = ((CA_R0ATT | CA_R0RE_RSP) << 4129*fcf3ce44SJohn Forte (ring_no * 4)); 4130*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), 4131*fcf3ce44SJohn Forte chipatt); 4132*fcf3ce44SJohn Forte 4133*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 4134*fcf3ce44SJohn Forte } 4135*fcf3ce44SJohn Forte } 4136*fcf3ce44SJohn Forte if (reg & HA_R0CE_RSP) { 4137*fcf3ce44SJohn Forte /* HBASTATS.hostRingFree++; */ 4138*fcf3ce44SJohn Forte 4139*fcf3ce44SJohn Forte /* Cmd ring may be available. Try sending more iocbs */ 4140*fcf3ce44SJohn Forte emlxs_issue_iocb_cmd(hba, rp, 0); 4141*fcf3ce44SJohn Forte } 4142*fcf3ce44SJohn Forte /* HBASTATS.ringEvent++; */ 4143*fcf3ce44SJohn Forte 4144*fcf3ce44SJohn Forte return; 4145*fcf3ce44SJohn Forte 4146*fcf3ce44SJohn Forte } /* emlxs_handle_ring_event() */ 4147*fcf3ce44SJohn Forte 4148*fcf3ce44SJohn Forte 4149*fcf3ce44SJohn Forte /* ARGSUSED */ 4150*fcf3ce44SJohn Forte extern void 4151*fcf3ce44SJohn Forte emlxs_proc_ring(emlxs_hba_t *hba, RING *rp, void *arg2) 4152*fcf3ce44SJohn Forte { 4153*fcf3ce44SJohn Forte IOCBQ *iocbq; 4154*fcf3ce44SJohn Forte IOCBQ *rsp_head; 4155*fcf3ce44SJohn Forte 4156*fcf3ce44SJohn Forte /* 4157*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "emlxs_proc_ring: 4158*fcf3ce44SJohn Forte * ringo=%d", rp->ringno); 4159*fcf3ce44SJohn Forte */ 4160*fcf3ce44SJohn Forte 4161*fcf3ce44SJohn Forte mutex_enter(&rp->rsp_lock); 4162*fcf3ce44SJohn Forte 4163*fcf3ce44SJohn Forte while ((rsp_head = rp->rsp_head) != NULL) { 4164*fcf3ce44SJohn Forte rp->rsp_head = NULL; 4165*fcf3ce44SJohn Forte rp->rsp_tail = NULL; 4166*fcf3ce44SJohn Forte 4167*fcf3ce44SJohn Forte mutex_exit(&rp->rsp_lock); 4168*fcf3ce44SJohn Forte 4169*fcf3ce44SJohn Forte while ((iocbq = rsp_head) != NULL) { 4170*fcf3ce44SJohn Forte rsp_head = (IOCBQ *) iocbq->next; 4171*fcf3ce44SJohn Forte 4172*fcf3ce44SJohn Forte emlxs_proc_ring_event(hba, rp, iocbq); 4173*fcf3ce44SJohn Forte } 4174*fcf3ce44SJohn Forte 4175*fcf3ce44SJohn Forte mutex_enter(&rp->rsp_lock); 4176*fcf3ce44SJohn Forte } 4177*fcf3ce44SJohn Forte 4178*fcf3ce44SJohn Forte mutex_exit(&rp->rsp_lock); 4179*fcf3ce44SJohn Forte 4180*fcf3ce44SJohn Forte emlxs_issue_iocb_cmd(hba, rp, 0); 4181*fcf3ce44SJohn Forte 4182*fcf3ce44SJohn Forte return; 4183*fcf3ce44SJohn Forte 4184*fcf3ce44SJohn Forte } /* emlxs_proc_ring() */ 4185*fcf3ce44SJohn Forte 4186*fcf3ce44SJohn Forte 4187*fcf3ce44SJohn Forte /* 4188*fcf3ce44SJohn Forte * Called from SLI-1 and SLI-2 ring event routines to process a rsp ring IOCB. 4189*fcf3ce44SJohn Forte */ 4190*fcf3ce44SJohn Forte static void 4191*fcf3ce44SJohn Forte emlxs_proc_ring_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 4192*fcf3ce44SJohn Forte { 4193*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 4194*fcf3ce44SJohn Forte char buffer[MAX_MSG_DATA + 1]; 4195*fcf3ce44SJohn Forte IOCB *iocb; 4196*fcf3ce44SJohn Forte 4197*fcf3ce44SJohn Forte iocb = &iocbq->iocb; 4198*fcf3ce44SJohn Forte 4199*fcf3ce44SJohn Forte /* Check for IOCB local error */ 4200*fcf3ce44SJohn Forte if (iocb->ulpStatus == IOSTAT_LOCAL_REJECT) { 4201*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 4202*fcf3ce44SJohn Forte "Local reject. ringno=%d iocb=%p cmd=%x iotag=%x " 4203*fcf3ce44SJohn Forte "context=%x info=%x error=%x", 4204*fcf3ce44SJohn Forte rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 4205*fcf3ce44SJohn Forte (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 4206*fcf3ce44SJohn Forte (uint8_t)iocb->ulpRsvdByte, 4207*fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 4208*fcf3ce44SJohn Forte } else if (iocb->ulpStatus == IOSTAT_ILLEGAL_FRAME_RCVD) { 4209*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 4210*fcf3ce44SJohn Forte "Illegal frame. ringno=%d iocb=%p cmd=%x iotag=%x " 4211*fcf3ce44SJohn Forte "context=%x info=%x error=%x", 4212*fcf3ce44SJohn Forte rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 4213*fcf3ce44SJohn Forte (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 4214*fcf3ce44SJohn Forte (uint8_t)iocb->ulpRsvdByte, 4215*fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 4216*fcf3ce44SJohn Forte } 4217*fcf3ce44SJohn Forte switch (iocb->ulpCommand) { 4218*fcf3ce44SJohn Forte /* RING 0 FCP commands */ 4219*fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR: 4220*fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX: 4221*fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR: 4222*fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX: 4223*fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR: 4224*fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX: 4225*fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR: 4226*fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX: 4227*fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR: 4228*fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX: 4229*fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR: 4230*fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX: 4231*fcf3ce44SJohn Forte (void) emlxs_handle_fcp_event(hba, rp, iocbq); 4232*fcf3ce44SJohn Forte break; 4233*fcf3ce44SJohn Forte 4234*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 4235*fcf3ce44SJohn Forte case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 4236*fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 4237*fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 4238*fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 4239*fcf3ce44SJohn Forte case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 4240*fcf3ce44SJohn Forte case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 4241*fcf3ce44SJohn Forte (void) emlxs_fct_handle_fcp_event(hba, rp, iocbq); 4242*fcf3ce44SJohn Forte break; 4243*fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 4244*fcf3ce44SJohn Forte 4245*fcf3ce44SJohn Forte /* RING 1 IP commands */ 4246*fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN: 4247*fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX: 4248*fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN: 4249*fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX: 4250*fcf3ce44SJohn Forte (void) emlxs_ip_handle_event(hba, rp, iocbq); 4251*fcf3ce44SJohn Forte break; 4252*fcf3ce44SJohn Forte 4253*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX: 4254*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR: 4255*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX: 4256*fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR: 4257*fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 4258*fcf3ce44SJohn Forte case FC_TYPE_IS8802_SNAP: 4259*fcf3ce44SJohn Forte (void) emlxs_ip_handle_event(hba, rp, iocbq); 4260*fcf3ce44SJohn Forte break; 4261*fcf3ce44SJohn Forte 4262*fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 4263*fcf3ce44SJohn Forte (void) emlxs_ct_handle_event(hba, rp, iocbq); 4264*fcf3ce44SJohn Forte break; 4265*fcf3ce44SJohn Forte 4266*fcf3ce44SJohn Forte default: 4267*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 4268*fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 4269*fcf3ce44SJohn Forte iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 4270*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->ulpIoTag, iocb->ulpContext); 4271*fcf3ce44SJohn Forte } 4272*fcf3ce44SJohn Forte break; 4273*fcf3ce44SJohn Forte 4274*fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE_CX: 4275*fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE64_CX: 4276*fcf3ce44SJohn Forte case CMD_RCV_SEQ64_CX: 4277*fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 4278*fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 4279*fcf3ce44SJohn Forte case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 4280*fcf3ce44SJohn Forte (void) emlxs_handle_rcv_seq(hba, rp, iocbq); 4281*fcf3ce44SJohn Forte break; 4282*fcf3ce44SJohn Forte 4283*fcf3ce44SJohn Forte case CMD_RCV_SEQ_LIST64_CX: 4284*fcf3ce44SJohn Forte (void) emlxs_ip_handle_rcv_seq_list(hba, rp, iocbq); 4285*fcf3ce44SJohn Forte break; 4286*fcf3ce44SJohn Forte 4287*fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR: 4288*fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX: 4289*fcf3ce44SJohn Forte (void) emlxs_handle_create_xri(hba, rp, iocbq); 4290*fcf3ce44SJohn Forte break; 4291*fcf3ce44SJohn Forte 4292*fcf3ce44SJohn Forte /* RING 2 ELS commands */ 4293*fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR: 4294*fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX: 4295*fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX: 4296*fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR: 4297*fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX: 4298*fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX: 4299*fcf3ce44SJohn Forte (void) emlxs_els_handle_event(hba, rp, iocbq); 4300*fcf3ce44SJohn Forte break; 4301*fcf3ce44SJohn Forte 4302*fcf3ce44SJohn Forte /* RING 3 CT commands */ 4303*fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR: 4304*fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX: 4305*fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 4306*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 4307*fcf3ce44SJohn Forte case EMLXS_MENLO_TYPE: 4308*fcf3ce44SJohn Forte (void) emlxs_menlo_handle_event(hba, rp, iocbq); 4309*fcf3ce44SJohn Forte break; 4310*fcf3ce44SJohn Forte #endif /* MENLO_SUPPORT */ 4311*fcf3ce44SJohn Forte 4312*fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 4313*fcf3ce44SJohn Forte (void) emlxs_ct_handle_event(hba, rp, iocbq); 4314*fcf3ce44SJohn Forte break; 4315*fcf3ce44SJohn Forte 4316*fcf3ce44SJohn Forte default: 4317*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 4318*fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 4319*fcf3ce44SJohn Forte iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 4320*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->ulpIoTag, iocb->ulpContext); 4321*fcf3ce44SJohn Forte } 4322*fcf3ce44SJohn Forte break; 4323*fcf3ce44SJohn Forte 4324*fcf3ce44SJohn Forte case CMD_ABORT_XRI_CN: /* Abort fcp command */ 4325*fcf3ce44SJohn Forte 4326*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 4327*fcf3ce44SJohn Forte "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 4328*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 4329*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortIoTag, 4330*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->un.acxri.parm); 4331*fcf3ce44SJohn Forte 4332*fcf3ce44SJohn Forte break; 4333*fcf3ce44SJohn Forte 4334*fcf3ce44SJohn Forte case CMD_ABORT_XRI_CX: /* Abort command */ 4335*fcf3ce44SJohn Forte 4336*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 4337*fcf3ce44SJohn Forte "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x", 4338*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 4339*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortIoTag, 4340*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->un.acxri.parm); 4341*fcf3ce44SJohn Forte 4342*fcf3ce44SJohn Forte break; 4343*fcf3ce44SJohn Forte 4344*fcf3ce44SJohn Forte case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 4345*fcf3ce44SJohn Forte 4346*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 4347*fcf3ce44SJohn Forte "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x", 4348*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 4349*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortIoTag, 4350*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->un.acxri.parm); 4351*fcf3ce44SJohn Forte 4352*fcf3ce44SJohn Forte break; 4353*fcf3ce44SJohn Forte 4354*fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 4355*fcf3ce44SJohn Forte 4356*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 4357*fcf3ce44SJohn Forte "CLOSE_XRI_CR: rpi=%d iotag=%x status=%x parm=%x", 4358*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 4359*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortIoTag, 4360*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->un.acxri.parm); 4361*fcf3ce44SJohn Forte 4362*fcf3ce44SJohn Forte break; 4363*fcf3ce44SJohn Forte 4364*fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 4365*fcf3ce44SJohn Forte 4366*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 4367*fcf3ce44SJohn Forte "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x", 4368*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 4369*fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortIoTag, 4370*fcf3ce44SJohn Forte iocb->ulpStatus, iocb->un.acxri.parm); 4371*fcf3ce44SJohn Forte 4372*fcf3ce44SJohn Forte break; 4373*fcf3ce44SJohn Forte 4374*fcf3ce44SJohn Forte case CMD_ADAPTER_MSG: 4375*fcf3ce44SJohn Forte /* Allows debug adapter firmware messages to print on host */ 4376*fcf3ce44SJohn Forte bzero(buffer, sizeof (buffer)); 4377*fcf3ce44SJohn Forte bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 4378*fcf3ce44SJohn Forte 4379*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 4380*fcf3ce44SJohn Forte 4381*fcf3ce44SJohn Forte break; 4382*fcf3ce44SJohn Forte 4383*fcf3ce44SJohn Forte case CMD_QUE_RING_LIST64_CN: 4384*fcf3ce44SJohn Forte case CMD_QUE_RING_BUF64_CN: 4385*fcf3ce44SJohn Forte break; 4386*fcf3ce44SJohn Forte 4387*fcf3ce44SJohn Forte case CMD_ASYNC_STATUS: 4388*fcf3ce44SJohn Forte (void) emlxs_handle_async_event(hba, rp, iocbq); 4389*fcf3ce44SJohn Forte break; 4390*fcf3ce44SJohn Forte 4391*fcf3ce44SJohn Forte default: 4392*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 4393*fcf3ce44SJohn Forte "cmd=%x status=%x iotag=%x context=%x", 4394*fcf3ce44SJohn Forte iocb->ulpCommand, iocb->ulpStatus, iocb->ulpIoTag, 4395*fcf3ce44SJohn Forte iocb->ulpContext); 4396*fcf3ce44SJohn Forte 4397*fcf3ce44SJohn Forte break; 4398*fcf3ce44SJohn Forte } /* switch(entry->ulpCommand) */ 4399*fcf3ce44SJohn Forte 4400*fcf3ce44SJohn Forte return; 4401*fcf3ce44SJohn Forte 4402*fcf3ce44SJohn Forte } /* emlxs_proc_ring_event() */ 4403*fcf3ce44SJohn Forte 4404*fcf3ce44SJohn Forte 4405*fcf3ce44SJohn Forte 4406*fcf3ce44SJohn Forte static int 4407*fcf3ce44SJohn Forte emlxs_handle_rcv_seq(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 4408*fcf3ce44SJohn Forte { 4409*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 4410*fcf3ce44SJohn Forte IOCB *iocb; 4411*fcf3ce44SJohn Forte MATCHMAP *mp = NULL; 4412*fcf3ce44SJohn Forte uint64_t bdeAddr; 4413*fcf3ce44SJohn Forte uint32_t vpi = 0; 4414*fcf3ce44SJohn Forte uint32_t ringno; 4415*fcf3ce44SJohn Forte uint32_t size = 0; 4416*fcf3ce44SJohn Forte uint32_t *RcvError; 4417*fcf3ce44SJohn Forte uint32_t *RcvDropped; 4418*fcf3ce44SJohn Forte uint32_t *UbPosted; 4419*fcf3ce44SJohn Forte emlxs_msg_t *dropped_msg; 4420*fcf3ce44SJohn Forte char error_str[64]; 4421*fcf3ce44SJohn Forte uint32_t buf_type; 4422*fcf3ce44SJohn Forte uint32_t *word; 4423*fcf3ce44SJohn Forte 4424*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 4425*fcf3ce44SJohn Forte uint32_t hbq_id; 4426*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 4427*fcf3ce44SJohn Forte 4428*fcf3ce44SJohn Forte ringno = rp->ringno; 4429*fcf3ce44SJohn Forte iocb = &iocbq->iocb; 4430*fcf3ce44SJohn Forte word = (uint32_t *)iocb; 4431*fcf3ce44SJohn Forte 4432*fcf3ce44SJohn Forte switch (ringno) { 4433*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 4434*fcf3ce44SJohn Forte case FC_FCT_RING: 4435*fcf3ce44SJohn Forte HBASTATS.FctRingEvent++; 4436*fcf3ce44SJohn Forte RcvError = &HBASTATS.FctRingError; 4437*fcf3ce44SJohn Forte RcvDropped = &HBASTATS.FctRingDropped; 4438*fcf3ce44SJohn Forte UbPosted = &HBASTATS.FctUbPosted; 4439*fcf3ce44SJohn Forte dropped_msg = &emlxs_fct_detail_msg; 4440*fcf3ce44SJohn Forte buf_type = MEM_FCTBUF; 4441*fcf3ce44SJohn Forte break; 4442*fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 4443*fcf3ce44SJohn Forte 4444*fcf3ce44SJohn Forte case FC_IP_RING: 4445*fcf3ce44SJohn Forte HBASTATS.IpRcvEvent++; 4446*fcf3ce44SJohn Forte RcvError = &HBASTATS.IpDropped; 4447*fcf3ce44SJohn Forte RcvDropped = &HBASTATS.IpDropped; 4448*fcf3ce44SJohn Forte UbPosted = &HBASTATS.IpUbPosted; 4449*fcf3ce44SJohn Forte dropped_msg = &emlxs_unsol_ip_dropped_msg; 4450*fcf3ce44SJohn Forte buf_type = MEM_IPBUF; 4451*fcf3ce44SJohn Forte break; 4452*fcf3ce44SJohn Forte 4453*fcf3ce44SJohn Forte case FC_ELS_RING: 4454*fcf3ce44SJohn Forte HBASTATS.ElsRcvEvent++; 4455*fcf3ce44SJohn Forte RcvError = &HBASTATS.ElsRcvError; 4456*fcf3ce44SJohn Forte RcvDropped = &HBASTATS.ElsRcvDropped; 4457*fcf3ce44SJohn Forte UbPosted = &HBASTATS.ElsUbPosted; 4458*fcf3ce44SJohn Forte dropped_msg = &emlxs_unsol_els_dropped_msg; 4459*fcf3ce44SJohn Forte buf_type = MEM_ELSBUF; 4460*fcf3ce44SJohn Forte break; 4461*fcf3ce44SJohn Forte 4462*fcf3ce44SJohn Forte case FC_CT_RING: 4463*fcf3ce44SJohn Forte HBASTATS.CtRcvEvent++; 4464*fcf3ce44SJohn Forte RcvError = &HBASTATS.CtRcvError; 4465*fcf3ce44SJohn Forte RcvDropped = &HBASTATS.CtRcvDropped; 4466*fcf3ce44SJohn Forte UbPosted = &HBASTATS.CtUbPosted; 4467*fcf3ce44SJohn Forte dropped_msg = &emlxs_unsol_ct_dropped_msg; 4468*fcf3ce44SJohn Forte buf_type = MEM_CTBUF; 4469*fcf3ce44SJohn Forte break; 4470*fcf3ce44SJohn Forte 4471*fcf3ce44SJohn Forte default: 4472*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 4473*fcf3ce44SJohn Forte "ring=%d cmd=%x %s %x %x %x %x", 4474*fcf3ce44SJohn Forte ringno, iocb->ulpCommand, 4475*fcf3ce44SJohn Forte emlxs_state_xlate(iocb->ulpStatus), 4476*fcf3ce44SJohn Forte word[4], word[5], word[6], word[7]); 4477*fcf3ce44SJohn Forte return (1); 4478*fcf3ce44SJohn Forte } 4479*fcf3ce44SJohn Forte 4480*fcf3ce44SJohn Forte if (iocb->ulpStatus) { 4481*fcf3ce44SJohn Forte if ((iocb->ulpStatus == IOSTAT_LOCAL_REJECT) && 4482*fcf3ce44SJohn Forte (iocb->un.grsp.perr.statLocalError == 4483*fcf3ce44SJohn Forte IOERR_RCV_BUFFER_TIMEOUT)) { 4484*fcf3ce44SJohn Forte (void) strcpy(error_str, "Out of posted buffers:"); 4485*fcf3ce44SJohn Forte } else if ((iocb->ulpStatus == IOSTAT_LOCAL_REJECT) && 4486*fcf3ce44SJohn Forte (iocb->un.grsp.perr.statLocalError == 4487*fcf3ce44SJohn Forte IOERR_RCV_BUFFER_WAITING)) { 4488*fcf3ce44SJohn Forte (void) strcpy(error_str, "Buffer waiting:"); 4489*fcf3ce44SJohn Forte goto done; 4490*fcf3ce44SJohn Forte } else if (iocb->ulpStatus == IOSTAT_ILLEGAL_FRAME_RCVD) { 4491*fcf3ce44SJohn Forte (void) strcpy(error_str, "Illegal frame:"); 4492*fcf3ce44SJohn Forte } else { 4493*fcf3ce44SJohn Forte (void) strcpy(error_str, "General error:"); 4494*fcf3ce44SJohn Forte } 4495*fcf3ce44SJohn Forte 4496*fcf3ce44SJohn Forte goto failed; 4497*fcf3ce44SJohn Forte } 4498*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 4499*fcf3ce44SJohn Forte if (hba->flag & FC_HBQ_ENABLED) { 4500*fcf3ce44SJohn Forte HBQ_INIT_t *hbq; 4501*fcf3ce44SJohn Forte HBQE_t *hbqE; 4502*fcf3ce44SJohn Forte uint32_t hbqe_tag; 4503*fcf3ce44SJohn Forte 4504*fcf3ce44SJohn Forte *UbPosted -= 1; 4505*fcf3ce44SJohn Forte 4506*fcf3ce44SJohn Forte hbqE = (HBQE_t *)iocb; 4507*fcf3ce44SJohn Forte hbq_id = hbqE->unt.ext.HBQ_tag; 4508*fcf3ce44SJohn Forte hbqe_tag = hbqE->unt.ext.HBQE_tag; 4509*fcf3ce44SJohn Forte 4510*fcf3ce44SJohn Forte hbq = &hba->hbq_table[hbq_id]; 4511*fcf3ce44SJohn Forte 4512*fcf3ce44SJohn Forte if (hbqe_tag >= hbq->HBQ_numEntries) { 4513*fcf3ce44SJohn Forte (void) sprintf(error_str, "Invalid HBQE tag=%x:", 4514*fcf3ce44SJohn Forte hbqe_tag); 4515*fcf3ce44SJohn Forte goto dropped; 4516*fcf3ce44SJohn Forte } 4517*fcf3ce44SJohn Forte mp = hba->hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag]; 4518*fcf3ce44SJohn Forte 4519*fcf3ce44SJohn Forte size = iocb->unsli3.ext_rcv.seq_len; 4520*fcf3ce44SJohn Forte } else 4521*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 4522*fcf3ce44SJohn Forte { 4523*fcf3ce44SJohn Forte bdeAddr = getPaddr(iocb->un.cont64[0].addrHigh, 4524*fcf3ce44SJohn Forte iocb->un.cont64[0].addrLow); 4525*fcf3ce44SJohn Forte 4526*fcf3ce44SJohn Forte /* Check for invalid buffer */ 4527*fcf3ce44SJohn Forte if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) { 4528*fcf3ce44SJohn Forte (void) strcpy(error_str, "Invalid buffer:"); 4529*fcf3ce44SJohn Forte goto dropped; 4530*fcf3ce44SJohn Forte } 4531*fcf3ce44SJohn Forte mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr); 4532*fcf3ce44SJohn Forte 4533*fcf3ce44SJohn Forte size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize; 4534*fcf3ce44SJohn Forte } 4535*fcf3ce44SJohn Forte 4536*fcf3ce44SJohn Forte if (!mp) { 4537*fcf3ce44SJohn Forte (void) strcpy(error_str, "Buffer not mapped:"); 4538*fcf3ce44SJohn Forte goto dropped; 4539*fcf3ce44SJohn Forte } 4540*fcf3ce44SJohn Forte if (!size) { 4541*fcf3ce44SJohn Forte (void) strcpy(error_str, "Buffer empty:"); 4542*fcf3ce44SJohn Forte goto dropped; 4543*fcf3ce44SJohn Forte } 4544*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 4545*fcf3ce44SJohn Forte /* To avoid we drop the broadcast packets */ 4546*fcf3ce44SJohn Forte if (ringno != FC_IP_RING) { 4547*fcf3ce44SJohn Forte /* Get virtual port */ 4548*fcf3ce44SJohn Forte if (hba->flag & FC_NPIV_ENABLED) { 4549*fcf3ce44SJohn Forte vpi = iocb->unsli3.ext_rcv.vpi; 4550*fcf3ce44SJohn Forte if (vpi >= hba->vpi_max) { 4551*fcf3ce44SJohn Forte (void) sprintf(error_str, "Invalid VPI=%d:", 4552*fcf3ce44SJohn Forte vpi); 4553*fcf3ce44SJohn Forte goto dropped; 4554*fcf3ce44SJohn Forte } 4555*fcf3ce44SJohn Forte port = &VPORT(vpi); 4556*fcf3ce44SJohn Forte } 4557*fcf3ce44SJohn Forte } 4558*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 4559*fcf3ce44SJohn Forte 4560*fcf3ce44SJohn Forte /* Process request */ 4561*fcf3ce44SJohn Forte switch (ringno) { 4562*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 4563*fcf3ce44SJohn Forte case FC_FCT_RING: 4564*fcf3ce44SJohn Forte (void) emlxs_fct_handle_unsol_req(port, rp, iocbq, mp, size); 4565*fcf3ce44SJohn Forte break; 4566*fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 4567*fcf3ce44SJohn Forte 4568*fcf3ce44SJohn Forte case FC_IP_RING: 4569*fcf3ce44SJohn Forte (void) emlxs_ip_handle_unsol_req(port, rp, iocbq, mp, size); 4570*fcf3ce44SJohn Forte break; 4571*fcf3ce44SJohn Forte 4572*fcf3ce44SJohn Forte case FC_ELS_RING: 4573*fcf3ce44SJohn Forte /* If this is a target port, then let fct handle this */ 4574*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 4575*fcf3ce44SJohn Forte if (port->tgt_mode) { 4576*fcf3ce44SJohn Forte (void) emlxs_fct_handle_unsol_els(port, rp, iocbq, 4577*fcf3ce44SJohn Forte mp, size); 4578*fcf3ce44SJohn Forte } else { 4579*fcf3ce44SJohn Forte (void) emlxs_els_handle_unsol_req(port, rp, iocbq, 4580*fcf3ce44SJohn Forte mp, size); 4581*fcf3ce44SJohn Forte } 4582*fcf3ce44SJohn Forte #else 4583*fcf3ce44SJohn Forte (void) emlxs_els_handle_unsol_req(port, rp, iocbq, 4584*fcf3ce44SJohn Forte mp, size); 4585*fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 4586*fcf3ce44SJohn Forte break; 4587*fcf3ce44SJohn Forte 4588*fcf3ce44SJohn Forte case FC_CT_RING: 4589*fcf3ce44SJohn Forte (void) emlxs_ct_handle_unsol_req(port, rp, iocbq, mp, size); 4590*fcf3ce44SJohn Forte break; 4591*fcf3ce44SJohn Forte } 4592*fcf3ce44SJohn Forte 4593*fcf3ce44SJohn Forte goto done; 4594*fcf3ce44SJohn Forte 4595*fcf3ce44SJohn Forte dropped: 4596*fcf3ce44SJohn Forte *RcvDropped += 1; 4597*fcf3ce44SJohn Forte 4598*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 4599*fcf3ce44SJohn Forte "%s: cmd=%x %s %x %x %x %x", 4600*fcf3ce44SJohn Forte error_str, iocb->ulpCommand, emlxs_state_xlate(iocb->ulpStatus), 4601*fcf3ce44SJohn Forte word[4], word[5], word[6], word[7]); 4602*fcf3ce44SJohn Forte 4603*fcf3ce44SJohn Forte if (ringno == FC_FCT_RING) { 4604*fcf3ce44SJohn Forte uint32_t sid; 4605*fcf3ce44SJohn Forte 4606*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 4607*fcf3ce44SJohn Forte if (hba->sli_mode >= 3) { 4608*fcf3ce44SJohn Forte emlxs_node_t *ndlp; 4609*fcf3ce44SJohn Forte ndlp = emlxs_node_find_rpi(port, iocb->ulpIoTag); 4610*fcf3ce44SJohn Forte sid = ndlp->nlp_DID; 4611*fcf3ce44SJohn Forte } else 4612*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 4613*fcf3ce44SJohn Forte { 4614*fcf3ce44SJohn Forte sid = iocb->un.ulpWord[4] & 0xFFFFFF; 4615*fcf3ce44SJohn Forte } 4616*fcf3ce44SJohn Forte 4617*fcf3ce44SJohn Forte emlxs_send_logo(port, sid); 4618*fcf3ce44SJohn Forte } 4619*fcf3ce44SJohn Forte goto done; 4620*fcf3ce44SJohn Forte 4621*fcf3ce44SJohn Forte failed: 4622*fcf3ce44SJohn Forte *RcvError += 1; 4623*fcf3ce44SJohn Forte 4624*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 4625*fcf3ce44SJohn Forte "%s: cmd=%x %s %x %x %x %x hba:%x %x", 4626*fcf3ce44SJohn Forte error_str, iocb->ulpCommand, emlxs_state_xlate(iocb->ulpStatus), 4627*fcf3ce44SJohn Forte word[4], word[5], word[6], word[7], hba->state, hba->flag); 4628*fcf3ce44SJohn Forte 4629*fcf3ce44SJohn Forte done: 4630*fcf3ce44SJohn Forte 4631*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT 4632*fcf3ce44SJohn Forte if (hba->flag & FC_HBQ_ENABLED) { 4633*fcf3ce44SJohn Forte emlxs_update_HBQ_index(hba, hbq_id); 4634*fcf3ce44SJohn Forte } else 4635*fcf3ce44SJohn Forte #endif /* SLI3_SUPPORT */ 4636*fcf3ce44SJohn Forte { 4637*fcf3ce44SJohn Forte if (mp) { 4638*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, buf_type, (uint8_t *)mp); 4639*fcf3ce44SJohn Forte } 4640*fcf3ce44SJohn Forte (void) emlxs_post_buffer(hba, rp, 1); 4641*fcf3ce44SJohn Forte } 4642*fcf3ce44SJohn Forte 4643*fcf3ce44SJohn Forte return (0); 4644*fcf3ce44SJohn Forte 4645*fcf3ce44SJohn Forte } /* emlxs_handle_rcv_seq() */ 4646*fcf3ce44SJohn Forte 4647*fcf3ce44SJohn Forte 4648*fcf3ce44SJohn Forte 4649*fcf3ce44SJohn Forte extern void 4650*fcf3ce44SJohn Forte emlxs_issue_iocb_cmd(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 4651*fcf3ce44SJohn Forte { 4652*fcf3ce44SJohn Forte PGP *pgp; 4653*fcf3ce44SJohn Forte emlxs_buf_t *sbp; 4654*fcf3ce44SJohn Forte SLIM2 *slim2p = (SLIM2 *)hba->slim2.virt; 4655*fcf3ce44SJohn Forte uint32_t nextIdx; 4656*fcf3ce44SJohn Forte uint32_t status; 4657*fcf3ce44SJohn Forte void *ioa2; 4658*fcf3ce44SJohn Forte off_t offset; 4659*fcf3ce44SJohn Forte uint32_t count; 4660*fcf3ce44SJohn Forte uint32_t ringno; 4661*fcf3ce44SJohn Forte int32_t throttle; 4662*fcf3ce44SJohn Forte 4663*fcf3ce44SJohn Forte ringno = rp->ringno; 4664*fcf3ce44SJohn Forte throttle = 0; 4665*fcf3ce44SJohn Forte 4666*fcf3ce44SJohn Forte begin: 4667*fcf3ce44SJohn Forte 4668*fcf3ce44SJohn Forte /* Check if FCP ring and adapter is not ready */ 4669*fcf3ce44SJohn Forte if ((ringno == FC_FCP_RING) && (hba->state != FC_READY)) { 4670*fcf3ce44SJohn Forte if (!iocbq) { 4671*fcf3ce44SJohn Forte return; 4672*fcf3ce44SJohn Forte } 4673*fcf3ce44SJohn Forte if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port || 4674*fcf3ce44SJohn Forte !(((emlxs_port_t *)iocbq->port)->tgt_mode)) { 4675*fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 4676*fcf3ce44SJohn Forte return; 4677*fcf3ce44SJohn Forte } 4678*fcf3ce44SJohn Forte } 4679*fcf3ce44SJohn Forte /* Attempt to acquire CMD_RING lock */ 4680*fcf3ce44SJohn Forte if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(ringno)) == 0) { 4681*fcf3ce44SJohn Forte /* Queue it for later */ 4682*fcf3ce44SJohn Forte if (iocbq) { 4683*fcf3ce44SJohn Forte if ((hba->io_count[ringno] - 4684*fcf3ce44SJohn Forte hba->ring_tx_count[ringno]) > 10) { 4685*fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 4686*fcf3ce44SJohn Forte return; 4687*fcf3ce44SJohn Forte } else { 4688*fcf3ce44SJohn Forte 4689*fcf3ce44SJohn Forte /* 4690*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, 4691*fcf3ce44SJohn Forte * &emlxs_ring_watchdog_msg, "%s host=%d 4692*fcf3ce44SJohn Forte * port=%d cnt=%d,%d RACE CONDITION3 4693*fcf3ce44SJohn Forte * DETECTED.", emlxs_ring_xlate(ringno), 4694*fcf3ce44SJohn Forte * rp->fc_cmdidx, rp->fc_port_cmdidx, 4695*fcf3ce44SJohn Forte * hba->ring_tx_count[ringno], 4696*fcf3ce44SJohn Forte * hba->io_count[ringno]); 4697*fcf3ce44SJohn Forte */ 4698*fcf3ce44SJohn Forte mutex_enter(&EMLXS_CMD_RING_LOCK(ringno)); 4699*fcf3ce44SJohn Forte } 4700*fcf3ce44SJohn Forte } else { 4701*fcf3ce44SJohn Forte return; 4702*fcf3ce44SJohn Forte } 4703*fcf3ce44SJohn Forte } 4704*fcf3ce44SJohn Forte /* CMD_RING_LOCK acquired */ 4705*fcf3ce44SJohn Forte 4706*fcf3ce44SJohn Forte /* Check if HBA is full */ 4707*fcf3ce44SJohn Forte throttle = hba->io_throttle - hba->io_active; 4708*fcf3ce44SJohn Forte if (throttle <= 0) { 4709*fcf3ce44SJohn Forte /* Hitting adapter throttle limit */ 4710*fcf3ce44SJohn Forte /* Queue it for later */ 4711*fcf3ce44SJohn Forte if (iocbq) { 4712*fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 4713*fcf3ce44SJohn Forte } 4714*fcf3ce44SJohn Forte goto busy; 4715*fcf3ce44SJohn Forte } 4716*fcf3ce44SJohn Forte /* Read adapter's get index */ 4717*fcf3ce44SJohn Forte pgp = (PGP *) & ((SLIM2 *) hba->slim2.virt)->mbx.us.s2.port[ringno]; 4718*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)&(pgp->cmdGetInx) - 4719*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 4720*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4721*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 4722*fcf3ce44SJohn Forte rp->fc_port_cmdidx = PCIMEM_LONG(pgp->cmdGetInx); 4723*fcf3ce44SJohn Forte 4724*fcf3ce44SJohn Forte /* Calculate the next put index */ 4725*fcf3ce44SJohn Forte nextIdx = (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 4726*fcf3ce44SJohn Forte 0 : rp->fc_cmdidx + 1; 4727*fcf3ce44SJohn Forte 4728*fcf3ce44SJohn Forte /* Check if ring is full */ 4729*fcf3ce44SJohn Forte if (nextIdx == rp->fc_port_cmdidx) { 4730*fcf3ce44SJohn Forte /* Try one more time */ 4731*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4732*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 4733*fcf3ce44SJohn Forte rp->fc_port_cmdidx = PCIMEM_LONG(pgp->cmdGetInx); 4734*fcf3ce44SJohn Forte 4735*fcf3ce44SJohn Forte if (nextIdx == rp->fc_port_cmdidx) { 4736*fcf3ce44SJohn Forte /* Queue it for later */ 4737*fcf3ce44SJohn Forte if (iocbq) { 4738*fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 4739*fcf3ce44SJohn Forte } 4740*fcf3ce44SJohn Forte goto busy; 4741*fcf3ce44SJohn Forte } 4742*fcf3ce44SJohn Forte } 4743*fcf3ce44SJohn Forte /* We have a command ring slot available */ 4744*fcf3ce44SJohn Forte /* Make sure we have an iocb to send */ 4745*fcf3ce44SJohn Forte 4746*fcf3ce44SJohn Forte if (iocbq) { 4747*fcf3ce44SJohn Forte mutex_enter(&EMLXS_RINGTX_LOCK); 4748*fcf3ce44SJohn Forte 4749*fcf3ce44SJohn Forte /* Check if the ring already has iocb's waiting */ 4750*fcf3ce44SJohn Forte if (rp->nodeq.q_first != NULL) { 4751*fcf3ce44SJohn Forte /* Put the current iocbq on the tx queue */ 4752*fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 0); 4753*fcf3ce44SJohn Forte 4754*fcf3ce44SJohn Forte /* 4755*fcf3ce44SJohn Forte * Attempt to replace it with the next iocbq in the 4756*fcf3ce44SJohn Forte * tx queue 4757*fcf3ce44SJohn Forte */ 4758*fcf3ce44SJohn Forte iocbq = emlxs_tx_get(rp, 0); 4759*fcf3ce44SJohn Forte } 4760*fcf3ce44SJohn Forte mutex_exit(&EMLXS_RINGTX_LOCK); 4761*fcf3ce44SJohn Forte } else { 4762*fcf3ce44SJohn Forte /* Try to get the next iocb on the tx queue */ 4763*fcf3ce44SJohn Forte iocbq = emlxs_tx_get(rp, 1); 4764*fcf3ce44SJohn Forte } 4765*fcf3ce44SJohn Forte 4766*fcf3ce44SJohn Forte sendit: 4767*fcf3ce44SJohn Forte count = 0; 4768*fcf3ce44SJohn Forte 4769*fcf3ce44SJohn Forte /* Process each iocbq */ 4770*fcf3ce44SJohn Forte while (iocbq) { 4771*fcf3ce44SJohn Forte 4772*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT 4773*fcf3ce44SJohn Forte sbp = iocbq->sbp; 4774*fcf3ce44SJohn Forte if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) { 4775*fcf3ce44SJohn Forte /* 4776*fcf3ce44SJohn Forte * Update adapter if needed, since we are about to 4777*fcf3ce44SJohn Forte * delay here 4778*fcf3ce44SJohn Forte */ 4779*fcf3ce44SJohn Forte if (count) { 4780*fcf3ce44SJohn Forte count = 0; 4781*fcf3ce44SJohn Forte 4782*fcf3ce44SJohn Forte /* Update the adapter's cmd put index */ 4783*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 4784*fcf3ce44SJohn Forte slim2p->mbx.us.s2.host[ringno]. 4785*fcf3ce44SJohn Forte cmdPutInx = 4786*fcf3ce44SJohn Forte PCIMEM_LONG(rp->fc_cmdidx); 4787*fcf3ce44SJohn Forte 4788*fcf3ce44SJohn Forte /* DMA sync the index for the adapter */ 4789*fcf3ce44SJohn Forte offset = 4790*fcf3ce44SJohn Forte (off_t) 4791*fcf3ce44SJohn Forte ((uint64_t)(unsigned long)&(slim2p-> 4792*fcf3ce44SJohn Forte mbx.us.s2.host[ringno].cmdPutInx) - 4793*fcf3ce44SJohn Forte (uint64_t)(unsigned long)slim2p); 4794*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, 4795*fcf3ce44SJohn Forte offset, 4, DDI_DMA_SYNC_FORDEV); 4796*fcf3ce44SJohn Forte } else { 4797*fcf3ce44SJohn Forte ioa2 = (void *)((char *)hba->slim_addr + 4798*fcf3ce44SJohn Forte hba->hgp_ring_offset + 4799*fcf3ce44SJohn Forte ((ringno * 2) * sizeof (uint32_t))); 4800*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, 4801*fcf3ce44SJohn Forte (volatile uint32_t *)ioa2, 4802*fcf3ce44SJohn Forte rp->fc_cmdidx); 4803*fcf3ce44SJohn Forte } 4804*fcf3ce44SJohn Forte 4805*fcf3ce44SJohn Forte status = (CA_R0ATT << (ringno * 4)); 4806*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, 4807*fcf3ce44SJohn Forte FC_CA_REG(hba, hba->csr_addr), 4808*fcf3ce44SJohn Forte (volatile uint32_t)status); 4809*fcf3ce44SJohn Forte 4810*fcf3ce44SJohn Forte } 4811*fcf3ce44SJohn Forte /* Perform delay */ 4812*fcf3ce44SJohn Forte if (ringno == FC_ELS_RING) { 4813*fcf3ce44SJohn Forte (void) drv_usecwait(100000); 4814*fcf3ce44SJohn Forte } else { 4815*fcf3ce44SJohn Forte (void) drv_usecwait(20000); 4816*fcf3ce44SJohn Forte } 4817*fcf3ce44SJohn Forte } 4818*fcf3ce44SJohn Forte #endif /* NPIV_SUPPORT */ 4819*fcf3ce44SJohn Forte 4820*fcf3ce44SJohn Forte /* At this point, we have a command ring slot available */ 4821*fcf3ce44SJohn Forte /* and an iocb to send */ 4822*fcf3ce44SJohn Forte 4823*fcf3ce44SJohn Forte /* Send the iocb */ 4824*fcf3ce44SJohn Forte emlxs_issue_iocb(hba, rp, iocbq); 4825*fcf3ce44SJohn Forte 4826*fcf3ce44SJohn Forte count++; 4827*fcf3ce44SJohn Forte 4828*fcf3ce44SJohn Forte /* Check if HBA is full */ 4829*fcf3ce44SJohn Forte throttle = hba->io_throttle - hba->io_active; 4830*fcf3ce44SJohn Forte if (throttle <= 0) { 4831*fcf3ce44SJohn Forte goto busy; 4832*fcf3ce44SJohn Forte } 4833*fcf3ce44SJohn Forte /* Calculate the next put index */ 4834*fcf3ce44SJohn Forte nextIdx = (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 4835*fcf3ce44SJohn Forte 0 : rp->fc_cmdidx + 1; 4836*fcf3ce44SJohn Forte 4837*fcf3ce44SJohn Forte /* Check if ring is full */ 4838*fcf3ce44SJohn Forte if (nextIdx == rp->fc_port_cmdidx) { 4839*fcf3ce44SJohn Forte /* Try one more time */ 4840*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4841*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 4842*fcf3ce44SJohn Forte rp->fc_port_cmdidx = PCIMEM_LONG(pgp->cmdGetInx); 4843*fcf3ce44SJohn Forte 4844*fcf3ce44SJohn Forte if (nextIdx == rp->fc_port_cmdidx) { 4845*fcf3ce44SJohn Forte goto busy; 4846*fcf3ce44SJohn Forte } 4847*fcf3ce44SJohn Forte } 4848*fcf3ce44SJohn Forte /* Get the next iocb from the tx queue if there is one */ 4849*fcf3ce44SJohn Forte iocbq = emlxs_tx_get(rp, 1); 4850*fcf3ce44SJohn Forte } 4851*fcf3ce44SJohn Forte 4852*fcf3ce44SJohn Forte if (count) { 4853*fcf3ce44SJohn Forte /* Update the adapter's cmd put index */ 4854*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 4855*fcf3ce44SJohn Forte slim2p->mbx.us.s2.host[ringno]. 4856*fcf3ce44SJohn Forte cmdPutInx = PCIMEM_LONG(rp->fc_cmdidx); 4857*fcf3ce44SJohn Forte 4858*fcf3ce44SJohn Forte /* DMA sync the index for the adapter */ 4859*fcf3ce44SJohn Forte offset = (off_t) 4860*fcf3ce44SJohn Forte ((uint64_t)(unsigned long)&(slim2p->mbx.us.s2. 4861*fcf3ce44SJohn Forte host[ringno].cmdPutInx) - 4862*fcf3ce44SJohn Forte (uint64_t)(unsigned long)slim2p); 4863*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4864*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 4865*fcf3ce44SJohn Forte } else { 4866*fcf3ce44SJohn Forte ioa2 = (void *) ((char *)hba->slim_addr + 4867*fcf3ce44SJohn Forte hba->hgp_ring_offset + ((ringno * 2) * 4868*fcf3ce44SJohn Forte sizeof (uint32_t))); 4869*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, 4870*fcf3ce44SJohn Forte (volatile uint32_t *)ioa2, rp->fc_cmdidx); 4871*fcf3ce44SJohn Forte } 4872*fcf3ce44SJohn Forte 4873*fcf3ce44SJohn Forte status = (CA_R0ATT << (ringno * 4)); 4874*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), 4875*fcf3ce44SJohn Forte (volatile uint32_t)status); 4876*fcf3ce44SJohn Forte 4877*fcf3ce44SJohn Forte /* Check tx queue one more time before releasing */ 4878*fcf3ce44SJohn Forte if ((iocbq = emlxs_tx_get(rp, 1))) { 4879*fcf3ce44SJohn Forte /* 4880*fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, 4881*fcf3ce44SJohn Forte * &emlxs_ring_watchdog_msg, "%s host=%d port=%d 4882*fcf3ce44SJohn Forte * RACE CONDITION1 DETECTED.", 4883*fcf3ce44SJohn Forte * emlxs_ring_xlate(ringno), rp->fc_cmdidx, 4884*fcf3ce44SJohn Forte * rp->fc_port_cmdidx); 4885*fcf3ce44SJohn Forte */ 4886*fcf3ce44SJohn Forte goto sendit; 4887*fcf3ce44SJohn Forte } 4888*fcf3ce44SJohn Forte } 4889*fcf3ce44SJohn Forte mutex_exit(&EMLXS_CMD_RING_LOCK(ringno)); 4890*fcf3ce44SJohn Forte 4891*fcf3ce44SJohn Forte return; 4892*fcf3ce44SJohn Forte 4893*fcf3ce44SJohn Forte busy: 4894*fcf3ce44SJohn Forte 4895*fcf3ce44SJohn Forte /* 4896*fcf3ce44SJohn Forte * Set ring to SET R0CE_REQ in Chip Att register. Chip will tell us 4897*fcf3ce44SJohn Forte * when an entry is freed. 4898*fcf3ce44SJohn Forte */ 4899*fcf3ce44SJohn Forte if (count) { 4900*fcf3ce44SJohn Forte /* Update the adapter's cmd put index */ 4901*fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 4902*fcf3ce44SJohn Forte slim2p->mbx.us.s2.host[ringno].cmdPutInx = 4903*fcf3ce44SJohn Forte PCIMEM_LONG(rp->fc_cmdidx); 4904*fcf3ce44SJohn Forte 4905*fcf3ce44SJohn Forte /* DMA sync the index for the adapter */ 4906*fcf3ce44SJohn Forte offset = (off_t) 4907*fcf3ce44SJohn Forte ((uint64_t)(unsigned long)&(slim2p->mbx.us.s2. 4908*fcf3ce44SJohn Forte host[ringno].cmdPutInx) - 4909*fcf3ce44SJohn Forte (uint64_t)(unsigned long)slim2p); 4910*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 4911*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 4912*fcf3ce44SJohn Forte } else { 4913*fcf3ce44SJohn Forte ioa2 = (void *) ((char *)hba->slim_addr + 4914*fcf3ce44SJohn Forte hba->hgp_ring_offset + ((ringno * 2) * 4915*fcf3ce44SJohn Forte sizeof (uint32_t))); 4916*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, (volatile uint32_t *) ioa2, 4917*fcf3ce44SJohn Forte rp->fc_cmdidx); 4918*fcf3ce44SJohn Forte } 4919*fcf3ce44SJohn Forte } 4920*fcf3ce44SJohn Forte status = ((CA_R0ATT | CA_R0CE_REQ) << (ringno * 4)); 4921*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), 4922*fcf3ce44SJohn Forte (volatile uint32_t) status); 4923*fcf3ce44SJohn Forte 4924*fcf3ce44SJohn Forte if (throttle <= 0) { 4925*fcf3ce44SJohn Forte HBASTATS.IocbThrottled++; 4926*fcf3ce44SJohn Forte } else { 4927*fcf3ce44SJohn Forte HBASTATS.IocbRingFull[ringno]++; 4928*fcf3ce44SJohn Forte } 4929*fcf3ce44SJohn Forte 4930*fcf3ce44SJohn Forte mutex_exit(&EMLXS_CMD_RING_LOCK(ringno)); 4931*fcf3ce44SJohn Forte 4932*fcf3ce44SJohn Forte return; 4933*fcf3ce44SJohn Forte 4934*fcf3ce44SJohn Forte } /* emlxs_issue_iocb_cmd() */ 4935*fcf3ce44SJohn Forte 4936*fcf3ce44SJohn Forte 4937*fcf3ce44SJohn Forte 4938*fcf3ce44SJohn Forte /* EMLXS_CMD_RING_LOCK must be held when calling this function */ 4939*fcf3ce44SJohn Forte static void 4940*fcf3ce44SJohn Forte emlxs_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 4941*fcf3ce44SJohn Forte { 4942*fcf3ce44SJohn Forte emlxs_port_t *port; 4943*fcf3ce44SJohn Forte IOCB *icmd; 4944*fcf3ce44SJohn Forte IOCB *iocb; 4945*fcf3ce44SJohn Forte emlxs_buf_t *sbp; 4946*fcf3ce44SJohn Forte off_t offset; 4947*fcf3ce44SJohn Forte uint32_t ringno; 4948*fcf3ce44SJohn Forte 4949*fcf3ce44SJohn Forte ringno = rp->ringno; 4950*fcf3ce44SJohn Forte sbp = iocbq->sbp; 4951*fcf3ce44SJohn Forte icmd = &iocbq->iocb; 4952*fcf3ce44SJohn Forte port = iocbq->port; 4953*fcf3ce44SJohn Forte 4954*fcf3ce44SJohn Forte HBASTATS.IocbIssued[ringno]++; 4955*fcf3ce44SJohn Forte 4956*fcf3ce44SJohn Forte /* Check for ULP pkt request */ 4957*fcf3ce44SJohn Forte if (sbp) { 4958*fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 4959*fcf3ce44SJohn Forte 4960*fcf3ce44SJohn Forte if (sbp->node == NULL) { 4961*fcf3ce44SJohn Forte /* Set node to base node by default */ 4962*fcf3ce44SJohn Forte iocbq->node = (void *) &port->node_base; 4963*fcf3ce44SJohn Forte sbp->node = (void *) &port->node_base; 4964*fcf3ce44SJohn Forte } 4965*fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_CHIPQ; 4966*fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 4967*fcf3ce44SJohn Forte 4968*fcf3ce44SJohn Forte atomic_add_32(&hba->io_active, 1); 4969*fcf3ce44SJohn Forte } 4970*fcf3ce44SJohn Forte /* get the next available command ring iocb */ 4971*fcf3ce44SJohn Forte iocb = (IOCB *) (((char *)rp->fc_cmdringaddr + 4972*fcf3ce44SJohn Forte (rp->fc_cmdidx * hba->iocb_cmd_size))); 4973*fcf3ce44SJohn Forte 4974*fcf3ce44SJohn Forte /* Copy the local iocb to the command ring iocb */ 4975*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)icmd, (uint32_t *)iocb, 4976*fcf3ce44SJohn Forte hba->iocb_cmd_size); 4977*fcf3ce44SJohn Forte 4978*fcf3ce44SJohn Forte /* DMA sync the command ring iocb for the adapter */ 4979*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)iocb - 4980*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 4981*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4982*fcf3ce44SJohn Forte hba->iocb_cmd_size, DDI_DMA_SYNC_FORDEV); 4983*fcf3ce44SJohn Forte 4984*fcf3ce44SJohn Forte /* Free the local iocb if there is no sbp tracking it */ 4985*fcf3ce44SJohn Forte if (!sbp) { 4986*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); 4987*fcf3ce44SJohn Forte } 4988*fcf3ce44SJohn Forte /* update local ring index to next available ring index */ 4989*fcf3ce44SJohn Forte rp->fc_cmdidx = (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 4990*fcf3ce44SJohn Forte 0 : rp->fc_cmdidx + 1; 4991*fcf3ce44SJohn Forte 4992*fcf3ce44SJohn Forte 4993*fcf3ce44SJohn Forte return; 4994*fcf3ce44SJohn Forte 4995*fcf3ce44SJohn Forte } /* emlxs_issue_iocb() */ 4996*fcf3ce44SJohn Forte 4997*fcf3ce44SJohn Forte 4998*fcf3ce44SJohn Forte extern uint32_t 4999*fcf3ce44SJohn Forte emlxs_interlock(emlxs_hba_t *hba) 5000*fcf3ce44SJohn Forte { 5001*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5002*fcf3ce44SJohn Forte MAILBOX *swpmb; 5003*fcf3ce44SJohn Forte MAILBOX *mb2; 5004*fcf3ce44SJohn Forte MAILBOX *mb1; 5005*fcf3ce44SJohn Forte uint32_t word0; 5006*fcf3ce44SJohn Forte uint32_t j; 5007*fcf3ce44SJohn Forte uint32_t interlock_failed; 5008*fcf3ce44SJohn Forte uint32_t ha_copy; 5009*fcf3ce44SJohn Forte uint32_t value; 5010*fcf3ce44SJohn Forte off_t offset; 5011*fcf3ce44SJohn Forte uint32_t size; 5012*fcf3ce44SJohn Forte 5013*fcf3ce44SJohn Forte interlock_failed = 0; 5014*fcf3ce44SJohn Forte 5015*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 5016*fcf3ce44SJohn Forte if (hba->flag & FC_INTERLOCKED) { 5017*fcf3ce44SJohn Forte emlxs_ffstate_change_locked(hba, FC_KILLED); 5018*fcf3ce44SJohn Forte 5019*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 5020*fcf3ce44SJohn Forte 5021*fcf3ce44SJohn Forte return (FC_SUCCESS); 5022*fcf3ce44SJohn Forte } 5023*fcf3ce44SJohn Forte j = 0; 5024*fcf3ce44SJohn Forte while (j++ < 10000) { 5025*fcf3ce44SJohn Forte if (hba->mbox_queue_flag == 0) { 5026*fcf3ce44SJohn Forte break; 5027*fcf3ce44SJohn Forte } 5028*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 5029*fcf3ce44SJohn Forte DELAYUS(100); 5030*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 5031*fcf3ce44SJohn Forte } 5032*fcf3ce44SJohn Forte 5033*fcf3ce44SJohn Forte if (hba->mbox_queue_flag != 0) { 5034*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5035*fcf3ce44SJohn Forte "Interlock failed. Mailbox busy."); 5036*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 5037*fcf3ce44SJohn Forte return (FC_SUCCESS); 5038*fcf3ce44SJohn Forte } 5039*fcf3ce44SJohn Forte hba->flag |= FC_INTERLOCKED; 5040*fcf3ce44SJohn Forte hba->mbox_queue_flag = 1; 5041*fcf3ce44SJohn Forte 5042*fcf3ce44SJohn Forte /* Disable all host interrupts */ 5043*fcf3ce44SJohn Forte hba->hc_copy = 0; 5044*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 5045*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr), 0xffffffff); 5046*fcf3ce44SJohn Forte 5047*fcf3ce44SJohn Forte mb2 = FC_SLIM2_MAILBOX(hba); 5048*fcf3ce44SJohn Forte mb1 = FC_SLIM1_MAILBOX(hba); 5049*fcf3ce44SJohn Forte swpmb = (MAILBOX *) & word0; 5050*fcf3ce44SJohn Forte 5051*fcf3ce44SJohn Forte if (!(hba->flag & FC_SLIM2_MODE)) { 5052*fcf3ce44SJohn Forte goto mode_B; 5053*fcf3ce44SJohn Forte } 5054*fcf3ce44SJohn Forte mode_A: 5055*fcf3ce44SJohn Forte 5056*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5057*fcf3ce44SJohn Forte "Attempting SLIM2 Interlock..."); 5058*fcf3ce44SJohn Forte 5059*fcf3ce44SJohn Forte interlock_A: 5060*fcf3ce44SJohn Forte 5061*fcf3ce44SJohn Forte value = 0xFFFFFFFF; 5062*fcf3ce44SJohn Forte word0 = 0; 5063*fcf3ce44SJohn Forte swpmb->mbxCommand = MBX_KILL_BOARD; 5064*fcf3ce44SJohn Forte swpmb->mbxOwner = OWN_CHIP; 5065*fcf3ce44SJohn Forte 5066*fcf3ce44SJohn Forte /* Write value to SLIM */ 5067*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, (((volatile uint32_t *) mb1) + 1), value); 5068*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, (((volatile uint32_t *) mb1)), word0); 5069*fcf3ce44SJohn Forte 5070*fcf3ce44SJohn Forte /* Send Kill board request */ 5071*fcf3ce44SJohn Forte mb2->un.varWords[0] = value; 5072*fcf3ce44SJohn Forte mb2->mbxCommand = MBX_KILL_BOARD; 5073*fcf3ce44SJohn Forte mb2->mbxOwner = OWN_CHIP; 5074*fcf3ce44SJohn Forte 5075*fcf3ce44SJohn Forte /* Sync the memory */ 5076*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)mb2 - 5077*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 5078*fcf3ce44SJohn Forte size = (sizeof (uint32_t) * 2); 5079*fcf3ce44SJohn Forte emlxs_pcimem_bcopy((uint32_t *)mb2, (uint32_t *)mb2, size); 5080*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, size, 5081*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 5082*fcf3ce44SJohn Forte 5083*fcf3ce44SJohn Forte /* interrupt board to do it right away */ 5084*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), CA_MBATT); 5085*fcf3ce44SJohn Forte 5086*fcf3ce44SJohn Forte /* First wait for command acceptence */ 5087*fcf3ce44SJohn Forte j = 0; 5088*fcf3ce44SJohn Forte while (j++ < 1000) { 5089*fcf3ce44SJohn Forte value = READ_SLIM_ADDR(hba, (((volatile uint32_t *) mb1) + 1)); 5090*fcf3ce44SJohn Forte 5091*fcf3ce44SJohn Forte if (value == 0) { 5092*fcf3ce44SJohn Forte break; 5093*fcf3ce44SJohn Forte } 5094*fcf3ce44SJohn Forte DELAYUS(50); 5095*fcf3ce44SJohn Forte } 5096*fcf3ce44SJohn Forte 5097*fcf3ce44SJohn Forte if (value == 0) { 5098*fcf3ce44SJohn Forte /* Now wait for mailbox ownership to clear */ 5099*fcf3ce44SJohn Forte while (j++ < 10000) { 5100*fcf3ce44SJohn Forte word0 = READ_SLIM_ADDR(hba, 5101*fcf3ce44SJohn Forte ((volatile uint32_t *)mb1)); 5102*fcf3ce44SJohn Forte 5103*fcf3ce44SJohn Forte if (swpmb->mbxOwner == 0) { 5104*fcf3ce44SJohn Forte break; 5105*fcf3ce44SJohn Forte } 5106*fcf3ce44SJohn Forte DELAYUS(50); 5107*fcf3ce44SJohn Forte } 5108*fcf3ce44SJohn Forte 5109*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5110*fcf3ce44SJohn Forte "Interlock succeeded."); 5111*fcf3ce44SJohn Forte 5112*fcf3ce44SJohn Forte goto done; 5113*fcf3ce44SJohn Forte } 5114*fcf3ce44SJohn Forte /* Interlock failed !!! */ 5115*fcf3ce44SJohn Forte interlock_failed = 1; 5116*fcf3ce44SJohn Forte 5117*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5118*fcf3ce44SJohn Forte "Interlock failed."); 5119*fcf3ce44SJohn Forte 5120*fcf3ce44SJohn Forte mode_B: 5121*fcf3ce44SJohn Forte 5122*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5123*fcf3ce44SJohn Forte "Attempting SLIM1 Interlock..."); 5124*fcf3ce44SJohn Forte 5125*fcf3ce44SJohn Forte interlock_B: 5126*fcf3ce44SJohn Forte 5127*fcf3ce44SJohn Forte value = 0xFFFFFFFF; 5128*fcf3ce44SJohn Forte word0 = 0; 5129*fcf3ce44SJohn Forte swpmb->mbxCommand = MBX_KILL_BOARD; 5130*fcf3ce44SJohn Forte swpmb->mbxOwner = OWN_CHIP; 5131*fcf3ce44SJohn Forte 5132*fcf3ce44SJohn Forte /* Write KILL BOARD to mailbox */ 5133*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, (((volatile uint32_t *) mb1) + 1), value); 5134*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, ((volatile uint32_t *) mb1), word0); 5135*fcf3ce44SJohn Forte 5136*fcf3ce44SJohn Forte /* interrupt board to do it right away */ 5137*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), CA_MBATT); 5138*fcf3ce44SJohn Forte 5139*fcf3ce44SJohn Forte /* First wait for command acceptence */ 5140*fcf3ce44SJohn Forte j = 0; 5141*fcf3ce44SJohn Forte while (j++ < 1000) { 5142*fcf3ce44SJohn Forte value = READ_SLIM_ADDR(hba, (((volatile uint32_t *) mb1) + 1)); 5143*fcf3ce44SJohn Forte 5144*fcf3ce44SJohn Forte if (value == 0) { 5145*fcf3ce44SJohn Forte break; 5146*fcf3ce44SJohn Forte } 5147*fcf3ce44SJohn Forte DELAYUS(50); 5148*fcf3ce44SJohn Forte } 5149*fcf3ce44SJohn Forte 5150*fcf3ce44SJohn Forte if (value == 0) { 5151*fcf3ce44SJohn Forte /* Now wait for mailbox ownership to clear */ 5152*fcf3ce44SJohn Forte while (j++ < 10000) { 5153*fcf3ce44SJohn Forte word0 = READ_SLIM_ADDR(hba, 5154*fcf3ce44SJohn Forte ((volatile uint32_t *)mb1)); 5155*fcf3ce44SJohn Forte 5156*fcf3ce44SJohn Forte if (swpmb->mbxOwner == 0) { 5157*fcf3ce44SJohn Forte break; 5158*fcf3ce44SJohn Forte } 5159*fcf3ce44SJohn Forte DELAYUS(50); 5160*fcf3ce44SJohn Forte } 5161*fcf3ce44SJohn Forte 5162*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5163*fcf3ce44SJohn Forte "Interlock succeeded."); 5164*fcf3ce44SJohn Forte 5165*fcf3ce44SJohn Forte goto done; 5166*fcf3ce44SJohn Forte } 5167*fcf3ce44SJohn Forte /* Interlock failed !!! */ 5168*fcf3ce44SJohn Forte 5169*fcf3ce44SJohn Forte /* If this is the first time then try again */ 5170*fcf3ce44SJohn Forte if (interlock_failed == 0) { 5171*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5172*fcf3ce44SJohn Forte "Interlock failed. Retrying..."); 5173*fcf3ce44SJohn Forte 5174*fcf3ce44SJohn Forte /* Try again */ 5175*fcf3ce44SJohn Forte interlock_failed = 1; 5176*fcf3ce44SJohn Forte goto interlock_B; 5177*fcf3ce44SJohn Forte } 5178*fcf3ce44SJohn Forte /* 5179*fcf3ce44SJohn Forte * Now check for error attention to indicate the board has been 5180*fcf3ce44SJohn Forte * kiilled 5181*fcf3ce44SJohn Forte */ 5182*fcf3ce44SJohn Forte j = 0; 5183*fcf3ce44SJohn Forte while (j++ < 10000) { 5184*fcf3ce44SJohn Forte ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 5185*fcf3ce44SJohn Forte 5186*fcf3ce44SJohn Forte if (ha_copy & HA_ERATT) { 5187*fcf3ce44SJohn Forte break; 5188*fcf3ce44SJohn Forte } 5189*fcf3ce44SJohn Forte DELAYUS(50); 5190*fcf3ce44SJohn Forte } 5191*fcf3ce44SJohn Forte 5192*fcf3ce44SJohn Forte if (ha_copy & HA_ERATT) { 5193*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5194*fcf3ce44SJohn Forte "Interlock failed. Board killed."); 5195*fcf3ce44SJohn Forte } else { 5196*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5197*fcf3ce44SJohn Forte "Interlock failed. Board not killed."); 5198*fcf3ce44SJohn Forte } 5199*fcf3ce44SJohn Forte 5200*fcf3ce44SJohn Forte done: 5201*fcf3ce44SJohn Forte 5202*fcf3ce44SJohn Forte hba->mbox_queue_flag = 0; 5203*fcf3ce44SJohn Forte 5204*fcf3ce44SJohn Forte emlxs_ffstate_change_locked(hba, FC_KILLED); 5205*fcf3ce44SJohn Forte 5206*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 5207*fcf3ce44SJohn Forte 5208*fcf3ce44SJohn Forte return (FC_SUCCESS); 5209*fcf3ce44SJohn Forte 5210*fcf3ce44SJohn Forte } /* emlxs_interlock() */ 5211*fcf3ce44SJohn Forte 5212*fcf3ce44SJohn Forte 5213*fcf3ce44SJohn Forte 5214*fcf3ce44SJohn Forte extern uint32_t 5215*fcf3ce44SJohn Forte emlxs_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post) 5216*fcf3ce44SJohn Forte { 5217*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5218*fcf3ce44SJohn Forte MAILBOX *swpmb; 5219*fcf3ce44SJohn Forte MAILBOX *mb; 5220*fcf3ce44SJohn Forte uint32_t word0; 5221*fcf3ce44SJohn Forte uint16_t cfg_value; 5222*fcf3ce44SJohn Forte uint32_t status; 5223*fcf3ce44SJohn Forte uint32_t status1; 5224*fcf3ce44SJohn Forte uint32_t status2; 5225*fcf3ce44SJohn Forte uint32_t i; 5226*fcf3ce44SJohn Forte uint32_t ready; 5227*fcf3ce44SJohn Forte emlxs_port_t *vport; 5228*fcf3ce44SJohn Forte RING *rp; 5229*fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 5230*fcf3ce44SJohn Forte 5231*fcf3ce44SJohn Forte i = 0; 5232*fcf3ce44SJohn Forte 5233*fcf3ce44SJohn Forte if (!cfg[CFG_RESET_ENABLE].current) { 5234*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 5235*fcf3ce44SJohn Forte "Adapter reset disabled."); 5236*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 5237*fcf3ce44SJohn Forte 5238*fcf3ce44SJohn Forte return (1); 5239*fcf3ce44SJohn Forte } 5240*fcf3ce44SJohn Forte /* Make sure we have called interlock */ 5241*fcf3ce44SJohn Forte (void) emlxs_interlock(hba); 5242*fcf3ce44SJohn Forte 5243*fcf3ce44SJohn Forte if (restart) { 5244*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Restarting."); 5245*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_START); 5246*fcf3ce44SJohn Forte 5247*fcf3ce44SJohn Forte ready = (HS_FFRDY | HS_MBRDY); 5248*fcf3ce44SJohn Forte } else { 5249*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Resetting."); 5250*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_WARM_START); 5251*fcf3ce44SJohn Forte 5252*fcf3ce44SJohn Forte ready = HS_MBRDY; 5253*fcf3ce44SJohn Forte } 5254*fcf3ce44SJohn Forte 5255*fcf3ce44SJohn Forte hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR); 5256*fcf3ce44SJohn Forte 5257*fcf3ce44SJohn Forte mb = FC_SLIM1_MAILBOX(hba); 5258*fcf3ce44SJohn Forte swpmb = (MAILBOX *) & word0; 5259*fcf3ce44SJohn Forte 5260*fcf3ce44SJohn Forte reset: 5261*fcf3ce44SJohn Forte 5262*fcf3ce44SJohn Forte /* Save reset time */ 5263*fcf3ce44SJohn Forte HBASTATS.ResetTime = hba->timer_tics; 5264*fcf3ce44SJohn Forte 5265*fcf3ce44SJohn Forte if (restart) { 5266*fcf3ce44SJohn Forte /* First put restart command in mailbox */ 5267*fcf3ce44SJohn Forte word0 = 0; 5268*fcf3ce44SJohn Forte swpmb->mbxCommand = MBX_RESTART; 5269*fcf3ce44SJohn Forte swpmb->mbxHc = 1; 5270*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, ((volatile uint32_t *) mb), word0); 5271*fcf3ce44SJohn Forte 5272*fcf3ce44SJohn Forte /* Only skip post after emlxs_ffinit is completed */ 5273*fcf3ce44SJohn Forte if (skip_post) { 5274*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, 5275*fcf3ce44SJohn Forte (((volatile uint32_t *)mb) + 1), 1); 5276*fcf3ce44SJohn Forte } else { 5277*fcf3ce44SJohn Forte WRITE_SLIM_ADDR(hba, 5278*fcf3ce44SJohn Forte (((volatile uint32_t *)mb) + 1), 0); 5279*fcf3ce44SJohn Forte } 5280*fcf3ce44SJohn Forte 5281*fcf3ce44SJohn Forte } 5282*fcf3ce44SJohn Forte /* 5283*fcf3ce44SJohn Forte * Turn off SERR, PERR in PCI cmd register 5284*fcf3ce44SJohn Forte */ 5285*fcf3ce44SJohn Forte cfg_value = ddi_get16(hba->pci_acc_handle, 5286*fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER)); 5287*fcf3ce44SJohn Forte 5288*fcf3ce44SJohn Forte (void) ddi_put16(hba->pci_acc_handle, 5289*fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 5290*fcf3ce44SJohn Forte (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL))); 5291*fcf3ce44SJohn Forte 5292*fcf3ce44SJohn Forte hba->hc_copy = HC_INITFF; 5293*fcf3ce44SJohn Forte WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr), hba->hc_copy); 5294*fcf3ce44SJohn Forte 5295*fcf3ce44SJohn Forte /* Wait 1 msec before restoring PCI config */ 5296*fcf3ce44SJohn Forte DELAYMS(1); 5297*fcf3ce44SJohn Forte 5298*fcf3ce44SJohn Forte /* Restore PCI cmd register */ 5299*fcf3ce44SJohn Forte (void) ddi_put16(hba->pci_acc_handle, 5300*fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 5301*fcf3ce44SJohn Forte (uint16_t)cfg_value); 5302*fcf3ce44SJohn Forte 5303*fcf3ce44SJohn Forte /* Wait 3 seconds before checking */ 5304*fcf3ce44SJohn Forte DELAYMS(3000); 5305*fcf3ce44SJohn Forte i += 3; 5306*fcf3ce44SJohn Forte 5307*fcf3ce44SJohn Forte /* Wait for reset completion */ 5308*fcf3ce44SJohn Forte while (i < 30) { 5309*fcf3ce44SJohn Forte /* Check status register to see what current state is */ 5310*fcf3ce44SJohn Forte status = READ_CSR_REG(hba, FC_HS_REG(hba, hba->csr_addr)); 5311*fcf3ce44SJohn Forte 5312*fcf3ce44SJohn Forte /* Check to see if any errors occurred during init */ 5313*fcf3ce44SJohn Forte if (status & HS_FFERM) { 5314*fcf3ce44SJohn Forte status1 = READ_SLIM_ADDR(hba, 5315*fcf3ce44SJohn Forte ((volatile uint8_t *) hba->slim_addr + 0xa8)); 5316*fcf3ce44SJohn Forte status2 = READ_SLIM_ADDR(hba, 5317*fcf3ce44SJohn Forte ((volatile uint8_t *) hba->slim_addr + 0xac)); 5318*fcf3ce44SJohn Forte 5319*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 5320*fcf3ce44SJohn Forte "HS_FFERM: status=0x%x status1=0x%x status2=0x%x", 5321*fcf3ce44SJohn Forte status, status1, status2); 5322*fcf3ce44SJohn Forte 5323*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 5324*fcf3ce44SJohn Forte return (1); 5325*fcf3ce44SJohn Forte } 5326*fcf3ce44SJohn Forte if ((status & ready) == ready) { 5327*fcf3ce44SJohn Forte /* Reset Done !! */ 5328*fcf3ce44SJohn Forte goto done; 5329*fcf3ce44SJohn Forte } 5330*fcf3ce44SJohn Forte /* 5331*fcf3ce44SJohn Forte * Check every 1 second for 15 seconds, then reset board 5332*fcf3ce44SJohn Forte * again (w/post), then check every 1 second for 15 seconds. 5333*fcf3ce44SJohn Forte */ 5334*fcf3ce44SJohn Forte DELAYMS(1000); 5335*fcf3ce44SJohn Forte i++; 5336*fcf3ce44SJohn Forte 5337*fcf3ce44SJohn Forte /* Reset again (w/post) at 15 seconds */ 5338*fcf3ce44SJohn Forte if (i == 15) { 5339*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5340*fcf3ce44SJohn Forte "Reset failed. Retrying..."); 5341*fcf3ce44SJohn Forte 5342*fcf3ce44SJohn Forte goto reset; 5343*fcf3ce44SJohn Forte } 5344*fcf3ce44SJohn Forte } 5345*fcf3ce44SJohn Forte 5346*fcf3ce44SJohn Forte /* Timeout occurred */ 5347*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 5348*fcf3ce44SJohn Forte "Timeout: status=0x%x", status); 5349*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_ERROR); 5350*fcf3ce44SJohn Forte 5351*fcf3ce44SJohn Forte /* Log a dump event */ 5352*fcf3ce44SJohn Forte emlxs_log_dump_event(port, NULL, 0); 5353*fcf3ce44SJohn Forte 5354*fcf3ce44SJohn Forte return (1); 5355*fcf3ce44SJohn Forte 5356*fcf3ce44SJohn Forte done: 5357*fcf3ce44SJohn Forte 5358*fcf3ce44SJohn Forte /* Reset the hba structure */ 5359*fcf3ce44SJohn Forte hba->flag &= FC_RESET_MASK; 5360*fcf3ce44SJohn Forte bzero(hba->ring_tx_count, sizeof (hba->ring_tx_count)); 5361*fcf3ce44SJohn Forte bzero(hba->io_count, sizeof (hba->io_count)); 5362*fcf3ce44SJohn Forte hba->iodone_count = 0; 5363*fcf3ce44SJohn Forte hba->topology = 0; 5364*fcf3ce44SJohn Forte hba->linkspeed = 0; 5365*fcf3ce44SJohn Forte hba->heartbeat_active = 0; 5366*fcf3ce44SJohn Forte hba->discovery_timer = 0; 5367*fcf3ce44SJohn Forte hba->linkup_timer = 0; 5368*fcf3ce44SJohn Forte hba->loopback_tics = 0; 5369*fcf3ce44SJohn Forte 5370*fcf3ce44SJohn Forte /* Initialize hc_copy */ 5371*fcf3ce44SJohn Forte hba->hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr)); 5372*fcf3ce44SJohn Forte 5373*fcf3ce44SJohn Forte /* Reset the ring objects */ 5374*fcf3ce44SJohn Forte for (i = 0; i < MAX_RINGS; i++) { 5375*fcf3ce44SJohn Forte rp = &hba->ring[i]; 5376*fcf3ce44SJohn Forte rp->fc_mpon = 0; 5377*fcf3ce44SJohn Forte rp->fc_mpoff = 0; 5378*fcf3ce44SJohn Forte } 5379*fcf3ce44SJohn Forte 5380*fcf3ce44SJohn Forte /* Reset the port objects */ 5381*fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 5382*fcf3ce44SJohn Forte vport = &VPORT(i); 5383*fcf3ce44SJohn Forte 5384*fcf3ce44SJohn Forte vport->flag &= EMLXS_PORT_RESET_MASK; 5385*fcf3ce44SJohn Forte vport->did = 0; 5386*fcf3ce44SJohn Forte vport->prev_did = 0; 5387*fcf3ce44SJohn Forte vport->lip_type = 0; 5388*fcf3ce44SJohn Forte bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); 5389*fcf3ce44SJohn Forte 5390*fcf3ce44SJohn Forte bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); 5391*fcf3ce44SJohn Forte vport->node_base.nlp_Rpi = 0; 5392*fcf3ce44SJohn Forte vport->node_base.nlp_DID = 0xffffff; 5393*fcf3ce44SJohn Forte vport->node_base.nlp_list_next = NULL; 5394*fcf3ce44SJohn Forte vport->node_base.nlp_list_prev = NULL; 5395*fcf3ce44SJohn Forte vport->node_base.nlp_active = 1; 5396*fcf3ce44SJohn Forte vport->node_count = 0; 5397*fcf3ce44SJohn Forte 5398*fcf3ce44SJohn Forte if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) { 5399*fcf3ce44SJohn Forte vport->ub_count = EMLXS_UB_TOKEN_OFFSET; 5400*fcf3ce44SJohn Forte } 5401*fcf3ce44SJohn Forte } 5402*fcf3ce44SJohn Forte 5403*fcf3ce44SJohn Forte return (0); 5404*fcf3ce44SJohn Forte 5405*fcf3ce44SJohn Forte } /* emlxs_hba_reset */ 5406*fcf3ce44SJohn Forte 5407*fcf3ce44SJohn Forte 5408*fcf3ce44SJohn Forte 5409*fcf3ce44SJohn Forte extern void 5410*fcf3ce44SJohn Forte emlxs_poll_intr(emlxs_hba_t *hba, uint32_t att_bit) 5411*fcf3ce44SJohn Forte { 5412*fcf3ce44SJohn Forte uint32_t ha_copy; 5413*fcf3ce44SJohn Forte 5414*fcf3ce44SJohn Forte /* 5415*fcf3ce44SJohn Forte * Polling a specific attention bit. 5416*fcf3ce44SJohn Forte */ 5417*fcf3ce44SJohn Forte for (;;) { 5418*fcf3ce44SJohn Forte ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr)); 5419*fcf3ce44SJohn Forte 5420*fcf3ce44SJohn Forte if (ha_copy & att_bit) { 5421*fcf3ce44SJohn Forte break; 5422*fcf3ce44SJohn Forte } 5423*fcf3ce44SJohn Forte } 5424*fcf3ce44SJohn Forte 5425*fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 5426*fcf3ce44SJohn Forte ha_copy = emlxs_get_attention(hba, -1); 5427*fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 5428*fcf3ce44SJohn Forte 5429*fcf3ce44SJohn Forte /* Process the attentions */ 5430*fcf3ce44SJohn Forte emlxs_proc_attention(hba, ha_copy); 5431*fcf3ce44SJohn Forte 5432*fcf3ce44SJohn Forte return; 5433*fcf3ce44SJohn Forte 5434*fcf3ce44SJohn Forte } /* emlxs_poll_intr() */ 5435*fcf3ce44SJohn Forte 5436*fcf3ce44SJohn Forte 5437*fcf3ce44SJohn Forte extern uint32_t 5438*fcf3ce44SJohn Forte emlxs_reset_ring(emlxs_hba_t *hba, uint32_t ringno) 5439*fcf3ce44SJohn Forte { 5440*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5441*fcf3ce44SJohn Forte RING *rp; 5442*fcf3ce44SJohn Forte MAILBOX *mb; 5443*fcf3ce44SJohn Forte PGP *pgp; 5444*fcf3ce44SJohn Forte off_t offset; 5445*fcf3ce44SJohn Forte NODELIST *ndlp; 5446*fcf3ce44SJohn Forte uint32_t i; 5447*fcf3ce44SJohn Forte emlxs_port_t *vport; 5448*fcf3ce44SJohn Forte 5449*fcf3ce44SJohn Forte rp = &hba->ring[ringno]; 5450*fcf3ce44SJohn Forte pgp = (PGP *) & ((SLIM2 *) hba->slim2.virt)->mbx.us.s2.port[ringno]; 5451*fcf3ce44SJohn Forte 5452*fcf3ce44SJohn Forte if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 5453*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, 5454*fcf3ce44SJohn Forte "%s: Unable to allocate mailbox buffer.", 5455*fcf3ce44SJohn Forte emlxs_ring_xlate(ringno)); 5456*fcf3ce44SJohn Forte 5457*fcf3ce44SJohn Forte return ((uint32_t)FC_FAILURE); 5458*fcf3ce44SJohn Forte } 5459*fcf3ce44SJohn Forte emlxs_mb_reset_ring(hba, mb, ringno); 5460*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 5461*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, 5462*fcf3ce44SJohn Forte "%s: Unable to reset ring. Mailbox cmd=%x status=%x", 5463*fcf3ce44SJohn Forte emlxs_ring_xlate(ringno), mb->mbxCommand, mb->mbxStatus); 5464*fcf3ce44SJohn Forte 5465*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 5466*fcf3ce44SJohn Forte return ((uint32_t)FC_FAILURE); 5467*fcf3ce44SJohn Forte } 5468*fcf3ce44SJohn Forte /* Free the mailbox */ 5469*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 5470*fcf3ce44SJohn Forte 5471*fcf3ce44SJohn Forte /* Update the response ring indicies */ 5472*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)&(pgp->rspPutInx) - 5473*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 5474*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 5475*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 5476*fcf3ce44SJohn Forte rp->fc_rspidx = rp->fc_port_rspidx = PCIMEM_LONG(pgp->rspPutInx); 5477*fcf3ce44SJohn Forte 5478*fcf3ce44SJohn Forte /* Update the command ring indicies */ 5479*fcf3ce44SJohn Forte offset = (off_t)((uint64_t)(unsigned long)&(pgp->cmdGetInx) - 5480*fcf3ce44SJohn Forte (uint64_t)(unsigned long)hba->slim2.virt); 5481*fcf3ce44SJohn Forte emlxs_mpdata_sync(hba->slim2.dma_handle, offset, 4, 5482*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 5483*fcf3ce44SJohn Forte rp->fc_cmdidx = rp->fc_port_cmdidx = PCIMEM_LONG(pgp->cmdGetInx); 5484*fcf3ce44SJohn Forte 5485*fcf3ce44SJohn Forte 5486*fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 5487*fcf3ce44SJohn Forte vport = &VPORT(i); 5488*fcf3ce44SJohn Forte 5489*fcf3ce44SJohn Forte if (!(vport->flag & EMLXS_PORT_BOUND)) { 5490*fcf3ce44SJohn Forte continue; 5491*fcf3ce44SJohn Forte } 5492*fcf3ce44SJohn Forte /* Clear all node XRI contexts */ 5493*fcf3ce44SJohn Forte rw_enter(&vport->node_rwlock, RW_WRITER); 5494*fcf3ce44SJohn Forte mutex_enter(&EMLXS_RINGTX_LOCK); 5495*fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 5496*fcf3ce44SJohn Forte ndlp = vport->node_table[i]; 5497*fcf3ce44SJohn Forte while (ndlp != NULL) { 5498*fcf3ce44SJohn Forte ndlp->nlp_flag[FC_IP_RING] &= ~NLP_RPI_XRI; 5499*fcf3ce44SJohn Forte ndlp = ndlp->nlp_list_next; 5500*fcf3ce44SJohn Forte } 5501*fcf3ce44SJohn Forte } 5502*fcf3ce44SJohn Forte mutex_exit(&EMLXS_RINGTX_LOCK); 5503*fcf3ce44SJohn Forte rw_exit(&vport->node_rwlock); 5504*fcf3ce44SJohn Forte } 5505*fcf3ce44SJohn Forte 5506*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, 5507*fcf3ce44SJohn Forte "%s", emlxs_ring_xlate(ringno)); 5508*fcf3ce44SJohn Forte 5509*fcf3ce44SJohn Forte return (FC_SUCCESS); 5510*fcf3ce44SJohn Forte 5511*fcf3ce44SJohn Forte } /* emlxs_reset_ring() */ 5512*fcf3ce44SJohn Forte 5513*fcf3ce44SJohn Forte 5514*fcf3ce44SJohn Forte extern char * 5515*fcf3ce44SJohn Forte emlxs_ffstate_xlate(uint32_t state) 5516*fcf3ce44SJohn Forte { 5517*fcf3ce44SJohn Forte static char buffer[32]; 5518*fcf3ce44SJohn Forte uint32_t i; 5519*fcf3ce44SJohn Forte uint32_t count; 5520*fcf3ce44SJohn Forte 5521*fcf3ce44SJohn Forte count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 5522*fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 5523*fcf3ce44SJohn Forte if (state == emlxs_ffstate_table[i].code) { 5524*fcf3ce44SJohn Forte return (emlxs_ffstate_table[i].string); 5525*fcf3ce44SJohn Forte } 5526*fcf3ce44SJohn Forte } 5527*fcf3ce44SJohn Forte 5528*fcf3ce44SJohn Forte (void) sprintf(buffer, "state=0x%x", state); 5529*fcf3ce44SJohn Forte return (buffer); 5530*fcf3ce44SJohn Forte 5531*fcf3ce44SJohn Forte } /* emlxs_ffstate_xlate() */ 5532*fcf3ce44SJohn Forte 5533*fcf3ce44SJohn Forte 5534*fcf3ce44SJohn Forte extern char * 5535*fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno) 5536*fcf3ce44SJohn Forte { 5537*fcf3ce44SJohn Forte static char buffer[32]; 5538*fcf3ce44SJohn Forte uint32_t i; 5539*fcf3ce44SJohn Forte uint32_t count; 5540*fcf3ce44SJohn Forte 5541*fcf3ce44SJohn Forte count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 5542*fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 5543*fcf3ce44SJohn Forte if (ringno == emlxs_ring_table[i].code) { 5544*fcf3ce44SJohn Forte return (emlxs_ring_table[i].string); 5545*fcf3ce44SJohn Forte } 5546*fcf3ce44SJohn Forte } 5547*fcf3ce44SJohn Forte 5548*fcf3ce44SJohn Forte (void) sprintf(buffer, "ring=0x%x", ringno); 5549*fcf3ce44SJohn Forte return (buffer); 5550*fcf3ce44SJohn Forte 5551*fcf3ce44SJohn Forte } /* emlxs_ring_xlate() */ 5552*fcf3ce44SJohn Forte 5553*fcf3ce44SJohn Forte 5554*fcf3ce44SJohn Forte 5555*fcf3ce44SJohn Forte extern void 5556*fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 5557*fcf3ce44SJohn Forte { 5558*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5559*fcf3ce44SJohn Forte MAILBOX *mb; 5560*fcf3ce44SJohn Forte emlxs_config_t *cfg; 5561*fcf3ce44SJohn Forte uint32_t value; 5562*fcf3ce44SJohn Forte 5563*fcf3ce44SJohn Forte cfg = &CFG; 5564*fcf3ce44SJohn Forte 5565*fcf3ce44SJohn Forte xlate: 5566*fcf3ce44SJohn Forte 5567*fcf3ce44SJohn Forte switch (cfg[CFG_PCI_MAX_READ].current) { 5568*fcf3ce44SJohn Forte case 512: 5569*fcf3ce44SJohn Forte value = 0; 5570*fcf3ce44SJohn Forte break; 5571*fcf3ce44SJohn Forte 5572*fcf3ce44SJohn Forte case 1024: 5573*fcf3ce44SJohn Forte value = 1; 5574*fcf3ce44SJohn Forte break; 5575*fcf3ce44SJohn Forte 5576*fcf3ce44SJohn Forte case 2048: 5577*fcf3ce44SJohn Forte value = 2; 5578*fcf3ce44SJohn Forte break; 5579*fcf3ce44SJohn Forte 5580*fcf3ce44SJohn Forte case 4096: 5581*fcf3ce44SJohn Forte value = 3; 5582*fcf3ce44SJohn Forte break; 5583*fcf3ce44SJohn Forte 5584*fcf3ce44SJohn Forte default: 5585*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5586*fcf3ce44SJohn Forte "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 5587*fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 5588*fcf3ce44SJohn Forte 5589*fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 5590*fcf3ce44SJohn Forte goto xlate; 5591*fcf3ce44SJohn Forte } 5592*fcf3ce44SJohn Forte 5593*fcf3ce44SJohn Forte if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 5594*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5595*fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to allocate mailbox buffer."); 5596*fcf3ce44SJohn Forte return; 5597*fcf3ce44SJohn Forte } 5598*fcf3ce44SJohn Forte emlxs_mb_set_var(hba, (MAILBOX *) mb, 0x00100506, value); 5599*fcf3ce44SJohn Forte 5600*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 5601*fcf3ce44SJohn Forte if (verbose || (mb->mbxStatus != 0x12)) { 5602*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5603*fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to update. status=%x " 5604*fcf3ce44SJohn Forte "value=%d (%d bytes)", mb->mbxStatus, value, 5605*fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 5606*fcf3ce44SJohn Forte } 5607*fcf3ce44SJohn Forte } else { 5608*fcf3ce44SJohn Forte if (verbose && (cfg[CFG_PCI_MAX_READ].current != 5609*fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].def)) { 5610*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5611*fcf3ce44SJohn Forte "PCI_MAX_READ: Updated. %d bytes", 5612*fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 5613*fcf3ce44SJohn Forte } 5614*fcf3ce44SJohn Forte } 5615*fcf3ce44SJohn Forte 5616*fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 5617*fcf3ce44SJohn Forte 5618*fcf3ce44SJohn Forte return; 5619*fcf3ce44SJohn Forte 5620*fcf3ce44SJohn Forte } /* emlxs_pcix_mxr_update */ 5621*fcf3ce44SJohn Forte 5622*fcf3ce44SJohn Forte 5623*fcf3ce44SJohn Forte 5624*fcf3ce44SJohn Forte extern uint32_t 5625*fcf3ce44SJohn Forte emlxs_get_key(emlxs_hba_t *hba, MAILBOX *mb) 5626*fcf3ce44SJohn Forte { 5627*fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5628*fcf3ce44SJohn Forte uint32_t npname0, npname1; 5629*fcf3ce44SJohn Forte uint32_t tmpkey, theKey; 5630*fcf3ce44SJohn Forte uint16_t key850; 5631*fcf3ce44SJohn Forte uint32_t t1, t2, t3, t4; 5632*fcf3ce44SJohn Forte uint32_t ts; 5633*fcf3ce44SJohn Forte 5634*fcf3ce44SJohn Forte #define SEED 0x876EDC21 5635*fcf3ce44SJohn Forte 5636*fcf3ce44SJohn Forte /* This key is only used currently for SBUS adapters */ 5637*fcf3ce44SJohn Forte if (hba->bus_type != SBUS_FC) { 5638*fcf3ce44SJohn Forte return (0); 5639*fcf3ce44SJohn Forte } 5640*fcf3ce44SJohn Forte tmpkey = mb->un.varWords[30]; 5641*fcf3ce44SJohn Forte emlxs_ffstate_change(hba, FC_INIT_NVPARAMS); 5642*fcf3ce44SJohn Forte 5643*fcf3ce44SJohn Forte emlxs_mb_read_nv(hba, mb); 5644*fcf3ce44SJohn Forte if (emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 5645*fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5646*fcf3ce44SJohn Forte "Unable to read nvram. cmd=%x status=%x", 5647*fcf3ce44SJohn Forte mb->mbxCommand, mb->mbxStatus); 5648*fcf3ce44SJohn Forte 5649*fcf3ce44SJohn Forte return (0); 5650*fcf3ce44SJohn Forte } 5651*fcf3ce44SJohn Forte npname0 = mb->un.varRDnvp.portname[0]; 5652*fcf3ce44SJohn Forte npname1 = mb->un.varRDnvp.portname[1]; 5653*fcf3ce44SJohn Forte 5654*fcf3ce44SJohn Forte key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 5655*fcf3ce44SJohn Forte ts = (uint16_t)(npname1 + 1); 5656*fcf3ce44SJohn Forte t1 = ts * key850; 5657*fcf3ce44SJohn Forte ts = (uint16_t)((npname1 >> 16) + 1); 5658*fcf3ce44SJohn Forte t2 = ts * key850; 5659*fcf3ce44SJohn Forte ts = (uint16_t)(npname0 + 1); 5660*fcf3ce44SJohn Forte t3 = ts * key850; 5661*fcf3ce44SJohn Forte ts = (uint16_t)((npname0 >> 16) + 1); 5662*fcf3ce44SJohn Forte t4 = ts * key850; 5663*fcf3ce44SJohn Forte theKey = SEED + t1 + t2 + t3 + t4; 5664*fcf3ce44SJohn Forte 5665*fcf3ce44SJohn Forte return (theKey); 5666*fcf3ce44SJohn Forte 5667*fcf3ce44SJohn Forte } /* emlxs_get_key() */ 5668