1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22c1fad183SDaniel Beauregard /* Copyright 2010 QLogic Corporation */ 23fcf3ce44SJohn Forte 24fcf3ce44SJohn Forte /* 25*f885d00fSDaniel Beauregard * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28c1fad183SDaniel Beauregard #pragma ident "Copyright 2010 QLogic Corporation; ql_init.c" 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte /* 31fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 32fcf3ce44SJohn Forte * 33fcf3ce44SJohn Forte * *********************************************************************** 34fcf3ce44SJohn Forte * * ** 35fcf3ce44SJohn Forte * * NOTICE ** 36c1fad183SDaniel Beauregard * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION ** 37fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 38fcf3ce44SJohn Forte * * ** 39fcf3ce44SJohn Forte * *********************************************************************** 40fcf3ce44SJohn Forte * 41fcf3ce44SJohn Forte */ 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte #include <ql_apps.h> 44fcf3ce44SJohn Forte #include <ql_api.h> 45fcf3ce44SJohn Forte #include <ql_debug.h> 46fcf3ce44SJohn Forte #include <ql_init.h> 47fcf3ce44SJohn Forte #include <ql_iocb.h> 48fcf3ce44SJohn Forte #include <ql_isr.h> 49fcf3ce44SJohn Forte #include <ql_mbx.h> 50eb82ff87SDaniel Beauregard #include <ql_nx.h> 51fcf3ce44SJohn Forte #include <ql_xioctl.h> 52fcf3ce44SJohn Forte 53fcf3ce44SJohn Forte /* 54fcf3ce44SJohn Forte * Local data 55fcf3ce44SJohn Forte */ 56fcf3ce44SJohn Forte 57fcf3ce44SJohn Forte /* 58fcf3ce44SJohn Forte * Local prototypes 59fcf3ce44SJohn Forte */ 60fcf3ce44SJohn Forte static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t); 61fcf3ce44SJohn Forte static int ql_nvram_24xx_config(ql_adapter_state_t *); 62fcf3ce44SJohn Forte static void ql_23_properties(ql_adapter_state_t *, nvram_t *); 63fcf3ce44SJohn Forte static void ql_24xx_properties(ql_adapter_state_t *, nvram_24xx_t *); 64fcf3ce44SJohn Forte static int ql_check_isp_firmware(ql_adapter_state_t *); 65fcf3ce44SJohn Forte static int ql_chip_diag(ql_adapter_state_t *); 66fcf3ce44SJohn Forte static int ql_load_flash_fw(ql_adapter_state_t *); 67fcf3ce44SJohn Forte static int ql_configure_loop(ql_adapter_state_t *); 68fcf3ce44SJohn Forte static int ql_configure_hba(ql_adapter_state_t *); 69fcf3ce44SJohn Forte static int ql_configure_fabric(ql_adapter_state_t *); 70fcf3ce44SJohn Forte static int ql_configure_device_d_id(ql_adapter_state_t *); 71fcf3ce44SJohn Forte static void ql_set_max_read_req(ql_adapter_state_t *); 725dfd244aSDaniel Beauregard static void ql_configure_n_port_info(ql_adapter_state_t *); 73a2b3ff35SDaniel Beauregard static void ql_clear_mcp(ql_adapter_state_t *); 74f33c1cdbSDaniel Beauregard static void ql_mps_reset(ql_adapter_state_t *); 75a2b3ff35SDaniel Beauregard 76fcf3ce44SJohn Forte /* 77fcf3ce44SJohn Forte * ql_initialize_adapter 78fcf3ce44SJohn Forte * Initialize board. 79fcf3ce44SJohn Forte * 80fcf3ce44SJohn Forte * Input: 81fcf3ce44SJohn Forte * ha = adapter state pointer. 82fcf3ce44SJohn Forte * 83fcf3ce44SJohn Forte * Returns: 84fcf3ce44SJohn Forte * ql local function return status code. 85fcf3ce44SJohn Forte * 86fcf3ce44SJohn Forte * Context: 87fcf3ce44SJohn Forte * Kernel context. 88fcf3ce44SJohn Forte */ 89fcf3ce44SJohn Forte int 90fcf3ce44SJohn Forte ql_initialize_adapter(ql_adapter_state_t *ha) 91fcf3ce44SJohn Forte { 92fcf3ce44SJohn Forte int rval; 93fcf3ce44SJohn Forte class_svc_param_t *class3_param; 94fcf3ce44SJohn Forte caddr_t msg; 95fcf3ce44SJohn Forte la_els_logi_t *els = &ha->loginparams; 96fcf3ce44SJohn Forte int retries = 5; 97fcf3ce44SJohn Forte 98fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 99fcf3ce44SJohn Forte 100fcf3ce44SJohn Forte do { 101fcf3ce44SJohn Forte /* Clear adapter flags. */ 102fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 103fcf3ce44SJohn Forte ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG | 104fcf3ce44SJohn Forte TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG | 105fcf3ce44SJohn Forte TASK_DAEMON_IDLE_CHK_FLG; 106fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 107fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 108fcf3ce44SJohn Forte 109fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 110fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 11116dd44c2SDaniel Beauregard ha->flags |= ABORT_CMDS_LOOP_DOWN_TMO; 112fcf3ce44SJohn Forte ha->flags &= ~ONLINE; 113fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 114fcf3ce44SJohn Forte 115fcf3ce44SJohn Forte ha->state = FC_STATE_OFFLINE; 116fcf3ce44SJohn Forte msg = "Loop OFFLINE"; 117fcf3ce44SJohn Forte 118fcf3ce44SJohn Forte rval = ql_pci_sbus_config(ha); 119fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 120fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 121fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) { 122fcf3ce44SJohn Forte EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n"); 123fcf3ce44SJohn Forte ha->task_daemon_flags |= ISP_ABORT_NEEDED; 124fcf3ce44SJohn Forte } 125fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 126fcf3ce44SJohn Forte continue; 127fcf3ce44SJohn Forte } 128fcf3ce44SJohn Forte 1295dfd244aSDaniel Beauregard (void) ql_setup_fcache(ha); 130fcf3ce44SJohn Forte 131fcf3ce44SJohn Forte /* Reset ISP chip. */ 132fcf3ce44SJohn Forte ql_reset_chip(ha); 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte /* Get NVRAM configuration if needed. */ 135fcf3ce44SJohn Forte if (ha->init_ctrl_blk.cb.version == 0) { 136fcf3ce44SJohn Forte (void) ql_nvram_config(ha); 137fcf3ce44SJohn Forte } 138fcf3ce44SJohn Forte 139fcf3ce44SJohn Forte /* Set login parameters. */ 140eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 141fcf3ce44SJohn Forte els->common_service.rx_bufsize = CHAR_TO_SHORT( 142fcf3ce44SJohn Forte ha->init_ctrl_blk.cb24.max_frame_length[0], 143fcf3ce44SJohn Forte ha->init_ctrl_blk.cb24.max_frame_length[1]); 144fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb24.port_name[0], 145fcf3ce44SJohn Forte (void *)&els->nport_ww_name.raw_wwn[0], 8); 146fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb24.node_name[0], 147fcf3ce44SJohn Forte (void *)&els->node_ww_name.raw_wwn[0], 8); 148fcf3ce44SJohn Forte } else { 149fcf3ce44SJohn Forte els->common_service.rx_bufsize = CHAR_TO_SHORT( 150fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.max_frame_length[0], 151fcf3ce44SJohn Forte ha->init_ctrl_blk.cb.max_frame_length[1]); 152fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb.port_name[0], 153fcf3ce44SJohn Forte (void *)&els->nport_ww_name.raw_wwn[0], 8); 154fcf3ce44SJohn Forte bcopy((void *)&ha->init_ctrl_blk.cb.node_name[0], 155fcf3ce44SJohn Forte (void *)&els->node_ww_name.raw_wwn[0], 8); 156fcf3ce44SJohn Forte } 157*f885d00fSDaniel Beauregard bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv, 158*f885d00fSDaniel Beauregard strlen(QL_VERSION)); 159fcf3ce44SJohn Forte 160fcf3ce44SJohn Forte /* Determine which RISC code to use. */ 161eb82ff87SDaniel Beauregard if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) { 162eb82ff87SDaniel Beauregard if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) { 163eb82ff87SDaniel Beauregard rval = ql_load_isp_firmware(ha); 164eb82ff87SDaniel Beauregard } 165fcf3ce44SJohn Forte } 166fcf3ce44SJohn Forte 167fcf3ce44SJohn Forte if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) == 1685dfd244aSDaniel Beauregard QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS) { 169fcf3ce44SJohn Forte 170fcf3ce44SJohn Forte (void) ql_fw_ready(ha, ha->fwwait); 171fcf3ce44SJohn Forte 172fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & QL_SUSPENDED) && 173fcf3ce44SJohn Forte ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 174fcf3ce44SJohn Forte if (ha->topology & QL_LOOP_CONNECTION) { 175fcf3ce44SJohn Forte ha->state = ha->state | FC_STATE_LOOP; 176fcf3ce44SJohn Forte msg = "Loop ONLINE"; 177fcf3ce44SJohn Forte ha->task_daemon_flags |= STATE_ONLINE; 178fcf3ce44SJohn Forte } else if (ha->topology & QL_P2P_CONNECTION) { 179fcf3ce44SJohn Forte ha->state = ha->state | 180fcf3ce44SJohn Forte FC_STATE_ONLINE; 181fcf3ce44SJohn Forte msg = "Link ONLINE"; 182fcf3ce44SJohn Forte ha->task_daemon_flags |= STATE_ONLINE; 183fcf3ce44SJohn Forte } else { 184fcf3ce44SJohn Forte msg = "Unknown Link state"; 185fcf3ce44SJohn Forte } 186fcf3ce44SJohn Forte } 187fcf3ce44SJohn Forte } else { 188fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 189fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) { 190fcf3ce44SJohn Forte EL(ha, "failed, isp_abort_needed\n"); 191fcf3ce44SJohn Forte ha->task_daemon_flags |= ISP_ABORT_NEEDED | 192fcf3ce44SJohn Forte LOOP_DOWN; 193fcf3ce44SJohn Forte } 194fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 195fcf3ce44SJohn Forte } 196fcf3ce44SJohn Forte 197fcf3ce44SJohn Forte } while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED); 198fcf3ce44SJohn Forte 199fcf3ce44SJohn Forte cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg); 200fcf3ce44SJohn Forte 201fcf3ce44SJohn Forte /* Enable ISP interrupts and login parameters. */ 202eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 203eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ha); 204eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 205eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, ictrl, ISP_EN_RISC); 206eb82ff87SDaniel Beauregard } else { 207eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 208eb82ff87SDaniel Beauregard } 209fcf3ce44SJohn Forte 210fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 211fcf3ce44SJohn Forte ha->flags |= (INTERRUPTS_ENABLED | ONLINE); 212fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 213fcf3ce44SJohn Forte 214fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FC_STATE_CHANGE | RESET_MARKER_NEEDED | 215fcf3ce44SJohn Forte COMMAND_WAIT_NEEDED); 216fcf3ce44SJohn Forte 217fcf3ce44SJohn Forte /* 218fcf3ce44SJohn Forte * Setup login parameters. 219fcf3ce44SJohn Forte */ 220fcf3ce44SJohn Forte els->common_service.fcph_version = 0x2006; 221fcf3ce44SJohn Forte els->common_service.btob_credit = 3; 222fcf3ce44SJohn Forte els->common_service.cmn_features = 0x8800; 223fcf3ce44SJohn Forte els->common_service.conc_sequences = 0xff; 224fcf3ce44SJohn Forte els->common_service.relative_offset = 3; 225fcf3ce44SJohn Forte els->common_service.e_d_tov = 0x07d0; 226fcf3ce44SJohn Forte 227fcf3ce44SJohn Forte class3_param = (class_svc_param_t *)&els->class_3; 228fcf3ce44SJohn Forte class3_param->class_valid_svc_opt = 0x8800; 229fcf3ce44SJohn Forte class3_param->rcv_data_size = els->common_service.rx_bufsize; 230fcf3ce44SJohn Forte class3_param->conc_sequences = 0xff; 231fcf3ce44SJohn Forte 232fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 233fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 234fcf3ce44SJohn Forte } else { 235fcf3ce44SJohn Forte /*EMPTY*/ 236fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 237fcf3ce44SJohn Forte } 238fcf3ce44SJohn Forte return (rval); 239fcf3ce44SJohn Forte } 240fcf3ce44SJohn Forte 241fcf3ce44SJohn Forte /* 242fcf3ce44SJohn Forte * ql_pci_sbus_config 243fcf3ce44SJohn Forte * Setup device PCI/SBUS configuration registers. 244fcf3ce44SJohn Forte * 245fcf3ce44SJohn Forte * Input: 246fcf3ce44SJohn Forte * ha = adapter state pointer. 247fcf3ce44SJohn Forte * 248fcf3ce44SJohn Forte * Returns: 249fcf3ce44SJohn Forte * ql local function return status code. 250fcf3ce44SJohn Forte * 251fcf3ce44SJohn Forte * Context: 252fcf3ce44SJohn Forte * Kernel context. 253fcf3ce44SJohn Forte */ 254fcf3ce44SJohn Forte int 255fcf3ce44SJohn Forte ql_pci_sbus_config(ql_adapter_state_t *ha) 256fcf3ce44SJohn Forte { 257fcf3ce44SJohn Forte uint32_t timer; 258fcf3ce44SJohn Forte uint16_t cmd, w16; 259fcf3ce44SJohn Forte 260fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 261fcf3ce44SJohn Forte 262fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 263fcf3ce44SJohn Forte w16 = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle, 264fcf3ce44SJohn Forte (uint16_t *)(ha->sbus_fpga_iobase + FPGA_REVISION)); 265fcf3ce44SJohn Forte EL(ha, "FPGA rev is %d.%d", (w16 & 0xf0) >> 4, 266fcf3ce44SJohn Forte w16 & 0xf); 267fcf3ce44SJohn Forte } else { 268fcf3ce44SJohn Forte /* 269fcf3ce44SJohn Forte * we want to respect framework's setting of PCI 270fcf3ce44SJohn Forte * configuration space command register and also 271fcf3ce44SJohn Forte * want to make sure that all bits of interest to us 272fcf3ce44SJohn Forte * are properly set in command register. 273fcf3ce44SJohn Forte */ 274fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 275fcf3ce44SJohn Forte cmd = (uint16_t)(cmd | PCI_COMM_IO | PCI_COMM_MAE | 276fcf3ce44SJohn Forte PCI_COMM_ME | PCI_COMM_MEMWR_INVAL | 277fcf3ce44SJohn Forte PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE); 278fcf3ce44SJohn Forte 279fcf3ce44SJohn Forte /* 280fcf3ce44SJohn Forte * If this is a 2300 card and not 2312, reset the 281fcf3ce44SJohn Forte * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the 282fcf3ce44SJohn Forte * 2310 also reports itself as a 2300 so we need to get the 283fcf3ce44SJohn Forte * fb revision level -- a 6 indicates it really is a 2300 and 284fcf3ce44SJohn Forte * not a 2310. 285fcf3ce44SJohn Forte */ 286fcf3ce44SJohn Forte 287fcf3ce44SJohn Forte if (ha->device_id == 0x2300) { 288fcf3ce44SJohn Forte /* Pause RISC. */ 289fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 290fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 291fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 292fcf3ce44SJohn Forte 0) { 293fcf3ce44SJohn Forte break; 294fcf3ce44SJohn Forte } else { 295fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 296fcf3ce44SJohn Forte } 297fcf3ce44SJohn Forte } 298fcf3ce44SJohn Forte 299fcf3ce44SJohn Forte /* Select FPM registers. */ 300fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x20); 301fcf3ce44SJohn Forte 302fcf3ce44SJohn Forte /* Get the fb rev level */ 303fcf3ce44SJohn Forte if (RD16_IO_REG(ha, fb_cmd) == 6) { 304fcf3ce44SJohn Forte cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL); 305fcf3ce44SJohn Forte } 306fcf3ce44SJohn Forte 307fcf3ce44SJohn Forte /* Deselect FPM registers. */ 308fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x0); 309fcf3ce44SJohn Forte 310fcf3ce44SJohn Forte /* Release RISC module. */ 311fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 312fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 313fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) == 314fcf3ce44SJohn Forte 0) { 315fcf3ce44SJohn Forte break; 316fcf3ce44SJohn Forte } else { 317fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 318fcf3ce44SJohn Forte } 319fcf3ce44SJohn Forte } 320fcf3ce44SJohn Forte } else if (ha->device_id == 0x2312) { 321fcf3ce44SJohn Forte /* 322fcf3ce44SJohn Forte * cPCI ISP2312 specific code to service function 1 323fcf3ce44SJohn Forte * hot-swap registers. 324fcf3ce44SJohn Forte */ 325fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK) 326fcf3ce44SJohn Forte != 0) { 327fcf3ce44SJohn Forte ql_pci_config_put8(ha, 0x66, 0xc2); 328fcf3ce44SJohn Forte } 329fcf3ce44SJohn Forte } 330fcf3ce44SJohn Forte 331eb82ff87SDaniel Beauregard if (!(CFG_IST(ha, CFG_CTRL_8021)) && 332eb82ff87SDaniel Beauregard ha->pci_max_read_req != 0) { 333fcf3ce44SJohn Forte ql_set_max_read_req(ha); 334fcf3ce44SJohn Forte } 335fcf3ce44SJohn Forte 336fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 337fcf3ce44SJohn Forte 338fcf3ce44SJohn Forte /* Set cache line register. */ 339fcf3ce44SJohn Forte ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10); 340fcf3ce44SJohn Forte 341fcf3ce44SJohn Forte /* Set latency register. */ 342fcf3ce44SJohn Forte ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40); 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte /* Reset expansion ROM address decode enable. */ 345fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM); 346fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~BIT_0); 347fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_ROM, w16); 348fcf3ce44SJohn Forte } 349fcf3ce44SJohn Forte 350fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 351fcf3ce44SJohn Forte 352fcf3ce44SJohn Forte return (QL_SUCCESS); 353fcf3ce44SJohn Forte } 354fcf3ce44SJohn Forte 355fcf3ce44SJohn Forte /* 356fcf3ce44SJohn Forte * Set the PCI max read request value. 357fcf3ce44SJohn Forte * 358fcf3ce44SJohn Forte * Input: 359fcf3ce44SJohn Forte * ha: adapter state pointer. 360fcf3ce44SJohn Forte * 361fcf3ce44SJohn Forte * Output: 362fcf3ce44SJohn Forte * none. 363fcf3ce44SJohn Forte * 364fcf3ce44SJohn Forte * Returns: 365fcf3ce44SJohn Forte * 366fcf3ce44SJohn Forte * Context: 367fcf3ce44SJohn Forte * Kernel context. 368fcf3ce44SJohn Forte */ 369fcf3ce44SJohn Forte 370fcf3ce44SJohn Forte static void 371fcf3ce44SJohn Forte ql_set_max_read_req(ql_adapter_state_t *ha) 372fcf3ce44SJohn Forte { 373fcf3ce44SJohn Forte uint16_t read_req, w16; 374fcf3ce44SJohn Forte uint16_t tmp = ha->pci_max_read_req; 375fcf3ce44SJohn Forte 376fcf3ce44SJohn Forte if ((ha->device_id == 0x2422) || 377fcf3ce44SJohn Forte ((ha->device_id & 0xff00) == 0x2300)) { 378fcf3ce44SJohn Forte /* check for vaild override value */ 379fcf3ce44SJohn Forte if (tmp == 512 || tmp == 1024 || tmp == 2048 || 380fcf3ce44SJohn Forte tmp == 4096) { 381fcf3ce44SJohn Forte /* shift away the don't cares */ 382fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 10); 383fcf3ce44SJohn Forte /* convert bit pos to request value */ 384fcf3ce44SJohn Forte for (read_req = 0; tmp != 0; read_req++) { 385fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 1); 386fcf3ce44SJohn Forte } 387fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, 0x4e); 388fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2)); 389fcf3ce44SJohn Forte w16 = (uint16_t)(w16 | (read_req << 2)); 390fcf3ce44SJohn Forte ql_pci_config_put16(ha, 0x4e, w16); 391fcf3ce44SJohn Forte } else { 392fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 393fcf3ce44SJohn Forte "'pci-max-read-request': %d; using system " 394fcf3ce44SJohn Forte "default\n", tmp); 395fcf3ce44SJohn Forte } 396fcf3ce44SJohn Forte } else if ((ha->device_id == 0x2432) || ((ha->device_id & 0xff00) == 39716dd44c2SDaniel Beauregard 0x2500) || (ha->device_id == 0x8432)) { 398fcf3ce44SJohn Forte /* check for vaild override value */ 399fcf3ce44SJohn Forte if (tmp == 128 || tmp == 256 || tmp == 512 || 400fcf3ce44SJohn Forte tmp == 1024 || tmp == 2048 || tmp == 4096) { 401fcf3ce44SJohn Forte /* shift away the don't cares */ 402fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 8); 403fcf3ce44SJohn Forte /* convert bit pos to request value */ 404fcf3ce44SJohn Forte for (read_req = 0; tmp != 0; read_req++) { 405fcf3ce44SJohn Forte tmp = (uint16_t)(tmp >> 1); 406fcf3ce44SJohn Forte } 407fcf3ce44SJohn Forte w16 = (uint16_t)ql_pci_config_get16(ha, 0x54); 408fcf3ce44SJohn Forte w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 | 409fcf3ce44SJohn Forte BIT_12)); 410fcf3ce44SJohn Forte w16 = (uint16_t)(w16 | (read_req << 12)); 411fcf3ce44SJohn Forte ql_pci_config_put16(ha, 0x54, w16); 412fcf3ce44SJohn Forte } else { 413fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 414fcf3ce44SJohn Forte "'pci-max-read-request': %d; using system " 415fcf3ce44SJohn Forte "default\n", tmp); 416fcf3ce44SJohn Forte } 417fcf3ce44SJohn Forte } 418fcf3ce44SJohn Forte } 419fcf3ce44SJohn Forte 420fcf3ce44SJohn Forte /* 421fcf3ce44SJohn Forte * NVRAM configuration. 422fcf3ce44SJohn Forte * 423fcf3ce44SJohn Forte * Input: 424fcf3ce44SJohn Forte * ha: adapter state pointer. 425fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 426fcf3ce44SJohn Forte * 427fcf3ce44SJohn Forte * Output: 428fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 429fcf3ce44SJohn Forte * host adapters parameters in host adapter block 430fcf3ce44SJohn Forte * 431fcf3ce44SJohn Forte * Returns: 432fcf3ce44SJohn Forte * ql local function return status code. 433fcf3ce44SJohn Forte * 434fcf3ce44SJohn Forte * Context: 435fcf3ce44SJohn Forte * Kernel context. 436fcf3ce44SJohn Forte */ 437fcf3ce44SJohn Forte int 438fcf3ce44SJohn Forte ql_nvram_config(ql_adapter_state_t *ha) 439fcf3ce44SJohn Forte { 440fcf3ce44SJohn Forte uint32_t cnt; 441fcf3ce44SJohn Forte caddr_t dptr1, dptr2; 442fcf3ce44SJohn Forte ql_init_cb_t *icb = &ha->init_ctrl_blk.cb; 443fcf3ce44SJohn Forte ql_ip_init_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb; 444fcf3ce44SJohn Forte nvram_t *nv = (nvram_t *)ha->request_ring_bp; 445fcf3ce44SJohn Forte uint16_t *wptr = (uint16_t *)ha->request_ring_bp; 446fcf3ce44SJohn Forte uint8_t chksum = 0; 447fcf3ce44SJohn Forte int rval; 448fcf3ce44SJohn Forte int idpromlen; 449fcf3ce44SJohn Forte char idprombuf[32]; 450fcf3ce44SJohn Forte uint32_t start_addr; 451fcf3ce44SJohn Forte 452fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 453fcf3ce44SJohn Forte 454eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 455fcf3ce44SJohn Forte return (ql_nvram_24xx_config(ha)); 456fcf3ce44SJohn Forte } 457fcf3ce44SJohn Forte 458fcf3ce44SJohn Forte start_addr = 0; 459fcf3ce44SJohn Forte if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) == 460fcf3ce44SJohn Forte QL_SUCCESS) { 461fcf3ce44SJohn Forte /* Verify valid NVRAM checksum. */ 462fcf3ce44SJohn Forte for (cnt = 0; cnt < sizeof (nvram_t)/2; cnt++) { 463fcf3ce44SJohn Forte *wptr = (uint16_t)ql_get_nvram_word(ha, 464fcf3ce44SJohn Forte (uint32_t)(cnt + start_addr)); 465fcf3ce44SJohn Forte chksum = (uint8_t)(chksum + (uint8_t)*wptr); 466fcf3ce44SJohn Forte chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8)); 467fcf3ce44SJohn Forte wptr++; 468fcf3ce44SJohn Forte } 469fcf3ce44SJohn Forte ql_release_nvram(ha); 470fcf3ce44SJohn Forte } 471fcf3ce44SJohn Forte 472fcf3ce44SJohn Forte /* Bad NVRAM data, set defaults parameters. */ 473fcf3ce44SJohn Forte if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' || 474fcf3ce44SJohn Forte nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || 475fcf3ce44SJohn Forte nv->nvram_version < 1) { 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte EL(ha, "failed, rval=%xh, checksum=%xh, " 478fcf3ce44SJohn Forte "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, " 479fcf3ce44SJohn Forte "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1], 480fcf3ce44SJohn Forte nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size, 481fcf3ce44SJohn Forte ha->subven_id, nv->nvram_version); 482fcf3ce44SJohn Forte 483fcf3ce44SJohn Forte /* Don't print nvram message if it's an on-board 2200 */ 484fcf3ce44SJohn Forte if (!((CFG_IST(ha, CFG_CTRL_2200)) && 485fcf3ce44SJohn Forte (ha->xioctl->fdesc.flash_size == 0))) { 486fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed," 487fcf3ce44SJohn Forte " using driver defaults.", QL_NAME, ha->instance); 488fcf3ce44SJohn Forte } 489fcf3ce44SJohn Forte 490fcf3ce44SJohn Forte /* Reset NVRAM data. */ 491fcf3ce44SJohn Forte bzero((void *)nv, sizeof (nvram_t)); 492fcf3ce44SJohn Forte 493fcf3ce44SJohn Forte /* 494fcf3ce44SJohn Forte * Set default initialization control block. 495fcf3ce44SJohn Forte */ 496fcf3ce44SJohn Forte nv->parameter_block_version = ICB_VERSION; 497fcf3ce44SJohn Forte nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1; 498fcf3ce44SJohn Forte nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2; 499fcf3ce44SJohn Forte 500fcf3ce44SJohn Forte nv->max_frame_length[1] = 4; 501fcf3ce44SJohn Forte 502fcf3ce44SJohn Forte /* 503fcf3ce44SJohn Forte * Allow 2048 byte frames for 2300 504fcf3ce44SJohn Forte */ 505fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 506fcf3ce44SJohn Forte nv->max_frame_length[1] = 8; 507fcf3ce44SJohn Forte } 508fcf3ce44SJohn Forte nv->max_iocb_allocation[1] = 1; 509fcf3ce44SJohn Forte nv->execution_throttle[0] = 16; 510fcf3ce44SJohn Forte nv->login_retry_count = 8; 511fcf3ce44SJohn Forte 512fcf3ce44SJohn Forte idpromlen = 32; 513fcf3ce44SJohn Forte 514fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 515fcf3ce44SJohn Forte if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip, 516fcf3ce44SJohn Forte DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf, 517fcf3ce44SJohn Forte &idpromlen) != DDI_PROP_SUCCESS) { 518fcf3ce44SJohn Forte 519fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): Unable to read idprom " 520fcf3ce44SJohn Forte "property\n", ha->instance); 521fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) : Unable to read idprom " 522fcf3ce44SJohn Forte "property", QL_NAME, ha->instance); 523fcf3ce44SJohn Forte 524fcf3ce44SJohn Forte nv->port_name[2] = 33; 525fcf3ce44SJohn Forte nv->port_name[3] = 224; 526fcf3ce44SJohn Forte nv->port_name[4] = 139; 527fcf3ce44SJohn Forte nv->port_name[7] = (uint8_t) 528fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 529fcf3ce44SJohn Forte } else { 530fcf3ce44SJohn Forte 531fcf3ce44SJohn Forte nv->port_name[2] = idprombuf[2]; 532fcf3ce44SJohn Forte nv->port_name[3] = idprombuf[3]; 533fcf3ce44SJohn Forte nv->port_name[4] = idprombuf[4]; 534fcf3ce44SJohn Forte nv->port_name[5] = idprombuf[5]; 535fcf3ce44SJohn Forte nv->port_name[6] = idprombuf[6]; 536fcf3ce44SJohn Forte nv->port_name[7] = idprombuf[7]; 537fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t) 538fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 539fcf3ce44SJohn Forte } 540fcf3ce44SJohn Forte 541fcf3ce44SJohn Forte /* Don't print nvram message if it's an on-board 2200 */ 542fcf3ce44SJohn Forte if (!(CFG_IST(ha, CFG_CTRL_2200)) && 543fcf3ce44SJohn Forte (ha->xioctl->fdesc.flash_size == 0)) { 544fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using" 545fcf3ce44SJohn Forte " default HBA parameters and temporary WWPN:" 546fcf3ce44SJohn Forte " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME, 547fcf3ce44SJohn Forte ha->instance, nv->port_name[0], nv->port_name[1], 548fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], 549fcf3ce44SJohn Forte nv->port_name[4], nv->port_name[5], 550fcf3ce44SJohn Forte nv->port_name[6], nv->port_name[7]); 551fcf3ce44SJohn Forte } 552fcf3ce44SJohn Forte 553fcf3ce44SJohn Forte nv->login_timeout = 4; 554fcf3ce44SJohn Forte 555fcf3ce44SJohn Forte /* Set default connection options for the 23xx to 2 */ 556fcf3ce44SJohn Forte if (!(CFG_IST(ha, CFG_CTRL_2200))) { 557fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] | 558fcf3ce44SJohn Forte BIT_5); 559fcf3ce44SJohn Forte } 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte /* 562fcf3ce44SJohn Forte * Set default host adapter parameters 563fcf3ce44SJohn Forte */ 564fcf3ce44SJohn Forte nv->host_p[0] = BIT_1; 565fcf3ce44SJohn Forte nv->host_p[1] = BIT_2; 566fcf3ce44SJohn Forte nv->reset_delay = 5; 567fcf3ce44SJohn Forte nv->port_down_retry_count = 8; 568fcf3ce44SJohn Forte nv->maximum_luns_per_target[0] = 8; 569fcf3ce44SJohn Forte 570fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 571fcf3ce44SJohn Forte } 572fcf3ce44SJohn Forte 573fcf3ce44SJohn Forte /* Check for adapter node name (big endian). */ 574fcf3ce44SJohn Forte for (cnt = 0; cnt < 8; cnt++) { 575fcf3ce44SJohn Forte if (nv->node_name[cnt] != 0) { 576fcf3ce44SJohn Forte break; 577fcf3ce44SJohn Forte } 578fcf3ce44SJohn Forte } 579fcf3ce44SJohn Forte 580fcf3ce44SJohn Forte /* Copy port name if no node name (big endian). */ 581fcf3ce44SJohn Forte if (cnt == 8) { 582fcf3ce44SJohn Forte bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8); 583fcf3ce44SJohn Forte nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0); 584fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0); 585fcf3ce44SJohn Forte } 586fcf3ce44SJohn Forte 587fcf3ce44SJohn Forte /* Reset initialization control blocks. */ 588fcf3ce44SJohn Forte bzero((void *)icb, sizeof (ql_init_cb_t)); 589fcf3ce44SJohn Forte 590fcf3ce44SJohn Forte /* Get driver properties. */ 591fcf3ce44SJohn Forte ql_23_properties(ha, nv); 592fcf3ce44SJohn Forte 593fcf3ce44SJohn Forte cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x" 594fcf3ce44SJohn Forte "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n", 595fcf3ce44SJohn Forte QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1], 596fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 597fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7], 598fcf3ce44SJohn Forte nv->node_name[0], nv->node_name[1], nv->node_name[2], 599fcf3ce44SJohn Forte nv->node_name[3], nv->node_name[4], nv->node_name[5], 600fcf3ce44SJohn Forte nv->node_name[6], nv->node_name[7]); 601fcf3ce44SJohn Forte 602fcf3ce44SJohn Forte /* 603fcf3ce44SJohn Forte * Copy over NVRAM RISC parameter block 604fcf3ce44SJohn Forte * to initialization control block. 605fcf3ce44SJohn Forte */ 606fcf3ce44SJohn Forte dptr1 = (caddr_t)icb; 607fcf3ce44SJohn Forte dptr2 = (caddr_t)&nv->parameter_block_version; 608fcf3ce44SJohn Forte cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] - 609fcf3ce44SJohn Forte (uintptr_t)&icb->version); 610fcf3ce44SJohn Forte while (cnt-- != 0) { 611fcf3ce44SJohn Forte *dptr1++ = *dptr2++; 612fcf3ce44SJohn Forte } 613fcf3ce44SJohn Forte 614fcf3ce44SJohn Forte /* Copy 2nd half. */ 615fcf3ce44SJohn Forte dptr1 = (caddr_t)&icb->add_fw_opt[0]; 616fcf3ce44SJohn Forte cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] - 617fcf3ce44SJohn Forte (uintptr_t)&icb->add_fw_opt[0]); 618fcf3ce44SJohn Forte 619fcf3ce44SJohn Forte while (cnt-- != 0) { 620fcf3ce44SJohn Forte *dptr1++ = *dptr2++; 621fcf3ce44SJohn Forte } 622fcf3ce44SJohn Forte 623fcf3ce44SJohn Forte /* 624fcf3ce44SJohn Forte * Setup driver firmware options. 625fcf3ce44SJohn Forte */ 626fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 627fcf3ce44SJohn Forte (icb->firmware_options[0] | BIT_6 | BIT_1); 628fcf3ce44SJohn Forte 629fcf3ce44SJohn Forte /* 630fcf3ce44SJohn Forte * There is no use enabling fast post for SBUS or 2300 6315dfd244aSDaniel Beauregard * Always enable 64bit addressing, except SBUS cards. 632fcf3ce44SJohn Forte */ 6335dfd244aSDaniel Beauregard ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING; 634fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_SBUS_CARD | CFG_CTRL_2300 | CFG_CTRL_6322))) { 635fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 636fcf3ce44SJohn Forte (icb->firmware_options[0] & ~BIT_3); 637fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 638fcf3ce44SJohn Forte icb->special_options[0] = (uint8_t) 639fcf3ce44SJohn Forte (icb->special_options[0] | BIT_5); 6405dfd244aSDaniel Beauregard ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING; 641fcf3ce44SJohn Forte } 642fcf3ce44SJohn Forte } else { 643fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 644fcf3ce44SJohn Forte (icb->firmware_options[0] | BIT_3); 645fcf3ce44SJohn Forte } 646fcf3ce44SJohn Forte /* RIO and ZIO not supported. */ 647fcf3ce44SJohn Forte icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] & 648fcf3ce44SJohn Forte ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); 649fcf3ce44SJohn Forte 650fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] | 651fcf3ce44SJohn Forte BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0); 652fcf3ce44SJohn Forte icb->firmware_options[0] = (uint8_t) 653fcf3ce44SJohn Forte (icb->firmware_options[0] & ~(BIT_5 | BIT_4)); 654fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t) 655fcf3ce44SJohn Forte (icb->firmware_options[1] & ~BIT_4); 656fcf3ce44SJohn Forte 657fcf3ce44SJohn Forte icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4)); 658fcf3ce44SJohn Forte icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1); 659fcf3ce44SJohn Forte 660fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 661fcf3ce44SJohn Forte if ((icb->special_options[1] & 0x20) == 0) { 662fcf3ce44SJohn Forte EL(ha, "50 ohm is not set\n"); 663fcf3ce44SJohn Forte } 664fcf3ce44SJohn Forte } 665fcf3ce44SJohn Forte icb->execution_throttle[0] = 0xff; 666fcf3ce44SJohn Forte icb->execution_throttle[1] = 0xff; 667fcf3ce44SJohn Forte 668fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) { 669fcf3ce44SJohn Forte icb->firmware_options[1] = (uint8_t) 670fcf3ce44SJohn Forte (icb->firmware_options[1] | BIT_7 | BIT_6); 671fcf3ce44SJohn Forte icb->add_fw_opt[1] = (uint8_t) 672fcf3ce44SJohn Forte (icb->add_fw_opt[1] | BIT_5 | BIT_4); 673fcf3ce44SJohn Forte } 674fcf3ce44SJohn Forte 675fcf3ce44SJohn Forte /* 676fcf3ce44SJohn Forte * Set host adapter parameters 677fcf3ce44SJohn Forte */ 678fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 679fcf3ce44SJohn Forte ha->nvram_version = nv->nvram_version; 680fcf3ce44SJohn Forte ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0], 681fcf3ce44SJohn Forte nv->adapter_features[1]); 682fcf3ce44SJohn Forte 683fcf3ce44SJohn Forte nv->host_p[0] & BIT_4 ? (ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD) : 684fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_DISABLE_RISC_CODE_LOAD); 685fcf3ce44SJohn Forte nv->host_p[0] & BIT_5 ? (ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1) : 686fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_SET_CACHE_LINE_SIZE_1); 687fcf3ce44SJohn Forte 688fcf3ce44SJohn Forte nv->host_p[1] & BIT_1 ? (ha->cfg_flags |= CFG_ENABLE_LIP_RESET) : 689fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET); 690fcf3ce44SJohn Forte nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) : 691fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN); 692fcf3ce44SJohn Forte nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) : 693fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET); 694fcf3ce44SJohn Forte 695fcf3ce44SJohn Forte nv->adapter_features[0] & BIT_3 ? 696fcf3ce44SJohn Forte (ha->cfg_flags |= CFG_MULTI_CHIP_ADAPTER) : 697fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_MULTI_CHIP_ADAPTER); 698fcf3ce44SJohn Forte 699fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 700fcf3ce44SJohn Forte 701fcf3ce44SJohn Forte ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0], 702fcf3ce44SJohn Forte nv->execution_throttle[1]); 703fcf3ce44SJohn Forte ha->loop_reset_delay = nv->reset_delay; 704fcf3ce44SJohn Forte ha->port_down_retry_count = nv->port_down_retry_count; 705fcf3ce44SJohn Forte ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ? 706fcf3ce44SJohn Forte R_A_TOV_DEFAULT : icb->login_timeout); 707fcf3ce44SJohn Forte ha->maximum_luns_per_target = CHAR_TO_SHORT( 708fcf3ce44SJohn Forte nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]); 709fcf3ce44SJohn Forte if (ha->maximum_luns_per_target == 0) { 710fcf3ce44SJohn Forte ha->maximum_luns_per_target++; 711fcf3ce44SJohn Forte } 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte /* 714fcf3ce44SJohn Forte * Setup ring parameters in initialization control block 715fcf3ce44SJohn Forte */ 716fcf3ce44SJohn Forte cnt = REQUEST_ENTRY_CNT; 717fcf3ce44SJohn Forte icb->request_q_length[0] = LSB(cnt); 718fcf3ce44SJohn Forte icb->request_q_length[1] = MSB(cnt); 719fcf3ce44SJohn Forte cnt = RESPONSE_ENTRY_CNT; 720fcf3ce44SJohn Forte icb->response_q_length[0] = LSB(cnt); 721fcf3ce44SJohn Forte icb->response_q_length[1] = MSB(cnt); 722fcf3ce44SJohn Forte 723fcf3ce44SJohn Forte icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma))); 724fcf3ce44SJohn Forte icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma))); 725fcf3ce44SJohn Forte icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma))); 726fcf3ce44SJohn Forte icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma))); 727fcf3ce44SJohn Forte icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma))); 728fcf3ce44SJohn Forte icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma))); 729fcf3ce44SJohn Forte icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma))); 730fcf3ce44SJohn Forte icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma))); 731fcf3ce44SJohn Forte 732fcf3ce44SJohn Forte icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma))); 733fcf3ce44SJohn Forte icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma))); 734fcf3ce44SJohn Forte icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma))); 735fcf3ce44SJohn Forte icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma))); 736fcf3ce44SJohn Forte icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma))); 737fcf3ce44SJohn Forte icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma))); 738fcf3ce44SJohn Forte icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma))); 739fcf3ce44SJohn Forte icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma))); 740fcf3ce44SJohn Forte 741fcf3ce44SJohn Forte /* 742fcf3ce44SJohn Forte * Setup IP initialization control block 743fcf3ce44SJohn Forte */ 744fcf3ce44SJohn Forte ip_icb->version = IP_ICB_VERSION; 745fcf3ce44SJohn Forte 746fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 747fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 748fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0); 749fcf3ce44SJohn Forte } else { 750fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 751fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2); 752fcf3ce44SJohn Forte } 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte cnt = RCVBUF_CONTAINER_CNT; 755fcf3ce44SJohn Forte ip_icb->queue_size[0] = LSB(cnt); 756fcf3ce44SJohn Forte ip_icb->queue_size[1] = MSB(cnt); 757fcf3ce44SJohn Forte 758fcf3ce44SJohn Forte ip_icb->queue_address[0] = LSB(LSW(LSD(ha->rcvbuf_dvma))); 759fcf3ce44SJohn Forte ip_icb->queue_address[1] = MSB(LSW(LSD(ha->rcvbuf_dvma))); 760fcf3ce44SJohn Forte ip_icb->queue_address[2] = LSB(MSW(LSD(ha->rcvbuf_dvma))); 761fcf3ce44SJohn Forte ip_icb->queue_address[3] = MSB(MSW(LSD(ha->rcvbuf_dvma))); 762fcf3ce44SJohn Forte ip_icb->queue_address[4] = LSB(LSW(MSD(ha->rcvbuf_dvma))); 763fcf3ce44SJohn Forte ip_icb->queue_address[5] = MSB(LSW(MSD(ha->rcvbuf_dvma))); 764fcf3ce44SJohn Forte ip_icb->queue_address[6] = LSB(MSW(MSD(ha->rcvbuf_dvma))); 765fcf3ce44SJohn Forte ip_icb->queue_address[7] = MSB(MSW(MSD(ha->rcvbuf_dvma))); 766fcf3ce44SJohn Forte 767fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 768fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 769fcf3ce44SJohn Forte } else { 770fcf3ce44SJohn Forte /*EMPTY*/ 771fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 772fcf3ce44SJohn Forte } 773fcf3ce44SJohn Forte return (rval); 774fcf3ce44SJohn Forte } 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte /* 777fcf3ce44SJohn Forte * Get NVRAM data word 778fcf3ce44SJohn Forte * Calculates word position in NVRAM and calls request routine to 779fcf3ce44SJohn Forte * get the word from NVRAM. 780fcf3ce44SJohn Forte * 781fcf3ce44SJohn Forte * Input: 782fcf3ce44SJohn Forte * ha = adapter state pointer. 783fcf3ce44SJohn Forte * address = NVRAM word address. 784fcf3ce44SJohn Forte * 785fcf3ce44SJohn Forte * Returns: 786fcf3ce44SJohn Forte * data word. 787fcf3ce44SJohn Forte * 788fcf3ce44SJohn Forte * Context: 789fcf3ce44SJohn Forte * Kernel context. 790fcf3ce44SJohn Forte */ 791fcf3ce44SJohn Forte uint16_t 792fcf3ce44SJohn Forte ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address) 793fcf3ce44SJohn Forte { 794fcf3ce44SJohn Forte uint32_t nv_cmd; 795fcf3ce44SJohn Forte uint16_t rval; 796fcf3ce44SJohn Forte 797fcf3ce44SJohn Forte QL_PRINT_4(CE_CONT, "(%d): started\n", ha->instance); 798fcf3ce44SJohn Forte 799fcf3ce44SJohn Forte nv_cmd = address << 16; 800fcf3ce44SJohn Forte nv_cmd = nv_cmd | NV_READ_OP; 801fcf3ce44SJohn Forte 802fcf3ce44SJohn Forte rval = (uint16_t)ql_nvram_request(ha, nv_cmd); 803fcf3ce44SJohn Forte 804fcf3ce44SJohn Forte QL_PRINT_4(CE_CONT, "(%d): NVRAM data = %xh\n", ha->instance, rval); 805fcf3ce44SJohn Forte 806fcf3ce44SJohn Forte return (rval); 807fcf3ce44SJohn Forte } 808fcf3ce44SJohn Forte 809fcf3ce44SJohn Forte /* 810fcf3ce44SJohn Forte * NVRAM request 811fcf3ce44SJohn Forte * Sends read command to NVRAM and gets data from NVRAM. 812fcf3ce44SJohn Forte * 813fcf3ce44SJohn Forte * Input: 814fcf3ce44SJohn Forte * ha = adapter state pointer. 815fcf3ce44SJohn Forte * nv_cmd = Bit 26= start bit 816fcf3ce44SJohn Forte * Bit 25, 24 = opcode 817fcf3ce44SJohn Forte * Bit 23-16 = address 818fcf3ce44SJohn Forte * Bit 15-0 = write data 819fcf3ce44SJohn Forte * 820fcf3ce44SJohn Forte * Returns: 821fcf3ce44SJohn Forte * data word. 822fcf3ce44SJohn Forte * 823fcf3ce44SJohn Forte * Context: 824fcf3ce44SJohn Forte * Kernel context. 825fcf3ce44SJohn Forte */ 826fcf3ce44SJohn Forte static uint16_t 827fcf3ce44SJohn Forte ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd) 828fcf3ce44SJohn Forte { 829fcf3ce44SJohn Forte uint8_t cnt; 830fcf3ce44SJohn Forte uint16_t reg_data; 831fcf3ce44SJohn Forte uint16_t data = 0; 832fcf3ce44SJohn Forte 833fcf3ce44SJohn Forte /* Send command to NVRAM. */ 834fcf3ce44SJohn Forte 835fcf3ce44SJohn Forte nv_cmd <<= 5; 836fcf3ce44SJohn Forte for (cnt = 0; cnt < 11; cnt++) { 837fcf3ce44SJohn Forte if (nv_cmd & BIT_31) { 838fcf3ce44SJohn Forte ql_nv_write(ha, NV_DATA_OUT); 839fcf3ce44SJohn Forte } else { 840fcf3ce44SJohn Forte ql_nv_write(ha, 0); 841fcf3ce44SJohn Forte } 842fcf3ce44SJohn Forte nv_cmd <<= 1; 843fcf3ce44SJohn Forte } 844fcf3ce44SJohn Forte 845fcf3ce44SJohn Forte /* Read data from NVRAM. */ 846fcf3ce44SJohn Forte 847fcf3ce44SJohn Forte for (cnt = 0; cnt < 16; cnt++) { 848fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_SELECT+NV_CLOCK); 849fcf3ce44SJohn Forte ql_nv_delay(); 850fcf3ce44SJohn Forte data <<= 1; 851fcf3ce44SJohn Forte reg_data = RD16_IO_REG(ha, nvram); 852fcf3ce44SJohn Forte if (reg_data & NV_DATA_IN) { 853fcf3ce44SJohn Forte data = (uint16_t)(data | BIT_0); 854fcf3ce44SJohn Forte } 855fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_SELECT); 856fcf3ce44SJohn Forte ql_nv_delay(); 857fcf3ce44SJohn Forte } 858fcf3ce44SJohn Forte 859fcf3ce44SJohn Forte /* Deselect chip. */ 860fcf3ce44SJohn Forte 861fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, NV_DESELECT); 862fcf3ce44SJohn Forte ql_nv_delay(); 863fcf3ce44SJohn Forte 864fcf3ce44SJohn Forte return (data); 865fcf3ce44SJohn Forte } 866fcf3ce44SJohn Forte 867fcf3ce44SJohn Forte void 868fcf3ce44SJohn Forte ql_nv_write(ql_adapter_state_t *ha, uint16_t data) 869fcf3ce44SJohn Forte { 870fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT)); 871fcf3ce44SJohn Forte ql_nv_delay(); 872fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK)); 873fcf3ce44SJohn Forte ql_nv_delay(); 874fcf3ce44SJohn Forte WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT)); 875fcf3ce44SJohn Forte ql_nv_delay(); 876fcf3ce44SJohn Forte } 877fcf3ce44SJohn Forte 878fcf3ce44SJohn Forte void 8795dfd244aSDaniel Beauregard ql_nv_delay(void) 8805dfd244aSDaniel Beauregard { 881fcf3ce44SJohn Forte drv_usecwait(NV_DELAY_COUNT); 882fcf3ce44SJohn Forte } 883fcf3ce44SJohn Forte 884fcf3ce44SJohn Forte /* 885fcf3ce44SJohn Forte * ql_nvram_24xx_config 886fcf3ce44SJohn Forte * ISP2400 nvram. 887fcf3ce44SJohn Forte * 888fcf3ce44SJohn Forte * Input: 889fcf3ce44SJohn Forte * ha: adapter state pointer. 890fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 891fcf3ce44SJohn Forte * 892fcf3ce44SJohn Forte * Output: 893fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 894fcf3ce44SJohn Forte * host adapters parameters in host adapter block 895fcf3ce44SJohn Forte * 896fcf3ce44SJohn Forte * Returns: 897fcf3ce44SJohn Forte * ql local function return status code. 898fcf3ce44SJohn Forte * 899fcf3ce44SJohn Forte * Context: 900fcf3ce44SJohn Forte * Kernel context. 901fcf3ce44SJohn Forte */ 902fcf3ce44SJohn Forte int 903fcf3ce44SJohn Forte ql_nvram_24xx_config(ql_adapter_state_t *ha) 904fcf3ce44SJohn Forte { 905fcf3ce44SJohn Forte uint32_t index, addr, chksum, saved_chksum; 906fcf3ce44SJohn Forte uint32_t *longptr; 907fcf3ce44SJohn Forte nvram_24xx_t nvram; 908fcf3ce44SJohn Forte int idpromlen; 909fcf3ce44SJohn Forte char idprombuf[32]; 910fcf3ce44SJohn Forte caddr_t src, dst; 911fcf3ce44SJohn Forte uint16_t w1; 912fcf3ce44SJohn Forte int rval; 913fcf3ce44SJohn Forte nvram_24xx_t *nv = (nvram_24xx_t *)&nvram; 914fcf3ce44SJohn Forte ql_init_24xx_cb_t *icb = 915fcf3ce44SJohn Forte (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24; 916fcf3ce44SJohn Forte ql_ip_init_24xx_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb24; 917fcf3ce44SJohn Forte 918fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 919fcf3ce44SJohn Forte 920fcf3ce44SJohn Forte if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) { 921fcf3ce44SJohn Forte 922fcf3ce44SJohn Forte /* Get NVRAM data and calculate checksum. */ 923fcf3ce44SJohn Forte longptr = (uint32_t *)nv; 924fcf3ce44SJohn Forte chksum = saved_chksum = 0; 925fcf3ce44SJohn Forte for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) { 926fcf3ce44SJohn Forte rval = ql_24xx_read_flash(ha, addr++, longptr); 927fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 928fcf3ce44SJohn Forte EL(ha, "24xx_read_flash failed=%xh\n", rval); 929fcf3ce44SJohn Forte break; 930fcf3ce44SJohn Forte } 931fcf3ce44SJohn Forte saved_chksum = chksum; 932fcf3ce44SJohn Forte chksum += *longptr; 933fcf3ce44SJohn Forte LITTLE_ENDIAN_32(longptr); 934fcf3ce44SJohn Forte longptr++; 935fcf3ce44SJohn Forte } 936fcf3ce44SJohn Forte 937fcf3ce44SJohn Forte ql_release_nvram(ha); 938fcf3ce44SJohn Forte } 939fcf3ce44SJohn Forte 940fcf3ce44SJohn Forte /* Bad NVRAM data, set defaults parameters. */ 941fcf3ce44SJohn Forte if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' || 942fcf3ce44SJohn Forte nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || 943fcf3ce44SJohn Forte (nv->nvram_version[0] | nv->nvram_version[1]) == 0) { 944fcf3ce44SJohn Forte 945fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using " 946fcf3ce44SJohn Forte "driver defaults.", QL_NAME, ha->instance); 947fcf3ce44SJohn Forte 948fcf3ce44SJohn Forte EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, " 949fcf3ce44SJohn Forte "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1], 950fcf3ce44SJohn Forte nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0], 951fcf3ce44SJohn Forte nv->nvram_version[1])); 952fcf3ce44SJohn Forte 953fcf3ce44SJohn Forte saved_chksum = ~saved_chksum + 1; 954fcf3ce44SJohn Forte 955fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0, 956fcf3ce44SJohn Forte MSW(saved_chksum), LSW(saved_chksum)); 957fcf3ce44SJohn Forte 958fcf3ce44SJohn Forte /* Reset NVRAM data. */ 959fcf3ce44SJohn Forte bzero((void *)nv, sizeof (nvram_24xx_t)); 960fcf3ce44SJohn Forte 961fcf3ce44SJohn Forte /* 962fcf3ce44SJohn Forte * Set default initialization control block. 963fcf3ce44SJohn Forte */ 964fcf3ce44SJohn Forte nv->nvram_version[0] = LSB(ICB_24XX_VERSION); 965fcf3ce44SJohn Forte nv->nvram_version[1] = MSB(ICB_24XX_VERSION); 966fcf3ce44SJohn Forte 967fcf3ce44SJohn Forte nv->version[0] = 1; 968fcf3ce44SJohn Forte nv->max_frame_length[1] = 8; 969fcf3ce44SJohn Forte nv->execution_throttle[0] = 16; 970eb82ff87SDaniel Beauregard nv->exchange_count[0] = 128; 971fcf3ce44SJohn Forte nv->max_luns_per_target[0] = 8; 972fcf3ce44SJohn Forte 973fcf3ce44SJohn Forte idpromlen = 32; 974fcf3ce44SJohn Forte 975fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 97616dd44c2SDaniel Beauregard if (rval = ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip, 977fcf3ce44SJohn Forte DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf, 978fcf3ce44SJohn Forte &idpromlen) != DDI_PROP_SUCCESS) { 979fcf3ce44SJohn Forte 980fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) : Unable to read idprom " 98116dd44c2SDaniel Beauregard "property, rval=%x", QL_NAME, ha->instance, rval); 982fcf3ce44SJohn Forte 983fcf3ce44SJohn Forte nv->port_name[0] = 33; 984fcf3ce44SJohn Forte nv->port_name[3] = 224; 985fcf3ce44SJohn Forte nv->port_name[4] = 139; 986fcf3ce44SJohn Forte nv->port_name[7] = (uint8_t) 987fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 988fcf3ce44SJohn Forte } else { 989fcf3ce44SJohn Forte nv->port_name[2] = idprombuf[2]; 990fcf3ce44SJohn Forte nv->port_name[3] = idprombuf[3]; 991fcf3ce44SJohn Forte nv->port_name[4] = idprombuf[4]; 992fcf3ce44SJohn Forte nv->port_name[5] = idprombuf[5]; 993fcf3ce44SJohn Forte nv->port_name[6] = idprombuf[6]; 994fcf3ce44SJohn Forte nv->port_name[7] = idprombuf[7]; 995fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t) 996fcf3ce44SJohn Forte (NAA_ID_IEEE_EXTENDED << 4 | ha->instance); 997fcf3ce44SJohn Forte } 998fcf3ce44SJohn Forte 999fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default " 1000fcf3ce44SJohn Forte "HBA parameters and temporary " 1001fcf3ce44SJohn Forte "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME, 1002fcf3ce44SJohn Forte ha->instance, nv->port_name[0], nv->port_name[1], 1003fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 1004fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7]); 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte nv->login_retry_count[0] = 8; 1007fcf3ce44SJohn Forte 1008fcf3ce44SJohn Forte nv->firmware_options_1[0] = BIT_2 | BIT_1; 1009fcf3ce44SJohn Forte nv->firmware_options_1[1] = BIT_5; 1010fcf3ce44SJohn Forte nv->firmware_options_2[0] = BIT_5; 1011fcf3ce44SJohn Forte nv->firmware_options_2[1] = BIT_4; 1012fcf3ce44SJohn Forte nv->firmware_options_3[1] = BIT_6; 1013fcf3ce44SJohn Forte 1014fcf3ce44SJohn Forte /* 1015fcf3ce44SJohn Forte * Set default host adapter parameters 1016fcf3ce44SJohn Forte */ 1017fcf3ce44SJohn Forte nv->host_p[0] = BIT_4 | BIT_1; 1018fcf3ce44SJohn Forte nv->host_p[1] = BIT_3 | BIT_2; 1019fcf3ce44SJohn Forte nv->reset_delay = 5; 1020fcf3ce44SJohn Forte nv->max_luns_per_target[0] = 128; 1021fcf3ce44SJohn Forte nv->port_down_retry_count[0] = 30; 1022fcf3ce44SJohn Forte nv->link_down_timeout[0] = 30; 1023fcf3ce44SJohn Forte 1024eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081)) { 10255dfd244aSDaniel Beauregard nv->firmware_options_3[2] = BIT_4; 10265dfd244aSDaniel Beauregard nv->feature_mask_l[0] = 9; 10275dfd244aSDaniel Beauregard nv->ext_blk.version[0] = 1; 10285dfd244aSDaniel Beauregard nv->ext_blk.fcf_vlan_match = 1; 10295dfd244aSDaniel Beauregard nv->ext_blk.fcf_vlan_id[0] = LSB(1002); 10305dfd244aSDaniel Beauregard nv->ext_blk.fcf_vlan_id[1] = MSB(1002); 1031eb82ff87SDaniel Beauregard nv->fw.isp8001.e_node_mac_addr[1] = 2; 1032eb82ff87SDaniel Beauregard nv->fw.isp8001.e_node_mac_addr[2] = 3; 1033eb82ff87SDaniel Beauregard nv->fw.isp8001.e_node_mac_addr[3] = 4; 1034eb82ff87SDaniel Beauregard nv->fw.isp8001.e_node_mac_addr[4] = MSB(ha->instance); 1035eb82ff87SDaniel Beauregard nv->fw.isp8001.e_node_mac_addr[5] = LSB(ha->instance); 10365dfd244aSDaniel Beauregard } 10375dfd244aSDaniel Beauregard 1038fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 1039fcf3ce44SJohn Forte } 1040fcf3ce44SJohn Forte 1041fcf3ce44SJohn Forte /* Check for adapter node name (big endian). */ 1042fcf3ce44SJohn Forte for (index = 0; index < 8; index++) { 1043fcf3ce44SJohn Forte if (nv->node_name[index] != 0) { 1044fcf3ce44SJohn Forte break; 1045fcf3ce44SJohn Forte } 1046fcf3ce44SJohn Forte } 1047fcf3ce44SJohn Forte 1048fcf3ce44SJohn Forte /* Copy port name if no node name (big endian). */ 1049fcf3ce44SJohn Forte if (index == 8) { 1050fcf3ce44SJohn Forte bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8); 1051fcf3ce44SJohn Forte nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0); 1052fcf3ce44SJohn Forte nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0); 1053fcf3ce44SJohn Forte } 1054fcf3ce44SJohn Forte 1055fcf3ce44SJohn Forte /* Reset initialization control blocks. */ 1056fcf3ce44SJohn Forte bzero((void *)icb, sizeof (ql_init_24xx_cb_t)); 1057fcf3ce44SJohn Forte 1058fcf3ce44SJohn Forte /* Get driver properties. */ 1059fcf3ce44SJohn Forte ql_24xx_properties(ha, nv); 1060fcf3ce44SJohn Forte 1061fcf3ce44SJohn Forte cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x" 1062fcf3ce44SJohn Forte "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n", 1063fcf3ce44SJohn Forte QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1], 1064fcf3ce44SJohn Forte nv->port_name[2], nv->port_name[3], nv->port_name[4], 1065fcf3ce44SJohn Forte nv->port_name[5], nv->port_name[6], nv->port_name[7], 1066fcf3ce44SJohn Forte nv->node_name[0], nv->node_name[1], nv->node_name[2], 1067fcf3ce44SJohn Forte nv->node_name[3], nv->node_name[4], nv->node_name[5], 1068fcf3ce44SJohn Forte nv->node_name[6], nv->node_name[7]); 1069fcf3ce44SJohn Forte 1070fcf3ce44SJohn Forte /* 1071fcf3ce44SJohn Forte * Copy over NVRAM Firmware Initialization Control Block. 1072fcf3ce44SJohn Forte */ 1073fcf3ce44SJohn Forte dst = (caddr_t)icb; 1074fcf3ce44SJohn Forte src = (caddr_t)&nv->version; 1075fcf3ce44SJohn Forte index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] - 1076fcf3ce44SJohn Forte (uintptr_t)icb); 1077fcf3ce44SJohn Forte while (index--) { 1078fcf3ce44SJohn Forte *dst++ = *src++; 1079fcf3ce44SJohn Forte } 1080fcf3ce44SJohn Forte icb->login_retry_count[0] = nv->login_retry_count[0]; 1081fcf3ce44SJohn Forte icb->login_retry_count[1] = nv->login_retry_count[1]; 1082fcf3ce44SJohn Forte icb->link_down_on_nos[0] = nv->link_down_on_nos[0]; 1083fcf3ce44SJohn Forte icb->link_down_on_nos[1] = nv->link_down_on_nos[1]; 1084fcf3ce44SJohn Forte 1085fcf3ce44SJohn Forte dst = (caddr_t)&icb->interrupt_delay_timer; 1086fcf3ce44SJohn Forte src = (caddr_t)&nv->interrupt_delay_timer; 10875dfd244aSDaniel Beauregard index = (uint32_t)((uintptr_t)&icb->qos - 1088fcf3ce44SJohn Forte (uintptr_t)&icb->interrupt_delay_timer); 1089fcf3ce44SJohn Forte while (index--) { 1090fcf3ce44SJohn Forte *dst++ = *src++; 1091fcf3ce44SJohn Forte } 1092fcf3ce44SJohn Forte 1093fcf3ce44SJohn Forte /* 1094fcf3ce44SJohn Forte * Setup driver firmware options. 1095fcf3ce44SJohn Forte */ 1096eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081)) { 10975dfd244aSDaniel Beauregard dst = (caddr_t)icb->enode_mac_addr; 1098a2b3ff35SDaniel Beauregard src = (caddr_t)nv->fw.isp8001.e_node_mac_addr; 1099a2b3ff35SDaniel Beauregard index = sizeof (nv->fw.isp8001.e_node_mac_addr); 11005dfd244aSDaniel Beauregard while (index--) { 11015dfd244aSDaniel Beauregard *dst++ = *src++; 11025dfd244aSDaniel Beauregard } 11035dfd244aSDaniel Beauregard dst = (caddr_t)&icb->ext_blk; 11045dfd244aSDaniel Beauregard src = (caddr_t)&nv->ext_blk; 11055dfd244aSDaniel Beauregard index = sizeof (ql_ext_icb_8100_t); 11065dfd244aSDaniel Beauregard while (index--) { 11075dfd244aSDaniel Beauregard *dst++ = *src++; 11085dfd244aSDaniel Beauregard } 1109a2b3ff35SDaniel Beauregard EL(ha, "e_node_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n", 1110a2b3ff35SDaniel Beauregard icb->enode_mac_addr[0], icb->enode_mac_addr[1], 1111a2b3ff35SDaniel Beauregard icb->enode_mac_addr[2], icb->enode_mac_addr[3], 1112a2b3ff35SDaniel Beauregard icb->enode_mac_addr[4], icb->enode_mac_addr[5]); 1113fcf3ce44SJohn Forte } else { 1114fcf3ce44SJohn Forte icb->firmware_options_1[0] = (uint8_t) 1115fcf3ce44SJohn Forte (icb->firmware_options_1[0] | BIT_1); 11165dfd244aSDaniel Beauregard icb->firmware_options_1[1] = (uint8_t) 11175dfd244aSDaniel Beauregard (icb->firmware_options_1[1] | BIT_5 | BIT_2); 11185dfd244aSDaniel Beauregard icb->firmware_options_3[0] = (uint8_t) 11195dfd244aSDaniel Beauregard (icb->firmware_options_3[0] | BIT_1); 1120fcf3ce44SJohn Forte } 11215dfd244aSDaniel Beauregard icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] & 11225dfd244aSDaniel Beauregard ~(BIT_5 | BIT_4)); 11235dfd244aSDaniel Beauregard icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] | 11245dfd244aSDaniel Beauregard BIT_6); 11255dfd244aSDaniel Beauregard icb->firmware_options_2[0] = (uint8_t)(icb->firmware_options_2[0] & 11265dfd244aSDaniel Beauregard ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); 1127fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) { 1128fcf3ce44SJohn Forte icb->firmware_options_2[1] = (uint8_t) 1129fcf3ce44SJohn Forte (icb->firmware_options_2[1] | BIT_4); 1130fcf3ce44SJohn Forte } else { 1131fcf3ce44SJohn Forte icb->firmware_options_2[1] = (uint8_t) 1132fcf3ce44SJohn Forte (icb->firmware_options_2[1] & ~BIT_4); 1133fcf3ce44SJohn Forte } 1134fcf3ce44SJohn Forte 1135fcf3ce44SJohn Forte icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] & 1136fcf3ce44SJohn Forte ~BIT_7); 1137fcf3ce44SJohn Forte 11385dfd244aSDaniel Beauregard /* enable special N port 2 N port login behaviour */ 11395dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_2425)) { 11405dfd244aSDaniel Beauregard icb->firmware_options_3[1] = 11415dfd244aSDaniel Beauregard (uint8_t)(icb->firmware_options_3[1] | BIT_0); 11425dfd244aSDaniel Beauregard } 11435dfd244aSDaniel Beauregard 1144fcf3ce44SJohn Forte icb->execution_throttle[0] = 0xff; 1145fcf3ce44SJohn Forte icb->execution_throttle[1] = 0xff; 1146fcf3ce44SJohn Forte 1147fcf3ce44SJohn Forte /* 1148fcf3ce44SJohn Forte * Set host adapter parameters 1149fcf3ce44SJohn Forte */ 1150fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1151fcf3ce44SJohn Forte ha->nvram_version = CHAR_TO_SHORT(nv->nvram_version[0], 1152fcf3ce44SJohn Forte nv->nvram_version[1]); 1153fcf3ce44SJohn Forte nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) : 1154fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN); 1155fcf3ce44SJohn Forte nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) : 1156fcf3ce44SJohn Forte (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET); 1157eb82ff87SDaniel Beauregard ha->cfg_flags &= ~(CFG_DISABLE_RISC_CODE_LOAD | CFG_LR_SUPPORT | 1158fcf3ce44SJohn Forte CFG_SET_CACHE_LINE_SIZE_1 | CFG_MULTI_CHIP_ADAPTER); 1159fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING; 1160eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_81XX) && nv->enhanced_features[0] & BIT_0) { 1161eb82ff87SDaniel Beauregard ha->cfg_flags |= CFG_LR_SUPPORT; 1162eb82ff87SDaniel Beauregard } 1163fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1164fcf3ce44SJohn Forte 1165fcf3ce44SJohn Forte ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0], 1166fcf3ce44SJohn Forte nv->execution_throttle[1]); 1167fcf3ce44SJohn Forte ha->loop_reset_delay = nv->reset_delay; 1168fcf3ce44SJohn Forte ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0], 1169fcf3ce44SJohn Forte nv->port_down_retry_count[1]); 1170fcf3ce44SJohn Forte w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]); 1171fcf3ce44SJohn Forte ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1); 1172fcf3ce44SJohn Forte ha->maximum_luns_per_target = CHAR_TO_SHORT( 1173fcf3ce44SJohn Forte nv->max_luns_per_target[0], nv->max_luns_per_target[1]); 1174fcf3ce44SJohn Forte if (ha->maximum_luns_per_target == 0) { 1175fcf3ce44SJohn Forte ha->maximum_luns_per_target++; 1176fcf3ce44SJohn Forte } 1177fcf3ce44SJohn Forte 1178fcf3ce44SJohn Forte /* ISP2422 Serial Link Control */ 11795dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_2422)) { 11805dfd244aSDaniel Beauregard ha->serdes_param[0] = CHAR_TO_SHORT(nv->fw.isp2400.swing_opt[0], 11815dfd244aSDaniel Beauregard nv->fw.isp2400.swing_opt[1]); 11825dfd244aSDaniel Beauregard ha->serdes_param[1] = CHAR_TO_SHORT(nv->fw.isp2400.swing_1g[0], 11835dfd244aSDaniel Beauregard nv->fw.isp2400.swing_1g[1]); 11845dfd244aSDaniel Beauregard ha->serdes_param[2] = CHAR_TO_SHORT(nv->fw.isp2400.swing_2g[0], 11855dfd244aSDaniel Beauregard nv->fw.isp2400.swing_2g[1]); 11865dfd244aSDaniel Beauregard ha->serdes_param[3] = CHAR_TO_SHORT(nv->fw.isp2400.swing_4g[0], 11875dfd244aSDaniel Beauregard nv->fw.isp2400.swing_4g[1]); 11885dfd244aSDaniel Beauregard } 1189fcf3ce44SJohn Forte 1190fcf3ce44SJohn Forte /* 1191fcf3ce44SJohn Forte * Setup ring parameters in initialization control block 1192fcf3ce44SJohn Forte */ 1193fcf3ce44SJohn Forte w1 = REQUEST_ENTRY_CNT; 1194fcf3ce44SJohn Forte icb->request_q_length[0] = LSB(w1); 1195fcf3ce44SJohn Forte icb->request_q_length[1] = MSB(w1); 1196fcf3ce44SJohn Forte w1 = RESPONSE_ENTRY_CNT; 1197fcf3ce44SJohn Forte icb->response_q_length[0] = LSB(w1); 1198fcf3ce44SJohn Forte icb->response_q_length[1] = MSB(w1); 1199fcf3ce44SJohn Forte 1200fcf3ce44SJohn Forte icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma))); 1201fcf3ce44SJohn Forte icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma))); 1202fcf3ce44SJohn Forte icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma))); 1203fcf3ce44SJohn Forte icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma))); 1204fcf3ce44SJohn Forte icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma))); 1205fcf3ce44SJohn Forte icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma))); 1206fcf3ce44SJohn Forte icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma))); 1207fcf3ce44SJohn Forte icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma))); 1208fcf3ce44SJohn Forte 1209fcf3ce44SJohn Forte icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma))); 1210fcf3ce44SJohn Forte icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma))); 1211fcf3ce44SJohn Forte icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma))); 1212fcf3ce44SJohn Forte icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma))); 1213fcf3ce44SJohn Forte icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma))); 1214fcf3ce44SJohn Forte icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma))); 1215fcf3ce44SJohn Forte icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma))); 1216fcf3ce44SJohn Forte icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma))); 1217fcf3ce44SJohn Forte 1218fcf3ce44SJohn Forte /* 1219fcf3ce44SJohn Forte * Setup IP initialization control block 1220fcf3ce44SJohn Forte */ 1221fcf3ce44SJohn Forte ip_icb->version = IP_ICB_24XX_VERSION; 1222fcf3ce44SJohn Forte 1223fcf3ce44SJohn Forte ip_icb->ip_firmware_options[0] = (uint8_t) 1224fcf3ce44SJohn Forte (ip_icb->ip_firmware_options[0] | BIT_2); 1225fcf3ce44SJohn Forte 1226fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1227fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 1228fcf3ce44SJohn Forte } else { 1229fcf3ce44SJohn Forte /*EMPTY*/ 1230fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1231fcf3ce44SJohn Forte } 1232fcf3ce44SJohn Forte return (rval); 1233fcf3ce44SJohn Forte } 1234fcf3ce44SJohn Forte 1235fcf3ce44SJohn Forte /* 1236fcf3ce44SJohn Forte * ql_lock_nvram 1237fcf3ce44SJohn Forte * Locks NVRAM access and returns starting address of NVRAM. 1238fcf3ce44SJohn Forte * 1239fcf3ce44SJohn Forte * Input: 1240fcf3ce44SJohn Forte * ha: adapter state pointer. 1241fcf3ce44SJohn Forte * addr: pointer for start address. 1242fcf3ce44SJohn Forte * flags: Are mutually exclusive: 1243fcf3ce44SJohn Forte * LNF_NVRAM_DATA --> get nvram 1244fcf3ce44SJohn Forte * LNF_VPD_DATA --> get vpd data (24/25xx only). 1245fcf3ce44SJohn Forte * 1246fcf3ce44SJohn Forte * Returns: 1247fcf3ce44SJohn Forte * ql local function return status code. 1248fcf3ce44SJohn Forte * 1249fcf3ce44SJohn Forte * Context: 1250fcf3ce44SJohn Forte * Kernel context. 1251fcf3ce44SJohn Forte */ 1252fcf3ce44SJohn Forte int 1253fcf3ce44SJohn Forte ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags) 1254fcf3ce44SJohn Forte { 1255fcf3ce44SJohn Forte int i; 1256fcf3ce44SJohn Forte 1257fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) { 1258fcf3ce44SJohn Forte EL(ha, "invalid options for function"); 1259fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1260fcf3ce44SJohn Forte } 1261fcf3ce44SJohn Forte 1262fcf3ce44SJohn Forte if (ha->device_id == 0x2312 || ha->device_id == 0x2322) { 1263fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) == 0) { 1264fcf3ce44SJohn Forte EL(ha, "invalid 2312/2322 option for HBA"); 1265fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1266fcf3ce44SJohn Forte } 1267fcf3ce44SJohn Forte 1268fcf3ce44SJohn Forte /* if function number is non-zero, then adjust offset */ 12695dfd244aSDaniel Beauregard *addr = ha->flash_nvram_addr; 1270fcf3ce44SJohn Forte 1271fcf3ce44SJohn Forte /* Try to get resource lock. Wait for 10 seconds max */ 1272fcf3ce44SJohn Forte for (i = 0; i < 10000; i++) { 1273fcf3ce44SJohn Forte /* if nvram busy bit is reset, acquire sema */ 1274fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) { 1275fcf3ce44SJohn Forte WRT16_IO_REG(ha, host_to_host_sema, 1); 1276fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 1277fcf3ce44SJohn Forte if (RD16_IO_REG(ha, host_to_host_sema) & 1) { 1278fcf3ce44SJohn Forte break; 1279fcf3ce44SJohn Forte } 1280fcf3ce44SJohn Forte } 1281fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 1282fcf3ce44SJohn Forte } 1283fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) { 1284fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock", 1285fcf3ce44SJohn Forte QL_NAME, ha->instance); 1286fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1287fcf3ce44SJohn Forte } 1288fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_CTRL_2422)) { 1289fcf3ce44SJohn Forte if (flags & LNF_VPD_DATA) { 12905dfd244aSDaniel Beauregard *addr = NVRAM_DATA_ADDR | ha->flash_vpd_addr; 1291fcf3ce44SJohn Forte } else if (flags & LNF_NVRAM_DATA) { 12925dfd244aSDaniel Beauregard *addr = NVRAM_DATA_ADDR | ha->flash_nvram_addr; 1293fcf3ce44SJohn Forte } else { 12945dfd244aSDaniel Beauregard EL(ha, "invalid 2422 option for HBA"); 1295fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1296fcf3ce44SJohn Forte } 1297fcf3ce44SJohn Forte 1298fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1299eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_258081)) { 1300fcf3ce44SJohn Forte if (flags & LNF_VPD_DATA) { 13015dfd244aSDaniel Beauregard *addr = ha->flash_data_addr | ha->flash_vpd_addr; 1302fcf3ce44SJohn Forte } else if (flags & LNF_NVRAM_DATA) { 13035dfd244aSDaniel Beauregard *addr = ha->flash_data_addr | ha->flash_nvram_addr; 1304fcf3ce44SJohn Forte } else { 13055dfd244aSDaniel Beauregard EL(ha, "invalid 2581 option for HBA"); 1306fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1307fcf3ce44SJohn Forte } 1308fcf3ce44SJohn Forte 1309fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1310fcf3ce44SJohn Forte } else { 1311fcf3ce44SJohn Forte if ((flags & LNF_NVRAM_DATA) == 0) { 1312fcf3ce44SJohn Forte EL(ha, "invalid option for HBA"); 1313fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 1314fcf3ce44SJohn Forte } 1315fcf3ce44SJohn Forte *addr = 0; 1316fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 1317fcf3ce44SJohn Forte } 1318fcf3ce44SJohn Forte 1319fcf3ce44SJohn Forte return (QL_SUCCESS); 1320fcf3ce44SJohn Forte } 1321fcf3ce44SJohn Forte 1322fcf3ce44SJohn Forte /* 1323fcf3ce44SJohn Forte * ql_release_nvram 1324fcf3ce44SJohn Forte * Releases NVRAM access. 1325fcf3ce44SJohn Forte * 1326fcf3ce44SJohn Forte * Input: 1327fcf3ce44SJohn Forte * ha: adapter state pointer. 1328fcf3ce44SJohn Forte * 1329fcf3ce44SJohn Forte * Context: 1330fcf3ce44SJohn Forte * Kernel context. 1331fcf3ce44SJohn Forte */ 1332fcf3ce44SJohn Forte void 1333fcf3ce44SJohn Forte ql_release_nvram(ql_adapter_state_t *ha) 1334fcf3ce44SJohn Forte { 1335fcf3ce44SJohn Forte if (ha->device_id == 0x2312 || ha->device_id == 0x2322) { 1336fcf3ce44SJohn Forte /* Release resource lock */ 1337fcf3ce44SJohn Forte WRT16_IO_REG(ha, host_to_host_sema, 0); 1338fcf3ce44SJohn Forte } else { 1339fcf3ce44SJohn Forte GLOBAL_HW_UNLOCK(); 1340fcf3ce44SJohn Forte } 1341fcf3ce44SJohn Forte } 1342fcf3ce44SJohn Forte 1343fcf3ce44SJohn Forte /* 1344fcf3ce44SJohn Forte * ql_23_properties 1345fcf3ce44SJohn Forte * Copies driver properties to NVRAM or adapter structure. 1346fcf3ce44SJohn Forte * 1347fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1348fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1349fcf3ce44SJohn Forte * override the default values using driver.conf 1350fcf3ce44SJohn Forte * 1351fcf3ce44SJohn Forte * Input: 1352fcf3ce44SJohn Forte * ha: adapter state pointer. 1353fcf3ce44SJohn Forte * nv: NVRAM structure pointer. 1354fcf3ce44SJohn Forte * 1355fcf3ce44SJohn Forte * Context: 1356fcf3ce44SJohn Forte * Kernel context. 1357fcf3ce44SJohn Forte */ 1358fcf3ce44SJohn Forte static void 1359fcf3ce44SJohn Forte ql_23_properties(ql_adapter_state_t *ha, nvram_t *nv) 1360fcf3ce44SJohn Forte { 1361fcf3ce44SJohn Forte uint32_t data, cnt; 1362fcf3ce44SJohn Forte 1363fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1364fcf3ce44SJohn Forte 1365fcf3ce44SJohn Forte /* Get frame payload size. */ 1366fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) { 1367fcf3ce44SJohn Forte data = 2048; 1368fcf3ce44SJohn Forte } 1369fcf3ce44SJohn Forte if (data == 512 || data == 1024 || data == 2048) { 1370fcf3ce44SJohn Forte nv->max_frame_length[0] = LSB(data); 1371fcf3ce44SJohn Forte nv->max_frame_length[1] = MSB(data); 1372fcf3ce44SJohn Forte } else { 1373fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'max-frame-length': " 1374fcf3ce44SJohn Forte "%d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1375fcf3ce44SJohn Forte nv->max_frame_length[0], nv->max_frame_length[1])); 1376fcf3ce44SJohn Forte } 1377fcf3ce44SJohn Forte 1378fcf3ce44SJohn Forte /* Get max IOCB allocation. */ 1379fcf3ce44SJohn Forte nv->max_iocb_allocation[0] = 0; 1380fcf3ce44SJohn Forte nv->max_iocb_allocation[1] = 1; 1381fcf3ce44SJohn Forte 1382fcf3ce44SJohn Forte /* Get execution throttle. */ 1383fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) { 1384fcf3ce44SJohn Forte data = 32; 1385fcf3ce44SJohn Forte } 1386fcf3ce44SJohn Forte if (data != 0 && data < 65536) { 1387fcf3ce44SJohn Forte nv->execution_throttle[0] = LSB(data); 1388fcf3ce44SJohn Forte nv->execution_throttle[1] = MSB(data); 1389fcf3ce44SJohn Forte } else { 1390fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'execution-throttle': " 1391fcf3ce44SJohn Forte "%d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1392fcf3ce44SJohn Forte nv->execution_throttle[0], nv->execution_throttle[1])); 1393fcf3ce44SJohn Forte } 1394fcf3ce44SJohn Forte 1395fcf3ce44SJohn Forte /* Get Login timeout. */ 1396fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) { 1397fcf3ce44SJohn Forte data = 3; 1398fcf3ce44SJohn Forte } 1399fcf3ce44SJohn Forte if (data < 256) { 1400fcf3ce44SJohn Forte nv->login_timeout = (uint8_t)data; 1401fcf3ce44SJohn Forte } else { 1402fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-timeout': " 1403fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, nv->login_timeout); 1404fcf3ce44SJohn Forte } 1405fcf3ce44SJohn Forte 1406fcf3ce44SJohn Forte /* Get retry count. */ 1407fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) { 1408fcf3ce44SJohn Forte data = 4; 1409fcf3ce44SJohn Forte } 1410fcf3ce44SJohn Forte if (data < 256) { 1411fcf3ce44SJohn Forte nv->login_retry_count = (uint8_t)data; 1412fcf3ce44SJohn Forte } else { 1413fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-retry-count': " 1414fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1415fcf3ce44SJohn Forte nv->login_retry_count); 1416fcf3ce44SJohn Forte } 1417fcf3ce44SJohn Forte 1418fcf3ce44SJohn Forte /* Get adapter hard loop ID enable. */ 1419fcf3ce44SJohn Forte data = ql_get_prop(ha, "enable-adapter-hard-loop-ID"); 1420fcf3ce44SJohn Forte if (data == 0) { 1421fcf3ce44SJohn Forte nv->firmware_options[0] = 1422fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options[0] & ~BIT_0); 1423fcf3ce44SJohn Forte } else if (data == 1) { 1424fcf3ce44SJohn Forte nv->firmware_options[0] = 1425fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options[0] | BIT_0); 1426fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1427fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1428fcf3ce44SJohn Forte "'enable-adapter-hard-loop-ID': %d; using nvram value " 1429fcf3ce44SJohn Forte "of %d\n", data, nv->firmware_options[0] & BIT_0 ? 1 : 0); 1430fcf3ce44SJohn Forte } 1431fcf3ce44SJohn Forte 1432fcf3ce44SJohn Forte /* Get adapter hard loop ID. */ 1433fcf3ce44SJohn Forte data = ql_get_prop(ha, "adapter-hard-loop-ID"); 1434fcf3ce44SJohn Forte if (data < 126) { 1435fcf3ce44SJohn Forte nv->hard_address[0] = (uint8_t)data; 1436fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1437fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': " 143816dd44c2SDaniel Beauregard "%d; using nvram value of %d\n", 143916dd44c2SDaniel Beauregard data, nv->hard_address[0]); 1440fcf3ce44SJohn Forte } 1441fcf3ce44SJohn Forte 1442fcf3ce44SJohn Forte /* Get LIP reset. */ 1443fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) == 1444fcf3ce44SJohn Forte 0xffffffff) { 1445fcf3ce44SJohn Forte data = 0; 1446fcf3ce44SJohn Forte } 1447fcf3ce44SJohn Forte if (data == 0) { 1448fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_1); 1449fcf3ce44SJohn Forte } else if (data == 1) { 1450fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_1); 1451fcf3ce44SJohn Forte } else { 1452fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1453fcf3ce44SJohn Forte "'enable-LIP-reset-on-bus-reset': %d; using nvram value " 1454fcf3ce44SJohn Forte "of %d\n", data, nv->host_p[1] & BIT_1 ? 1 : 0); 1455fcf3ce44SJohn Forte } 1456fcf3ce44SJohn Forte 1457fcf3ce44SJohn Forte /* Get LIP full login. */ 1458fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) == 1459fcf3ce44SJohn Forte 0xffffffff) { 1460fcf3ce44SJohn Forte data = 1; 1461fcf3ce44SJohn Forte } 1462fcf3ce44SJohn Forte if (data == 0) { 1463fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2); 1464fcf3ce44SJohn Forte } else if (data == 1) { 1465fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2); 1466fcf3ce44SJohn Forte } else { 1467fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1468fcf3ce44SJohn Forte "'enable-LIP-full-login-on-bus-reset': %d; using nvram " 1469fcf3ce44SJohn Forte "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0); 1470fcf3ce44SJohn Forte } 1471fcf3ce44SJohn Forte 1472fcf3ce44SJohn Forte /* Get target reset. */ 1473fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) == 1474fcf3ce44SJohn Forte 0xffffffff) { 1475fcf3ce44SJohn Forte data = 0; 1476fcf3ce44SJohn Forte } 1477fcf3ce44SJohn Forte if (data == 0) { 1478fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3); 1479fcf3ce44SJohn Forte } else if (data == 1) { 1480fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3); 1481fcf3ce44SJohn Forte } else { 1482fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1483fcf3ce44SJohn Forte "'enable-target-reset-on-bus-reset': %d; using nvram " 1484fcf3ce44SJohn Forte "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0); 1485fcf3ce44SJohn Forte } 1486fcf3ce44SJohn Forte 1487fcf3ce44SJohn Forte /* Get reset delay. */ 1488fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) { 1489fcf3ce44SJohn Forte data = 5; 1490fcf3ce44SJohn Forte } 1491fcf3ce44SJohn Forte if (data != 0 && data < 256) { 1492fcf3ce44SJohn Forte nv->reset_delay = (uint8_t)data; 1493fcf3ce44SJohn Forte } else { 1494fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'reset-delay': %d; " 1495fcf3ce44SJohn Forte "using nvram value of %d", data, nv->reset_delay); 1496fcf3ce44SJohn Forte } 1497fcf3ce44SJohn Forte 1498fcf3ce44SJohn Forte /* Get port down retry count. */ 1499fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) { 1500fcf3ce44SJohn Forte data = 8; 1501fcf3ce44SJohn Forte } 1502fcf3ce44SJohn Forte if (data < 256) { 1503fcf3ce44SJohn Forte nv->port_down_retry_count = (uint8_t)data; 1504fcf3ce44SJohn Forte } else { 1505fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-count':" 1506fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, 1507fcf3ce44SJohn Forte nv->port_down_retry_count); 1508fcf3ce44SJohn Forte } 1509fcf3ce44SJohn Forte 1510fcf3ce44SJohn Forte /* Get connection mode setting. */ 1511fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) { 1512fcf3ce44SJohn Forte data = 2; 1513fcf3ce44SJohn Forte } 1514fcf3ce44SJohn Forte cnt = CFG_IST(ha, CFG_CTRL_2200) ? 3 : 2; 1515fcf3ce44SJohn Forte if (data <= cnt) { 1516fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] & 1517fcf3ce44SJohn Forte ~(BIT_6 | BIT_5 | BIT_4)); 1518fcf3ce44SJohn Forte nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] | 1519fcf3ce44SJohn Forte (uint8_t)(data << 4)); 1520fcf3ce44SJohn Forte } else { 1521fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'connection-options': " 1522fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1523fcf3ce44SJohn Forte (nv->add_fw_opt[0] >> 4) & 0x3); 1524fcf3ce44SJohn Forte } 1525fcf3ce44SJohn Forte 1526fcf3ce44SJohn Forte /* Get data rate setting. */ 1527fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2200)) == 0) { 1528fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) { 1529fcf3ce44SJohn Forte data = 2; 1530fcf3ce44SJohn Forte } 1531fcf3ce44SJohn Forte if (data < 3) { 1532fcf3ce44SJohn Forte nv->special_options[1] = (uint8_t) 1533fcf3ce44SJohn Forte (nv->special_options[1] & 0x3f); 1534fcf3ce44SJohn Forte nv->special_options[1] = (uint8_t) 1535fcf3ce44SJohn Forte (nv->special_options[1] | (uint8_t)(data << 6)); 1536fcf3ce44SJohn Forte } else { 1537fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'fc-data-rate': " 1538fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, 1539fcf3ce44SJohn Forte (nv->special_options[1] >> 6) & 0x3); 1540fcf3ce44SJohn Forte } 1541fcf3ce44SJohn Forte } 1542fcf3ce44SJohn Forte 1543fcf3ce44SJohn Forte /* Get adapter id string for Sun branded 23xx only */ 1544fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2300)) && nv->adapInfo[0] != 0) { 1545fcf3ce44SJohn Forte (void) snprintf((int8_t *)ha->adapInfo, 16, "%s", 1546fcf3ce44SJohn Forte nv->adapInfo); 1547fcf3ce44SJohn Forte } 1548fcf3ce44SJohn Forte 1549fcf3ce44SJohn Forte /* Get IP FW container count. */ 1550fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count); 1551fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count); 1552fcf3ce44SJohn Forte 1553fcf3ce44SJohn Forte /* Get IP low water mark. */ 1554fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water); 1555fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water); 1556fcf3ce44SJohn Forte 1557fcf3ce44SJohn Forte /* Get IP fast register post count. */ 1558fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] = 1559fcf3ce44SJohn Forte ql_ip_fast_post_count; 1560fcf3ce44SJohn Forte 1561fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1562fcf3ce44SJohn Forte 1563fcf3ce44SJohn Forte ql_common_properties(ha); 1564fcf3ce44SJohn Forte 1565fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1566fcf3ce44SJohn Forte 1567fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1568fcf3ce44SJohn Forte } 1569fcf3ce44SJohn Forte 1570fcf3ce44SJohn Forte /* 1571fcf3ce44SJohn Forte * ql_common_properties 1572fcf3ce44SJohn Forte * Driver properties adapter structure. 1573fcf3ce44SJohn Forte * 1574fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1575fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1576fcf3ce44SJohn Forte * override the default values using driver.conf 1577fcf3ce44SJohn Forte * 1578fcf3ce44SJohn Forte * Input: 1579fcf3ce44SJohn Forte * ha: adapter state pointer. 1580fcf3ce44SJohn Forte * 1581fcf3ce44SJohn Forte * Context: 1582fcf3ce44SJohn Forte * Kernel context. 1583fcf3ce44SJohn Forte */ 1584fcf3ce44SJohn Forte void 1585fcf3ce44SJohn Forte ql_common_properties(ql_adapter_state_t *ha) 1586fcf3ce44SJohn Forte { 1587fcf3ce44SJohn Forte uint32_t data; 1588fcf3ce44SJohn Forte 1589fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1590fcf3ce44SJohn Forte 159116dd44c2SDaniel Beauregard /* Get extended logging trace buffer size. */ 159216dd44c2SDaniel Beauregard if ((data = ql_get_prop(ha, "set-ext-log-buffer-size")) != 159316dd44c2SDaniel Beauregard 0xffffffff && data != 0) { 159416dd44c2SDaniel Beauregard char *new_trace; 159516dd44c2SDaniel Beauregard uint32_t new_size; 159616dd44c2SDaniel Beauregard 159716dd44c2SDaniel Beauregard if (ha->el_trace_desc->trace_buffer != NULL) { 159816dd44c2SDaniel Beauregard new_size = 1024 * data; 159916dd44c2SDaniel Beauregard new_trace = (char *)kmem_zalloc(new_size, KM_SLEEP); 160016dd44c2SDaniel Beauregard 160116dd44c2SDaniel Beauregard if (new_trace == NULL) { 160216dd44c2SDaniel Beauregard cmn_err(CE_WARN, "%s(%d): can't get new" 160316dd44c2SDaniel Beauregard " trace buffer", 160416dd44c2SDaniel Beauregard QL_NAME, ha->instance); 160516dd44c2SDaniel Beauregard } else { 160616dd44c2SDaniel Beauregard /* free the previous */ 160716dd44c2SDaniel Beauregard kmem_free(ha->el_trace_desc->trace_buffer, 160816dd44c2SDaniel Beauregard ha->el_trace_desc->trace_buffer_size); 160916dd44c2SDaniel Beauregard /* Use the new one */ 161016dd44c2SDaniel Beauregard ha->el_trace_desc->trace_buffer = new_trace; 161116dd44c2SDaniel Beauregard ha->el_trace_desc->trace_buffer_size = new_size; 161216dd44c2SDaniel Beauregard } 161316dd44c2SDaniel Beauregard } 161416dd44c2SDaniel Beauregard 161516dd44c2SDaniel Beauregard } 161616dd44c2SDaniel Beauregard 161716dd44c2SDaniel Beauregard /* Get extended logging enable. */ 161816dd44c2SDaniel Beauregard if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff || 161916dd44c2SDaniel Beauregard data == 0) { 162016dd44c2SDaniel Beauregard ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING; 162116dd44c2SDaniel Beauregard } else if (data == 1) { 162216dd44c2SDaniel Beauregard ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING; 162316dd44c2SDaniel Beauregard } else { 162416dd44c2SDaniel Beauregard EL(ha, "invalid parameter value for 'extended-logging': %d;" 162516dd44c2SDaniel Beauregard " using default value of 0\n", data); 162616dd44c2SDaniel Beauregard ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING; 162716dd44c2SDaniel Beauregard } 162816dd44c2SDaniel Beauregard 162916dd44c2SDaniel Beauregard /* Get extended logging trace disable. */ 163016dd44c2SDaniel Beauregard if ((data = ql_get_prop(ha, "disable-extended-logging-trace")) == 163116dd44c2SDaniel Beauregard 0xffffffff || data == 0) { 163216dd44c2SDaniel Beauregard ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE; 163316dd44c2SDaniel Beauregard } else if (data == 1) { 163416dd44c2SDaniel Beauregard ha->cfg_flags |= CFG_DISABLE_EXTENDED_LOGGING_TRACE; 163516dd44c2SDaniel Beauregard } else { 163616dd44c2SDaniel Beauregard EL(ha, "invalid parameter value for " 163716dd44c2SDaniel Beauregard "'disable-extended-logging-trace': %d;" 163816dd44c2SDaniel Beauregard " using default value of 0\n", data); 163916dd44c2SDaniel Beauregard ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE; 164016dd44c2SDaniel Beauregard } 164116dd44c2SDaniel Beauregard 1642fcf3ce44SJohn Forte /* Get FCP 2 Error Recovery. */ 1643fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) == 1644fcf3ce44SJohn Forte 0xffffffff || data == 1) { 1645fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT; 1646fcf3ce44SJohn Forte } else if (data == 0) { 1647fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT; 1648fcf3ce44SJohn Forte } else { 1649fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1650fcf3ce44SJohn Forte "'enable-FCP-2-error-recovery': %d; using nvram value of " 1651fcf3ce44SJohn Forte "1\n", data); 1652fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT; 1653fcf3ce44SJohn Forte } 1654fcf3ce44SJohn Forte 1655fcf3ce44SJohn Forte #ifdef QL_DEBUG_LEVEL_2 1656fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING; 1657fcf3ce44SJohn Forte #endif 1658fcf3ce44SJohn Forte 1659fcf3ce44SJohn Forte /* Get port down retry delay. */ 1660fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) { 1661fcf3ce44SJohn Forte ha->port_down_retry_delay = PORT_RETRY_TIME; 1662fcf3ce44SJohn Forte } else if (data < 256) { 1663fcf3ce44SJohn Forte ha->port_down_retry_delay = (uint8_t)data; 1664fcf3ce44SJohn Forte } else { 1665fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-delay':" 1666fcf3ce44SJohn Forte " %d; using default value of %d", data, PORT_RETRY_TIME); 1667fcf3ce44SJohn Forte ha->port_down_retry_delay = PORT_RETRY_TIME; 1668fcf3ce44SJohn Forte } 1669fcf3ce44SJohn Forte 1670fcf3ce44SJohn Forte /* Get queue full retry count. */ 1671fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) { 1672fcf3ce44SJohn Forte ha->qfull_retry_count = 16; 1673fcf3ce44SJohn Forte } else if (data < 256) { 1674fcf3ce44SJohn Forte ha->qfull_retry_count = (uint8_t)data; 1675fcf3ce44SJohn Forte } else { 1676fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'queue-full-retry-count':" 1677fcf3ce44SJohn Forte " %d; using default value of 16", data); 1678fcf3ce44SJohn Forte ha->qfull_retry_count = 16; 1679fcf3ce44SJohn Forte } 1680fcf3ce44SJohn Forte 1681fcf3ce44SJohn Forte /* Get queue full retry delay. */ 1682fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) { 1683fcf3ce44SJohn Forte ha->qfull_retry_delay = PORT_RETRY_TIME; 1684fcf3ce44SJohn Forte } else if (data < 256) { 1685fcf3ce44SJohn Forte ha->qfull_retry_delay = (uint8_t)data; 1686fcf3ce44SJohn Forte } else { 1687fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'queue-full-retry-delay':" 1688fcf3ce44SJohn Forte " %d; using default value of %d", data, PORT_RETRY_TIME); 1689fcf3ce44SJohn Forte ha->qfull_retry_delay = PORT_RETRY_TIME; 1690fcf3ce44SJohn Forte } 1691fcf3ce44SJohn Forte 1692fcf3ce44SJohn Forte /* Get loop down timeout. */ 1693fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) { 1694fcf3ce44SJohn Forte data = 0; 1695fcf3ce44SJohn Forte } else if (data > 255) { 1696fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'link-down-timeout': %d;" 1697fcf3ce44SJohn Forte " using nvram value of 0\n", data); 1698fcf3ce44SJohn Forte data = 0; 1699fcf3ce44SJohn Forte } 1700fcf3ce44SJohn Forte ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data); 1701fcf3ce44SJohn Forte if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) { 1702fcf3ce44SJohn Forte ha->loop_down_abort_time--; 1703fcf3ce44SJohn Forte } else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) { 1704fcf3ce44SJohn Forte ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1; 1705fcf3ce44SJohn Forte } 1706fcf3ce44SJohn Forte 1707fcf3ce44SJohn Forte /* Get link down error enable. */ 1708fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff || 1709fcf3ce44SJohn Forte data == 1) { 1710fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING; 1711fcf3ce44SJohn Forte } else if (data == 0) { 1712fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING; 1713fcf3ce44SJohn Forte } else { 1714fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'link-down-error': %d;" 1715fcf3ce44SJohn Forte " using default value of 1\n", data); 1716fcf3ce44SJohn Forte } 1717fcf3ce44SJohn Forte 1718fcf3ce44SJohn Forte /* 1719fcf3ce44SJohn Forte * Get firmware dump flags. 1720fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT BIT_0 1721fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR BIT_1 1722fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT BIT_2 1723fcf3ce44SJohn Forte * TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT BIT_3 1724fcf3ce44SJohn Forte */ 1725fcf3ce44SJohn Forte ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT | 1726fcf3ce44SJohn Forte CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT | 1727fcf3ce44SJohn Forte CFG_DUMP_LOOP_OFFLINE_TIMEOUT); 1728fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) { 1729fcf3ce44SJohn Forte if (data & BIT_0) { 1730fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT; 1731fcf3ce44SJohn Forte } 1732fcf3ce44SJohn Forte if (data & BIT_1) { 1733fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR; 1734fcf3ce44SJohn Forte } 1735fcf3ce44SJohn Forte if (data & BIT_2) { 1736fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT; 1737fcf3ce44SJohn Forte } 1738fcf3ce44SJohn Forte if (data & BIT_3) { 1739fcf3ce44SJohn Forte ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT; 1740fcf3ce44SJohn Forte } 1741fcf3ce44SJohn Forte } 1742fcf3ce44SJohn Forte 1743fcf3ce44SJohn Forte /* Get the PCI max read request size override. */ 1744fcf3ce44SJohn Forte ha->pci_max_read_req = 0; 1745fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff && 1746fcf3ce44SJohn Forte data != 0) { 1747fcf3ce44SJohn Forte ha->pci_max_read_req = (uint16_t)(data); 1748fcf3ce44SJohn Forte } 1749fcf3ce44SJohn Forte 1750a2b3ff35SDaniel Beauregard /* 1751a2b3ff35SDaniel Beauregard * Set default fw wait, adjusted for slow FCF's. 1752a2b3ff35SDaniel Beauregard * Revisit when FCF's as fast as FC switches. 1753a2b3ff35SDaniel Beauregard */ 1754eb82ff87SDaniel Beauregard ha->fwwait = (uint8_t)(CFG_IST(ha, CFG_CTRL_8081) ? 45 : 10); 1755fcf3ce44SJohn Forte /* Get the attach fw_ready override value. */ 1756fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) { 1757fcf3ce44SJohn Forte if (data > 0 && data <= 240) { 1758fcf3ce44SJohn Forte ha->fwwait = (uint8_t)data; 1759fcf3ce44SJohn Forte } else { 1760fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1761fcf3ce44SJohn Forte "'init-loop-sync-wait': %d; using default " 1762fcf3ce44SJohn Forte "value of %d\n", data, ha->fwwait); 1763fcf3ce44SJohn Forte } 1764fcf3ce44SJohn Forte } 1765fcf3ce44SJohn Forte 1766fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1767fcf3ce44SJohn Forte } 1768fcf3ce44SJohn Forte 1769fcf3ce44SJohn Forte /* 1770fcf3ce44SJohn Forte * ql_24xx_properties 1771fcf3ce44SJohn Forte * Copies driver properties to NVRAM or adapter structure. 1772fcf3ce44SJohn Forte * 1773fcf3ce44SJohn Forte * Driver properties are by design global variables and hidden 1774fcf3ce44SJohn Forte * completely from administrators. Knowledgeable folks can 1775fcf3ce44SJohn Forte * override the default values using /etc/system. 1776fcf3ce44SJohn Forte * 1777fcf3ce44SJohn Forte * Input: 1778fcf3ce44SJohn Forte * ha: adapter state pointer. 1779fcf3ce44SJohn Forte * nv: NVRAM structure pointer. 1780fcf3ce44SJohn Forte * 1781fcf3ce44SJohn Forte * Context: 1782fcf3ce44SJohn Forte * Kernel context. 1783fcf3ce44SJohn Forte */ 1784fcf3ce44SJohn Forte static void 1785fcf3ce44SJohn Forte ql_24xx_properties(ql_adapter_state_t *ha, nvram_24xx_t *nv) 1786fcf3ce44SJohn Forte { 1787fcf3ce44SJohn Forte uint32_t data; 1788fcf3ce44SJohn Forte 1789fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1790fcf3ce44SJohn Forte 1791fcf3ce44SJohn Forte /* Get frame size */ 1792fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) { 1793fcf3ce44SJohn Forte data = 2048; 1794fcf3ce44SJohn Forte } 1795eb82ff87SDaniel Beauregard if (data == 512 || data == 1024 || data == 2048 || data == 2112) { 1796fcf3ce44SJohn Forte nv->max_frame_length[0] = LSB(data); 1797fcf3ce44SJohn Forte nv->max_frame_length[1] = MSB(data); 1798fcf3ce44SJohn Forte } else { 1799fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'max-frame-length': %d;" 1800fcf3ce44SJohn Forte " using nvram default of %d\n", data, CHAR_TO_SHORT( 1801fcf3ce44SJohn Forte nv->max_frame_length[0], nv->max_frame_length[1])); 1802fcf3ce44SJohn Forte } 1803fcf3ce44SJohn Forte 1804fcf3ce44SJohn Forte /* Get execution throttle. */ 1805fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) { 1806fcf3ce44SJohn Forte data = 32; 1807fcf3ce44SJohn Forte } 1808fcf3ce44SJohn Forte if (data != 0 && data < 65536) { 1809fcf3ce44SJohn Forte nv->execution_throttle[0] = LSB(data); 1810fcf3ce44SJohn Forte nv->execution_throttle[1] = MSB(data); 1811fcf3ce44SJohn Forte } else { 1812fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'execution-throttle':" 1813fcf3ce44SJohn Forte " %d; using nvram default of %d\n", data, CHAR_TO_SHORT( 1814fcf3ce44SJohn Forte nv->execution_throttle[0], nv->execution_throttle[1])); 1815fcf3ce44SJohn Forte } 1816fcf3ce44SJohn Forte 1817fcf3ce44SJohn Forte /* Get Login timeout. */ 1818fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) { 1819fcf3ce44SJohn Forte data = 3; 1820fcf3ce44SJohn Forte } 1821fcf3ce44SJohn Forte if (data < 65536) { 1822fcf3ce44SJohn Forte nv->login_timeout[0] = LSB(data); 1823fcf3ce44SJohn Forte nv->login_timeout[1] = MSB(data); 1824fcf3ce44SJohn Forte } else { 1825fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-timeout': %d; " 1826fcf3ce44SJohn Forte "using nvram value of %d\n", data, CHAR_TO_SHORT( 1827fcf3ce44SJohn Forte nv->login_timeout[0], nv->login_timeout[1])); 1828fcf3ce44SJohn Forte } 1829fcf3ce44SJohn Forte 1830fcf3ce44SJohn Forte /* Get retry count. */ 1831fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) { 1832fcf3ce44SJohn Forte data = 4; 1833fcf3ce44SJohn Forte } 1834fcf3ce44SJohn Forte if (data < 65536) { 1835fcf3ce44SJohn Forte nv->login_retry_count[0] = LSB(data); 1836fcf3ce44SJohn Forte nv->login_retry_count[1] = MSB(data); 1837fcf3ce44SJohn Forte } else { 1838fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'login-retry-count': " 1839fcf3ce44SJohn Forte "%d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1840fcf3ce44SJohn Forte nv->login_retry_count[0], nv->login_retry_count[1])); 1841fcf3ce44SJohn Forte } 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte /* Get adapter hard loop ID enable. */ 1844fcf3ce44SJohn Forte data = ql_get_prop(ha, "enable-adapter-hard-loop-ID"); 1845fcf3ce44SJohn Forte if (data == 0) { 1846fcf3ce44SJohn Forte nv->firmware_options_1[0] = 1847fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options_1[0] & ~BIT_0); 1848fcf3ce44SJohn Forte } else if (data == 1) { 1849fcf3ce44SJohn Forte nv->firmware_options_1[0] = 1850fcf3ce44SJohn Forte (uint8_t)(nv->firmware_options_1[0] | BIT_0); 1851fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1852fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1853fcf3ce44SJohn Forte "'enable-adapter-hard-loop-ID': %d; using nvram value " 1854fcf3ce44SJohn Forte "of %d\n", data, 1855fcf3ce44SJohn Forte nv->firmware_options_1[0] & BIT_0 ? 1 : 0); 1856fcf3ce44SJohn Forte } 1857fcf3ce44SJohn Forte 1858fcf3ce44SJohn Forte /* Get adapter hard loop ID. */ 1859fcf3ce44SJohn Forte data = ql_get_prop(ha, "adapter-hard-loop-ID"); 1860fcf3ce44SJohn Forte if (data < 126) { 1861fcf3ce44SJohn Forte nv->hard_address[0] = LSB(data); 1862fcf3ce44SJohn Forte nv->hard_address[1] = MSB(data); 1863fcf3ce44SJohn Forte } else if (data != 0xffffffff) { 1864fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':" 1865fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1866fcf3ce44SJohn Forte nv->hard_address[0], nv->hard_address[1])); 1867fcf3ce44SJohn Forte } 1868fcf3ce44SJohn Forte 1869fcf3ce44SJohn Forte /* Get LIP reset. */ 1870fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) == 1871fcf3ce44SJohn Forte 0xffffffff) { 1872fcf3ce44SJohn Forte data = 0; 1873fcf3ce44SJohn Forte } 1874fcf3ce44SJohn Forte if (data == 0) { 1875fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET; 1876fcf3ce44SJohn Forte } else if (data == 1) { 1877fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_LIP_RESET; 1878fcf3ce44SJohn Forte } else { 1879fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1880fcf3ce44SJohn Forte "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n", 1881fcf3ce44SJohn Forte data); 1882fcf3ce44SJohn Forte } 1883fcf3ce44SJohn Forte 1884fcf3ce44SJohn Forte /* Get LIP full login. */ 1885fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) == 1886fcf3ce44SJohn Forte 0xffffffff) { 1887fcf3ce44SJohn Forte data = 1; 1888fcf3ce44SJohn Forte } 1889fcf3ce44SJohn Forte if (data == 0) { 1890fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2); 1891fcf3ce44SJohn Forte } else if (data == 1) { 1892fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2); 1893fcf3ce44SJohn Forte } else { 1894fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1895fcf3ce44SJohn Forte "'enable-LIP-full-login-on-bus-reset': %d; using nvram " 1896fcf3ce44SJohn Forte "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0); 1897fcf3ce44SJohn Forte } 1898fcf3ce44SJohn Forte 1899fcf3ce44SJohn Forte /* Get target reset. */ 1900fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) == 1901fcf3ce44SJohn Forte 0xffffffff) { 1902fcf3ce44SJohn Forte data = 0; 1903fcf3ce44SJohn Forte } 1904fcf3ce44SJohn Forte if (data == 0) { 1905fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3); 1906fcf3ce44SJohn Forte } else if (data == 1) { 1907fcf3ce44SJohn Forte nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3); 1908fcf3ce44SJohn Forte } else { 1909fcf3ce44SJohn Forte EL(ha, "invalid parameter value for " 1910fcf3ce44SJohn Forte "'enable-target-reset-on-bus-reset': %d; using nvram " 1911fcf3ce44SJohn Forte "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0); 1912fcf3ce44SJohn Forte } 1913fcf3ce44SJohn Forte 1914fcf3ce44SJohn Forte /* Get reset delay. */ 1915fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) { 1916fcf3ce44SJohn Forte data = 5; 1917fcf3ce44SJohn Forte } 1918fcf3ce44SJohn Forte if (data != 0 && data < 256) { 1919fcf3ce44SJohn Forte nv->reset_delay = (uint8_t)data; 1920fcf3ce44SJohn Forte } else { 1921fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'reset-delay': %d; " 1922fcf3ce44SJohn Forte "using nvram value of %d", data, nv->reset_delay); 1923fcf3ce44SJohn Forte } 1924fcf3ce44SJohn Forte 1925fcf3ce44SJohn Forte /* Get port down retry count. */ 1926fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) { 1927fcf3ce44SJohn Forte data = 8; 1928fcf3ce44SJohn Forte } 1929fcf3ce44SJohn Forte if (data < 256) { 1930fcf3ce44SJohn Forte nv->port_down_retry_count[0] = LSB(data); 1931fcf3ce44SJohn Forte nv->port_down_retry_count[1] = MSB(data); 1932fcf3ce44SJohn Forte } else { 1933fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'port-down-retry-count':" 1934fcf3ce44SJohn Forte " %d; using nvram value of %d\n", data, CHAR_TO_SHORT( 1935fcf3ce44SJohn Forte nv->port_down_retry_count[0], 1936fcf3ce44SJohn Forte nv->port_down_retry_count[1])); 1937fcf3ce44SJohn Forte } 1938fcf3ce44SJohn Forte 1939eb82ff87SDaniel Beauregard if (!(CFG_IST(ha, CFG_CTRL_8081))) { 1940eb82ff87SDaniel Beauregard /* Get connection mode setting. */ 1941eb82ff87SDaniel Beauregard if ((data = ql_get_prop(ha, "connection-options")) == 1942eb82ff87SDaniel Beauregard 0xffffffff) { 1943eb82ff87SDaniel Beauregard data = 2; 1944eb82ff87SDaniel Beauregard } 1945eb82ff87SDaniel Beauregard if (data <= 2) { 1946eb82ff87SDaniel Beauregard nv->firmware_options_2[0] = (uint8_t) 1947eb82ff87SDaniel Beauregard (nv->firmware_options_2[0] & 1948eb82ff87SDaniel Beauregard ~(BIT_6 | BIT_5 | BIT_4)); 1949eb82ff87SDaniel Beauregard nv->firmware_options_2[0] = (uint8_t) 1950eb82ff87SDaniel Beauregard (nv->firmware_options_2[0] | (uint8_t)(data << 4)); 1951eb82ff87SDaniel Beauregard } else { 1952eb82ff87SDaniel Beauregard EL(ha, "invalid parameter value for 'connection-" 1953eb82ff87SDaniel Beauregard "options': %d; using nvram value of %d\n", data, 1954eb82ff87SDaniel Beauregard (nv->firmware_options_2[0] >> 4) & 0x3); 1955eb82ff87SDaniel Beauregard } 1956fcf3ce44SJohn Forte 1957eb82ff87SDaniel Beauregard /* Get data rate setting. */ 1958eb82ff87SDaniel Beauregard if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) { 1959eb82ff87SDaniel Beauregard data = 2; 1960eb82ff87SDaniel Beauregard } 1961eb82ff87SDaniel Beauregard if ((CFG_IST(ha, CFG_CTRL_2422) && data < 4) || 1962eb82ff87SDaniel Beauregard (CFG_IST(ha, CFG_CTRL_258081) && data < 5)) { 1963eb82ff87SDaniel Beauregard nv->firmware_options_3[1] = (uint8_t) 1964eb82ff87SDaniel Beauregard (nv->firmware_options_3[1] & 0x1f); 1965eb82ff87SDaniel Beauregard nv->firmware_options_3[1] = (uint8_t) 1966eb82ff87SDaniel Beauregard (nv->firmware_options_3[1] | (uint8_t)(data << 5)); 1967eb82ff87SDaniel Beauregard } else { 1968eb82ff87SDaniel Beauregard EL(ha, "invalid parameter value for 'fc-data-rate': " 1969eb82ff87SDaniel Beauregard "%d; using nvram value of %d\n", data, 1970eb82ff87SDaniel Beauregard (nv->firmware_options_3[1] >> 5) & 0x7); 1971eb82ff87SDaniel Beauregard } 1972fcf3ce44SJohn Forte } 1973fcf3ce44SJohn Forte 1974fcf3ce44SJohn Forte /* Get IP FW container count. */ 1975fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count); 1976fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count); 1977fcf3ce44SJohn Forte 1978fcf3ce44SJohn Forte /* Get IP low water mark. */ 1979fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water); 1980fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water); 1981fcf3ce44SJohn Forte 1982fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1983fcf3ce44SJohn Forte 1984fcf3ce44SJohn Forte /* Get enable flash load. */ 1985fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff || 1986fcf3ce44SJohn Forte data == 0) { 1987fcf3ce44SJohn Forte ha->cfg_flags &= ~CFG_LOAD_FLASH_FW; 1988fcf3ce44SJohn Forte } else if (data == 1) { 1989fcf3ce44SJohn Forte ha->cfg_flags |= CFG_LOAD_FLASH_FW; 1990fcf3ce44SJohn Forte } else { 1991fcf3ce44SJohn Forte EL(ha, "invalid parameter value for 'enable-flash-load': " 1992fcf3ce44SJohn Forte "%d; using default value of 0\n", data); 1993fcf3ce44SJohn Forte } 1994fcf3ce44SJohn Forte 1995fcf3ce44SJohn Forte /* Enable firmware extended tracing */ 1996fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) { 1997fcf3ce44SJohn Forte if (data != 0) { 1998fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE; 1999fcf3ce44SJohn Forte } 2000fcf3ce44SJohn Forte } 2001fcf3ce44SJohn Forte 2002fcf3ce44SJohn Forte /* Enable firmware fc tracing */ 2003fcf3ce44SJohn Forte if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) { 2004fcf3ce44SJohn Forte ha->cfg_flags |= CFG_ENABLE_FWFCETRACE; 2005fcf3ce44SJohn Forte ha->fwfcetraceopt = data; 2006fcf3ce44SJohn Forte } 2007fcf3ce44SJohn Forte 2008c1fad183SDaniel Beauregard /* Enable fast timeout */ 2009c1fad183SDaniel Beauregard if ((data = ql_get_prop(ha, "enable-fasttimeout")) != 0xffffffff) { 2010c1fad183SDaniel Beauregard if (data != 0) { 2011c1fad183SDaniel Beauregard ha->cfg_flags |= CFG_FAST_TIMEOUT; 2012c1fad183SDaniel Beauregard } 2013c1fad183SDaniel Beauregard } 2014c1fad183SDaniel Beauregard 2015fcf3ce44SJohn Forte ql_common_properties(ha); 2016fcf3ce44SJohn Forte 2017fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2018fcf3ce44SJohn Forte 2019fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2020fcf3ce44SJohn Forte } 2021fcf3ce44SJohn Forte 2022fcf3ce44SJohn Forte /* 2023fcf3ce44SJohn Forte * ql_get_prop 2024fcf3ce44SJohn Forte * Get property value from configuration file. 2025fcf3ce44SJohn Forte * 2026fcf3ce44SJohn Forte * Input: 2027fcf3ce44SJohn Forte * ha= adapter state pointer. 2028fcf3ce44SJohn Forte * string = property string pointer. 2029fcf3ce44SJohn Forte * 2030fcf3ce44SJohn Forte * Returns: 2031fcf3ce44SJohn Forte * 0xFFFFFFFF = no property else property value. 2032fcf3ce44SJohn Forte * 2033fcf3ce44SJohn Forte * Context: 2034fcf3ce44SJohn Forte * Kernel context. 2035fcf3ce44SJohn Forte */ 2036fcf3ce44SJohn Forte uint32_t 2037fcf3ce44SJohn Forte ql_get_prop(ql_adapter_state_t *ha, char *string) 2038fcf3ce44SJohn Forte { 2039fcf3ce44SJohn Forte char buf[256]; 204016dd44c2SDaniel Beauregard uint32_t data = 0xffffffff; 204116dd44c2SDaniel Beauregard 204216dd44c2SDaniel Beauregard /* 204316dd44c2SDaniel Beauregard * Look for a adapter instance NPIV (virtual port) specific parameter 204416dd44c2SDaniel Beauregard */ 2045eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 204616dd44c2SDaniel Beauregard (void) sprintf(buf, "hba%d-vp%d-%s", ha->instance, 204716dd44c2SDaniel Beauregard ha->vp_index, string); 204816dd44c2SDaniel Beauregard /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 204916dd44c2SDaniel Beauregard data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0, 205016dd44c2SDaniel Beauregard buf, (int)0xffffffff); 205116dd44c2SDaniel Beauregard } 2052fcf3ce44SJohn Forte 205316dd44c2SDaniel Beauregard /* 205416dd44c2SDaniel Beauregard * Get adapter instance parameter if a vp specific one isn't found. 205516dd44c2SDaniel Beauregard */ 205616dd44c2SDaniel Beauregard if (data == 0xffffffff) { 205716dd44c2SDaniel Beauregard (void) sprintf(buf, "hba%d-%s", ha->instance, string); 205816dd44c2SDaniel Beauregard /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 205916dd44c2SDaniel Beauregard data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 206016dd44c2SDaniel Beauregard 0, buf, (int)0xffffffff); 206116dd44c2SDaniel Beauregard } 2062fcf3ce44SJohn Forte 2063fcf3ce44SJohn Forte /* Adapter instance parameter found? */ 2064fcf3ce44SJohn Forte if (data == 0xffffffff) { 2065fcf3ce44SJohn Forte /* No, get default parameter. */ 2066fcf3ce44SJohn Forte /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 2067fcf3ce44SJohn Forte data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0, 2068fcf3ce44SJohn Forte string, (int)0xffffffff); 2069fcf3ce44SJohn Forte } 2070fcf3ce44SJohn Forte 2071fcf3ce44SJohn Forte return (data); 2072fcf3ce44SJohn Forte } 2073fcf3ce44SJohn Forte 2074fcf3ce44SJohn Forte /* 2075fcf3ce44SJohn Forte * ql_check_isp_firmware 2076fcf3ce44SJohn Forte * Checks if using already loaded RISC code or drivers copy. 2077fcf3ce44SJohn Forte * If using already loaded code, save a copy of it. 2078fcf3ce44SJohn Forte * 2079fcf3ce44SJohn Forte * Input: 2080fcf3ce44SJohn Forte * ha = adapter state pointer. 2081fcf3ce44SJohn Forte * 2082fcf3ce44SJohn Forte * Returns: 2083fcf3ce44SJohn Forte * ql local function return status code. 2084fcf3ce44SJohn Forte * 2085fcf3ce44SJohn Forte * Context: 2086fcf3ce44SJohn Forte * Kernel context. 2087fcf3ce44SJohn Forte */ 2088fcf3ce44SJohn Forte static int 2089fcf3ce44SJohn Forte ql_check_isp_firmware(ql_adapter_state_t *ha) 2090fcf3ce44SJohn Forte { 2091fcf3ce44SJohn Forte int rval; 2092fcf3ce44SJohn Forte uint16_t word_count; 2093fcf3ce44SJohn Forte uint32_t byte_count; 2094fcf3ce44SJohn Forte uint32_t fw_size, *lptr; 2095fcf3ce44SJohn Forte caddr_t bufp; 2096fcf3ce44SJohn Forte uint16_t risc_address = (uint16_t)ha->risc_fw[0].addr; 2097fcf3ce44SJohn Forte 2098fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2099fcf3ce44SJohn Forte 2100eb82ff87SDaniel Beauregard /* Test for firmware running. */ 2101eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 2102eb82ff87SDaniel Beauregard if (ql_8021_idc_handler(ha) != NX_DEV_READY) { 2103eb82ff87SDaniel Beauregard rval = QL_FUNCTION_FAILED; 2104eb82ff87SDaniel Beauregard } else { 2105eb82ff87SDaniel Beauregard rval = ql_start_firmware(ha); 2106eb82ff87SDaniel Beauregard } 2107eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) { 2108fcf3ce44SJohn Forte if (ha->risc_code != NULL) { 2109fcf3ce44SJohn Forte kmem_free(ha->risc_code, ha->risc_code_size); 2110fcf3ce44SJohn Forte ha->risc_code = NULL; 2111fcf3ce44SJohn Forte ha->risc_code_size = 0; 2112fcf3ce44SJohn Forte } 2113fcf3ce44SJohn Forte 2114fcf3ce44SJohn Forte /* Get RISC code length. */ 2115fcf3ce44SJohn Forte rval = ql_rd_risc_ram(ha, risc_address + 3, ha->request_dvma, 2116fcf3ce44SJohn Forte 1); 2117fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2118fcf3ce44SJohn Forte lptr = (uint32_t *)ha->request_ring_bp; 2119fcf3ce44SJohn Forte fw_size = *lptr << 1; 2120fcf3ce44SJohn Forte 2121fcf3ce44SJohn Forte if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) { 2122fcf3ce44SJohn Forte ha->risc_code_size = fw_size; 2123fcf3ce44SJohn Forte ha->risc_code = bufp; 2124fcf3ce44SJohn Forte ha->fw_transfer_size = 128; 2125fcf3ce44SJohn Forte 2126fcf3ce44SJohn Forte /* Dump RISC code. */ 2127fcf3ce44SJohn Forte do { 2128fcf3ce44SJohn Forte if (fw_size > ha->fw_transfer_size) { 2129fcf3ce44SJohn Forte byte_count = 2130fcf3ce44SJohn Forte ha->fw_transfer_size; 2131fcf3ce44SJohn Forte } else { 2132fcf3ce44SJohn Forte byte_count = fw_size; 2133fcf3ce44SJohn Forte } 2134fcf3ce44SJohn Forte 2135fcf3ce44SJohn Forte word_count = 2136fcf3ce44SJohn Forte (uint16_t)(byte_count >> 1); 2137fcf3ce44SJohn Forte 2138fcf3ce44SJohn Forte rval = ql_rd_risc_ram(ha, risc_address, 2139fcf3ce44SJohn Forte ha->request_dvma, word_count); 2140fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2141fcf3ce44SJohn Forte kmem_free(ha->risc_code, 2142fcf3ce44SJohn Forte ha->risc_code_size); 2143fcf3ce44SJohn Forte ha->risc_code = NULL; 2144fcf3ce44SJohn Forte ha->risc_code_size = 0; 2145fcf3ce44SJohn Forte break; 2146fcf3ce44SJohn Forte } 2147fcf3ce44SJohn Forte 2148fcf3ce44SJohn Forte (void) ddi_dma_sync( 2149fcf3ce44SJohn Forte ha->hba_buf.dma_handle, 2150fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET, 2151fcf3ce44SJohn Forte byte_count, 2152fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 2153fcf3ce44SJohn Forte ddi_rep_get16(ha->hba_buf.acc_handle, 2154fcf3ce44SJohn Forte (uint16_t *)bufp, 2155fcf3ce44SJohn Forte (uint16_t *)ha->request_ring_bp, 2156fcf3ce44SJohn Forte word_count, DDI_DEV_AUTOINCR); 2157fcf3ce44SJohn Forte 2158fcf3ce44SJohn Forte risc_address += word_count; 2159fcf3ce44SJohn Forte fw_size -= byte_count; 2160fcf3ce44SJohn Forte bufp += byte_count; 2161fcf3ce44SJohn Forte } while (fw_size != 0); 2162fcf3ce44SJohn Forte } 2163eb82ff87SDaniel Beauregard rval = QL_FUNCTION_FAILED; 2164fcf3ce44SJohn Forte } 2165fcf3ce44SJohn Forte } else { 2166fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2167fcf3ce44SJohn Forte } 2168fcf3ce44SJohn Forte 2169fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2170fcf3ce44SJohn Forte EL(ha, "Load RISC code\n"); 2171fcf3ce44SJohn Forte } else { 2172fcf3ce44SJohn Forte /*EMPTY*/ 2173fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2174fcf3ce44SJohn Forte } 2175fcf3ce44SJohn Forte return (rval); 2176fcf3ce44SJohn Forte } 2177fcf3ce44SJohn Forte 2178fcf3ce44SJohn Forte /* 2179fcf3ce44SJohn Forte * Chip diagnostics 2180fcf3ce44SJohn Forte * Test chip for proper operation. 2181fcf3ce44SJohn Forte * 2182fcf3ce44SJohn Forte * Input: 2183fcf3ce44SJohn Forte * ha = adapter state pointer. 2184fcf3ce44SJohn Forte * 2185fcf3ce44SJohn Forte * Returns: 2186fcf3ce44SJohn Forte * ql local function return status code. 2187fcf3ce44SJohn Forte * 2188fcf3ce44SJohn Forte * Context: 2189fcf3ce44SJohn Forte * Kernel context. 2190fcf3ce44SJohn Forte */ 2191fcf3ce44SJohn Forte static int 2192fcf3ce44SJohn Forte ql_chip_diag(ql_adapter_state_t *ha) 2193fcf3ce44SJohn Forte { 2194fcf3ce44SJohn Forte ql_mbx_data_t mr; 2195eb82ff87SDaniel Beauregard int rval; 2196fcf3ce44SJohn Forte int32_t retries = 4; 2197fcf3ce44SJohn Forte uint16_t id; 2198fcf3ce44SJohn Forte 2199fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2200fcf3ce44SJohn Forte 2201fcf3ce44SJohn Forte do { 2202fcf3ce44SJohn Forte /* Reset ISP chip. */ 2203fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2204fcf3ce44SJohn Forte ha->task_daemon_flags &= ~ISP_ABORT_NEEDED; 2205fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2206fcf3ce44SJohn Forte 2207fcf3ce44SJohn Forte /* For ISP2200A reduce firmware load size. */ 2208fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2200) && 2209eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[7]) == 4) { 2210fcf3ce44SJohn Forte ha->fw_transfer_size = 128; 2211fcf3ce44SJohn Forte } else { 2212fcf3ce44SJohn Forte ha->fw_transfer_size = REQUEST_QUEUE_SIZE; 2213fcf3ce44SJohn Forte } 2214fcf3ce44SJohn Forte 2215eb82ff87SDaniel Beauregard rval = QL_SUCCESS; 2216eb82ff87SDaniel Beauregard if (!(CFG_IST(ha, CFG_CTRL_8021))) { 2217eb82ff87SDaniel Beauregard ql_reset_chip(ha); 2218eb82ff87SDaniel Beauregard 2219eb82ff87SDaniel Beauregard /* Check product ID of chip */ 2220eb82ff87SDaniel Beauregard mr.mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 2221eb82ff87SDaniel Beauregard mr.mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 2222eb82ff87SDaniel Beauregard mr.mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 2223fcf3ce44SJohn Forte 2224eb82ff87SDaniel Beauregard if (ha->device_id == 0x5432 || 2225eb82ff87SDaniel Beauregard ha->device_id == 0x8432) { 2226eb82ff87SDaniel Beauregard id = 0x2432; 2227eb82ff87SDaniel Beauregard } else if (ha->device_id == 0x5422 || 2228eb82ff87SDaniel Beauregard ha->device_id == 0x8422) { 2229eb82ff87SDaniel Beauregard id = 0x2422; 2230eb82ff87SDaniel Beauregard } else { 2231eb82ff87SDaniel Beauregard id = ha->device_id; 2232eb82ff87SDaniel Beauregard } 2233fcf3ce44SJohn Forte 2234eb82ff87SDaniel Beauregard if (mr.mb[1] == PROD_ID_1 && 2235eb82ff87SDaniel Beauregard (mr.mb[2] == PROD_ID_2 || mr.mb[2] == PROD_ID_2a) && 2236eb82ff87SDaniel Beauregard (mr.mb[3] == PROD_ID_3 || mr.mb[3] == id)) { 2237eb82ff87SDaniel Beauregard ha->adapter_stats->revlvl.isp2200 = 2238eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[4]); 2239eb82ff87SDaniel Beauregard ha->adapter_stats->revlvl.risc = 2240eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[5]); 2241eb82ff87SDaniel Beauregard ha->adapter_stats->revlvl.frmbfr = 2242eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[6]); 2243eb82ff87SDaniel Beauregard ha->adapter_stats->revlvl.riscrom = 2244eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[7]); 2245eb82ff87SDaniel Beauregard } else { 2246eb82ff87SDaniel Beauregard cmn_err(CE_WARN, "%s(%d) - prod id failed!, " 2247eb82ff87SDaniel Beauregard "mb1=%xh, mb2=%xh, mb3=%xh", QL_NAME, 2248eb82ff87SDaniel Beauregard ha->instance, mr.mb[1], mr.mb[2], mr.mb[3]); 2249eb82ff87SDaniel Beauregard rval = QL_FUNCTION_FAILED; 2250eb82ff87SDaniel Beauregard } 2251eb82ff87SDaniel Beauregard } else if (!(ha->task_daemon_flags & FIRMWARE_LOADED)) { 2252eb82ff87SDaniel Beauregard break; 2253eb82ff87SDaniel Beauregard } 2254fcf3ce44SJohn Forte 2255eb82ff87SDaniel Beauregard if (rval == QL_SUCCESS) { 2256fcf3ce44SJohn Forte /* Wrap Incoming Mailboxes Test. */ 2257fcf3ce44SJohn Forte mr.mb[1] = 0xAAAA; 2258fcf3ce44SJohn Forte mr.mb[2] = 0x5555; 2259fcf3ce44SJohn Forte mr.mb[3] = 0xAA55; 2260fcf3ce44SJohn Forte mr.mb[4] = 0x55AA; 2261fcf3ce44SJohn Forte mr.mb[5] = 0xA5A5; 2262fcf3ce44SJohn Forte mr.mb[6] = 0x5A5A; 2263fcf3ce44SJohn Forte mr.mb[7] = 0x2525; 2264fcf3ce44SJohn Forte rval = ql_mbx_wrap_test(ha, &mr); 2265fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2266fcf3ce44SJohn Forte if (mr.mb[1] != 0xAAAA || 2267fcf3ce44SJohn Forte mr.mb[2] != 0x5555 || 2268fcf3ce44SJohn Forte mr.mb[3] != 0xAA55 || 2269fcf3ce44SJohn Forte mr.mb[4] != 0x55AA || 2270fcf3ce44SJohn Forte mr.mb[5] != 0xA5A5 || 2271fcf3ce44SJohn Forte mr.mb[6] != 0x5A5A || 2272fcf3ce44SJohn Forte mr.mb[7] != 0x2525) { 2273fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2274fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, 2275fcf3ce44SJohn Forte FLASH_ERRLOG_ISP_ERR, 0, 2276fcf3ce44SJohn Forte RD16_IO_REG(ha, hccr), 2277fcf3ce44SJohn Forte RD16_IO_REG(ha, istatus)); 2278fcf3ce44SJohn Forte } 2279fcf3ce44SJohn Forte } else { 2280fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s(%d) - reg test failed=" 2281fcf3ce44SJohn Forte "%xh!", QL_NAME, ha->instance, rval); 2282fcf3ce44SJohn Forte } 2283fcf3ce44SJohn Forte } 2284fcf3ce44SJohn Forte } while ((retries-- != 0) && (rval != QL_SUCCESS)); 2285fcf3ce44SJohn Forte 2286fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2287fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2288fcf3ce44SJohn Forte } else { 2289fcf3ce44SJohn Forte /*EMPTY*/ 2290fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2291fcf3ce44SJohn Forte } 2292fcf3ce44SJohn Forte return (rval); 2293fcf3ce44SJohn Forte } 2294fcf3ce44SJohn Forte 2295fcf3ce44SJohn Forte /* 2296fcf3ce44SJohn Forte * ql_load_isp_firmware 2297fcf3ce44SJohn Forte * Load and start RISC firmware. 2298fcf3ce44SJohn Forte * Uses request ring for DMA buffer. 2299fcf3ce44SJohn Forte * 2300fcf3ce44SJohn Forte * Input: 2301fcf3ce44SJohn Forte * ha = adapter state pointer. 2302fcf3ce44SJohn Forte * 2303fcf3ce44SJohn Forte * Returns: 2304fcf3ce44SJohn Forte * ql local function return status code. 2305fcf3ce44SJohn Forte * 2306fcf3ce44SJohn Forte * Context: 2307fcf3ce44SJohn Forte * Kernel context. 2308fcf3ce44SJohn Forte */ 2309fcf3ce44SJohn Forte int 2310fcf3ce44SJohn Forte ql_load_isp_firmware(ql_adapter_state_t *vha) 2311fcf3ce44SJohn Forte { 2312fcf3ce44SJohn Forte caddr_t risc_code_address; 2313fcf3ce44SJohn Forte uint32_t risc_address, risc_code_size; 2314fcf3ce44SJohn Forte int rval; 2315fcf3ce44SJohn Forte uint32_t word_count, cnt; 2316fcf3ce44SJohn Forte size_t byte_count; 2317fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 2318fcf3ce44SJohn Forte 2319eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 2320eb82ff87SDaniel Beauregard rval = ql_8021_load_risc(ha); 2321eb82ff87SDaniel Beauregard } else { 2322eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_81XX)) { 2323eb82ff87SDaniel Beauregard ql_mps_reset(ha); 2324eb82ff87SDaniel Beauregard } 2325f33c1cdbSDaniel Beauregard 2326eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) { 2327eb82ff87SDaniel Beauregard return (ql_load_flash_fw(ha)); 2328eb82ff87SDaniel Beauregard } 2329fcf3ce44SJohn Forte 2330eb82ff87SDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2331fcf3ce44SJohn Forte 2332eb82ff87SDaniel Beauregard /* Load firmware segments */ 2333eb82ff87SDaniel Beauregard for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS && 2334eb82ff87SDaniel Beauregard ha->risc_fw[cnt].code != NULL; cnt++) { 2335fcf3ce44SJohn Forte 2336eb82ff87SDaniel Beauregard risc_code_address = ha->risc_fw[cnt].code; 2337eb82ff87SDaniel Beauregard risc_address = ha->risc_fw[cnt].addr; 2338eb82ff87SDaniel Beauregard risc_code_size = ha->risc_fw[cnt].length; 2339fcf3ce44SJohn Forte 2340eb82ff87SDaniel Beauregard while (risc_code_size) { 2341eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_242581)) { 2342eb82ff87SDaniel Beauregard word_count = ha->fw_transfer_size >> 2; 2343eb82ff87SDaniel Beauregard if (word_count > risc_code_size) { 2344eb82ff87SDaniel Beauregard word_count = risc_code_size; 2345eb82ff87SDaniel Beauregard } 2346eb82ff87SDaniel Beauregard byte_count = word_count << 2; 2347fcf3ce44SJohn Forte 2348eb82ff87SDaniel Beauregard ddi_rep_put32(ha->hba_buf.acc_handle, 2349eb82ff87SDaniel Beauregard (uint32_t *)risc_code_address, 2350eb82ff87SDaniel Beauregard (uint32_t *)ha->request_ring_bp, 2351eb82ff87SDaniel Beauregard word_count, DDI_DEV_AUTOINCR); 2352eb82ff87SDaniel Beauregard } else { 2353eb82ff87SDaniel Beauregard word_count = ha->fw_transfer_size >> 1; 2354eb82ff87SDaniel Beauregard if (word_count > risc_code_size) { 2355eb82ff87SDaniel Beauregard word_count = risc_code_size; 2356eb82ff87SDaniel Beauregard } 2357eb82ff87SDaniel Beauregard byte_count = word_count << 1; 2358eb82ff87SDaniel Beauregard 2359eb82ff87SDaniel Beauregard ddi_rep_put16(ha->hba_buf.acc_handle, 2360eb82ff87SDaniel Beauregard (uint16_t *)risc_code_address, 2361eb82ff87SDaniel Beauregard (uint16_t *)ha->request_ring_bp, 2362eb82ff87SDaniel Beauregard word_count, DDI_DEV_AUTOINCR); 2363fcf3ce44SJohn Forte } 2364fcf3ce44SJohn Forte 2365eb82ff87SDaniel Beauregard (void) ddi_dma_sync(ha->hba_buf.dma_handle, 2366eb82ff87SDaniel Beauregard REQUEST_Q_BUFFER_OFFSET, byte_count, 2367eb82ff87SDaniel Beauregard DDI_DMA_SYNC_FORDEV); 2368fcf3ce44SJohn Forte 2369eb82ff87SDaniel Beauregard rval = ql_wrt_risc_ram(ha, risc_address, 2370eb82ff87SDaniel Beauregard ha->request_dvma, word_count); 2371eb82ff87SDaniel Beauregard if (rval != QL_SUCCESS) { 2372eb82ff87SDaniel Beauregard EL(ha, "failed, load=%xh\n", rval); 2373eb82ff87SDaniel Beauregard cnt = MAX_RISC_CODE_SEGMENTS; 2374eb82ff87SDaniel Beauregard break; 2375eb82ff87SDaniel Beauregard } 2376fcf3ce44SJohn Forte 2377eb82ff87SDaniel Beauregard risc_address += word_count; 2378eb82ff87SDaniel Beauregard risc_code_size -= word_count; 2379eb82ff87SDaniel Beauregard risc_code_address += byte_count; 2380fcf3ce44SJohn Forte } 2381fcf3ce44SJohn Forte } 2382fcf3ce44SJohn Forte } 2383fcf3ce44SJohn Forte 2384fcf3ce44SJohn Forte /* Start firmware. */ 2385fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2386fcf3ce44SJohn Forte rval = ql_start_firmware(ha); 2387fcf3ce44SJohn Forte } 2388fcf3ce44SJohn Forte 2389fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2390fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2391fcf3ce44SJohn Forte } else { 2392fcf3ce44SJohn Forte /*EMPTY*/ 2393fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2394fcf3ce44SJohn Forte } 2395fcf3ce44SJohn Forte 2396fcf3ce44SJohn Forte return (rval); 2397fcf3ce44SJohn Forte } 2398fcf3ce44SJohn Forte 2399fcf3ce44SJohn Forte /* 2400fcf3ce44SJohn Forte * ql_load_flash_fw 2401fcf3ce44SJohn Forte * Gets ISP24xx firmware from flash and loads ISP. 2402fcf3ce44SJohn Forte * 2403fcf3ce44SJohn Forte * Input: 2404fcf3ce44SJohn Forte * ha: adapter state pointer. 2405fcf3ce44SJohn Forte * 2406fcf3ce44SJohn Forte * Returns: 24075dfd244aSDaniel Beauregard * ql local function return status code. 2408fcf3ce44SJohn Forte */ 2409fcf3ce44SJohn Forte static int 2410fcf3ce44SJohn Forte ql_load_flash_fw(ql_adapter_state_t *ha) 2411fcf3ce44SJohn Forte { 2412fcf3ce44SJohn Forte int rval; 2413fcf3ce44SJohn Forte uint8_t seg_cnt; 2414fcf3ce44SJohn Forte uint32_t risc_address, xfer_size, count, *bp, faddr; 2415fcf3ce44SJohn Forte uint32_t risc_code_size = 0; 2416fcf3ce44SJohn Forte 2417fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2418fcf3ce44SJohn Forte 24195dfd244aSDaniel Beauregard faddr = ha->flash_data_addr | ha->flash_fw_addr; 2420fcf3ce44SJohn Forte 2421fcf3ce44SJohn Forte for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) { 2422fcf3ce44SJohn Forte xfer_size = ha->fw_transfer_size >> 2; 2423fcf3ce44SJohn Forte do { 2424fcf3ce44SJohn Forte GLOBAL_HW_LOCK(); 2425fcf3ce44SJohn Forte 2426fcf3ce44SJohn Forte /* Read data from flash. */ 2427fcf3ce44SJohn Forte bp = (uint32_t *)ha->request_ring_bp; 2428fcf3ce44SJohn Forte for (count = 0; count < xfer_size; count++) { 2429fcf3ce44SJohn Forte rval = ql_24xx_read_flash(ha, faddr++, bp); 2430fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2431fcf3ce44SJohn Forte break; 2432fcf3ce44SJohn Forte } 2433fcf3ce44SJohn Forte ql_chg_endian((uint8_t *)bp++, 4); 2434fcf3ce44SJohn Forte } 2435fcf3ce44SJohn Forte 2436fcf3ce44SJohn Forte GLOBAL_HW_UNLOCK(); 2437fcf3ce44SJohn Forte 2438fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2439fcf3ce44SJohn Forte EL(ha, "24xx_read_flash failed=%xh\n", rval); 2440fcf3ce44SJohn Forte break; 2441fcf3ce44SJohn Forte } 2442fcf3ce44SJohn Forte 2443fcf3ce44SJohn Forte if (risc_code_size == 0) { 2444fcf3ce44SJohn Forte bp = (uint32_t *)ha->request_ring_bp; 2445fcf3ce44SJohn Forte risc_address = bp[2]; 2446fcf3ce44SJohn Forte risc_code_size = bp[3]; 2447fcf3ce44SJohn Forte ha->risc_fw[seg_cnt].addr = risc_address; 2448fcf3ce44SJohn Forte } 2449fcf3ce44SJohn Forte 2450fcf3ce44SJohn Forte if (risc_code_size < xfer_size) { 24515dfd244aSDaniel Beauregard faddr -= xfer_size - risc_code_size; 2452fcf3ce44SJohn Forte xfer_size = risc_code_size; 2453fcf3ce44SJohn Forte } 2454fcf3ce44SJohn Forte 2455fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 2456fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET, xfer_size << 2, 2457fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 2458fcf3ce44SJohn Forte 2459fcf3ce44SJohn Forte rval = ql_wrt_risc_ram(ha, risc_address, 2460fcf3ce44SJohn Forte ha->request_dvma, xfer_size); 2461fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2462fcf3ce44SJohn Forte EL(ha, "ql_wrt_risc_ram failed=%xh\n", rval); 2463fcf3ce44SJohn Forte break; 2464fcf3ce44SJohn Forte } 2465fcf3ce44SJohn Forte 2466fcf3ce44SJohn Forte risc_address += xfer_size; 2467fcf3ce44SJohn Forte risc_code_size -= xfer_size; 2468fcf3ce44SJohn Forte } while (risc_code_size); 2469fcf3ce44SJohn Forte 2470fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2471fcf3ce44SJohn Forte break; 2472fcf3ce44SJohn Forte } 2473fcf3ce44SJohn Forte } 2474fcf3ce44SJohn Forte 2475fcf3ce44SJohn Forte /* Start firmware. */ 2476fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2477fcf3ce44SJohn Forte rval = ql_start_firmware(ha); 2478fcf3ce44SJohn Forte } 2479fcf3ce44SJohn Forte 2480fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2481fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2482fcf3ce44SJohn Forte } else { 2483fcf3ce44SJohn Forte /*EMPTY*/ 2484fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2485fcf3ce44SJohn Forte } 2486fcf3ce44SJohn Forte return (rval); 2487fcf3ce44SJohn Forte } 2488fcf3ce44SJohn Forte 2489fcf3ce44SJohn Forte /* 2490fcf3ce44SJohn Forte * ql_start_firmware 2491fcf3ce44SJohn Forte * Starts RISC code. 2492fcf3ce44SJohn Forte * 2493fcf3ce44SJohn Forte * Input: 2494fcf3ce44SJohn Forte * ha = adapter state pointer. 2495fcf3ce44SJohn Forte * 2496fcf3ce44SJohn Forte * Returns: 2497fcf3ce44SJohn Forte * ql local function return status code. 2498fcf3ce44SJohn Forte * 2499fcf3ce44SJohn Forte * Context: 2500fcf3ce44SJohn Forte * Kernel context. 2501fcf3ce44SJohn Forte */ 2502fcf3ce44SJohn Forte int 2503fcf3ce44SJohn Forte ql_start_firmware(ql_adapter_state_t *vha) 2504fcf3ce44SJohn Forte { 25055dfd244aSDaniel Beauregard int rval, rval2; 25065dfd244aSDaniel Beauregard uint32_t data; 2507fcf3ce44SJohn Forte ql_mbx_data_t mr; 2508fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 2509fcf3ce44SJohn Forte 2510fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2511fcf3ce44SJohn Forte 2512eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 2513eb82ff87SDaniel Beauregard /* Save firmware version. */ 2514eb82ff87SDaniel Beauregard rval = ql_get_fw_version(ha, &mr, MAILBOX_TOV); 2515eb82ff87SDaniel Beauregard ha->fw_major_version = mr.mb[1]; 2516eb82ff87SDaniel Beauregard ha->fw_minor_version = mr.mb[2]; 2517eb82ff87SDaniel Beauregard ha->fw_subminor_version = mr.mb[3]; 2518*f885d00fSDaniel Beauregard ha->fw_attributes = mr.mb[6]; 2519eb82ff87SDaniel Beauregard } else if ((rval = ql_verify_checksum(ha)) == QL_SUCCESS) { 2520eb82ff87SDaniel Beauregard /* Verify checksum of loaded RISC code. */ 2521fcf3ce44SJohn Forte /* Start firmware execution. */ 2522fcf3ce44SJohn Forte (void) ql_execute_fw(ha); 2523fcf3ce44SJohn Forte 2524fcf3ce44SJohn Forte /* Save firmware version. */ 2525eb82ff87SDaniel Beauregard (void) ql_get_fw_version(ha, &mr, MAILBOX_TOV); 2526fcf3ce44SJohn Forte ha->fw_major_version = mr.mb[1]; 2527fcf3ce44SJohn Forte ha->fw_minor_version = mr.mb[2]; 2528fcf3ce44SJohn Forte ha->fw_subminor_version = mr.mb[3]; 2529fcf3ce44SJohn Forte ha->fw_ext_memory_size = ((SHORT_TO_LONG(mr.mb[4], mr.mb[5]) - 2530fcf3ce44SJohn Forte 0x100000) + 1) * 4; 2531fcf3ce44SJohn Forte ha->fw_attributes = mr.mb[6]; 2532fcf3ce44SJohn Forte 25335dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_81XX)) { 25345dfd244aSDaniel Beauregard ha->phy_fw_major_version = LSB(mr.mb[8]); 25355dfd244aSDaniel Beauregard ha->phy_fw_minor_version = MSB(mr.mb[9]); 25365dfd244aSDaniel Beauregard ha->phy_fw_subminor_version = LSB(mr.mb[9]); 25375dfd244aSDaniel Beauregard ha->mpi_fw_major_version = LSB(mr.mb[10]); 25385dfd244aSDaniel Beauregard ha->mpi_fw_minor_version = MSB(mr.mb[11]); 25395dfd244aSDaniel Beauregard ha->mpi_fw_subminor_version = LSB(mr.mb[11]); 25405dfd244aSDaniel Beauregard ha->mpi_capability_list = SHORT_TO_LONG(mr.mb[13], 25415dfd244aSDaniel Beauregard mr.mb[12]); 25425dfd244aSDaniel Beauregard if ((rval2 = ql_flash_access(ha, FAC_GET_SECTOR_SIZE, 25435dfd244aSDaniel Beauregard 0, 0, &data)) == QL_SUCCESS) { 25445dfd244aSDaniel Beauregard ha->xioctl->fdesc.block_size = data << 2; 25455dfd244aSDaniel Beauregard QL_PRINT_10(CE_CONT, "(%d): fdesc.block_size=" 25465dfd244aSDaniel Beauregard "%xh\n", ha->instance, 25475dfd244aSDaniel Beauregard ha->xioctl->fdesc.block_size); 25485dfd244aSDaniel Beauregard } else { 25495dfd244aSDaniel Beauregard EL(ha, "flash_access status=%xh\n", rval2); 25505dfd244aSDaniel Beauregard } 25515dfd244aSDaniel Beauregard } 25525dfd244aSDaniel Beauregard 2553fcf3ce44SJohn Forte /* Set Serdes Transmit Parameters. */ 25545dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_2422) && ha->serdes_param[0] & BIT_0) { 2555fcf3ce44SJohn Forte mr.mb[1] = ha->serdes_param[0]; 2556fcf3ce44SJohn Forte mr.mb[2] = ha->serdes_param[1]; 2557fcf3ce44SJohn Forte mr.mb[3] = ha->serdes_param[2]; 2558fcf3ce44SJohn Forte mr.mb[4] = ha->serdes_param[3]; 2559fcf3ce44SJohn Forte (void) ql_serdes_param(ha, &mr); 2560fcf3ce44SJohn Forte } 2561fcf3ce44SJohn Forte } 2562*f885d00fSDaniel Beauregard /* ETS workaround */ 2563*f885d00fSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_81XX) && ql_enable_ets) { 2564*f885d00fSDaniel Beauregard if (ql_get_firmware_option(ha, &mr) == QL_SUCCESS) { 2565*f885d00fSDaniel Beauregard mr.mb[2] = (uint16_t) 2566*f885d00fSDaniel Beauregard (mr.mb[2] | FO2_FCOE_512_MAX_MEM_WR_BURST); 2567*f885d00fSDaniel Beauregard (void) ql_set_firmware_option(ha, &mr); 2568*f885d00fSDaniel Beauregard } 2569*f885d00fSDaniel Beauregard } 2570fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2571fcf3ce44SJohn Forte ha->task_daemon_flags &= ~FIRMWARE_LOADED; 2572fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2573fcf3ce44SJohn Forte } else { 2574fcf3ce44SJohn Forte ha->task_daemon_flags |= FIRMWARE_LOADED; 2575fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2576fcf3ce44SJohn Forte } 2577fcf3ce44SJohn Forte return (rval); 2578fcf3ce44SJohn Forte } 2579fcf3ce44SJohn Forte 2580fcf3ce44SJohn Forte /* 2581fcf3ce44SJohn Forte * ql_set_cache_line 2582fcf3ce44SJohn Forte * Sets PCI cache line parameter. 2583fcf3ce44SJohn Forte * 2584fcf3ce44SJohn Forte * Input: 2585fcf3ce44SJohn Forte * ha = adapter state pointer. 2586fcf3ce44SJohn Forte * 2587fcf3ce44SJohn Forte * Returns: 2588fcf3ce44SJohn Forte * ql local function return status code. 2589fcf3ce44SJohn Forte * 2590fcf3ce44SJohn Forte * Context: 2591fcf3ce44SJohn Forte * Kernel context. 2592fcf3ce44SJohn Forte */ 2593fcf3ce44SJohn Forte int 2594fcf3ce44SJohn Forte ql_set_cache_line(ql_adapter_state_t *ha) 2595fcf3ce44SJohn Forte { 2596fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2597fcf3ce44SJohn Forte 2598fcf3ce44SJohn Forte /* Set the cache line. */ 2599fcf3ce44SJohn Forte if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) { 2600fcf3ce44SJohn Forte /* Set cache line register. */ 2601fcf3ce44SJohn Forte ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1); 2602fcf3ce44SJohn Forte } 2603fcf3ce44SJohn Forte 2604fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2605fcf3ce44SJohn Forte 2606fcf3ce44SJohn Forte return (QL_SUCCESS); 2607fcf3ce44SJohn Forte } 2608fcf3ce44SJohn Forte 2609fcf3ce44SJohn Forte /* 2610fcf3ce44SJohn Forte * ql_init_rings 2611fcf3ce44SJohn Forte * Initializes firmware and ring pointers. 2612fcf3ce44SJohn Forte * 2613fcf3ce44SJohn Forte * Beginning of response ring has initialization control block 2614fcf3ce44SJohn Forte * already built by nvram config routine. 2615fcf3ce44SJohn Forte * 2616fcf3ce44SJohn Forte * Input: 2617fcf3ce44SJohn Forte * ha = adapter state pointer. 2618fcf3ce44SJohn Forte * ha->hba_buf = request and response rings 2619fcf3ce44SJohn Forte * ha->init_ctrl_blk = initialization control block 2620fcf3ce44SJohn Forte * 2621fcf3ce44SJohn Forte * Returns: 2622fcf3ce44SJohn Forte * ql local function return status code. 2623fcf3ce44SJohn Forte * 2624fcf3ce44SJohn Forte * Context: 2625fcf3ce44SJohn Forte * Kernel context. 2626fcf3ce44SJohn Forte */ 2627fcf3ce44SJohn Forte int 2628fcf3ce44SJohn Forte ql_init_rings(ql_adapter_state_t *vha2) 2629fcf3ce44SJohn Forte { 2630fcf3ce44SJohn Forte int rval, rval2; 2631fcf3ce44SJohn Forte uint16_t index; 2632fcf3ce44SJohn Forte ql_mbx_data_t mr; 2633fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha2->pha; 2634fcf3ce44SJohn Forte 2635fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2636fcf3ce44SJohn Forte 2637fcf3ce44SJohn Forte /* Clear outstanding commands array. */ 2638fcf3ce44SJohn Forte for (index = 0; index < MAX_OUTSTANDING_COMMANDS; index++) { 2639fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 2640fcf3ce44SJohn Forte } 2641fcf3ce44SJohn Forte ha->osc_index = 1; 2642fcf3ce44SJohn Forte 2643fcf3ce44SJohn Forte ha->pending_cmds.first = NULL; 2644fcf3ce44SJohn Forte ha->pending_cmds.last = NULL; 2645fcf3ce44SJohn Forte 2646fcf3ce44SJohn Forte /* Initialize firmware. */ 2647fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 2648fcf3ce44SJohn Forte ha->req_ring_index = 0; 2649fcf3ce44SJohn Forte ha->req_q_cnt = REQUEST_ENTRY_CNT - 1; 2650fcf3ce44SJohn Forte ha->response_ring_ptr = ha->response_ring_bp; 2651fcf3ce44SJohn Forte ha->rsp_ring_index = 0; 2652fcf3ce44SJohn Forte 2653fcf3ce44SJohn Forte if (ha->flags & VP_ENABLED) { 2654fcf3ce44SJohn Forte ql_adapter_state_t *vha; 2655fcf3ce44SJohn Forte uint16_t cnt; 2656fcf3ce44SJohn Forte uint32_t max_vports; 2657fcf3ce44SJohn Forte ql_init_24xx_cb_t *icb = &ha->init_ctrl_blk.cb24; 2658fcf3ce44SJohn Forte 2659fcf3ce44SJohn Forte max_vports = (CFG_IST(ha, CFG_CTRL_2422) ? 2660fcf3ce44SJohn Forte MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS); 2661fcf3ce44SJohn Forte bzero(icb->vp_count, 2662fcf3ce44SJohn Forte ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) - 2663fcf3ce44SJohn Forte (uintptr_t)icb->vp_count); 2664fcf3ce44SJohn Forte icb->vp_count[0] = (uint8_t)max_vports; 2665fcf3ce44SJohn Forte 2666fcf3ce44SJohn Forte /* Allow connection option 2. */ 2667fcf3ce44SJohn Forte icb->global_vp_option[0] = BIT_1; 2668fcf3ce44SJohn Forte 2669fcf3ce44SJohn Forte for (cnt = 0, vha = ha->vp_next; cnt < max_vports && 2670fcf3ce44SJohn Forte vha != NULL; vha = vha->vp_next, cnt++) { 2671fcf3ce44SJohn Forte 2672fcf3ce44SJohn Forte index = (uint8_t)(vha->vp_index - 1); 2673fcf3ce44SJohn Forte bcopy(vha->loginparams.node_ww_name.raw_wwn, 2674fcf3ce44SJohn Forte icb->vpc[index].node_name, 8); 2675fcf3ce44SJohn Forte bcopy(vha->loginparams.nport_ww_name.raw_wwn, 2676fcf3ce44SJohn Forte icb->vpc[index].port_name, 8); 2677fcf3ce44SJohn Forte 2678fcf3ce44SJohn Forte icb->vpc[index].options = VPO_TARGET_MODE_DISABLED | 2679fcf3ce44SJohn Forte VPO_INITIATOR_MODE_ENABLED; 2680fcf3ce44SJohn Forte if (vha->flags & VP_ENABLED) { 2681fcf3ce44SJohn Forte icb->vpc[index].options = (uint8_t) 2682fcf3ce44SJohn Forte (icb->vpc[index].options | VPO_ENABLED); 2683fcf3ce44SJohn Forte } 2684fcf3ce44SJohn Forte } 2685fcf3ce44SJohn Forte } 2686fcf3ce44SJohn Forte 2687eb82ff87SDaniel Beauregard for (index = 0; index < 2; index++) { 2688eb82ff87SDaniel Beauregard rval = ql_init_firmware(ha); 2689eb82ff87SDaniel Beauregard if (rval == QL_COMMAND_ERROR) { 2690eb82ff87SDaniel Beauregard EL(ha, "stopping firmware\n"); 2691eb82ff87SDaniel Beauregard (void) ql_stop_firmware(ha); 2692eb82ff87SDaniel Beauregard } else { 2693eb82ff87SDaniel Beauregard break; 2694eb82ff87SDaniel Beauregard } 2695eb82ff87SDaniel Beauregard } 2696fcf3ce44SJohn Forte 2697eb82ff87SDaniel Beauregard if (rval == QL_SUCCESS && (CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 2698fcf3ce44SJohn Forte /* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */ 2699fcf3ce44SJohn Forte rval = ql_get_firmware_option(ha, &mr); 2700fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2701fcf3ce44SJohn Forte mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9); 2702fcf3ce44SJohn Forte mr.mb[2] = 0; 2703fcf3ce44SJohn Forte mr.mb[3] = BIT_10; 2704fcf3ce44SJohn Forte rval = ql_set_firmware_option(ha, &mr); 2705fcf3ce44SJohn Forte } 2706fcf3ce44SJohn Forte } 2707fcf3ce44SJohn Forte 2708fcf3ce44SJohn Forte if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) { 270916dd44c2SDaniel Beauregard /* Firmware Fibre Channel Event Trace Buffer */ 271016dd44c2SDaniel Beauregard if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf, FWFCESIZE, 271116dd44c2SDaniel Beauregard LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) { 2712fcf3ce44SJohn Forte EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2); 2713fcf3ce44SJohn Forte } else { 2714fcf3ce44SJohn Forte if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf, 271516dd44c2SDaniel Beauregard FTO_FCE_TRACE_ENABLE)) != QL_SUCCESS) { 2716fcf3ce44SJohn Forte EL(ha, "fcetrace enable failed: %xh\n", rval2); 2717fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwfcetracebuf); 2718fcf3ce44SJohn Forte } 2719fcf3ce44SJohn Forte } 2720fcf3ce44SJohn Forte } 2721fcf3ce44SJohn Forte 2722fcf3ce44SJohn Forte if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) { 272316dd44c2SDaniel Beauregard /* Firmware Extended Trace Buffer */ 272416dd44c2SDaniel Beauregard if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf, FWEXTSIZE, 272516dd44c2SDaniel Beauregard LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) { 2726fcf3ce44SJohn Forte EL(ha, "exttrace buffer alloc failed: %xh\n", rval2); 2727fcf3ce44SJohn Forte } else { 2728fcf3ce44SJohn Forte if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf, 272916dd44c2SDaniel Beauregard FTO_EXT_TRACE_ENABLE)) != QL_SUCCESS) { 2730fcf3ce44SJohn Forte EL(ha, "exttrace enable failed: %xh\n", rval2); 2731fcf3ce44SJohn Forte ql_free_phys(ha, &ha->fwexttracebuf); 2732fcf3ce44SJohn Forte } 2733fcf3ce44SJohn Forte } 2734fcf3ce44SJohn Forte } 2735fcf3ce44SJohn Forte 2736fcf3ce44SJohn Forte if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) { 2737fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 2738fcf3ce44SJohn Forte clock_t timer; 2739fcf3ce44SJohn Forte 2740fcf3ce44SJohn Forte /* Wait for firmware login of menlo. */ 2741fcf3ce44SJohn Forte for (timer = 3000; timer; timer--) { 2742fcf3ce44SJohn Forte if (ha->flags & MENLO_LOGIN_OPERATIONAL) { 2743fcf3ce44SJohn Forte break; 2744fcf3ce44SJohn Forte } 2745fcf3ce44SJohn Forte 2746fcf3ce44SJohn Forte if (!(ha->flags & INTERRUPTS_ENABLED) || 2747fcf3ce44SJohn Forte ddi_in_panic()) { 2748eb82ff87SDaniel Beauregard if (INTERRUPT_PENDING(ha)) { 2749fcf3ce44SJohn Forte (void) ql_isr((caddr_t)ha); 2750fcf3ce44SJohn Forte INTR_LOCK(ha); 2751fcf3ce44SJohn Forte ha->intr_claimed = B_TRUE; 2752fcf3ce44SJohn Forte INTR_UNLOCK(ha); 2753fcf3ce44SJohn Forte } 2754fcf3ce44SJohn Forte } 2755fcf3ce44SJohn Forte 2756fcf3ce44SJohn Forte /* Delay for 1 tick (10 milliseconds). */ 2757fcf3ce44SJohn Forte ql_delay(ha, 10000); 2758fcf3ce44SJohn Forte } 2759fcf3ce44SJohn Forte 2760fcf3ce44SJohn Forte if (timer == 0) { 2761fcf3ce44SJohn Forte rval = QL_FUNCTION_TIMEOUT; 2762fcf3ce44SJohn Forte } else { 2763fcf3ce44SJohn Forte pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP); 2764fcf3ce44SJohn Forte if (pkt == NULL) { 2765fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 2766fcf3ce44SJohn Forte rval = QL_MEMORY_ALLOC_FAILED; 2767fcf3ce44SJohn Forte } else { 2768fcf3ce44SJohn Forte pkt->mvfy.entry_type = VERIFY_MENLO_TYPE; 2769fcf3ce44SJohn Forte pkt->mvfy.entry_count = 1; 2770fcf3ce44SJohn Forte pkt->mvfy.options_status = 2771fcf3ce44SJohn Forte LE_16(VMF_DO_NOT_UPDATE_FW); 2772fcf3ce44SJohn Forte 2773fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 2774fcf3ce44SJohn Forte sizeof (ql_mbx_iocb_t)); 2775fcf3ce44SJohn Forte LITTLE_ENDIAN_16(&pkt->mvfy.options_status); 2776fcf3ce44SJohn Forte LITTLE_ENDIAN_16(&pkt->mvfy.failure_code); 2777fcf3ce44SJohn Forte 2778fcf3ce44SJohn Forte if (rval != QL_SUCCESS || 2779fcf3ce44SJohn Forte (pkt->mvfy.entry_status & 0x3c) != 0 || 2780fcf3ce44SJohn Forte pkt->mvfy.options_status != CS_COMPLETE) { 2781fcf3ce44SJohn Forte EL(ha, "failed, status=%xh, es=%xh, " 2782fcf3ce44SJohn Forte "cs=%xh, fc=%xh\n", rval, 2783fcf3ce44SJohn Forte pkt->mvfy.entry_status & 0x3c, 2784fcf3ce44SJohn Forte pkt->mvfy.options_status, 2785fcf3ce44SJohn Forte pkt->mvfy.failure_code); 2786fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2787fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2788fcf3ce44SJohn Forte } 2789fcf3ce44SJohn Forte } 2790fcf3ce44SJohn Forte 2791fcf3ce44SJohn Forte kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 2792fcf3ce44SJohn Forte } 2793fcf3ce44SJohn Forte } 2794fcf3ce44SJohn Forte } 2795fcf3ce44SJohn Forte 2796fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2797fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2798fcf3ce44SJohn Forte ha->task_daemon_flags &= ~FIRMWARE_UP; 2799fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2800fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2801fcf3ce44SJohn Forte } else { 2802fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2803fcf3ce44SJohn Forte ha->task_daemon_flags |= FIRMWARE_UP; 2804fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2805fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2806fcf3ce44SJohn Forte } 2807fcf3ce44SJohn Forte return (rval); 2808fcf3ce44SJohn Forte } 2809fcf3ce44SJohn Forte 2810fcf3ce44SJohn Forte /* 2811fcf3ce44SJohn Forte * ql_fw_ready 2812fcf3ce44SJohn Forte * Waits for firmware ready. If firmware becomes ready 2813fcf3ce44SJohn Forte * device queues and RISC code are synchronized. 2814fcf3ce44SJohn Forte * 2815fcf3ce44SJohn Forte * Input: 2816fcf3ce44SJohn Forte * ha = adapter state pointer. 2817fcf3ce44SJohn Forte * secs = max wait time, in seconds (0-255). 2818fcf3ce44SJohn Forte * 2819fcf3ce44SJohn Forte * Returns: 2820fcf3ce44SJohn Forte * ql local function return status code. 2821fcf3ce44SJohn Forte * 2822fcf3ce44SJohn Forte * Context: 2823fcf3ce44SJohn Forte * Kernel context. 2824fcf3ce44SJohn Forte */ 2825fcf3ce44SJohn Forte int 2826fcf3ce44SJohn Forte ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs) 2827fcf3ce44SJohn Forte { 2828fcf3ce44SJohn Forte ql_mbx_data_t mr; 2829fcf3ce44SJohn Forte clock_t timer; 2830fcf3ce44SJohn Forte clock_t dly = 250000; 2831fcf3ce44SJohn Forte clock_t sec_delay = MICROSEC / dly; 2832fcf3ce44SJohn Forte clock_t wait = secs * sec_delay; 2833fcf3ce44SJohn Forte int rval = QL_FUNCTION_FAILED; 2834fcf3ce44SJohn Forte uint16_t state = 0xffff; 2835fcf3ce44SJohn Forte 2836fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2837fcf3ce44SJohn Forte 2838fcf3ce44SJohn Forte timer = ha->r_a_tov < secs ? secs : ha->r_a_tov; 2839fcf3ce44SJohn Forte timer = (timer + 2) * sec_delay; 2840fcf3ce44SJohn Forte 2841fcf3ce44SJohn Forte /* Wait for ISP to finish LIP */ 2842fcf3ce44SJohn Forte while (timer != 0 && wait != 0 && 2843fcf3ce44SJohn Forte !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) { 2844fcf3ce44SJohn Forte 2845fcf3ce44SJohn Forte rval = ql_get_firmware_state(ha, &mr); 2846fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 2847fcf3ce44SJohn Forte if (ha->task_daemon_flags & (ISP_ABORT_NEEDED | 2848fcf3ce44SJohn Forte LOOP_DOWN)) { 2849fcf3ce44SJohn Forte wait--; 2850fcf3ce44SJohn Forte } else if (mr.mb[1] != FSTATE_READY) { 2851fcf3ce44SJohn Forte if (mr.mb[1] != FSTATE_WAIT_LOGIN) { 2852fcf3ce44SJohn Forte wait--; 2853fcf3ce44SJohn Forte } 2854fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 2855fcf3ce44SJohn Forte } else { 2856fcf3ce44SJohn Forte /* Firmware is ready. Get 2 * R_A_TOV. */ 2857fcf3ce44SJohn Forte rval = ql_get_timeout_parameters(ha, 2858fcf3ce44SJohn Forte &ha->r_a_tov); 2859fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2860fcf3ce44SJohn Forte EL(ha, "failed, get_timeout_param" 2861fcf3ce44SJohn Forte "=%xh\n", rval); 2862fcf3ce44SJohn Forte } 2863fcf3ce44SJohn Forte 2864fcf3ce44SJohn Forte /* Configure loop. */ 2865fcf3ce44SJohn Forte rval = ql_configure_loop(ha); 2866fcf3ce44SJohn Forte (void) ql_marker(ha, 0, 0, MK_SYNC_ALL); 2867fcf3ce44SJohn Forte 2868fcf3ce44SJohn Forte if (ha->task_daemon_flags & 2869fcf3ce44SJohn Forte LOOP_RESYNC_NEEDED) { 2870fcf3ce44SJohn Forte wait--; 2871fcf3ce44SJohn Forte EL(ha, "loop trans; tdf=%xh\n", 2872fcf3ce44SJohn Forte ha->task_daemon_flags); 2873fcf3ce44SJohn Forte } else { 2874fcf3ce44SJohn Forte break; 2875fcf3ce44SJohn Forte } 2876fcf3ce44SJohn Forte } 2877fcf3ce44SJohn Forte } else { 2878fcf3ce44SJohn Forte wait--; 2879fcf3ce44SJohn Forte } 2880fcf3ce44SJohn Forte 2881fcf3ce44SJohn Forte if (state != mr.mb[1]) { 2882fcf3ce44SJohn Forte EL(ha, "mailbox_reg[1] = %xh\n", mr.mb[1]); 2883fcf3ce44SJohn Forte state = mr.mb[1]; 2884fcf3ce44SJohn Forte } 2885fcf3ce44SJohn Forte 2886fcf3ce44SJohn Forte /* Delay for a tick if waiting. */ 2887fcf3ce44SJohn Forte if (timer-- != 0 && wait != 0) { 2888fcf3ce44SJohn Forte if (timer % 4 == 0) { 2889fcf3ce44SJohn Forte delay(drv_usectohz(dly)); 2890fcf3ce44SJohn Forte } else { 2891fcf3ce44SJohn Forte drv_usecwait(dly); 2892fcf3ce44SJohn Forte } 2893fcf3ce44SJohn Forte } else { 2894fcf3ce44SJohn Forte rval = QL_FUNCTION_TIMEOUT; 2895fcf3ce44SJohn Forte } 2896fcf3ce44SJohn Forte } 2897fcf3ce44SJohn Forte 2898fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2899fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2900fcf3ce44SJohn Forte } else { 2901fcf3ce44SJohn Forte /*EMPTY*/ 2902fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2903fcf3ce44SJohn Forte } 2904fcf3ce44SJohn Forte return (rval); 2905fcf3ce44SJohn Forte } 2906fcf3ce44SJohn Forte 2907fcf3ce44SJohn Forte /* 2908fcf3ce44SJohn Forte * ql_configure_loop 2909fcf3ce44SJohn Forte * Setup configurations based on loop. 2910fcf3ce44SJohn Forte * 2911fcf3ce44SJohn Forte * Input: 2912fcf3ce44SJohn Forte * ha = adapter state pointer. 2913fcf3ce44SJohn Forte * 2914fcf3ce44SJohn Forte * Returns: 2915fcf3ce44SJohn Forte * ql local function return status code. 2916fcf3ce44SJohn Forte * 2917fcf3ce44SJohn Forte * Context: 2918fcf3ce44SJohn Forte * Kernel context. 2919fcf3ce44SJohn Forte */ 2920fcf3ce44SJohn Forte static int 2921fcf3ce44SJohn Forte ql_configure_loop(ql_adapter_state_t *ha) 2922fcf3ce44SJohn Forte { 2923fcf3ce44SJohn Forte int rval; 2924fcf3ce44SJohn Forte ql_adapter_state_t *vha; 2925fcf3ce44SJohn Forte 2926fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2927fcf3ce44SJohn Forte 2928fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 2929fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 2930fcf3ce44SJohn Forte if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) && 2931fcf3ce44SJohn Forte vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) { 2932fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2933fcf3ce44SJohn Forte continue; 2934fcf3ce44SJohn Forte } 2935fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED; 2936fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 2937fcf3ce44SJohn Forte 2938fcf3ce44SJohn Forte rval = ql_configure_hba(vha); 2939fcf3ce44SJohn Forte if (rval == QL_SUCCESS && !(ha->task_daemon_flags & 2940fcf3ce44SJohn Forte (LOOP_RESYNC_NEEDED | LOOP_DOWN))) { 2941fcf3ce44SJohn Forte rval = ql_configure_device_d_id(vha); 2942fcf3ce44SJohn Forte if (rval == QL_SUCCESS && !(ha->task_daemon_flags & 2943fcf3ce44SJohn Forte (LOOP_RESYNC_NEEDED | LOOP_DOWN))) { 2944fcf3ce44SJohn Forte (void) ql_configure_fabric(vha); 2945fcf3ce44SJohn Forte } 2946fcf3ce44SJohn Forte } 2947fcf3ce44SJohn Forte } 2948fcf3ce44SJohn Forte 2949fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 2950fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 2951fcf3ce44SJohn Forte } else { 2952fcf3ce44SJohn Forte /*EMPTY*/ 2953fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2954fcf3ce44SJohn Forte } 2955fcf3ce44SJohn Forte return (rval); 2956fcf3ce44SJohn Forte } 2957fcf3ce44SJohn Forte 29585dfd244aSDaniel Beauregard /* 29595dfd244aSDaniel Beauregard * ql_configure_n_port_info 29605dfd244aSDaniel Beauregard * Setup configurations based on N port 2 N port topology. 29615dfd244aSDaniel Beauregard * 29625dfd244aSDaniel Beauregard * Input: 29635dfd244aSDaniel Beauregard * ha = adapter state pointer. 29645dfd244aSDaniel Beauregard * 29655dfd244aSDaniel Beauregard * Returns: 29665dfd244aSDaniel Beauregard * ql local function return status code. 29675dfd244aSDaniel Beauregard * 29685dfd244aSDaniel Beauregard * Context: 29695dfd244aSDaniel Beauregard * Kernel context. 29705dfd244aSDaniel Beauregard */ 29715dfd244aSDaniel Beauregard static void 29725dfd244aSDaniel Beauregard ql_configure_n_port_info(ql_adapter_state_t *ha) 29735dfd244aSDaniel Beauregard { 29745dfd244aSDaniel Beauregard ql_tgt_t tmp_tq; 29755dfd244aSDaniel Beauregard ql_tgt_t *tq; 29765dfd244aSDaniel Beauregard uint8_t *cb_port_name; 29775dfd244aSDaniel Beauregard ql_link_t *link; 29785dfd244aSDaniel Beauregard int index, rval; 29795dfd244aSDaniel Beauregard 29805dfd244aSDaniel Beauregard tq = &tmp_tq; 29815dfd244aSDaniel Beauregard 29825dfd244aSDaniel Beauregard /* Free existing target queues. */ 29835dfd244aSDaniel Beauregard for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 29845dfd244aSDaniel Beauregard link = ha->dev[index].first; 29855dfd244aSDaniel Beauregard while (link != NULL) { 29865dfd244aSDaniel Beauregard tq = link->base_address; 29875dfd244aSDaniel Beauregard link = link->next; 29885dfd244aSDaniel Beauregard ql_remove_link(&ha->dev[index], &tq->device); 29895dfd244aSDaniel Beauregard ql_dev_free(ha, tq); 29905dfd244aSDaniel Beauregard } 29915dfd244aSDaniel Beauregard } 29925dfd244aSDaniel Beauregard 29935dfd244aSDaniel Beauregard /* 29945dfd244aSDaniel Beauregard * If the N_Port's WWPN is larger than our's then it has the 29955dfd244aSDaniel Beauregard * N_Port login initiative. It will have determined that and 29965dfd244aSDaniel Beauregard * logged in with the firmware. This results in a device 29975dfd244aSDaniel Beauregard * database entry. In this situation we will later send up a PLOGI 29985dfd244aSDaniel Beauregard * by proxy for the N_Port to get things going. 29995dfd244aSDaniel Beauregard * 30005dfd244aSDaniel Beauregard * If the N_Ports WWPN is smaller then the firmware has the 30015dfd244aSDaniel Beauregard * N_Port login initiative and does a FLOGI in order to obtain the 30025dfd244aSDaniel Beauregard * N_Ports WWNN and WWPN. These names are required later 30035dfd244aSDaniel Beauregard * during Leadvilles FLOGI. No PLOGI is done by the firmware in 30045dfd244aSDaniel Beauregard * anticipation of a PLOGI via the driver from the upper layers. 30055dfd244aSDaniel Beauregard * Upon reciept of said PLOGI the driver issues an ELS PLOGI 30065dfd244aSDaniel Beauregard * pass-through command and the firmware assumes the s_id 30075dfd244aSDaniel Beauregard * and the N_Port assumes the d_id and Bob's your uncle. 30085dfd244aSDaniel Beauregard */ 30095dfd244aSDaniel Beauregard 30105dfd244aSDaniel Beauregard /* 30115dfd244aSDaniel Beauregard * In N port 2 N port topology the FW provides a port database entry at 30125dfd244aSDaniel Beauregard * loop_id 0x7fe which allows us to acquire the Ports WWPN. 30135dfd244aSDaniel Beauregard */ 30145dfd244aSDaniel Beauregard tq->d_id.b.al_pa = 0; 30155dfd244aSDaniel Beauregard tq->d_id.b.area = 0; 30165dfd244aSDaniel Beauregard tq->d_id.b.domain = 0; 30175dfd244aSDaniel Beauregard tq->loop_id = 0x7fe; 30185dfd244aSDaniel Beauregard 30195dfd244aSDaniel Beauregard rval = ql_get_port_database(ha, tq, PDF_NONE); 30205dfd244aSDaniel Beauregard if (rval == QL_SUCCESS || rval == QL_NOT_LOGGED_IN) { 30215dfd244aSDaniel Beauregard ql_dev_id_list_t *list; 30225dfd244aSDaniel Beauregard uint32_t list_size; 30235dfd244aSDaniel Beauregard ql_mbx_data_t mr; 30245dfd244aSDaniel Beauregard port_id_t d_id = {0, 0, 0, 0}; 30255dfd244aSDaniel Beauregard uint16_t loop_id = 0; 30265dfd244aSDaniel Beauregard 3027eb82ff87SDaniel Beauregard cb_port_name = (uint8_t *)(CFG_IST(ha, CFG_CTRL_24258081) ? 30285dfd244aSDaniel Beauregard &ha->init_ctrl_blk.cb24.port_name[0] : 30295dfd244aSDaniel Beauregard &ha->init_ctrl_blk.cb.port_name[0]); 30305dfd244aSDaniel Beauregard 30315dfd244aSDaniel Beauregard if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0], 30325dfd244aSDaniel Beauregard (la_wwn_t *)cb_port_name) == 1)) { 30335dfd244aSDaniel Beauregard EL(ha, "target port has N_Port login initiative\n"); 30345dfd244aSDaniel Beauregard } else { 30355dfd244aSDaniel Beauregard EL(ha, "host port has N_Port login initiative\n"); 30365dfd244aSDaniel Beauregard } 30375dfd244aSDaniel Beauregard 30385dfd244aSDaniel Beauregard /* Capture the N Ports WWPN */ 30395dfd244aSDaniel Beauregard 30405dfd244aSDaniel Beauregard bcopy((void *)&tq->port_name[0], 30415dfd244aSDaniel Beauregard (void *)&ha->n_port->port_name[0], 8); 30425dfd244aSDaniel Beauregard bcopy((void *)&tq->node_name[0], 30435dfd244aSDaniel Beauregard (void *)&ha->n_port->node_name[0], 8); 30445dfd244aSDaniel Beauregard 30455dfd244aSDaniel Beauregard /* Resolve an n_port_handle */ 30465dfd244aSDaniel Beauregard ha->n_port->n_port_handle = 0x7fe; 30475dfd244aSDaniel Beauregard 30485dfd244aSDaniel Beauregard list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES; 30495dfd244aSDaniel Beauregard list = (ql_dev_id_list_t *)kmem_zalloc(list_size, KM_SLEEP); 30505dfd244aSDaniel Beauregard 30515dfd244aSDaniel Beauregard if (list != NULL && 30525dfd244aSDaniel Beauregard ql_get_id_list(ha, (caddr_t)list, list_size, &mr) == 30535dfd244aSDaniel Beauregard QL_SUCCESS) { 30545dfd244aSDaniel Beauregard if (mr.mb[1]) { 30555dfd244aSDaniel Beauregard EL(ha, "id list entries = %d\n", mr.mb[1]); 30565dfd244aSDaniel Beauregard for (index = 0; index < mr.mb[1]; index++) { 30575dfd244aSDaniel Beauregard ql_dev_list(ha, list, index, 30585dfd244aSDaniel Beauregard &d_id, &loop_id); 30595dfd244aSDaniel Beauregard ha->n_port->n_port_handle = loop_id; 30605dfd244aSDaniel Beauregard } 30615dfd244aSDaniel Beauregard } else { 30625dfd244aSDaniel Beauregard for (index = 0; index <= LAST_LOCAL_LOOP_ID; 30635dfd244aSDaniel Beauregard index++) { 30645dfd244aSDaniel Beauregard /* resuse tq */ 30655dfd244aSDaniel Beauregard tq->loop_id = (uint16_t)index; 30665dfd244aSDaniel Beauregard rval = ql_get_port_database(ha, tq, 30675dfd244aSDaniel Beauregard PDF_NONE); 30685dfd244aSDaniel Beauregard if (rval == QL_NOT_LOGGED_IN) { 30695dfd244aSDaniel Beauregard if (tq->master_state == 30705dfd244aSDaniel Beauregard PD_STATE_PLOGI_PENDING) { 30715dfd244aSDaniel Beauregard ha->n_port-> 30725dfd244aSDaniel Beauregard n_port_handle = 30735dfd244aSDaniel Beauregard tq->loop_id; 30745dfd244aSDaniel Beauregard break; 30755dfd244aSDaniel Beauregard } 30765dfd244aSDaniel Beauregard } else { 30775dfd244aSDaniel Beauregard ha->n_port->n_port_handle = 30785dfd244aSDaniel Beauregard tq->loop_id; 30795dfd244aSDaniel Beauregard break; 30805dfd244aSDaniel Beauregard } 30815dfd244aSDaniel Beauregard } 30825dfd244aSDaniel Beauregard } 30835dfd244aSDaniel Beauregard } else { 30845dfd244aSDaniel Beauregard cmn_err(CE_WARN, "!%s(%d) didn't get list for %xh", 30855dfd244aSDaniel Beauregard QL_NAME, ha->instance, d_id.b24); 30865dfd244aSDaniel Beauregard } 30875dfd244aSDaniel Beauregard if (list != NULL) { 30885dfd244aSDaniel Beauregard kmem_free(list, list_size); 30895dfd244aSDaniel Beauregard } 30905dfd244aSDaniel Beauregard } 30915dfd244aSDaniel Beauregard } 30925dfd244aSDaniel Beauregard 30935dfd244aSDaniel Beauregard 3094fcf3ce44SJohn Forte /* 3095fcf3ce44SJohn Forte * ql_configure_hba 3096fcf3ce44SJohn Forte * Setup adapter context. 3097fcf3ce44SJohn Forte * 3098fcf3ce44SJohn Forte * Input: 3099fcf3ce44SJohn Forte * ha = adapter state pointer. 3100fcf3ce44SJohn Forte * 3101fcf3ce44SJohn Forte * Returns: 3102fcf3ce44SJohn Forte * ql local function return status code. 3103fcf3ce44SJohn Forte * 3104fcf3ce44SJohn Forte * Context: 3105fcf3ce44SJohn Forte * Kernel context. 3106fcf3ce44SJohn Forte */ 3107fcf3ce44SJohn Forte static int 3108fcf3ce44SJohn Forte ql_configure_hba(ql_adapter_state_t *ha) 3109fcf3ce44SJohn Forte { 3110fcf3ce44SJohn Forte uint8_t *bp; 3111fcf3ce44SJohn Forte int rval; 3112fcf3ce44SJohn Forte uint32_t state; 3113fcf3ce44SJohn Forte ql_mbx_data_t mr; 3114fcf3ce44SJohn Forte 3115fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3116fcf3ce44SJohn Forte 3117fcf3ce44SJohn Forte /* Get host addresses. */ 3118fcf3ce44SJohn Forte rval = ql_get_adapter_id(ha, &mr); 3119fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 3120fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & 3121fcf3ce44SJohn Forte ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT)); 3122fcf3ce44SJohn Forte 3123fcf3ce44SJohn Forte /* Save Host d_id, alpa, loop ID. */ 3124fcf3ce44SJohn Forte ha->loop_id = mr.mb[1]; 3125fcf3ce44SJohn Forte ha->d_id.b.al_pa = LSB(mr.mb[2]); 3126fcf3ce44SJohn Forte ha->d_id.b.area = MSB(mr.mb[2]); 3127fcf3ce44SJohn Forte ha->d_id.b.domain = LSB(mr.mb[3]); 3128fcf3ce44SJohn Forte 3129fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3130fcf3ce44SJohn Forte ha->flags &= ~FDISC_ENABLED; 3131fcf3ce44SJohn Forte 3132fcf3ce44SJohn Forte /* Get loop topology. */ 3133fcf3ce44SJohn Forte switch (mr.mb[6]) { 3134fcf3ce44SJohn Forte case CNX_LOOP_NO_FABRIC: 3135fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_NL_PORT); 3136fcf3ce44SJohn Forte break; 3137fcf3ce44SJohn Forte case CNX_FLPORT_IN_LOOP: 3138fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_FL_PORT); 3139fcf3ce44SJohn Forte break; 3140fcf3ce44SJohn Forte case CNX_NPORT_2_NPORT_P2P: 3141fcf3ce44SJohn Forte case CNX_NPORT_2_NPORT_NO_TGT_RSP: 3142fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 3143fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_N_PORT); 31445dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_2425)) { 31455dfd244aSDaniel Beauregard ql_configure_n_port_info(ha); 31465dfd244aSDaniel Beauregard } 3147fcf3ce44SJohn Forte break; 3148fcf3ce44SJohn Forte case CNX_FLPORT_P2P: 3149fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 3150fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | QL_F_PORT); 3151fcf3ce44SJohn Forte 3152fcf3ce44SJohn Forte /* Get supported option. */ 3153eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081) && 31545dfd244aSDaniel Beauregard mr.mb[7] & GID_FP_NPIV_SUPPORT) { 3155fcf3ce44SJohn Forte ha->flags |= FDISC_ENABLED; 3156fcf3ce44SJohn Forte } 31577a2b99c0SDaniel Beauregard /* Get VLAN ID, mac address */ 3158eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081)) { 31597a2b99c0SDaniel Beauregard ha->fabric_params = mr.mb[7]; 31607a2b99c0SDaniel Beauregard ha->fcoe_vlan_id = (uint16_t)(mr.mb[9] & 0xfff); 31617a2b99c0SDaniel Beauregard ha->fcoe_fcf_idx = mr.mb[10]; 31627a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[0] = MSB(mr.mb[11]); 31637a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[1] = LSB(mr.mb[11]); 31647a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[2] = MSB(mr.mb[12]); 31657a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[3] = LSB(mr.mb[12]); 31667a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[4] = MSB(mr.mb[13]); 31677a2b99c0SDaniel Beauregard ha->fcoe_vnport_mac[5] = LSB(mr.mb[13]); 31687a2b99c0SDaniel Beauregard } 3169fcf3ce44SJohn Forte break; 3170fcf3ce44SJohn Forte default: 3171fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d,%d): UNKNOWN topology=%xh, " 3172fcf3ce44SJohn Forte "d_id=%xh\n", ha->instance, ha->vp_index, mr.mb[6], 3173fcf3ce44SJohn Forte ha->d_id.b24); 3174fcf3ce44SJohn Forte rval = QL_FUNCTION_FAILED; 3175fcf3ce44SJohn Forte break; 3176fcf3ce44SJohn Forte } 3177fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3178fcf3ce44SJohn Forte 31795dfd244aSDaniel Beauregard if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 | 3180eb82ff87SDaniel Beauregard CFG_CTRL_24258081))) { 3181fcf3ce44SJohn Forte mr.mb[1] = 0; 3182fcf3ce44SJohn Forte mr.mb[2] = 0; 3183fcf3ce44SJohn Forte rval = ql_data_rate(ha, &mr); 3184fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3185fcf3ce44SJohn Forte EL(ha, "data_rate status=%xh\n", rval); 3186fcf3ce44SJohn Forte state = FC_STATE_FULL_SPEED; 3187fcf3ce44SJohn Forte } else { 3188*f885d00fSDaniel Beauregard ha->iidma_rate = mr.mb[1]; 31895dfd244aSDaniel Beauregard if (mr.mb[1] == IIDMA_RATE_1GB) { 3190fcf3ce44SJohn Forte state = FC_STATE_1GBIT_SPEED; 31915dfd244aSDaniel Beauregard } else if (mr.mb[1] == IIDMA_RATE_2GB) { 3192fcf3ce44SJohn Forte state = FC_STATE_2GBIT_SPEED; 31935dfd244aSDaniel Beauregard } else if (mr.mb[1] == IIDMA_RATE_4GB) { 3194fcf3ce44SJohn Forte state = FC_STATE_4GBIT_SPEED; 31955dfd244aSDaniel Beauregard } else if (mr.mb[1] == IIDMA_RATE_8GB) { 3196fcf3ce44SJohn Forte state = FC_STATE_8GBIT_SPEED; 31975dfd244aSDaniel Beauregard } else if (mr.mb[1] == IIDMA_RATE_10GB) { 31985dfd244aSDaniel Beauregard state = FC_STATE_10GBIT_SPEED; 3199fcf3ce44SJohn Forte } else { 3200fcf3ce44SJohn Forte state = 0; 3201fcf3ce44SJohn Forte } 3202fcf3ce44SJohn Forte } 3203fcf3ce44SJohn Forte } else { 3204*f885d00fSDaniel Beauregard ha->iidma_rate = IIDMA_RATE_1GB; 3205fcf3ce44SJohn Forte state = FC_STATE_FULL_SPEED; 3206fcf3ce44SJohn Forte } 3207fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK(ha->state) | state; 320816dd44c2SDaniel Beauregard } else if (rval == MBS_COMMAND_ERROR) { 320916dd44c2SDaniel Beauregard EL(ha, "mbox cmd error, rval = %xh, mr.mb[1]=%hx\n", 321016dd44c2SDaniel Beauregard rval, mr.mb[1]); 3211fcf3ce44SJohn Forte } 3212fcf3ce44SJohn Forte 3213fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3214fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3215fcf3ce44SJohn Forte } else { 3216fcf3ce44SJohn Forte bp = ha->loginparams.nport_ww_name.raw_wwn; 3217fcf3ce44SJohn Forte EL(ha, "topology=%xh, d_id=%xh, " 3218fcf3ce44SJohn Forte "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n", 3219fcf3ce44SJohn Forte ha->topology, ha->d_id.b24, bp[0], bp[1], 3220fcf3ce44SJohn Forte bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]); 3221fcf3ce44SJohn Forte } 3222fcf3ce44SJohn Forte return (rval); 3223fcf3ce44SJohn Forte } 3224fcf3ce44SJohn Forte 3225fcf3ce44SJohn Forte /* 3226fcf3ce44SJohn Forte * ql_configure_device_d_id 3227fcf3ce44SJohn Forte * Updates device loop ID. 3228fcf3ce44SJohn Forte * Also adds to device queue any new devices found on private loop. 3229fcf3ce44SJohn Forte * 3230fcf3ce44SJohn Forte * Input: 3231fcf3ce44SJohn Forte * ha = adapter state pointer. 3232fcf3ce44SJohn Forte * 3233fcf3ce44SJohn Forte * Returns: 3234fcf3ce44SJohn Forte * ql local function return status code. 3235fcf3ce44SJohn Forte * 3236fcf3ce44SJohn Forte * Context: 3237fcf3ce44SJohn Forte * Kernel context. 3238fcf3ce44SJohn Forte */ 3239fcf3ce44SJohn Forte static int 3240fcf3ce44SJohn Forte ql_configure_device_d_id(ql_adapter_state_t *ha) 3241fcf3ce44SJohn Forte { 3242fcf3ce44SJohn Forte port_id_t d_id; 3243fcf3ce44SJohn Forte ql_link_t *link; 3244fcf3ce44SJohn Forte int rval; 3245fcf3ce44SJohn Forte int loop; 3246fcf3ce44SJohn Forte ql_tgt_t *tq; 3247fcf3ce44SJohn Forte ql_dev_id_list_t *list; 3248fcf3ce44SJohn Forte uint32_t list_size; 3249fcf3ce44SJohn Forte uint16_t index, loop_id; 3250fcf3ce44SJohn Forte ql_mbx_data_t mr; 3251fcf3ce44SJohn Forte uint8_t retries = MAX_DEVICE_LOST_RETRY; 3252fcf3ce44SJohn Forte 3253fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3254fcf3ce44SJohn Forte 3255fcf3ce44SJohn Forte list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES; 3256fcf3ce44SJohn Forte list = kmem_zalloc(list_size, KM_SLEEP); 3257fcf3ce44SJohn Forte if (list == NULL) { 3258fcf3ce44SJohn Forte rval = QL_MEMORY_ALLOC_FAILED; 3259fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3260fcf3ce44SJohn Forte return (rval); 3261fcf3ce44SJohn Forte } 3262fcf3ce44SJohn Forte 3263fcf3ce44SJohn Forte do { 3264fcf3ce44SJohn Forte /* 3265fcf3ce44SJohn Forte * Get data from RISC code d_id list to init each device queue. 3266fcf3ce44SJohn Forte */ 3267fcf3ce44SJohn Forte rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr); 3268fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3269fcf3ce44SJohn Forte kmem_free(list, list_size); 3270fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 3271fcf3ce44SJohn Forte return (rval); 3272fcf3ce44SJohn Forte } 3273fcf3ce44SJohn Forte 3274fcf3ce44SJohn Forte /* Acquire adapter state lock. */ 3275fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3276fcf3ce44SJohn Forte 3277fcf3ce44SJohn Forte /* Mark all queues as unusable. */ 3278fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 3279fcf3ce44SJohn Forte for (link = ha->dev[index].first; link != NULL; 3280fcf3ce44SJohn Forte link = link->next) { 3281fcf3ce44SJohn Forte tq = link->base_address; 3282fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 32835dfd244aSDaniel Beauregard if (!(tq->flags & TQF_PLOGI_PROGRS) && 32845dfd244aSDaniel Beauregard !(ha->topology & QL_N_PORT)) { 3285fcf3ce44SJohn Forte tq->loop_id = (uint16_t) 3286fcf3ce44SJohn Forte (tq->loop_id | PORT_LOST_ID); 3287fcf3ce44SJohn Forte } 3288fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3289fcf3ce44SJohn Forte } 3290fcf3ce44SJohn Forte } 3291fcf3ce44SJohn Forte 3292fcf3ce44SJohn Forte /* If device not in queues add new queue. */ 3293fcf3ce44SJohn Forte for (index = 0; index < mr.mb[1]; index++) { 3294fcf3ce44SJohn Forte ql_dev_list(ha, list, index, &d_id, &loop_id); 3295fcf3ce44SJohn Forte 3296fcf3ce44SJohn Forte if (VALID_DEVICE_ID(ha, loop_id)) { 3297fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, loop_id); 3298fcf3ce44SJohn Forte if (tq != NULL) { 3299fcf3ce44SJohn Forte tq->loop_id = loop_id; 3300fcf3ce44SJohn Forte 3301fcf3ce44SJohn Forte /* Test for fabric device. */ 3302fcf3ce44SJohn Forte if (d_id.b.domain != 3303fcf3ce44SJohn Forte ha->d_id.b.domain || 3304fcf3ce44SJohn Forte d_id.b.area != ha->d_id.b.area) { 3305fcf3ce44SJohn Forte tq->flags |= TQF_FABRIC_DEVICE; 3306fcf3ce44SJohn Forte } 3307fcf3ce44SJohn Forte 3308fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3309fcf3ce44SJohn Forte if (ql_get_port_database(ha, tq, 3310fcf3ce44SJohn Forte PDF_NONE) == QL_SUCCESS) { 3311fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3312fcf3ce44SJohn Forte tq->loop_id = (uint16_t) 3313fcf3ce44SJohn Forte (tq->loop_id & 3314fcf3ce44SJohn Forte ~PORT_LOST_ID); 3315fcf3ce44SJohn Forte } else { 3316fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3317fcf3ce44SJohn Forte } 3318fcf3ce44SJohn Forte } 3319fcf3ce44SJohn Forte } 3320fcf3ce44SJohn Forte } 3321fcf3ce44SJohn Forte 3322fcf3ce44SJohn Forte /* 24xx does not report switch devices in ID list. */ 3323eb82ff87SDaniel Beauregard if ((CFG_IST(ha, CFG_CTRL_24258081)) && 3324fcf3ce44SJohn Forte ha->topology & (QL_F_PORT | QL_FL_PORT)) { 3325fcf3ce44SJohn Forte d_id.b24 = 0xfffffe; 3326fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL); 3327fcf3ce44SJohn Forte if (tq != NULL) { 332816dd44c2SDaniel Beauregard tq->flags |= TQF_FABRIC_DEVICE; 3329fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3330fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3331fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3332fcf3ce44SJohn Forte } 3333fcf3ce44SJohn Forte d_id.b24 = 0xfffffc; 3334fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, SNS_24XX_HDL); 3335fcf3ce44SJohn Forte if (tq != NULL) { 333616dd44c2SDaniel Beauregard tq->flags |= TQF_FABRIC_DEVICE; 3337fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3338fcf3ce44SJohn Forte if (ha->vp_index != 0) { 3339fcf3ce44SJohn Forte (void) ql_login_fport(ha, tq, 3340fcf3ce44SJohn Forte SNS_24XX_HDL, LFF_NONE, NULL); 3341fcf3ce44SJohn Forte } 3342fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3343fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3344fcf3ce44SJohn Forte } 3345fcf3ce44SJohn Forte } 3346fcf3ce44SJohn Forte 3347fcf3ce44SJohn Forte /* If F_port exists, allocate queue for FL_Port. */ 3348fcf3ce44SJohn Forte index = ql_alpa_to_index[0xfe]; 3349fcf3ce44SJohn Forte d_id.b24 = 0; 3350fcf3ce44SJohn Forte if (ha->dev[index].first != NULL) { 3351fcf3ce44SJohn Forte tq = ql_dev_init(ha, d_id, (uint16_t) 3352eb82ff87SDaniel Beauregard (CFG_IST(ha, CFG_CTRL_24258081) ? 3353fcf3ce44SJohn Forte FL_PORT_24XX_HDL : FL_PORT_LOOP_ID)); 3354fcf3ce44SJohn Forte if (tq != NULL) { 335516dd44c2SDaniel Beauregard tq->flags |= TQF_FABRIC_DEVICE; 3356fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3357fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3358fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3359fcf3ce44SJohn Forte } 3360fcf3ce44SJohn Forte } 3361fcf3ce44SJohn Forte 3362fcf3ce44SJohn Forte /* Allocate queue for broadcast. */ 3363fcf3ce44SJohn Forte d_id.b24 = 0xffffff; 3364fcf3ce44SJohn Forte (void) ql_dev_init(ha, d_id, (uint16_t) 3365eb82ff87SDaniel Beauregard (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL : 3366fcf3ce44SJohn Forte IP_BROADCAST_LOOP_ID)); 3367fcf3ce44SJohn Forte 3368fcf3ce44SJohn Forte /* Check for any devices lost. */ 3369fcf3ce44SJohn Forte loop = FALSE; 3370fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 3371fcf3ce44SJohn Forte for (link = ha->dev[index].first; link != NULL; 3372fcf3ce44SJohn Forte link = link->next) { 3373fcf3ce44SJohn Forte tq = link->base_address; 3374fcf3ce44SJohn Forte 3375fcf3ce44SJohn Forte if ((tq->loop_id & PORT_LOST_ID) && 3376fcf3ce44SJohn Forte !(tq->flags & (TQF_INITIATOR_DEVICE | 3377fcf3ce44SJohn Forte TQF_FABRIC_DEVICE))) { 3378fcf3ce44SJohn Forte loop = TRUE; 3379fcf3ce44SJohn Forte } 3380fcf3ce44SJohn Forte } 3381fcf3ce44SJohn Forte } 3382fcf3ce44SJohn Forte 3383fcf3ce44SJohn Forte /* Release adapter state lock. */ 3384fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3385fcf3ce44SJohn Forte 3386fcf3ce44SJohn Forte /* Give devices time to recover. */ 3387fcf3ce44SJohn Forte if (loop == TRUE) { 3388fcf3ce44SJohn Forte drv_usecwait(1000000); 3389fcf3ce44SJohn Forte } 3390fcf3ce44SJohn Forte } while (retries-- && loop == TRUE && 3391fcf3ce44SJohn Forte !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED)); 3392fcf3ce44SJohn Forte 3393fcf3ce44SJohn Forte kmem_free(list, list_size); 3394fcf3ce44SJohn Forte 3395fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3396fcf3ce44SJohn Forte EL(ha, "failed=%xh\n", rval); 3397fcf3ce44SJohn Forte } else { 3398fcf3ce44SJohn Forte /*EMPTY*/ 3399fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3400fcf3ce44SJohn Forte } 3401fcf3ce44SJohn Forte 3402fcf3ce44SJohn Forte return (rval); 3403fcf3ce44SJohn Forte } 3404fcf3ce44SJohn Forte 3405fcf3ce44SJohn Forte /* 3406fcf3ce44SJohn Forte * ql_dev_list 3407fcf3ce44SJohn Forte * Gets device d_id and loop ID from firmware device list. 3408fcf3ce44SJohn Forte * 3409fcf3ce44SJohn Forte * Input: 3410fcf3ce44SJohn Forte * ha: adapter state pointer. 3411fcf3ce44SJohn Forte * list device list pointer. 3412fcf3ce44SJohn Forte * index: list index of device data. 3413fcf3ce44SJohn Forte * d_id: pointer for d_id data. 3414fcf3ce44SJohn Forte * id: pointer for loop ID. 3415fcf3ce44SJohn Forte * 3416fcf3ce44SJohn Forte * Context: 3417fcf3ce44SJohn Forte * Kernel context. 3418fcf3ce44SJohn Forte */ 3419fcf3ce44SJohn Forte void 3420fcf3ce44SJohn Forte ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list, 3421fcf3ce44SJohn Forte uint32_t index, port_id_t *d_id, uint16_t *id) 3422fcf3ce44SJohn Forte { 3423eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 3424fcf3ce44SJohn Forte struct ql_24_dev_id *list24 = (struct ql_24_dev_id *)list; 3425fcf3ce44SJohn Forte 3426fcf3ce44SJohn Forte d_id->b.al_pa = list24[index].al_pa; 3427fcf3ce44SJohn Forte d_id->b.area = list24[index].area; 3428fcf3ce44SJohn Forte d_id->b.domain = list24[index].domain; 3429fcf3ce44SJohn Forte *id = CHAR_TO_SHORT(list24[index].n_port_hdl_l, 3430fcf3ce44SJohn Forte list24[index].n_port_hdl_h); 3431fcf3ce44SJohn Forte 3432fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 3433fcf3ce44SJohn Forte struct ql_ex_dev_id *list23 = (struct ql_ex_dev_id *)list; 3434fcf3ce44SJohn Forte 3435fcf3ce44SJohn Forte d_id->b.al_pa = list23[index].al_pa; 3436fcf3ce44SJohn Forte d_id->b.area = list23[index].area; 3437fcf3ce44SJohn Forte d_id->b.domain = list23[index].domain; 3438fcf3ce44SJohn Forte *id = CHAR_TO_SHORT(list23[index].loop_id_l, 3439fcf3ce44SJohn Forte list23[index].loop_id_h); 3440fcf3ce44SJohn Forte 3441fcf3ce44SJohn Forte } else { 3442fcf3ce44SJohn Forte struct ql_dev_id *list22 = (struct ql_dev_id *)list; 3443fcf3ce44SJohn Forte 3444fcf3ce44SJohn Forte d_id->b.al_pa = list22[index].al_pa; 3445fcf3ce44SJohn Forte d_id->b.area = list22[index].area; 3446fcf3ce44SJohn Forte d_id->b.domain = list22[index].domain; 3447fcf3ce44SJohn Forte *id = (uint16_t)list22[index].loop_id; 3448fcf3ce44SJohn Forte } 3449fcf3ce44SJohn Forte } 3450fcf3ce44SJohn Forte 3451fcf3ce44SJohn Forte /* 3452fcf3ce44SJohn Forte * ql_configure_fabric 3453fcf3ce44SJohn Forte * Setup fabric context. 3454fcf3ce44SJohn Forte * 3455fcf3ce44SJohn Forte * Input: 3456fcf3ce44SJohn Forte * ha = adapter state pointer. 3457fcf3ce44SJohn Forte * 3458fcf3ce44SJohn Forte * Returns: 3459fcf3ce44SJohn Forte * ql local function return status code. 3460fcf3ce44SJohn Forte * 3461fcf3ce44SJohn Forte * Context: 3462fcf3ce44SJohn Forte * Kernel context. 3463fcf3ce44SJohn Forte */ 3464fcf3ce44SJohn Forte static int 3465fcf3ce44SJohn Forte ql_configure_fabric(ql_adapter_state_t *ha) 3466fcf3ce44SJohn Forte { 3467fcf3ce44SJohn Forte port_id_t d_id; 3468fcf3ce44SJohn Forte ql_tgt_t *tq; 3469fcf3ce44SJohn Forte int rval = QL_FUNCTION_FAILED; 3470fcf3ce44SJohn Forte 3471fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3472fcf3ce44SJohn Forte 3473fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & ~QL_SNS_CONNECTION); 3474fcf3ce44SJohn Forte 3475fcf3ce44SJohn Forte /* Test switch fabric controller present. */ 3476fcf3ce44SJohn Forte d_id.b24 = FS_FABRIC_F_PORT; 3477fcf3ce44SJohn Forte tq = ql_d_id_to_queue(ha, d_id); 3478fcf3ce44SJohn Forte if (tq != NULL) { 3479fcf3ce44SJohn Forte /* Get port/node names of F_Port. */ 3480fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3481fcf3ce44SJohn Forte 3482fcf3ce44SJohn Forte d_id.b24 = FS_NAME_SERVER; 3483fcf3ce44SJohn Forte tq = ql_d_id_to_queue(ha, d_id); 3484fcf3ce44SJohn Forte if (tq != NULL) { 3485fcf3ce44SJohn Forte (void) ql_get_port_database(ha, tq, PDF_NONE); 3486fcf3ce44SJohn Forte ha->topology = (uint8_t) 3487fcf3ce44SJohn Forte (ha->topology | QL_SNS_CONNECTION); 3488fcf3ce44SJohn Forte rval = QL_SUCCESS; 3489fcf3ce44SJohn Forte } 3490fcf3ce44SJohn Forte } 3491fcf3ce44SJohn Forte 3492fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 3493fcf3ce44SJohn Forte EL(ha, "failed=%xh\n", rval); 3494fcf3ce44SJohn Forte } else { 3495fcf3ce44SJohn Forte /*EMPTY*/ 3496fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3497fcf3ce44SJohn Forte } 3498fcf3ce44SJohn Forte return (rval); 3499fcf3ce44SJohn Forte } 3500fcf3ce44SJohn Forte 3501fcf3ce44SJohn Forte /* 3502fcf3ce44SJohn Forte * ql_reset_chip 3503fcf3ce44SJohn Forte * Reset ISP chip. 3504fcf3ce44SJohn Forte * 3505fcf3ce44SJohn Forte * Input: 3506fcf3ce44SJohn Forte * ha = adapter block pointer. 3507fcf3ce44SJohn Forte * All activity on chip must be already stopped. 3508fcf3ce44SJohn Forte * ADAPTER_STATE_LOCK must be released. 3509fcf3ce44SJohn Forte * 3510fcf3ce44SJohn Forte * Context: 3511fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3512fcf3ce44SJohn Forte */ 3513fcf3ce44SJohn Forte void 3514fcf3ce44SJohn Forte ql_reset_chip(ql_adapter_state_t *vha) 3515fcf3ce44SJohn Forte { 3516fcf3ce44SJohn Forte uint32_t cnt; 3517fcf3ce44SJohn Forte uint16_t cmd; 3518fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 3519fcf3ce44SJohn Forte 3520fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3521fcf3ce44SJohn Forte 3522fcf3ce44SJohn Forte /* 3523fcf3ce44SJohn Forte * accessing pci space while not powered can cause panic's 3524fcf3ce44SJohn Forte * on some platforms (i.e. Sunblade 1000's) 3525fcf3ce44SJohn Forte */ 3526fcf3ce44SJohn Forte if (ha->power_level == PM_LEVEL_D3) { 3527fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): Low Power exit\n", ha->instance); 3528fcf3ce44SJohn Forte return; 3529fcf3ce44SJohn Forte } 3530fcf3ce44SJohn Forte 3531fcf3ce44SJohn Forte /* Reset all outbound mailbox registers */ 3532fcf3ce44SJohn Forte for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) { 3533eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0); 3534eb82ff87SDaniel Beauregard } 3535eb82ff87SDaniel Beauregard 3536eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 3537*f885d00fSDaniel Beauregard ha->timeout_cnt = 0; 3538eb82ff87SDaniel Beauregard ql_8021_reset_chip(ha); 3539eb82ff87SDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): 8021 exit\n", ha->instance); 3540eb82ff87SDaniel Beauregard return; 3541fcf3ce44SJohn Forte } 3542fcf3ce44SJohn Forte 3543fcf3ce44SJohn Forte /* Disable ISP interrupts. */ 3544fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, 0); 3545fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3546fcf3ce44SJohn Forte ha->flags &= ~INTERRUPTS_ENABLED; 3547fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3548fcf3ce44SJohn Forte 35495dfd244aSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_242581)) { 3550fcf3ce44SJohn Forte RD32_IO_REG(ha, ictrl); 3551fcf3ce44SJohn Forte ql_reset_24xx_chip(ha); 3552fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): 24xx exit\n", ha->instance); 3553fcf3ce44SJohn Forte return; 3554fcf3ce44SJohn Forte } 3555fcf3ce44SJohn Forte 3556fcf3ce44SJohn Forte /* 3557fcf3ce44SJohn Forte * We are going to reset the chip in case of 2300. That might cause 3558fcf3ce44SJohn Forte * a PBM ERR if a DMA transaction is in progress. One way of 3559fcf3ce44SJohn Forte * avoiding it is to disable Bus Master operation before we start 3560fcf3ce44SJohn Forte * the reset activity. 3561fcf3ce44SJohn Forte */ 3562fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 3563fcf3ce44SJohn Forte cmd = (uint16_t)(cmd & ~PCI_COMM_ME); 3564fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 3565fcf3ce44SJohn Forte 3566fcf3ce44SJohn Forte /* Pause RISC. */ 3567fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 3568fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3569fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) { 3570fcf3ce44SJohn Forte break; 3571fcf3ce44SJohn Forte } 3572fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3573fcf3ce44SJohn Forte } 3574fcf3ce44SJohn Forte 3575fcf3ce44SJohn Forte /* 3576fcf3ce44SJohn Forte * A call to ql_isr() can still happen through 3577fcf3ce44SJohn Forte * ql_mailbox_command(). So Mark that we are/(will-be) 3578fcf3ce44SJohn Forte * running from rom code now. 3579fcf3ce44SJohn Forte */ 3580fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3581fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED); 3582fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3583fcf3ce44SJohn Forte 3584fcf3ce44SJohn Forte /* Select FPM registers. */ 3585fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x20); 3586fcf3ce44SJohn Forte 3587fcf3ce44SJohn Forte /* FPM Soft Reset. */ 3588fcf3ce44SJohn Forte WRT16_IO_REG(ha, fpm_diag_config, 0x100); 3589fcf3ce44SJohn Forte 3590fcf3ce44SJohn Forte /* Toggle FPM reset for 2300 */ 3591fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3592fcf3ce44SJohn Forte WRT16_IO_REG(ha, fpm_diag_config, 0); 3593fcf3ce44SJohn Forte } 3594fcf3ce44SJohn Forte 3595fcf3ce44SJohn Forte /* Select frame buffer registers. */ 3596fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x10); 3597fcf3ce44SJohn Forte 3598fcf3ce44SJohn Forte /* Reset frame buffer FIFOs. */ 3599fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3600fcf3ce44SJohn Forte WRT16_IO_REG(ha, fb_cmd, 0x00fc); 3601fcf3ce44SJohn Forte /* read back fb_cmd until zero or 3 seconds max */ 3602fcf3ce44SJohn Forte for (cnt = 0; cnt < 300000; cnt++) { 3603fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) { 3604fcf3ce44SJohn Forte break; 3605fcf3ce44SJohn Forte } 3606fcf3ce44SJohn Forte drv_usecwait(10); 3607fcf3ce44SJohn Forte } 3608fcf3ce44SJohn Forte } else { 3609fcf3ce44SJohn Forte WRT16_IO_REG(ha, fb_cmd, 0xa000); 3610fcf3ce44SJohn Forte } 3611fcf3ce44SJohn Forte 3612fcf3ce44SJohn Forte /* Select RISC module registers. */ 3613fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0); 3614fcf3ce44SJohn Forte 3615fcf3ce44SJohn Forte /* Reset RISC module. */ 3616fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RESET_RISC); 3617fcf3ce44SJohn Forte 3618fcf3ce44SJohn Forte /* Reset ISP semaphore. */ 3619fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 3620fcf3ce44SJohn Forte 3621fcf3ce44SJohn Forte /* Release RISC module. */ 3622fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 3623fcf3ce44SJohn Forte 3624fcf3ce44SJohn Forte /* Insure mailbox registers are free. */ 3625fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 3626fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT); 3627a2b3ff35SDaniel Beauregard 3628a2b3ff35SDaniel Beauregard /* clear the mailbox command pointer. */ 3629a2b3ff35SDaniel Beauregard ql_clear_mcp(ha); 3630a2b3ff35SDaniel Beauregard 3631fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & 3632fcf3ce44SJohn Forte ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT)); 3633fcf3ce44SJohn Forte 3634fcf3ce44SJohn Forte /* Bus Master is disabled so chip reset is safe. */ 3635fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 3636fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, ISP_RESET); 3637fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3638fcf3ce44SJohn Forte 3639fcf3ce44SJohn Forte /* Wait for reset to finish. */ 3640fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3641fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) { 3642fcf3ce44SJohn Forte break; 3643fcf3ce44SJohn Forte } 3644fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3645fcf3ce44SJohn Forte } 3646fcf3ce44SJohn Forte } 3647fcf3ce44SJohn Forte 3648fcf3ce44SJohn Forte /* Wait for RISC to recover from reset. */ 3649fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3650eb82ff87SDaniel Beauregard if (RD16_IO_REG(ha, mailbox_out[0]) != MBS_BUSY) { 3651fcf3ce44SJohn Forte break; 3652fcf3ce44SJohn Forte } 3653fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3654fcf3ce44SJohn Forte } 3655fcf3ce44SJohn Forte 3656fcf3ce44SJohn Forte /* restore bus master */ 3657fcf3ce44SJohn Forte cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM); 3658fcf3ce44SJohn Forte cmd = (uint16_t)(cmd | PCI_COMM_ME); 3659fcf3ce44SJohn Forte ql_pci_config_put16(ha, PCI_CONF_COMM, cmd); 3660fcf3ce44SJohn Forte 3661fcf3ce44SJohn Forte /* Disable RISC pause on FPM parity error. */ 3662fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE); 3663fcf3ce44SJohn Forte 3664fcf3ce44SJohn Forte /* Initialize probe registers */ 3665fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_SBUS_CARD)) { 3666fcf3ce44SJohn Forte /* Pause RISC. */ 3667fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC); 3668fcf3ce44SJohn Forte for (cnt = 0; cnt < 30000; cnt++) { 3669fcf3ce44SJohn Forte if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) { 3670fcf3ce44SJohn Forte break; 3671fcf3ce44SJohn Forte } else { 3672fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 3673fcf3ce44SJohn Forte } 3674fcf3ce44SJohn Forte } 3675fcf3ce44SJohn Forte 3676fcf3ce44SJohn Forte /* Select FPM registers. */ 3677fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0x30); 3678fcf3ce44SJohn Forte 3679fcf3ce44SJohn Forte /* Set probe register */ 3680eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[23], 0x204c); 3681fcf3ce44SJohn Forte 3682fcf3ce44SJohn Forte /* Select RISC module registers. */ 3683fcf3ce44SJohn Forte WRT16_IO_REG(ha, ctrl_status, 0); 3684fcf3ce44SJohn Forte 3685fcf3ce44SJohn Forte /* Release RISC module. */ 3686fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC); 3687fcf3ce44SJohn Forte } 3688fcf3ce44SJohn Forte 3689fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3690fcf3ce44SJohn Forte } 3691fcf3ce44SJohn Forte 3692fcf3ce44SJohn Forte /* 3693fcf3ce44SJohn Forte * ql_reset_24xx_chip 3694fcf3ce44SJohn Forte * Reset ISP24xx chip. 3695fcf3ce44SJohn Forte * 3696fcf3ce44SJohn Forte * Input: 3697fcf3ce44SJohn Forte * ha = adapter block pointer. 3698fcf3ce44SJohn Forte * All activity on chip must be already stopped. 3699fcf3ce44SJohn Forte * 3700fcf3ce44SJohn Forte * Context: 3701fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3702fcf3ce44SJohn Forte */ 3703fcf3ce44SJohn Forte void 3704fcf3ce44SJohn Forte ql_reset_24xx_chip(ql_adapter_state_t *ha) 3705fcf3ce44SJohn Forte { 3706fcf3ce44SJohn Forte uint32_t timer, stat; 3707fcf3ce44SJohn Forte 3708fcf3ce44SJohn Forte /* Shutdown DMA. */ 3709fcf3ce44SJohn Forte WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES); 3710fcf3ce44SJohn Forte 3711fcf3ce44SJohn Forte /* Wait for DMA to stop. */ 3712fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3713fcf3ce44SJohn Forte if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) { 3714fcf3ce44SJohn Forte break; 3715fcf3ce44SJohn Forte } 3716fcf3ce44SJohn Forte drv_usecwait(100); 3717fcf3ce44SJohn Forte } 3718fcf3ce44SJohn Forte 3719fcf3ce44SJohn Forte /* Stop the firmware. */ 3720fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3721eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE); 3722fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT); 3723fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3724eb82ff87SDaniel Beauregard stat = RD32_IO_REG(ha, risc2host); 3725fcf3ce44SJohn Forte if (stat & BIT_15) { 3726fcf3ce44SJohn Forte if ((stat & 0xff) < 0x12) { 3727fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3728fcf3ce44SJohn Forte break; 3729fcf3ce44SJohn Forte } 3730fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3731fcf3ce44SJohn Forte } 3732fcf3ce44SJohn Forte drv_usecwait(100); 3733fcf3ce44SJohn Forte } 3734fcf3ce44SJohn Forte 3735fcf3ce44SJohn Forte /* Reset the chip. */ 3736fcf3ce44SJohn Forte WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN | 3737fcf3ce44SJohn Forte MWB_4096_BYTES); 3738fcf3ce44SJohn Forte drv_usecwait(100); 3739fcf3ce44SJohn Forte 3740fcf3ce44SJohn Forte /* Wait for idle status from ROM firmware. */ 3741fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3742eb82ff87SDaniel Beauregard if (RD16_IO_REG(ha, mailbox_out[0]) == 0) { 3743fcf3ce44SJohn Forte break; 3744fcf3ce44SJohn Forte } 3745fcf3ce44SJohn Forte drv_usecwait(100); 3746fcf3ce44SJohn Forte } 3747fcf3ce44SJohn Forte 3748fcf3ce44SJohn Forte /* Wait for reset to finish. */ 3749fcf3ce44SJohn Forte for (timer = 0; timer < 30000; timer++) { 3750fcf3ce44SJohn Forte if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) { 3751fcf3ce44SJohn Forte break; 3752fcf3ce44SJohn Forte } 3753fcf3ce44SJohn Forte drv_usecwait(100); 3754fcf3ce44SJohn Forte } 3755fcf3ce44SJohn Forte 3756a2b3ff35SDaniel Beauregard /* clear the mailbox command pointer. */ 3757a2b3ff35SDaniel Beauregard ql_clear_mcp(ha); 3758a2b3ff35SDaniel Beauregard 3759fcf3ce44SJohn Forte /* Insure mailbox registers are free. */ 3760fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & 3761fcf3ce44SJohn Forte ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT)); 3762fcf3ce44SJohn Forte 37634f8b8adcSDaniel Beauregard if (ha->flags & MPI_RESET_NEEDED) { 37644f8b8adcSDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 3765eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[0], MBC_RESTART_MPI); 37664f8b8adcSDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT); 37674f8b8adcSDaniel Beauregard for (timer = 0; timer < 30000; timer++) { 3768eb82ff87SDaniel Beauregard stat = RD32_IO_REG(ha, risc2host); 37694f8b8adcSDaniel Beauregard if (stat & BIT_15) { 37704f8b8adcSDaniel Beauregard if ((stat & 0xff) < 0x12) { 37714f8b8adcSDaniel Beauregard WRT32_IO_REG(ha, hccr, 37724f8b8adcSDaniel Beauregard HC24_CLR_RISC_INT); 37734f8b8adcSDaniel Beauregard break; 37744f8b8adcSDaniel Beauregard } 37754f8b8adcSDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 37764f8b8adcSDaniel Beauregard } 37774f8b8adcSDaniel Beauregard drv_usecwait(100); 37784f8b8adcSDaniel Beauregard } 37794f8b8adcSDaniel Beauregard ADAPTER_STATE_LOCK(ha); 37804f8b8adcSDaniel Beauregard ha->flags &= ~MPI_RESET_NEEDED; 37814f8b8adcSDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 37824f8b8adcSDaniel Beauregard } 37834f8b8adcSDaniel Beauregard 3784fcf3ce44SJohn Forte /* 3785fcf3ce44SJohn Forte * Set flash write-protection. 3786fcf3ce44SJohn Forte */ 3787fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 3788fcf3ce44SJohn Forte ql_24xx_protect_flash(ha); 3789fcf3ce44SJohn Forte } 3790fcf3ce44SJohn Forte } 3791fcf3ce44SJohn Forte 3792a2b3ff35SDaniel Beauregard /* 3793a2b3ff35SDaniel Beauregard * ql_clear_mcp 3794a2b3ff35SDaniel Beauregard * Carefully clear the mailbox command pointer in the ha struct. 3795a2b3ff35SDaniel Beauregard * 3796a2b3ff35SDaniel Beauregard * Input: 3797a2b3ff35SDaniel Beauregard * ha = adapter block pointer. 3798a2b3ff35SDaniel Beauregard * 3799a2b3ff35SDaniel Beauregard * Context: 3800a2b3ff35SDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 3801a2b3ff35SDaniel Beauregard */ 3802a2b3ff35SDaniel Beauregard 3803a2b3ff35SDaniel Beauregard static void 3804a2b3ff35SDaniel Beauregard ql_clear_mcp(ql_adapter_state_t *ha) 3805a2b3ff35SDaniel Beauregard { 3806a2b3ff35SDaniel Beauregard uint32_t cnt; 3807a2b3ff35SDaniel Beauregard 3808a2b3ff35SDaniel Beauregard /* Don't null ha->mcp without the lock, but don't hang either. */ 3809a2b3ff35SDaniel Beauregard if (MBX_REGISTER_LOCK_OWNER(ha) == curthread) { 3810a2b3ff35SDaniel Beauregard ha->mcp = NULL; 3811a2b3ff35SDaniel Beauregard } else { 3812a2b3ff35SDaniel Beauregard for (cnt = 0; cnt < 300000; cnt++) { 3813a2b3ff35SDaniel Beauregard if (TRY_MBX_REGISTER_LOCK(ha) != 0) { 3814a2b3ff35SDaniel Beauregard ha->mcp = NULL; 3815a2b3ff35SDaniel Beauregard MBX_REGISTER_UNLOCK(ha); 3816a2b3ff35SDaniel Beauregard break; 3817a2b3ff35SDaniel Beauregard } else { 3818a2b3ff35SDaniel Beauregard drv_usecwait(10); 3819a2b3ff35SDaniel Beauregard } 3820a2b3ff35SDaniel Beauregard } 3821a2b3ff35SDaniel Beauregard } 3822a2b3ff35SDaniel Beauregard } 3823a2b3ff35SDaniel Beauregard 3824a2b3ff35SDaniel Beauregard 3825fcf3ce44SJohn Forte /* 3826fcf3ce44SJohn Forte * ql_abort_isp 3827fcf3ce44SJohn Forte * Resets ISP and aborts all outstanding commands. 3828fcf3ce44SJohn Forte * 3829fcf3ce44SJohn Forte * Input: 3830fcf3ce44SJohn Forte * ha = adapter state pointer. 3831fcf3ce44SJohn Forte * DEVICE_QUEUE_LOCK must be released. 3832fcf3ce44SJohn Forte * 3833fcf3ce44SJohn Forte * Returns: 3834fcf3ce44SJohn Forte * ql local function return status code. 3835fcf3ce44SJohn Forte * 3836fcf3ce44SJohn Forte * Context: 3837fcf3ce44SJohn Forte * Kernel context. 3838fcf3ce44SJohn Forte */ 3839fcf3ce44SJohn Forte int 3840fcf3ce44SJohn Forte ql_abort_isp(ql_adapter_state_t *vha) 3841fcf3ce44SJohn Forte { 3842fcf3ce44SJohn Forte ql_link_t *link, *link2; 3843fcf3ce44SJohn Forte ddi_devstate_t state; 3844fcf3ce44SJohn Forte uint16_t index; 3845fcf3ce44SJohn Forte ql_tgt_t *tq; 3846fcf3ce44SJohn Forte ql_lun_t *lq; 3847fcf3ce44SJohn Forte ql_srb_t *sp; 3848fcf3ce44SJohn Forte int rval = QL_SUCCESS; 3849fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 3850fcf3ce44SJohn Forte 3851fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 3852fcf3ce44SJohn Forte 3853fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3854fcf3ce44SJohn Forte ha->task_daemon_flags &= ~ISP_ABORT_NEEDED; 3855fcf3ce44SJohn Forte if (ha->task_daemon_flags & ABORT_ISP_ACTIVE || 3856fcf3ce44SJohn Forte (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) { 3857fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3858fcf3ce44SJohn Forte return (rval); 3859fcf3ce44SJohn Forte } 3860fcf3ce44SJohn Forte 3861fcf3ce44SJohn Forte ha->task_daemon_flags |= ABORT_ISP_ACTIVE; 3862fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(RESET_MARKER_NEEDED | FIRMWARE_UP | 3863fcf3ce44SJohn Forte FIRMWARE_LOADED); 3864fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3865fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_DOWN; 3866fcf3ce44SJohn Forte vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED | 3867fcf3ce44SJohn Forte LOOP_RESYNC_NEEDED); 3868fcf3ce44SJohn Forte } 3869fcf3ce44SJohn Forte 3870fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3871fcf3ce44SJohn Forte 3872fcf3ce44SJohn Forte if (ha->mailbox_flags & MBX_BUSY_FLG) { 3873fcf3ce44SJohn Forte /* Acquire mailbox register lock. */ 3874fcf3ce44SJohn Forte MBX_REGISTER_LOCK(ha); 3875fcf3ce44SJohn Forte 3876fcf3ce44SJohn Forte /* Wake up mailbox box routine. */ 3877fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT); 3878fcf3ce44SJohn Forte cv_broadcast(&ha->cv_mbx_intr); 3879fcf3ce44SJohn Forte 3880fcf3ce44SJohn Forte /* Release mailbox register lock. */ 3881fcf3ce44SJohn Forte MBX_REGISTER_UNLOCK(ha); 3882fcf3ce44SJohn Forte 3883fcf3ce44SJohn Forte /* Wait for mailbox. */ 3884fcf3ce44SJohn Forte for (index = 100; index && 3885fcf3ce44SJohn Forte ha->mailbox_flags & MBX_ABORT; index--) { 3886fcf3ce44SJohn Forte drv_usecwait(50000); 3887fcf3ce44SJohn Forte } 3888fcf3ce44SJohn Forte } 3889fcf3ce44SJohn Forte 3890fcf3ce44SJohn Forte /* Wait for commands to end gracefully if not in panic. */ 3891fcf3ce44SJohn Forte if (ha->flags & PARITY_ERROR) { 3892fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3893fcf3ce44SJohn Forte ha->flags &= ~PARITY_ERROR; 3894fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3895fcf3ce44SJohn Forte } else if (ddi_in_panic() == 0) { 3896fcf3ce44SJohn Forte ql_cmd_wait(ha); 3897fcf3ce44SJohn Forte } 3898fcf3ce44SJohn Forte 3899fcf3ce44SJohn Forte /* Shutdown IP. */ 3900fcf3ce44SJohn Forte if (ha->flags & IP_INITIALIZED) { 3901fcf3ce44SJohn Forte (void) ql_shutdown_ip(ha); 3902fcf3ce44SJohn Forte } 3903fcf3ce44SJohn Forte 3904fcf3ce44SJohn Forte /* Reset the chip. */ 3905fcf3ce44SJohn Forte ql_reset_chip(ha); 3906fcf3ce44SJohn Forte 3907a2b3ff35SDaniel Beauregard /* 3908a2b3ff35SDaniel Beauregard * Even though we have waited for outstanding commands to complete, 3909a2b3ff35SDaniel Beauregard * except for ones marked SRB_COMMAND_TIMEOUT, and reset the ISP, 3910a2b3ff35SDaniel Beauregard * there could still be an interrupt thread active. The interrupt 3911a2b3ff35SDaniel Beauregard * lock will prevent us from getting an sp from the outstanding 3912a2b3ff35SDaniel Beauregard * cmds array that the ISR may be using. 3913a2b3ff35SDaniel Beauregard */ 3914a2b3ff35SDaniel Beauregard 3915fcf3ce44SJohn Forte /* Place all commands in outstanding cmd list on device queue. */ 3916fcf3ce44SJohn Forte for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { 3917fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 3918a2b3ff35SDaniel Beauregard INTR_LOCK(ha); 3919fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) != NULL) { 3920fcf3ce44SJohn Forte sp = link->base_address; 3921fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 3922fcf3ce44SJohn Forte 3923fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 3924fcf3ce44SJohn Forte index = 0; 3925fcf3ce44SJohn Forte } else { 3926fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 3927fcf3ce44SJohn Forte if ((sp = ha->outstanding_cmds[index]) == NULL) { 3928a2b3ff35SDaniel Beauregard INTR_UNLOCK(ha); 3929fcf3ce44SJohn Forte continue; 3930fcf3ce44SJohn Forte } 3931fcf3ce44SJohn Forte } 3932fcf3ce44SJohn Forte 3933a2b3ff35SDaniel Beauregard /* 3934a2b3ff35SDaniel Beauregard * It's not obvious but the index for commands pulled from 3935a2b3ff35SDaniel Beauregard * pending will be zero and that entry in the outstanding array 3936a2b3ff35SDaniel Beauregard * is not used so nulling it is "no harm, no foul". 3937a2b3ff35SDaniel Beauregard */ 3938a2b3ff35SDaniel Beauregard 3939a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 3940a2b3ff35SDaniel Beauregard sp->handle = 0; 3941a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 3942a2b3ff35SDaniel Beauregard 3943a2b3ff35SDaniel Beauregard INTR_UNLOCK(ha); 3944a2b3ff35SDaniel Beauregard 3945fcf3ce44SJohn Forte /* If command timeout. */ 3946fcf3ce44SJohn Forte if (sp->flags & SRB_COMMAND_TIMEOUT) { 3947fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_TIMEOUT; 3948fcf3ce44SJohn Forte sp->flags &= ~SRB_RETRY; 3949fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 3950fcf3ce44SJohn Forte 3951fcf3ce44SJohn Forte /* Call done routine to handle completion. */ 3952fcf3ce44SJohn Forte ql_done(&sp->cmd); 3953fcf3ce44SJohn Forte continue; 3954fcf3ce44SJohn Forte } 3955fcf3ce44SJohn Forte 3956fcf3ce44SJohn Forte /* Acquire target queue lock. */ 3957fcf3ce44SJohn Forte lq = sp->lun_queue; 3958fcf3ce44SJohn Forte tq = lq->target_queue; 3959fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3960fcf3ce44SJohn Forte 3961fcf3ce44SJohn Forte /* Reset watchdog time. */ 3962fcf3ce44SJohn Forte sp->wdg_q_time = sp->init_wdg_q_time; 3963fcf3ce44SJohn Forte 3964fcf3ce44SJohn Forte /* Place request back on top of device queue. */ 3965fcf3ce44SJohn Forte sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | 3966fcf3ce44SJohn Forte SRB_RETRY); 3967fcf3ce44SJohn Forte 3968fcf3ce44SJohn Forte ql_add_link_t(&lq->cmd, &sp->cmd); 3969fcf3ce44SJohn Forte sp->flags |= SRB_IN_DEVICE_QUEUE; 3970fcf3ce44SJohn Forte 3971fcf3ce44SJohn Forte /* Release target queue lock. */ 3972fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3973fcf3ce44SJohn Forte } 3974fcf3ce44SJohn Forte 3975fcf3ce44SJohn Forte /* 3976fcf3ce44SJohn Forte * Clear per LUN active count, because there should not be 3977fcf3ce44SJohn Forte * any IO outstanding at this time. 3978fcf3ce44SJohn Forte */ 3979fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3980fcf3ce44SJohn Forte for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 3981fcf3ce44SJohn Forte link = vha->dev[index].first; 3982fcf3ce44SJohn Forte while (link != NULL) { 3983fcf3ce44SJohn Forte tq = link->base_address; 3984fcf3ce44SJohn Forte link = link->next; 3985fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3986fcf3ce44SJohn Forte tq->outcnt = 0; 3987fcf3ce44SJohn Forte tq->flags &= ~TQF_QUEUE_SUSPENDED; 3988fcf3ce44SJohn Forte for (link2 = tq->lun_queues.first; 3989fcf3ce44SJohn Forte link2 != NULL; link2 = link2->next) { 3990fcf3ce44SJohn Forte lq = link2->base_address; 3991fcf3ce44SJohn Forte lq->lun_outcnt = 0; 3992fcf3ce44SJohn Forte lq->flags &= ~LQF_UNTAGGED_PENDING; 3993fcf3ce44SJohn Forte } 3994fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3995fcf3ce44SJohn Forte } 3996fcf3ce44SJohn Forte } 3997fcf3ce44SJohn Forte } 3998fcf3ce44SJohn Forte 3999eb82ff87SDaniel Beauregard if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) { 4000eb82ff87SDaniel Beauregard if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) { 4001eb82ff87SDaniel Beauregard rval = ql_load_isp_firmware(ha); 4002eb82ff87SDaniel Beauregard } 4003fcf3ce44SJohn Forte } 4004fcf3ce44SJohn Forte 4005fcf3ce44SJohn Forte if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) == 4006fcf3ce44SJohn Forte QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS && 4007fcf3ce44SJohn Forte (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) { 4008fcf3ce44SJohn Forte 4009fcf3ce44SJohn Forte /* If reset abort needed that may have been set. */ 4010fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 4011fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | 4012fcf3ce44SJohn Forte ABORT_ISP_ACTIVE); 4013fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 4014fcf3ce44SJohn Forte 4015fcf3ce44SJohn Forte /* Enable ISP interrupts. */ 4016eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 4017eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ha); 4018eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 4019eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, ictrl, ISP_EN_RISC); 4020eb82ff87SDaniel Beauregard } else { 4021eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 4022eb82ff87SDaniel Beauregard } 4023fcf3ce44SJohn Forte 4024fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 4025fcf3ce44SJohn Forte ha->flags |= INTERRUPTS_ENABLED; 4026fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 4027fcf3ce44SJohn Forte 4028fcf3ce44SJohn Forte /* Set loop online, if it really is. */ 4029fcf3ce44SJohn Forte ql_loop_online(ha); 4030fcf3ce44SJohn Forte 4031fcf3ce44SJohn Forte state = ddi_get_devstate(ha->dip); 4032fcf3ce44SJohn Forte if (state != DDI_DEVSTATE_UP) { 4033fcf3ce44SJohn Forte /*EMPTY*/ 4034fcf3ce44SJohn Forte ddi_dev_report_fault(ha->dip, DDI_SERVICE_RESTORED, 4035fcf3ce44SJohn Forte DDI_DEVICE_FAULT, "Device reset succeeded"); 4036fcf3ce44SJohn Forte } 4037fcf3ce44SJohn Forte } else { 4038fcf3ce44SJohn Forte /* Enable ISP interrupts. */ 4039eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 4040eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ha); 4041eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 4042eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, ictrl, ISP_EN_RISC); 4043eb82ff87SDaniel Beauregard } else { 4044eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC); 4045eb82ff87SDaniel Beauregard } 4046fcf3ce44SJohn Forte 4047fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 4048fcf3ce44SJohn Forte ha->flags |= INTERRUPTS_ENABLED; 4049fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 4050fcf3ce44SJohn Forte 4051fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 4052fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE); 4053fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 4054fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 4055fcf3ce44SJohn Forte 4056fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE); 4057fcf3ce44SJohn Forte } 4058fcf3ce44SJohn Forte 4059fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 4060fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 4061fcf3ce44SJohn Forte } else { 4062fcf3ce44SJohn Forte /*EMPTY*/ 4063fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): done\n", ha->instance); 4064fcf3ce44SJohn Forte } 4065fcf3ce44SJohn Forte return (rval); 4066fcf3ce44SJohn Forte } 4067fcf3ce44SJohn Forte 4068fcf3ce44SJohn Forte /* 4069fcf3ce44SJohn Forte * ql_vport_control 4070fcf3ce44SJohn Forte * Issue Virtual Port Control command. 4071fcf3ce44SJohn Forte * 4072fcf3ce44SJohn Forte * Input: 4073fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 4074fcf3ce44SJohn Forte * cmd = control command. 4075fcf3ce44SJohn Forte * 4076fcf3ce44SJohn Forte * Returns: 4077fcf3ce44SJohn Forte * ql local function return status code. 4078fcf3ce44SJohn Forte * 4079fcf3ce44SJohn Forte * Context: 4080fcf3ce44SJohn Forte * Kernel context. 4081fcf3ce44SJohn Forte */ 4082fcf3ce44SJohn Forte int 4083fcf3ce44SJohn Forte ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd) 4084fcf3ce44SJohn Forte { 4085fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 4086fcf3ce44SJohn Forte uint8_t bit; 4087fcf3ce44SJohn Forte int rval; 4088fcf3ce44SJohn Forte uint32_t pkt_size; 4089fcf3ce44SJohn Forte 4090fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 4091fcf3ce44SJohn Forte 4092fcf3ce44SJohn Forte if (ha->vp_index != 0) { 4093fcf3ce44SJohn Forte pkt_size = sizeof (ql_mbx_iocb_t); 4094fcf3ce44SJohn Forte pkt = kmem_zalloc(pkt_size, KM_SLEEP); 4095fcf3ce44SJohn Forte if (pkt == NULL) { 4096fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 4097fcf3ce44SJohn Forte return (QL_MEMORY_ALLOC_FAILED); 4098fcf3ce44SJohn Forte } 4099fcf3ce44SJohn Forte 4100fcf3ce44SJohn Forte pkt->vpc.entry_type = VP_CONTROL_TYPE; 4101fcf3ce44SJohn Forte pkt->vpc.entry_count = 1; 4102fcf3ce44SJohn Forte pkt->vpc.command = cmd; 4103fcf3ce44SJohn Forte pkt->vpc.vp_count = 1; 4104fcf3ce44SJohn Forte bit = (uint8_t)(ha->vp_index - 1); 4105fcf3ce44SJohn Forte pkt->vpc.vp_index[bit / 8] = (uint8_t) 4106fcf3ce44SJohn Forte (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8); 4107fcf3ce44SJohn Forte 4108fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); 4109fcf3ce44SJohn Forte if (rval == QL_SUCCESS && pkt->vpc.status != 0) { 4110fcf3ce44SJohn Forte rval = QL_COMMAND_ERROR; 4111fcf3ce44SJohn Forte } 4112fcf3ce44SJohn Forte 4113fcf3ce44SJohn Forte kmem_free(pkt, pkt_size); 4114fcf3ce44SJohn Forte } else { 4115fcf3ce44SJohn Forte rval = QL_SUCCESS; 4116fcf3ce44SJohn Forte } 4117fcf3ce44SJohn Forte 4118fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 4119fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 4120fcf3ce44SJohn Forte } else { 4121fcf3ce44SJohn Forte /*EMPTY*/ 4122fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, 4123fcf3ce44SJohn Forte ha->vp_index); 4124fcf3ce44SJohn Forte } 4125fcf3ce44SJohn Forte return (rval); 4126fcf3ce44SJohn Forte } 4127fcf3ce44SJohn Forte 4128fcf3ce44SJohn Forte /* 4129fcf3ce44SJohn Forte * ql_vport_modify 4130fcf3ce44SJohn Forte * Issue of Modify Virtual Port command. 4131fcf3ce44SJohn Forte * 4132fcf3ce44SJohn Forte * Input: 4133fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 4134fcf3ce44SJohn Forte * cmd = command. 4135fcf3ce44SJohn Forte * opt = option. 4136fcf3ce44SJohn Forte * 4137fcf3ce44SJohn Forte * Context: 4138fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 4139fcf3ce44SJohn Forte */ 4140fcf3ce44SJohn Forte int 4141fcf3ce44SJohn Forte ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt) 4142fcf3ce44SJohn Forte { 4143fcf3ce44SJohn Forte ql_mbx_iocb_t *pkt; 4144fcf3ce44SJohn Forte int rval; 4145fcf3ce44SJohn Forte uint32_t pkt_size; 4146fcf3ce44SJohn Forte 4147fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 4148fcf3ce44SJohn Forte 4149fcf3ce44SJohn Forte pkt_size = sizeof (ql_mbx_iocb_t); 4150fcf3ce44SJohn Forte pkt = kmem_zalloc(pkt_size, KM_SLEEP); 4151fcf3ce44SJohn Forte if (pkt == NULL) { 4152fcf3ce44SJohn Forte EL(ha, "failed, kmem_zalloc\n"); 4153fcf3ce44SJohn Forte return (QL_MEMORY_ALLOC_FAILED); 4154fcf3ce44SJohn Forte } 4155fcf3ce44SJohn Forte 4156fcf3ce44SJohn Forte pkt->vpm.entry_type = VP_MODIFY_TYPE; 4157fcf3ce44SJohn Forte pkt->vpm.entry_count = 1; 4158fcf3ce44SJohn Forte pkt->vpm.command = cmd; 4159fcf3ce44SJohn Forte pkt->vpm.vp_count = 1; 4160fcf3ce44SJohn Forte pkt->vpm.first_vp_index = ha->vp_index; 4161fcf3ce44SJohn Forte pkt->vpm.first_options = opt; 4162fcf3ce44SJohn Forte bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name, 4163fcf3ce44SJohn Forte 8); 4164fcf3ce44SJohn Forte bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name, 4165fcf3ce44SJohn Forte 8); 4166fcf3ce44SJohn Forte 4167fcf3ce44SJohn Forte rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); 4168fcf3ce44SJohn Forte if (rval == QL_SUCCESS && pkt->vpm.status != 0) { 4169fcf3ce44SJohn Forte EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval, 4170fcf3ce44SJohn Forte pkt->vpm.status); 4171fcf3ce44SJohn Forte rval = QL_COMMAND_ERROR; 4172fcf3ce44SJohn Forte } 4173fcf3ce44SJohn Forte 4174fcf3ce44SJohn Forte kmem_free(pkt, pkt_size); 4175fcf3ce44SJohn Forte 4176fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 4177fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 4178fcf3ce44SJohn Forte } else { 4179fcf3ce44SJohn Forte /*EMPTY*/ 4180fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, 4181fcf3ce44SJohn Forte ha->vp_index); 4182fcf3ce44SJohn Forte } 4183fcf3ce44SJohn Forte return (rval); 4184fcf3ce44SJohn Forte } 4185fcf3ce44SJohn Forte 4186fcf3ce44SJohn Forte /* 4187fcf3ce44SJohn Forte * ql_vport_enable 4188fcf3ce44SJohn Forte * Enable virtual port. 4189fcf3ce44SJohn Forte * 4190fcf3ce44SJohn Forte * Input: 4191fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 4192fcf3ce44SJohn Forte * 4193fcf3ce44SJohn Forte * Context: 4194fcf3ce44SJohn Forte * Kernel context. 4195fcf3ce44SJohn Forte */ 4196fcf3ce44SJohn Forte int 4197fcf3ce44SJohn Forte ql_vport_enable(ql_adapter_state_t *ha) 4198fcf3ce44SJohn Forte { 4199fcf3ce44SJohn Forte int timer; 4200fcf3ce44SJohn Forte 4201fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 4202fcf3ce44SJohn Forte 4203fcf3ce44SJohn Forte ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE; 4204fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 4205fcf3ce44SJohn Forte ha->task_daemon_flags |= LOOP_DOWN; 4206fcf3ce44SJohn Forte ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE); 4207fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 4208fcf3ce44SJohn Forte 4209fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 4210fcf3ce44SJohn Forte ha->flags |= VP_ENABLED; 4211fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 4212fcf3ce44SJohn Forte 4213fcf3ce44SJohn Forte if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED | 4214fcf3ce44SJohn Forte VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) { 4215fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): failed to enable virtual port=%d\n", 4216fcf3ce44SJohn Forte ha->instance, ha->vp_index); 4217fcf3ce44SJohn Forte return (QL_FUNCTION_FAILED); 4218fcf3ce44SJohn Forte } 4219fcf3ce44SJohn Forte if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) { 4220fcf3ce44SJohn Forte /* Wait for loop to come up. */ 4221fcf3ce44SJohn Forte for (timer = 0; timer < 3000 && 4222fcf3ce44SJohn Forte !(ha->task_daemon_flags & STATE_ONLINE); 4223fcf3ce44SJohn Forte timer++) { 4224fcf3ce44SJohn Forte delay(1); 4225fcf3ce44SJohn Forte } 4226fcf3ce44SJohn Forte } 4227fcf3ce44SJohn Forte 4228fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 4229fcf3ce44SJohn Forte 4230fcf3ce44SJohn Forte return (QL_SUCCESS); 4231fcf3ce44SJohn Forte } 4232fcf3ce44SJohn Forte 4233fcf3ce44SJohn Forte /* 4234fcf3ce44SJohn Forte * ql_vport_create 4235fcf3ce44SJohn Forte * Create virtual port context. 4236fcf3ce44SJohn Forte * 4237fcf3ce44SJohn Forte * Input: 4238fcf3ce44SJohn Forte * ha: parent adapter state pointer. 4239fcf3ce44SJohn Forte * index: virtual port index number. 4240fcf3ce44SJohn Forte * 4241fcf3ce44SJohn Forte * Context: 4242fcf3ce44SJohn Forte * Kernel context. 4243fcf3ce44SJohn Forte */ 4244fcf3ce44SJohn Forte ql_adapter_state_t * 4245fcf3ce44SJohn Forte ql_vport_create(ql_adapter_state_t *ha, uint8_t index) 4246fcf3ce44SJohn Forte { 4247fcf3ce44SJohn Forte ql_adapter_state_t *vha; 4248fcf3ce44SJohn Forte 4249fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 4250fcf3ce44SJohn Forte 4251fcf3ce44SJohn Forte /* Inherit the parents data. */ 4252fcf3ce44SJohn Forte vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP); 4253fcf3ce44SJohn Forte 4254fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 4255fcf3ce44SJohn Forte bcopy(ha, vha, sizeof (ql_adapter_state_t)); 4256fcf3ce44SJohn Forte vha->pi_attrs = NULL; 4257fcf3ce44SJohn Forte vha->ub_outcnt = 0; 4258fcf3ce44SJohn Forte vha->ub_allocated = 0; 4259fcf3ce44SJohn Forte vha->flags = 0; 4260fcf3ce44SJohn Forte vha->task_daemon_flags = 0; 4261fcf3ce44SJohn Forte ha->vp_next = vha; 4262fcf3ce44SJohn Forte vha->pha = ha; 4263fcf3ce44SJohn Forte vha->vp_index = index; 4264fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 4265fcf3ce44SJohn Forte 4266fcf3ce44SJohn Forte vha->hba.next = NULL; 4267fcf3ce44SJohn Forte vha->hba.prev = NULL; 4268fcf3ce44SJohn Forte vha->hba.base_address = vha; 4269fcf3ce44SJohn Forte vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE; 4270fcf3ce44SJohn Forte vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE, 4271fcf3ce44SJohn Forte KM_SLEEP); 4272fcf3ce44SJohn Forte vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT, 4273fcf3ce44SJohn Forte KM_SLEEP); 4274fcf3ce44SJohn Forte 4275fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 4276fcf3ce44SJohn Forte 4277fcf3ce44SJohn Forte return (vha); 4278fcf3ce44SJohn Forte } 4279fcf3ce44SJohn Forte 4280fcf3ce44SJohn Forte /* 4281fcf3ce44SJohn Forte * ql_vport_destroy 4282fcf3ce44SJohn Forte * Destroys virtual port context. 4283fcf3ce44SJohn Forte * 4284fcf3ce44SJohn Forte * Input: 4285fcf3ce44SJohn Forte * ha = virtual adapter state pointer. 4286fcf3ce44SJohn Forte * 4287fcf3ce44SJohn Forte * Context: 4288fcf3ce44SJohn Forte * Kernel context. 4289fcf3ce44SJohn Forte */ 4290fcf3ce44SJohn Forte void 4291fcf3ce44SJohn Forte ql_vport_destroy(ql_adapter_state_t *ha) 4292fcf3ce44SJohn Forte { 4293fcf3ce44SJohn Forte ql_adapter_state_t *vha; 4294fcf3ce44SJohn Forte 4295fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index); 4296fcf3ce44SJohn Forte 4297fcf3ce44SJohn Forte /* Remove port from list. */ 4298fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 4299fcf3ce44SJohn Forte for (vha = ha->pha; vha != NULL; vha = vha->vp_next) { 4300fcf3ce44SJohn Forte if (vha->vp_next == ha) { 4301fcf3ce44SJohn Forte vha->vp_next = ha->vp_next; 4302fcf3ce44SJohn Forte break; 4303fcf3ce44SJohn Forte } 4304fcf3ce44SJohn Forte } 4305fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 4306fcf3ce44SJohn Forte 4307fcf3ce44SJohn Forte if (ha->ub_array != NULL) { 4308fcf3ce44SJohn Forte kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT); 4309fcf3ce44SJohn Forte } 4310fcf3ce44SJohn Forte if (ha->dev != NULL) { 4311fcf3ce44SJohn Forte kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE); 4312fcf3ce44SJohn Forte } 4313fcf3ce44SJohn Forte kmem_free(ha, sizeof (ql_adapter_state_t)); 4314fcf3ce44SJohn Forte 4315fcf3ce44SJohn Forte QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index); 4316fcf3ce44SJohn Forte } 4317f33c1cdbSDaniel Beauregard 4318f33c1cdbSDaniel Beauregard /* 4319f33c1cdbSDaniel Beauregard * ql_mps_reset 4320f33c1cdbSDaniel Beauregard * Reset MPS for FCoE functions. 4321f33c1cdbSDaniel Beauregard * 4322f33c1cdbSDaniel Beauregard * Input: 4323f33c1cdbSDaniel Beauregard * ha = virtual adapter state pointer. 4324f33c1cdbSDaniel Beauregard * 4325f33c1cdbSDaniel Beauregard * Context: 4326f33c1cdbSDaniel Beauregard * Kernel context. 4327f33c1cdbSDaniel Beauregard */ 4328f33c1cdbSDaniel Beauregard static void 4329f33c1cdbSDaniel Beauregard ql_mps_reset(ql_adapter_state_t *ha) 4330f33c1cdbSDaniel Beauregard { 4331f33c1cdbSDaniel Beauregard uint32_t data, dctl = 1000; 4332f33c1cdbSDaniel Beauregard 4333f33c1cdbSDaniel Beauregard do { 4334f33c1cdbSDaniel Beauregard if (dctl-- == 0 || ql_wrt_risc_ram_word(ha, 0x7c00, 1) != 4335f33c1cdbSDaniel Beauregard QL_SUCCESS) { 4336f33c1cdbSDaniel Beauregard return; 4337f33c1cdbSDaniel Beauregard } 4338f33c1cdbSDaniel Beauregard if (ql_rd_risc_ram_word(ha, 0x7c00, &data) != QL_SUCCESS) { 4339c1374a13SSurya Prakki (void) ql_wrt_risc_ram_word(ha, 0x7c00, 0); 4340f33c1cdbSDaniel Beauregard return; 4341f33c1cdbSDaniel Beauregard } 4342f33c1cdbSDaniel Beauregard } while (!(data & BIT_0)); 4343f33c1cdbSDaniel Beauregard 4344f33c1cdbSDaniel Beauregard if (ql_rd_risc_ram_word(ha, 0x7A15, &data) == QL_SUCCESS) { 4345f33c1cdbSDaniel Beauregard dctl = (uint16_t)ql_pci_config_get16(ha, 0x54); 4346f33c1cdbSDaniel Beauregard if ((data & 0xe0) != (dctl & 0xe0)) { 4347f33c1cdbSDaniel Beauregard data &= 0xff1f; 4348f33c1cdbSDaniel Beauregard data |= dctl & 0xe0; 4349c1374a13SSurya Prakki (void) ql_wrt_risc_ram_word(ha, 0x7A15, data); 4350f33c1cdbSDaniel Beauregard } 4351f33c1cdbSDaniel Beauregard } 4352c1374a13SSurya Prakki (void) ql_wrt_risc_ram_word(ha, 0x7c00, 0); 4353f33c1cdbSDaniel Beauregard } 4354