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 /* Copyright 2008 QLogic Corporation */ 23*fcf3ce44SJohn Forte 24*fcf3ce44SJohn Forte /* 25*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*fcf3ce44SJohn Forte * Use is subject to license terms. 27*fcf3ce44SJohn Forte */ 28*fcf3ce44SJohn Forte 29*fcf3ce44SJohn Forte #pragma ident "Copyright 2008 QLogic Corporation; ql_init.c" 30*fcf3ce44SJohn Forte 31*fcf3ce44SJohn Forte /* 32*fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 33*fcf3ce44SJohn Forte * 34*fcf3ce44SJohn Forte * *********************************************************************** 35*fcf3ce44SJohn Forte * * ** 36*fcf3ce44SJohn Forte * * NOTICE ** 37*fcf3ce44SJohn Forte * * COPYRIGHT (C) 1996-2008 QLOGIC CORPORATION ** 38*fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 39*fcf3ce44SJohn Forte * * ** 40*fcf3ce44SJohn Forte * *********************************************************************** 41*fcf3ce44SJohn Forte * 42*fcf3ce44SJohn Forte */ 43*fcf3ce44SJohn Forte 44*fcf3ce44SJohn Forte #include <ql_apps.h> 45*fcf3ce44SJohn Forte #include <ql_api.h> 46*fcf3ce44SJohn Forte #include <ql_debug.h> 47*fcf3ce44SJohn Forte #include <ql_init.h> 48*fcf3ce44SJohn Forte #include <ql_iocb.h> 49*fcf3ce44SJohn Forte #include <ql_isr.h> 50*fcf3ce44SJohn Forte #include <ql_mbx.h> 51*fcf3ce44SJohn Forte #include <ql_xioctl.h> 52*fcf3ce44SJohn Forte 53*fcf3ce44SJohn Forte /* 54*fcf3ce44SJohn Forte * Local data 55*fcf3ce44SJohn Forte */ 56*fcf3ce44SJohn Forte 57*fcf3ce44SJohn Forte /* 58*fcf3ce44SJohn Forte * Local prototypes 59*fcf3ce44SJohn Forte */ 60*fcf3ce44SJohn Forte static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t); 61*fcf3ce44SJohn Forte static int ql_nvram_24xx_config(ql_adapter_state_t *); 62*fcf3ce44SJohn Forte static void ql_23_properties(ql_adapter_state_t *, nvram_t *); 63*fcf3ce44SJohn Forte static void ql_24xx_properties(ql_adapter_state_t *, nvram_24xx_t *); 64*fcf3ce44SJohn Forte static int ql_check_isp_firmware(ql_adapter_state_t *); 65*fcf3ce44SJohn Forte static int ql_chip_diag(ql_adapter_state_t *); 66*fcf3ce44SJohn Forte static int ql_load_flash_fw(ql_adapter_state_t *); 67*fcf3ce44SJohn Forte static int ql_configure_loop(ql_adapter_state_t *); 68*fcf3ce44SJohn Forte static int ql_configure_hba(ql_adapter_state_t *); 69*fcf3ce44SJohn Forte static int ql_configure_fabric(ql_adapter_state_t *); 70*fcf3ce44SJohn Forte static int ql_configure_device_d_id(ql_adapter_state_t *); 71*fcf3ce44SJohn Forte static void ql_set_max_read_req(ql_adapter_state_t *); 72*fcf3ce44SJohn Forte /* 73*fcf3ce44SJohn Forte * ql_initialize_adapter 74*fcf3ce44SJohn Forte * Initialize board. 75*fcf3ce44SJohn Forte * 76*fcf3ce44SJohn Forte * Input: 77*fcf3ce44SJohn Forte * ha = adapter state pointer. 78*fcf3ce44SJohn Forte * 79*fcf3ce44SJohn Forte * Returns: 80*fcf3ce44SJohn Forte * ql local function return status code. 81*fcf3ce44SJohn Forte * 82*fcf3ce44SJohn Forte * Context: 83*fcf3ce44SJohn Forte * Kernel context. 84*fcf3ce44SJohn Forte */ 85*fcf3ce44SJohn Forte int 86*fcf3ce44SJohn Forte ql_initialize_adapter(ql_adapter_state_t *ha) 87*fcf3ce44SJohn Forte { 88*fcf3ce44SJohn Forte int rval; 89*fcf3ce44SJohn Forte class_svc_param_t *class3_param; 90*fcf3ce44SJohn Forte caddr_t msg; 91*fcf3ce44SJohn Forte la_els_logi_t *els = &ha->loginparams; 92*fcf3ce44SJohn Forte int retries = 5; 93*fcf3ce44SJohn Forte 94*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 95*fcf3ce44SJohn Forte 96*fcf3ce44SJohn Forte do { 97*fcf3ce44SJohn Forte /* Clear adapter flags. */ 98*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 99*fcf3ce44SJohn Forte ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG | 100*fcf3ce44SJohn Forte TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG | 101*fcf3ce44SJohn Forte TASK_DAEMON_IDLE_CHK_FLG; 102*fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 103*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 104*fcf3ce44SJohn Forte 105*fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 106*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 107*fcf3ce44SJohn Forte ha->flags |= COMMAND_ABORT_TIMEOUT; 108*fcf3ce44SJohn Forte ha->flags &= ~ONLINE; 109*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 110*fcf3ce44SJohn Forte 111*fcf3ce44SJohn Forte ha->state = FC_STATE_OFFLINE; 112*fcf3ce44SJohn Forte msg = "Loop OFFLINE"; 113*fcf3ce44SJohn Forte 114*fcf3ce44SJohn Forte rval = ql_pci_sbus_config(ha); 115*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 116*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 117*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) { 118*fcf3ce44SJohn Forte EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n"); 119*fcf3ce44SJohn Forte ha->task_daemon_flags |= ISP_ABORT_NEEDED; 120*fcf3ce44SJohn Forte } 121*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 122*fcf3ce44SJohn Forte continue; 123*fcf3ce44SJohn Forte } 124*fcf3ce44SJohn Forte 125*fcf3ce44SJohn Forte ql_setup_fcache(ha); 126*fcf3ce44SJohn Forte 127*fcf3ce44SJohn Forte /* Reset ISP chip. */ 128*fcf3ce44SJohn Forte ql_reset_chip(ha); 129*fcf3ce44SJohn Forte 130*fcf3ce44SJohn Forte /* Get NVRAM configuration if needed. */ 131*fcf3ce44SJohn Forte if (ha->init_ctrl_blk.cb.version == 0) { 132*fcf3ce44SJohn Forte (void) ql_nvram_config(ha); 133*fcf3ce44SJohn Forte } 134*fcf3ce44SJohn Forte 135*fcf3ce44SJohn Forte /* Set login parameters. */ 136*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 137*fcf3ce44SJohn Forte els->common_service.rx_bufsize = CHAR_TO_SHORT( 138*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb24.max_frame_length[0], 139*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb24.max_frame_length[1]); 140*fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb24.port_name[0], 141*fcf3ce44SJohn Forte (void *)&els->nport_ww_name.raw_wwn[0], 8); 142*fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb24.node_name[0], 143*fcf3ce44SJohn Forte (void *)&els->node_ww_name.raw_wwn[0], 8); 144*fcf3ce44SJohn Forte } else { 145*fcf3ce44SJohn Forte els->common_service.rx_bufsize = CHAR_TO_SHORT( 146*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.max_frame_length[0], 147*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.max_frame_length[1]); 148*fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb.port_name[0], 149*fcf3ce44SJohn Forte (void *)&els->nport_ww_name.raw_wwn[0], 8); 150*fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb.node_name[0], 151*fcf3ce44SJohn Forte (void *)&els->node_ww_name.raw_wwn[0], 8); 152*fcf3ce44SJohn Forte } 153*fcf3ce44SJohn Forte 154*fcf3ce44SJohn Forte /* Determine which RISC code to use. */ 155*fcf3ce44SJohn Forte (void) ql_check_isp_firmware(ha); 156*fcf3ce44SJohn Forte 157*fcf3ce44SJohn Forte rval = ql_chip_diag(ha); 158*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 159*fcf3ce44SJohn Forte rval = ql_load_isp_firmware(ha); 160*fcf3ce44SJohn Forte } 161*fcf3ce44SJohn Forte 162*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) == 163*fcf3ce44SJohn Forte QL_SUCCESS && (rval = ql_init_rings(ha)) == 164*fcf3ce44SJohn Forte QL_SUCCESS) { 165*fcf3ce44SJohn Forte 166*fcf3ce44SJohn Forte (void) ql_fw_ready(ha, ha->fwwait); 167*fcf3ce44SJohn Forte 168*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & QL_SUSPENDED) && 169*fcf3ce44SJohn Forte ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 170*fcf3ce44SJohn Forte if (ha->topology & QL_LOOP_CONNECTION) { 171*fcf3ce44SJohn Forte ha->state = ha->state | FC_STATE_LOOP; 172*fcf3ce44SJohn Forte msg = "Loop ONLINE"; 173*fcf3ce44SJohn Forte ha->task_daemon_flags |= STATE_ONLINE; 174*fcf3ce44SJohn Forte } else if (ha->topology & QL_P2P_CONNECTION) { 175*fcf3ce44SJohn Forte ha->state = ha->state | 176*fcf3ce44SJohn Forte FC_STATE_ONLINE; 177*fcf3ce44SJohn Forte msg = "Link ONLINE"; 178*fcf3ce44SJohn Forte ha->task_daemon_flags |= STATE_ONLINE; 179*fcf3ce44SJohn Forte } else { 180*fcf3ce44SJohn Forte msg = "Unknown Link state"; 181*fcf3ce44SJohn Forte } 182*fcf3ce44SJohn Forte } 183*fcf3ce44SJohn Forte } else { 184*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 185*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) { 186*fcf3ce44SJohn Forte EL(ha, "failed, isp_abort_needed\n"); 187*fcf3ce44SJohn Forte ha->task_daemon_flags |= ISP_ABORT_NEEDED | 188*fcf3ce44SJohn Forte LOOP_DOWN; 189*fcf3ce44SJohn Forte } 190*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 191*fcf3ce44SJohn Forte } 192*fcf3ce44SJohn Forte 193*fcf3ce44SJohn Forte } while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED); 194*fcf3ce44SJohn Forte 195*fcf3ce44SJohn Forte cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg); 196*fcf3ce44SJohn Forte 197*fcf3ce44SJohn Forte /* Enable ISP interrupts and login parameters. */ 198*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? WRT32_IO_REG(ha, ictrl, ISP_EN_RISC): 199*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 200*fcf3ce44SJohn Forte 201*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 202*fcf3ce44SJohn Forte ha->flags |= (INTERRUPTS_ENABLED | ONLINE); 203*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 204*fcf3ce44SJohn Forte 205*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FC_STATE_CHANGE | RESET_MARKER_NEEDED | 206*fcf3ce44SJohn Forte COMMAND_WAIT_NEEDED); 207*fcf3ce44SJohn Forte 208*fcf3ce44SJohn Forte /* 209*fcf3ce44SJohn Forte * Setup login parameters. 210*fcf3ce44SJohn Forte */ 211*fcf3ce44SJohn Forte els->common_service.fcph_version = 0x2006; 212*fcf3ce44SJohn Forte els->common_service.btob_credit = 3; 213*fcf3ce44SJohn Forte els->common_service.cmn_features = 0x8800; 214*fcf3ce44SJohn Forte els->common_service.conc_sequences = 0xff; 215*fcf3ce44SJohn Forte els->common_service.relative_offset = 3; 216*fcf3ce44SJohn Forte els->common_service.e_d_tov = 0x07d0; 217*fcf3ce44SJohn Forte 218*fcf3ce44SJohn Forte class3_param = (class_svc_param_t *)&els->class_3; 219*fcf3ce44SJohn Forte class3_param->class_valid_svc_opt = 0x8800; 220*fcf3ce44SJohn Forte class3_param->rcv_data_size = els->common_service.rx_bufsize; 221*fcf3ce44SJohn Forte class3_param->conc_sequences = 0xff; 222*fcf3ce44SJohn Forte 223*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 224*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 225*fcf3ce44SJohn Forte } else { 226*fcf3ce44SJohn Forte /*EMPTY*/ 227*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 228*fcf3ce44SJohn Forte } 229*fcf3ce44SJohn Forte return (rval); 230*fcf3ce44SJohn Forte } 231*fcf3ce44SJohn Forte 232*fcf3ce44SJohn Forte /* 233*fcf3ce44SJohn Forte * ql_pci_sbus_config 234*fcf3ce44SJohn Forte * Setup device PCI/SBUS configuration registers. 235*fcf3ce44SJohn Forte * 236*fcf3ce44SJohn Forte * Input: 237*fcf3ce44SJohn Forte * ha = adapter state pointer. 238*fcf3ce44SJohn Forte * 239*fcf3ce44SJohn Forte * Returns: 240*fcf3ce44SJohn Forte * ql local function return status code. 241*fcf3ce44SJohn Forte * 242*fcf3ce44SJohn Forte * Context: 243*fcf3ce44SJohn Forte * Kernel context. 244*fcf3ce44SJohn Forte */ 245*fcf3ce44SJohn Forte int 246*fcf3ce44SJohn Forte ql_pci_sbus_config(ql_adapter_state_t *ha) 247*fcf3ce44SJohn Forte { 248*fcf3ce44SJohn Forte uint32_t timer; 249*fcf3ce44SJohn Forte uint16_t cmd, w16; 250*fcf3ce44SJohn Forte 251*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 252*fcf3ce44SJohn Forte 253*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 254*fcf3ce44SJohn Forte w16 = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle, 255*fcf3ce44SJohn Forte (uint16_t *)(ha->sbus_fpga_iobase + FPGA_REVISION)); 256*fcf3ce44SJohn Forte EL(ha, "FPGA rev is %d.%d", (w16 & 0xf0) >> 4, 257*fcf3ce44SJohn Forte w16 & 0xf); 258*fcf3ce44SJohn Forte } else { 259*fcf3ce44SJohn Forte /* 260*fcf3ce44SJohn Forte * we want to respect framework's setting of PCI 261*fcf3ce44SJohn Forte * configuration space command register and also 262*fcf3ce44SJohn Forte * want to make sure that all bits of interest to us 263*fcf3ce44SJohn Forte * are properly set in command register. 264*fcf3ce44SJohn Forte */ 265*fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 266*fcf3ce44SJohn Forte cmd = (uint16_t)(cmd | PCI_COMM_IO | PCI_COMM_MAE | 267*fcf3ce44SJohn Forte PCI_COMM_ME | PCI_COMM_MEMWR_INVAL | 268*fcf3ce44SJohn Forte PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE); 269*fcf3ce44SJohn Forte 270*fcf3ce44SJohn Forte /* 271*fcf3ce44SJohn Forte * If this is a 2300 card and not 2312, reset the 272*fcf3ce44SJohn Forte * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the 273*fcf3ce44SJohn Forte * 2310 also reports itself as a 2300 so we need to get the 274*fcf3ce44SJohn Forte * fb revision level -- a 6 indicates it really is a 2300 and 275*fcf3ce44SJohn Forte * not a 2310. 276*fcf3ce44SJohn Forte */ 277*fcf3ce44SJohn Forte 278*fcf3ce44SJohn Forte if (ha->device_id == 0x2300) { 279*fcf3ce44SJohn Forte /* Pause RISC. */ 280*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 281*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 282*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 283*fcf3ce44SJohn Forte 0) { 284*fcf3ce44SJohn Forte break; 285*fcf3ce44SJohn Forte } else { 286*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 287*fcf3ce44SJohn Forte } 288*fcf3ce44SJohn Forte } 289*fcf3ce44SJohn Forte 290*fcf3ce44SJohn Forte /* Select FPM registers. */ 291*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x20); 292*fcf3ce44SJohn Forte 293*fcf3ce44SJohn Forte /* Get the fb rev level */ 294*fcf3ce44SJohn Forte if (RD16_IO_REG(ha, fb_cmd) == 6) { 295*fcf3ce44SJohn Forte cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL); 296*fcf3ce44SJohn Forte } 297*fcf3ce44SJohn Forte 298*fcf3ce44SJohn Forte /* Deselect FPM registers. */ 299*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x0); 300*fcf3ce44SJohn Forte 301*fcf3ce44SJohn Forte /* Release RISC module. */ 302*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 303*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 304*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) == 305*fcf3ce44SJohn Forte 0) { 306*fcf3ce44SJohn Forte break; 307*fcf3ce44SJohn Forte } else { 308*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 309*fcf3ce44SJohn Forte } 310*fcf3ce44SJohn Forte } 311*fcf3ce44SJohn Forte } else if (ha->device_id == 0x2312) { 312*fcf3ce44SJohn Forte /* 313*fcf3ce44SJohn Forte * cPCI ISP2312 specific code to service function 1 314*fcf3ce44SJohn Forte * hot-swap registers. 315*fcf3ce44SJohn Forte */ 316*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK) 317*fcf3ce44SJohn Forte != 0) { 318*fcf3ce44SJohn Forte ql_pci_config_put8(ha, 0x66, 0xc2); 319*fcf3ce44SJohn Forte } 320*fcf3ce44SJohn Forte } 321*fcf3ce44SJohn Forte 322*fcf3ce44SJohn Forte /* max memory read byte cnt override */ 323*fcf3ce44SJohn Forte if (ha->pci_max_read_req != 0) { 324*fcf3ce44SJohn Forte ql_set_max_read_req(ha); 325*fcf3ce44SJohn Forte } 326*fcf3ce44SJohn Forte 327*fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 328*fcf3ce44SJohn Forte 329*fcf3ce44SJohn Forte /* Set cache line register. */ 330*fcf3ce44SJohn Forte ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10); 331*fcf3ce44SJohn Forte 332*fcf3ce44SJohn Forte /* Set latency register. */ 333*fcf3ce44SJohn Forte ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40); 334*fcf3ce44SJohn Forte 335*fcf3ce44SJohn Forte /* Reset expansion ROM address decode enable. */ 336*fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM); 337*fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~BIT_0); 338*fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_ROM, w16); 339*fcf3ce44SJohn Forte } 340*fcf3ce44SJohn Forte 341*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 342*fcf3ce44SJohn Forte 343*fcf3ce44SJohn Forte return (QL_SUCCESS); 344*fcf3ce44SJohn Forte } 345*fcf3ce44SJohn Forte 346*fcf3ce44SJohn Forte /* 347*fcf3ce44SJohn Forte * Set the PCI max read request value. 348*fcf3ce44SJohn Forte * 349*fcf3ce44SJohn Forte * Input: 350*fcf3ce44SJohn Forte * ha: adapter state pointer. 351*fcf3ce44SJohn Forte * 352*fcf3ce44SJohn Forte * Output: 353*fcf3ce44SJohn Forte * none. 354*fcf3ce44SJohn Forte * 355*fcf3ce44SJohn Forte * Returns: 356*fcf3ce44SJohn Forte * 357*fcf3ce44SJohn Forte * Context: 358*fcf3ce44SJohn Forte * Kernel context. 359*fcf3ce44SJohn Forte */ 360*fcf3ce44SJohn Forte 361*fcf3ce44SJohn Forte static void 362*fcf3ce44SJohn Forte ql_set_max_read_req(ql_adapter_state_t *ha) 363*fcf3ce44SJohn Forte { 364*fcf3ce44SJohn Forte uint16_t read_req, w16; 365*fcf3ce44SJohn Forte uint16_t tmp = ha->pci_max_read_req; 366*fcf3ce44SJohn Forte 367*fcf3ce44SJohn Forte if ((ha->device_id == 0x2422) || 368*fcf3ce44SJohn Forte ((ha->device_id & 0xff00) == 0x2300)) { 369*fcf3ce44SJohn Forte /* check for vaild override value */ 370*fcf3ce44SJohn Forte if (tmp == 512 || tmp == 1024 || tmp == 2048 || 371*fcf3ce44SJohn Forte tmp == 4096) { 372*fcf3ce44SJohn Forte /* shift away the don't cares */ 373*fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 10); 374*fcf3ce44SJohn Forte /* convert bit pos to request value */ 375*fcf3ce44SJohn Forte for (read_req = 0; tmp != 0; read_req++) { 376*fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 1); 377*fcf3ce44SJohn Forte } 378*fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, 0x4e); 379*fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2)); 380*fcf3ce44SJohn Forte w16 = (uint16_t)(w16 | (read_req << 2)); 381*fcf3ce44SJohn Forte ql_pci_config_put16(ha, 0x4e, w16); 382*fcf3ce44SJohn Forte } else { 383*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 384*fcf3ce44SJohn Forte "'pci-max-read-request': %d; using system " 385*fcf3ce44SJohn Forte "default\n", tmp); 386*fcf3ce44SJohn Forte } 387*fcf3ce44SJohn Forte } else if ((ha->device_id == 0x2432) || ((ha->device_id & 0xff00) == 388*fcf3ce44SJohn Forte 0x2500)) { 389*fcf3ce44SJohn Forte /* check for vaild override value */ 390*fcf3ce44SJohn Forte if (tmp == 128 || tmp == 256 || tmp == 512 || 391*fcf3ce44SJohn Forte tmp == 1024 || tmp == 2048 || tmp == 4096) { 392*fcf3ce44SJohn Forte /* shift away the don't cares */ 393*fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 8); 394*fcf3ce44SJohn Forte /* convert bit pos to request value */ 395*fcf3ce44SJohn Forte for (read_req = 0; tmp != 0; read_req++) { 396*fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 1); 397*fcf3ce44SJohn Forte } 398*fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, 0x54); 399*fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 | 400*fcf3ce44SJohn Forte BIT_12)); 401*fcf3ce44SJohn Forte w16 = (uint16_t)(w16 | (read_req << 12)); 402*fcf3ce44SJohn Forte ql_pci_config_put16(ha, 0x54, w16); 403*fcf3ce44SJohn Forte } else { 404*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 405*fcf3ce44SJohn Forte "'pci-max-read-request': %d; using system " 406*fcf3ce44SJohn Forte "default\n", tmp); 407*fcf3ce44SJohn Forte } 408*fcf3ce44SJohn Forte } 409*fcf3ce44SJohn Forte } 410*fcf3ce44SJohn Forte 411*fcf3ce44SJohn Forte /* 412*fcf3ce44SJohn Forte * NVRAM configuration. 413*fcf3ce44SJohn Forte * 414*fcf3ce44SJohn Forte * Input: 415*fcf3ce44SJohn Forte * ha: adapter state pointer. 416*fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 417*fcf3ce44SJohn Forte * 418*fcf3ce44SJohn Forte * Output: 419*fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 420*fcf3ce44SJohn Forte * host adapters parameters in host adapter block 421*fcf3ce44SJohn Forte * 422*fcf3ce44SJohn Forte * Returns: 423*fcf3ce44SJohn Forte * ql local function return status code. 424*fcf3ce44SJohn Forte * 425*fcf3ce44SJohn Forte * Context: 426*fcf3ce44SJohn Forte * Kernel context. 427*fcf3ce44SJohn Forte */ 428*fcf3ce44SJohn Forte int 429*fcf3ce44SJohn Forte ql_nvram_config(ql_adapter_state_t *ha) 430*fcf3ce44SJohn Forte { 431*fcf3ce44SJohn Forte uint32_t cnt; 432*fcf3ce44SJohn Forte caddr_t dptr1, dptr2; 433*fcf3ce44SJohn Forte ql_init_cb_t *icb = &ha->init_ctrl_blk.cb; 434*fcf3ce44SJohn Forte ql_ip_init_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb; 435*fcf3ce44SJohn Forte nvram_t *nv = (nvram_t *)ha->request_ring_bp; 436*fcf3ce44SJohn Forte uint16_t *wptr = (uint16_t *)ha->request_ring_bp; 437*fcf3ce44SJohn Forte uint8_t chksum = 0; 438*fcf3ce44SJohn Forte int rval; 439*fcf3ce44SJohn Forte int idpromlen; 440*fcf3ce44SJohn Forte char idprombuf[32]; 441*fcf3ce44SJohn Forte uint32_t start_addr; 442*fcf3ce44SJohn Forte 443*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 444*fcf3ce44SJohn Forte 445*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 446*fcf3ce44SJohn Forte return (ql_nvram_24xx_config(ha)); 447*fcf3ce44SJohn Forte } 448*fcf3ce44SJohn Forte 449*fcf3ce44SJohn Forte start_addr = 0; 450*fcf3ce44SJohn Forte if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) == 451*fcf3ce44SJohn Forte QL_SUCCESS) { 452*fcf3ce44SJohn Forte /* Verify valid NVRAM checksum. */ 453*fcf3ce44SJohn Forte for (cnt = 0; cnt < sizeof (nvram_t)/2; cnt++) { 454*fcf3ce44SJohn Forte *wptr = (uint16_t)ql_get_nvram_word(ha, 455*fcf3ce44SJohn Forte (uint32_t)(cnt + start_addr)); 456*fcf3ce44SJohn Forte chksum = (uint8_t)(chksum + (uint8_t)*wptr); 457*fcf3ce44SJohn Forte chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8)); 458*fcf3ce44SJohn Forte wptr++; 459*fcf3ce44SJohn Forte } 460*fcf3ce44SJohn Forte ql_release_nvram(ha); 461*fcf3ce44SJohn Forte } 462*fcf3ce44SJohn Forte 463*fcf3ce44SJohn Forte /* Bad NVRAM data, set defaults parameters. */ 464*fcf3ce44SJohn Forte if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' || 465*fcf3ce44SJohn Forte nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || 466*fcf3ce44SJohn Forte nv->nvram_version < 1) { 467*fcf3ce44SJohn Forte 468*fcf3ce44SJohn Forte EL(ha, "failed, rval=%xh, checksum=%xh, " 469*fcf3ce44SJohn Forte "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, " 470*fcf3ce44SJohn Forte "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1], 471*fcf3ce44SJohn Forte nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size, 472*fcf3ce44SJohn Forte ha->subven_id, nv->nvram_version); 473*fcf3ce44SJohn Forte 474*fcf3ce44SJohn Forte /* Don't print nvram message if it's an on-board 2200 */ 475*fcf3ce44SJohn Forte if (!((CFG_IST(ha, CFG_CTRL_2200)) && 476*fcf3ce44SJohn Forte (ha->xioctl->fdesc.flash_size == 0))) { 477*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed," 478*fcf3ce44SJohn Forte " using driver defaults.", QL_NAME, ha->instance); 479*fcf3ce44SJohn Forte } 480*fcf3ce44SJohn Forte 481*fcf3ce44SJohn Forte /* Reset NVRAM data. */ 482*fcf3ce44SJohn Forte bzero((void *)nv, sizeof (nvram_t)); 483*fcf3ce44SJohn Forte 484*fcf3ce44SJohn Forte /* 485*fcf3ce44SJohn Forte * Set default initialization control block. 486*fcf3ce44SJohn Forte */ 487*fcf3ce44SJohn Forte nv->parameter_block_version = ICB_VERSION; 488*fcf3ce44SJohn Forte nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1; 489*fcf3ce44SJohn Forte nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2; 490*fcf3ce44SJohn Forte 491*fcf3ce44SJohn Forte nv->max_frame_length[1] = 4; 492*fcf3ce44SJohn Forte 493*fcf3ce44SJohn Forte /* 494*fcf3ce44SJohn Forte * Allow 2048 byte frames for 2300 495*fcf3ce44SJohn Forte */ 496*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 497*fcf3ce44SJohn Forte nv->max_frame_length[1] = 8; 498*fcf3ce44SJohn Forte } 499*fcf3ce44SJohn Forte nv->max_iocb_allocation[1] = 1; 500*fcf3ce44SJohn Forte nv->execution_throttle[0] = 16; 501*fcf3ce44SJohn Forte nv->login_retry_count = 8; 502*fcf3ce44SJohn Forte 503*fcf3ce44SJohn Forte idpromlen = 32; 504*fcf3ce44SJohn Forte 505*fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 506*fcf3ce44SJohn Forte if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip, 507*fcf3ce44SJohn Forte DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf, 508*fcf3ce44SJohn Forte &idpromlen) != DDI_PROP_SUCCESS) { 509*fcf3ce44SJohn Forte 510*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): Unable to read idprom " 511*fcf3ce44SJohn Forte "property\n", ha->instance); 512*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) : Unable to read idprom " 513*fcf3ce44SJohn Forte "property", QL_NAME, ha->instance); 514*fcf3ce44SJohn Forte 515*fcf3ce44SJohn Forte nv->port_name[2] = 33; 516*fcf3ce44SJohn Forte nv->port_name[3] = 224; 517*fcf3ce44SJohn Forte nv->port_name[4] = 139; 518*fcf3ce44SJohn Forte nv->port_name[7] = (uint8_t) 519*fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 520*fcf3ce44SJohn Forte 521*fcf3ce44SJohn Forte } else { 522*fcf3ce44SJohn Forte 523*fcf3ce44SJohn Forte nv->port_name[2] = idprombuf[2]; 524*fcf3ce44SJohn Forte nv->port_name[3] = idprombuf[3]; 525*fcf3ce44SJohn Forte nv->port_name[4] = idprombuf[4]; 526*fcf3ce44SJohn Forte nv->port_name[5] = idprombuf[5]; 527*fcf3ce44SJohn Forte nv->port_name[6] = idprombuf[6]; 528*fcf3ce44SJohn Forte nv->port_name[7] = idprombuf[7]; 529*fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t) 530*fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 531*fcf3ce44SJohn Forte 532*fcf3ce44SJohn Forte } 533*fcf3ce44SJohn Forte 534*fcf3ce44SJohn Forte /* Don't print nvram message if it's an on-board 2200 */ 535*fcf3ce44SJohn Forte if (!(CFG_IST(ha, CFG_CTRL_2200)) && 536*fcf3ce44SJohn Forte (ha->xioctl->fdesc.flash_size == 0)) { 537*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using" 538*fcf3ce44SJohn Forte " default HBA parameters and temporary WWPN:" 539*fcf3ce44SJohn Forte " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME, 540*fcf3ce44SJohn Forte ha->instance, nv->port_name[0], nv->port_name[1], 541*fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], 542*fcf3ce44SJohn Forte nv->port_name[4], nv->port_name[5], 543*fcf3ce44SJohn Forte nv->port_name[6], nv->port_name[7]); 544*fcf3ce44SJohn Forte } 545*fcf3ce44SJohn Forte 546*fcf3ce44SJohn Forte nv->login_timeout = 4; 547*fcf3ce44SJohn Forte 548*fcf3ce44SJohn Forte /* Set default connection options for the 23xx to 2 */ 549*fcf3ce44SJohn Forte if (!(CFG_IST(ha, CFG_CTRL_2200))) { 550*fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] | 551*fcf3ce44SJohn Forte BIT_5); 552*fcf3ce44SJohn Forte } 553*fcf3ce44SJohn Forte 554*fcf3ce44SJohn Forte /* 555*fcf3ce44SJohn Forte * Set default host adapter parameters 556*fcf3ce44SJohn Forte */ 557*fcf3ce44SJohn Forte nv->host_p[0] = BIT_1; 558*fcf3ce44SJohn Forte nv->host_p[1] = BIT_2; 559*fcf3ce44SJohn Forte nv->reset_delay = 5; 560*fcf3ce44SJohn Forte nv->port_down_retry_count = 8; 561*fcf3ce44SJohn Forte nv->maximum_luns_per_target[0] = 8; 562*fcf3ce44SJohn Forte 563*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 564*fcf3ce44SJohn Forte } 565*fcf3ce44SJohn Forte 566*fcf3ce44SJohn Forte /* Check for adapter node name (big endian). */ 567*fcf3ce44SJohn Forte for (cnt = 0; cnt < 8; cnt++) { 568*fcf3ce44SJohn Forte if (nv->node_name[cnt] != 0) { 569*fcf3ce44SJohn Forte break; 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte } 572*fcf3ce44SJohn Forte 573*fcf3ce44SJohn Forte /* Copy port name if no node name (big endian). */ 574*fcf3ce44SJohn Forte if (cnt == 8) { 575*fcf3ce44SJohn Forte bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8); 576*fcf3ce44SJohn Forte nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0); 577*fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0); 578*fcf3ce44SJohn Forte } 579*fcf3ce44SJohn Forte 580*fcf3ce44SJohn Forte /* Reset initialization control blocks. */ 581*fcf3ce44SJohn Forte bzero((void *)icb, sizeof (ql_init_cb_t)); 582*fcf3ce44SJohn Forte 583*fcf3ce44SJohn Forte /* Get driver properties. */ 584*fcf3ce44SJohn Forte ql_23_properties(ha, nv); 585*fcf3ce44SJohn Forte 586*fcf3ce44SJohn Forte cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x" 587*fcf3ce44SJohn Forte "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n", 588*fcf3ce44SJohn Forte QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1], 589*fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 590*fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7], 591*fcf3ce44SJohn Forte nv->node_name[0], nv->node_name[1], nv->node_name[2], 592*fcf3ce44SJohn Forte nv->node_name[3], nv->node_name[4], nv->node_name[5], 593*fcf3ce44SJohn Forte nv->node_name[6], nv->node_name[7]); 594*fcf3ce44SJohn Forte 595*fcf3ce44SJohn Forte /* 596*fcf3ce44SJohn Forte * Copy over NVRAM RISC parameter block 597*fcf3ce44SJohn Forte * to initialization control block. 598*fcf3ce44SJohn Forte */ 599*fcf3ce44SJohn Forte dptr1 = (caddr_t)icb; 600*fcf3ce44SJohn Forte dptr2 = (caddr_t)&nv->parameter_block_version; 601*fcf3ce44SJohn Forte cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] - 602*fcf3ce44SJohn Forte (uintptr_t)&icb->version); 603*fcf3ce44SJohn Forte while (cnt-- != 0) { 604*fcf3ce44SJohn Forte *dptr1++ = *dptr2++; 605*fcf3ce44SJohn Forte } 606*fcf3ce44SJohn Forte 607*fcf3ce44SJohn Forte /* Copy 2nd half. */ 608*fcf3ce44SJohn Forte dptr1 = (caddr_t)&icb->add_fw_opt[0]; 609*fcf3ce44SJohn Forte cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] - 610*fcf3ce44SJohn Forte (uintptr_t)&icb->add_fw_opt[0]); 611*fcf3ce44SJohn Forte 612*fcf3ce44SJohn Forte while (cnt-- != 0) { 613*fcf3ce44SJohn Forte *dptr1++ = *dptr2++; 614*fcf3ce44SJohn Forte } 615*fcf3ce44SJohn Forte 616*fcf3ce44SJohn Forte /* 617*fcf3ce44SJohn Forte * Setup driver firmware options. 618*fcf3ce44SJohn Forte */ 619*fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 620*fcf3ce44SJohn Forte (icb->firmware_options[0] | BIT_6 | BIT_1); 621*fcf3ce44SJohn Forte 622*fcf3ce44SJohn Forte /* 623*fcf3ce44SJohn Forte * There is no use enabling fast post for SBUS or 2300 624*fcf3ce44SJohn Forte */ 625*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_SBUS_CARD | CFG_CTRL_2300 | CFG_CTRL_6322))) { 626*fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 627*fcf3ce44SJohn Forte (icb->firmware_options[0] & ~BIT_3); 628*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 629*fcf3ce44SJohn Forte icb->special_options[0] = (uint8_t) 630*fcf3ce44SJohn Forte (icb->special_options[0] | BIT_5); 631*fcf3ce44SJohn Forte } 632*fcf3ce44SJohn Forte } else { 633*fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 634*fcf3ce44SJohn Forte (icb->firmware_options[0] | BIT_3); 635*fcf3ce44SJohn Forte } 636*fcf3ce44SJohn Forte /* RIO and ZIO not supported. */ 637*fcf3ce44SJohn Forte icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] & 638*fcf3ce44SJohn Forte ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); 639*fcf3ce44SJohn Forte 640*fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] | 641*fcf3ce44SJohn Forte BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0); 642*fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 643*fcf3ce44SJohn Forte (icb->firmware_options[0] & ~(BIT_5 | BIT_4)); 644*fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t) 645*fcf3ce44SJohn Forte (icb->firmware_options[1] & ~BIT_4); 646*fcf3ce44SJohn Forte 647*fcf3ce44SJohn Forte icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4)); 648*fcf3ce44SJohn Forte icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1); 649*fcf3ce44SJohn Forte 650*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 651*fcf3ce44SJohn Forte if ((icb->special_options[1] & 0x20) == 0) { 652*fcf3ce44SJohn Forte EL(ha, "50 ohm is not set\n"); 653*fcf3ce44SJohn Forte } 654*fcf3ce44SJohn Forte } 655*fcf3ce44SJohn Forte icb->execution_throttle[0] = 0xff; 656*fcf3ce44SJohn Forte icb->execution_throttle[1] = 0xff; 657*fcf3ce44SJohn Forte 658*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_TARGET_MODE_ENABLE)) { 659*fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 660*fcf3ce44SJohn Forte (icb->firmware_options[0] | BIT_4 | BIT_7); 661*fcf3ce44SJohn Forte icb->inquiry = 0x1F; 662*fcf3ce44SJohn Forte EL(ha, "Target mode enabled"); 663*fcf3ce44SJohn Forte } 664*fcf3ce44SJohn Forte 665*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) { 666*fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t) 667*fcf3ce44SJohn Forte (icb->firmware_options[1] | BIT_7 | BIT_6); 668*fcf3ce44SJohn Forte icb->add_fw_opt[1] = (uint8_t) 669*fcf3ce44SJohn Forte (icb->add_fw_opt[1] | BIT_5 | BIT_4); 670*fcf3ce44SJohn Forte } 671*fcf3ce44SJohn Forte 672*fcf3ce44SJohn Forte /* 673*fcf3ce44SJohn Forte * Set host adapter parameters 674*fcf3ce44SJohn Forte */ 675*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 676*fcf3ce44SJohn Forte ha->nvram_version = nv->nvram_version; 677*fcf3ce44SJohn Forte ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0], 678*fcf3ce44SJohn Forte nv->adapter_features[1]); 679*fcf3ce44SJohn Forte 680*fcf3ce44SJohn Forte nv->host_p[0] & BIT_4 ? (ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD) : 681*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_DISABLE_RISC_CODE_LOAD); 682*fcf3ce44SJohn Forte nv->host_p[0] & BIT_5 ? (ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1) : 683*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_SET_CACHE_LINE_SIZE_1); 684*fcf3ce44SJohn Forte 685*fcf3ce44SJohn Forte /* Always enable 64bit addressing, except SBUS cards. */ 686*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 687*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING; 688*fcf3ce44SJohn Forte ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS; 689*fcf3ce44SJohn Forte ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS; 690*fcf3ce44SJohn Forte } else { 691*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING; 692*fcf3ce44SJohn Forte ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS; 693*fcf3ce44SJohn Forte ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS; 694*fcf3ce44SJohn Forte } 695*fcf3ce44SJohn Forte 696*fcf3ce44SJohn Forte nv->host_p[1] & BIT_1 ? (ha->cfg_flags |= CFG_ENABLE_LIP_RESET) : 697*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET); 698*fcf3ce44SJohn Forte nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) : 699*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN); 700*fcf3ce44SJohn Forte nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) : 701*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET); 702*fcf3ce44SJohn Forte 703*fcf3ce44SJohn Forte nv->adapter_features[0] & BIT_3 ? 704*fcf3ce44SJohn Forte (ha->cfg_flags |= CFG_MULTI_CHIP_ADAPTER) : 705*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_MULTI_CHIP_ADAPTER); 706*fcf3ce44SJohn Forte 707*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 708*fcf3ce44SJohn Forte 709*fcf3ce44SJohn Forte ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0], 710*fcf3ce44SJohn Forte nv->execution_throttle[1]); 711*fcf3ce44SJohn Forte ha->loop_reset_delay = nv->reset_delay; 712*fcf3ce44SJohn Forte ha->port_down_retry_count = nv->port_down_retry_count; 713*fcf3ce44SJohn Forte ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ? 714*fcf3ce44SJohn Forte R_A_TOV_DEFAULT : icb->login_timeout); 715*fcf3ce44SJohn Forte ha->maximum_luns_per_target = CHAR_TO_SHORT( 716*fcf3ce44SJohn Forte nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]); 717*fcf3ce44SJohn Forte if (ha->maximum_luns_per_target == 0) { 718*fcf3ce44SJohn Forte ha->maximum_luns_per_target++; 719*fcf3ce44SJohn Forte } 720*fcf3ce44SJohn Forte 721*fcf3ce44SJohn Forte /* 722*fcf3ce44SJohn Forte * Setup ring parameters in initialization control block 723*fcf3ce44SJohn Forte */ 724*fcf3ce44SJohn Forte cnt = REQUEST_ENTRY_CNT; 725*fcf3ce44SJohn Forte icb->request_q_length[0] = LSB(cnt); 726*fcf3ce44SJohn Forte icb->request_q_length[1] = MSB(cnt); 727*fcf3ce44SJohn Forte cnt = RESPONSE_ENTRY_CNT; 728*fcf3ce44SJohn Forte icb->response_q_length[0] = LSB(cnt); 729*fcf3ce44SJohn Forte icb->response_q_length[1] = MSB(cnt); 730*fcf3ce44SJohn Forte 731*fcf3ce44SJohn Forte icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma))); 732*fcf3ce44SJohn Forte icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma))); 733*fcf3ce44SJohn Forte icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma))); 734*fcf3ce44SJohn Forte icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma))); 735*fcf3ce44SJohn Forte icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma))); 736*fcf3ce44SJohn Forte icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma))); 737*fcf3ce44SJohn Forte icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma))); 738*fcf3ce44SJohn Forte icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma))); 739*fcf3ce44SJohn Forte 740*fcf3ce44SJohn Forte icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma))); 741*fcf3ce44SJohn Forte icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma))); 742*fcf3ce44SJohn Forte icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma))); 743*fcf3ce44SJohn Forte icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma))); 744*fcf3ce44SJohn Forte icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma))); 745*fcf3ce44SJohn Forte icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma))); 746*fcf3ce44SJohn Forte icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma))); 747*fcf3ce44SJohn Forte icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma))); 748*fcf3ce44SJohn Forte 749*fcf3ce44SJohn Forte /* 750*fcf3ce44SJohn Forte * Setup IP initialization control block 751*fcf3ce44SJohn Forte */ 752*fcf3ce44SJohn Forte ip_icb->version = IP_ICB_VERSION; 753*fcf3ce44SJohn Forte 754*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 755*fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 756*fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0); 757*fcf3ce44SJohn Forte } else { 758*fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 759*fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2); 760*fcf3ce44SJohn Forte } 761*fcf3ce44SJohn Forte 762*fcf3ce44SJohn Forte cnt = RCVBUF_CONTAINER_CNT; 763*fcf3ce44SJohn Forte ip_icb->queue_size[0] = LSB(cnt); 764*fcf3ce44SJohn Forte ip_icb->queue_size[1] = MSB(cnt); 765*fcf3ce44SJohn Forte 766*fcf3ce44SJohn Forte ip_icb->queue_address[0] = LSB(LSW(LSD(ha->rcvbuf_dvma))); 767*fcf3ce44SJohn Forte ip_icb->queue_address[1] = MSB(LSW(LSD(ha->rcvbuf_dvma))); 768*fcf3ce44SJohn Forte ip_icb->queue_address[2] = LSB(MSW(LSD(ha->rcvbuf_dvma))); 769*fcf3ce44SJohn Forte ip_icb->queue_address[3] = MSB(MSW(LSD(ha->rcvbuf_dvma))); 770*fcf3ce44SJohn Forte ip_icb->queue_address[4] = LSB(LSW(MSD(ha->rcvbuf_dvma))); 771*fcf3ce44SJohn Forte ip_icb->queue_address[5] = MSB(LSW(MSD(ha->rcvbuf_dvma))); 772*fcf3ce44SJohn Forte ip_icb->queue_address[6] = LSB(MSW(MSD(ha->rcvbuf_dvma))); 773*fcf3ce44SJohn Forte ip_icb->queue_address[7] = MSB(MSW(MSD(ha->rcvbuf_dvma))); 774*fcf3ce44SJohn Forte 775*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 776*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 777*fcf3ce44SJohn Forte } else { 778*fcf3ce44SJohn Forte /*EMPTY*/ 779*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 780*fcf3ce44SJohn Forte } 781*fcf3ce44SJohn Forte return (rval); 782*fcf3ce44SJohn Forte } 783*fcf3ce44SJohn Forte 784*fcf3ce44SJohn Forte /* 785*fcf3ce44SJohn Forte * Get NVRAM data word 786*fcf3ce44SJohn Forte * Calculates word position in NVRAM and calls request routine to 787*fcf3ce44SJohn Forte * get the word from NVRAM. 788*fcf3ce44SJohn Forte * 789*fcf3ce44SJohn Forte * Input: 790*fcf3ce44SJohn Forte * ha = adapter state pointer. 791*fcf3ce44SJohn Forte * address = NVRAM word address. 792*fcf3ce44SJohn Forte * 793*fcf3ce44SJohn Forte * Returns: 794*fcf3ce44SJohn Forte * data word. 795*fcf3ce44SJohn Forte * 796*fcf3ce44SJohn Forte * Context: 797*fcf3ce44SJohn Forte * Kernel context. 798*fcf3ce44SJohn Forte */ 799*fcf3ce44SJohn Forte uint16_t 800*fcf3ce44SJohn Forte ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address) 801*fcf3ce44SJohn Forte { 802*fcf3ce44SJohn Forte uint32_t nv_cmd; 803*fcf3ce44SJohn Forte uint16_t rval; 804*fcf3ce44SJohn Forte 805*fcf3ce44SJohn Forte QL_PRINT_4(CE_CONT, "(%d): started\n", ha->instance); 806*fcf3ce44SJohn Forte 807*fcf3ce44SJohn Forte nv_cmd = address << 16; 808*fcf3ce44SJohn Forte nv_cmd = nv_cmd | NV_READ_OP; 809*fcf3ce44SJohn Forte 810*fcf3ce44SJohn Forte rval = (uint16_t)ql_nvram_request(ha, nv_cmd); 811*fcf3ce44SJohn Forte 812*fcf3ce44SJohn Forte QL_PRINT_4(CE_CONT, "(%d): NVRAM data = %xh\n", ha->instance, rval); 813*fcf3ce44SJohn Forte 814*fcf3ce44SJohn Forte return (rval); 815*fcf3ce44SJohn Forte } 816*fcf3ce44SJohn Forte 817*fcf3ce44SJohn Forte /* 818*fcf3ce44SJohn Forte * NVRAM request 819*fcf3ce44SJohn Forte * Sends read command to NVRAM and gets data from NVRAM. 820*fcf3ce44SJohn Forte * 821*fcf3ce44SJohn Forte * Input: 822*fcf3ce44SJohn Forte * ha = adapter state pointer. 823*fcf3ce44SJohn Forte * nv_cmd = Bit 26= start bit 824*fcf3ce44SJohn Forte * Bit 25, 24 = opcode 825*fcf3ce44SJohn Forte * Bit 23-16 = address 826*fcf3ce44SJohn Forte * Bit 15-0 = write data 827*fcf3ce44SJohn Forte * 828*fcf3ce44SJohn Forte * Returns: 829*fcf3ce44SJohn Forte * data word. 830*fcf3ce44SJohn Forte * 831*fcf3ce44SJohn Forte * Context: 832*fcf3ce44SJohn Forte * Kernel context. 833*fcf3ce44SJohn Forte */ 834*fcf3ce44SJohn Forte static uint16_t 835*fcf3ce44SJohn Forte ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd) 836*fcf3ce44SJohn Forte { 837*fcf3ce44SJohn Forte uint8_t cnt; 838*fcf3ce44SJohn Forte uint16_t reg_data; 839*fcf3ce44SJohn Forte uint16_t data = 0; 840*fcf3ce44SJohn Forte 841*fcf3ce44SJohn Forte /* Send command to NVRAM. */ 842*fcf3ce44SJohn Forte 843*fcf3ce44SJohn Forte nv_cmd <<= 5; 844*fcf3ce44SJohn Forte for (cnt = 0; cnt < 11; cnt++) { 845*fcf3ce44SJohn Forte if (nv_cmd & BIT_31) { 846*fcf3ce44SJohn Forte ql_nv_write(ha, NV_DATA_OUT); 847*fcf3ce44SJohn Forte } else { 848*fcf3ce44SJohn Forte ql_nv_write(ha, 0); 849*fcf3ce44SJohn Forte } 850*fcf3ce44SJohn Forte nv_cmd <<= 1; 851*fcf3ce44SJohn Forte } 852*fcf3ce44SJohn Forte 853*fcf3ce44SJohn Forte /* Read data from NVRAM. */ 854*fcf3ce44SJohn Forte 855*fcf3ce44SJohn Forte for (cnt = 0; cnt < 16; cnt++) { 856*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_SELECT+NV_CLOCK); 857*fcf3ce44SJohn Forte ql_nv_delay(); 858*fcf3ce44SJohn Forte data <<= 1; 859*fcf3ce44SJohn Forte reg_data = RD16_IO_REG(ha, nvram); 860*fcf3ce44SJohn Forte if (reg_data & NV_DATA_IN) { 861*fcf3ce44SJohn Forte data = (uint16_t)(data | BIT_0); 862*fcf3ce44SJohn Forte } 863*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_SELECT); 864*fcf3ce44SJohn Forte ql_nv_delay(); 865*fcf3ce44SJohn Forte } 866*fcf3ce44SJohn Forte 867*fcf3ce44SJohn Forte /* Deselect chip. */ 868*fcf3ce44SJohn Forte 869*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_DESELECT); 870*fcf3ce44SJohn Forte ql_nv_delay(); 871*fcf3ce44SJohn Forte 872*fcf3ce44SJohn Forte return (data); 873*fcf3ce44SJohn Forte } 874*fcf3ce44SJohn Forte 875*fcf3ce44SJohn Forte void 876*fcf3ce44SJohn Forte ql_nv_write(ql_adapter_state_t *ha, uint16_t data) 877*fcf3ce44SJohn Forte { 878*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT)); 879*fcf3ce44SJohn Forte ql_nv_delay(); 880*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK)); 881*fcf3ce44SJohn Forte ql_nv_delay(); 882*fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT)); 883*fcf3ce44SJohn Forte ql_nv_delay(); 884*fcf3ce44SJohn Forte } 885*fcf3ce44SJohn Forte 886*fcf3ce44SJohn Forte void 887*fcf3ce44SJohn Forte ql_nv_delay(void) { 888*fcf3ce44SJohn Forte drv_usecwait(NV_DELAY_COUNT); 889*fcf3ce44SJohn Forte } 890*fcf3ce44SJohn Forte 891*fcf3ce44SJohn Forte /* 892*fcf3ce44SJohn Forte * ql_nvram_24xx_config 893*fcf3ce44SJohn Forte * ISP2400 nvram. 894*fcf3ce44SJohn Forte * 895*fcf3ce44SJohn Forte * Input: 896*fcf3ce44SJohn Forte * ha: adapter state pointer. 897*fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 898*fcf3ce44SJohn Forte * 899*fcf3ce44SJohn Forte * Output: 900*fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 901*fcf3ce44SJohn Forte * host adapters parameters in host adapter block 902*fcf3ce44SJohn Forte * 903*fcf3ce44SJohn Forte * Returns: 904*fcf3ce44SJohn Forte * ql local function return status code. 905*fcf3ce44SJohn Forte * 906*fcf3ce44SJohn Forte * Context: 907*fcf3ce44SJohn Forte * Kernel context. 908*fcf3ce44SJohn Forte */ 909*fcf3ce44SJohn Forte int 910*fcf3ce44SJohn Forte ql_nvram_24xx_config(ql_adapter_state_t *ha) 911*fcf3ce44SJohn Forte { 912*fcf3ce44SJohn Forte uint32_t index, addr, chksum, saved_chksum; 913*fcf3ce44SJohn Forte uint32_t *longptr; 914*fcf3ce44SJohn Forte nvram_24xx_t nvram; 915*fcf3ce44SJohn Forte int idpromlen; 916*fcf3ce44SJohn Forte char idprombuf[32]; 917*fcf3ce44SJohn Forte caddr_t src, dst; 918*fcf3ce44SJohn Forte uint16_t w1; 919*fcf3ce44SJohn Forte int rval; 920*fcf3ce44SJohn Forte nvram_24xx_t *nv = (nvram_24xx_t *)&nvram; 921*fcf3ce44SJohn Forte ql_init_24xx_cb_t *icb = 922*fcf3ce44SJohn Forte (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24; 923*fcf3ce44SJohn Forte ql_ip_init_24xx_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb24; 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 926*fcf3ce44SJohn Forte 927*fcf3ce44SJohn Forte if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) { 928*fcf3ce44SJohn Forte 929*fcf3ce44SJohn Forte /* Get NVRAM data and calculate checksum. */ 930*fcf3ce44SJohn Forte longptr = (uint32_t *)nv; 931*fcf3ce44SJohn Forte chksum = saved_chksum = 0; 932*fcf3ce44SJohn Forte for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) { 933*fcf3ce44SJohn Forte rval = ql_24xx_read_flash(ha, addr++, longptr); 934*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 935*fcf3ce44SJohn Forte EL(ha, "24xx_read_flash failed=%xh\n", rval); 936*fcf3ce44SJohn Forte break; 937*fcf3ce44SJohn Forte } 938*fcf3ce44SJohn Forte saved_chksum = chksum; 939*fcf3ce44SJohn Forte chksum += *longptr; 940*fcf3ce44SJohn Forte LITTLE_ENDIAN_32(longptr); 941*fcf3ce44SJohn Forte longptr++; 942*fcf3ce44SJohn Forte } 943*fcf3ce44SJohn Forte 944*fcf3ce44SJohn Forte ql_release_nvram(ha); 945*fcf3ce44SJohn Forte } 946*fcf3ce44SJohn Forte 947*fcf3ce44SJohn Forte /* Bad NVRAM data, set defaults parameters. */ 948*fcf3ce44SJohn Forte if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' || 949*fcf3ce44SJohn Forte nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || 950*fcf3ce44SJohn Forte (nv->nvram_version[0] | nv->nvram_version[1]) == 0) { 951*fcf3ce44SJohn Forte 952*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using " 953*fcf3ce44SJohn Forte "driver defaults.", QL_NAME, ha->instance); 954*fcf3ce44SJohn Forte 955*fcf3ce44SJohn Forte EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, " 956*fcf3ce44SJohn Forte "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1], 957*fcf3ce44SJohn Forte nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0], 958*fcf3ce44SJohn Forte nv->nvram_version[1])); 959*fcf3ce44SJohn Forte 960*fcf3ce44SJohn Forte saved_chksum = ~saved_chksum + 1; 961*fcf3ce44SJohn Forte 962*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0, 963*fcf3ce44SJohn Forte MSW(saved_chksum), LSW(saved_chksum)); 964*fcf3ce44SJohn Forte 965*fcf3ce44SJohn Forte /* Reset NVRAM data. */ 966*fcf3ce44SJohn Forte bzero((void *)nv, sizeof (nvram_24xx_t)); 967*fcf3ce44SJohn Forte 968*fcf3ce44SJohn Forte /* 969*fcf3ce44SJohn Forte * Set default initialization control block. 970*fcf3ce44SJohn Forte */ 971*fcf3ce44SJohn Forte nv->nvram_version[0] = LSB(ICB_24XX_VERSION); 972*fcf3ce44SJohn Forte nv->nvram_version[1] = MSB(ICB_24XX_VERSION); 973*fcf3ce44SJohn Forte 974*fcf3ce44SJohn Forte nv->version[0] = 1; 975*fcf3ce44SJohn Forte nv->max_frame_length[1] = 8; 976*fcf3ce44SJohn Forte nv->execution_throttle[0] = 16; 977*fcf3ce44SJohn Forte nv->max_luns_per_target[0] = 8; 978*fcf3ce44SJohn Forte 979*fcf3ce44SJohn Forte idpromlen = 32; 980*fcf3ce44SJohn Forte 981*fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 982*fcf3ce44SJohn Forte if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip, 983*fcf3ce44SJohn Forte DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf, 984*fcf3ce44SJohn Forte &idpromlen) != DDI_PROP_SUCCESS) { 985*fcf3ce44SJohn Forte 986*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) : Unable to read idprom " 987*fcf3ce44SJohn Forte "property", QL_NAME, ha->instance); 988*fcf3ce44SJohn Forte 989*fcf3ce44SJohn Forte nv->port_name[0] = 33; 990*fcf3ce44SJohn Forte nv->port_name[3] = 224; 991*fcf3ce44SJohn Forte nv->port_name[4] = 139; 992*fcf3ce44SJohn Forte nv->port_name[7] = (uint8_t) 993*fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 994*fcf3ce44SJohn Forte 995*fcf3ce44SJohn Forte } else { 996*fcf3ce44SJohn Forte nv->port_name[2] = idprombuf[2]; 997*fcf3ce44SJohn Forte nv->port_name[3] = idprombuf[3]; 998*fcf3ce44SJohn Forte nv->port_name[4] = idprombuf[4]; 999*fcf3ce44SJohn Forte nv->port_name[5] = idprombuf[5]; 1000*fcf3ce44SJohn Forte nv->port_name[6] = idprombuf[6]; 1001*fcf3ce44SJohn Forte nv->port_name[7] = idprombuf[7]; 1002*fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t) 1003*fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 1004*fcf3ce44SJohn Forte 1005*fcf3ce44SJohn Forte } 1006*fcf3ce44SJohn Forte 1007*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default " 1008*fcf3ce44SJohn Forte "HBA parameters and temporary " 1009*fcf3ce44SJohn Forte "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME, 1010*fcf3ce44SJohn Forte ha->instance, nv->port_name[0], nv->port_name[1], 1011*fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 1012*fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7]); 1013*fcf3ce44SJohn Forte 1014*fcf3ce44SJohn Forte 1015*fcf3ce44SJohn Forte nv->login_retry_count[0] = 8; 1016*fcf3ce44SJohn Forte 1017*fcf3ce44SJohn Forte nv->firmware_options_1[0] = BIT_2 | BIT_1; 1018*fcf3ce44SJohn Forte nv->firmware_options_1[1] = BIT_5; 1019*fcf3ce44SJohn Forte nv->firmware_options_2[0] = BIT_5; 1020*fcf3ce44SJohn Forte nv->firmware_options_2[1] = BIT_4; 1021*fcf3ce44SJohn Forte nv->firmware_options_3[1] = BIT_6; 1022*fcf3ce44SJohn Forte 1023*fcf3ce44SJohn Forte /* 1024*fcf3ce44SJohn Forte * Set default host adapter parameters 1025*fcf3ce44SJohn Forte */ 1026*fcf3ce44SJohn Forte nv->host_p[0] = BIT_4 | BIT_1; 1027*fcf3ce44SJohn Forte nv->host_p[1] = BIT_3 | BIT_2; 1028*fcf3ce44SJohn Forte nv->reset_delay = 5; 1029*fcf3ce44SJohn Forte nv->max_luns_per_target[0] = 128; 1030*fcf3ce44SJohn Forte nv->port_down_retry_count[0] = 30; 1031*fcf3ce44SJohn Forte nv->link_down_timeout[0] = 30; 1032*fcf3ce44SJohn Forte 1033*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 1034*fcf3ce44SJohn Forte } 1035*fcf3ce44SJohn Forte 1036*fcf3ce44SJohn Forte /* Check for adapter node name (big endian). */ 1037*fcf3ce44SJohn Forte for (index = 0; index < 8; index++) { 1038*fcf3ce44SJohn Forte if (nv->node_name[index] != 0) { 1039*fcf3ce44SJohn Forte break; 1040*fcf3ce44SJohn Forte } 1041*fcf3ce44SJohn Forte } 1042*fcf3ce44SJohn Forte 1043*fcf3ce44SJohn Forte /* Copy port name if no node name (big endian). */ 1044*fcf3ce44SJohn Forte if (index == 8) { 1045*fcf3ce44SJohn Forte bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8); 1046*fcf3ce44SJohn Forte nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0); 1047*fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0); 1048*fcf3ce44SJohn Forte } 1049*fcf3ce44SJohn Forte 1050*fcf3ce44SJohn Forte /* Reset initialization control blocks. */ 1051*fcf3ce44SJohn Forte bzero((void *)icb, sizeof (ql_init_24xx_cb_t)); 1052*fcf3ce44SJohn Forte 1053*fcf3ce44SJohn Forte /* Get driver properties. */ 1054*fcf3ce44SJohn Forte ql_24xx_properties(ha, nv); 1055*fcf3ce44SJohn Forte 1056*fcf3ce44SJohn Forte cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x" 1057*fcf3ce44SJohn Forte "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n", 1058*fcf3ce44SJohn Forte QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1], 1059*fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 1060*fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7], 1061*fcf3ce44SJohn Forte nv->node_name[0], nv->node_name[1], nv->node_name[2], 1062*fcf3ce44SJohn Forte nv->node_name[3], nv->node_name[4], nv->node_name[5], 1063*fcf3ce44SJohn Forte nv->node_name[6], nv->node_name[7]); 1064*fcf3ce44SJohn Forte 1065*fcf3ce44SJohn Forte /* 1066*fcf3ce44SJohn Forte * Copy over NVRAM Firmware Initialization Control Block. 1067*fcf3ce44SJohn Forte */ 1068*fcf3ce44SJohn Forte dst = (caddr_t)icb; 1069*fcf3ce44SJohn Forte src = (caddr_t)&nv->version; 1070*fcf3ce44SJohn Forte index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] - 1071*fcf3ce44SJohn Forte (uintptr_t)icb); 1072*fcf3ce44SJohn Forte while (index--) { 1073*fcf3ce44SJohn Forte *dst++ = *src++; 1074*fcf3ce44SJohn Forte } 1075*fcf3ce44SJohn Forte icb->login_retry_count[0] = nv->login_retry_count[0]; 1076*fcf3ce44SJohn Forte icb->login_retry_count[1] = nv->login_retry_count[1]; 1077*fcf3ce44SJohn Forte icb->link_down_on_nos[0] = nv->link_down_on_nos[0]; 1078*fcf3ce44SJohn Forte icb->link_down_on_nos[1] = nv->link_down_on_nos[1]; 1079*fcf3ce44SJohn Forte 1080*fcf3ce44SJohn Forte dst = (caddr_t)&icb->interrupt_delay_timer; 1081*fcf3ce44SJohn Forte src = (caddr_t)&nv->interrupt_delay_timer; 1082*fcf3ce44SJohn Forte index = (uint32_t)((uintptr_t)&icb->reserved_3 - 1083*fcf3ce44SJohn Forte (uintptr_t)&icb->interrupt_delay_timer); 1084*fcf3ce44SJohn Forte while (index--) { 1085*fcf3ce44SJohn Forte *dst++ = *src++; 1086*fcf3ce44SJohn Forte } 1087*fcf3ce44SJohn Forte 1088*fcf3ce44SJohn Forte /* 1089*fcf3ce44SJohn Forte * Setup driver firmware options. 1090*fcf3ce44SJohn Forte */ 1091*fcf3ce44SJohn Forte icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] & 1092*fcf3ce44SJohn Forte ~(BIT_5 | BIT_4)); 1093*fcf3ce44SJohn Forte icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] | 1094*fcf3ce44SJohn Forte BIT_6 | BIT_5 | BIT_2); 1095*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_TARGET_MODE_ENABLE)) { 1096*fcf3ce44SJohn Forte icb->firmware_options_1[0] = (uint8_t) 1097*fcf3ce44SJohn Forte (icb->firmware_options_1[0] | BIT_4 | BIT_1); 1098*fcf3ce44SJohn Forte EL(ha, "Target mode enabled\n"); 1099*fcf3ce44SJohn Forte } else { 1100*fcf3ce44SJohn Forte icb->firmware_options_1[0] = (uint8_t) 1101*fcf3ce44SJohn Forte (icb->firmware_options_1[0] | BIT_1); 1102*fcf3ce44SJohn Forte } 1103*fcf3ce44SJohn Forte 1104*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) { 1105*fcf3ce44SJohn Forte icb->firmware_options_2[1] = (uint8_t) 1106*fcf3ce44SJohn Forte (icb->firmware_options_2[1] | BIT_4); 1107*fcf3ce44SJohn Forte } else { 1108*fcf3ce44SJohn Forte icb->firmware_options_2[1] = (uint8_t) 1109*fcf3ce44SJohn Forte (icb->firmware_options_2[1] & ~BIT_4); 1110*fcf3ce44SJohn Forte } 1111*fcf3ce44SJohn Forte 1112*fcf3ce44SJohn Forte icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] | 1113*fcf3ce44SJohn Forte BIT_1); 1114*fcf3ce44SJohn Forte icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] & 1115*fcf3ce44SJohn Forte ~BIT_7); 1116*fcf3ce44SJohn Forte 1117*fcf3ce44SJohn Forte icb->execution_throttle[0] = 0xff; 1118*fcf3ce44SJohn Forte icb->execution_throttle[1] = 0xff; 1119*fcf3ce44SJohn Forte 1120*fcf3ce44SJohn Forte /* 1121*fcf3ce44SJohn Forte * Set host adapter parameters 1122*fcf3ce44SJohn Forte */ 1123*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1124*fcf3ce44SJohn Forte ha->nvram_version = CHAR_TO_SHORT(nv->nvram_version[0], 1125*fcf3ce44SJohn Forte nv->nvram_version[1]); 1126*fcf3ce44SJohn Forte nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) : 1127*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN); 1128*fcf3ce44SJohn Forte nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) : 1129*fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET); 1130*fcf3ce44SJohn Forte ha->cfg_flags &= ~(CFG_DISABLE_RISC_CODE_LOAD | 1131*fcf3ce44SJohn Forte CFG_SET_CACHE_LINE_SIZE_1 | CFG_MULTI_CHIP_ADAPTER); 1132*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING; 1133*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1134*fcf3ce44SJohn Forte 1135*fcf3ce44SJohn Forte ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS; 1136*fcf3ce44SJohn Forte ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS; 1137*fcf3ce44SJohn Forte 1138*fcf3ce44SJohn Forte ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0], 1139*fcf3ce44SJohn Forte nv->execution_throttle[1]); 1140*fcf3ce44SJohn Forte ha->loop_reset_delay = nv->reset_delay; 1141*fcf3ce44SJohn Forte ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0], 1142*fcf3ce44SJohn Forte nv->port_down_retry_count[1]); 1143*fcf3ce44SJohn Forte w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]); 1144*fcf3ce44SJohn Forte ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1); 1145*fcf3ce44SJohn Forte ha->maximum_luns_per_target = CHAR_TO_SHORT( 1146*fcf3ce44SJohn Forte nv->max_luns_per_target[0], nv->max_luns_per_target[1]); 1147*fcf3ce44SJohn Forte if (ha->maximum_luns_per_target == 0) { 1148*fcf3ce44SJohn Forte ha->maximum_luns_per_target++; 1149*fcf3ce44SJohn Forte } 1150*fcf3ce44SJohn Forte 1151*fcf3ce44SJohn Forte /* ISP2422 Serial Link Control */ 1152*fcf3ce44SJohn Forte ha->serdes_param[0] = CHAR_TO_SHORT(nv->swing_opt[0], 1153*fcf3ce44SJohn Forte nv->swing_opt[1]); 1154*fcf3ce44SJohn Forte ha->serdes_param[1] = CHAR_TO_SHORT(nv->swing_1g[0], nv->swing_1g[1]); 1155*fcf3ce44SJohn Forte ha->serdes_param[2] = CHAR_TO_SHORT(nv->swing_2g[0], nv->swing_2g[1]); 1156*fcf3ce44SJohn Forte ha->serdes_param[3] = CHAR_TO_SHORT(nv->swing_4g[0], nv->swing_4g[1]); 1157*fcf3ce44SJohn Forte 1158*fcf3ce44SJohn Forte /* 1159*fcf3ce44SJohn Forte * Setup ring parameters in initialization control block 1160*fcf3ce44SJohn Forte */ 1161*fcf3ce44SJohn Forte w1 = REQUEST_ENTRY_CNT; 1162*fcf3ce44SJohn Forte icb->request_q_length[0] = LSB(w1); 1163*fcf3ce44SJohn Forte icb->request_q_length[1] = MSB(w1); 1164*fcf3ce44SJohn Forte w1 = RESPONSE_ENTRY_CNT; 1165*fcf3ce44SJohn Forte icb->response_q_length[0] = LSB(w1); 1166*fcf3ce44SJohn Forte icb->response_q_length[1] = MSB(w1); 1167*fcf3ce44SJohn Forte 1168*fcf3ce44SJohn Forte icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma))); 1169*fcf3ce44SJohn Forte icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma))); 1170*fcf3ce44SJohn Forte icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma))); 1171*fcf3ce44SJohn Forte icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma))); 1172*fcf3ce44SJohn Forte icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma))); 1173*fcf3ce44SJohn Forte icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma))); 1174*fcf3ce44SJohn Forte icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma))); 1175*fcf3ce44SJohn Forte icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma))); 1176*fcf3ce44SJohn Forte 1177*fcf3ce44SJohn Forte icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma))); 1178*fcf3ce44SJohn Forte icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma))); 1179*fcf3ce44SJohn Forte icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma))); 1180*fcf3ce44SJohn Forte icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma))); 1181*fcf3ce44SJohn Forte icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma))); 1182*fcf3ce44SJohn Forte icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma))); 1183*fcf3ce44SJohn Forte icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma))); 1184*fcf3ce44SJohn Forte icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma))); 1185*fcf3ce44SJohn Forte 1186*fcf3ce44SJohn Forte /* 1187*fcf3ce44SJohn Forte * Setup IP initialization control block 1188*fcf3ce44SJohn Forte */ 1189*fcf3ce44SJohn Forte ip_icb->version = IP_ICB_24XX_VERSION; 1190*fcf3ce44SJohn Forte 1191*fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 1192*fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2); 1193*fcf3ce44SJohn Forte 1194*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1195*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 1196*fcf3ce44SJohn Forte } else { 1197*fcf3ce44SJohn Forte /*EMPTY*/ 1198*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1199*fcf3ce44SJohn Forte } 1200*fcf3ce44SJohn Forte return (rval); 1201*fcf3ce44SJohn Forte } 1202*fcf3ce44SJohn Forte 1203*fcf3ce44SJohn Forte /* 1204*fcf3ce44SJohn Forte * ql_lock_nvram 1205*fcf3ce44SJohn Forte * Locks NVRAM access and returns starting address of NVRAM. 1206*fcf3ce44SJohn Forte * 1207*fcf3ce44SJohn Forte * Input: 1208*fcf3ce44SJohn Forte * ha: adapter state pointer. 1209*fcf3ce44SJohn Forte * addr: pointer for start address. 1210*fcf3ce44SJohn Forte * flags: Are mutually exclusive: 1211*fcf3ce44SJohn Forte * LNF_NVRAM_DATA --> get nvram 1212*fcf3ce44SJohn Forte * LNF_VPD_DATA --> get vpd data (24/25xx only). 1213*fcf3ce44SJohn Forte * 1214*fcf3ce44SJohn Forte * Returns: 1215*fcf3ce44SJohn Forte * ql local function return status code. 1216*fcf3ce44SJohn Forte * 1217*fcf3ce44SJohn Forte * Context: 1218*fcf3ce44SJohn Forte * Kernel context. 1219*fcf3ce44SJohn Forte */ 1220*fcf3ce44SJohn Forte int 1221*fcf3ce44SJohn Forte ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags) 1222*fcf3ce44SJohn Forte { 1223*fcf3ce44SJohn Forte int i; 1224*fcf3ce44SJohn Forte 1225*fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) { 1226*fcf3ce44SJohn Forte EL(ha, "invalid options for function"); 1227*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1228*fcf3ce44SJohn Forte } 1229*fcf3ce44SJohn Forte 1230*fcf3ce44SJohn Forte if (ha->device_id == 0x2312 || ha->device_id == 0x2322) { 1231*fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) == 0) { 1232*fcf3ce44SJohn Forte EL(ha, "invalid 2312/2322 option for HBA"); 1233*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1234*fcf3ce44SJohn Forte } 1235*fcf3ce44SJohn Forte 1236*fcf3ce44SJohn Forte /* if function number is non-zero, then adjust offset */ 1237*fcf3ce44SJohn Forte *addr = RD16_IO_REG(ha, ctrl_status) & 0xc000 ? 128 : 0; 1238*fcf3ce44SJohn Forte 1239*fcf3ce44SJohn Forte /* Try to get resource lock. Wait for 10 seconds max */ 1240*fcf3ce44SJohn Forte for (i = 0; i < 10000; i++) { 1241*fcf3ce44SJohn Forte /* if nvram busy bit is reset, acquire sema */ 1242*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) { 1243*fcf3ce44SJohn Forte WRT16_IO_REG(ha, host_to_host_sema, 1); 1244*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 1245*fcf3ce44SJohn Forte if (RD16_IO_REG(ha, host_to_host_sema) & 1) { 1246*fcf3ce44SJohn Forte break; 1247*fcf3ce44SJohn Forte } 1248*fcf3ce44SJohn Forte } 1249*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 1250*fcf3ce44SJohn Forte } 1251*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) { 1252*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock", 1253*fcf3ce44SJohn Forte QL_NAME, ha->instance); 1254*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1255*fcf3ce44SJohn Forte } 1256*fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_CTRL_2422)) { 1257*fcf3ce44SJohn Forte if (flags & LNF_VPD_DATA) { 1258*fcf3ce44SJohn Forte *addr = RD32_IO_REG(ha, ctrl_status) & 1259*fcf3ce44SJohn Forte FUNCTION_NUMBER ? VPD_24XX_FUNC1_ADDR : 1260*fcf3ce44SJohn Forte VPD_24XX_FUNC0_ADDR; 1261*fcf3ce44SJohn Forte } else if (flags & LNF_NVRAM_DATA) { 1262*fcf3ce44SJohn Forte *addr = RD32_IO_REG(ha, ctrl_status) & 1263*fcf3ce44SJohn Forte FUNCTION_NUMBER ? NVRAM_24XX_FUNC1_ADDR : 1264*fcf3ce44SJohn Forte NVRAM_24XX_FUNC0_ADDR; 1265*fcf3ce44SJohn Forte } else { 1266*fcf3ce44SJohn Forte EL(ha, "invalid 24xx option for HBA"); 1267*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1268*fcf3ce44SJohn Forte } 1269*fcf3ce44SJohn Forte 1270*fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1271*fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_CTRL_25XX)) { 1272*fcf3ce44SJohn Forte if (flags & LNF_VPD_DATA) { 1273*fcf3ce44SJohn Forte *addr = RD32_IO_REG(ha, ctrl_status) & 1274*fcf3ce44SJohn Forte FUNCTION_NUMBER ? VPD_25XX_FUNC1_ADDR : 1275*fcf3ce44SJohn Forte VPD_25XX_FUNC0_ADDR; 1276*fcf3ce44SJohn Forte } else if (flags & LNF_NVRAM_DATA) { 1277*fcf3ce44SJohn Forte *addr = RD32_IO_REG(ha, ctrl_status) & 1278*fcf3ce44SJohn Forte FUNCTION_NUMBER ? NVRAM_25XX_FUNC1_ADDR : 1279*fcf3ce44SJohn Forte NVRAM_25XX_FUNC0_ADDR; 1280*fcf3ce44SJohn Forte } else { 1281*fcf3ce44SJohn Forte EL(ha, "invalid 25xx option for HBA"); 1282*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1283*fcf3ce44SJohn Forte } 1284*fcf3ce44SJohn Forte 1285*fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1286*fcf3ce44SJohn Forte } else { 1287*fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) == 0) { 1288*fcf3ce44SJohn Forte EL(ha, "invalid option for HBA"); 1289*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1290*fcf3ce44SJohn Forte } 1291*fcf3ce44SJohn Forte *addr = 0; 1292*fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1293*fcf3ce44SJohn Forte } 1294*fcf3ce44SJohn Forte 1295*fcf3ce44SJohn Forte return (QL_SUCCESS); 1296*fcf3ce44SJohn Forte } 1297*fcf3ce44SJohn Forte 1298*fcf3ce44SJohn Forte /* 1299*fcf3ce44SJohn Forte * ql_release_nvram 1300*fcf3ce44SJohn Forte * Releases NVRAM access. 1301*fcf3ce44SJohn Forte * 1302*fcf3ce44SJohn Forte * Input: 1303*fcf3ce44SJohn Forte * ha: adapter state pointer. 1304*fcf3ce44SJohn Forte * 1305*fcf3ce44SJohn Forte * Context: 1306*fcf3ce44SJohn Forte * Kernel context. 1307*fcf3ce44SJohn Forte */ 1308*fcf3ce44SJohn Forte void 1309*fcf3ce44SJohn Forte ql_release_nvram(ql_adapter_state_t *ha) 1310*fcf3ce44SJohn Forte { 1311*fcf3ce44SJohn Forte if (ha->device_id == 0x2312 || ha->device_id == 0x2322) { 1312*fcf3ce44SJohn Forte /* Release resource lock */ 1313*fcf3ce44SJohn Forte WRT16_IO_REG(ha, host_to_host_sema, 0); 1314*fcf3ce44SJohn Forte } else { 1315*fcf3ce44SJohn Forte GLOBAL_HW_UNLOCK(); 1316*fcf3ce44SJohn Forte } 1317*fcf3ce44SJohn Forte } 1318*fcf3ce44SJohn Forte 1319*fcf3ce44SJohn Forte /* 1320*fcf3ce44SJohn Forte * ql_23_properties 1321*fcf3ce44SJohn Forte * Copies driver properties to NVRAM or adapter structure. 1322*fcf3ce44SJohn Forte * 1323*fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1324*fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1325*fcf3ce44SJohn Forte * override the default values using driver.conf 1326*fcf3ce44SJohn Forte * 1327*fcf3ce44SJohn Forte * Input: 1328*fcf3ce44SJohn Forte * ha: adapter state pointer. 1329*fcf3ce44SJohn Forte * nv: NVRAM structure pointer. 1330*fcf3ce44SJohn Forte * 1331*fcf3ce44SJohn Forte * Context: 1332*fcf3ce44SJohn Forte * Kernel context. 1333*fcf3ce44SJohn Forte */ 1334*fcf3ce44SJohn Forte static void 1335*fcf3ce44SJohn Forte ql_23_properties(ql_adapter_state_t *ha, nvram_t *nv) 1336*fcf3ce44SJohn Forte { 1337*fcf3ce44SJohn Forte uint32_t data, cnt; 1338*fcf3ce44SJohn Forte 1339*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1340*fcf3ce44SJohn Forte 1341*fcf3ce44SJohn Forte /* Get frame payload size. */ 1342*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) { 1343*fcf3ce44SJohn Forte data = 2048; 1344*fcf3ce44SJohn Forte } 1345*fcf3ce44SJohn Forte if (data == 512 || data == 1024 || data == 2048) { 1346*fcf3ce44SJohn Forte nv->max_frame_length[0] = LSB(data); 1347*fcf3ce44SJohn Forte nv->max_frame_length[1] = MSB(data); 1348*fcf3ce44SJohn Forte } else { 1349*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'max-frame-length': " 1350*fcf3ce44SJohn Forte "%d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1351*fcf3ce44SJohn Forte nv->max_frame_length[0], nv->max_frame_length[1])); 1352*fcf3ce44SJohn Forte } 1353*fcf3ce44SJohn Forte 1354*fcf3ce44SJohn Forte /* Get max IOCB allocation. */ 1355*fcf3ce44SJohn Forte nv->max_iocb_allocation[0] = 0; 1356*fcf3ce44SJohn Forte nv->max_iocb_allocation[1] = 1; 1357*fcf3ce44SJohn Forte 1358*fcf3ce44SJohn Forte /* Get execution throttle. */ 1359*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) { 1360*fcf3ce44SJohn Forte data = 32; 1361*fcf3ce44SJohn Forte } 1362*fcf3ce44SJohn Forte if (data != 0 && data < 65536) { 1363*fcf3ce44SJohn Forte nv->execution_throttle[0] = LSB(data); 1364*fcf3ce44SJohn Forte nv->execution_throttle[1] = MSB(data); 1365*fcf3ce44SJohn Forte } else { 1366*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'execution-throttle': " 1367*fcf3ce44SJohn Forte "%d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1368*fcf3ce44SJohn Forte nv->execution_throttle[0], nv->execution_throttle[1])); 1369*fcf3ce44SJohn Forte } 1370*fcf3ce44SJohn Forte 1371*fcf3ce44SJohn Forte /* Get Login timeout. */ 1372*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) { 1373*fcf3ce44SJohn Forte data = 3; 1374*fcf3ce44SJohn Forte } 1375*fcf3ce44SJohn Forte if (data < 256) { 1376*fcf3ce44SJohn Forte nv->login_timeout = (uint8_t)data; 1377*fcf3ce44SJohn Forte } else { 1378*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-timeout': " 1379*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, nv->login_timeout); 1380*fcf3ce44SJohn Forte } 1381*fcf3ce44SJohn Forte 1382*fcf3ce44SJohn Forte /* Get retry count. */ 1383*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) { 1384*fcf3ce44SJohn Forte data = 4; 1385*fcf3ce44SJohn Forte } 1386*fcf3ce44SJohn Forte if (data < 256) { 1387*fcf3ce44SJohn Forte nv->login_retry_count = (uint8_t)data; 1388*fcf3ce44SJohn Forte } else { 1389*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-retry-count': " 1390*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1391*fcf3ce44SJohn Forte nv->login_retry_count); 1392*fcf3ce44SJohn Forte } 1393*fcf3ce44SJohn Forte 1394*fcf3ce44SJohn Forte /* Get adapter hard loop ID enable. */ 1395*fcf3ce44SJohn Forte data = ql_get_prop(ha, "enable-adapter-hard-loop-ID"); 1396*fcf3ce44SJohn Forte if (data == 0) { 1397*fcf3ce44SJohn Forte nv->firmware_options[0] = 1398*fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options[0] & ~BIT_0); 1399*fcf3ce44SJohn Forte } else if (data == 1) { 1400*fcf3ce44SJohn Forte nv->firmware_options[0] = 1401*fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options[0] | BIT_0); 1402*fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1403*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1404*fcf3ce44SJohn Forte "'enable-adapter-hard-loop-ID': %d; using nvram value " 1405*fcf3ce44SJohn Forte "of %d\n", data, nv->firmware_options[0] & BIT_0 ? 1 : 0); 1406*fcf3ce44SJohn Forte } 1407*fcf3ce44SJohn Forte 1408*fcf3ce44SJohn Forte /* Get adapter hard loop ID. */ 1409*fcf3ce44SJohn Forte data = ql_get_prop(ha, "adapter-hard-loop-ID"); 1410*fcf3ce44SJohn Forte if (data < 126) { 1411*fcf3ce44SJohn Forte nv->hard_address[0] = (uint8_t)data; 1412*fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1413*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': " 1414*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, nv->hard_address[0]); 1415*fcf3ce44SJohn Forte } 1416*fcf3ce44SJohn Forte 1417*fcf3ce44SJohn Forte /* Get LIP reset. */ 1418*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) == 1419*fcf3ce44SJohn Forte 0xffffffff) { 1420*fcf3ce44SJohn Forte data = 0; 1421*fcf3ce44SJohn Forte } 1422*fcf3ce44SJohn Forte if (data == 0) { 1423*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_1); 1424*fcf3ce44SJohn Forte } else if (data == 1) { 1425*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_1); 1426*fcf3ce44SJohn Forte } else { 1427*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1428*fcf3ce44SJohn Forte "'enable-LIP-reset-on-bus-reset': %d; using nvram value " 1429*fcf3ce44SJohn Forte "of %d\n", data, nv->host_p[1] & BIT_1 ? 1 : 0); 1430*fcf3ce44SJohn Forte } 1431*fcf3ce44SJohn Forte 1432*fcf3ce44SJohn Forte /* Get LIP full login. */ 1433*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) == 1434*fcf3ce44SJohn Forte 0xffffffff) { 1435*fcf3ce44SJohn Forte data = 1; 1436*fcf3ce44SJohn Forte } 1437*fcf3ce44SJohn Forte if (data == 0) { 1438*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2); 1439*fcf3ce44SJohn Forte } else if (data == 1) { 1440*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2); 1441*fcf3ce44SJohn Forte } else { 1442*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1443*fcf3ce44SJohn Forte "'enable-LIP-full-login-on-bus-reset': %d; using nvram " 1444*fcf3ce44SJohn Forte "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0); 1445*fcf3ce44SJohn Forte } 1446*fcf3ce44SJohn Forte 1447*fcf3ce44SJohn Forte /* Get target reset. */ 1448*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) == 1449*fcf3ce44SJohn Forte 0xffffffff) { 1450*fcf3ce44SJohn Forte data = 0; 1451*fcf3ce44SJohn Forte } 1452*fcf3ce44SJohn Forte if (data == 0) { 1453*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3); 1454*fcf3ce44SJohn Forte } else if (data == 1) { 1455*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3); 1456*fcf3ce44SJohn Forte } else { 1457*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1458*fcf3ce44SJohn Forte "'enable-target-reset-on-bus-reset': %d; using nvram " 1459*fcf3ce44SJohn Forte "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0); 1460*fcf3ce44SJohn Forte } 1461*fcf3ce44SJohn Forte 1462*fcf3ce44SJohn Forte /* Get reset delay. */ 1463*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) { 1464*fcf3ce44SJohn Forte data = 5; 1465*fcf3ce44SJohn Forte } 1466*fcf3ce44SJohn Forte if (data != 0 && data < 256) { 1467*fcf3ce44SJohn Forte nv->reset_delay = (uint8_t)data; 1468*fcf3ce44SJohn Forte } else { 1469*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'reset-delay': %d; " 1470*fcf3ce44SJohn Forte "using nvram value of %d", data, nv->reset_delay); 1471*fcf3ce44SJohn Forte } 1472*fcf3ce44SJohn Forte 1473*fcf3ce44SJohn Forte /* Get port down retry count. */ 1474*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) { 1475*fcf3ce44SJohn Forte data = 8; 1476*fcf3ce44SJohn Forte } 1477*fcf3ce44SJohn Forte if (data < 256) { 1478*fcf3ce44SJohn Forte nv->port_down_retry_count = (uint8_t)data; 1479*fcf3ce44SJohn Forte } else { 1480*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-count':" 1481*fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, 1482*fcf3ce44SJohn Forte nv->port_down_retry_count); 1483*fcf3ce44SJohn Forte } 1484*fcf3ce44SJohn Forte 1485*fcf3ce44SJohn Forte /* Get connection mode setting. */ 1486*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) { 1487*fcf3ce44SJohn Forte data = 2; 1488*fcf3ce44SJohn Forte } 1489*fcf3ce44SJohn Forte cnt = CFG_IST(ha, CFG_CTRL_2200) ? 3 : 2; 1490*fcf3ce44SJohn Forte if (data <= cnt) { 1491*fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] & 1492*fcf3ce44SJohn Forte ~(BIT_6 | BIT_5 | BIT_4)); 1493*fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] | 1494*fcf3ce44SJohn Forte (uint8_t)(data << 4)); 1495*fcf3ce44SJohn Forte } else { 1496*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'connection-options': " 1497*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1498*fcf3ce44SJohn Forte (nv->add_fw_opt[0] >> 4) & 0x3); 1499*fcf3ce44SJohn Forte } 1500*fcf3ce44SJohn Forte 1501*fcf3ce44SJohn Forte /* Get data rate setting. */ 1502*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2200)) == 0) { 1503*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) { 1504*fcf3ce44SJohn Forte data = 2; 1505*fcf3ce44SJohn Forte } 1506*fcf3ce44SJohn Forte if (data < 3) { 1507*fcf3ce44SJohn Forte nv->special_options[1] = (uint8_t) 1508*fcf3ce44SJohn Forte (nv->special_options[1] & 0x3f); 1509*fcf3ce44SJohn Forte nv->special_options[1] = (uint8_t) 1510*fcf3ce44SJohn Forte (nv->special_options[1] | (uint8_t)(data << 6)); 1511*fcf3ce44SJohn Forte } else { 1512*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'fc-data-rate': " 1513*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1514*fcf3ce44SJohn Forte (nv->special_options[1] >> 6) & 0x3); 1515*fcf3ce44SJohn Forte } 1516*fcf3ce44SJohn Forte } 1517*fcf3ce44SJohn Forte 1518*fcf3ce44SJohn Forte /* Get adapter id string for Sun branded 23xx only */ 1519*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2300)) && nv->adapInfo[0] != 0) { 1520*fcf3ce44SJohn Forte (void) snprintf((int8_t *)ha->adapInfo, 16, "%s", 1521*fcf3ce44SJohn Forte nv->adapInfo); 1522*fcf3ce44SJohn Forte } 1523*fcf3ce44SJohn Forte 1524*fcf3ce44SJohn Forte /* Get IP FW container count. */ 1525*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count); 1526*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count); 1527*fcf3ce44SJohn Forte 1528*fcf3ce44SJohn Forte /* Get IP low water mark. */ 1529*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water); 1530*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water); 1531*fcf3ce44SJohn Forte 1532*fcf3ce44SJohn Forte /* Get IP fast register post count. */ 1533*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] = 1534*fcf3ce44SJohn Forte ql_ip_fast_post_count; 1535*fcf3ce44SJohn Forte 1536*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1537*fcf3ce44SJohn Forte 1538*fcf3ce44SJohn Forte ql_common_properties(ha); 1539*fcf3ce44SJohn Forte 1540*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1541*fcf3ce44SJohn Forte 1542*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1543*fcf3ce44SJohn Forte } 1544*fcf3ce44SJohn Forte 1545*fcf3ce44SJohn Forte /* 1546*fcf3ce44SJohn Forte * ql_common_properties 1547*fcf3ce44SJohn Forte * Driver properties adapter structure. 1548*fcf3ce44SJohn Forte * 1549*fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1550*fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1551*fcf3ce44SJohn Forte * override the default values using driver.conf 1552*fcf3ce44SJohn Forte * 1553*fcf3ce44SJohn Forte * Input: 1554*fcf3ce44SJohn Forte * ha: adapter state pointer. 1555*fcf3ce44SJohn Forte * 1556*fcf3ce44SJohn Forte * Context: 1557*fcf3ce44SJohn Forte * Kernel context. 1558*fcf3ce44SJohn Forte */ 1559*fcf3ce44SJohn Forte void 1560*fcf3ce44SJohn Forte ql_common_properties(ql_adapter_state_t *ha) 1561*fcf3ce44SJohn Forte { 1562*fcf3ce44SJohn Forte uint32_t data; 1563*fcf3ce44SJohn Forte 1564*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1565*fcf3ce44SJohn Forte 1566*fcf3ce44SJohn Forte /* Get FCP 2 Error Recovery. */ 1567*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) == 1568*fcf3ce44SJohn Forte 0xffffffff || data == 1) { 1569*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT; 1570*fcf3ce44SJohn Forte } else if (data == 0) { 1571*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT; 1572*fcf3ce44SJohn Forte } else { 1573*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1574*fcf3ce44SJohn Forte "'enable-FCP-2-error-recovery': %d; using nvram value of " 1575*fcf3ce44SJohn Forte "1\n", data); 1576*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT; 1577*fcf3ce44SJohn Forte } 1578*fcf3ce44SJohn Forte 1579*fcf3ce44SJohn Forte /* Get target mode enable. */ 1580*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_TARGET_MODE_ENABLE; 1581*fcf3ce44SJohn Forte 1582*fcf3ce44SJohn Forte /* Get extended logging enable. */ 1583*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff || 1584*fcf3ce44SJohn Forte data == 0) { 1585*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING; 1586*fcf3ce44SJohn Forte } else if (data == 1) { 1587*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING; 1588*fcf3ce44SJohn Forte } else { 1589*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'extended-logging': %d;" 1590*fcf3ce44SJohn Forte " using default value of 0\n", data); 1591*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING; 1592*fcf3ce44SJohn Forte } 1593*fcf3ce44SJohn Forte 1594*fcf3ce44SJohn Forte #ifdef QL_DEBUG_LEVEL_2 1595*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING; 1596*fcf3ce44SJohn Forte #endif 1597*fcf3ce44SJohn Forte 1598*fcf3ce44SJohn Forte /* Get port down retry delay. */ 1599*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) { 1600*fcf3ce44SJohn Forte ha->port_down_retry_delay = PORT_RETRY_TIME; 1601*fcf3ce44SJohn Forte } else if (data < 256) { 1602*fcf3ce44SJohn Forte ha->port_down_retry_delay = (uint8_t)data; 1603*fcf3ce44SJohn Forte } else { 1604*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-delay':" 1605*fcf3ce44SJohn Forte " %d; using default value of %d", data, PORT_RETRY_TIME); 1606*fcf3ce44SJohn Forte ha->port_down_retry_delay = PORT_RETRY_TIME; 1607*fcf3ce44SJohn Forte } 1608*fcf3ce44SJohn Forte 1609*fcf3ce44SJohn Forte /* Get queue full retry count. */ 1610*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) { 1611*fcf3ce44SJohn Forte ha->qfull_retry_count = 16; 1612*fcf3ce44SJohn Forte } else if (data < 256) { 1613*fcf3ce44SJohn Forte ha->qfull_retry_count = (uint8_t)data; 1614*fcf3ce44SJohn Forte } else { 1615*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'queue-full-retry-count':" 1616*fcf3ce44SJohn Forte " %d; using default value of 16", data); 1617*fcf3ce44SJohn Forte ha->qfull_retry_count = 16; 1618*fcf3ce44SJohn Forte } 1619*fcf3ce44SJohn Forte 1620*fcf3ce44SJohn Forte /* Get queue full retry delay. */ 1621*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) { 1622*fcf3ce44SJohn Forte ha->qfull_retry_delay = PORT_RETRY_TIME; 1623*fcf3ce44SJohn Forte } else if (data < 256) { 1624*fcf3ce44SJohn Forte ha->qfull_retry_delay = (uint8_t)data; 1625*fcf3ce44SJohn Forte } else { 1626*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'queue-full-retry-delay':" 1627*fcf3ce44SJohn Forte " %d; using default value of %d", data, PORT_RETRY_TIME); 1628*fcf3ce44SJohn Forte ha->qfull_retry_delay = PORT_RETRY_TIME; 1629*fcf3ce44SJohn Forte } 1630*fcf3ce44SJohn Forte 1631*fcf3ce44SJohn Forte /* Get loop down timeout. */ 1632*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) { 1633*fcf3ce44SJohn Forte data = 0; 1634*fcf3ce44SJohn Forte } else if (data > 255) { 1635*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'link-down-timeout': %d;" 1636*fcf3ce44SJohn Forte " using nvram value of 0\n", data); 1637*fcf3ce44SJohn Forte data = 0; 1638*fcf3ce44SJohn Forte } 1639*fcf3ce44SJohn Forte ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data); 1640*fcf3ce44SJohn Forte if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) { 1641*fcf3ce44SJohn Forte ha->loop_down_abort_time--; 1642*fcf3ce44SJohn Forte } else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) { 1643*fcf3ce44SJohn Forte ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1; 1644*fcf3ce44SJohn Forte } 1645*fcf3ce44SJohn Forte 1646*fcf3ce44SJohn Forte /* Get link down error enable. */ 1647*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff || 1648*fcf3ce44SJohn Forte data == 1) { 1649*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING; 1650*fcf3ce44SJohn Forte } else if (data == 0) { 1651*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING; 1652*fcf3ce44SJohn Forte } else { 1653*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'link-down-error': %d;" 1654*fcf3ce44SJohn Forte " using default value of 1\n", data); 1655*fcf3ce44SJohn Forte } 1656*fcf3ce44SJohn Forte 1657*fcf3ce44SJohn Forte /* 1658*fcf3ce44SJohn Forte * Get firmware dump flags. 1659*fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT BIT_0 1660*fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR BIT_1 1661*fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT BIT_2 1662*fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT BIT_3 1663*fcf3ce44SJohn Forte */ 1664*fcf3ce44SJohn Forte ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT | 1665*fcf3ce44SJohn Forte CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT | 1666*fcf3ce44SJohn Forte CFG_DUMP_LOOP_OFFLINE_TIMEOUT); 1667*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) { 1668*fcf3ce44SJohn Forte if (data & BIT_0) { 1669*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT; 1670*fcf3ce44SJohn Forte } 1671*fcf3ce44SJohn Forte if (data & BIT_1) { 1672*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR; 1673*fcf3ce44SJohn Forte } 1674*fcf3ce44SJohn Forte if (data & BIT_2) { 1675*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT; 1676*fcf3ce44SJohn Forte } 1677*fcf3ce44SJohn Forte if (data & BIT_3) { 1678*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT; 1679*fcf3ce44SJohn Forte } 1680*fcf3ce44SJohn Forte } 1681*fcf3ce44SJohn Forte 1682*fcf3ce44SJohn Forte /* Get the PCI max read request size override. */ 1683*fcf3ce44SJohn Forte ha->pci_max_read_req = 0; 1684*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff && 1685*fcf3ce44SJohn Forte data != 0) { 1686*fcf3ce44SJohn Forte ha->pci_max_read_req = (uint16_t)(data); 1687*fcf3ce44SJohn Forte } 1688*fcf3ce44SJohn Forte 1689*fcf3ce44SJohn Forte /* Get the attach fw_ready override value. */ 1690*fcf3ce44SJohn Forte ha->fwwait = 10; 1691*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) { 1692*fcf3ce44SJohn Forte if (data > 0 && data <= 240) { 1693*fcf3ce44SJohn Forte ha->fwwait = (uint8_t)data; 1694*fcf3ce44SJohn Forte } else { 1695*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1696*fcf3ce44SJohn Forte "'init-loop-sync-wait': %d; using default " 1697*fcf3ce44SJohn Forte "value of %d\n", data, ha->fwwait); 1698*fcf3ce44SJohn Forte } 1699*fcf3ce44SJohn Forte } 1700*fcf3ce44SJohn Forte 1701*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1702*fcf3ce44SJohn Forte } 1703*fcf3ce44SJohn Forte 1704*fcf3ce44SJohn Forte /* 1705*fcf3ce44SJohn Forte * ql_24xx_properties 1706*fcf3ce44SJohn Forte * Copies driver properties to NVRAM or adapter structure. 1707*fcf3ce44SJohn Forte * 1708*fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1709*fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1710*fcf3ce44SJohn Forte * override the default values using /etc/system. 1711*fcf3ce44SJohn Forte * 1712*fcf3ce44SJohn Forte * Input: 1713*fcf3ce44SJohn Forte * ha: adapter state pointer. 1714*fcf3ce44SJohn Forte * nv: NVRAM structure pointer. 1715*fcf3ce44SJohn Forte * 1716*fcf3ce44SJohn Forte * Context: 1717*fcf3ce44SJohn Forte * Kernel context. 1718*fcf3ce44SJohn Forte */ 1719*fcf3ce44SJohn Forte static void 1720*fcf3ce44SJohn Forte ql_24xx_properties(ql_adapter_state_t *ha, nvram_24xx_t *nv) 1721*fcf3ce44SJohn Forte { 1722*fcf3ce44SJohn Forte uint32_t data; 1723*fcf3ce44SJohn Forte 1724*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1725*fcf3ce44SJohn Forte 1726*fcf3ce44SJohn Forte /* Get frame size */ 1727*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) { 1728*fcf3ce44SJohn Forte data = 2048; 1729*fcf3ce44SJohn Forte } 1730*fcf3ce44SJohn Forte if (data == 512 || data == 1024 || data == 2048) { 1731*fcf3ce44SJohn Forte nv->max_frame_length[0] = LSB(data); 1732*fcf3ce44SJohn Forte nv->max_frame_length[1] = MSB(data); 1733*fcf3ce44SJohn Forte } else { 1734*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'max-frame-length': %d;" 1735*fcf3ce44SJohn Forte " using nvram default of %d\n", data, CHAR_TO_SHORT( 1736*fcf3ce44SJohn Forte nv->max_frame_length[0], nv->max_frame_length[1])); 1737*fcf3ce44SJohn Forte } 1738*fcf3ce44SJohn Forte 1739*fcf3ce44SJohn Forte /* Get execution throttle. */ 1740*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) { 1741*fcf3ce44SJohn Forte data = 32; 1742*fcf3ce44SJohn Forte } 1743*fcf3ce44SJohn Forte if (data != 0 && data < 65536) { 1744*fcf3ce44SJohn Forte nv->execution_throttle[0] = LSB(data); 1745*fcf3ce44SJohn Forte nv->execution_throttle[1] = MSB(data); 1746*fcf3ce44SJohn Forte } else { 1747*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'execution-throttle':" 1748*fcf3ce44SJohn Forte " %d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1749*fcf3ce44SJohn Forte nv->execution_throttle[0], nv->execution_throttle[1])); 1750*fcf3ce44SJohn Forte } 1751*fcf3ce44SJohn Forte 1752*fcf3ce44SJohn Forte /* Get Login timeout. */ 1753*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) { 1754*fcf3ce44SJohn Forte data = 3; 1755*fcf3ce44SJohn Forte } 1756*fcf3ce44SJohn Forte if (data < 65536) { 1757*fcf3ce44SJohn Forte nv->login_timeout[0] = LSB(data); 1758*fcf3ce44SJohn Forte nv->login_timeout[1] = MSB(data); 1759*fcf3ce44SJohn Forte } else { 1760*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-timeout': %d; " 1761*fcf3ce44SJohn Forte "using nvram value of %d\n", data, CHAR_TO_SHORT( 1762*fcf3ce44SJohn Forte nv->login_timeout[0], nv->login_timeout[1])); 1763*fcf3ce44SJohn Forte } 1764*fcf3ce44SJohn Forte 1765*fcf3ce44SJohn Forte /* Get retry count. */ 1766*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) { 1767*fcf3ce44SJohn Forte data = 4; 1768*fcf3ce44SJohn Forte } 1769*fcf3ce44SJohn Forte if (data < 65536) { 1770*fcf3ce44SJohn Forte nv->login_retry_count[0] = LSB(data); 1771*fcf3ce44SJohn Forte nv->login_retry_count[1] = MSB(data); 1772*fcf3ce44SJohn Forte } else { 1773*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-retry-count': " 1774*fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1775*fcf3ce44SJohn Forte nv->login_retry_count[0], nv->login_retry_count[1])); 1776*fcf3ce44SJohn Forte } 1777*fcf3ce44SJohn Forte 1778*fcf3ce44SJohn Forte /* Get adapter hard loop ID enable. */ 1779*fcf3ce44SJohn Forte data = ql_get_prop(ha, "enable-adapter-hard-loop-ID"); 1780*fcf3ce44SJohn Forte if (data == 0) { 1781*fcf3ce44SJohn Forte nv->firmware_options_1[0] = 1782*fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options_1[0] & ~BIT_0); 1783*fcf3ce44SJohn Forte } else if (data == 1) { 1784*fcf3ce44SJohn Forte nv->firmware_options_1[0] = 1785*fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options_1[0] | BIT_0); 1786*fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1787*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1788*fcf3ce44SJohn Forte "'enable-adapter-hard-loop-ID': %d; using nvram value " 1789*fcf3ce44SJohn Forte "of %d\n", data, 1790*fcf3ce44SJohn Forte nv->firmware_options_1[0] & BIT_0 ? 1 : 0); 1791*fcf3ce44SJohn Forte } 1792*fcf3ce44SJohn Forte 1793*fcf3ce44SJohn Forte /* Get adapter hard loop ID. */ 1794*fcf3ce44SJohn Forte data = ql_get_prop(ha, "adapter-hard-loop-ID"); 1795*fcf3ce44SJohn Forte if (data < 126) { 1796*fcf3ce44SJohn Forte nv->hard_address[0] = LSB(data); 1797*fcf3ce44SJohn Forte nv->hard_address[1] = MSB(data); 1798*fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1799*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':" 1800*fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1801*fcf3ce44SJohn Forte nv->hard_address[0], nv->hard_address[1])); 1802*fcf3ce44SJohn Forte } 1803*fcf3ce44SJohn Forte 1804*fcf3ce44SJohn Forte /* Get LIP reset. */ 1805*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) == 1806*fcf3ce44SJohn Forte 0xffffffff) { 1807*fcf3ce44SJohn Forte data = 0; 1808*fcf3ce44SJohn Forte } 1809*fcf3ce44SJohn Forte if (data == 0) { 1810*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET; 1811*fcf3ce44SJohn Forte } else if (data == 1) { 1812*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_LIP_RESET; 1813*fcf3ce44SJohn Forte } else { 1814*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1815*fcf3ce44SJohn Forte "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n", 1816*fcf3ce44SJohn Forte data); 1817*fcf3ce44SJohn Forte } 1818*fcf3ce44SJohn Forte 1819*fcf3ce44SJohn Forte /* Get LIP full login. */ 1820*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) == 1821*fcf3ce44SJohn Forte 0xffffffff) { 1822*fcf3ce44SJohn Forte data = 1; 1823*fcf3ce44SJohn Forte } 1824*fcf3ce44SJohn Forte if (data == 0) { 1825*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2); 1826*fcf3ce44SJohn Forte } else if (data == 1) { 1827*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2); 1828*fcf3ce44SJohn Forte } else { 1829*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1830*fcf3ce44SJohn Forte "'enable-LIP-full-login-on-bus-reset': %d; using nvram " 1831*fcf3ce44SJohn Forte "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0); 1832*fcf3ce44SJohn Forte } 1833*fcf3ce44SJohn Forte 1834*fcf3ce44SJohn Forte /* Get target reset. */ 1835*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) == 1836*fcf3ce44SJohn Forte 0xffffffff) { 1837*fcf3ce44SJohn Forte data = 0; 1838*fcf3ce44SJohn Forte } 1839*fcf3ce44SJohn Forte if (data == 0) { 1840*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3); 1841*fcf3ce44SJohn Forte } else if (data == 1) { 1842*fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3); 1843*fcf3ce44SJohn Forte } else { 1844*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1845*fcf3ce44SJohn Forte "'enable-target-reset-on-bus-reset': %d; using nvram " 1846*fcf3ce44SJohn Forte "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0); 1847*fcf3ce44SJohn Forte } 1848*fcf3ce44SJohn Forte 1849*fcf3ce44SJohn Forte /* Get reset delay. */ 1850*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) { 1851*fcf3ce44SJohn Forte data = 5; 1852*fcf3ce44SJohn Forte } 1853*fcf3ce44SJohn Forte if (data != 0 && data < 256) { 1854*fcf3ce44SJohn Forte nv->reset_delay = (uint8_t)data; 1855*fcf3ce44SJohn Forte } else { 1856*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'reset-delay': %d; " 1857*fcf3ce44SJohn Forte "using nvram value of %d", data, nv->reset_delay); 1858*fcf3ce44SJohn Forte } 1859*fcf3ce44SJohn Forte 1860*fcf3ce44SJohn Forte /* Get port down retry count. */ 1861*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) { 1862*fcf3ce44SJohn Forte data = 8; 1863*fcf3ce44SJohn Forte } 1864*fcf3ce44SJohn Forte if (data < 256) { 1865*fcf3ce44SJohn Forte nv->port_down_retry_count[0] = LSB(data); 1866*fcf3ce44SJohn Forte nv->port_down_retry_count[1] = MSB(data); 1867*fcf3ce44SJohn Forte } else { 1868*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-count':" 1869*fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1870*fcf3ce44SJohn Forte nv->port_down_retry_count[0], 1871*fcf3ce44SJohn Forte nv->port_down_retry_count[1])); 1872*fcf3ce44SJohn Forte } 1873*fcf3ce44SJohn Forte 1874*fcf3ce44SJohn Forte /* Get connection mode setting. */ 1875*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) { 1876*fcf3ce44SJohn Forte data = 2; 1877*fcf3ce44SJohn Forte } 1878*fcf3ce44SJohn Forte if (data <= 2) { 1879*fcf3ce44SJohn Forte nv->firmware_options_2[0] = (uint8_t) 1880*fcf3ce44SJohn Forte (nv->firmware_options_2[0] & ~(BIT_6 | BIT_5 | BIT_4)); 1881*fcf3ce44SJohn Forte nv->firmware_options_2[0] = (uint8_t) 1882*fcf3ce44SJohn Forte (nv->firmware_options_2[0] | (uint8_t)(data << 4)); 1883*fcf3ce44SJohn Forte } else { 1884*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'connection-options':" 1885*fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, 1886*fcf3ce44SJohn Forte (nv->firmware_options_2[0] >> 4) & 0x3); 1887*fcf3ce44SJohn Forte } 1888*fcf3ce44SJohn Forte 1889*fcf3ce44SJohn Forte /* Get data rate setting. */ 1890*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) { 1891*fcf3ce44SJohn Forte data = 2; 1892*fcf3ce44SJohn Forte } 1893*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2422) && data < 4) || 1894*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_CTRL_25XX) && data < 5)) { 1895*fcf3ce44SJohn Forte nv->firmware_options_3[1] = (uint8_t) 1896*fcf3ce44SJohn Forte (nv->firmware_options_3[1] & 0x1f); 1897*fcf3ce44SJohn Forte nv->firmware_options_3[1] = (uint8_t) 1898*fcf3ce44SJohn Forte (nv->firmware_options_3[1] | (uint8_t)(data << 5)); 1899*fcf3ce44SJohn Forte } else { 1900*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'fc-data-rate': %d; " 1901*fcf3ce44SJohn Forte "using nvram value of %d\n", data, 1902*fcf3ce44SJohn Forte (nv->firmware_options_3[1] >> 5) & 0x7); 1903*fcf3ce44SJohn Forte } 1904*fcf3ce44SJohn Forte 1905*fcf3ce44SJohn Forte /* Get IP FW container count. */ 1906*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count); 1907*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count); 1908*fcf3ce44SJohn Forte 1909*fcf3ce44SJohn Forte /* Get IP low water mark. */ 1910*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water); 1911*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water); 1912*fcf3ce44SJohn Forte 1913*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1914*fcf3ce44SJohn Forte 1915*fcf3ce44SJohn Forte /* Get enable flash load. */ 1916*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff || 1917*fcf3ce44SJohn Forte data == 0) { 1918*fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_LOAD_FLASH_FW; 1919*fcf3ce44SJohn Forte } else if (data == 1) { 1920*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_LOAD_FLASH_FW; 1921*fcf3ce44SJohn Forte } else { 1922*fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'enable-flash-load': " 1923*fcf3ce44SJohn Forte "%d; using default value of 0\n", data); 1924*fcf3ce44SJohn Forte } 1925*fcf3ce44SJohn Forte 1926*fcf3ce44SJohn Forte /* Enable firmware extended tracing */ 1927*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) { 1928*fcf3ce44SJohn Forte if (data != 0) { 1929*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE; 1930*fcf3ce44SJohn Forte } 1931*fcf3ce44SJohn Forte } 1932*fcf3ce44SJohn Forte 1933*fcf3ce44SJohn Forte /* Enable firmware fc tracing */ 1934*fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) { 1935*fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FWFCETRACE; 1936*fcf3ce44SJohn Forte ha->fwfcetraceopt = data; 1937*fcf3ce44SJohn Forte } 1938*fcf3ce44SJohn Forte 1939*fcf3ce44SJohn Forte ql_common_properties(ha); 1940*fcf3ce44SJohn Forte 1941*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1942*fcf3ce44SJohn Forte 1943*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1944*fcf3ce44SJohn Forte } 1945*fcf3ce44SJohn Forte 1946*fcf3ce44SJohn Forte /* 1947*fcf3ce44SJohn Forte * ql_get_prop 1948*fcf3ce44SJohn Forte * Get property value from configuration file. 1949*fcf3ce44SJohn Forte * 1950*fcf3ce44SJohn Forte * Input: 1951*fcf3ce44SJohn Forte * ha= adapter state pointer. 1952*fcf3ce44SJohn Forte * string = property string pointer. 1953*fcf3ce44SJohn Forte * 1954*fcf3ce44SJohn Forte * Returns: 1955*fcf3ce44SJohn Forte * 0xFFFFFFFF = no property else property value. 1956*fcf3ce44SJohn Forte * 1957*fcf3ce44SJohn Forte * Context: 1958*fcf3ce44SJohn Forte * Kernel context. 1959*fcf3ce44SJohn Forte */ 1960*fcf3ce44SJohn Forte uint32_t 1961*fcf3ce44SJohn Forte ql_get_prop(ql_adapter_state_t *ha, char *string) 1962*fcf3ce44SJohn Forte { 1963*fcf3ce44SJohn Forte char buf[256]; 1964*fcf3ce44SJohn Forte uint32_t data; 1965*fcf3ce44SJohn Forte 1966*fcf3ce44SJohn Forte /* Get adapter instance parameter. */ 1967*fcf3ce44SJohn Forte (void) sprintf(buf, "hba%d-%s", ha->instance, string); 1968*fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 1969*fcf3ce44SJohn Forte data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0, buf, 1970*fcf3ce44SJohn Forte (int)0xffffffff); 1971*fcf3ce44SJohn Forte 1972*fcf3ce44SJohn Forte /* Adapter instance parameter found? */ 1973*fcf3ce44SJohn Forte if (data == 0xffffffff) { 1974*fcf3ce44SJohn Forte /* No, get default parameter. */ 1975*fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 1976*fcf3ce44SJohn Forte data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0, 1977*fcf3ce44SJohn Forte string, (int)0xffffffff); 1978*fcf3ce44SJohn Forte } 1979*fcf3ce44SJohn Forte 1980*fcf3ce44SJohn Forte return (data); 1981*fcf3ce44SJohn Forte } 1982*fcf3ce44SJohn Forte 1983*fcf3ce44SJohn Forte /* 1984*fcf3ce44SJohn Forte * ql_check_isp_firmware 1985*fcf3ce44SJohn Forte * Checks if using already loaded RISC code or drivers copy. 1986*fcf3ce44SJohn Forte * If using already loaded code, save a copy of it. 1987*fcf3ce44SJohn Forte * 1988*fcf3ce44SJohn Forte * Input: 1989*fcf3ce44SJohn Forte * ha = adapter state pointer. 1990*fcf3ce44SJohn Forte * 1991*fcf3ce44SJohn Forte * Returns: 1992*fcf3ce44SJohn Forte * ql local function return status code. 1993*fcf3ce44SJohn Forte * 1994*fcf3ce44SJohn Forte * Context: 1995*fcf3ce44SJohn Forte * Kernel context. 1996*fcf3ce44SJohn Forte */ 1997*fcf3ce44SJohn Forte static int 1998*fcf3ce44SJohn Forte ql_check_isp_firmware(ql_adapter_state_t *ha) 1999*fcf3ce44SJohn Forte { 2000*fcf3ce44SJohn Forte int rval; 2001*fcf3ce44SJohn Forte uint16_t word_count; 2002*fcf3ce44SJohn Forte uint32_t byte_count; 2003*fcf3ce44SJohn Forte uint32_t fw_size, *lptr; 2004*fcf3ce44SJohn Forte caddr_t bufp; 2005*fcf3ce44SJohn Forte uint16_t risc_address = (uint16_t)ha->risc_fw[0].addr; 2006*fcf3ce44SJohn Forte 2007*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2008*fcf3ce44SJohn Forte 2009*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) { 2010*fcf3ce44SJohn Forte if (ha->risc_code != NULL) { 2011*fcf3ce44SJohn Forte kmem_free(ha->risc_code, ha->risc_code_size); 2012*fcf3ce44SJohn Forte ha->risc_code = NULL; 2013*fcf3ce44SJohn Forte ha->risc_code_size = 0; 2014*fcf3ce44SJohn Forte } 2015*fcf3ce44SJohn Forte 2016*fcf3ce44SJohn Forte /* Get RISC code length. */ 2017*fcf3ce44SJohn Forte rval = ql_rd_risc_ram(ha, risc_address + 3, ha->request_dvma, 2018*fcf3ce44SJohn Forte 1); 2019*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2020*fcf3ce44SJohn Forte lptr = (uint32_t *)ha->request_ring_bp; 2021*fcf3ce44SJohn Forte fw_size = *lptr << 1; 2022*fcf3ce44SJohn Forte 2023*fcf3ce44SJohn Forte if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) { 2024*fcf3ce44SJohn Forte ha->risc_code_size = fw_size; 2025*fcf3ce44SJohn Forte ha->risc_code = bufp; 2026*fcf3ce44SJohn Forte ha->fw_transfer_size = 128; 2027*fcf3ce44SJohn Forte 2028*fcf3ce44SJohn Forte /* Dump RISC code. */ 2029*fcf3ce44SJohn Forte do { 2030*fcf3ce44SJohn Forte if (fw_size > ha->fw_transfer_size) { 2031*fcf3ce44SJohn Forte byte_count = 2032*fcf3ce44SJohn Forte ha->fw_transfer_size; 2033*fcf3ce44SJohn Forte } else { 2034*fcf3ce44SJohn Forte byte_count = fw_size; 2035*fcf3ce44SJohn Forte } 2036*fcf3ce44SJohn Forte 2037*fcf3ce44SJohn Forte word_count = 2038*fcf3ce44SJohn Forte (uint16_t)(byte_count >> 1); 2039*fcf3ce44SJohn Forte 2040*fcf3ce44SJohn Forte rval = ql_rd_risc_ram(ha, risc_address, 2041*fcf3ce44SJohn Forte ha->request_dvma, word_count); 2042*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2043*fcf3ce44SJohn Forte kmem_free(ha->risc_code, 2044*fcf3ce44SJohn Forte ha->risc_code_size); 2045*fcf3ce44SJohn Forte ha->risc_code = NULL; 2046*fcf3ce44SJohn Forte ha->risc_code_size = 0; 2047*fcf3ce44SJohn Forte break; 2048*fcf3ce44SJohn Forte } 2049*fcf3ce44SJohn Forte 2050*fcf3ce44SJohn Forte (void) ddi_dma_sync( 2051*fcf3ce44SJohn Forte ha->hba_buf.dma_handle, 2052*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET, 2053*fcf3ce44SJohn Forte byte_count, 2054*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 2055*fcf3ce44SJohn Forte ddi_rep_get16(ha->hba_buf.acc_handle, 2056*fcf3ce44SJohn Forte (uint16_t *)bufp, 2057*fcf3ce44SJohn Forte (uint16_t *)ha->request_ring_bp, 2058*fcf3ce44SJohn Forte word_count, DDI_DEV_AUTOINCR); 2059*fcf3ce44SJohn Forte 2060*fcf3ce44SJohn Forte risc_address += word_count; 2061*fcf3ce44SJohn Forte fw_size -= byte_count; 2062*fcf3ce44SJohn Forte bufp += byte_count; 2063*fcf3ce44SJohn Forte } while (fw_size != 0); 2064*fcf3ce44SJohn Forte } 2065*fcf3ce44SJohn Forte } 2066*fcf3ce44SJohn Forte } else { 2067*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2068*fcf3ce44SJohn Forte } 2069*fcf3ce44SJohn Forte 2070*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2071*fcf3ce44SJohn Forte EL(ha, "Load RISC code\n"); 2072*fcf3ce44SJohn Forte } else { 2073*fcf3ce44SJohn Forte /*EMPTY*/ 2074*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2075*fcf3ce44SJohn Forte } 2076*fcf3ce44SJohn Forte return (rval); 2077*fcf3ce44SJohn Forte } 2078*fcf3ce44SJohn Forte 2079*fcf3ce44SJohn Forte /* 2080*fcf3ce44SJohn Forte * Chip diagnostics 2081*fcf3ce44SJohn Forte * Test chip for proper operation. 2082*fcf3ce44SJohn Forte * 2083*fcf3ce44SJohn Forte * Input: 2084*fcf3ce44SJohn Forte * ha = adapter state pointer. 2085*fcf3ce44SJohn Forte * 2086*fcf3ce44SJohn Forte * Returns: 2087*fcf3ce44SJohn Forte * ql local function return status code. 2088*fcf3ce44SJohn Forte * 2089*fcf3ce44SJohn Forte * Context: 2090*fcf3ce44SJohn Forte * Kernel context. 2091*fcf3ce44SJohn Forte */ 2092*fcf3ce44SJohn Forte static int 2093*fcf3ce44SJohn Forte ql_chip_diag(ql_adapter_state_t *ha) 2094*fcf3ce44SJohn Forte { 2095*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2096*fcf3ce44SJohn Forte int32_t rval = QL_FUNCTION_FAILED; 2097*fcf3ce44SJohn Forte int32_t retries = 4; 2098*fcf3ce44SJohn Forte uint16_t id; 2099*fcf3ce44SJohn Forte 2100*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2101*fcf3ce44SJohn Forte 2102*fcf3ce44SJohn Forte do { 2103*fcf3ce44SJohn Forte /* Reset ISP chip. */ 2104*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2105*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~ISP_ABORT_NEEDED; 2106*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2107*fcf3ce44SJohn Forte ql_reset_chip(ha); 2108*fcf3ce44SJohn Forte 2109*fcf3ce44SJohn Forte /* For ISP2200A reduce firmware load size. */ 2110*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2200) && 2111*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[7]) == 4) { 2112*fcf3ce44SJohn Forte ha->fw_transfer_size = 128; 2113*fcf3ce44SJohn Forte } else { 2114*fcf3ce44SJohn Forte ha->fw_transfer_size = REQUEST_QUEUE_SIZE; 2115*fcf3ce44SJohn Forte } 2116*fcf3ce44SJohn Forte 2117*fcf3ce44SJohn Forte /* Check product ID of chip */ 2118*fcf3ce44SJohn Forte mr.mb[1] = RD16_IO_REG(ha, mailbox[1]); 2119*fcf3ce44SJohn Forte mr.mb[2] = RD16_IO_REG(ha, mailbox[2]); 2120*fcf3ce44SJohn Forte mr.mb[3] = RD16_IO_REG(ha, mailbox[3]); 2121*fcf3ce44SJohn Forte 2122*fcf3ce44SJohn Forte if (ha->device_id == 0x5432 || ha->device_id == 0x8432) { 2123*fcf3ce44SJohn Forte id = 0x2432; 2124*fcf3ce44SJohn Forte } else if (ha->device_id == 0x5422 || 2125*fcf3ce44SJohn Forte ha->device_id == 0x8432) { 2126*fcf3ce44SJohn Forte id = 0x2422; 2127*fcf3ce44SJohn Forte } else { 2128*fcf3ce44SJohn Forte id = ha->device_id; 2129*fcf3ce44SJohn Forte } 2130*fcf3ce44SJohn Forte 2131*fcf3ce44SJohn Forte if (mr.mb[1] == PROD_ID_1 && 2132*fcf3ce44SJohn Forte (mr.mb[2] == PROD_ID_2 || mr.mb[2] == PROD_ID_2a) && 2133*fcf3ce44SJohn Forte (mr.mb[3] == PROD_ID_3 || mr.mb[3] == id)) { 2134*fcf3ce44SJohn Forte 2135*fcf3ce44SJohn Forte ha->adapter_stats->revlvl.isp2200 = RD16_IO_REG(ha, 2136*fcf3ce44SJohn Forte mailbox[4]); 2137*fcf3ce44SJohn Forte ha->adapter_stats->revlvl.risc = RD16_IO_REG(ha, 2138*fcf3ce44SJohn Forte mailbox[5]); 2139*fcf3ce44SJohn Forte ha->adapter_stats->revlvl.frmbfr = RD16_IO_REG(ha, 2140*fcf3ce44SJohn Forte mailbox[6]); 2141*fcf3ce44SJohn Forte ha->adapter_stats->revlvl.riscrom = RD16_IO_REG(ha, 2142*fcf3ce44SJohn Forte mailbox[7]); 2143*fcf3ce44SJohn Forte bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv, 2144*fcf3ce44SJohn Forte strlen(QL_VERSION)); 2145*fcf3ce44SJohn Forte 2146*fcf3ce44SJohn Forte /* Wrap Incoming Mailboxes Test. */ 2147*fcf3ce44SJohn Forte mr.mb[1] = 0xAAAA; 2148*fcf3ce44SJohn Forte mr.mb[2] = 0x5555; 2149*fcf3ce44SJohn Forte mr.mb[3] = 0xAA55; 2150*fcf3ce44SJohn Forte mr.mb[4] = 0x55AA; 2151*fcf3ce44SJohn Forte mr.mb[5] = 0xA5A5; 2152*fcf3ce44SJohn Forte mr.mb[6] = 0x5A5A; 2153*fcf3ce44SJohn Forte mr.mb[7] = 0x2525; 2154*fcf3ce44SJohn Forte rval = ql_mbx_wrap_test(ha, &mr); 2155*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2156*fcf3ce44SJohn Forte if (mr.mb[1] != 0xAAAA || 2157*fcf3ce44SJohn Forte mr.mb[2] != 0x5555 || 2158*fcf3ce44SJohn Forte mr.mb[3] != 0xAA55 || 2159*fcf3ce44SJohn Forte mr.mb[4] != 0x55AA || 2160*fcf3ce44SJohn Forte mr.mb[5] != 0xA5A5 || 2161*fcf3ce44SJohn Forte mr.mb[6] != 0x5A5A || 2162*fcf3ce44SJohn Forte mr.mb[7] != 0x2525) { 2163*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2164*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, 2165*fcf3ce44SJohn Forte FLASH_ERRLOG_ISP_ERR, 0, 2166*fcf3ce44SJohn Forte RD16_IO_REG(ha, hccr), 2167*fcf3ce44SJohn Forte RD16_IO_REG(ha, istatus)); 2168*fcf3ce44SJohn Forte } 2169*fcf3ce44SJohn Forte } else { 2170*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) - reg test failed=" 2171*fcf3ce44SJohn Forte "%xh!", QL_NAME, ha->instance, rval); 2172*fcf3ce44SJohn Forte } 2173*fcf3ce44SJohn Forte } else { 2174*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) - prod id failed!, mb1=%xh, " 2175*fcf3ce44SJohn Forte "mb2=%xh, mb3=%xh", QL_NAME, ha->instance, 2176*fcf3ce44SJohn Forte mr.mb[1], mr.mb[2], mr.mb[3]); 2177*fcf3ce44SJohn Forte } 2178*fcf3ce44SJohn Forte } while ((retries-- != 0) && (rval != QL_SUCCESS)); 2179*fcf3ce44SJohn Forte 2180*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2181*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2182*fcf3ce44SJohn Forte } else { 2183*fcf3ce44SJohn Forte /*EMPTY*/ 2184*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2185*fcf3ce44SJohn Forte } 2186*fcf3ce44SJohn Forte return (rval); 2187*fcf3ce44SJohn Forte } 2188*fcf3ce44SJohn Forte 2189*fcf3ce44SJohn Forte /* 2190*fcf3ce44SJohn Forte * ql_load_isp_firmware 2191*fcf3ce44SJohn Forte * Load and start RISC firmware. 2192*fcf3ce44SJohn Forte * Uses request ring for DMA buffer. 2193*fcf3ce44SJohn Forte * 2194*fcf3ce44SJohn Forte * Input: 2195*fcf3ce44SJohn Forte * ha = adapter state pointer. 2196*fcf3ce44SJohn Forte * 2197*fcf3ce44SJohn Forte * Returns: 2198*fcf3ce44SJohn Forte * ql local function return status code. 2199*fcf3ce44SJohn Forte * 2200*fcf3ce44SJohn Forte * Context: 2201*fcf3ce44SJohn Forte * Kernel context. 2202*fcf3ce44SJohn Forte */ 2203*fcf3ce44SJohn Forte int 2204*fcf3ce44SJohn Forte ql_load_isp_firmware(ql_adapter_state_t *vha) 2205*fcf3ce44SJohn Forte { 2206*fcf3ce44SJohn Forte caddr_t risc_code_address; 2207*fcf3ce44SJohn Forte uint32_t risc_address, risc_code_size; 2208*fcf3ce44SJohn Forte int rval; 2209*fcf3ce44SJohn Forte uint32_t word_count, cnt; 2210*fcf3ce44SJohn Forte size_t byte_count; 2211*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 2212*fcf3ce44SJohn Forte 2213*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) { 2214*fcf3ce44SJohn Forte return (ql_load_flash_fw(ha)); 2215*fcf3ce44SJohn Forte } 2216*fcf3ce44SJohn Forte 2217*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2218*fcf3ce44SJohn Forte 2219*fcf3ce44SJohn Forte /* Load firmware segments */ 2220*fcf3ce44SJohn Forte for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS && 2221*fcf3ce44SJohn Forte ha->risc_fw[cnt].code != NULL; cnt++) { 2222*fcf3ce44SJohn Forte 2223*fcf3ce44SJohn Forte risc_code_address = ha->risc_fw[cnt].code; 2224*fcf3ce44SJohn Forte risc_address = ha->risc_fw[cnt].addr; 2225*fcf3ce44SJohn Forte risc_code_size = ha->risc_fw[cnt].length; 2226*fcf3ce44SJohn Forte 2227*fcf3ce44SJohn Forte while (risc_code_size) { 2228*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 2229*fcf3ce44SJohn Forte word_count = ha->fw_transfer_size >> 2; 2230*fcf3ce44SJohn Forte if (word_count > risc_code_size) { 2231*fcf3ce44SJohn Forte word_count = risc_code_size; 2232*fcf3ce44SJohn Forte } 2233*fcf3ce44SJohn Forte byte_count = word_count << 2; 2234*fcf3ce44SJohn Forte 2235*fcf3ce44SJohn Forte ddi_rep_put32(ha->hba_buf.acc_handle, 2236*fcf3ce44SJohn Forte (uint32_t *)risc_code_address, 2237*fcf3ce44SJohn Forte (uint32_t *)ha->request_ring_bp, 2238*fcf3ce44SJohn Forte word_count, DDI_DEV_AUTOINCR); 2239*fcf3ce44SJohn Forte } else { 2240*fcf3ce44SJohn Forte word_count = ha->fw_transfer_size >> 1; 2241*fcf3ce44SJohn Forte if (word_count > risc_code_size) { 2242*fcf3ce44SJohn Forte word_count = risc_code_size; 2243*fcf3ce44SJohn Forte } 2244*fcf3ce44SJohn Forte byte_count = word_count << 1; 2245*fcf3ce44SJohn Forte 2246*fcf3ce44SJohn Forte ddi_rep_put16(ha->hba_buf.acc_handle, 2247*fcf3ce44SJohn Forte (uint16_t *)risc_code_address, 2248*fcf3ce44SJohn Forte (uint16_t *)ha->request_ring_bp, 2249*fcf3ce44SJohn Forte word_count, DDI_DEV_AUTOINCR); 2250*fcf3ce44SJohn Forte } 2251*fcf3ce44SJohn Forte 2252*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 2253*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET, byte_count, 2254*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 2255*fcf3ce44SJohn Forte 2256*fcf3ce44SJohn Forte rval = ql_wrt_risc_ram(ha, risc_address, 2257*fcf3ce44SJohn Forte ha->request_dvma, word_count); 2258*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2259*fcf3ce44SJohn Forte EL(ha, "failed, load=%xh\n", rval); 2260*fcf3ce44SJohn Forte cnt = MAX_RISC_CODE_SEGMENTS; 2261*fcf3ce44SJohn Forte break; 2262*fcf3ce44SJohn Forte } 2263*fcf3ce44SJohn Forte 2264*fcf3ce44SJohn Forte risc_address += word_count; 2265*fcf3ce44SJohn Forte risc_code_size -= word_count; 2266*fcf3ce44SJohn Forte risc_code_address += byte_count; 2267*fcf3ce44SJohn Forte } 2268*fcf3ce44SJohn Forte } 2269*fcf3ce44SJohn Forte 2270*fcf3ce44SJohn Forte /* Start firmware. */ 2271*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2272*fcf3ce44SJohn Forte rval = ql_start_firmware(ha); 2273*fcf3ce44SJohn Forte } 2274*fcf3ce44SJohn Forte 2275*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2276*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2277*fcf3ce44SJohn Forte } else { 2278*fcf3ce44SJohn Forte /*EMPTY*/ 2279*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2280*fcf3ce44SJohn Forte } 2281*fcf3ce44SJohn Forte 2282*fcf3ce44SJohn Forte return (rval); 2283*fcf3ce44SJohn Forte } 2284*fcf3ce44SJohn Forte 2285*fcf3ce44SJohn Forte /* 2286*fcf3ce44SJohn Forte * ql_load_flash_fw 2287*fcf3ce44SJohn Forte * Gets ISP24xx firmware from flash and loads ISP. 2288*fcf3ce44SJohn Forte * 2289*fcf3ce44SJohn Forte * Input: 2290*fcf3ce44SJohn Forte * ha: adapter state pointer. 2291*fcf3ce44SJohn Forte * 2292*fcf3ce44SJohn Forte * Returns: 2293*fcf3ce44SJohn Forte * qla local function return status code. 2294*fcf3ce44SJohn Forte */ 2295*fcf3ce44SJohn Forte static int 2296*fcf3ce44SJohn Forte ql_load_flash_fw(ql_adapter_state_t *ha) 2297*fcf3ce44SJohn Forte { 2298*fcf3ce44SJohn Forte int rval; 2299*fcf3ce44SJohn Forte uint8_t seg_cnt; 2300*fcf3ce44SJohn Forte uint32_t risc_address, xfer_size, count, *bp, faddr; 2301*fcf3ce44SJohn Forte uint32_t flash_addr = FLASH_24XX_FIRMWARE_ADDR; 2302*fcf3ce44SJohn Forte uint32_t risc_code_size = 0; 2303*fcf3ce44SJohn Forte 2304*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2305*fcf3ce44SJohn Forte 2306*fcf3ce44SJohn Forte /* Adjust addr for 32 bit words */ 2307*fcf3ce44SJohn Forte flash_addr = flash_addr / 4; 2308*fcf3ce44SJohn Forte 2309*fcf3ce44SJohn Forte for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) { 2310*fcf3ce44SJohn Forte xfer_size = ha->fw_transfer_size >> 2; 2311*fcf3ce44SJohn Forte do { 2312*fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 2313*fcf3ce44SJohn Forte 2314*fcf3ce44SJohn Forte /* Read data from flash. */ 2315*fcf3ce44SJohn Forte bp = (uint32_t *)ha->request_ring_bp; 2316*fcf3ce44SJohn Forte faddr = FLASH_DATA_ADDR | flash_addr; 2317*fcf3ce44SJohn Forte for (count = 0; count < xfer_size; count++) { 2318*fcf3ce44SJohn Forte rval = ql_24xx_read_flash(ha, faddr++, bp); 2319*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2320*fcf3ce44SJohn Forte break; 2321*fcf3ce44SJohn Forte } 2322*fcf3ce44SJohn Forte ql_chg_endian((uint8_t *)bp++, 4); 2323*fcf3ce44SJohn Forte } 2324*fcf3ce44SJohn Forte 2325*fcf3ce44SJohn Forte GLOBAL_HW_UNLOCK(); 2326*fcf3ce44SJohn Forte 2327*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2328*fcf3ce44SJohn Forte EL(ha, "24xx_read_flash failed=%xh\n", rval); 2329*fcf3ce44SJohn Forte break; 2330*fcf3ce44SJohn Forte } 2331*fcf3ce44SJohn Forte 2332*fcf3ce44SJohn Forte if (risc_code_size == 0) { 2333*fcf3ce44SJohn Forte bp = (uint32_t *)ha->request_ring_bp; 2334*fcf3ce44SJohn Forte risc_address = bp[2]; 2335*fcf3ce44SJohn Forte risc_code_size = bp[3]; 2336*fcf3ce44SJohn Forte ha->risc_fw[seg_cnt].addr = risc_address; 2337*fcf3ce44SJohn Forte ha->risc_fw[seg_cnt].length = risc_code_size; 2338*fcf3ce44SJohn Forte } 2339*fcf3ce44SJohn Forte 2340*fcf3ce44SJohn Forte if (risc_code_size < xfer_size) { 2341*fcf3ce44SJohn Forte xfer_size = risc_code_size; 2342*fcf3ce44SJohn Forte } 2343*fcf3ce44SJohn Forte 2344*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 2345*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET, xfer_size << 2, 2346*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 2347*fcf3ce44SJohn Forte 2348*fcf3ce44SJohn Forte rval = ql_wrt_risc_ram(ha, risc_address, 2349*fcf3ce44SJohn Forte ha->request_dvma, xfer_size); 2350*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2351*fcf3ce44SJohn Forte EL(ha, "ql_wrt_risc_ram failed=%xh\n", rval); 2352*fcf3ce44SJohn Forte break; 2353*fcf3ce44SJohn Forte } 2354*fcf3ce44SJohn Forte 2355*fcf3ce44SJohn Forte risc_address += xfer_size; 2356*fcf3ce44SJohn Forte risc_code_size -= xfer_size; 2357*fcf3ce44SJohn Forte flash_addr += xfer_size; 2358*fcf3ce44SJohn Forte } while (risc_code_size); 2359*fcf3ce44SJohn Forte 2360*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2361*fcf3ce44SJohn Forte break; 2362*fcf3ce44SJohn Forte } 2363*fcf3ce44SJohn Forte } 2364*fcf3ce44SJohn Forte 2365*fcf3ce44SJohn Forte /* Start firmware. */ 2366*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2367*fcf3ce44SJohn Forte rval = ql_start_firmware(ha); 2368*fcf3ce44SJohn Forte } 2369*fcf3ce44SJohn Forte 2370*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2371*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2372*fcf3ce44SJohn Forte } else { 2373*fcf3ce44SJohn Forte /*EMPTY*/ 2374*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2375*fcf3ce44SJohn Forte } 2376*fcf3ce44SJohn Forte return (rval); 2377*fcf3ce44SJohn Forte } 2378*fcf3ce44SJohn Forte 2379*fcf3ce44SJohn Forte /* 2380*fcf3ce44SJohn Forte * ql_start_firmware 2381*fcf3ce44SJohn Forte * Starts RISC code. 2382*fcf3ce44SJohn Forte * 2383*fcf3ce44SJohn Forte * Input: 2384*fcf3ce44SJohn Forte * ha = adapter state pointer. 2385*fcf3ce44SJohn Forte * 2386*fcf3ce44SJohn Forte * Returns: 2387*fcf3ce44SJohn Forte * ql local function return status code. 2388*fcf3ce44SJohn Forte * 2389*fcf3ce44SJohn Forte * Context: 2390*fcf3ce44SJohn Forte * Kernel context. 2391*fcf3ce44SJohn Forte */ 2392*fcf3ce44SJohn Forte int 2393*fcf3ce44SJohn Forte ql_start_firmware(ql_adapter_state_t *vha) 2394*fcf3ce44SJohn Forte { 2395*fcf3ce44SJohn Forte int rval; 2396*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2397*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 2398*fcf3ce44SJohn Forte 2399*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2400*fcf3ce44SJohn Forte 2401*fcf3ce44SJohn Forte /* Verify checksum of loaded RISC code. */ 2402*fcf3ce44SJohn Forte rval = ql_verify_checksum(ha); 2403*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2404*fcf3ce44SJohn Forte /* Start firmware execution. */ 2405*fcf3ce44SJohn Forte (void) ql_execute_fw(ha); 2406*fcf3ce44SJohn Forte 2407*fcf3ce44SJohn Forte /* Save firmware version. */ 2408*fcf3ce44SJohn Forte (void) ql_get_fw_version(ha, &mr); 2409*fcf3ce44SJohn Forte ha->fw_major_version = mr.mb[1]; 2410*fcf3ce44SJohn Forte ha->fw_minor_version = mr.mb[2]; 2411*fcf3ce44SJohn Forte ha->fw_subminor_version = mr.mb[3]; 2412*fcf3ce44SJohn Forte ha->fw_ext_memory_size = ((SHORT_TO_LONG(mr.mb[4], mr.mb[5]) - 2413*fcf3ce44SJohn Forte 0x100000) + 1) * 4; 2414*fcf3ce44SJohn Forte ha->fw_attributes = mr.mb[6]; 2415*fcf3ce44SJohn Forte 2416*fcf3ce44SJohn Forte /* Set Serdes Transmit Parameters. */ 2417*fcf3ce44SJohn Forte if (ha->serdes_param[0] & BIT_0) { 2418*fcf3ce44SJohn Forte mr.mb[1] = ha->serdes_param[0]; 2419*fcf3ce44SJohn Forte mr.mb[2] = ha->serdes_param[1]; 2420*fcf3ce44SJohn Forte mr.mb[3] = ha->serdes_param[2]; 2421*fcf3ce44SJohn Forte mr.mb[4] = ha->serdes_param[3]; 2422*fcf3ce44SJohn Forte (void) ql_serdes_param(ha, &mr); 2423*fcf3ce44SJohn Forte } 2424*fcf3ce44SJohn Forte } 2425*fcf3ce44SJohn Forte 2426*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2427*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~FIRMWARE_LOADED; 2428*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2429*fcf3ce44SJohn Forte } else { 2430*fcf3ce44SJohn Forte ha->task_daemon_flags |= FIRMWARE_LOADED; 2431*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2432*fcf3ce44SJohn Forte } 2433*fcf3ce44SJohn Forte return (rval); 2434*fcf3ce44SJohn Forte } 2435*fcf3ce44SJohn Forte 2436*fcf3ce44SJohn Forte /* 2437*fcf3ce44SJohn Forte * ql_set_cache_line 2438*fcf3ce44SJohn Forte * Sets PCI cache line parameter. 2439*fcf3ce44SJohn Forte * 2440*fcf3ce44SJohn Forte * Input: 2441*fcf3ce44SJohn Forte * ha = adapter state pointer. 2442*fcf3ce44SJohn Forte * 2443*fcf3ce44SJohn Forte * Returns: 2444*fcf3ce44SJohn Forte * ql local function return status code. 2445*fcf3ce44SJohn Forte * 2446*fcf3ce44SJohn Forte * Context: 2447*fcf3ce44SJohn Forte * Kernel context. 2448*fcf3ce44SJohn Forte */ 2449*fcf3ce44SJohn Forte int 2450*fcf3ce44SJohn Forte ql_set_cache_line(ql_adapter_state_t *ha) 2451*fcf3ce44SJohn Forte { 2452*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2453*fcf3ce44SJohn Forte 2454*fcf3ce44SJohn Forte /* Set the cache line. */ 2455*fcf3ce44SJohn Forte if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) { 2456*fcf3ce44SJohn Forte /* Set cache line register. */ 2457*fcf3ce44SJohn Forte ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1); 2458*fcf3ce44SJohn Forte } 2459*fcf3ce44SJohn Forte 2460*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2461*fcf3ce44SJohn Forte 2462*fcf3ce44SJohn Forte return (QL_SUCCESS); 2463*fcf3ce44SJohn Forte } 2464*fcf3ce44SJohn Forte 2465*fcf3ce44SJohn Forte /* 2466*fcf3ce44SJohn Forte * ql_init_rings 2467*fcf3ce44SJohn Forte * Initializes firmware and ring pointers. 2468*fcf3ce44SJohn Forte * 2469*fcf3ce44SJohn Forte * Beginning of response ring has initialization control block 2470*fcf3ce44SJohn Forte * already built by nvram config routine. 2471*fcf3ce44SJohn Forte * 2472*fcf3ce44SJohn Forte * Input: 2473*fcf3ce44SJohn Forte * ha = adapter state pointer. 2474*fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 2475*fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 2476*fcf3ce44SJohn Forte * 2477*fcf3ce44SJohn Forte * Returns: 2478*fcf3ce44SJohn Forte * ql local function return status code. 2479*fcf3ce44SJohn Forte * 2480*fcf3ce44SJohn Forte * Context: 2481*fcf3ce44SJohn Forte * Kernel context. 2482*fcf3ce44SJohn Forte */ 2483*fcf3ce44SJohn Forte int 2484*fcf3ce44SJohn Forte ql_init_rings(ql_adapter_state_t *vha2) 2485*fcf3ce44SJohn Forte { 2486*fcf3ce44SJohn Forte int rval, rval2; 2487*fcf3ce44SJohn Forte uint16_t index; 2488*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2489*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha2->pha; 2490*fcf3ce44SJohn Forte 2491*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2492*fcf3ce44SJohn Forte 2493*fcf3ce44SJohn Forte /* Clear outstanding commands array. */ 2494*fcf3ce44SJohn Forte for (index = 0; index < MAX_OUTSTANDING_COMMANDS; index++) { 2495*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 2496*fcf3ce44SJohn Forte } 2497*fcf3ce44SJohn Forte ha->osc_index = 1; 2498*fcf3ce44SJohn Forte 2499*fcf3ce44SJohn Forte ha->pending_cmds.first = NULL; 2500*fcf3ce44SJohn Forte ha->pending_cmds.last = NULL; 2501*fcf3ce44SJohn Forte 2502*fcf3ce44SJohn Forte /* Initialize firmware. */ 2503*fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 2504*fcf3ce44SJohn Forte ha->req_ring_index = 0; 2505*fcf3ce44SJohn Forte ha->req_q_cnt = REQUEST_ENTRY_CNT - 1; 2506*fcf3ce44SJohn Forte ha->response_ring_ptr = ha->response_ring_bp; 2507*fcf3ce44SJohn Forte ha->rsp_ring_index = 0; 2508*fcf3ce44SJohn Forte 2509*fcf3ce44SJohn Forte if (ha->flags & VP_ENABLED) { 2510*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 2511*fcf3ce44SJohn Forte uint16_t cnt; 2512*fcf3ce44SJohn Forte uint32_t max_vports; 2513*fcf3ce44SJohn Forte ql_init_24xx_cb_t *icb = &ha->init_ctrl_blk.cb24; 2514*fcf3ce44SJohn Forte 2515*fcf3ce44SJohn Forte max_vports = (CFG_IST(ha, CFG_CTRL_2422) ? 2516*fcf3ce44SJohn Forte MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS); 2517*fcf3ce44SJohn Forte bzero(icb->vp_count, 2518*fcf3ce44SJohn Forte ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) - 2519*fcf3ce44SJohn Forte (uintptr_t)icb->vp_count); 2520*fcf3ce44SJohn Forte icb->vp_count[0] = (uint8_t)max_vports; 2521*fcf3ce44SJohn Forte 2522*fcf3ce44SJohn Forte /* Allow connection option 2. */ 2523*fcf3ce44SJohn Forte icb->global_vp_option[0] = BIT_1; 2524*fcf3ce44SJohn Forte 2525*fcf3ce44SJohn Forte for (cnt = 0, vha = ha->vp_next; cnt < max_vports && 2526*fcf3ce44SJohn Forte vha != NULL; vha = vha->vp_next, cnt++) { 2527*fcf3ce44SJohn Forte 2528*fcf3ce44SJohn Forte index = (uint8_t)(vha->vp_index - 1); 2529*fcf3ce44SJohn Forte bcopy(vha->loginparams.node_ww_name.raw_wwn, 2530*fcf3ce44SJohn Forte icb->vpc[index].node_name, 8); 2531*fcf3ce44SJohn Forte bcopy(vha->loginparams.nport_ww_name.raw_wwn, 2532*fcf3ce44SJohn Forte icb->vpc[index].port_name, 8); 2533*fcf3ce44SJohn Forte 2534*fcf3ce44SJohn Forte icb->vpc[index].options = VPO_TARGET_MODE_DISABLED | 2535*fcf3ce44SJohn Forte VPO_INITIATOR_MODE_ENABLED; 2536*fcf3ce44SJohn Forte if (vha->flags & VP_ENABLED) { 2537*fcf3ce44SJohn Forte icb->vpc[index].options = (uint8_t) 2538*fcf3ce44SJohn Forte (icb->vpc[index].options | VPO_ENABLED); 2539*fcf3ce44SJohn Forte } 2540*fcf3ce44SJohn Forte } 2541*fcf3ce44SJohn Forte } 2542*fcf3ce44SJohn Forte 2543*fcf3ce44SJohn Forte rval = ql_init_firmware(ha); 2544*fcf3ce44SJohn Forte 2545*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && (CFG_IST(ha, CFG_CTRL_2425)) == 0) { 2546*fcf3ce44SJohn Forte /* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */ 2547*fcf3ce44SJohn Forte rval = ql_get_firmware_option(ha, &mr); 2548*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2549*fcf3ce44SJohn Forte mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9); 2550*fcf3ce44SJohn Forte mr.mb[2] = 0; 2551*fcf3ce44SJohn Forte mr.mb[3] = BIT_10; 2552*fcf3ce44SJohn Forte rval = ql_set_firmware_option(ha, &mr); 2553*fcf3ce44SJohn Forte } 2554*fcf3ce44SJohn Forte } 2555*fcf3ce44SJohn Forte 2556*fcf3ce44SJohn Forte if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) { 2557*fcf3ce44SJohn Forte if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf, 2558*fcf3ce44SJohn Forte FWFCESIZE, LITTLE_ENDIAN_DMA, MEM_RING_ALIGN)) 2559*fcf3ce44SJohn Forte != QL_SUCCESS) { 2560*fcf3ce44SJohn Forte EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2); 2561*fcf3ce44SJohn Forte } else { 2562*fcf3ce44SJohn Forte if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf, 2563*fcf3ce44SJohn Forte FTO_FCEENABLE)) != QL_SUCCESS) { 2564*fcf3ce44SJohn Forte EL(ha, "fcetrace enable failed: %xh\n", rval2); 2565*fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwfcetracebuf); 2566*fcf3ce44SJohn Forte } 2567*fcf3ce44SJohn Forte } 2568*fcf3ce44SJohn Forte } 2569*fcf3ce44SJohn Forte 2570*fcf3ce44SJohn Forte if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) { 2571*fcf3ce44SJohn Forte if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf, 2572*fcf3ce44SJohn Forte FWEXTSIZE, LITTLE_ENDIAN_DMA, MEM_RING_ALIGN)) 2573*fcf3ce44SJohn Forte != QL_SUCCESS) { 2574*fcf3ce44SJohn Forte EL(ha, "exttrace buffer alloc failed: %xh\n", rval2); 2575*fcf3ce44SJohn Forte } else { 2576*fcf3ce44SJohn Forte if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf, 2577*fcf3ce44SJohn Forte FTO_EXTENABLE)) != QL_SUCCESS) { 2578*fcf3ce44SJohn Forte EL(ha, "exttrace enable failed: %xh\n", rval2); 2579*fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwexttracebuf); 2580*fcf3ce44SJohn Forte } 2581*fcf3ce44SJohn Forte } 2582*fcf3ce44SJohn Forte } 2583*fcf3ce44SJohn Forte 2584*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) { 2585*fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 2586*fcf3ce44SJohn Forte clock_t timer; 2587*fcf3ce44SJohn Forte 2588*fcf3ce44SJohn Forte /* Wait for firmware login of menlo. */ 2589*fcf3ce44SJohn Forte for (timer = 3000; timer; timer--) { 2590*fcf3ce44SJohn Forte if (ha->flags & MENLO_LOGIN_OPERATIONAL) { 2591*fcf3ce44SJohn Forte break; 2592*fcf3ce44SJohn Forte } 2593*fcf3ce44SJohn Forte 2594*fcf3ce44SJohn Forte if (!(ha->flags & INTERRUPTS_ENABLED) || 2595*fcf3ce44SJohn Forte ddi_in_panic()) { 2596*fcf3ce44SJohn Forte if (RD16_IO_REG(ha, istatus) & RISC_INT) { 2597*fcf3ce44SJohn Forte (void) ql_isr((caddr_t)ha); 2598*fcf3ce44SJohn Forte INTR_LOCK(ha); 2599*fcf3ce44SJohn Forte ha->intr_claimed = B_TRUE; 2600*fcf3ce44SJohn Forte INTR_UNLOCK(ha); 2601*fcf3ce44SJohn Forte } 2602*fcf3ce44SJohn Forte } 2603*fcf3ce44SJohn Forte 2604*fcf3ce44SJohn Forte /* Delay for 1 tick (10 milliseconds). */ 2605*fcf3ce44SJohn Forte ql_delay(ha, 10000); 2606*fcf3ce44SJohn Forte } 2607*fcf3ce44SJohn Forte 2608*fcf3ce44SJohn Forte if (timer == 0) { 2609*fcf3ce44SJohn Forte rval = QL_FUNCTION_TIMEOUT; 2610*fcf3ce44SJohn Forte } else { 2611*fcf3ce44SJohn Forte pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP); 2612*fcf3ce44SJohn Forte if (pkt == NULL) { 2613*fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 2614*fcf3ce44SJohn Forte rval = QL_MEMORY_ALLOC_FAILED; 2615*fcf3ce44SJohn Forte } else { 2616*fcf3ce44SJohn Forte pkt->mvfy.entry_type = VERIFY_MENLO_TYPE; 2617*fcf3ce44SJohn Forte pkt->mvfy.entry_count = 1; 2618*fcf3ce44SJohn Forte pkt->mvfy.options_status = 2619*fcf3ce44SJohn Forte LE_16(VMF_DO_NOT_UPDATE_FW); 2620*fcf3ce44SJohn Forte 2621*fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 2622*fcf3ce44SJohn Forte sizeof (ql_mbx_iocb_t)); 2623*fcf3ce44SJohn Forte LITTLE_ENDIAN_16(&pkt->mvfy.options_status); 2624*fcf3ce44SJohn Forte LITTLE_ENDIAN_16(&pkt->mvfy.failure_code); 2625*fcf3ce44SJohn Forte 2626*fcf3ce44SJohn Forte if (rval != QL_SUCCESS || 2627*fcf3ce44SJohn Forte (pkt->mvfy.entry_status & 0x3c) != 0 || 2628*fcf3ce44SJohn Forte pkt->mvfy.options_status != CS_COMPLETE) { 2629*fcf3ce44SJohn Forte EL(ha, "failed, status=%xh, es=%xh, " 2630*fcf3ce44SJohn Forte "cs=%xh, fc=%xh\n", rval, 2631*fcf3ce44SJohn Forte pkt->mvfy.entry_status & 0x3c, 2632*fcf3ce44SJohn Forte pkt->mvfy.options_status, 2633*fcf3ce44SJohn Forte pkt->mvfy.failure_code); 2634*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2635*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2636*fcf3ce44SJohn Forte } 2637*fcf3ce44SJohn Forte } 2638*fcf3ce44SJohn Forte 2639*fcf3ce44SJohn Forte kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 2640*fcf3ce44SJohn Forte } 2641*fcf3ce44SJohn Forte } 2642*fcf3ce44SJohn Forte } 2643*fcf3ce44SJohn Forte 2644*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2645*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2646*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~FIRMWARE_UP; 2647*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2648*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2649*fcf3ce44SJohn Forte } else { 2650*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2651*fcf3ce44SJohn Forte ha->task_daemon_flags |= FIRMWARE_UP; 2652*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2653*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2654*fcf3ce44SJohn Forte } 2655*fcf3ce44SJohn Forte return (rval); 2656*fcf3ce44SJohn Forte } 2657*fcf3ce44SJohn Forte 2658*fcf3ce44SJohn Forte /* 2659*fcf3ce44SJohn Forte * ql_fw_ready 2660*fcf3ce44SJohn Forte * Waits for firmware ready. If firmware becomes ready 2661*fcf3ce44SJohn Forte * device queues and RISC code are synchronized. 2662*fcf3ce44SJohn Forte * 2663*fcf3ce44SJohn Forte * Input: 2664*fcf3ce44SJohn Forte * ha = adapter state pointer. 2665*fcf3ce44SJohn Forte * secs = max wait time, in seconds (0-255). 2666*fcf3ce44SJohn Forte * 2667*fcf3ce44SJohn Forte * Returns: 2668*fcf3ce44SJohn Forte * ql local function return status code. 2669*fcf3ce44SJohn Forte * 2670*fcf3ce44SJohn Forte * Context: 2671*fcf3ce44SJohn Forte * Kernel context. 2672*fcf3ce44SJohn Forte */ 2673*fcf3ce44SJohn Forte int 2674*fcf3ce44SJohn Forte ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs) 2675*fcf3ce44SJohn Forte { 2676*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2677*fcf3ce44SJohn Forte clock_t timer; 2678*fcf3ce44SJohn Forte clock_t dly = 250000; 2679*fcf3ce44SJohn Forte clock_t sec_delay = MICROSEC / dly; 2680*fcf3ce44SJohn Forte clock_t wait = secs * sec_delay; 2681*fcf3ce44SJohn Forte int rval = QL_FUNCTION_FAILED; 2682*fcf3ce44SJohn Forte uint16_t state = 0xffff; 2683*fcf3ce44SJohn Forte 2684*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2685*fcf3ce44SJohn Forte 2686*fcf3ce44SJohn Forte timer = ha->r_a_tov < secs ? secs : ha->r_a_tov; 2687*fcf3ce44SJohn Forte timer = (timer + 2) * sec_delay; 2688*fcf3ce44SJohn Forte 2689*fcf3ce44SJohn Forte /* Wait for ISP to finish LIP */ 2690*fcf3ce44SJohn Forte while (timer != 0 && wait != 0 && 2691*fcf3ce44SJohn Forte !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) { 2692*fcf3ce44SJohn Forte 2693*fcf3ce44SJohn Forte rval = ql_get_firmware_state(ha, &mr); 2694*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2695*fcf3ce44SJohn Forte if (ha->task_daemon_flags & (ISP_ABORT_NEEDED | 2696*fcf3ce44SJohn Forte LOOP_DOWN)) { 2697*fcf3ce44SJohn Forte wait--; 2698*fcf3ce44SJohn Forte } else if (mr.mb[1] != FSTATE_READY) { 2699*fcf3ce44SJohn Forte if (mr.mb[1] != FSTATE_WAIT_LOGIN) { 2700*fcf3ce44SJohn Forte wait--; 2701*fcf3ce44SJohn Forte } 2702*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2703*fcf3ce44SJohn Forte } else { 2704*fcf3ce44SJohn Forte /* Firmware is ready. Get 2 * R_A_TOV. */ 2705*fcf3ce44SJohn Forte rval = ql_get_timeout_parameters(ha, 2706*fcf3ce44SJohn Forte &ha->r_a_tov); 2707*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2708*fcf3ce44SJohn Forte EL(ha, "failed, get_timeout_param" 2709*fcf3ce44SJohn Forte "=%xh\n", rval); 2710*fcf3ce44SJohn Forte } 2711*fcf3ce44SJohn Forte 2712*fcf3ce44SJohn Forte /* Configure loop. */ 2713*fcf3ce44SJohn Forte rval = ql_configure_loop(ha); 2714*fcf3ce44SJohn Forte (void) ql_marker(ha, 0, 0, MK_SYNC_ALL); 2715*fcf3ce44SJohn Forte 2716*fcf3ce44SJohn Forte if (ha->task_daemon_flags & 2717*fcf3ce44SJohn Forte LOOP_RESYNC_NEEDED) { 2718*fcf3ce44SJohn Forte wait--; 2719*fcf3ce44SJohn Forte EL(ha, "loop trans; tdf=%xh\n", 2720*fcf3ce44SJohn Forte ha->task_daemon_flags); 2721*fcf3ce44SJohn Forte } else { 2722*fcf3ce44SJohn Forte break; 2723*fcf3ce44SJohn Forte } 2724*fcf3ce44SJohn Forte } 2725*fcf3ce44SJohn Forte } else { 2726*fcf3ce44SJohn Forte wait--; 2727*fcf3ce44SJohn Forte } 2728*fcf3ce44SJohn Forte 2729*fcf3ce44SJohn Forte if (state != mr.mb[1]) { 2730*fcf3ce44SJohn Forte EL(ha, "mailbox_reg[1] = %xh\n", mr.mb[1]); 2731*fcf3ce44SJohn Forte state = mr.mb[1]; 2732*fcf3ce44SJohn Forte } 2733*fcf3ce44SJohn Forte 2734*fcf3ce44SJohn Forte /* Delay for a tick if waiting. */ 2735*fcf3ce44SJohn Forte if (timer-- != 0 && wait != 0) { 2736*fcf3ce44SJohn Forte if (timer % 4 == 0) { 2737*fcf3ce44SJohn Forte delay(drv_usectohz(dly)); 2738*fcf3ce44SJohn Forte } else { 2739*fcf3ce44SJohn Forte drv_usecwait(dly); 2740*fcf3ce44SJohn Forte } 2741*fcf3ce44SJohn Forte } else { 2742*fcf3ce44SJohn Forte rval = QL_FUNCTION_TIMEOUT; 2743*fcf3ce44SJohn Forte } 2744*fcf3ce44SJohn Forte } 2745*fcf3ce44SJohn Forte 2746*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2747*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2748*fcf3ce44SJohn Forte } else { 2749*fcf3ce44SJohn Forte /*EMPTY*/ 2750*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2751*fcf3ce44SJohn Forte } 2752*fcf3ce44SJohn Forte return (rval); 2753*fcf3ce44SJohn Forte } 2754*fcf3ce44SJohn Forte 2755*fcf3ce44SJohn Forte /* 2756*fcf3ce44SJohn Forte * ql_configure_loop 2757*fcf3ce44SJohn Forte * Setup configurations based on loop. 2758*fcf3ce44SJohn Forte * 2759*fcf3ce44SJohn Forte * Input: 2760*fcf3ce44SJohn Forte * ha = adapter state pointer. 2761*fcf3ce44SJohn Forte * 2762*fcf3ce44SJohn Forte * Returns: 2763*fcf3ce44SJohn Forte * ql local function return status code. 2764*fcf3ce44SJohn Forte * 2765*fcf3ce44SJohn Forte * Context: 2766*fcf3ce44SJohn Forte * Kernel context. 2767*fcf3ce44SJohn Forte */ 2768*fcf3ce44SJohn Forte static int 2769*fcf3ce44SJohn Forte ql_configure_loop(ql_adapter_state_t *ha) 2770*fcf3ce44SJohn Forte { 2771*fcf3ce44SJohn Forte int rval; 2772*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 2773*fcf3ce44SJohn Forte 2774*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2775*fcf3ce44SJohn Forte 2776*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 2777*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2778*fcf3ce44SJohn Forte if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) && 2779*fcf3ce44SJohn Forte vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) { 2780*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2781*fcf3ce44SJohn Forte continue; 2782*fcf3ce44SJohn Forte } 2783*fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED; 2784*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2785*fcf3ce44SJohn Forte 2786*fcf3ce44SJohn Forte rval = ql_configure_hba(vha); 2787*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && !(ha->task_daemon_flags & 2788*fcf3ce44SJohn Forte (LOOP_RESYNC_NEEDED | LOOP_DOWN))) { 2789*fcf3ce44SJohn Forte rval = ql_configure_device_d_id(vha); 2790*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && !(ha->task_daemon_flags & 2791*fcf3ce44SJohn Forte (LOOP_RESYNC_NEEDED | LOOP_DOWN))) { 2792*fcf3ce44SJohn Forte (void) ql_configure_fabric(vha); 2793*fcf3ce44SJohn Forte } 2794*fcf3ce44SJohn Forte } 2795*fcf3ce44SJohn Forte } 2796*fcf3ce44SJohn Forte 2797*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2798*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2799*fcf3ce44SJohn Forte } else { 2800*fcf3ce44SJohn Forte /*EMPTY*/ 2801*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2802*fcf3ce44SJohn Forte } 2803*fcf3ce44SJohn Forte return (rval); 2804*fcf3ce44SJohn Forte } 2805*fcf3ce44SJohn Forte 2806*fcf3ce44SJohn Forte /* 2807*fcf3ce44SJohn Forte * ql_configure_hba 2808*fcf3ce44SJohn Forte * Setup adapter context. 2809*fcf3ce44SJohn Forte * 2810*fcf3ce44SJohn Forte * Input: 2811*fcf3ce44SJohn Forte * ha = adapter state pointer. 2812*fcf3ce44SJohn Forte * 2813*fcf3ce44SJohn Forte * Returns: 2814*fcf3ce44SJohn Forte * ql local function return status code. 2815*fcf3ce44SJohn Forte * 2816*fcf3ce44SJohn Forte * Context: 2817*fcf3ce44SJohn Forte * Kernel context. 2818*fcf3ce44SJohn Forte */ 2819*fcf3ce44SJohn Forte static int 2820*fcf3ce44SJohn Forte ql_configure_hba(ql_adapter_state_t *ha) 2821*fcf3ce44SJohn Forte { 2822*fcf3ce44SJohn Forte uint8_t *bp; 2823*fcf3ce44SJohn Forte int rval; 2824*fcf3ce44SJohn Forte uint32_t state; 2825*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2826*fcf3ce44SJohn Forte 2827*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2828*fcf3ce44SJohn Forte 2829*fcf3ce44SJohn Forte /* Get host addresses. */ 2830*fcf3ce44SJohn Forte rval = ql_get_adapter_id(ha, &mr); 2831*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2832*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & 2833*fcf3ce44SJohn Forte ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT)); 2834*fcf3ce44SJohn Forte 2835*fcf3ce44SJohn Forte /* Save Host d_id, alpa, loop ID. */ 2836*fcf3ce44SJohn Forte ha->loop_id = mr.mb[1]; 2837*fcf3ce44SJohn Forte ha->d_id.b.al_pa = LSB(mr.mb[2]); 2838*fcf3ce44SJohn Forte ha->d_id.b.area = MSB(mr.mb[2]); 2839*fcf3ce44SJohn Forte ha->d_id.b.domain = LSB(mr.mb[3]); 2840*fcf3ce44SJohn Forte 2841*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2842*fcf3ce44SJohn Forte ha->flags &= ~FDISC_ENABLED; 2843*fcf3ce44SJohn Forte 2844*fcf3ce44SJohn Forte /* Get loop topology. */ 2845*fcf3ce44SJohn Forte switch (mr.mb[6]) { 2846*fcf3ce44SJohn Forte case CNX_LOOP_NO_FABRIC: 2847*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_NL_PORT); 2848*fcf3ce44SJohn Forte break; 2849*fcf3ce44SJohn Forte case CNX_FLPORT_IN_LOOP: 2850*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_FL_PORT); 2851*fcf3ce44SJohn Forte break; 2852*fcf3ce44SJohn Forte case CNX_NPORT_2_NPORT_P2P: 2853*fcf3ce44SJohn Forte case CNX_NPORT_2_NPORT_NO_TGT_RSP: 2854*fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 2855*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_N_PORT); 2856*fcf3ce44SJohn Forte break; 2857*fcf3ce44SJohn Forte case CNX_FLPORT_P2P: 2858*fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 2859*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_F_PORT); 2860*fcf3ce44SJohn Forte 2861*fcf3ce44SJohn Forte /* Get supported option. */ 2862*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425) && 2863*fcf3ce44SJohn Forte mr.mb[7] & FLOGI_NPIV_SUPPORT) { 2864*fcf3ce44SJohn Forte ha->flags |= FDISC_ENABLED; 2865*fcf3ce44SJohn Forte } 2866*fcf3ce44SJohn Forte break; 2867*fcf3ce44SJohn Forte default: 2868*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d,%d): UNKNOWN topology=%xh, " 2869*fcf3ce44SJohn Forte "d_id=%xh\n", ha->instance, ha->vp_index, mr.mb[6], 2870*fcf3ce44SJohn Forte ha->d_id.b24); 2871*fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2872*fcf3ce44SJohn Forte break; 2873*fcf3ce44SJohn Forte } 2874*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2875*fcf3ce44SJohn Forte 2876*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300|CFG_CTRL_6322| 2877*fcf3ce44SJohn Forte CFG_CTRL_2425))) { 2878*fcf3ce44SJohn Forte mr.mb[1] = 0; 2879*fcf3ce44SJohn Forte mr.mb[2] = 0; 2880*fcf3ce44SJohn Forte rval = ql_data_rate(ha, &mr); 2881*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2882*fcf3ce44SJohn Forte EL(ha, "data_rate status=%xh\n", rval); 2883*fcf3ce44SJohn Forte state = FC_STATE_FULL_SPEED; 2884*fcf3ce44SJohn Forte } else { 2885*fcf3ce44SJohn Forte if (mr.mb[1] == 0) { 2886*fcf3ce44SJohn Forte state = FC_STATE_1GBIT_SPEED; 2887*fcf3ce44SJohn Forte } else if (mr.mb[1] == 1) { 2888*fcf3ce44SJohn Forte state = FC_STATE_2GBIT_SPEED; 2889*fcf3ce44SJohn Forte } else if (mr.mb[1] == 3) { 2890*fcf3ce44SJohn Forte state = FC_STATE_4GBIT_SPEED; 2891*fcf3ce44SJohn Forte } else if (mr.mb[1] == 4) { 2892*fcf3ce44SJohn Forte state = FC_STATE_8GBIT_SPEED; 2893*fcf3ce44SJohn Forte } else { 2894*fcf3ce44SJohn Forte state = 0; 2895*fcf3ce44SJohn Forte } 2896*fcf3ce44SJohn Forte } 2897*fcf3ce44SJohn Forte } else { 2898*fcf3ce44SJohn Forte state = FC_STATE_FULL_SPEED; 2899*fcf3ce44SJohn Forte } 2900*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK(ha->state) | state; 2901*fcf3ce44SJohn Forte } 2902*fcf3ce44SJohn Forte 2903*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2904*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2905*fcf3ce44SJohn Forte } else { 2906*fcf3ce44SJohn Forte bp = ha->loginparams.nport_ww_name.raw_wwn; 2907*fcf3ce44SJohn Forte EL(ha, "topology=%xh, d_id=%xh, " 2908*fcf3ce44SJohn Forte "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n", 2909*fcf3ce44SJohn Forte ha->topology, ha->d_id.b24, bp[0], bp[1], 2910*fcf3ce44SJohn Forte bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]); 2911*fcf3ce44SJohn Forte } 2912*fcf3ce44SJohn Forte return (rval); 2913*fcf3ce44SJohn Forte } 2914*fcf3ce44SJohn Forte 2915*fcf3ce44SJohn Forte /* 2916*fcf3ce44SJohn Forte * ql_configure_device_d_id 2917*fcf3ce44SJohn Forte * Updates device loop ID. 2918*fcf3ce44SJohn Forte * Also adds to device queue any new devices found on private loop. 2919*fcf3ce44SJohn Forte * 2920*fcf3ce44SJohn Forte * Input: 2921*fcf3ce44SJohn Forte * ha = adapter state pointer. 2922*fcf3ce44SJohn Forte * 2923*fcf3ce44SJohn Forte * Returns: 2924*fcf3ce44SJohn Forte * ql local function return status code. 2925*fcf3ce44SJohn Forte * 2926*fcf3ce44SJohn Forte * Context: 2927*fcf3ce44SJohn Forte * Kernel context. 2928*fcf3ce44SJohn Forte */ 2929*fcf3ce44SJohn Forte static int 2930*fcf3ce44SJohn Forte ql_configure_device_d_id(ql_adapter_state_t *ha) 2931*fcf3ce44SJohn Forte { 2932*fcf3ce44SJohn Forte port_id_t d_id; 2933*fcf3ce44SJohn Forte ql_link_t *link; 2934*fcf3ce44SJohn Forte int rval; 2935*fcf3ce44SJohn Forte int loop; 2936*fcf3ce44SJohn Forte ql_tgt_t *tq; 2937*fcf3ce44SJohn Forte ql_dev_id_list_t *list; 2938*fcf3ce44SJohn Forte uint32_t list_size; 2939*fcf3ce44SJohn Forte uint16_t index, loop_id; 2940*fcf3ce44SJohn Forte ql_mbx_data_t mr; 2941*fcf3ce44SJohn Forte uint8_t retries = MAX_DEVICE_LOST_RETRY; 2942*fcf3ce44SJohn Forte 2943*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2944*fcf3ce44SJohn Forte 2945*fcf3ce44SJohn Forte list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES; 2946*fcf3ce44SJohn Forte list = kmem_zalloc(list_size, KM_SLEEP); 2947*fcf3ce44SJohn Forte if (list == NULL) { 2948*fcf3ce44SJohn Forte rval = QL_MEMORY_ALLOC_FAILED; 2949*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2950*fcf3ce44SJohn Forte return (rval); 2951*fcf3ce44SJohn Forte } 2952*fcf3ce44SJohn Forte 2953*fcf3ce44SJohn Forte do { 2954*fcf3ce44SJohn Forte /* 2955*fcf3ce44SJohn Forte * Get data from RISC code d_id list to init each device queue. 2956*fcf3ce44SJohn Forte */ 2957*fcf3ce44SJohn Forte rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr); 2958*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2959*fcf3ce44SJohn Forte kmem_free(list, list_size); 2960*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2961*fcf3ce44SJohn Forte return (rval); 2962*fcf3ce44SJohn Forte } 2963*fcf3ce44SJohn Forte 2964*fcf3ce44SJohn Forte /* Acquire adapter state lock. */ 2965*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2966*fcf3ce44SJohn Forte 2967*fcf3ce44SJohn Forte /* Mark all queues as unusable. */ 2968*fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 2969*fcf3ce44SJohn Forte for (link = ha->dev[index].first; link != NULL; 2970*fcf3ce44SJohn Forte link = link->next) { 2971*fcf3ce44SJohn Forte tq = link->base_address; 2972*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 2973*fcf3ce44SJohn Forte if (!(tq->flags & TQF_PLOGI_PROGRS)) { 2974*fcf3ce44SJohn Forte tq->loop_id = (uint16_t) 2975*fcf3ce44SJohn Forte (tq->loop_id | PORT_LOST_ID); 2976*fcf3ce44SJohn Forte } 2977*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 2978*fcf3ce44SJohn Forte } 2979*fcf3ce44SJohn Forte } 2980*fcf3ce44SJohn Forte 2981*fcf3ce44SJohn Forte /* If device not in queues add new queue. */ 2982*fcf3ce44SJohn Forte for (index = 0; index < mr.mb[1]; index++) { 2983*fcf3ce44SJohn Forte ql_dev_list(ha, list, index, &d_id, &loop_id); 2984*fcf3ce44SJohn Forte 2985*fcf3ce44SJohn Forte if (VALID_DEVICE_ID(ha, loop_id)) { 2986*fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, loop_id); 2987*fcf3ce44SJohn Forte if (tq != NULL) { 2988*fcf3ce44SJohn Forte tq->loop_id = loop_id; 2989*fcf3ce44SJohn Forte 2990*fcf3ce44SJohn Forte /* Test for fabric device. */ 2991*fcf3ce44SJohn Forte if (d_id.b.domain != 2992*fcf3ce44SJohn Forte ha->d_id.b.domain || 2993*fcf3ce44SJohn Forte d_id.b.area != ha->d_id.b.area) { 2994*fcf3ce44SJohn Forte tq->flags |= TQF_FABRIC_DEVICE; 2995*fcf3ce44SJohn Forte } 2996*fcf3ce44SJohn Forte 2997*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2998*fcf3ce44SJohn Forte if (ql_get_port_database(ha, tq, 2999*fcf3ce44SJohn Forte PDF_NONE) == QL_SUCCESS) { 3000*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3001*fcf3ce44SJohn Forte tq->loop_id = (uint16_t) 3002*fcf3ce44SJohn Forte (tq->loop_id & 3003*fcf3ce44SJohn Forte ~PORT_LOST_ID); 3004*fcf3ce44SJohn Forte } else { 3005*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3006*fcf3ce44SJohn Forte } 3007*fcf3ce44SJohn Forte } 3008*fcf3ce44SJohn Forte } 3009*fcf3ce44SJohn Forte } 3010*fcf3ce44SJohn Forte 3011*fcf3ce44SJohn Forte /* 24xx does not report switch devices in ID list. */ 3012*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2425)) && 3013*fcf3ce44SJohn Forte ha->topology & (QL_F_PORT | QL_FL_PORT)) { 3014*fcf3ce44SJohn Forte d_id.b24 = 0xfffffe; 3015*fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL); 3016*fcf3ce44SJohn Forte if (tq != NULL) { 3017*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3018*fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3019*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3020*fcf3ce44SJohn Forte } 3021*fcf3ce44SJohn Forte d_id.b24 = 0xfffffc; 3022*fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, SNS_24XX_HDL); 3023*fcf3ce44SJohn Forte if (tq != NULL) { 3024*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3025*fcf3ce44SJohn Forte if (ha->vp_index != 0) { 3026*fcf3ce44SJohn Forte (void) ql_login_fport(ha, tq, 3027*fcf3ce44SJohn Forte SNS_24XX_HDL, LFF_NONE, NULL); 3028*fcf3ce44SJohn Forte } 3029*fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3030*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3031*fcf3ce44SJohn Forte } 3032*fcf3ce44SJohn Forte } 3033*fcf3ce44SJohn Forte 3034*fcf3ce44SJohn Forte /* If F_port exists, allocate queue for FL_Port. */ 3035*fcf3ce44SJohn Forte index = ql_alpa_to_index[0xfe]; 3036*fcf3ce44SJohn Forte d_id.b24 = 0; 3037*fcf3ce44SJohn Forte if (ha->dev[index].first != NULL) { 3038*fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, (uint16_t) 3039*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_CTRL_2425) ? 3040*fcf3ce44SJohn Forte FL_PORT_24XX_HDL : FL_PORT_LOOP_ID)); 3041*fcf3ce44SJohn Forte if (tq != NULL) { 3042*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3043*fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3044*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3045*fcf3ce44SJohn Forte } 3046*fcf3ce44SJohn Forte } 3047*fcf3ce44SJohn Forte 3048*fcf3ce44SJohn Forte /* Allocate queue for broadcast. */ 3049*fcf3ce44SJohn Forte d_id.b24 = 0xffffff; 3050*fcf3ce44SJohn Forte (void) ql_dev_init(ha, d_id, (uint16_t) 3051*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_CTRL_2425) ? BROADCAST_24XX_HDL : 3052*fcf3ce44SJohn Forte IP_BROADCAST_LOOP_ID)); 3053*fcf3ce44SJohn Forte 3054*fcf3ce44SJohn Forte /* Check for any devices lost. */ 3055*fcf3ce44SJohn Forte loop = FALSE; 3056*fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 3057*fcf3ce44SJohn Forte for (link = ha->dev[index].first; link != NULL; 3058*fcf3ce44SJohn Forte link = link->next) { 3059*fcf3ce44SJohn Forte tq = link->base_address; 3060*fcf3ce44SJohn Forte 3061*fcf3ce44SJohn Forte if ((tq->loop_id & PORT_LOST_ID) && 3062*fcf3ce44SJohn Forte !(tq->flags & (TQF_INITIATOR_DEVICE | 3063*fcf3ce44SJohn Forte TQF_FABRIC_DEVICE))) { 3064*fcf3ce44SJohn Forte loop = TRUE; 3065*fcf3ce44SJohn Forte } 3066*fcf3ce44SJohn Forte } 3067*fcf3ce44SJohn Forte } 3068*fcf3ce44SJohn Forte 3069*fcf3ce44SJohn Forte /* Release adapter state lock. */ 3070*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3071*fcf3ce44SJohn Forte 3072*fcf3ce44SJohn Forte /* Give devices time to recover. */ 3073*fcf3ce44SJohn Forte if (loop == TRUE) { 3074*fcf3ce44SJohn Forte drv_usecwait(1000000); 3075*fcf3ce44SJohn Forte } 3076*fcf3ce44SJohn Forte } while (retries-- && loop == TRUE && 3077*fcf3ce44SJohn Forte !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED)); 3078*fcf3ce44SJohn Forte 3079*fcf3ce44SJohn Forte kmem_free(list, list_size); 3080*fcf3ce44SJohn Forte 3081*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3082*fcf3ce44SJohn Forte EL(ha, "failed=%xh\n", rval); 3083*fcf3ce44SJohn Forte } else { 3084*fcf3ce44SJohn Forte /*EMPTY*/ 3085*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3086*fcf3ce44SJohn Forte } 3087*fcf3ce44SJohn Forte 3088*fcf3ce44SJohn Forte return (rval); 3089*fcf3ce44SJohn Forte } 3090*fcf3ce44SJohn Forte 3091*fcf3ce44SJohn Forte /* 3092*fcf3ce44SJohn Forte * ql_dev_list 3093*fcf3ce44SJohn Forte * Gets device d_id and loop ID from firmware device list. 3094*fcf3ce44SJohn Forte * 3095*fcf3ce44SJohn Forte * Input: 3096*fcf3ce44SJohn Forte * ha: adapter state pointer. 3097*fcf3ce44SJohn Forte * list device list pointer. 3098*fcf3ce44SJohn Forte * index: list index of device data. 3099*fcf3ce44SJohn Forte * d_id: pointer for d_id data. 3100*fcf3ce44SJohn Forte * id: pointer for loop ID. 3101*fcf3ce44SJohn Forte * 3102*fcf3ce44SJohn Forte * Context: 3103*fcf3ce44SJohn Forte * Kernel context. 3104*fcf3ce44SJohn Forte */ 3105*fcf3ce44SJohn Forte void 3106*fcf3ce44SJohn Forte ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list, 3107*fcf3ce44SJohn Forte uint32_t index, port_id_t *d_id, uint16_t *id) 3108*fcf3ce44SJohn Forte { 3109*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 3110*fcf3ce44SJohn Forte struct ql_24_dev_id *list24 = (struct ql_24_dev_id *)list; 3111*fcf3ce44SJohn Forte 3112*fcf3ce44SJohn Forte d_id->b.al_pa = list24[index].al_pa; 3113*fcf3ce44SJohn Forte d_id->b.area = list24[index].area; 3114*fcf3ce44SJohn Forte d_id->b.domain = list24[index].domain; 3115*fcf3ce44SJohn Forte *id = CHAR_TO_SHORT(list24[index].n_port_hdl_l, 3116*fcf3ce44SJohn Forte list24[index].n_port_hdl_h); 3117*fcf3ce44SJohn Forte 3118*fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 3119*fcf3ce44SJohn Forte struct ql_ex_dev_id *list23 = (struct ql_ex_dev_id *)list; 3120*fcf3ce44SJohn Forte 3121*fcf3ce44SJohn Forte d_id->b.al_pa = list23[index].al_pa; 3122*fcf3ce44SJohn Forte d_id->b.area = list23[index].area; 3123*fcf3ce44SJohn Forte d_id->b.domain = list23[index].domain; 3124*fcf3ce44SJohn Forte *id = CHAR_TO_SHORT(list23[index].loop_id_l, 3125*fcf3ce44SJohn Forte list23[index].loop_id_h); 3126*fcf3ce44SJohn Forte 3127*fcf3ce44SJohn Forte } else { 3128*fcf3ce44SJohn Forte struct ql_dev_id *list22 = (struct ql_dev_id *)list; 3129*fcf3ce44SJohn Forte 3130*fcf3ce44SJohn Forte d_id->b.al_pa = list22[index].al_pa; 3131*fcf3ce44SJohn Forte d_id->b.area = list22[index].area; 3132*fcf3ce44SJohn Forte d_id->b.domain = list22[index].domain; 3133*fcf3ce44SJohn Forte *id = (uint16_t)list22[index].loop_id; 3134*fcf3ce44SJohn Forte } 3135*fcf3ce44SJohn Forte } 3136*fcf3ce44SJohn Forte 3137*fcf3ce44SJohn Forte /* 3138*fcf3ce44SJohn Forte * ql_configure_fabric 3139*fcf3ce44SJohn Forte * Setup fabric context. 3140*fcf3ce44SJohn Forte * 3141*fcf3ce44SJohn Forte * Input: 3142*fcf3ce44SJohn Forte * ha = adapter state pointer. 3143*fcf3ce44SJohn Forte * 3144*fcf3ce44SJohn Forte * Returns: 3145*fcf3ce44SJohn Forte * ql local function return status code. 3146*fcf3ce44SJohn Forte * 3147*fcf3ce44SJohn Forte * Context: 3148*fcf3ce44SJohn Forte * Kernel context. 3149*fcf3ce44SJohn Forte */ 3150*fcf3ce44SJohn Forte static int 3151*fcf3ce44SJohn Forte ql_configure_fabric(ql_adapter_state_t *ha) 3152*fcf3ce44SJohn Forte { 3153*fcf3ce44SJohn Forte port_id_t d_id; 3154*fcf3ce44SJohn Forte ql_tgt_t *tq; 3155*fcf3ce44SJohn Forte int rval = QL_FUNCTION_FAILED; 3156*fcf3ce44SJohn Forte 3157*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3158*fcf3ce44SJohn Forte 3159*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & ~QL_SNS_CONNECTION); 3160*fcf3ce44SJohn Forte 3161*fcf3ce44SJohn Forte /* Test switch fabric controller present. */ 3162*fcf3ce44SJohn Forte d_id.b24 = FS_FABRIC_F_PORT; 3163*fcf3ce44SJohn Forte tq = ql_d_id_to_queue(ha, d_id); 3164*fcf3ce44SJohn Forte if (tq != NULL) { 3165*fcf3ce44SJohn Forte /* Get port/node names of F_Port. */ 3166*fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3167*fcf3ce44SJohn Forte 3168*fcf3ce44SJohn Forte d_id.b24 = FS_NAME_SERVER; 3169*fcf3ce44SJohn Forte tq = ql_d_id_to_queue(ha, d_id); 3170*fcf3ce44SJohn Forte if (tq != NULL) { 3171*fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3172*fcf3ce44SJohn Forte ha->topology = (uint8_t) 3173*fcf3ce44SJohn Forte (ha->topology | QL_SNS_CONNECTION); 3174*fcf3ce44SJohn Forte rval = QL_SUCCESS; 3175*fcf3ce44SJohn Forte } 3176*fcf3ce44SJohn Forte } 3177*fcf3ce44SJohn Forte 3178*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3179*fcf3ce44SJohn Forte EL(ha, "failed=%xh\n", rval); 3180*fcf3ce44SJohn Forte } else { 3181*fcf3ce44SJohn Forte /*EMPTY*/ 3182*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3183*fcf3ce44SJohn Forte } 3184*fcf3ce44SJohn Forte return (rval); 3185*fcf3ce44SJohn Forte } 3186*fcf3ce44SJohn Forte 3187*fcf3ce44SJohn Forte /* 3188*fcf3ce44SJohn Forte * ql_reset_chip 3189*fcf3ce44SJohn Forte * Reset ISP chip. 3190*fcf3ce44SJohn Forte * 3191*fcf3ce44SJohn Forte * Input: 3192*fcf3ce44SJohn Forte * ha = adapter block pointer. 3193*fcf3ce44SJohn Forte * All activity on chip must be already stopped. 3194*fcf3ce44SJohn Forte * ADAPTER_STATE_LOCK must be released. 3195*fcf3ce44SJohn Forte * 3196*fcf3ce44SJohn Forte * Context: 3197*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3198*fcf3ce44SJohn Forte */ 3199*fcf3ce44SJohn Forte void 3200*fcf3ce44SJohn Forte ql_reset_chip(ql_adapter_state_t *vha) 3201*fcf3ce44SJohn Forte { 3202*fcf3ce44SJohn Forte uint32_t cnt; 3203*fcf3ce44SJohn Forte uint16_t cmd; 3204*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 3205*fcf3ce44SJohn Forte 3206*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3207*fcf3ce44SJohn Forte 3208*fcf3ce44SJohn Forte /* 3209*fcf3ce44SJohn Forte * accessing pci space while not powered can cause panic's 3210*fcf3ce44SJohn Forte * on some platforms (i.e. Sunblade 1000's) 3211*fcf3ce44SJohn Forte */ 3212*fcf3ce44SJohn Forte if (ha->power_level == PM_LEVEL_D3) { 3213*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): Low Power exit\n", ha->instance); 3214*fcf3ce44SJohn Forte return; 3215*fcf3ce44SJohn Forte } 3216*fcf3ce44SJohn Forte 3217*fcf3ce44SJohn Forte /* Reset all outbound mailbox registers */ 3218*fcf3ce44SJohn Forte for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) { 3219*fcf3ce44SJohn Forte WRT16_IO_REG(ha, mailbox[cnt], (uint16_t)0); 3220*fcf3ce44SJohn Forte } 3221*fcf3ce44SJohn Forte 3222*fcf3ce44SJohn Forte /* Disable ISP interrupts. */ 3223*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, 0); 3224*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3225*fcf3ce44SJohn Forte ha->flags &= ~INTERRUPTS_ENABLED; 3226*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3227*fcf3ce44SJohn Forte 3228*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 3229*fcf3ce44SJohn Forte RD32_IO_REG(ha, ictrl); 3230*fcf3ce44SJohn Forte ql_reset_24xx_chip(ha); 3231*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): 24xx exit\n", ha->instance); 3232*fcf3ce44SJohn Forte return; 3233*fcf3ce44SJohn Forte } 3234*fcf3ce44SJohn Forte 3235*fcf3ce44SJohn Forte /* 3236*fcf3ce44SJohn Forte * We are going to reset the chip in case of 2300. That might cause 3237*fcf3ce44SJohn Forte * a PBM ERR if a DMA transaction is in progress. One way of 3238*fcf3ce44SJohn Forte * avoiding it is to disable Bus Master operation before we start 3239*fcf3ce44SJohn Forte * the reset activity. 3240*fcf3ce44SJohn Forte */ 3241*fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 3242*fcf3ce44SJohn Forte cmd = (uint16_t)(cmd & ~PCI_COMM_ME); 3243*fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 3244*fcf3ce44SJohn Forte 3245*fcf3ce44SJohn Forte /* Pause RISC. */ 3246*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 3247*fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3248*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) { 3249*fcf3ce44SJohn Forte break; 3250*fcf3ce44SJohn Forte } 3251*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3252*fcf3ce44SJohn Forte } 3253*fcf3ce44SJohn Forte 3254*fcf3ce44SJohn Forte /* 3255*fcf3ce44SJohn Forte * A call to ql_isr() can still happen through 3256*fcf3ce44SJohn Forte * ql_mailbox_command(). So Mark that we are/(will-be) 3257*fcf3ce44SJohn Forte * running from rom code now. 3258*fcf3ce44SJohn Forte */ 3259*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3260*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED); 3261*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3262*fcf3ce44SJohn Forte 3263*fcf3ce44SJohn Forte /* Select FPM registers. */ 3264*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x20); 3265*fcf3ce44SJohn Forte 3266*fcf3ce44SJohn Forte /* FPM Soft Reset. */ 3267*fcf3ce44SJohn Forte WRT16_IO_REG(ha, fpm_diag_config, 0x100); 3268*fcf3ce44SJohn Forte 3269*fcf3ce44SJohn Forte /* Toggle FPM reset for 2300 */ 3270*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3271*fcf3ce44SJohn Forte WRT16_IO_REG(ha, fpm_diag_config, 0); 3272*fcf3ce44SJohn Forte } 3273*fcf3ce44SJohn Forte 3274*fcf3ce44SJohn Forte /* Select frame buffer registers. */ 3275*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x10); 3276*fcf3ce44SJohn Forte 3277*fcf3ce44SJohn Forte /* Reset frame buffer FIFOs. */ 3278*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3279*fcf3ce44SJohn Forte WRT16_IO_REG(ha, fb_cmd, 0x00fc); 3280*fcf3ce44SJohn Forte /* read back fb_cmd until zero or 3 seconds max */ 3281*fcf3ce44SJohn Forte for (cnt = 0; cnt < 300000; cnt++) { 3282*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) { 3283*fcf3ce44SJohn Forte break; 3284*fcf3ce44SJohn Forte } 3285*fcf3ce44SJohn Forte drv_usecwait(10); 3286*fcf3ce44SJohn Forte } 3287*fcf3ce44SJohn Forte } else { 3288*fcf3ce44SJohn Forte WRT16_IO_REG(ha, fb_cmd, 0xa000); 3289*fcf3ce44SJohn Forte } 3290*fcf3ce44SJohn Forte 3291*fcf3ce44SJohn Forte /* Select RISC module registers. */ 3292*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0); 3293*fcf3ce44SJohn Forte 3294*fcf3ce44SJohn Forte /* Reset RISC module. */ 3295*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RESET_RISC); 3296*fcf3ce44SJohn Forte 3297*fcf3ce44SJohn Forte /* Reset ISP semaphore. */ 3298*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 3299*fcf3ce44SJohn Forte 3300*fcf3ce44SJohn Forte /* Release RISC module. */ 3301*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 3302*fcf3ce44SJohn Forte 3303*fcf3ce44SJohn Forte /* Insure mailbox registers are free. */ 3304*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 3305*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT); 3306*fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & 3307*fcf3ce44SJohn Forte ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT)); 3308*fcf3ce44SJohn Forte ha->mcp = NULL; 3309*fcf3ce44SJohn Forte 3310*fcf3ce44SJohn Forte /* Bus Master is disabled so chip reset is safe. */ 3311*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3312*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, ISP_RESET); 3313*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3314*fcf3ce44SJohn Forte 3315*fcf3ce44SJohn Forte /* Wait for reset to finish. */ 3316*fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3317*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) { 3318*fcf3ce44SJohn Forte break; 3319*fcf3ce44SJohn Forte } 3320*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3321*fcf3ce44SJohn Forte } 3322*fcf3ce44SJohn Forte } 3323*fcf3ce44SJohn Forte 3324*fcf3ce44SJohn Forte /* Wait for RISC to recover from reset. */ 3325*fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3326*fcf3ce44SJohn Forte if (RD16_IO_REG(ha, mailbox[0]) != MBS_BUSY) { 3327*fcf3ce44SJohn Forte break; 3328*fcf3ce44SJohn Forte } 3329*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3330*fcf3ce44SJohn Forte } 3331*fcf3ce44SJohn Forte 3332*fcf3ce44SJohn Forte /* restore bus master */ 3333*fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 3334*fcf3ce44SJohn Forte cmd = (uint16_t)(cmd | PCI_COMM_ME); 3335*fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 3336*fcf3ce44SJohn Forte 3337*fcf3ce44SJohn Forte /* Disable RISC pause on FPM parity error. */ 3338*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE); 3339*fcf3ce44SJohn Forte 3340*fcf3ce44SJohn Forte /* Initialize probe registers */ 3341*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 3342*fcf3ce44SJohn Forte /* Pause RISC. */ 3343*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 3344*fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3345*fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) { 3346*fcf3ce44SJohn Forte break; 3347*fcf3ce44SJohn Forte } else { 3348*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3349*fcf3ce44SJohn Forte } 3350*fcf3ce44SJohn Forte } 3351*fcf3ce44SJohn Forte 3352*fcf3ce44SJohn Forte /* Select FPM registers. */ 3353*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x30); 3354*fcf3ce44SJohn Forte 3355*fcf3ce44SJohn Forte /* Set probe register */ 3356*fcf3ce44SJohn Forte WRT16_IO_REG(ha, mailbox[23], 0x204c); 3357*fcf3ce44SJohn Forte 3358*fcf3ce44SJohn Forte /* Select RISC module registers. */ 3359*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0); 3360*fcf3ce44SJohn Forte 3361*fcf3ce44SJohn Forte /* Release RISC module. */ 3362*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 3363*fcf3ce44SJohn Forte } 3364*fcf3ce44SJohn Forte 3365*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3366*fcf3ce44SJohn Forte } 3367*fcf3ce44SJohn Forte 3368*fcf3ce44SJohn Forte /* 3369*fcf3ce44SJohn Forte * ql_reset_24xx_chip 3370*fcf3ce44SJohn Forte * Reset ISP24xx chip. 3371*fcf3ce44SJohn Forte * 3372*fcf3ce44SJohn Forte * Input: 3373*fcf3ce44SJohn Forte * ha = adapter block pointer. 3374*fcf3ce44SJohn Forte * All activity on chip must be already stopped. 3375*fcf3ce44SJohn Forte * 3376*fcf3ce44SJohn Forte * Context: 3377*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3378*fcf3ce44SJohn Forte */ 3379*fcf3ce44SJohn Forte void 3380*fcf3ce44SJohn Forte ql_reset_24xx_chip(ql_adapter_state_t *ha) 3381*fcf3ce44SJohn Forte { 3382*fcf3ce44SJohn Forte uint32_t timer, stat; 3383*fcf3ce44SJohn Forte 3384*fcf3ce44SJohn Forte /* Shutdown DMA. */ 3385*fcf3ce44SJohn Forte WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES); 3386*fcf3ce44SJohn Forte 3387*fcf3ce44SJohn Forte /* Wait for DMA to stop. */ 3388*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3389*fcf3ce44SJohn Forte if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) { 3390*fcf3ce44SJohn Forte break; 3391*fcf3ce44SJohn Forte } 3392*fcf3ce44SJohn Forte drv_usecwait(100); 3393*fcf3ce44SJohn Forte } 3394*fcf3ce44SJohn Forte 3395*fcf3ce44SJohn Forte /* Stop the firmware. */ 3396*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3397*fcf3ce44SJohn Forte WRT16_IO_REG(ha, mailbox[0], MBC_STOP_FIRMWARE); 3398*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT); 3399*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3400*fcf3ce44SJohn Forte stat = RD32_IO_REG(ha, intr_info_lo); 3401*fcf3ce44SJohn Forte if (stat & BIT_15) { 3402*fcf3ce44SJohn Forte if ((stat & 0xff) < 0x12) { 3403*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3404*fcf3ce44SJohn Forte break; 3405*fcf3ce44SJohn Forte } 3406*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3407*fcf3ce44SJohn Forte } 3408*fcf3ce44SJohn Forte drv_usecwait(100); 3409*fcf3ce44SJohn Forte } 3410*fcf3ce44SJohn Forte 3411*fcf3ce44SJohn Forte /* Reset the chip. */ 3412*fcf3ce44SJohn Forte WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN | 3413*fcf3ce44SJohn Forte MWB_4096_BYTES); 3414*fcf3ce44SJohn Forte drv_usecwait(100); 3415*fcf3ce44SJohn Forte 3416*fcf3ce44SJohn Forte /* Wait for idle status from ROM firmware. */ 3417*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3418*fcf3ce44SJohn Forte if (RD16_IO_REG(ha, mailbox[0]) == 0) { 3419*fcf3ce44SJohn Forte break; 3420*fcf3ce44SJohn Forte } 3421*fcf3ce44SJohn Forte drv_usecwait(100); 3422*fcf3ce44SJohn Forte } 3423*fcf3ce44SJohn Forte 3424*fcf3ce44SJohn Forte /* Wait for reset to finish. */ 3425*fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3426*fcf3ce44SJohn Forte if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) { 3427*fcf3ce44SJohn Forte break; 3428*fcf3ce44SJohn Forte } 3429*fcf3ce44SJohn Forte drv_usecwait(100); 3430*fcf3ce44SJohn Forte } 3431*fcf3ce44SJohn Forte 3432*fcf3ce44SJohn Forte /* Insure mailbox registers are free. */ 3433*fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & 3434*fcf3ce44SJohn Forte ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT)); 3435*fcf3ce44SJohn Forte ha->mcp = NULL; 3436*fcf3ce44SJohn Forte 3437*fcf3ce44SJohn Forte if (ha->fwfcetracebuf.bp != NULL) { 3438*fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwfcetracebuf); 3439*fcf3ce44SJohn Forte } 3440*fcf3ce44SJohn Forte 3441*fcf3ce44SJohn Forte if (ha->fwexttracebuf.bp != NULL) { 3442*fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwexttracebuf); 3443*fcf3ce44SJohn Forte } 3444*fcf3ce44SJohn Forte 3445*fcf3ce44SJohn Forte /* 3446*fcf3ce44SJohn Forte * Set flash write-protection. 3447*fcf3ce44SJohn Forte */ 3448*fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 3449*fcf3ce44SJohn Forte ql_24xx_protect_flash(ha); 3450*fcf3ce44SJohn Forte } 3451*fcf3ce44SJohn Forte } 3452*fcf3ce44SJohn Forte 3453*fcf3ce44SJohn Forte /* 3454*fcf3ce44SJohn Forte * ql_abort_isp 3455*fcf3ce44SJohn Forte * Resets ISP and aborts all outstanding commands. 3456*fcf3ce44SJohn Forte * 3457*fcf3ce44SJohn Forte * Input: 3458*fcf3ce44SJohn Forte * ha = adapter state pointer. 3459*fcf3ce44SJohn Forte * DEVICE_QUEUE_LOCK must be released. 3460*fcf3ce44SJohn Forte * 3461*fcf3ce44SJohn Forte * Returns: 3462*fcf3ce44SJohn Forte * ql local function return status code. 3463*fcf3ce44SJohn Forte * 3464*fcf3ce44SJohn Forte * Context: 3465*fcf3ce44SJohn Forte * Kernel context. 3466*fcf3ce44SJohn Forte */ 3467*fcf3ce44SJohn Forte int 3468*fcf3ce44SJohn Forte ql_abort_isp(ql_adapter_state_t *vha) 3469*fcf3ce44SJohn Forte { 3470*fcf3ce44SJohn Forte ql_link_t *link, *link2; 3471*fcf3ce44SJohn Forte ddi_devstate_t state; 3472*fcf3ce44SJohn Forte uint16_t index; 3473*fcf3ce44SJohn Forte ql_tgt_t *tq; 3474*fcf3ce44SJohn Forte ql_lun_t *lq; 3475*fcf3ce44SJohn Forte ql_srb_t *sp; 3476*fcf3ce44SJohn Forte int rval = QL_SUCCESS; 3477*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 3478*fcf3ce44SJohn Forte 3479*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3480*fcf3ce44SJohn Forte 3481*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3482*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~ISP_ABORT_NEEDED; 3483*fcf3ce44SJohn Forte if (ha->task_daemon_flags & ABORT_ISP_ACTIVE || 3484*fcf3ce44SJohn Forte (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) { 3485*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3486*fcf3ce44SJohn Forte return (rval); 3487*fcf3ce44SJohn Forte } 3488*fcf3ce44SJohn Forte 3489*fcf3ce44SJohn Forte ha->task_daemon_flags |= ABORT_ISP_ACTIVE; 3490*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(RESET_MARKER_NEEDED | FIRMWARE_UP | 3491*fcf3ce44SJohn Forte FIRMWARE_LOADED); 3492*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3493*fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_DOWN; 3494*fcf3ce44SJohn Forte vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED | 3495*fcf3ce44SJohn Forte LOOP_RESYNC_NEEDED); 3496*fcf3ce44SJohn Forte } 3497*fcf3ce44SJohn Forte 3498*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3499*fcf3ce44SJohn Forte 3500*fcf3ce44SJohn Forte if (ha->mailbox_flags & MBX_BUSY_FLG) { 3501*fcf3ce44SJohn Forte /* Acquire mailbox register lock. */ 3502*fcf3ce44SJohn Forte MBX_REGISTER_LOCK(ha); 3503*fcf3ce44SJohn Forte 3504*fcf3ce44SJohn Forte /* Wake up mailbox box routine. */ 3505*fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT); 3506*fcf3ce44SJohn Forte cv_broadcast(&ha->cv_mbx_intr); 3507*fcf3ce44SJohn Forte 3508*fcf3ce44SJohn Forte /* Release mailbox register lock. */ 3509*fcf3ce44SJohn Forte MBX_REGISTER_UNLOCK(ha); 3510*fcf3ce44SJohn Forte 3511*fcf3ce44SJohn Forte /* Wait for mailbox. */ 3512*fcf3ce44SJohn Forte for (index = 100; index && 3513*fcf3ce44SJohn Forte ha->mailbox_flags & MBX_ABORT; index--) { 3514*fcf3ce44SJohn Forte drv_usecwait(50000); 3515*fcf3ce44SJohn Forte } 3516*fcf3ce44SJohn Forte } 3517*fcf3ce44SJohn Forte 3518*fcf3ce44SJohn Forte /* Wait for commands to end gracefully if not in panic. */ 3519*fcf3ce44SJohn Forte if (ha->flags & PARITY_ERROR) { 3520*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3521*fcf3ce44SJohn Forte ha->flags &= ~PARITY_ERROR; 3522*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3523*fcf3ce44SJohn Forte } else if (ddi_in_panic() == 0) { 3524*fcf3ce44SJohn Forte ql_cmd_wait(ha); 3525*fcf3ce44SJohn Forte } 3526*fcf3ce44SJohn Forte 3527*fcf3ce44SJohn Forte /* Shutdown IP. */ 3528*fcf3ce44SJohn Forte if (ha->flags & IP_INITIALIZED) { 3529*fcf3ce44SJohn Forte (void) ql_shutdown_ip(ha); 3530*fcf3ce44SJohn Forte } 3531*fcf3ce44SJohn Forte 3532*fcf3ce44SJohn Forte /* Reset the chip. */ 3533*fcf3ce44SJohn Forte ql_reset_chip(ha); 3534*fcf3ce44SJohn Forte 3535*fcf3ce44SJohn Forte /* Place all commands in outstanding cmd list on device queue. */ 3536*fcf3ce44SJohn Forte for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { 3537*fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 3538*fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) != NULL) { 3539*fcf3ce44SJohn Forte sp = link->base_address; 3540*fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 3541*fcf3ce44SJohn Forte 3542*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 3543*fcf3ce44SJohn Forte index = 0; 3544*fcf3ce44SJohn Forte } else { 3545*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 3546*fcf3ce44SJohn Forte if ((sp = ha->outstanding_cmds[index]) == NULL) { 3547*fcf3ce44SJohn Forte continue; 3548*fcf3ce44SJohn Forte } 3549*fcf3ce44SJohn Forte } 3550*fcf3ce44SJohn Forte 3551*fcf3ce44SJohn Forte /* If command timeout. */ 3552*fcf3ce44SJohn Forte if (sp->flags & SRB_COMMAND_TIMEOUT) { 3553*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_TIMEOUT; 3554*fcf3ce44SJohn Forte sp->flags &= ~SRB_RETRY; 3555*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 3556*fcf3ce44SJohn Forte 3557*fcf3ce44SJohn Forte /* Call done routine to handle completion. */ 3558*fcf3ce44SJohn Forte ql_done(&sp->cmd); 3559*fcf3ce44SJohn Forte continue; 3560*fcf3ce44SJohn Forte } 3561*fcf3ce44SJohn Forte 3562*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 3563*fcf3ce44SJohn Forte sp->handle = 0; 3564*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 3565*fcf3ce44SJohn Forte 3566*fcf3ce44SJohn Forte /* Acquire target queue lock. */ 3567*fcf3ce44SJohn Forte lq = sp->lun_queue; 3568*fcf3ce44SJohn Forte tq = lq->target_queue; 3569*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3570*fcf3ce44SJohn Forte 3571*fcf3ce44SJohn Forte /* Reset watchdog time. */ 3572*fcf3ce44SJohn Forte sp->wdg_q_time = sp->init_wdg_q_time; 3573*fcf3ce44SJohn Forte 3574*fcf3ce44SJohn Forte /* Place request back on top of device queue. */ 3575*fcf3ce44SJohn Forte sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | 3576*fcf3ce44SJohn Forte SRB_RETRY); 3577*fcf3ce44SJohn Forte 3578*fcf3ce44SJohn Forte ql_add_link_t(&lq->cmd, &sp->cmd); 3579*fcf3ce44SJohn Forte sp->flags |= SRB_IN_DEVICE_QUEUE; 3580*fcf3ce44SJohn Forte 3581*fcf3ce44SJohn Forte /* Release target queue lock. */ 3582*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3583*fcf3ce44SJohn Forte } 3584*fcf3ce44SJohn Forte 3585*fcf3ce44SJohn Forte /* 3586*fcf3ce44SJohn Forte * Clear per LUN active count, because there should not be 3587*fcf3ce44SJohn Forte * any IO outstanding at this time. 3588*fcf3ce44SJohn Forte */ 3589*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3590*fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 3591*fcf3ce44SJohn Forte link = vha->dev[index].first; 3592*fcf3ce44SJohn Forte while (link != NULL) { 3593*fcf3ce44SJohn Forte tq = link->base_address; 3594*fcf3ce44SJohn Forte link = link->next; 3595*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3596*fcf3ce44SJohn Forte tq->outcnt = 0; 3597*fcf3ce44SJohn Forte tq->flags &= ~TQF_QUEUE_SUSPENDED; 3598*fcf3ce44SJohn Forte for (link2 = tq->lun_queues.first; 3599*fcf3ce44SJohn Forte link2 != NULL; link2 = link2->next) { 3600*fcf3ce44SJohn Forte lq = link2->base_address; 3601*fcf3ce44SJohn Forte lq->lun_outcnt = 0; 3602*fcf3ce44SJohn Forte lq->flags &= ~LQF_UNTAGGED_PENDING; 3603*fcf3ce44SJohn Forte } 3604*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3605*fcf3ce44SJohn Forte } 3606*fcf3ce44SJohn Forte } 3607*fcf3ce44SJohn Forte } 3608*fcf3ce44SJohn Forte 3609*fcf3ce44SJohn Forte if (ha->flags & TARGET_MODE_INITIALIZED) { 3610*fcf3ce44SJohn Forte /* Enable Target Mode */ 3611*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.lun_enables[0] = (uint8_t) 3612*fcf3ce44SJohn Forte (ha->init_ctrl_blk.cb.lun_enables[0] | 0x01); 3613*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.immediate_notify_resouce_count = 3614*fcf3ce44SJohn Forte ha->ub_notify_count; 3615*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.command_resouce_count = 3616*fcf3ce44SJohn Forte ha->ub_command_count; 3617*fcf3ce44SJohn Forte } else { 3618*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.lun_enables[0] = 0; 3619*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.lun_enables[1] = 0; 3620*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.immediate_notify_resouce_count = 0; 3621*fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.command_resouce_count = 0; 3622*fcf3ce44SJohn Forte } 3623*fcf3ce44SJohn Forte 3624*fcf3ce44SJohn Forte rval = ql_chip_diag(ha); 3625*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 3626*fcf3ce44SJohn Forte (void) ql_load_isp_firmware(ha); 3627*fcf3ce44SJohn Forte } 3628*fcf3ce44SJohn Forte 3629*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) == 3630*fcf3ce44SJohn Forte QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS && 3631*fcf3ce44SJohn Forte (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) { 3632*fcf3ce44SJohn Forte 3633*fcf3ce44SJohn Forte /* If reset abort needed that may have been set. */ 3634*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3635*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | 3636*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE); 3637*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3638*fcf3ce44SJohn Forte 3639*fcf3ce44SJohn Forte /* Enable ISP interrupts. */ 3640*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 3641*fcf3ce44SJohn Forte WRT32_IO_REG(ha, ictrl, ISP_EN_RISC) : 3642*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 3643*fcf3ce44SJohn Forte 3644*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3645*fcf3ce44SJohn Forte ha->flags |= INTERRUPTS_ENABLED; 3646*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3647*fcf3ce44SJohn Forte 3648*fcf3ce44SJohn Forte /* Set loop online, if it really is. */ 3649*fcf3ce44SJohn Forte ql_loop_online(ha); 3650*fcf3ce44SJohn Forte 3651*fcf3ce44SJohn Forte state = ddi_get_devstate(ha->dip); 3652*fcf3ce44SJohn Forte if (state != DDI_DEVSTATE_UP) { 3653*fcf3ce44SJohn Forte /*EMPTY*/ 3654*fcf3ce44SJohn Forte ddi_dev_report_fault(ha->dip, DDI_SERVICE_RESTORED, 3655*fcf3ce44SJohn Forte DDI_DEVICE_FAULT, "Device reset succeeded"); 3656*fcf3ce44SJohn Forte } 3657*fcf3ce44SJohn Forte } else { 3658*fcf3ce44SJohn Forte /* Enable ISP interrupts. */ 3659*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 3660*fcf3ce44SJohn Forte WRT32_IO_REG(ha, ictrl, ISP_EN_RISC) : 3661*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 3662*fcf3ce44SJohn Forte 3663*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3664*fcf3ce44SJohn Forte ha->flags |= INTERRUPTS_ENABLED; 3665*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3666*fcf3ce44SJohn Forte 3667*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3668*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE); 3669*fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 3670*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3671*fcf3ce44SJohn Forte 3672*fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE); 3673*fcf3ce44SJohn Forte } 3674*fcf3ce44SJohn Forte 3675*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3676*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3677*fcf3ce44SJohn Forte } else { 3678*fcf3ce44SJohn Forte /*EMPTY*/ 3679*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): done\n", ha->instance); 3680*fcf3ce44SJohn Forte } 3681*fcf3ce44SJohn Forte return (rval); 3682*fcf3ce44SJohn Forte } 3683*fcf3ce44SJohn Forte 3684*fcf3ce44SJohn Forte /* 3685*fcf3ce44SJohn Forte * ql_vport_control 3686*fcf3ce44SJohn Forte * Issue Virtual Port Control command. 3687*fcf3ce44SJohn Forte * 3688*fcf3ce44SJohn Forte * Input: 3689*fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 3690*fcf3ce44SJohn Forte * cmd = control command. 3691*fcf3ce44SJohn Forte * 3692*fcf3ce44SJohn Forte * Returns: 3693*fcf3ce44SJohn Forte * ql local function return status code. 3694*fcf3ce44SJohn Forte * 3695*fcf3ce44SJohn Forte * Context: 3696*fcf3ce44SJohn Forte * Kernel context. 3697*fcf3ce44SJohn Forte */ 3698*fcf3ce44SJohn Forte int 3699*fcf3ce44SJohn Forte ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd) 3700*fcf3ce44SJohn Forte { 3701*fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 3702*fcf3ce44SJohn Forte uint8_t bit; 3703*fcf3ce44SJohn Forte int rval; 3704*fcf3ce44SJohn Forte uint32_t pkt_size; 3705*fcf3ce44SJohn Forte 3706*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3707*fcf3ce44SJohn Forte 3708*fcf3ce44SJohn Forte if (ha->vp_index != 0) { 3709*fcf3ce44SJohn Forte pkt_size = sizeof (ql_mbx_iocb_t); 3710*fcf3ce44SJohn Forte pkt = kmem_zalloc(pkt_size, KM_SLEEP); 3711*fcf3ce44SJohn Forte if (pkt == NULL) { 3712*fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 3713*fcf3ce44SJohn Forte return (QL_MEMORY_ALLOC_FAILED); 3714*fcf3ce44SJohn Forte } 3715*fcf3ce44SJohn Forte 3716*fcf3ce44SJohn Forte pkt->vpc.entry_type = VP_CONTROL_TYPE; 3717*fcf3ce44SJohn Forte pkt->vpc.entry_count = 1; 3718*fcf3ce44SJohn Forte pkt->vpc.command = cmd; 3719*fcf3ce44SJohn Forte pkt->vpc.vp_count = 1; 3720*fcf3ce44SJohn Forte bit = (uint8_t)(ha->vp_index - 1); 3721*fcf3ce44SJohn Forte pkt->vpc.vp_index[bit / 8] = (uint8_t) 3722*fcf3ce44SJohn Forte (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8); 3723*fcf3ce44SJohn Forte 3724*fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); 3725*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && pkt->vpc.status != 0) { 3726*fcf3ce44SJohn Forte rval = QL_COMMAND_ERROR; 3727*fcf3ce44SJohn Forte } 3728*fcf3ce44SJohn Forte 3729*fcf3ce44SJohn Forte kmem_free(pkt, pkt_size); 3730*fcf3ce44SJohn Forte } else { 3731*fcf3ce44SJohn Forte rval = QL_SUCCESS; 3732*fcf3ce44SJohn Forte } 3733*fcf3ce44SJohn Forte 3734*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3735*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3736*fcf3ce44SJohn Forte } else { 3737*fcf3ce44SJohn Forte /*EMPTY*/ 3738*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, 3739*fcf3ce44SJohn Forte ha->vp_index); 3740*fcf3ce44SJohn Forte } 3741*fcf3ce44SJohn Forte return (rval); 3742*fcf3ce44SJohn Forte } 3743*fcf3ce44SJohn Forte 3744*fcf3ce44SJohn Forte /* 3745*fcf3ce44SJohn Forte * ql_vport_modify 3746*fcf3ce44SJohn Forte * Issue of Modify Virtual Port command. 3747*fcf3ce44SJohn Forte * 3748*fcf3ce44SJohn Forte * Input: 3749*fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 3750*fcf3ce44SJohn Forte * cmd = command. 3751*fcf3ce44SJohn Forte * opt = option. 3752*fcf3ce44SJohn Forte * 3753*fcf3ce44SJohn Forte * Context: 3754*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3755*fcf3ce44SJohn Forte */ 3756*fcf3ce44SJohn Forte int 3757*fcf3ce44SJohn Forte ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt) 3758*fcf3ce44SJohn Forte { 3759*fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 3760*fcf3ce44SJohn Forte int rval; 3761*fcf3ce44SJohn Forte uint32_t pkt_size; 3762*fcf3ce44SJohn Forte 3763*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3764*fcf3ce44SJohn Forte 3765*fcf3ce44SJohn Forte pkt_size = sizeof (ql_mbx_iocb_t); 3766*fcf3ce44SJohn Forte pkt = kmem_zalloc(pkt_size, KM_SLEEP); 3767*fcf3ce44SJohn Forte if (pkt == NULL) { 3768*fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 3769*fcf3ce44SJohn Forte return (QL_MEMORY_ALLOC_FAILED); 3770*fcf3ce44SJohn Forte } 3771*fcf3ce44SJohn Forte 3772*fcf3ce44SJohn Forte pkt->vpm.entry_type = VP_MODIFY_TYPE; 3773*fcf3ce44SJohn Forte pkt->vpm.entry_count = 1; 3774*fcf3ce44SJohn Forte pkt->vpm.command = cmd; 3775*fcf3ce44SJohn Forte pkt->vpm.vp_count = 1; 3776*fcf3ce44SJohn Forte pkt->vpm.first_vp_index = ha->vp_index; 3777*fcf3ce44SJohn Forte pkt->vpm.first_options = opt; 3778*fcf3ce44SJohn Forte bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name, 3779*fcf3ce44SJohn Forte 8); 3780*fcf3ce44SJohn Forte bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name, 3781*fcf3ce44SJohn Forte 8); 3782*fcf3ce44SJohn Forte 3783*fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); 3784*fcf3ce44SJohn Forte if (rval == QL_SUCCESS && pkt->vpm.status != 0) { 3785*fcf3ce44SJohn Forte EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval, 3786*fcf3ce44SJohn Forte pkt->vpm.status); 3787*fcf3ce44SJohn Forte rval = QL_COMMAND_ERROR; 3788*fcf3ce44SJohn Forte } 3789*fcf3ce44SJohn Forte 3790*fcf3ce44SJohn Forte kmem_free(pkt, pkt_size); 3791*fcf3ce44SJohn Forte 3792*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3793*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3794*fcf3ce44SJohn Forte } else { 3795*fcf3ce44SJohn Forte /*EMPTY*/ 3796*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, 3797*fcf3ce44SJohn Forte ha->vp_index); 3798*fcf3ce44SJohn Forte } 3799*fcf3ce44SJohn Forte return (rval); 3800*fcf3ce44SJohn Forte } 3801*fcf3ce44SJohn Forte 3802*fcf3ce44SJohn Forte /* 3803*fcf3ce44SJohn Forte * ql_vport_enable 3804*fcf3ce44SJohn Forte * Enable virtual port. 3805*fcf3ce44SJohn Forte * 3806*fcf3ce44SJohn Forte * Input: 3807*fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 3808*fcf3ce44SJohn Forte * 3809*fcf3ce44SJohn Forte * Context: 3810*fcf3ce44SJohn Forte * Kernel context. 3811*fcf3ce44SJohn Forte */ 3812*fcf3ce44SJohn Forte int 3813*fcf3ce44SJohn Forte ql_vport_enable(ql_adapter_state_t *ha) 3814*fcf3ce44SJohn Forte { 3815*fcf3ce44SJohn Forte int timer; 3816*fcf3ce44SJohn Forte 3817*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3818*fcf3ce44SJohn Forte 3819*fcf3ce44SJohn Forte ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE; 3820*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3821*fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 3822*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE); 3823*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3824*fcf3ce44SJohn Forte 3825*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3826*fcf3ce44SJohn Forte ha->flags |= VP_ENABLED; 3827*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3828*fcf3ce44SJohn Forte 3829*fcf3ce44SJohn Forte if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED | 3830*fcf3ce44SJohn Forte VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) { 3831*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): failed to enable virtual port=%d\n", 3832*fcf3ce44SJohn Forte ha->instance, ha->vp_index); 3833*fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 3834*fcf3ce44SJohn Forte } 3835*fcf3ce44SJohn Forte if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) { 3836*fcf3ce44SJohn Forte /* Wait for loop to come up. */ 3837*fcf3ce44SJohn Forte for (timer = 0; timer < 3000 && 3838*fcf3ce44SJohn Forte !(ha->task_daemon_flags & STATE_ONLINE); 3839*fcf3ce44SJohn Forte timer++) { 3840*fcf3ce44SJohn Forte delay(1); 3841*fcf3ce44SJohn Forte } 3842*fcf3ce44SJohn Forte } 3843*fcf3ce44SJohn Forte 3844*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 3845*fcf3ce44SJohn Forte 3846*fcf3ce44SJohn Forte return (QL_SUCCESS); 3847*fcf3ce44SJohn Forte } 3848*fcf3ce44SJohn Forte 3849*fcf3ce44SJohn Forte /* 3850*fcf3ce44SJohn Forte * ql_vport_create 3851*fcf3ce44SJohn Forte * Create virtual port context. 3852*fcf3ce44SJohn Forte * 3853*fcf3ce44SJohn Forte * Input: 3854*fcf3ce44SJohn Forte * ha: parent adapter state pointer. 3855*fcf3ce44SJohn Forte * index: virtual port index number. 3856*fcf3ce44SJohn Forte * 3857*fcf3ce44SJohn Forte * Context: 3858*fcf3ce44SJohn Forte * Kernel context. 3859*fcf3ce44SJohn Forte */ 3860*fcf3ce44SJohn Forte ql_adapter_state_t * 3861*fcf3ce44SJohn Forte ql_vport_create(ql_adapter_state_t *ha, uint8_t index) 3862*fcf3ce44SJohn Forte { 3863*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 3864*fcf3ce44SJohn Forte 3865*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3866*fcf3ce44SJohn Forte 3867*fcf3ce44SJohn Forte /* Inherit the parents data. */ 3868*fcf3ce44SJohn Forte vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP); 3869*fcf3ce44SJohn Forte 3870*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3871*fcf3ce44SJohn Forte bcopy(ha, vha, sizeof (ql_adapter_state_t)); 3872*fcf3ce44SJohn Forte vha->pi_attrs = NULL; 3873*fcf3ce44SJohn Forte vha->ub_outcnt = 0; 3874*fcf3ce44SJohn Forte vha->ub_allocated = 0; 3875*fcf3ce44SJohn Forte vha->flags = 0; 3876*fcf3ce44SJohn Forte vha->task_daemon_flags = 0; 3877*fcf3ce44SJohn Forte ha->vp_next = vha; 3878*fcf3ce44SJohn Forte vha->pha = ha; 3879*fcf3ce44SJohn Forte vha->vp_index = index; 3880*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3881*fcf3ce44SJohn Forte 3882*fcf3ce44SJohn Forte vha->hba.next = NULL; 3883*fcf3ce44SJohn Forte vha->hba.prev = NULL; 3884*fcf3ce44SJohn Forte vha->hba.base_address = vha; 3885*fcf3ce44SJohn Forte vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE; 3886*fcf3ce44SJohn Forte vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE, 3887*fcf3ce44SJohn Forte KM_SLEEP); 3888*fcf3ce44SJohn Forte vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT, 3889*fcf3ce44SJohn Forte KM_SLEEP); 3890*fcf3ce44SJohn Forte 3891*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 3892*fcf3ce44SJohn Forte 3893*fcf3ce44SJohn Forte return (vha); 3894*fcf3ce44SJohn Forte } 3895*fcf3ce44SJohn Forte 3896*fcf3ce44SJohn Forte /* 3897*fcf3ce44SJohn Forte * ql_vport_destroy 3898*fcf3ce44SJohn Forte * Destroys virtual port context. 3899*fcf3ce44SJohn Forte * 3900*fcf3ce44SJohn Forte * Input: 3901*fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 3902*fcf3ce44SJohn Forte * 3903*fcf3ce44SJohn Forte * Context: 3904*fcf3ce44SJohn Forte * Kernel context. 3905*fcf3ce44SJohn Forte */ 3906*fcf3ce44SJohn Forte void 3907*fcf3ce44SJohn Forte ql_vport_destroy(ql_adapter_state_t *ha) 3908*fcf3ce44SJohn Forte { 3909*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 3910*fcf3ce44SJohn Forte 3911*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3912*fcf3ce44SJohn Forte 3913*fcf3ce44SJohn Forte /* Remove port from list. */ 3914*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3915*fcf3ce44SJohn Forte for (vha = ha->pha; vha != NULL; vha = vha->vp_next) { 3916*fcf3ce44SJohn Forte if (vha->vp_next == ha) { 3917*fcf3ce44SJohn Forte vha->vp_next = ha->vp_next; 3918*fcf3ce44SJohn Forte break; 3919*fcf3ce44SJohn Forte } 3920*fcf3ce44SJohn Forte } 3921*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3922*fcf3ce44SJohn Forte 3923*fcf3ce44SJohn Forte if (ha->ub_array != NULL) { 3924*fcf3ce44SJohn Forte kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT); 3925*fcf3ce44SJohn Forte } 3926*fcf3ce44SJohn Forte if (ha->dev != NULL) { 3927*fcf3ce44SJohn Forte kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE); 3928*fcf3ce44SJohn Forte } 3929*fcf3ce44SJohn Forte kmem_free(ha, sizeof (ql_adapter_state_t)); 3930*fcf3ce44SJohn Forte 3931*fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 3932*fcf3ce44SJohn Forte } 3933