17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM
2211541SDaniel.Beauregard@Sun.COM /* Copyright 2010 QLogic Corporation */
237836SJohn.Forte@Sun.COM
247836SJohn.Forte@Sun.COM /*
25*12279SDaniel.Beauregard@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
267836SJohn.Forte@Sun.COM */
277836SJohn.Forte@Sun.COM
2811541SDaniel.Beauregard@Sun.COM #pragma ident "Copyright 2010 QLogic Corporation; ql_init.c"
297836SJohn.Forte@Sun.COM
307836SJohn.Forte@Sun.COM /*
317836SJohn.Forte@Sun.COM * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
327836SJohn.Forte@Sun.COM *
337836SJohn.Forte@Sun.COM * ***********************************************************************
347836SJohn.Forte@Sun.COM * * **
357836SJohn.Forte@Sun.COM * * NOTICE **
3611541SDaniel.Beauregard@Sun.COM * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
377836SJohn.Forte@Sun.COM * * ALL RIGHTS RESERVED **
387836SJohn.Forte@Sun.COM * * **
397836SJohn.Forte@Sun.COM * ***********************************************************************
407836SJohn.Forte@Sun.COM *
417836SJohn.Forte@Sun.COM */
427836SJohn.Forte@Sun.COM
437836SJohn.Forte@Sun.COM #include <ql_apps.h>
447836SJohn.Forte@Sun.COM #include <ql_api.h>
457836SJohn.Forte@Sun.COM #include <ql_debug.h>
467836SJohn.Forte@Sun.COM #include <ql_init.h>
477836SJohn.Forte@Sun.COM #include <ql_iocb.h>
487836SJohn.Forte@Sun.COM #include <ql_isr.h>
497836SJohn.Forte@Sun.COM #include <ql_mbx.h>
5011924SDaniel.Beauregard@Sun.COM #include <ql_nx.h>
517836SJohn.Forte@Sun.COM #include <ql_xioctl.h>
527836SJohn.Forte@Sun.COM
537836SJohn.Forte@Sun.COM /*
547836SJohn.Forte@Sun.COM * Local data
557836SJohn.Forte@Sun.COM */
567836SJohn.Forte@Sun.COM
577836SJohn.Forte@Sun.COM /*
587836SJohn.Forte@Sun.COM * Local prototypes
597836SJohn.Forte@Sun.COM */
607836SJohn.Forte@Sun.COM static uint16_t ql_nvram_request(ql_adapter_state_t *, uint32_t);
617836SJohn.Forte@Sun.COM static int ql_nvram_24xx_config(ql_adapter_state_t *);
627836SJohn.Forte@Sun.COM static void ql_23_properties(ql_adapter_state_t *, nvram_t *);
637836SJohn.Forte@Sun.COM static void ql_24xx_properties(ql_adapter_state_t *, nvram_24xx_t *);
647836SJohn.Forte@Sun.COM static int ql_check_isp_firmware(ql_adapter_state_t *);
657836SJohn.Forte@Sun.COM static int ql_chip_diag(ql_adapter_state_t *);
667836SJohn.Forte@Sun.COM static int ql_load_flash_fw(ql_adapter_state_t *);
677836SJohn.Forte@Sun.COM static int ql_configure_loop(ql_adapter_state_t *);
687836SJohn.Forte@Sun.COM static int ql_configure_hba(ql_adapter_state_t *);
697836SJohn.Forte@Sun.COM static int ql_configure_fabric(ql_adapter_state_t *);
707836SJohn.Forte@Sun.COM static int ql_configure_device_d_id(ql_adapter_state_t *);
717836SJohn.Forte@Sun.COM static void ql_set_max_read_req(ql_adapter_state_t *);
729446SDaniel.Beauregard@Sun.COM static void ql_configure_n_port_info(ql_adapter_state_t *);
7310240SDaniel.Beauregard@Sun.COM static void ql_clear_mcp(ql_adapter_state_t *);
7410736SDaniel.Beauregard@Sun.COM static void ql_mps_reset(ql_adapter_state_t *);
7510240SDaniel.Beauregard@Sun.COM
767836SJohn.Forte@Sun.COM /*
777836SJohn.Forte@Sun.COM * ql_initialize_adapter
787836SJohn.Forte@Sun.COM * Initialize board.
797836SJohn.Forte@Sun.COM *
807836SJohn.Forte@Sun.COM * Input:
817836SJohn.Forte@Sun.COM * ha = adapter state pointer.
827836SJohn.Forte@Sun.COM *
837836SJohn.Forte@Sun.COM * Returns:
847836SJohn.Forte@Sun.COM * ql local function return status code.
857836SJohn.Forte@Sun.COM *
867836SJohn.Forte@Sun.COM * Context:
877836SJohn.Forte@Sun.COM * Kernel context.
887836SJohn.Forte@Sun.COM */
897836SJohn.Forte@Sun.COM int
ql_initialize_adapter(ql_adapter_state_t * ha)907836SJohn.Forte@Sun.COM ql_initialize_adapter(ql_adapter_state_t *ha)
917836SJohn.Forte@Sun.COM {
927836SJohn.Forte@Sun.COM int rval;
937836SJohn.Forte@Sun.COM class_svc_param_t *class3_param;
947836SJohn.Forte@Sun.COM caddr_t msg;
957836SJohn.Forte@Sun.COM la_els_logi_t *els = &ha->loginparams;
967836SJohn.Forte@Sun.COM int retries = 5;
977836SJohn.Forte@Sun.COM
987836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
997836SJohn.Forte@Sun.COM
1007836SJohn.Forte@Sun.COM do {
1017836SJohn.Forte@Sun.COM /* Clear adapter flags. */
1027836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
1037836SJohn.Forte@Sun.COM ha->task_daemon_flags &= TASK_DAEMON_STOP_FLG |
1047836SJohn.Forte@Sun.COM TASK_DAEMON_SLEEPING_FLG | TASK_DAEMON_ALIVE_FLG |
1057836SJohn.Forte@Sun.COM TASK_DAEMON_IDLE_CHK_FLG;
1067836SJohn.Forte@Sun.COM ha->task_daemon_flags |= LOOP_DOWN;
1077836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
1087836SJohn.Forte@Sun.COM
1097836SJohn.Forte@Sun.COM ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
1107836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
1119156SDaniel.Beauregard@Sun.COM ha->flags |= ABORT_CMDS_LOOP_DOWN_TMO;
1127836SJohn.Forte@Sun.COM ha->flags &= ~ONLINE;
1137836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
1147836SJohn.Forte@Sun.COM
1157836SJohn.Forte@Sun.COM ha->state = FC_STATE_OFFLINE;
1167836SJohn.Forte@Sun.COM msg = "Loop OFFLINE";
1177836SJohn.Forte@Sun.COM
1187836SJohn.Forte@Sun.COM rval = ql_pci_sbus_config(ha);
1197836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
1207836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
1217836SJohn.Forte@Sun.COM if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
1227836SJohn.Forte@Sun.COM EL(ha, "ql_pci_sbus_cfg, isp_abort_needed\n");
1237836SJohn.Forte@Sun.COM ha->task_daemon_flags |= ISP_ABORT_NEEDED;
1247836SJohn.Forte@Sun.COM }
1257836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
1267836SJohn.Forte@Sun.COM continue;
1277836SJohn.Forte@Sun.COM }
1287836SJohn.Forte@Sun.COM
1299446SDaniel.Beauregard@Sun.COM (void) ql_setup_fcache(ha);
1307836SJohn.Forte@Sun.COM
1317836SJohn.Forte@Sun.COM /* Reset ISP chip. */
1327836SJohn.Forte@Sun.COM ql_reset_chip(ha);
1337836SJohn.Forte@Sun.COM
1347836SJohn.Forte@Sun.COM /* Get NVRAM configuration if needed. */
1357836SJohn.Forte@Sun.COM if (ha->init_ctrl_blk.cb.version == 0) {
1367836SJohn.Forte@Sun.COM (void) ql_nvram_config(ha);
1377836SJohn.Forte@Sun.COM }
1387836SJohn.Forte@Sun.COM
1397836SJohn.Forte@Sun.COM /* Set login parameters. */
14011924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
1417836SJohn.Forte@Sun.COM els->common_service.rx_bufsize = CHAR_TO_SHORT(
1427836SJohn.Forte@Sun.COM ha->init_ctrl_blk.cb24.max_frame_length[0],
1437836SJohn.Forte@Sun.COM ha->init_ctrl_blk.cb24.max_frame_length[1]);
1447836SJohn.Forte@Sun.COM bcopy((void *)&ha->init_ctrl_blk.cb24.port_name[0],
1457836SJohn.Forte@Sun.COM (void *)&els->nport_ww_name.raw_wwn[0], 8);
1467836SJohn.Forte@Sun.COM bcopy((void *)&ha->init_ctrl_blk.cb24.node_name[0],
1477836SJohn.Forte@Sun.COM (void *)&els->node_ww_name.raw_wwn[0], 8);
1487836SJohn.Forte@Sun.COM } else {
1497836SJohn.Forte@Sun.COM els->common_service.rx_bufsize = CHAR_TO_SHORT(
1507836SJohn.Forte@Sun.COM ha->init_ctrl_blk.cb.max_frame_length[0],
1517836SJohn.Forte@Sun.COM ha->init_ctrl_blk.cb.max_frame_length[1]);
1527836SJohn.Forte@Sun.COM bcopy((void *)&ha->init_ctrl_blk.cb.port_name[0],
1537836SJohn.Forte@Sun.COM (void *)&els->nport_ww_name.raw_wwn[0], 8);
1547836SJohn.Forte@Sun.COM bcopy((void *)&ha->init_ctrl_blk.cb.node_name[0],
1557836SJohn.Forte@Sun.COM (void *)&els->node_ww_name.raw_wwn[0], 8);
1567836SJohn.Forte@Sun.COM }
157*12279SDaniel.Beauregard@Sun.COM bcopy(QL_VERSION, ha->adapter_stats->revlvl.qlddv,
158*12279SDaniel.Beauregard@Sun.COM strlen(QL_VERSION));
1597836SJohn.Forte@Sun.COM
1607836SJohn.Forte@Sun.COM /* Determine which RISC code to use. */
16111924SDaniel.Beauregard@Sun.COM if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
16211924SDaniel.Beauregard@Sun.COM if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) {
16311924SDaniel.Beauregard@Sun.COM rval = ql_load_isp_firmware(ha);
16411924SDaniel.Beauregard@Sun.COM }
1657836SJohn.Forte@Sun.COM }
1667836SJohn.Forte@Sun.COM
1677836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
1689446SDaniel.Beauregard@Sun.COM QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS) {
1697836SJohn.Forte@Sun.COM
1707836SJohn.Forte@Sun.COM (void) ql_fw_ready(ha, ha->fwwait);
1717836SJohn.Forte@Sun.COM
1727836SJohn.Forte@Sun.COM if (!(ha->task_daemon_flags & QL_SUSPENDED) &&
1737836SJohn.Forte@Sun.COM ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
1747836SJohn.Forte@Sun.COM if (ha->topology & QL_LOOP_CONNECTION) {
1757836SJohn.Forte@Sun.COM ha->state = ha->state | FC_STATE_LOOP;
1767836SJohn.Forte@Sun.COM msg = "Loop ONLINE";
1777836SJohn.Forte@Sun.COM ha->task_daemon_flags |= STATE_ONLINE;
1787836SJohn.Forte@Sun.COM } else if (ha->topology & QL_P2P_CONNECTION) {
1797836SJohn.Forte@Sun.COM ha->state = ha->state |
1807836SJohn.Forte@Sun.COM FC_STATE_ONLINE;
1817836SJohn.Forte@Sun.COM msg = "Link ONLINE";
1827836SJohn.Forte@Sun.COM ha->task_daemon_flags |= STATE_ONLINE;
1837836SJohn.Forte@Sun.COM } else {
1847836SJohn.Forte@Sun.COM msg = "Unknown Link state";
1857836SJohn.Forte@Sun.COM }
1867836SJohn.Forte@Sun.COM }
1877836SJohn.Forte@Sun.COM } else {
1887836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
1897836SJohn.Forte@Sun.COM if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
1907836SJohn.Forte@Sun.COM EL(ha, "failed, isp_abort_needed\n");
1917836SJohn.Forte@Sun.COM ha->task_daemon_flags |= ISP_ABORT_NEEDED |
1927836SJohn.Forte@Sun.COM LOOP_DOWN;
1937836SJohn.Forte@Sun.COM }
1947836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
1957836SJohn.Forte@Sun.COM }
1967836SJohn.Forte@Sun.COM
1977836SJohn.Forte@Sun.COM } while (retries-- != 0 && ha->task_daemon_flags & ISP_ABORT_NEEDED);
1987836SJohn.Forte@Sun.COM
1997836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "!Qlogic %s(%d): %s", QL_NAME, ha->instance, msg);
2007836SJohn.Forte@Sun.COM
2017836SJohn.Forte@Sun.COM /* Enable ISP interrupts and login parameters. */
20211924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
20311924SDaniel.Beauregard@Sun.COM ql_8021_enable_intrs(ha);
20411924SDaniel.Beauregard@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_242581)) {
20511924SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
20611924SDaniel.Beauregard@Sun.COM } else {
20711924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
20811924SDaniel.Beauregard@Sun.COM }
2097836SJohn.Forte@Sun.COM
2107836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
2117836SJohn.Forte@Sun.COM ha->flags |= (INTERRUPTS_ENABLED | ONLINE);
2127836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
2137836SJohn.Forte@Sun.COM
2147836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(FC_STATE_CHANGE | RESET_MARKER_NEEDED |
2157836SJohn.Forte@Sun.COM COMMAND_WAIT_NEEDED);
2167836SJohn.Forte@Sun.COM
2177836SJohn.Forte@Sun.COM /*
2187836SJohn.Forte@Sun.COM * Setup login parameters.
2197836SJohn.Forte@Sun.COM */
2207836SJohn.Forte@Sun.COM els->common_service.fcph_version = 0x2006;
2217836SJohn.Forte@Sun.COM els->common_service.btob_credit = 3;
2227836SJohn.Forte@Sun.COM els->common_service.cmn_features = 0x8800;
2237836SJohn.Forte@Sun.COM els->common_service.conc_sequences = 0xff;
2247836SJohn.Forte@Sun.COM els->common_service.relative_offset = 3;
2257836SJohn.Forte@Sun.COM els->common_service.e_d_tov = 0x07d0;
2267836SJohn.Forte@Sun.COM
2277836SJohn.Forte@Sun.COM class3_param = (class_svc_param_t *)&els->class_3;
2287836SJohn.Forte@Sun.COM class3_param->class_valid_svc_opt = 0x8800;
2297836SJohn.Forte@Sun.COM class3_param->rcv_data_size = els->common_service.rx_bufsize;
2307836SJohn.Forte@Sun.COM class3_param->conc_sequences = 0xff;
2317836SJohn.Forte@Sun.COM
2327836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
2337836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
2347836SJohn.Forte@Sun.COM } else {
2357836SJohn.Forte@Sun.COM /*EMPTY*/
2367836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2377836SJohn.Forte@Sun.COM }
2387836SJohn.Forte@Sun.COM return (rval);
2397836SJohn.Forte@Sun.COM }
2407836SJohn.Forte@Sun.COM
2417836SJohn.Forte@Sun.COM /*
2427836SJohn.Forte@Sun.COM * ql_pci_sbus_config
2437836SJohn.Forte@Sun.COM * Setup device PCI/SBUS configuration registers.
2447836SJohn.Forte@Sun.COM *
2457836SJohn.Forte@Sun.COM * Input:
2467836SJohn.Forte@Sun.COM * ha = adapter state pointer.
2477836SJohn.Forte@Sun.COM *
2487836SJohn.Forte@Sun.COM * Returns:
2497836SJohn.Forte@Sun.COM * ql local function return status code.
2507836SJohn.Forte@Sun.COM *
2517836SJohn.Forte@Sun.COM * Context:
2527836SJohn.Forte@Sun.COM * Kernel context.
2537836SJohn.Forte@Sun.COM */
2547836SJohn.Forte@Sun.COM int
ql_pci_sbus_config(ql_adapter_state_t * ha)2557836SJohn.Forte@Sun.COM ql_pci_sbus_config(ql_adapter_state_t *ha)
2567836SJohn.Forte@Sun.COM {
2577836SJohn.Forte@Sun.COM uint32_t timer;
2587836SJohn.Forte@Sun.COM uint16_t cmd, w16;
2597836SJohn.Forte@Sun.COM
2607836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2617836SJohn.Forte@Sun.COM
2627836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_SBUS_CARD)) {
2637836SJohn.Forte@Sun.COM w16 = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
2647836SJohn.Forte@Sun.COM (uint16_t *)(ha->sbus_fpga_iobase + FPGA_REVISION));
2657836SJohn.Forte@Sun.COM EL(ha, "FPGA rev is %d.%d", (w16 & 0xf0) >> 4,
2667836SJohn.Forte@Sun.COM w16 & 0xf);
2677836SJohn.Forte@Sun.COM } else {
2687836SJohn.Forte@Sun.COM /*
2697836SJohn.Forte@Sun.COM * we want to respect framework's setting of PCI
2707836SJohn.Forte@Sun.COM * configuration space command register and also
2717836SJohn.Forte@Sun.COM * want to make sure that all bits of interest to us
2727836SJohn.Forte@Sun.COM * are properly set in command register.
2737836SJohn.Forte@Sun.COM */
2747836SJohn.Forte@Sun.COM cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
2757836SJohn.Forte@Sun.COM cmd = (uint16_t)(cmd | PCI_COMM_IO | PCI_COMM_MAE |
2767836SJohn.Forte@Sun.COM PCI_COMM_ME | PCI_COMM_MEMWR_INVAL |
2777836SJohn.Forte@Sun.COM PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
2787836SJohn.Forte@Sun.COM
2797836SJohn.Forte@Sun.COM /*
2807836SJohn.Forte@Sun.COM * If this is a 2300 card and not 2312, reset the
2817836SJohn.Forte@Sun.COM * MEMWR_INVAL due to a bug in the 2300. Unfortunately, the
2827836SJohn.Forte@Sun.COM * 2310 also reports itself as a 2300 so we need to get the
2837836SJohn.Forte@Sun.COM * fb revision level -- a 6 indicates it really is a 2300 and
2847836SJohn.Forte@Sun.COM * not a 2310.
2857836SJohn.Forte@Sun.COM */
2867836SJohn.Forte@Sun.COM
2877836SJohn.Forte@Sun.COM if (ha->device_id == 0x2300) {
2887836SJohn.Forte@Sun.COM /* Pause RISC. */
2897836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
2907836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
2917836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) !=
2927836SJohn.Forte@Sun.COM 0) {
2937836SJohn.Forte@Sun.COM break;
2947836SJohn.Forte@Sun.COM } else {
2957836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
2967836SJohn.Forte@Sun.COM }
2977836SJohn.Forte@Sun.COM }
2987836SJohn.Forte@Sun.COM
2997836SJohn.Forte@Sun.COM /* Select FPM registers. */
3007836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0x20);
3017836SJohn.Forte@Sun.COM
3027836SJohn.Forte@Sun.COM /* Get the fb rev level */
3037836SJohn.Forte@Sun.COM if (RD16_IO_REG(ha, fb_cmd) == 6) {
3047836SJohn.Forte@Sun.COM cmd = (uint16_t)(cmd & ~PCI_COMM_MEMWR_INVAL);
3057836SJohn.Forte@Sun.COM }
3067836SJohn.Forte@Sun.COM
3077836SJohn.Forte@Sun.COM /* Deselect FPM registers. */
3087836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0x0);
3097836SJohn.Forte@Sun.COM
3107836SJohn.Forte@Sun.COM /* Release RISC module. */
3117836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
3127836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
3137836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) ==
3147836SJohn.Forte@Sun.COM 0) {
3157836SJohn.Forte@Sun.COM break;
3167836SJohn.Forte@Sun.COM } else {
3177836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
3187836SJohn.Forte@Sun.COM }
3197836SJohn.Forte@Sun.COM }
3207836SJohn.Forte@Sun.COM } else if (ha->device_id == 0x2312) {
3217836SJohn.Forte@Sun.COM /*
3227836SJohn.Forte@Sun.COM * cPCI ISP2312 specific code to service function 1
3237836SJohn.Forte@Sun.COM * hot-swap registers.
3247836SJohn.Forte@Sun.COM */
3257836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, ctrl_status) & ISP_FUNC_NUM_MASK)
3267836SJohn.Forte@Sun.COM != 0) {
3277836SJohn.Forte@Sun.COM ql_pci_config_put8(ha, 0x66, 0xc2);
3287836SJohn.Forte@Sun.COM }
3297836SJohn.Forte@Sun.COM }
3307836SJohn.Forte@Sun.COM
33111924SDaniel.Beauregard@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_8021)) &&
33211924SDaniel.Beauregard@Sun.COM ha->pci_max_read_req != 0) {
3337836SJohn.Forte@Sun.COM ql_set_max_read_req(ha);
3347836SJohn.Forte@Sun.COM }
3357836SJohn.Forte@Sun.COM
3367836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
3377836SJohn.Forte@Sun.COM
3387836SJohn.Forte@Sun.COM /* Set cache line register. */
3397836SJohn.Forte@Sun.COM ql_pci_config_put8(ha, PCI_CONF_CACHE_LINESZ, 0x10);
3407836SJohn.Forte@Sun.COM
3417836SJohn.Forte@Sun.COM /* Set latency register. */
3427836SJohn.Forte@Sun.COM ql_pci_config_put8(ha, PCI_CONF_LATENCY_TIMER, 0x40);
3437836SJohn.Forte@Sun.COM
3447836SJohn.Forte@Sun.COM /* Reset expansion ROM address decode enable. */
3457836SJohn.Forte@Sun.COM w16 = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_ROM);
3467836SJohn.Forte@Sun.COM w16 = (uint16_t)(w16 & ~BIT_0);
3477836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, PCI_CONF_ROM, w16);
3487836SJohn.Forte@Sun.COM }
3497836SJohn.Forte@Sun.COM
3507836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3517836SJohn.Forte@Sun.COM
3527836SJohn.Forte@Sun.COM return (QL_SUCCESS);
3537836SJohn.Forte@Sun.COM }
3547836SJohn.Forte@Sun.COM
3557836SJohn.Forte@Sun.COM /*
3567836SJohn.Forte@Sun.COM * Set the PCI max read request value.
3577836SJohn.Forte@Sun.COM *
3587836SJohn.Forte@Sun.COM * Input:
3597836SJohn.Forte@Sun.COM * ha: adapter state pointer.
3607836SJohn.Forte@Sun.COM *
3617836SJohn.Forte@Sun.COM * Output:
3627836SJohn.Forte@Sun.COM * none.
3637836SJohn.Forte@Sun.COM *
3647836SJohn.Forte@Sun.COM * Returns:
3657836SJohn.Forte@Sun.COM *
3667836SJohn.Forte@Sun.COM * Context:
3677836SJohn.Forte@Sun.COM * Kernel context.
3687836SJohn.Forte@Sun.COM */
3697836SJohn.Forte@Sun.COM
3707836SJohn.Forte@Sun.COM static void
ql_set_max_read_req(ql_adapter_state_t * ha)3717836SJohn.Forte@Sun.COM ql_set_max_read_req(ql_adapter_state_t *ha)
3727836SJohn.Forte@Sun.COM {
3737836SJohn.Forte@Sun.COM uint16_t read_req, w16;
3747836SJohn.Forte@Sun.COM uint16_t tmp = ha->pci_max_read_req;
3757836SJohn.Forte@Sun.COM
3767836SJohn.Forte@Sun.COM if ((ha->device_id == 0x2422) ||
3777836SJohn.Forte@Sun.COM ((ha->device_id & 0xff00) == 0x2300)) {
3787836SJohn.Forte@Sun.COM /* check for vaild override value */
3797836SJohn.Forte@Sun.COM if (tmp == 512 || tmp == 1024 || tmp == 2048 ||
3807836SJohn.Forte@Sun.COM tmp == 4096) {
3817836SJohn.Forte@Sun.COM /* shift away the don't cares */
3827836SJohn.Forte@Sun.COM tmp = (uint16_t)(tmp >> 10);
3837836SJohn.Forte@Sun.COM /* convert bit pos to request value */
3847836SJohn.Forte@Sun.COM for (read_req = 0; tmp != 0; read_req++) {
3857836SJohn.Forte@Sun.COM tmp = (uint16_t)(tmp >> 1);
3867836SJohn.Forte@Sun.COM }
3877836SJohn.Forte@Sun.COM w16 = (uint16_t)ql_pci_config_get16(ha, 0x4e);
3887836SJohn.Forte@Sun.COM w16 = (uint16_t)(w16 & ~(BIT_3 & BIT_2));
3897836SJohn.Forte@Sun.COM w16 = (uint16_t)(w16 | (read_req << 2));
3907836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, 0x4e, w16);
3917836SJohn.Forte@Sun.COM } else {
3927836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
3937836SJohn.Forte@Sun.COM "'pci-max-read-request': %d; using system "
3947836SJohn.Forte@Sun.COM "default\n", tmp);
3957836SJohn.Forte@Sun.COM }
3967836SJohn.Forte@Sun.COM } else if ((ha->device_id == 0x2432) || ((ha->device_id & 0xff00) ==
3979156SDaniel.Beauregard@Sun.COM 0x2500) || (ha->device_id == 0x8432)) {
3987836SJohn.Forte@Sun.COM /* check for vaild override value */
3997836SJohn.Forte@Sun.COM if (tmp == 128 || tmp == 256 || tmp == 512 ||
4007836SJohn.Forte@Sun.COM tmp == 1024 || tmp == 2048 || tmp == 4096) {
4017836SJohn.Forte@Sun.COM /* shift away the don't cares */
4027836SJohn.Forte@Sun.COM tmp = (uint16_t)(tmp >> 8);
4037836SJohn.Forte@Sun.COM /* convert bit pos to request value */
4047836SJohn.Forte@Sun.COM for (read_req = 0; tmp != 0; read_req++) {
4057836SJohn.Forte@Sun.COM tmp = (uint16_t)(tmp >> 1);
4067836SJohn.Forte@Sun.COM }
4077836SJohn.Forte@Sun.COM w16 = (uint16_t)ql_pci_config_get16(ha, 0x54);
4087836SJohn.Forte@Sun.COM w16 = (uint16_t)(w16 & ~(BIT_14 | BIT_13 |
4097836SJohn.Forte@Sun.COM BIT_12));
4107836SJohn.Forte@Sun.COM w16 = (uint16_t)(w16 | (read_req << 12));
4117836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, 0x54, w16);
4127836SJohn.Forte@Sun.COM } else {
4137836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
4147836SJohn.Forte@Sun.COM "'pci-max-read-request': %d; using system "
4157836SJohn.Forte@Sun.COM "default\n", tmp);
4167836SJohn.Forte@Sun.COM }
4177836SJohn.Forte@Sun.COM }
4187836SJohn.Forte@Sun.COM }
4197836SJohn.Forte@Sun.COM
4207836SJohn.Forte@Sun.COM /*
4217836SJohn.Forte@Sun.COM * NVRAM configuration.
4227836SJohn.Forte@Sun.COM *
4237836SJohn.Forte@Sun.COM * Input:
4247836SJohn.Forte@Sun.COM * ha: adapter state pointer.
4257836SJohn.Forte@Sun.COM * ha->hba_buf = request and response rings
4267836SJohn.Forte@Sun.COM *
4277836SJohn.Forte@Sun.COM * Output:
4287836SJohn.Forte@Sun.COM * ha->init_ctrl_blk = initialization control block
4297836SJohn.Forte@Sun.COM * host adapters parameters in host adapter block
4307836SJohn.Forte@Sun.COM *
4317836SJohn.Forte@Sun.COM * Returns:
4327836SJohn.Forte@Sun.COM * ql local function return status code.
4337836SJohn.Forte@Sun.COM *
4347836SJohn.Forte@Sun.COM * Context:
4357836SJohn.Forte@Sun.COM * Kernel context.
4367836SJohn.Forte@Sun.COM */
4377836SJohn.Forte@Sun.COM int
ql_nvram_config(ql_adapter_state_t * ha)4387836SJohn.Forte@Sun.COM ql_nvram_config(ql_adapter_state_t *ha)
4397836SJohn.Forte@Sun.COM {
4407836SJohn.Forte@Sun.COM uint32_t cnt;
4417836SJohn.Forte@Sun.COM caddr_t dptr1, dptr2;
4427836SJohn.Forte@Sun.COM ql_init_cb_t *icb = &ha->init_ctrl_blk.cb;
4437836SJohn.Forte@Sun.COM ql_ip_init_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb;
4447836SJohn.Forte@Sun.COM nvram_t *nv = (nvram_t *)ha->request_ring_bp;
4457836SJohn.Forte@Sun.COM uint16_t *wptr = (uint16_t *)ha->request_ring_bp;
4467836SJohn.Forte@Sun.COM uint8_t chksum = 0;
4477836SJohn.Forte@Sun.COM int rval;
4487836SJohn.Forte@Sun.COM int idpromlen;
4497836SJohn.Forte@Sun.COM char idprombuf[32];
4507836SJohn.Forte@Sun.COM uint32_t start_addr;
4517836SJohn.Forte@Sun.COM
4527836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4537836SJohn.Forte@Sun.COM
45411924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
4557836SJohn.Forte@Sun.COM return (ql_nvram_24xx_config(ha));
4567836SJohn.Forte@Sun.COM }
4577836SJohn.Forte@Sun.COM
4587836SJohn.Forte@Sun.COM start_addr = 0;
4597836SJohn.Forte@Sun.COM if ((rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) ==
4607836SJohn.Forte@Sun.COM QL_SUCCESS) {
4617836SJohn.Forte@Sun.COM /* Verify valid NVRAM checksum. */
4627836SJohn.Forte@Sun.COM for (cnt = 0; cnt < sizeof (nvram_t)/2; cnt++) {
4637836SJohn.Forte@Sun.COM *wptr = (uint16_t)ql_get_nvram_word(ha,
4647836SJohn.Forte@Sun.COM (uint32_t)(cnt + start_addr));
4657836SJohn.Forte@Sun.COM chksum = (uint8_t)(chksum + (uint8_t)*wptr);
4667836SJohn.Forte@Sun.COM chksum = (uint8_t)(chksum + (uint8_t)(*wptr >> 8));
4677836SJohn.Forte@Sun.COM wptr++;
4687836SJohn.Forte@Sun.COM }
4697836SJohn.Forte@Sun.COM ql_release_nvram(ha);
4707836SJohn.Forte@Sun.COM }
4717836SJohn.Forte@Sun.COM
4727836SJohn.Forte@Sun.COM /* Bad NVRAM data, set defaults parameters. */
4737836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
4747836SJohn.Forte@Sun.COM nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
4757836SJohn.Forte@Sun.COM nv->nvram_version < 1) {
4767836SJohn.Forte@Sun.COM
4777836SJohn.Forte@Sun.COM EL(ha, "failed, rval=%xh, checksum=%xh, "
4787836SJohn.Forte@Sun.COM "id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, "
4797836SJohn.Forte@Sun.COM "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
4807836SJohn.Forte@Sun.COM nv->id[2], nv->id[3], ha->xioctl->fdesc.flash_size,
4817836SJohn.Forte@Sun.COM ha->subven_id, nv->nvram_version);
4827836SJohn.Forte@Sun.COM
4837836SJohn.Forte@Sun.COM /* Don't print nvram message if it's an on-board 2200 */
4847836SJohn.Forte@Sun.COM if (!((CFG_IST(ha, CFG_CTRL_2200)) &&
4857836SJohn.Forte@Sun.COM (ha->xioctl->fdesc.flash_size == 0))) {
4867836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed,"
4877836SJohn.Forte@Sun.COM " using driver defaults.", QL_NAME, ha->instance);
4887836SJohn.Forte@Sun.COM }
4897836SJohn.Forte@Sun.COM
4907836SJohn.Forte@Sun.COM /* Reset NVRAM data. */
4917836SJohn.Forte@Sun.COM bzero((void *)nv, sizeof (nvram_t));
4927836SJohn.Forte@Sun.COM
4937836SJohn.Forte@Sun.COM /*
4947836SJohn.Forte@Sun.COM * Set default initialization control block.
4957836SJohn.Forte@Sun.COM */
4967836SJohn.Forte@Sun.COM nv->parameter_block_version = ICB_VERSION;
4977836SJohn.Forte@Sun.COM nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
4987836SJohn.Forte@Sun.COM nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
4997836SJohn.Forte@Sun.COM
5007836SJohn.Forte@Sun.COM nv->max_frame_length[1] = 4;
5017836SJohn.Forte@Sun.COM
5027836SJohn.Forte@Sun.COM /*
5037836SJohn.Forte@Sun.COM * Allow 2048 byte frames for 2300
5047836SJohn.Forte@Sun.COM */
5057836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
5067836SJohn.Forte@Sun.COM nv->max_frame_length[1] = 8;
5077836SJohn.Forte@Sun.COM }
5087836SJohn.Forte@Sun.COM nv->max_iocb_allocation[1] = 1;
5097836SJohn.Forte@Sun.COM nv->execution_throttle[0] = 16;
5107836SJohn.Forte@Sun.COM nv->login_retry_count = 8;
5117836SJohn.Forte@Sun.COM
5127836SJohn.Forte@Sun.COM idpromlen = 32;
5137836SJohn.Forte@Sun.COM
5147836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
5157836SJohn.Forte@Sun.COM if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
5167836SJohn.Forte@Sun.COM DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
5177836SJohn.Forte@Sun.COM &idpromlen) != DDI_PROP_SUCCESS) {
5187836SJohn.Forte@Sun.COM
5197836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): Unable to read idprom "
5207836SJohn.Forte@Sun.COM "property\n", ha->instance);
5217836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
5227836SJohn.Forte@Sun.COM "property", QL_NAME, ha->instance);
5237836SJohn.Forte@Sun.COM
5247836SJohn.Forte@Sun.COM nv->port_name[2] = 33;
5257836SJohn.Forte@Sun.COM nv->port_name[3] = 224;
5267836SJohn.Forte@Sun.COM nv->port_name[4] = 139;
5277836SJohn.Forte@Sun.COM nv->port_name[7] = (uint8_t)
5287836SJohn.Forte@Sun.COM (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
5297836SJohn.Forte@Sun.COM } else {
5307836SJohn.Forte@Sun.COM
5317836SJohn.Forte@Sun.COM nv->port_name[2] = idprombuf[2];
5327836SJohn.Forte@Sun.COM nv->port_name[3] = idprombuf[3];
5337836SJohn.Forte@Sun.COM nv->port_name[4] = idprombuf[4];
5347836SJohn.Forte@Sun.COM nv->port_name[5] = idprombuf[5];
5357836SJohn.Forte@Sun.COM nv->port_name[6] = idprombuf[6];
5367836SJohn.Forte@Sun.COM nv->port_name[7] = idprombuf[7];
5377836SJohn.Forte@Sun.COM nv->port_name[0] = (uint8_t)
5387836SJohn.Forte@Sun.COM (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
5397836SJohn.Forte@Sun.COM }
5407836SJohn.Forte@Sun.COM
5417836SJohn.Forte@Sun.COM /* Don't print nvram message if it's an on-board 2200 */
5427836SJohn.Forte@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_2200)) &&
5437836SJohn.Forte@Sun.COM (ha->xioctl->fdesc.flash_size == 0)) {
5447836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using"
5457836SJohn.Forte@Sun.COM " default HBA parameters and temporary WWPN:"
5467836SJohn.Forte@Sun.COM " %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
5477836SJohn.Forte@Sun.COM ha->instance, nv->port_name[0], nv->port_name[1],
5487836SJohn.Forte@Sun.COM nv->port_name[2], nv->port_name[3],
5497836SJohn.Forte@Sun.COM nv->port_name[4], nv->port_name[5],
5507836SJohn.Forte@Sun.COM nv->port_name[6], nv->port_name[7]);
5517836SJohn.Forte@Sun.COM }
5527836SJohn.Forte@Sun.COM
5537836SJohn.Forte@Sun.COM nv->login_timeout = 4;
5547836SJohn.Forte@Sun.COM
5557836SJohn.Forte@Sun.COM /* Set default connection options for the 23xx to 2 */
5567836SJohn.Forte@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_2200))) {
5577836SJohn.Forte@Sun.COM nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
5587836SJohn.Forte@Sun.COM BIT_5);
5597836SJohn.Forte@Sun.COM }
5607836SJohn.Forte@Sun.COM
5617836SJohn.Forte@Sun.COM /*
5627836SJohn.Forte@Sun.COM * Set default host adapter parameters
5637836SJohn.Forte@Sun.COM */
5647836SJohn.Forte@Sun.COM nv->host_p[0] = BIT_1;
5657836SJohn.Forte@Sun.COM nv->host_p[1] = BIT_2;
5667836SJohn.Forte@Sun.COM nv->reset_delay = 5;
5677836SJohn.Forte@Sun.COM nv->port_down_retry_count = 8;
5687836SJohn.Forte@Sun.COM nv->maximum_luns_per_target[0] = 8;
5697836SJohn.Forte@Sun.COM
5707836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
5717836SJohn.Forte@Sun.COM }
5727836SJohn.Forte@Sun.COM
5737836SJohn.Forte@Sun.COM /* Check for adapter node name (big endian). */
5747836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 8; cnt++) {
5757836SJohn.Forte@Sun.COM if (nv->node_name[cnt] != 0) {
5767836SJohn.Forte@Sun.COM break;
5777836SJohn.Forte@Sun.COM }
5787836SJohn.Forte@Sun.COM }
5797836SJohn.Forte@Sun.COM
5807836SJohn.Forte@Sun.COM /* Copy port name if no node name (big endian). */
5817836SJohn.Forte@Sun.COM if (cnt == 8) {
5827836SJohn.Forte@Sun.COM bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
5837836SJohn.Forte@Sun.COM nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
5847836SJohn.Forte@Sun.COM nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
5857836SJohn.Forte@Sun.COM }
5867836SJohn.Forte@Sun.COM
5877836SJohn.Forte@Sun.COM /* Reset initialization control blocks. */
5887836SJohn.Forte@Sun.COM bzero((void *)icb, sizeof (ql_init_cb_t));
5897836SJohn.Forte@Sun.COM
5907836SJohn.Forte@Sun.COM /* Get driver properties. */
5917836SJohn.Forte@Sun.COM ql_23_properties(ha, nv);
5927836SJohn.Forte@Sun.COM
5937836SJohn.Forte@Sun.COM cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
5947836SJohn.Forte@Sun.COM "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
5957836SJohn.Forte@Sun.COM QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
5967836SJohn.Forte@Sun.COM nv->port_name[2], nv->port_name[3], nv->port_name[4],
5977836SJohn.Forte@Sun.COM nv->port_name[5], nv->port_name[6], nv->port_name[7],
5987836SJohn.Forte@Sun.COM nv->node_name[0], nv->node_name[1], nv->node_name[2],
5997836SJohn.Forte@Sun.COM nv->node_name[3], nv->node_name[4], nv->node_name[5],
6007836SJohn.Forte@Sun.COM nv->node_name[6], nv->node_name[7]);
6017836SJohn.Forte@Sun.COM
6027836SJohn.Forte@Sun.COM /*
6037836SJohn.Forte@Sun.COM * Copy over NVRAM RISC parameter block
6047836SJohn.Forte@Sun.COM * to initialization control block.
6057836SJohn.Forte@Sun.COM */
6067836SJohn.Forte@Sun.COM dptr1 = (caddr_t)icb;
6077836SJohn.Forte@Sun.COM dptr2 = (caddr_t)&nv->parameter_block_version;
6087836SJohn.Forte@Sun.COM cnt = (uint32_t)((uintptr_t)&icb->request_q_outpointer[0] -
6097836SJohn.Forte@Sun.COM (uintptr_t)&icb->version);
6107836SJohn.Forte@Sun.COM while (cnt-- != 0) {
6117836SJohn.Forte@Sun.COM *dptr1++ = *dptr2++;
6127836SJohn.Forte@Sun.COM }
6137836SJohn.Forte@Sun.COM
6147836SJohn.Forte@Sun.COM /* Copy 2nd half. */
6157836SJohn.Forte@Sun.COM dptr1 = (caddr_t)&icb->add_fw_opt[0];
6167836SJohn.Forte@Sun.COM cnt = (uint32_t)((uintptr_t)&icb->reserved_3[0] -
6177836SJohn.Forte@Sun.COM (uintptr_t)&icb->add_fw_opt[0]);
6187836SJohn.Forte@Sun.COM
6197836SJohn.Forte@Sun.COM while (cnt-- != 0) {
6207836SJohn.Forte@Sun.COM *dptr1++ = *dptr2++;
6217836SJohn.Forte@Sun.COM }
6227836SJohn.Forte@Sun.COM
6237836SJohn.Forte@Sun.COM /*
6247836SJohn.Forte@Sun.COM * Setup driver firmware options.
6257836SJohn.Forte@Sun.COM */
6267836SJohn.Forte@Sun.COM icb->firmware_options[0] = (uint8_t)
6277836SJohn.Forte@Sun.COM (icb->firmware_options[0] | BIT_6 | BIT_1);
6287836SJohn.Forte@Sun.COM
6297836SJohn.Forte@Sun.COM /*
6307836SJohn.Forte@Sun.COM * There is no use enabling fast post for SBUS or 2300
6319446SDaniel.Beauregard@Sun.COM * Always enable 64bit addressing, except SBUS cards.
6327836SJohn.Forte@Sun.COM */
6339446SDaniel.Beauregard@Sun.COM ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
6347836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_SBUS_CARD | CFG_CTRL_2300 | CFG_CTRL_6322))) {
6357836SJohn.Forte@Sun.COM icb->firmware_options[0] = (uint8_t)
6367836SJohn.Forte@Sun.COM (icb->firmware_options[0] & ~BIT_3);
6377836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_SBUS_CARD)) {
6387836SJohn.Forte@Sun.COM icb->special_options[0] = (uint8_t)
6397836SJohn.Forte@Sun.COM (icb->special_options[0] | BIT_5);
6409446SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_64BIT_ADDRESSING;
6417836SJohn.Forte@Sun.COM }
6427836SJohn.Forte@Sun.COM } else {
6437836SJohn.Forte@Sun.COM icb->firmware_options[0] = (uint8_t)
6447836SJohn.Forte@Sun.COM (icb->firmware_options[0] | BIT_3);
6457836SJohn.Forte@Sun.COM }
6467836SJohn.Forte@Sun.COM /* RIO and ZIO not supported. */
6477836SJohn.Forte@Sun.COM icb->add_fw_opt[0] = (uint8_t)(icb->add_fw_opt[0] &
6487836SJohn.Forte@Sun.COM ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
6497836SJohn.Forte@Sun.COM
6507836SJohn.Forte@Sun.COM icb->firmware_options[1] = (uint8_t)(icb->firmware_options[1] |
6517836SJohn.Forte@Sun.COM BIT_7 | BIT_6 | BIT_5 | BIT_2 | BIT_0);
6527836SJohn.Forte@Sun.COM icb->firmware_options[0] = (uint8_t)
6537836SJohn.Forte@Sun.COM (icb->firmware_options[0] & ~(BIT_5 | BIT_4));
6547836SJohn.Forte@Sun.COM icb->firmware_options[1] = (uint8_t)
6557836SJohn.Forte@Sun.COM (icb->firmware_options[1] & ~BIT_4);
6567836SJohn.Forte@Sun.COM
6577836SJohn.Forte@Sun.COM icb->add_fw_opt[1] = (uint8_t)(icb->add_fw_opt[1] & ~(BIT_5 | BIT_4));
6587836SJohn.Forte@Sun.COM icb->special_options[0] = (uint8_t)(icb->special_options[0] | BIT_1);
6597836SJohn.Forte@Sun.COM
6607836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
6617836SJohn.Forte@Sun.COM if ((icb->special_options[1] & 0x20) == 0) {
6627836SJohn.Forte@Sun.COM EL(ha, "50 ohm is not set\n");
6637836SJohn.Forte@Sun.COM }
6647836SJohn.Forte@Sun.COM }
6657836SJohn.Forte@Sun.COM icb->execution_throttle[0] = 0xff;
6667836SJohn.Forte@Sun.COM icb->execution_throttle[1] = 0xff;
6677836SJohn.Forte@Sun.COM
6687836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
6697836SJohn.Forte@Sun.COM icb->firmware_options[1] = (uint8_t)
6707836SJohn.Forte@Sun.COM (icb->firmware_options[1] | BIT_7 | BIT_6);
6717836SJohn.Forte@Sun.COM icb->add_fw_opt[1] = (uint8_t)
6727836SJohn.Forte@Sun.COM (icb->add_fw_opt[1] | BIT_5 | BIT_4);
6737836SJohn.Forte@Sun.COM }
6747836SJohn.Forte@Sun.COM
6757836SJohn.Forte@Sun.COM /*
6767836SJohn.Forte@Sun.COM * Set host adapter parameters
6777836SJohn.Forte@Sun.COM */
6787836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
6797836SJohn.Forte@Sun.COM ha->nvram_version = nv->nvram_version;
6807836SJohn.Forte@Sun.COM ha->adapter_features = CHAR_TO_SHORT(nv->adapter_features[0],
6817836SJohn.Forte@Sun.COM nv->adapter_features[1]);
6827836SJohn.Forte@Sun.COM
6837836SJohn.Forte@Sun.COM nv->host_p[0] & BIT_4 ? (ha->cfg_flags |= CFG_DISABLE_RISC_CODE_LOAD) :
6847836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_DISABLE_RISC_CODE_LOAD);
6857836SJohn.Forte@Sun.COM nv->host_p[0] & BIT_5 ? (ha->cfg_flags |= CFG_SET_CACHE_LINE_SIZE_1) :
6867836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_SET_CACHE_LINE_SIZE_1);
6877836SJohn.Forte@Sun.COM
6887836SJohn.Forte@Sun.COM nv->host_p[1] & BIT_1 ? (ha->cfg_flags |= CFG_ENABLE_LIP_RESET) :
6897836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET);
6907836SJohn.Forte@Sun.COM nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
6917836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
6927836SJohn.Forte@Sun.COM nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
6937836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
6947836SJohn.Forte@Sun.COM
6957836SJohn.Forte@Sun.COM nv->adapter_features[0] & BIT_3 ?
6967836SJohn.Forte@Sun.COM (ha->cfg_flags |= CFG_MULTI_CHIP_ADAPTER) :
6977836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_MULTI_CHIP_ADAPTER);
6987836SJohn.Forte@Sun.COM
6997836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
7007836SJohn.Forte@Sun.COM
7017836SJohn.Forte@Sun.COM ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
7027836SJohn.Forte@Sun.COM nv->execution_throttle[1]);
7037836SJohn.Forte@Sun.COM ha->loop_reset_delay = nv->reset_delay;
7047836SJohn.Forte@Sun.COM ha->port_down_retry_count = nv->port_down_retry_count;
7057836SJohn.Forte@Sun.COM ha->r_a_tov = (uint16_t)(icb->login_timeout < R_A_TOV_DEFAULT ?
7067836SJohn.Forte@Sun.COM R_A_TOV_DEFAULT : icb->login_timeout);
7077836SJohn.Forte@Sun.COM ha->maximum_luns_per_target = CHAR_TO_SHORT(
7087836SJohn.Forte@Sun.COM nv->maximum_luns_per_target[0], nv->maximum_luns_per_target[1]);
7097836SJohn.Forte@Sun.COM if (ha->maximum_luns_per_target == 0) {
7107836SJohn.Forte@Sun.COM ha->maximum_luns_per_target++;
7117836SJohn.Forte@Sun.COM }
7127836SJohn.Forte@Sun.COM
7137836SJohn.Forte@Sun.COM /*
7147836SJohn.Forte@Sun.COM * Setup ring parameters in initialization control block
7157836SJohn.Forte@Sun.COM */
7167836SJohn.Forte@Sun.COM cnt = REQUEST_ENTRY_CNT;
7177836SJohn.Forte@Sun.COM icb->request_q_length[0] = LSB(cnt);
7187836SJohn.Forte@Sun.COM icb->request_q_length[1] = MSB(cnt);
7197836SJohn.Forte@Sun.COM cnt = RESPONSE_ENTRY_CNT;
7207836SJohn.Forte@Sun.COM icb->response_q_length[0] = LSB(cnt);
7217836SJohn.Forte@Sun.COM icb->response_q_length[1] = MSB(cnt);
7227836SJohn.Forte@Sun.COM
7237836SJohn.Forte@Sun.COM icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
7247836SJohn.Forte@Sun.COM icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
7257836SJohn.Forte@Sun.COM icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
7267836SJohn.Forte@Sun.COM icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
7277836SJohn.Forte@Sun.COM icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
7287836SJohn.Forte@Sun.COM icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
7297836SJohn.Forte@Sun.COM icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
7307836SJohn.Forte@Sun.COM icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
7317836SJohn.Forte@Sun.COM
7327836SJohn.Forte@Sun.COM icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
7337836SJohn.Forte@Sun.COM icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
7347836SJohn.Forte@Sun.COM icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
7357836SJohn.Forte@Sun.COM icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
7367836SJohn.Forte@Sun.COM icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
7377836SJohn.Forte@Sun.COM icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
7387836SJohn.Forte@Sun.COM icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
7397836SJohn.Forte@Sun.COM icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
7407836SJohn.Forte@Sun.COM
7417836SJohn.Forte@Sun.COM /*
7427836SJohn.Forte@Sun.COM * Setup IP initialization control block
7437836SJohn.Forte@Sun.COM */
7447836SJohn.Forte@Sun.COM ip_icb->version = IP_ICB_VERSION;
7457836SJohn.Forte@Sun.COM
7467836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
7477836SJohn.Forte@Sun.COM ip_icb->ip_firmware_options[0] = (uint8_t)
7487836SJohn.Forte@Sun.COM (ip_icb->ip_firmware_options[0] | BIT_2 | BIT_0);
7497836SJohn.Forte@Sun.COM } else {
7507836SJohn.Forte@Sun.COM ip_icb->ip_firmware_options[0] = (uint8_t)
7517836SJohn.Forte@Sun.COM (ip_icb->ip_firmware_options[0] | BIT_2);
7527836SJohn.Forte@Sun.COM }
7537836SJohn.Forte@Sun.COM
7547836SJohn.Forte@Sun.COM cnt = RCVBUF_CONTAINER_CNT;
7557836SJohn.Forte@Sun.COM ip_icb->queue_size[0] = LSB(cnt);
7567836SJohn.Forte@Sun.COM ip_icb->queue_size[1] = MSB(cnt);
7577836SJohn.Forte@Sun.COM
7587836SJohn.Forte@Sun.COM ip_icb->queue_address[0] = LSB(LSW(LSD(ha->rcvbuf_dvma)));
7597836SJohn.Forte@Sun.COM ip_icb->queue_address[1] = MSB(LSW(LSD(ha->rcvbuf_dvma)));
7607836SJohn.Forte@Sun.COM ip_icb->queue_address[2] = LSB(MSW(LSD(ha->rcvbuf_dvma)));
7617836SJohn.Forte@Sun.COM ip_icb->queue_address[3] = MSB(MSW(LSD(ha->rcvbuf_dvma)));
7627836SJohn.Forte@Sun.COM ip_icb->queue_address[4] = LSB(LSW(MSD(ha->rcvbuf_dvma)));
7637836SJohn.Forte@Sun.COM ip_icb->queue_address[5] = MSB(LSW(MSD(ha->rcvbuf_dvma)));
7647836SJohn.Forte@Sun.COM ip_icb->queue_address[6] = LSB(MSW(MSD(ha->rcvbuf_dvma)));
7657836SJohn.Forte@Sun.COM ip_icb->queue_address[7] = MSB(MSW(MSD(ha->rcvbuf_dvma)));
7667836SJohn.Forte@Sun.COM
7677836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
7687836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
7697836SJohn.Forte@Sun.COM } else {
7707836SJohn.Forte@Sun.COM /*EMPTY*/
7717836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
7727836SJohn.Forte@Sun.COM }
7737836SJohn.Forte@Sun.COM return (rval);
7747836SJohn.Forte@Sun.COM }
7757836SJohn.Forte@Sun.COM
7767836SJohn.Forte@Sun.COM /*
7777836SJohn.Forte@Sun.COM * Get NVRAM data word
7787836SJohn.Forte@Sun.COM * Calculates word position in NVRAM and calls request routine to
7797836SJohn.Forte@Sun.COM * get the word from NVRAM.
7807836SJohn.Forte@Sun.COM *
7817836SJohn.Forte@Sun.COM * Input:
7827836SJohn.Forte@Sun.COM * ha = adapter state pointer.
7837836SJohn.Forte@Sun.COM * address = NVRAM word address.
7847836SJohn.Forte@Sun.COM *
7857836SJohn.Forte@Sun.COM * Returns:
7867836SJohn.Forte@Sun.COM * data word.
7877836SJohn.Forte@Sun.COM *
7887836SJohn.Forte@Sun.COM * Context:
7897836SJohn.Forte@Sun.COM * Kernel context.
7907836SJohn.Forte@Sun.COM */
7917836SJohn.Forte@Sun.COM uint16_t
ql_get_nvram_word(ql_adapter_state_t * ha,uint32_t address)7927836SJohn.Forte@Sun.COM ql_get_nvram_word(ql_adapter_state_t *ha, uint32_t address)
7937836SJohn.Forte@Sun.COM {
7947836SJohn.Forte@Sun.COM uint32_t nv_cmd;
7957836SJohn.Forte@Sun.COM uint16_t rval;
7967836SJohn.Forte@Sun.COM
7977836SJohn.Forte@Sun.COM QL_PRINT_4(CE_CONT, "(%d): started\n", ha->instance);
7987836SJohn.Forte@Sun.COM
7997836SJohn.Forte@Sun.COM nv_cmd = address << 16;
8007836SJohn.Forte@Sun.COM nv_cmd = nv_cmd | NV_READ_OP;
8017836SJohn.Forte@Sun.COM
8027836SJohn.Forte@Sun.COM rval = (uint16_t)ql_nvram_request(ha, nv_cmd);
8037836SJohn.Forte@Sun.COM
8047836SJohn.Forte@Sun.COM QL_PRINT_4(CE_CONT, "(%d): NVRAM data = %xh\n", ha->instance, rval);
8057836SJohn.Forte@Sun.COM
8067836SJohn.Forte@Sun.COM return (rval);
8077836SJohn.Forte@Sun.COM }
8087836SJohn.Forte@Sun.COM
8097836SJohn.Forte@Sun.COM /*
8107836SJohn.Forte@Sun.COM * NVRAM request
8117836SJohn.Forte@Sun.COM * Sends read command to NVRAM and gets data from NVRAM.
8127836SJohn.Forte@Sun.COM *
8137836SJohn.Forte@Sun.COM * Input:
8147836SJohn.Forte@Sun.COM * ha = adapter state pointer.
8157836SJohn.Forte@Sun.COM * nv_cmd = Bit 26= start bit
8167836SJohn.Forte@Sun.COM * Bit 25, 24 = opcode
8177836SJohn.Forte@Sun.COM * Bit 23-16 = address
8187836SJohn.Forte@Sun.COM * Bit 15-0 = write data
8197836SJohn.Forte@Sun.COM *
8207836SJohn.Forte@Sun.COM * Returns:
8217836SJohn.Forte@Sun.COM * data word.
8227836SJohn.Forte@Sun.COM *
8237836SJohn.Forte@Sun.COM * Context:
8247836SJohn.Forte@Sun.COM * Kernel context.
8257836SJohn.Forte@Sun.COM */
8267836SJohn.Forte@Sun.COM static uint16_t
ql_nvram_request(ql_adapter_state_t * ha,uint32_t nv_cmd)8277836SJohn.Forte@Sun.COM ql_nvram_request(ql_adapter_state_t *ha, uint32_t nv_cmd)
8287836SJohn.Forte@Sun.COM {
8297836SJohn.Forte@Sun.COM uint8_t cnt;
8307836SJohn.Forte@Sun.COM uint16_t reg_data;
8317836SJohn.Forte@Sun.COM uint16_t data = 0;
8327836SJohn.Forte@Sun.COM
8337836SJohn.Forte@Sun.COM /* Send command to NVRAM. */
8347836SJohn.Forte@Sun.COM
8357836SJohn.Forte@Sun.COM nv_cmd <<= 5;
8367836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 11; cnt++) {
8377836SJohn.Forte@Sun.COM if (nv_cmd & BIT_31) {
8387836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
8397836SJohn.Forte@Sun.COM } else {
8407836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
8417836SJohn.Forte@Sun.COM }
8427836SJohn.Forte@Sun.COM nv_cmd <<= 1;
8437836SJohn.Forte@Sun.COM }
8447836SJohn.Forte@Sun.COM
8457836SJohn.Forte@Sun.COM /* Read data from NVRAM. */
8467836SJohn.Forte@Sun.COM
8477836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 16; cnt++) {
8487836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT+NV_CLOCK);
8497836SJohn.Forte@Sun.COM ql_nv_delay();
8507836SJohn.Forte@Sun.COM data <<= 1;
8517836SJohn.Forte@Sun.COM reg_data = RD16_IO_REG(ha, nvram);
8527836SJohn.Forte@Sun.COM if (reg_data & NV_DATA_IN) {
8537836SJohn.Forte@Sun.COM data = (uint16_t)(data | BIT_0);
8547836SJohn.Forte@Sun.COM }
8557836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT);
8567836SJohn.Forte@Sun.COM ql_nv_delay();
8577836SJohn.Forte@Sun.COM }
8587836SJohn.Forte@Sun.COM
8597836SJohn.Forte@Sun.COM /* Deselect chip. */
8607836SJohn.Forte@Sun.COM
8617836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8627836SJohn.Forte@Sun.COM ql_nv_delay();
8637836SJohn.Forte@Sun.COM
8647836SJohn.Forte@Sun.COM return (data);
8657836SJohn.Forte@Sun.COM }
8667836SJohn.Forte@Sun.COM
8677836SJohn.Forte@Sun.COM void
ql_nv_write(ql_adapter_state_t * ha,uint16_t data)8687836SJohn.Forte@Sun.COM ql_nv_write(ql_adapter_state_t *ha, uint16_t data)
8697836SJohn.Forte@Sun.COM {
8707836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
8717836SJohn.Forte@Sun.COM ql_nv_delay();
8727836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT | NV_CLOCK));
8737836SJohn.Forte@Sun.COM ql_nv_delay();
8747836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, (uint16_t)(data | NV_SELECT));
8757836SJohn.Forte@Sun.COM ql_nv_delay();
8767836SJohn.Forte@Sun.COM }
8777836SJohn.Forte@Sun.COM
8787836SJohn.Forte@Sun.COM void
ql_nv_delay(void)8799446SDaniel.Beauregard@Sun.COM ql_nv_delay(void)
8809446SDaniel.Beauregard@Sun.COM {
8817836SJohn.Forte@Sun.COM drv_usecwait(NV_DELAY_COUNT);
8827836SJohn.Forte@Sun.COM }
8837836SJohn.Forte@Sun.COM
8847836SJohn.Forte@Sun.COM /*
8857836SJohn.Forte@Sun.COM * ql_nvram_24xx_config
8867836SJohn.Forte@Sun.COM * ISP2400 nvram.
8877836SJohn.Forte@Sun.COM *
8887836SJohn.Forte@Sun.COM * Input:
8897836SJohn.Forte@Sun.COM * ha: adapter state pointer.
8907836SJohn.Forte@Sun.COM * ha->hba_buf = request and response rings
8917836SJohn.Forte@Sun.COM *
8927836SJohn.Forte@Sun.COM * Output:
8937836SJohn.Forte@Sun.COM * ha->init_ctrl_blk = initialization control block
8947836SJohn.Forte@Sun.COM * host adapters parameters in host adapter block
8957836SJohn.Forte@Sun.COM *
8967836SJohn.Forte@Sun.COM * Returns:
8977836SJohn.Forte@Sun.COM * ql local function return status code.
8987836SJohn.Forte@Sun.COM *
8997836SJohn.Forte@Sun.COM * Context:
9007836SJohn.Forte@Sun.COM * Kernel context.
9017836SJohn.Forte@Sun.COM */
9027836SJohn.Forte@Sun.COM int
ql_nvram_24xx_config(ql_adapter_state_t * ha)9037836SJohn.Forte@Sun.COM ql_nvram_24xx_config(ql_adapter_state_t *ha)
9047836SJohn.Forte@Sun.COM {
9057836SJohn.Forte@Sun.COM uint32_t index, addr, chksum, saved_chksum;
9067836SJohn.Forte@Sun.COM uint32_t *longptr;
9077836SJohn.Forte@Sun.COM nvram_24xx_t nvram;
9087836SJohn.Forte@Sun.COM int idpromlen;
9097836SJohn.Forte@Sun.COM char idprombuf[32];
9107836SJohn.Forte@Sun.COM caddr_t src, dst;
9117836SJohn.Forte@Sun.COM uint16_t w1;
9127836SJohn.Forte@Sun.COM int rval;
9137836SJohn.Forte@Sun.COM nvram_24xx_t *nv = (nvram_24xx_t *)&nvram;
9147836SJohn.Forte@Sun.COM ql_init_24xx_cb_t *icb =
9157836SJohn.Forte@Sun.COM (ql_init_24xx_cb_t *)&ha->init_ctrl_blk.cb24;
9167836SJohn.Forte@Sun.COM ql_ip_init_24xx_cb_t *ip_icb = &ha->ip_init_ctrl_blk.cb24;
9177836SJohn.Forte@Sun.COM
9187836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
9197836SJohn.Forte@Sun.COM
9207836SJohn.Forte@Sun.COM if ((rval = ql_lock_nvram(ha, &addr, LNF_NVRAM_DATA)) == QL_SUCCESS) {
9217836SJohn.Forte@Sun.COM
9227836SJohn.Forte@Sun.COM /* Get NVRAM data and calculate checksum. */
9237836SJohn.Forte@Sun.COM longptr = (uint32_t *)nv;
9247836SJohn.Forte@Sun.COM chksum = saved_chksum = 0;
9257836SJohn.Forte@Sun.COM for (index = 0; index < sizeof (nvram_24xx_t) / 4; index++) {
9267836SJohn.Forte@Sun.COM rval = ql_24xx_read_flash(ha, addr++, longptr);
9277836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
9287836SJohn.Forte@Sun.COM EL(ha, "24xx_read_flash failed=%xh\n", rval);
9297836SJohn.Forte@Sun.COM break;
9307836SJohn.Forte@Sun.COM }
9317836SJohn.Forte@Sun.COM saved_chksum = chksum;
9327836SJohn.Forte@Sun.COM chksum += *longptr;
9337836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32(longptr);
9347836SJohn.Forte@Sun.COM longptr++;
9357836SJohn.Forte@Sun.COM }
9367836SJohn.Forte@Sun.COM
9377836SJohn.Forte@Sun.COM ql_release_nvram(ha);
9387836SJohn.Forte@Sun.COM }
9397836SJohn.Forte@Sun.COM
9407836SJohn.Forte@Sun.COM /* Bad NVRAM data, set defaults parameters. */
9417836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS || chksum || nv->id[0] != 'I' ||
9427836SJohn.Forte@Sun.COM nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' ||
9437836SJohn.Forte@Sun.COM (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
9447836SJohn.Forte@Sun.COM
9457836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d): NVRAM configuration failed, using "
9467836SJohn.Forte@Sun.COM "driver defaults.", QL_NAME, ha->instance);
9477836SJohn.Forte@Sun.COM
9487836SJohn.Forte@Sun.COM EL(ha, "failed, rval=%xh, checksum=%xh, id=%c%c%c%c, "
9497836SJohn.Forte@Sun.COM "nvram_version=%x\n", rval, chksum, nv->id[0], nv->id[1],
9507836SJohn.Forte@Sun.COM nv->id[2], nv->id[3], CHAR_TO_SHORT(nv->nvram_version[0],
9517836SJohn.Forte@Sun.COM nv->nvram_version[1]));
9527836SJohn.Forte@Sun.COM
9537836SJohn.Forte@Sun.COM saved_chksum = ~saved_chksum + 1;
9547836SJohn.Forte@Sun.COM
9557836SJohn.Forte@Sun.COM (void) ql_flash_errlog(ha, FLASH_ERRLOG_NVRAM_CHKSUM_ERR, 0,
9567836SJohn.Forte@Sun.COM MSW(saved_chksum), LSW(saved_chksum));
9577836SJohn.Forte@Sun.COM
9587836SJohn.Forte@Sun.COM /* Reset NVRAM data. */
9597836SJohn.Forte@Sun.COM bzero((void *)nv, sizeof (nvram_24xx_t));
9607836SJohn.Forte@Sun.COM
9617836SJohn.Forte@Sun.COM /*
9627836SJohn.Forte@Sun.COM * Set default initialization control block.
9637836SJohn.Forte@Sun.COM */
9647836SJohn.Forte@Sun.COM nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
9657836SJohn.Forte@Sun.COM nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
9667836SJohn.Forte@Sun.COM
9677836SJohn.Forte@Sun.COM nv->version[0] = 1;
9687836SJohn.Forte@Sun.COM nv->max_frame_length[1] = 8;
9697836SJohn.Forte@Sun.COM nv->execution_throttle[0] = 16;
97011924SDaniel.Beauregard@Sun.COM nv->exchange_count[0] = 128;
9717836SJohn.Forte@Sun.COM nv->max_luns_per_target[0] = 8;
9727836SJohn.Forte@Sun.COM
9737836SJohn.Forte@Sun.COM idpromlen = 32;
9747836SJohn.Forte@Sun.COM
9757836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
9769156SDaniel.Beauregard@Sun.COM if (rval = ddi_getlongprop_buf(DDI_DEV_T_ANY, ha->dip,
9777836SJohn.Forte@Sun.COM DDI_PROP_CANSLEEP, "idprom", (caddr_t)idprombuf,
9787836SJohn.Forte@Sun.COM &idpromlen) != DDI_PROP_SUCCESS) {
9797836SJohn.Forte@Sun.COM
9807836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d) : Unable to read idprom "
9819156SDaniel.Beauregard@Sun.COM "property, rval=%x", QL_NAME, ha->instance, rval);
9827836SJohn.Forte@Sun.COM
9837836SJohn.Forte@Sun.COM nv->port_name[0] = 33;
9847836SJohn.Forte@Sun.COM nv->port_name[3] = 224;
9857836SJohn.Forte@Sun.COM nv->port_name[4] = 139;
9867836SJohn.Forte@Sun.COM nv->port_name[7] = (uint8_t)
9877836SJohn.Forte@Sun.COM (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
9887836SJohn.Forte@Sun.COM } else {
9897836SJohn.Forte@Sun.COM nv->port_name[2] = idprombuf[2];
9907836SJohn.Forte@Sun.COM nv->port_name[3] = idprombuf[3];
9917836SJohn.Forte@Sun.COM nv->port_name[4] = idprombuf[4];
9927836SJohn.Forte@Sun.COM nv->port_name[5] = idprombuf[5];
9937836SJohn.Forte@Sun.COM nv->port_name[6] = idprombuf[6];
9947836SJohn.Forte@Sun.COM nv->port_name[7] = idprombuf[7];
9957836SJohn.Forte@Sun.COM nv->port_name[0] = (uint8_t)
9967836SJohn.Forte@Sun.COM (NAA_ID_IEEE_EXTENDED << 4 | ha->instance);
9977836SJohn.Forte@Sun.COM }
9987836SJohn.Forte@Sun.COM
9997836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d): Unreliable HBA NVRAM, using default "
10007836SJohn.Forte@Sun.COM "HBA parameters and temporary "
10017836SJohn.Forte@Sun.COM "WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
10027836SJohn.Forte@Sun.COM ha->instance, nv->port_name[0], nv->port_name[1],
10037836SJohn.Forte@Sun.COM nv->port_name[2], nv->port_name[3], nv->port_name[4],
10047836SJohn.Forte@Sun.COM nv->port_name[5], nv->port_name[6], nv->port_name[7]);
10057836SJohn.Forte@Sun.COM
10067836SJohn.Forte@Sun.COM nv->login_retry_count[0] = 8;
10077836SJohn.Forte@Sun.COM
10087836SJohn.Forte@Sun.COM nv->firmware_options_1[0] = BIT_2 | BIT_1;
10097836SJohn.Forte@Sun.COM nv->firmware_options_1[1] = BIT_5;
10107836SJohn.Forte@Sun.COM nv->firmware_options_2[0] = BIT_5;
10117836SJohn.Forte@Sun.COM nv->firmware_options_2[1] = BIT_4;
10127836SJohn.Forte@Sun.COM nv->firmware_options_3[1] = BIT_6;
10137836SJohn.Forte@Sun.COM
10147836SJohn.Forte@Sun.COM /*
10157836SJohn.Forte@Sun.COM * Set default host adapter parameters
10167836SJohn.Forte@Sun.COM */
10177836SJohn.Forte@Sun.COM nv->host_p[0] = BIT_4 | BIT_1;
10187836SJohn.Forte@Sun.COM nv->host_p[1] = BIT_3 | BIT_2;
10197836SJohn.Forte@Sun.COM nv->reset_delay = 5;
10207836SJohn.Forte@Sun.COM nv->max_luns_per_target[0] = 128;
10217836SJohn.Forte@Sun.COM nv->port_down_retry_count[0] = 30;
10227836SJohn.Forte@Sun.COM nv->link_down_timeout[0] = 30;
10237836SJohn.Forte@Sun.COM
102411924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8081)) {
10259446SDaniel.Beauregard@Sun.COM nv->firmware_options_3[2] = BIT_4;
10269446SDaniel.Beauregard@Sun.COM nv->feature_mask_l[0] = 9;
10279446SDaniel.Beauregard@Sun.COM nv->ext_blk.version[0] = 1;
10289446SDaniel.Beauregard@Sun.COM nv->ext_blk.fcf_vlan_match = 1;
10299446SDaniel.Beauregard@Sun.COM nv->ext_blk.fcf_vlan_id[0] = LSB(1002);
10309446SDaniel.Beauregard@Sun.COM nv->ext_blk.fcf_vlan_id[1] = MSB(1002);
103111924SDaniel.Beauregard@Sun.COM nv->fw.isp8001.e_node_mac_addr[1] = 2;
103211924SDaniel.Beauregard@Sun.COM nv->fw.isp8001.e_node_mac_addr[2] = 3;
103311924SDaniel.Beauregard@Sun.COM nv->fw.isp8001.e_node_mac_addr[3] = 4;
103411924SDaniel.Beauregard@Sun.COM nv->fw.isp8001.e_node_mac_addr[4] = MSB(ha->instance);
103511924SDaniel.Beauregard@Sun.COM nv->fw.isp8001.e_node_mac_addr[5] = LSB(ha->instance);
10369446SDaniel.Beauregard@Sun.COM }
10379446SDaniel.Beauregard@Sun.COM
10387836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
10397836SJohn.Forte@Sun.COM }
10407836SJohn.Forte@Sun.COM
10417836SJohn.Forte@Sun.COM /* Check for adapter node name (big endian). */
10427836SJohn.Forte@Sun.COM for (index = 0; index < 8; index++) {
10437836SJohn.Forte@Sun.COM if (nv->node_name[index] != 0) {
10447836SJohn.Forte@Sun.COM break;
10457836SJohn.Forte@Sun.COM }
10467836SJohn.Forte@Sun.COM }
10477836SJohn.Forte@Sun.COM
10487836SJohn.Forte@Sun.COM /* Copy port name if no node name (big endian). */
10497836SJohn.Forte@Sun.COM if (index == 8) {
10507836SJohn.Forte@Sun.COM bcopy((void *)&nv->port_name[0], (void *)&nv->node_name[0], 8);
10517836SJohn.Forte@Sun.COM nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
10527836SJohn.Forte@Sun.COM nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
10537836SJohn.Forte@Sun.COM }
10547836SJohn.Forte@Sun.COM
10557836SJohn.Forte@Sun.COM /* Reset initialization control blocks. */
10567836SJohn.Forte@Sun.COM bzero((void *)icb, sizeof (ql_init_24xx_cb_t));
10577836SJohn.Forte@Sun.COM
10587836SJohn.Forte@Sun.COM /* Get driver properties. */
10597836SJohn.Forte@Sun.COM ql_24xx_properties(ha, nv);
10607836SJohn.Forte@Sun.COM
10617836SJohn.Forte@Sun.COM cmn_err(CE_CONT, "!Qlogic %s(%d) WWPN=%02x%02x%02x%02x"
10627836SJohn.Forte@Sun.COM "%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
10637836SJohn.Forte@Sun.COM QL_NAME, ha->instance, nv->port_name[0], nv->port_name[1],
10647836SJohn.Forte@Sun.COM nv->port_name[2], nv->port_name[3], nv->port_name[4],
10657836SJohn.Forte@Sun.COM nv->port_name[5], nv->port_name[6], nv->port_name[7],
10667836SJohn.Forte@Sun.COM nv->node_name[0], nv->node_name[1], nv->node_name[2],
10677836SJohn.Forte@Sun.COM nv->node_name[3], nv->node_name[4], nv->node_name[5],
10687836SJohn.Forte@Sun.COM nv->node_name[6], nv->node_name[7]);
10697836SJohn.Forte@Sun.COM
10707836SJohn.Forte@Sun.COM /*
10717836SJohn.Forte@Sun.COM * Copy over NVRAM Firmware Initialization Control Block.
10727836SJohn.Forte@Sun.COM */
10737836SJohn.Forte@Sun.COM dst = (caddr_t)icb;
10747836SJohn.Forte@Sun.COM src = (caddr_t)&nv->version;
10757836SJohn.Forte@Sun.COM index = (uint32_t)((uintptr_t)&icb->response_q_inpointer[0] -
10767836SJohn.Forte@Sun.COM (uintptr_t)icb);
10777836SJohn.Forte@Sun.COM while (index--) {
10787836SJohn.Forte@Sun.COM *dst++ = *src++;
10797836SJohn.Forte@Sun.COM }
10807836SJohn.Forte@Sun.COM icb->login_retry_count[0] = nv->login_retry_count[0];
10817836SJohn.Forte@Sun.COM icb->login_retry_count[1] = nv->login_retry_count[1];
10827836SJohn.Forte@Sun.COM icb->link_down_on_nos[0] = nv->link_down_on_nos[0];
10837836SJohn.Forte@Sun.COM icb->link_down_on_nos[1] = nv->link_down_on_nos[1];
10847836SJohn.Forte@Sun.COM
10857836SJohn.Forte@Sun.COM dst = (caddr_t)&icb->interrupt_delay_timer;
10867836SJohn.Forte@Sun.COM src = (caddr_t)&nv->interrupt_delay_timer;
10879446SDaniel.Beauregard@Sun.COM index = (uint32_t)((uintptr_t)&icb->qos -
10887836SJohn.Forte@Sun.COM (uintptr_t)&icb->interrupt_delay_timer);
10897836SJohn.Forte@Sun.COM while (index--) {
10907836SJohn.Forte@Sun.COM *dst++ = *src++;
10917836SJohn.Forte@Sun.COM }
10927836SJohn.Forte@Sun.COM
10937836SJohn.Forte@Sun.COM /*
10947836SJohn.Forte@Sun.COM * Setup driver firmware options.
10957836SJohn.Forte@Sun.COM */
109611924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8081)) {
10979446SDaniel.Beauregard@Sun.COM dst = (caddr_t)icb->enode_mac_addr;
109810240SDaniel.Beauregard@Sun.COM src = (caddr_t)nv->fw.isp8001.e_node_mac_addr;
109910240SDaniel.Beauregard@Sun.COM index = sizeof (nv->fw.isp8001.e_node_mac_addr);
11009446SDaniel.Beauregard@Sun.COM while (index--) {
11019446SDaniel.Beauregard@Sun.COM *dst++ = *src++;
11029446SDaniel.Beauregard@Sun.COM }
11039446SDaniel.Beauregard@Sun.COM dst = (caddr_t)&icb->ext_blk;
11049446SDaniel.Beauregard@Sun.COM src = (caddr_t)&nv->ext_blk;
11059446SDaniel.Beauregard@Sun.COM index = sizeof (ql_ext_icb_8100_t);
11069446SDaniel.Beauregard@Sun.COM while (index--) {
11079446SDaniel.Beauregard@Sun.COM *dst++ = *src++;
11089446SDaniel.Beauregard@Sun.COM }
110910240SDaniel.Beauregard@Sun.COM EL(ha, "e_node_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n",
111010240SDaniel.Beauregard@Sun.COM icb->enode_mac_addr[0], icb->enode_mac_addr[1],
111110240SDaniel.Beauregard@Sun.COM icb->enode_mac_addr[2], icb->enode_mac_addr[3],
111210240SDaniel.Beauregard@Sun.COM icb->enode_mac_addr[4], icb->enode_mac_addr[5]);
11139446SDaniel.Beauregard@Sun.COM } else {
11149446SDaniel.Beauregard@Sun.COM icb->firmware_options_1[0] = (uint8_t)
11159446SDaniel.Beauregard@Sun.COM (icb->firmware_options_1[0] | BIT_1);
11169446SDaniel.Beauregard@Sun.COM icb->firmware_options_1[1] = (uint8_t)
11179446SDaniel.Beauregard@Sun.COM (icb->firmware_options_1[1] | BIT_5 | BIT_2);
11189446SDaniel.Beauregard@Sun.COM icb->firmware_options_3[0] = (uint8_t)
11199446SDaniel.Beauregard@Sun.COM (icb->firmware_options_3[0] | BIT_1);
11209446SDaniel.Beauregard@Sun.COM }
11217836SJohn.Forte@Sun.COM icb->firmware_options_1[0] = (uint8_t)(icb->firmware_options_1[0] &
11227836SJohn.Forte@Sun.COM ~(BIT_5 | BIT_4));
11237836SJohn.Forte@Sun.COM icb->firmware_options_1[1] = (uint8_t)(icb->firmware_options_1[1] |
11249446SDaniel.Beauregard@Sun.COM BIT_6);
11259446SDaniel.Beauregard@Sun.COM icb->firmware_options_2[0] = (uint8_t)(icb->firmware_options_2[0] &
11269446SDaniel.Beauregard@Sun.COM ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
11277836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_ENABLE_FCP_2_SUPPORT)) {
11287836SJohn.Forte@Sun.COM icb->firmware_options_2[1] = (uint8_t)
11297836SJohn.Forte@Sun.COM (icb->firmware_options_2[1] | BIT_4);
11307836SJohn.Forte@Sun.COM } else {
11317836SJohn.Forte@Sun.COM icb->firmware_options_2[1] = (uint8_t)
11327836SJohn.Forte@Sun.COM (icb->firmware_options_2[1] & ~BIT_4);
11337836SJohn.Forte@Sun.COM }
11347836SJohn.Forte@Sun.COM
11357836SJohn.Forte@Sun.COM icb->firmware_options_3[0] = (uint8_t)(icb->firmware_options_3[0] &
11367836SJohn.Forte@Sun.COM ~BIT_7);
11377836SJohn.Forte@Sun.COM
11389446SDaniel.Beauregard@Sun.COM /* enable special N port 2 N port login behaviour */
11399446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_2425)) {
11409446SDaniel.Beauregard@Sun.COM icb->firmware_options_3[1] =
11419446SDaniel.Beauregard@Sun.COM (uint8_t)(icb->firmware_options_3[1] | BIT_0);
11429446SDaniel.Beauregard@Sun.COM }
11439446SDaniel.Beauregard@Sun.COM
11447836SJohn.Forte@Sun.COM icb->execution_throttle[0] = 0xff;
11457836SJohn.Forte@Sun.COM icb->execution_throttle[1] = 0xff;
11467836SJohn.Forte@Sun.COM
11477836SJohn.Forte@Sun.COM /*
11487836SJohn.Forte@Sun.COM * Set host adapter parameters
11497836SJohn.Forte@Sun.COM */
11507836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
11517836SJohn.Forte@Sun.COM ha->nvram_version = CHAR_TO_SHORT(nv->nvram_version[0],
11527836SJohn.Forte@Sun.COM nv->nvram_version[1]);
11537836SJohn.Forte@Sun.COM nv->host_p[1] & BIT_2 ? (ha->cfg_flags |= CFG_ENABLE_FULL_LIP_LOGIN) :
11547836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_FULL_LIP_LOGIN);
11557836SJohn.Forte@Sun.COM nv->host_p[1] & BIT_3 ? (ha->cfg_flags |= CFG_ENABLE_TARGET_RESET) :
11567836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_TARGET_RESET);
115711924SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~(CFG_DISABLE_RISC_CODE_LOAD | CFG_LR_SUPPORT |
11587836SJohn.Forte@Sun.COM CFG_SET_CACHE_LINE_SIZE_1 | CFG_MULTI_CHIP_ADAPTER);
11597836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_64BIT_ADDRESSING;
116011924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_81XX) && nv->enhanced_features[0] & BIT_0) {
116111924SDaniel.Beauregard@Sun.COM ha->cfg_flags |= CFG_LR_SUPPORT;
116211924SDaniel.Beauregard@Sun.COM }
11637836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
11647836SJohn.Forte@Sun.COM
11657836SJohn.Forte@Sun.COM ha->execution_throttle = CHAR_TO_SHORT(nv->execution_throttle[0],
11667836SJohn.Forte@Sun.COM nv->execution_throttle[1]);
11677836SJohn.Forte@Sun.COM ha->loop_reset_delay = nv->reset_delay;
11687836SJohn.Forte@Sun.COM ha->port_down_retry_count = CHAR_TO_SHORT(nv->port_down_retry_count[0],
11697836SJohn.Forte@Sun.COM nv->port_down_retry_count[1]);
11707836SJohn.Forte@Sun.COM w1 = CHAR_TO_SHORT(icb->login_timeout[0], icb->login_timeout[1]);
11717836SJohn.Forte@Sun.COM ha->r_a_tov = (uint16_t)(w1 < R_A_TOV_DEFAULT ? R_A_TOV_DEFAULT : w1);
11727836SJohn.Forte@Sun.COM ha->maximum_luns_per_target = CHAR_TO_SHORT(
11737836SJohn.Forte@Sun.COM nv->max_luns_per_target[0], nv->max_luns_per_target[1]);
11747836SJohn.Forte@Sun.COM if (ha->maximum_luns_per_target == 0) {
11757836SJohn.Forte@Sun.COM ha->maximum_luns_per_target++;
11767836SJohn.Forte@Sun.COM }
11777836SJohn.Forte@Sun.COM
11787836SJohn.Forte@Sun.COM /* ISP2422 Serial Link Control */
11799446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_2422)) {
11809446SDaniel.Beauregard@Sun.COM ha->serdes_param[0] = CHAR_TO_SHORT(nv->fw.isp2400.swing_opt[0],
11819446SDaniel.Beauregard@Sun.COM nv->fw.isp2400.swing_opt[1]);
11829446SDaniel.Beauregard@Sun.COM ha->serdes_param[1] = CHAR_TO_SHORT(nv->fw.isp2400.swing_1g[0],
11839446SDaniel.Beauregard@Sun.COM nv->fw.isp2400.swing_1g[1]);
11849446SDaniel.Beauregard@Sun.COM ha->serdes_param[2] = CHAR_TO_SHORT(nv->fw.isp2400.swing_2g[0],
11859446SDaniel.Beauregard@Sun.COM nv->fw.isp2400.swing_2g[1]);
11869446SDaniel.Beauregard@Sun.COM ha->serdes_param[3] = CHAR_TO_SHORT(nv->fw.isp2400.swing_4g[0],
11879446SDaniel.Beauregard@Sun.COM nv->fw.isp2400.swing_4g[1]);
11889446SDaniel.Beauregard@Sun.COM }
11897836SJohn.Forte@Sun.COM
11907836SJohn.Forte@Sun.COM /*
11917836SJohn.Forte@Sun.COM * Setup ring parameters in initialization control block
11927836SJohn.Forte@Sun.COM */
11937836SJohn.Forte@Sun.COM w1 = REQUEST_ENTRY_CNT;
11947836SJohn.Forte@Sun.COM icb->request_q_length[0] = LSB(w1);
11957836SJohn.Forte@Sun.COM icb->request_q_length[1] = MSB(w1);
11967836SJohn.Forte@Sun.COM w1 = RESPONSE_ENTRY_CNT;
11977836SJohn.Forte@Sun.COM icb->response_q_length[0] = LSB(w1);
11987836SJohn.Forte@Sun.COM icb->response_q_length[1] = MSB(w1);
11997836SJohn.Forte@Sun.COM
12007836SJohn.Forte@Sun.COM icb->request_q_address[0] = LSB(LSW(LSD(ha->request_dvma)));
12017836SJohn.Forte@Sun.COM icb->request_q_address[1] = MSB(LSW(LSD(ha->request_dvma)));
12027836SJohn.Forte@Sun.COM icb->request_q_address[2] = LSB(MSW(LSD(ha->request_dvma)));
12037836SJohn.Forte@Sun.COM icb->request_q_address[3] = MSB(MSW(LSD(ha->request_dvma)));
12047836SJohn.Forte@Sun.COM icb->request_q_address[4] = LSB(LSW(MSD(ha->request_dvma)));
12057836SJohn.Forte@Sun.COM icb->request_q_address[5] = MSB(LSW(MSD(ha->request_dvma)));
12067836SJohn.Forte@Sun.COM icb->request_q_address[6] = LSB(MSW(MSD(ha->request_dvma)));
12077836SJohn.Forte@Sun.COM icb->request_q_address[7] = MSB(MSW(MSD(ha->request_dvma)));
12087836SJohn.Forte@Sun.COM
12097836SJohn.Forte@Sun.COM icb->response_q_address[0] = LSB(LSW(LSD(ha->response_dvma)));
12107836SJohn.Forte@Sun.COM icb->response_q_address[1] = MSB(LSW(LSD(ha->response_dvma)));
12117836SJohn.Forte@Sun.COM icb->response_q_address[2] = LSB(MSW(LSD(ha->response_dvma)));
12127836SJohn.Forte@Sun.COM icb->response_q_address[3] = MSB(MSW(LSD(ha->response_dvma)));
12137836SJohn.Forte@Sun.COM icb->response_q_address[4] = LSB(LSW(MSD(ha->response_dvma)));
12147836SJohn.Forte@Sun.COM icb->response_q_address[5] = MSB(LSW(MSD(ha->response_dvma)));
12157836SJohn.Forte@Sun.COM icb->response_q_address[6] = LSB(MSW(MSD(ha->response_dvma)));
12167836SJohn.Forte@Sun.COM icb->response_q_address[7] = MSB(MSW(MSD(ha->response_dvma)));
12177836SJohn.Forte@Sun.COM
12187836SJohn.Forte@Sun.COM /*
12197836SJohn.Forte@Sun.COM * Setup IP initialization control block
12207836SJohn.Forte@Sun.COM */
12217836SJohn.Forte@Sun.COM ip_icb->version = IP_ICB_24XX_VERSION;
12227836SJohn.Forte@Sun.COM
12237836SJohn.Forte@Sun.COM ip_icb->ip_firmware_options[0] = (uint8_t)
12247836SJohn.Forte@Sun.COM (ip_icb->ip_firmware_options[0] | BIT_2);
12257836SJohn.Forte@Sun.COM
12267836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
12277836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
12287836SJohn.Forte@Sun.COM } else {
12297836SJohn.Forte@Sun.COM /*EMPTY*/
12307836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
12317836SJohn.Forte@Sun.COM }
12327836SJohn.Forte@Sun.COM return (rval);
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM /*
12367836SJohn.Forte@Sun.COM * ql_lock_nvram
12377836SJohn.Forte@Sun.COM * Locks NVRAM access and returns starting address of NVRAM.
12387836SJohn.Forte@Sun.COM *
12397836SJohn.Forte@Sun.COM * Input:
12407836SJohn.Forte@Sun.COM * ha: adapter state pointer.
12417836SJohn.Forte@Sun.COM * addr: pointer for start address.
12427836SJohn.Forte@Sun.COM * flags: Are mutually exclusive:
12437836SJohn.Forte@Sun.COM * LNF_NVRAM_DATA --> get nvram
12447836SJohn.Forte@Sun.COM * LNF_VPD_DATA --> get vpd data (24/25xx only).
12457836SJohn.Forte@Sun.COM *
12467836SJohn.Forte@Sun.COM * Returns:
12477836SJohn.Forte@Sun.COM * ql local function return status code.
12487836SJohn.Forte@Sun.COM *
12497836SJohn.Forte@Sun.COM * Context:
12507836SJohn.Forte@Sun.COM * Kernel context.
12517836SJohn.Forte@Sun.COM */
12527836SJohn.Forte@Sun.COM int
ql_lock_nvram(ql_adapter_state_t * ha,uint32_t * addr,uint32_t flags)12537836SJohn.Forte@Sun.COM ql_lock_nvram(ql_adapter_state_t *ha, uint32_t *addr, uint32_t flags)
12547836SJohn.Forte@Sun.COM {
12557836SJohn.Forte@Sun.COM int i;
12567836SJohn.Forte@Sun.COM
12577836SJohn.Forte@Sun.COM if ((flags & LNF_NVRAM_DATA) && (flags & LNF_VPD_DATA)) {
12587836SJohn.Forte@Sun.COM EL(ha, "invalid options for function");
12597836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
12607836SJohn.Forte@Sun.COM }
12617836SJohn.Forte@Sun.COM
12627836SJohn.Forte@Sun.COM if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
12637836SJohn.Forte@Sun.COM if ((flags & LNF_NVRAM_DATA) == 0) {
12647836SJohn.Forte@Sun.COM EL(ha, "invalid 2312/2322 option for HBA");
12657836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
12667836SJohn.Forte@Sun.COM }
12677836SJohn.Forte@Sun.COM
12687836SJohn.Forte@Sun.COM /* if function number is non-zero, then adjust offset */
12699446SDaniel.Beauregard@Sun.COM *addr = ha->flash_nvram_addr;
12707836SJohn.Forte@Sun.COM
12717836SJohn.Forte@Sun.COM /* Try to get resource lock. Wait for 10 seconds max */
12727836SJohn.Forte@Sun.COM for (i = 0; i < 10000; i++) {
12737836SJohn.Forte@Sun.COM /* if nvram busy bit is reset, acquire sema */
12747836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, nvram) & 0x8000) == 0) {
12757836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, host_to_host_sema, 1);
12767836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
12777836SJohn.Forte@Sun.COM if (RD16_IO_REG(ha, host_to_host_sema) & 1) {
12787836SJohn.Forte@Sun.COM break;
12797836SJohn.Forte@Sun.COM }
12807836SJohn.Forte@Sun.COM }
12817836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
12827836SJohn.Forte@Sun.COM }
12837836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, host_to_host_sema) & 1) == 0) {
12847836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d): unable to get NVRAM lock",
12857836SJohn.Forte@Sun.COM QL_NAME, ha->instance);
12867836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
12877836SJohn.Forte@Sun.COM }
12887836SJohn.Forte@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_2422)) {
12897836SJohn.Forte@Sun.COM if (flags & LNF_VPD_DATA) {
12909446SDaniel.Beauregard@Sun.COM *addr = NVRAM_DATA_ADDR | ha->flash_vpd_addr;
12917836SJohn.Forte@Sun.COM } else if (flags & LNF_NVRAM_DATA) {
12929446SDaniel.Beauregard@Sun.COM *addr = NVRAM_DATA_ADDR | ha->flash_nvram_addr;
12937836SJohn.Forte@Sun.COM } else {
12949446SDaniel.Beauregard@Sun.COM EL(ha, "invalid 2422 option for HBA");
12957836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
12967836SJohn.Forte@Sun.COM }
12977836SJohn.Forte@Sun.COM
12987836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
129911924SDaniel.Beauregard@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_258081)) {
13007836SJohn.Forte@Sun.COM if (flags & LNF_VPD_DATA) {
13019446SDaniel.Beauregard@Sun.COM *addr = ha->flash_data_addr | ha->flash_vpd_addr;
13027836SJohn.Forte@Sun.COM } else if (flags & LNF_NVRAM_DATA) {
13039446SDaniel.Beauregard@Sun.COM *addr = ha->flash_data_addr | ha->flash_nvram_addr;
13047836SJohn.Forte@Sun.COM } else {
13059446SDaniel.Beauregard@Sun.COM EL(ha, "invalid 2581 option for HBA");
13067836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
13077836SJohn.Forte@Sun.COM }
13087836SJohn.Forte@Sun.COM
13097836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
13107836SJohn.Forte@Sun.COM } else {
13117836SJohn.Forte@Sun.COM if ((flags & LNF_NVRAM_DATA) == 0) {
13127836SJohn.Forte@Sun.COM EL(ha, "invalid option for HBA");
13137836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
13147836SJohn.Forte@Sun.COM }
13157836SJohn.Forte@Sun.COM *addr = 0;
13167836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
13177836SJohn.Forte@Sun.COM }
13187836SJohn.Forte@Sun.COM
13197836SJohn.Forte@Sun.COM return (QL_SUCCESS);
13207836SJohn.Forte@Sun.COM }
13217836SJohn.Forte@Sun.COM
13227836SJohn.Forte@Sun.COM /*
13237836SJohn.Forte@Sun.COM * ql_release_nvram
13247836SJohn.Forte@Sun.COM * Releases NVRAM access.
13257836SJohn.Forte@Sun.COM *
13267836SJohn.Forte@Sun.COM * Input:
13277836SJohn.Forte@Sun.COM * ha: adapter state pointer.
13287836SJohn.Forte@Sun.COM *
13297836SJohn.Forte@Sun.COM * Context:
13307836SJohn.Forte@Sun.COM * Kernel context.
13317836SJohn.Forte@Sun.COM */
13327836SJohn.Forte@Sun.COM void
ql_release_nvram(ql_adapter_state_t * ha)13337836SJohn.Forte@Sun.COM ql_release_nvram(ql_adapter_state_t *ha)
13347836SJohn.Forte@Sun.COM {
13357836SJohn.Forte@Sun.COM if (ha->device_id == 0x2312 || ha->device_id == 0x2322) {
13367836SJohn.Forte@Sun.COM /* Release resource lock */
13377836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, host_to_host_sema, 0);
13387836SJohn.Forte@Sun.COM } else {
13397836SJohn.Forte@Sun.COM GLOBAL_HW_UNLOCK();
13407836SJohn.Forte@Sun.COM }
13417836SJohn.Forte@Sun.COM }
13427836SJohn.Forte@Sun.COM
13437836SJohn.Forte@Sun.COM /*
13447836SJohn.Forte@Sun.COM * ql_23_properties
13457836SJohn.Forte@Sun.COM * Copies driver properties to NVRAM or adapter structure.
13467836SJohn.Forte@Sun.COM *
13477836SJohn.Forte@Sun.COM * Driver properties are by design global variables and hidden
13487836SJohn.Forte@Sun.COM * completely from administrators. Knowledgeable folks can
13497836SJohn.Forte@Sun.COM * override the default values using driver.conf
13507836SJohn.Forte@Sun.COM *
13517836SJohn.Forte@Sun.COM * Input:
13527836SJohn.Forte@Sun.COM * ha: adapter state pointer.
13537836SJohn.Forte@Sun.COM * nv: NVRAM structure pointer.
13547836SJohn.Forte@Sun.COM *
13557836SJohn.Forte@Sun.COM * Context:
13567836SJohn.Forte@Sun.COM * Kernel context.
13577836SJohn.Forte@Sun.COM */
13587836SJohn.Forte@Sun.COM static void
ql_23_properties(ql_adapter_state_t * ha,nvram_t * nv)13597836SJohn.Forte@Sun.COM ql_23_properties(ql_adapter_state_t *ha, nvram_t *nv)
13607836SJohn.Forte@Sun.COM {
13617836SJohn.Forte@Sun.COM uint32_t data, cnt;
13627836SJohn.Forte@Sun.COM
13637836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
13647836SJohn.Forte@Sun.COM
13657836SJohn.Forte@Sun.COM /* Get frame payload size. */
13667836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
13677836SJohn.Forte@Sun.COM data = 2048;
13687836SJohn.Forte@Sun.COM }
13697836SJohn.Forte@Sun.COM if (data == 512 || data == 1024 || data == 2048) {
13707836SJohn.Forte@Sun.COM nv->max_frame_length[0] = LSB(data);
13717836SJohn.Forte@Sun.COM nv->max_frame_length[1] = MSB(data);
13727836SJohn.Forte@Sun.COM } else {
13737836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'max-frame-length': "
13747836SJohn.Forte@Sun.COM "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
13757836SJohn.Forte@Sun.COM nv->max_frame_length[0], nv->max_frame_length[1]));
13767836SJohn.Forte@Sun.COM }
13777836SJohn.Forte@Sun.COM
13787836SJohn.Forte@Sun.COM /* Get max IOCB allocation. */
13797836SJohn.Forte@Sun.COM nv->max_iocb_allocation[0] = 0;
13807836SJohn.Forte@Sun.COM nv->max_iocb_allocation[1] = 1;
13817836SJohn.Forte@Sun.COM
13827836SJohn.Forte@Sun.COM /* Get execution throttle. */
13837836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
13847836SJohn.Forte@Sun.COM data = 32;
13857836SJohn.Forte@Sun.COM }
13867836SJohn.Forte@Sun.COM if (data != 0 && data < 65536) {
13877836SJohn.Forte@Sun.COM nv->execution_throttle[0] = LSB(data);
13887836SJohn.Forte@Sun.COM nv->execution_throttle[1] = MSB(data);
13897836SJohn.Forte@Sun.COM } else {
13907836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'execution-throttle': "
13917836SJohn.Forte@Sun.COM "%d; using nvram default of %d\n", data, CHAR_TO_SHORT(
13927836SJohn.Forte@Sun.COM nv->execution_throttle[0], nv->execution_throttle[1]));
13937836SJohn.Forte@Sun.COM }
13947836SJohn.Forte@Sun.COM
13957836SJohn.Forte@Sun.COM /* Get Login timeout. */
13967836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
13977836SJohn.Forte@Sun.COM data = 3;
13987836SJohn.Forte@Sun.COM }
13997836SJohn.Forte@Sun.COM if (data < 256) {
14007836SJohn.Forte@Sun.COM nv->login_timeout = (uint8_t)data;
14017836SJohn.Forte@Sun.COM } else {
14027836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'login-timeout': "
14037836SJohn.Forte@Sun.COM "%d; using nvram value of %d\n", data, nv->login_timeout);
14047836SJohn.Forte@Sun.COM }
14057836SJohn.Forte@Sun.COM
14067836SJohn.Forte@Sun.COM /* Get retry count. */
14077836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
14087836SJohn.Forte@Sun.COM data = 4;
14097836SJohn.Forte@Sun.COM }
14107836SJohn.Forte@Sun.COM if (data < 256) {
14117836SJohn.Forte@Sun.COM nv->login_retry_count = (uint8_t)data;
14127836SJohn.Forte@Sun.COM } else {
14137836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'login-retry-count': "
14147836SJohn.Forte@Sun.COM "%d; using nvram value of %d\n", data,
14157836SJohn.Forte@Sun.COM nv->login_retry_count);
14167836SJohn.Forte@Sun.COM }
14177836SJohn.Forte@Sun.COM
14187836SJohn.Forte@Sun.COM /* Get adapter hard loop ID enable. */
14197836SJohn.Forte@Sun.COM data = ql_get_prop(ha, "enable-adapter-hard-loop-ID");
14207836SJohn.Forte@Sun.COM if (data == 0) {
14217836SJohn.Forte@Sun.COM nv->firmware_options[0] =
14227836SJohn.Forte@Sun.COM (uint8_t)(nv->firmware_options[0] & ~BIT_0);
14237836SJohn.Forte@Sun.COM } else if (data == 1) {
14247836SJohn.Forte@Sun.COM nv->firmware_options[0] =
14257836SJohn.Forte@Sun.COM (uint8_t)(nv->firmware_options[0] | BIT_0);
14267836SJohn.Forte@Sun.COM } else if (data != 0xffffffff) {
14277836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
14287836SJohn.Forte@Sun.COM "'enable-adapter-hard-loop-ID': %d; using nvram value "
14297836SJohn.Forte@Sun.COM "of %d\n", data, nv->firmware_options[0] & BIT_0 ? 1 : 0);
14307836SJohn.Forte@Sun.COM }
14317836SJohn.Forte@Sun.COM
14327836SJohn.Forte@Sun.COM /* Get adapter hard loop ID. */
14337836SJohn.Forte@Sun.COM data = ql_get_prop(ha, "adapter-hard-loop-ID");
14347836SJohn.Forte@Sun.COM if (data < 126) {
14357836SJohn.Forte@Sun.COM nv->hard_address[0] = (uint8_t)data;
14367836SJohn.Forte@Sun.COM } else if (data != 0xffffffff) {
14377836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'adapter-hard-loop-ID': "
14389156SDaniel.Beauregard@Sun.COM "%d; using nvram value of %d\n",
14399156SDaniel.Beauregard@Sun.COM data, nv->hard_address[0]);
14407836SJohn.Forte@Sun.COM }
14417836SJohn.Forte@Sun.COM
14427836SJohn.Forte@Sun.COM /* Get LIP reset. */
14437836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
14447836SJohn.Forte@Sun.COM 0xffffffff) {
14457836SJohn.Forte@Sun.COM data = 0;
14467836SJohn.Forte@Sun.COM }
14477836SJohn.Forte@Sun.COM if (data == 0) {
14487836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_1);
14497836SJohn.Forte@Sun.COM } else if (data == 1) {
14507836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_1);
14517836SJohn.Forte@Sun.COM } else {
14527836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
14537836SJohn.Forte@Sun.COM "'enable-LIP-reset-on-bus-reset': %d; using nvram value "
14547836SJohn.Forte@Sun.COM "of %d\n", data, nv->host_p[1] & BIT_1 ? 1 : 0);
14557836SJohn.Forte@Sun.COM }
14567836SJohn.Forte@Sun.COM
14577836SJohn.Forte@Sun.COM /* Get LIP full login. */
14587836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
14597836SJohn.Forte@Sun.COM 0xffffffff) {
14607836SJohn.Forte@Sun.COM data = 1;
14617836SJohn.Forte@Sun.COM }
14627836SJohn.Forte@Sun.COM if (data == 0) {
14637836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
14647836SJohn.Forte@Sun.COM } else if (data == 1) {
14657836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
14667836SJohn.Forte@Sun.COM } else {
14677836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
14687836SJohn.Forte@Sun.COM "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
14697836SJohn.Forte@Sun.COM "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
14707836SJohn.Forte@Sun.COM }
14717836SJohn.Forte@Sun.COM
14727836SJohn.Forte@Sun.COM /* Get target reset. */
14737836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
14747836SJohn.Forte@Sun.COM 0xffffffff) {
14757836SJohn.Forte@Sun.COM data = 0;
14767836SJohn.Forte@Sun.COM }
14777836SJohn.Forte@Sun.COM if (data == 0) {
14787836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
14797836SJohn.Forte@Sun.COM } else if (data == 1) {
14807836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
14817836SJohn.Forte@Sun.COM } else {
14827836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
14837836SJohn.Forte@Sun.COM "'enable-target-reset-on-bus-reset': %d; using nvram "
14847836SJohn.Forte@Sun.COM "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
14857836SJohn.Forte@Sun.COM }
14867836SJohn.Forte@Sun.COM
14877836SJohn.Forte@Sun.COM /* Get reset delay. */
14887836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
14897836SJohn.Forte@Sun.COM data = 5;
14907836SJohn.Forte@Sun.COM }
14917836SJohn.Forte@Sun.COM if (data != 0 && data < 256) {
14927836SJohn.Forte@Sun.COM nv->reset_delay = (uint8_t)data;
14937836SJohn.Forte@Sun.COM } else {
14947836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'reset-delay': %d; "
14957836SJohn.Forte@Sun.COM "using nvram value of %d", data, nv->reset_delay);
14967836SJohn.Forte@Sun.COM }
14977836SJohn.Forte@Sun.COM
14987836SJohn.Forte@Sun.COM /* Get port down retry count. */
14997836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
15007836SJohn.Forte@Sun.COM data = 8;
15017836SJohn.Forte@Sun.COM }
15027836SJohn.Forte@Sun.COM if (data < 256) {
15037836SJohn.Forte@Sun.COM nv->port_down_retry_count = (uint8_t)data;
15047836SJohn.Forte@Sun.COM } else {
15057836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'port-down-retry-count':"
15067836SJohn.Forte@Sun.COM " %d; using nvram value of %d\n", data,
15077836SJohn.Forte@Sun.COM nv->port_down_retry_count);
15087836SJohn.Forte@Sun.COM }
15097836SJohn.Forte@Sun.COM
15107836SJohn.Forte@Sun.COM /* Get connection mode setting. */
15117836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "connection-options")) == 0xffffffff) {
15127836SJohn.Forte@Sun.COM data = 2;
15137836SJohn.Forte@Sun.COM }
15147836SJohn.Forte@Sun.COM cnt = CFG_IST(ha, CFG_CTRL_2200) ? 3 : 2;
15157836SJohn.Forte@Sun.COM if (data <= cnt) {
15167836SJohn.Forte@Sun.COM nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] &
15177836SJohn.Forte@Sun.COM ~(BIT_6 | BIT_5 | BIT_4));
15187836SJohn.Forte@Sun.COM nv->add_fw_opt[0] = (uint8_t)(nv->add_fw_opt[0] |
15197836SJohn.Forte@Sun.COM (uint8_t)(data << 4));
15207836SJohn.Forte@Sun.COM } else {
15217836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'connection-options': "
15227836SJohn.Forte@Sun.COM "%d; using nvram value of %d\n", data,
15237836SJohn.Forte@Sun.COM (nv->add_fw_opt[0] >> 4) & 0x3);
15247836SJohn.Forte@Sun.COM }
15257836SJohn.Forte@Sun.COM
15267836SJohn.Forte@Sun.COM /* Get data rate setting. */
15277836SJohn.Forte@Sun.COM if ((CFG_IST(ha, CFG_CTRL_2200)) == 0) {
15287836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
15297836SJohn.Forte@Sun.COM data = 2;
15307836SJohn.Forte@Sun.COM }
15317836SJohn.Forte@Sun.COM if (data < 3) {
15327836SJohn.Forte@Sun.COM nv->special_options[1] = (uint8_t)
15337836SJohn.Forte@Sun.COM (nv->special_options[1] & 0x3f);
15347836SJohn.Forte@Sun.COM nv->special_options[1] = (uint8_t)
15357836SJohn.Forte@Sun.COM (nv->special_options[1] | (uint8_t)(data << 6));
15367836SJohn.Forte@Sun.COM } else {
15377836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'fc-data-rate': "
15387836SJohn.Forte@Sun.COM "%d; using nvram value of %d\n", data,
15397836SJohn.Forte@Sun.COM (nv->special_options[1] >> 6) & 0x3);
15407836SJohn.Forte@Sun.COM }
15417836SJohn.Forte@Sun.COM }
15427836SJohn.Forte@Sun.COM
15437836SJohn.Forte@Sun.COM /* Get adapter id string for Sun branded 23xx only */
15447836SJohn.Forte@Sun.COM if ((CFG_IST(ha, CFG_CTRL_2300)) && nv->adapInfo[0] != 0) {
15457836SJohn.Forte@Sun.COM (void) snprintf((int8_t *)ha->adapInfo, 16, "%s",
15467836SJohn.Forte@Sun.COM nv->adapInfo);
15477836SJohn.Forte@Sun.COM }
15487836SJohn.Forte@Sun.COM
15497836SJohn.Forte@Sun.COM /* Get IP FW container count. */
15507836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb.cc[0] = LSB(ql_ip_buffer_count);
15517836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb.cc[1] = MSB(ql_ip_buffer_count);
15527836SJohn.Forte@Sun.COM
15537836SJohn.Forte@Sun.COM /* Get IP low water mark. */
15547836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb.low_water_mark[0] = LSB(ql_ip_low_water);
15557836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb.low_water_mark[1] = MSB(ql_ip_low_water);
15567836SJohn.Forte@Sun.COM
15577836SJohn.Forte@Sun.COM /* Get IP fast register post count. */
15587836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb.fast_post_reg_count[0] =
15597836SJohn.Forte@Sun.COM ql_ip_fast_post_count;
15607836SJohn.Forte@Sun.COM
15617836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
15627836SJohn.Forte@Sun.COM
15637836SJohn.Forte@Sun.COM ql_common_properties(ha);
15647836SJohn.Forte@Sun.COM
15657836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
15667836SJohn.Forte@Sun.COM
15677836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
15687836SJohn.Forte@Sun.COM }
15697836SJohn.Forte@Sun.COM
15707836SJohn.Forte@Sun.COM /*
15717836SJohn.Forte@Sun.COM * ql_common_properties
15727836SJohn.Forte@Sun.COM * Driver properties adapter structure.
15737836SJohn.Forte@Sun.COM *
15747836SJohn.Forte@Sun.COM * Driver properties are by design global variables and hidden
15757836SJohn.Forte@Sun.COM * completely from administrators. Knowledgeable folks can
15767836SJohn.Forte@Sun.COM * override the default values using driver.conf
15777836SJohn.Forte@Sun.COM *
15787836SJohn.Forte@Sun.COM * Input:
15797836SJohn.Forte@Sun.COM * ha: adapter state pointer.
15807836SJohn.Forte@Sun.COM *
15817836SJohn.Forte@Sun.COM * Context:
15827836SJohn.Forte@Sun.COM * Kernel context.
15837836SJohn.Forte@Sun.COM */
15847836SJohn.Forte@Sun.COM void
ql_common_properties(ql_adapter_state_t * ha)15857836SJohn.Forte@Sun.COM ql_common_properties(ql_adapter_state_t *ha)
15867836SJohn.Forte@Sun.COM {
15877836SJohn.Forte@Sun.COM uint32_t data;
15887836SJohn.Forte@Sun.COM
15897836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
15907836SJohn.Forte@Sun.COM
15919156SDaniel.Beauregard@Sun.COM /* Get extended logging trace buffer size. */
15929156SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "set-ext-log-buffer-size")) !=
15939156SDaniel.Beauregard@Sun.COM 0xffffffff && data != 0) {
15949156SDaniel.Beauregard@Sun.COM char *new_trace;
15959156SDaniel.Beauregard@Sun.COM uint32_t new_size;
15969156SDaniel.Beauregard@Sun.COM
15979156SDaniel.Beauregard@Sun.COM if (ha->el_trace_desc->trace_buffer != NULL) {
15989156SDaniel.Beauregard@Sun.COM new_size = 1024 * data;
15999156SDaniel.Beauregard@Sun.COM new_trace = (char *)kmem_zalloc(new_size, KM_SLEEP);
16009156SDaniel.Beauregard@Sun.COM
16019156SDaniel.Beauregard@Sun.COM if (new_trace == NULL) {
16029156SDaniel.Beauregard@Sun.COM cmn_err(CE_WARN, "%s(%d): can't get new"
16039156SDaniel.Beauregard@Sun.COM " trace buffer",
16049156SDaniel.Beauregard@Sun.COM QL_NAME, ha->instance);
16059156SDaniel.Beauregard@Sun.COM } else {
16069156SDaniel.Beauregard@Sun.COM /* free the previous */
16079156SDaniel.Beauregard@Sun.COM kmem_free(ha->el_trace_desc->trace_buffer,
16089156SDaniel.Beauregard@Sun.COM ha->el_trace_desc->trace_buffer_size);
16099156SDaniel.Beauregard@Sun.COM /* Use the new one */
16109156SDaniel.Beauregard@Sun.COM ha->el_trace_desc->trace_buffer = new_trace;
16119156SDaniel.Beauregard@Sun.COM ha->el_trace_desc->trace_buffer_size = new_size;
16129156SDaniel.Beauregard@Sun.COM }
16139156SDaniel.Beauregard@Sun.COM }
16149156SDaniel.Beauregard@Sun.COM
16159156SDaniel.Beauregard@Sun.COM }
16169156SDaniel.Beauregard@Sun.COM
16179156SDaniel.Beauregard@Sun.COM /* Get extended logging enable. */
16189156SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "extended-logging")) == 0xffffffff ||
16199156SDaniel.Beauregard@Sun.COM data == 0) {
16209156SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
16219156SDaniel.Beauregard@Sun.COM } else if (data == 1) {
16229156SDaniel.Beauregard@Sun.COM ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
16239156SDaniel.Beauregard@Sun.COM } else {
16249156SDaniel.Beauregard@Sun.COM EL(ha, "invalid parameter value for 'extended-logging': %d;"
16259156SDaniel.Beauregard@Sun.COM " using default value of 0\n", data);
16269156SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING;
16279156SDaniel.Beauregard@Sun.COM }
16289156SDaniel.Beauregard@Sun.COM
16299156SDaniel.Beauregard@Sun.COM /* Get extended logging trace disable. */
16309156SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "disable-extended-logging-trace")) ==
16319156SDaniel.Beauregard@Sun.COM 0xffffffff || data == 0) {
16329156SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE;
16339156SDaniel.Beauregard@Sun.COM } else if (data == 1) {
16349156SDaniel.Beauregard@Sun.COM ha->cfg_flags |= CFG_DISABLE_EXTENDED_LOGGING_TRACE;
16359156SDaniel.Beauregard@Sun.COM } else {
16369156SDaniel.Beauregard@Sun.COM EL(ha, "invalid parameter value for "
16379156SDaniel.Beauregard@Sun.COM "'disable-extended-logging-trace': %d;"
16389156SDaniel.Beauregard@Sun.COM " using default value of 0\n", data);
16399156SDaniel.Beauregard@Sun.COM ha->cfg_flags &= ~CFG_DISABLE_EXTENDED_LOGGING_TRACE;
16409156SDaniel.Beauregard@Sun.COM }
16419156SDaniel.Beauregard@Sun.COM
16427836SJohn.Forte@Sun.COM /* Get FCP 2 Error Recovery. */
16437836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-FCP-2-error-recovery")) ==
16447836SJohn.Forte@Sun.COM 0xffffffff || data == 1) {
16457836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
16467836SJohn.Forte@Sun.COM } else if (data == 0) {
16477836SJohn.Forte@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_FCP_2_SUPPORT;
16487836SJohn.Forte@Sun.COM } else {
16497836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
16507836SJohn.Forte@Sun.COM "'enable-FCP-2-error-recovery': %d; using nvram value of "
16517836SJohn.Forte@Sun.COM "1\n", data);
16527836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_FCP_2_SUPPORT;
16537836SJohn.Forte@Sun.COM }
16547836SJohn.Forte@Sun.COM
16557836SJohn.Forte@Sun.COM #ifdef QL_DEBUG_LEVEL_2
16567836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING;
16577836SJohn.Forte@Sun.COM #endif
16587836SJohn.Forte@Sun.COM
16597836SJohn.Forte@Sun.COM /* Get port down retry delay. */
16607836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "port-down-retry-delay")) == 0xffffffff) {
16617836SJohn.Forte@Sun.COM ha->port_down_retry_delay = PORT_RETRY_TIME;
16627836SJohn.Forte@Sun.COM } else if (data < 256) {
16637836SJohn.Forte@Sun.COM ha->port_down_retry_delay = (uint8_t)data;
16647836SJohn.Forte@Sun.COM } else {
16657836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'port-down-retry-delay':"
16667836SJohn.Forte@Sun.COM " %d; using default value of %d", data, PORT_RETRY_TIME);
16677836SJohn.Forte@Sun.COM ha->port_down_retry_delay = PORT_RETRY_TIME;
16687836SJohn.Forte@Sun.COM }
16697836SJohn.Forte@Sun.COM
16707836SJohn.Forte@Sun.COM /* Get queue full retry count. */
16717836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "queue-full-retry-count")) == 0xffffffff) {
16727836SJohn.Forte@Sun.COM ha->qfull_retry_count = 16;
16737836SJohn.Forte@Sun.COM } else if (data < 256) {
16747836SJohn.Forte@Sun.COM ha->qfull_retry_count = (uint8_t)data;
16757836SJohn.Forte@Sun.COM } else {
16767836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'queue-full-retry-count':"
16777836SJohn.Forte@Sun.COM " %d; using default value of 16", data);
16787836SJohn.Forte@Sun.COM ha->qfull_retry_count = 16;
16797836SJohn.Forte@Sun.COM }
16807836SJohn.Forte@Sun.COM
16817836SJohn.Forte@Sun.COM /* Get queue full retry delay. */
16827836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "queue-full-retry-delay")) == 0xffffffff) {
16837836SJohn.Forte@Sun.COM ha->qfull_retry_delay = PORT_RETRY_TIME;
16847836SJohn.Forte@Sun.COM } else if (data < 256) {
16857836SJohn.Forte@Sun.COM ha->qfull_retry_delay = (uint8_t)data;
16867836SJohn.Forte@Sun.COM } else {
16877836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'queue-full-retry-delay':"
16887836SJohn.Forte@Sun.COM " %d; using default value of %d", data, PORT_RETRY_TIME);
16897836SJohn.Forte@Sun.COM ha->qfull_retry_delay = PORT_RETRY_TIME;
16907836SJohn.Forte@Sun.COM }
16917836SJohn.Forte@Sun.COM
16927836SJohn.Forte@Sun.COM /* Get loop down timeout. */
16937836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "link-down-timeout")) == 0xffffffff) {
16947836SJohn.Forte@Sun.COM data = 0;
16957836SJohn.Forte@Sun.COM } else if (data > 255) {
16967836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'link-down-timeout': %d;"
16977836SJohn.Forte@Sun.COM " using nvram value of 0\n", data);
16987836SJohn.Forte@Sun.COM data = 0;
16997836SJohn.Forte@Sun.COM }
17007836SJohn.Forte@Sun.COM ha->loop_down_abort_time = (uint8_t)(LOOP_DOWN_TIMER_START - data);
17017836SJohn.Forte@Sun.COM if (ha->loop_down_abort_time == LOOP_DOWN_TIMER_START) {
17027836SJohn.Forte@Sun.COM ha->loop_down_abort_time--;
17037836SJohn.Forte@Sun.COM } else if (ha->loop_down_abort_time <= LOOP_DOWN_TIMER_END) {
17047836SJohn.Forte@Sun.COM ha->loop_down_abort_time = LOOP_DOWN_TIMER_END + 1;
17057836SJohn.Forte@Sun.COM }
17067836SJohn.Forte@Sun.COM
17077836SJohn.Forte@Sun.COM /* Get link down error enable. */
17087836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-link-down-error")) == 0xffffffff ||
17097836SJohn.Forte@Sun.COM data == 1) {
17107836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_LINK_DOWN_REPORTING;
17117836SJohn.Forte@Sun.COM } else if (data == 0) {
17127836SJohn.Forte@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_LINK_DOWN_REPORTING;
17137836SJohn.Forte@Sun.COM } else {
17147836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'link-down-error': %d;"
17157836SJohn.Forte@Sun.COM " using default value of 1\n", data);
17167836SJohn.Forte@Sun.COM }
17177836SJohn.Forte@Sun.COM
17187836SJohn.Forte@Sun.COM /*
17197836SJohn.Forte@Sun.COM * Get firmware dump flags.
17207836SJohn.Forte@Sun.COM * TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT BIT_0
17217836SJohn.Forte@Sun.COM * TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR BIT_1
17227836SJohn.Forte@Sun.COM * TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT BIT_2
17237836SJohn.Forte@Sun.COM * TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT BIT_3
17247836SJohn.Forte@Sun.COM */
17257836SJohn.Forte@Sun.COM ha->cfg_flags &= ~(CFG_DUMP_MAILBOX_TIMEOUT |
17267836SJohn.Forte@Sun.COM CFG_DUMP_ISP_SYSTEM_ERROR | CFG_DUMP_DRIVER_COMMAND_TIMEOUT |
17277836SJohn.Forte@Sun.COM CFG_DUMP_LOOP_OFFLINE_TIMEOUT);
17287836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "firmware-dump-flags")) != 0xffffffff) {
17297836SJohn.Forte@Sun.COM if (data & BIT_0) {
17307836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_DUMP_MAILBOX_TIMEOUT;
17317836SJohn.Forte@Sun.COM }
17327836SJohn.Forte@Sun.COM if (data & BIT_1) {
17337836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_DUMP_ISP_SYSTEM_ERROR;
17347836SJohn.Forte@Sun.COM }
17357836SJohn.Forte@Sun.COM if (data & BIT_2) {
17367836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_DUMP_DRIVER_COMMAND_TIMEOUT;
17377836SJohn.Forte@Sun.COM }
17387836SJohn.Forte@Sun.COM if (data & BIT_3) {
17397836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_DUMP_LOOP_OFFLINE_TIMEOUT;
17407836SJohn.Forte@Sun.COM }
17417836SJohn.Forte@Sun.COM }
17427836SJohn.Forte@Sun.COM
17437836SJohn.Forte@Sun.COM /* Get the PCI max read request size override. */
17447836SJohn.Forte@Sun.COM ha->pci_max_read_req = 0;
17457836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "pci-max-read-request")) != 0xffffffff &&
17467836SJohn.Forte@Sun.COM data != 0) {
17477836SJohn.Forte@Sun.COM ha->pci_max_read_req = (uint16_t)(data);
17487836SJohn.Forte@Sun.COM }
17497836SJohn.Forte@Sun.COM
175010240SDaniel.Beauregard@Sun.COM /*
175110240SDaniel.Beauregard@Sun.COM * Set default fw wait, adjusted for slow FCF's.
175210240SDaniel.Beauregard@Sun.COM * Revisit when FCF's as fast as FC switches.
175310240SDaniel.Beauregard@Sun.COM */
175411924SDaniel.Beauregard@Sun.COM ha->fwwait = (uint8_t)(CFG_IST(ha, CFG_CTRL_8081) ? 45 : 10);
17557836SJohn.Forte@Sun.COM /* Get the attach fw_ready override value. */
17567836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "init-loop-sync-wait")) != 0xffffffff) {
17577836SJohn.Forte@Sun.COM if (data > 0 && data <= 240) {
17587836SJohn.Forte@Sun.COM ha->fwwait = (uint8_t)data;
17597836SJohn.Forte@Sun.COM } else {
17607836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
17617836SJohn.Forte@Sun.COM "'init-loop-sync-wait': %d; using default "
17627836SJohn.Forte@Sun.COM "value of %d\n", data, ha->fwwait);
17637836SJohn.Forte@Sun.COM }
17647836SJohn.Forte@Sun.COM }
17657836SJohn.Forte@Sun.COM
17667836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
17677836SJohn.Forte@Sun.COM }
17687836SJohn.Forte@Sun.COM
17697836SJohn.Forte@Sun.COM /*
17707836SJohn.Forte@Sun.COM * ql_24xx_properties
17717836SJohn.Forte@Sun.COM * Copies driver properties to NVRAM or adapter structure.
17727836SJohn.Forte@Sun.COM *
17737836SJohn.Forte@Sun.COM * Driver properties are by design global variables and hidden
17747836SJohn.Forte@Sun.COM * completely from administrators. Knowledgeable folks can
17757836SJohn.Forte@Sun.COM * override the default values using /etc/system.
17767836SJohn.Forte@Sun.COM *
17777836SJohn.Forte@Sun.COM * Input:
17787836SJohn.Forte@Sun.COM * ha: adapter state pointer.
17797836SJohn.Forte@Sun.COM * nv: NVRAM structure pointer.
17807836SJohn.Forte@Sun.COM *
17817836SJohn.Forte@Sun.COM * Context:
17827836SJohn.Forte@Sun.COM * Kernel context.
17837836SJohn.Forte@Sun.COM */
17847836SJohn.Forte@Sun.COM static void
ql_24xx_properties(ql_adapter_state_t * ha,nvram_24xx_t * nv)17857836SJohn.Forte@Sun.COM ql_24xx_properties(ql_adapter_state_t *ha, nvram_24xx_t *nv)
17867836SJohn.Forte@Sun.COM {
17877836SJohn.Forte@Sun.COM uint32_t data;
17887836SJohn.Forte@Sun.COM
17897836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
17907836SJohn.Forte@Sun.COM
17917836SJohn.Forte@Sun.COM /* Get frame size */
17927836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "max-frame-length")) == 0xffffffff) {
17937836SJohn.Forte@Sun.COM data = 2048;
17947836SJohn.Forte@Sun.COM }
179511924SDaniel.Beauregard@Sun.COM if (data == 512 || data == 1024 || data == 2048 || data == 2112) {
17967836SJohn.Forte@Sun.COM nv->max_frame_length[0] = LSB(data);
17977836SJohn.Forte@Sun.COM nv->max_frame_length[1] = MSB(data);
17987836SJohn.Forte@Sun.COM } else {
17997836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'max-frame-length': %d;"
18007836SJohn.Forte@Sun.COM " using nvram default of %d\n", data, CHAR_TO_SHORT(
18017836SJohn.Forte@Sun.COM nv->max_frame_length[0], nv->max_frame_length[1]));
18027836SJohn.Forte@Sun.COM }
18037836SJohn.Forte@Sun.COM
18047836SJohn.Forte@Sun.COM /* Get execution throttle. */
18057836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "execution-throttle")) == 0xffffffff) {
18067836SJohn.Forte@Sun.COM data = 32;
18077836SJohn.Forte@Sun.COM }
18087836SJohn.Forte@Sun.COM if (data != 0 && data < 65536) {
18097836SJohn.Forte@Sun.COM nv->execution_throttle[0] = LSB(data);
18107836SJohn.Forte@Sun.COM nv->execution_throttle[1] = MSB(data);
18117836SJohn.Forte@Sun.COM } else {
18127836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'execution-throttle':"
18137836SJohn.Forte@Sun.COM " %d; using nvram default of %d\n", data, CHAR_TO_SHORT(
18147836SJohn.Forte@Sun.COM nv->execution_throttle[0], nv->execution_throttle[1]));
18157836SJohn.Forte@Sun.COM }
18167836SJohn.Forte@Sun.COM
18177836SJohn.Forte@Sun.COM /* Get Login timeout. */
18187836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "login-timeout")) == 0xffffffff) {
18197836SJohn.Forte@Sun.COM data = 3;
18207836SJohn.Forte@Sun.COM }
18217836SJohn.Forte@Sun.COM if (data < 65536) {
18227836SJohn.Forte@Sun.COM nv->login_timeout[0] = LSB(data);
18237836SJohn.Forte@Sun.COM nv->login_timeout[1] = MSB(data);
18247836SJohn.Forte@Sun.COM } else {
18257836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'login-timeout': %d; "
18267836SJohn.Forte@Sun.COM "using nvram value of %d\n", data, CHAR_TO_SHORT(
18277836SJohn.Forte@Sun.COM nv->login_timeout[0], nv->login_timeout[1]));
18287836SJohn.Forte@Sun.COM }
18297836SJohn.Forte@Sun.COM
18307836SJohn.Forte@Sun.COM /* Get retry count. */
18317836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "login-retry-count")) == 0xffffffff) {
18327836SJohn.Forte@Sun.COM data = 4;
18337836SJohn.Forte@Sun.COM }
18347836SJohn.Forte@Sun.COM if (data < 65536) {
18357836SJohn.Forte@Sun.COM nv->login_retry_count[0] = LSB(data);
18367836SJohn.Forte@Sun.COM nv->login_retry_count[1] = MSB(data);
18377836SJohn.Forte@Sun.COM } else {
18387836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'login-retry-count': "
18397836SJohn.Forte@Sun.COM "%d; using nvram value of %d\n", data, CHAR_TO_SHORT(
18407836SJohn.Forte@Sun.COM nv->login_retry_count[0], nv->login_retry_count[1]));
18417836SJohn.Forte@Sun.COM }
18427836SJohn.Forte@Sun.COM
18437836SJohn.Forte@Sun.COM /* Get adapter hard loop ID enable. */
18447836SJohn.Forte@Sun.COM data = ql_get_prop(ha, "enable-adapter-hard-loop-ID");
18457836SJohn.Forte@Sun.COM if (data == 0) {
18467836SJohn.Forte@Sun.COM nv->firmware_options_1[0] =
18477836SJohn.Forte@Sun.COM (uint8_t)(nv->firmware_options_1[0] & ~BIT_0);
18487836SJohn.Forte@Sun.COM } else if (data == 1) {
18497836SJohn.Forte@Sun.COM nv->firmware_options_1[0] =
18507836SJohn.Forte@Sun.COM (uint8_t)(nv->firmware_options_1[0] | BIT_0);
18517836SJohn.Forte@Sun.COM } else if (data != 0xffffffff) {
18527836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
18537836SJohn.Forte@Sun.COM "'enable-adapter-hard-loop-ID': %d; using nvram value "
18547836SJohn.Forte@Sun.COM "of %d\n", data,
18557836SJohn.Forte@Sun.COM nv->firmware_options_1[0] & BIT_0 ? 1 : 0);
18567836SJohn.Forte@Sun.COM }
18577836SJohn.Forte@Sun.COM
18587836SJohn.Forte@Sun.COM /* Get adapter hard loop ID. */
18597836SJohn.Forte@Sun.COM data = ql_get_prop(ha, "adapter-hard-loop-ID");
18607836SJohn.Forte@Sun.COM if (data < 126) {
18617836SJohn.Forte@Sun.COM nv->hard_address[0] = LSB(data);
18627836SJohn.Forte@Sun.COM nv->hard_address[1] = MSB(data);
18637836SJohn.Forte@Sun.COM } else if (data != 0xffffffff) {
18647836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'adapter-hard-loop-ID':"
18657836SJohn.Forte@Sun.COM " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
18667836SJohn.Forte@Sun.COM nv->hard_address[0], nv->hard_address[1]));
18677836SJohn.Forte@Sun.COM }
18687836SJohn.Forte@Sun.COM
18697836SJohn.Forte@Sun.COM /* Get LIP reset. */
18707836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-LIP-reset-on-bus-reset")) ==
18717836SJohn.Forte@Sun.COM 0xffffffff) {
18727836SJohn.Forte@Sun.COM data = 0;
18737836SJohn.Forte@Sun.COM }
18747836SJohn.Forte@Sun.COM if (data == 0) {
18757836SJohn.Forte@Sun.COM ha->cfg_flags &= ~CFG_ENABLE_LIP_RESET;
18767836SJohn.Forte@Sun.COM } else if (data == 1) {
18777836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_LIP_RESET;
18787836SJohn.Forte@Sun.COM } else {
18797836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
18807836SJohn.Forte@Sun.COM "'enable-LIP-reset-on-bus-reset': %d; using value of 0\n",
18817836SJohn.Forte@Sun.COM data);
18827836SJohn.Forte@Sun.COM }
18837836SJohn.Forte@Sun.COM
18847836SJohn.Forte@Sun.COM /* Get LIP full login. */
18857836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-LIP-full-login-on-bus-reset")) ==
18867836SJohn.Forte@Sun.COM 0xffffffff) {
18877836SJohn.Forte@Sun.COM data = 1;
18887836SJohn.Forte@Sun.COM }
18897836SJohn.Forte@Sun.COM if (data == 0) {
18907836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_2);
18917836SJohn.Forte@Sun.COM } else if (data == 1) {
18927836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_2);
18937836SJohn.Forte@Sun.COM } else {
18947836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
18957836SJohn.Forte@Sun.COM "'enable-LIP-full-login-on-bus-reset': %d; using nvram "
18967836SJohn.Forte@Sun.COM "value of %d\n", data, nv->host_p[1] & BIT_2 ? 1 : 0);
18977836SJohn.Forte@Sun.COM }
18987836SJohn.Forte@Sun.COM
18997836SJohn.Forte@Sun.COM /* Get target reset. */
19007836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-target-reset-on-bus-reset")) ==
19017836SJohn.Forte@Sun.COM 0xffffffff) {
19027836SJohn.Forte@Sun.COM data = 0;
19037836SJohn.Forte@Sun.COM }
19047836SJohn.Forte@Sun.COM if (data == 0) {
19057836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] & ~BIT_3);
19067836SJohn.Forte@Sun.COM } else if (data == 1) {
19077836SJohn.Forte@Sun.COM nv->host_p[1] = (uint8_t)(nv->host_p[1] | BIT_3);
19087836SJohn.Forte@Sun.COM } else {
19097836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for "
19107836SJohn.Forte@Sun.COM "'enable-target-reset-on-bus-reset': %d; using nvram "
19117836SJohn.Forte@Sun.COM "value of %d", data, nv->host_p[1] & BIT_3 ? 1 : 0);
19127836SJohn.Forte@Sun.COM }
19137836SJohn.Forte@Sun.COM
19147836SJohn.Forte@Sun.COM /* Get reset delay. */
19157836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "reset-delay")) == 0xffffffff) {
19167836SJohn.Forte@Sun.COM data = 5;
19177836SJohn.Forte@Sun.COM }
19187836SJohn.Forte@Sun.COM if (data != 0 && data < 256) {
19197836SJohn.Forte@Sun.COM nv->reset_delay = (uint8_t)data;
19207836SJohn.Forte@Sun.COM } else {
19217836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'reset-delay': %d; "
19227836SJohn.Forte@Sun.COM "using nvram value of %d", data, nv->reset_delay);
19237836SJohn.Forte@Sun.COM }
19247836SJohn.Forte@Sun.COM
19257836SJohn.Forte@Sun.COM /* Get port down retry count. */
19267836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "port-down-retry-count")) == 0xffffffff) {
19277836SJohn.Forte@Sun.COM data = 8;
19287836SJohn.Forte@Sun.COM }
19297836SJohn.Forte@Sun.COM if (data < 256) {
19307836SJohn.Forte@Sun.COM nv->port_down_retry_count[0] = LSB(data);
19317836SJohn.Forte@Sun.COM nv->port_down_retry_count[1] = MSB(data);
19327836SJohn.Forte@Sun.COM } else {
19337836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'port-down-retry-count':"
19347836SJohn.Forte@Sun.COM " %d; using nvram value of %d\n", data, CHAR_TO_SHORT(
19357836SJohn.Forte@Sun.COM nv->port_down_retry_count[0],
19367836SJohn.Forte@Sun.COM nv->port_down_retry_count[1]));
19377836SJohn.Forte@Sun.COM }
19387836SJohn.Forte@Sun.COM
193911924SDaniel.Beauregard@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_8081))) {
194011924SDaniel.Beauregard@Sun.COM /* Get connection mode setting. */
194111924SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "connection-options")) ==
194211924SDaniel.Beauregard@Sun.COM 0xffffffff) {
194311924SDaniel.Beauregard@Sun.COM data = 2;
194411924SDaniel.Beauregard@Sun.COM }
194511924SDaniel.Beauregard@Sun.COM if (data <= 2) {
194611924SDaniel.Beauregard@Sun.COM nv->firmware_options_2[0] = (uint8_t)
194711924SDaniel.Beauregard@Sun.COM (nv->firmware_options_2[0] &
194811924SDaniel.Beauregard@Sun.COM ~(BIT_6 | BIT_5 | BIT_4));
194911924SDaniel.Beauregard@Sun.COM nv->firmware_options_2[0] = (uint8_t)
195011924SDaniel.Beauregard@Sun.COM (nv->firmware_options_2[0] | (uint8_t)(data << 4));
195111924SDaniel.Beauregard@Sun.COM } else {
195211924SDaniel.Beauregard@Sun.COM EL(ha, "invalid parameter value for 'connection-"
195311924SDaniel.Beauregard@Sun.COM "options': %d; using nvram value of %d\n", data,
195411924SDaniel.Beauregard@Sun.COM (nv->firmware_options_2[0] >> 4) & 0x3);
195511924SDaniel.Beauregard@Sun.COM }
195611924SDaniel.Beauregard@Sun.COM
195711924SDaniel.Beauregard@Sun.COM /* Get data rate setting. */
195811924SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "fc-data-rate")) == 0xffffffff) {
195911924SDaniel.Beauregard@Sun.COM data = 2;
196011924SDaniel.Beauregard@Sun.COM }
196111924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_2422) && data < 4) ||
196211924SDaniel.Beauregard@Sun.COM (CFG_IST(ha, CFG_CTRL_258081) && data < 5)) {
196311924SDaniel.Beauregard@Sun.COM nv->firmware_options_3[1] = (uint8_t)
196411924SDaniel.Beauregard@Sun.COM (nv->firmware_options_3[1] & 0x1f);
196511924SDaniel.Beauregard@Sun.COM nv->firmware_options_3[1] = (uint8_t)
196611924SDaniel.Beauregard@Sun.COM (nv->firmware_options_3[1] | (uint8_t)(data << 5));
196711924SDaniel.Beauregard@Sun.COM } else {
196811924SDaniel.Beauregard@Sun.COM EL(ha, "invalid parameter value for 'fc-data-rate': "
196911924SDaniel.Beauregard@Sun.COM "%d; using nvram value of %d\n", data,
197011924SDaniel.Beauregard@Sun.COM (nv->firmware_options_3[1] >> 5) & 0x7);
197111924SDaniel.Beauregard@Sun.COM }
19727836SJohn.Forte@Sun.COM }
19737836SJohn.Forte@Sun.COM
19747836SJohn.Forte@Sun.COM /* Get IP FW container count. */
19757836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb24.cc[0] = LSB(ql_ip_buffer_count);
19767836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb24.cc[1] = MSB(ql_ip_buffer_count);
19777836SJohn.Forte@Sun.COM
19787836SJohn.Forte@Sun.COM /* Get IP low water mark. */
19797836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb24.low_water_mark[0] = LSB(ql_ip_low_water);
19807836SJohn.Forte@Sun.COM ha->ip_init_ctrl_blk.cb24.low_water_mark[1] = MSB(ql_ip_low_water);
19817836SJohn.Forte@Sun.COM
19827836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
19837836SJohn.Forte@Sun.COM
19847836SJohn.Forte@Sun.COM /* Get enable flash load. */
19857836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-flash-load")) == 0xffffffff ||
19867836SJohn.Forte@Sun.COM data == 0) {
19877836SJohn.Forte@Sun.COM ha->cfg_flags &= ~CFG_LOAD_FLASH_FW;
19887836SJohn.Forte@Sun.COM } else if (data == 1) {
19897836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_LOAD_FLASH_FW;
19907836SJohn.Forte@Sun.COM } else {
19917836SJohn.Forte@Sun.COM EL(ha, "invalid parameter value for 'enable-flash-load': "
19927836SJohn.Forte@Sun.COM "%d; using default value of 0\n", data);
19937836SJohn.Forte@Sun.COM }
19947836SJohn.Forte@Sun.COM
19957836SJohn.Forte@Sun.COM /* Enable firmware extended tracing */
19967836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-fwexttrace")) != 0xffffffff) {
19977836SJohn.Forte@Sun.COM if (data != 0) {
19987836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_FWEXTTRACE;
19997836SJohn.Forte@Sun.COM }
20007836SJohn.Forte@Sun.COM }
20017836SJohn.Forte@Sun.COM
20027836SJohn.Forte@Sun.COM /* Enable firmware fc tracing */
20037836SJohn.Forte@Sun.COM if ((data = ql_get_prop(ha, "enable-fwfcetrace")) != 0xffffffff) {
20047836SJohn.Forte@Sun.COM ha->cfg_flags |= CFG_ENABLE_FWFCETRACE;
20057836SJohn.Forte@Sun.COM ha->fwfcetraceopt = data;
20067836SJohn.Forte@Sun.COM }
20077836SJohn.Forte@Sun.COM
200811541SDaniel.Beauregard@Sun.COM /* Enable fast timeout */
200911541SDaniel.Beauregard@Sun.COM if ((data = ql_get_prop(ha, "enable-fasttimeout")) != 0xffffffff) {
201011541SDaniel.Beauregard@Sun.COM if (data != 0) {
201111541SDaniel.Beauregard@Sun.COM ha->cfg_flags |= CFG_FAST_TIMEOUT;
201211541SDaniel.Beauregard@Sun.COM }
201311541SDaniel.Beauregard@Sun.COM }
201411541SDaniel.Beauregard@Sun.COM
20157836SJohn.Forte@Sun.COM ql_common_properties(ha);
20167836SJohn.Forte@Sun.COM
20177836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
20187836SJohn.Forte@Sun.COM
20197836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
20207836SJohn.Forte@Sun.COM }
20217836SJohn.Forte@Sun.COM
20227836SJohn.Forte@Sun.COM /*
20237836SJohn.Forte@Sun.COM * ql_get_prop
20247836SJohn.Forte@Sun.COM * Get property value from configuration file.
20257836SJohn.Forte@Sun.COM *
20267836SJohn.Forte@Sun.COM * Input:
20277836SJohn.Forte@Sun.COM * ha= adapter state pointer.
20287836SJohn.Forte@Sun.COM * string = property string pointer.
20297836SJohn.Forte@Sun.COM *
20307836SJohn.Forte@Sun.COM * Returns:
20317836SJohn.Forte@Sun.COM * 0xFFFFFFFF = no property else property value.
20327836SJohn.Forte@Sun.COM *
20337836SJohn.Forte@Sun.COM * Context:
20347836SJohn.Forte@Sun.COM * Kernel context.
20357836SJohn.Forte@Sun.COM */
20367836SJohn.Forte@Sun.COM uint32_t
ql_get_prop(ql_adapter_state_t * ha,char * string)20377836SJohn.Forte@Sun.COM ql_get_prop(ql_adapter_state_t *ha, char *string)
20387836SJohn.Forte@Sun.COM {
20397836SJohn.Forte@Sun.COM char buf[256];
20409156SDaniel.Beauregard@Sun.COM uint32_t data = 0xffffffff;
20419156SDaniel.Beauregard@Sun.COM
20429156SDaniel.Beauregard@Sun.COM /*
20439156SDaniel.Beauregard@Sun.COM * Look for a adapter instance NPIV (virtual port) specific parameter
20449156SDaniel.Beauregard@Sun.COM */
204511924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
20469156SDaniel.Beauregard@Sun.COM (void) sprintf(buf, "hba%d-vp%d-%s", ha->instance,
20479156SDaniel.Beauregard@Sun.COM ha->vp_index, string);
20489156SDaniel.Beauregard@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
20499156SDaniel.Beauregard@Sun.COM data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
20509156SDaniel.Beauregard@Sun.COM buf, (int)0xffffffff);
20519156SDaniel.Beauregard@Sun.COM }
20529156SDaniel.Beauregard@Sun.COM
20539156SDaniel.Beauregard@Sun.COM /*
20549156SDaniel.Beauregard@Sun.COM * Get adapter instance parameter if a vp specific one isn't found.
20559156SDaniel.Beauregard@Sun.COM */
20569156SDaniel.Beauregard@Sun.COM if (data == 0xffffffff) {
20579156SDaniel.Beauregard@Sun.COM (void) sprintf(buf, "hba%d-%s", ha->instance, string);
20589156SDaniel.Beauregard@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
20599156SDaniel.Beauregard@Sun.COM data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip,
20609156SDaniel.Beauregard@Sun.COM 0, buf, (int)0xffffffff);
20619156SDaniel.Beauregard@Sun.COM }
20627836SJohn.Forte@Sun.COM
20637836SJohn.Forte@Sun.COM /* Adapter instance parameter found? */
20647836SJohn.Forte@Sun.COM if (data == 0xffffffff) {
20657836SJohn.Forte@Sun.COM /* No, get default parameter. */
20667836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
20677836SJohn.Forte@Sun.COM data = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, ha->dip, 0,
20687836SJohn.Forte@Sun.COM string, (int)0xffffffff);
20697836SJohn.Forte@Sun.COM }
20707836SJohn.Forte@Sun.COM
20717836SJohn.Forte@Sun.COM return (data);
20727836SJohn.Forte@Sun.COM }
20737836SJohn.Forte@Sun.COM
20747836SJohn.Forte@Sun.COM /*
20757836SJohn.Forte@Sun.COM * ql_check_isp_firmware
20767836SJohn.Forte@Sun.COM * Checks if using already loaded RISC code or drivers copy.
20777836SJohn.Forte@Sun.COM * If using already loaded code, save a copy of it.
20787836SJohn.Forte@Sun.COM *
20797836SJohn.Forte@Sun.COM * Input:
20807836SJohn.Forte@Sun.COM * ha = adapter state pointer.
20817836SJohn.Forte@Sun.COM *
20827836SJohn.Forte@Sun.COM * Returns:
20837836SJohn.Forte@Sun.COM * ql local function return status code.
20847836SJohn.Forte@Sun.COM *
20857836SJohn.Forte@Sun.COM * Context:
20867836SJohn.Forte@Sun.COM * Kernel context.
20877836SJohn.Forte@Sun.COM */
20887836SJohn.Forte@Sun.COM static int
ql_check_isp_firmware(ql_adapter_state_t * ha)20897836SJohn.Forte@Sun.COM ql_check_isp_firmware(ql_adapter_state_t *ha)
20907836SJohn.Forte@Sun.COM {
20917836SJohn.Forte@Sun.COM int rval;
20927836SJohn.Forte@Sun.COM uint16_t word_count;
20937836SJohn.Forte@Sun.COM uint32_t byte_count;
20947836SJohn.Forte@Sun.COM uint32_t fw_size, *lptr;
20957836SJohn.Forte@Sun.COM caddr_t bufp;
20967836SJohn.Forte@Sun.COM uint16_t risc_address = (uint16_t)ha->risc_fw[0].addr;
20977836SJohn.Forte@Sun.COM
20987836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
20997836SJohn.Forte@Sun.COM
210011924SDaniel.Beauregard@Sun.COM /* Test for firmware running. */
210111924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
210211924SDaniel.Beauregard@Sun.COM if (ql_8021_idc_handler(ha) != NX_DEV_READY) {
210311924SDaniel.Beauregard@Sun.COM rval = QL_FUNCTION_FAILED;
210411924SDaniel.Beauregard@Sun.COM } else {
210511924SDaniel.Beauregard@Sun.COM rval = ql_start_firmware(ha);
210611924SDaniel.Beauregard@Sun.COM }
210711924SDaniel.Beauregard@Sun.COM } else if (CFG_IST(ha, CFG_DISABLE_RISC_CODE_LOAD)) {
21087836SJohn.Forte@Sun.COM if (ha->risc_code != NULL) {
21097836SJohn.Forte@Sun.COM kmem_free(ha->risc_code, ha->risc_code_size);
21107836SJohn.Forte@Sun.COM ha->risc_code = NULL;
21117836SJohn.Forte@Sun.COM ha->risc_code_size = 0;
21127836SJohn.Forte@Sun.COM }
21137836SJohn.Forte@Sun.COM
21147836SJohn.Forte@Sun.COM /* Get RISC code length. */
21157836SJohn.Forte@Sun.COM rval = ql_rd_risc_ram(ha, risc_address + 3, ha->request_dvma,
21167836SJohn.Forte@Sun.COM 1);
21177836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
21187836SJohn.Forte@Sun.COM lptr = (uint32_t *)ha->request_ring_bp;
21197836SJohn.Forte@Sun.COM fw_size = *lptr << 1;
21207836SJohn.Forte@Sun.COM
21217836SJohn.Forte@Sun.COM if ((bufp = kmem_alloc(fw_size, KM_SLEEP)) != NULL) {
21227836SJohn.Forte@Sun.COM ha->risc_code_size = fw_size;
21237836SJohn.Forte@Sun.COM ha->risc_code = bufp;
21247836SJohn.Forte@Sun.COM ha->fw_transfer_size = 128;
21257836SJohn.Forte@Sun.COM
21267836SJohn.Forte@Sun.COM /* Dump RISC code. */
21277836SJohn.Forte@Sun.COM do {
21287836SJohn.Forte@Sun.COM if (fw_size > ha->fw_transfer_size) {
21297836SJohn.Forte@Sun.COM byte_count =
21307836SJohn.Forte@Sun.COM ha->fw_transfer_size;
21317836SJohn.Forte@Sun.COM } else {
21327836SJohn.Forte@Sun.COM byte_count = fw_size;
21337836SJohn.Forte@Sun.COM }
21347836SJohn.Forte@Sun.COM
21357836SJohn.Forte@Sun.COM word_count =
21367836SJohn.Forte@Sun.COM (uint16_t)(byte_count >> 1);
21377836SJohn.Forte@Sun.COM
21387836SJohn.Forte@Sun.COM rval = ql_rd_risc_ram(ha, risc_address,
21397836SJohn.Forte@Sun.COM ha->request_dvma, word_count);
21407836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
21417836SJohn.Forte@Sun.COM kmem_free(ha->risc_code,
21427836SJohn.Forte@Sun.COM ha->risc_code_size);
21437836SJohn.Forte@Sun.COM ha->risc_code = NULL;
21447836SJohn.Forte@Sun.COM ha->risc_code_size = 0;
21457836SJohn.Forte@Sun.COM break;
21467836SJohn.Forte@Sun.COM }
21477836SJohn.Forte@Sun.COM
21487836SJohn.Forte@Sun.COM (void) ddi_dma_sync(
21497836SJohn.Forte@Sun.COM ha->hba_buf.dma_handle,
21507836SJohn.Forte@Sun.COM REQUEST_Q_BUFFER_OFFSET,
21517836SJohn.Forte@Sun.COM byte_count,
21527836SJohn.Forte@Sun.COM DDI_DMA_SYNC_FORKERNEL);
21537836SJohn.Forte@Sun.COM ddi_rep_get16(ha->hba_buf.acc_handle,
21547836SJohn.Forte@Sun.COM (uint16_t *)bufp,
21557836SJohn.Forte@Sun.COM (uint16_t *)ha->request_ring_bp,
21567836SJohn.Forte@Sun.COM word_count, DDI_DEV_AUTOINCR);
21577836SJohn.Forte@Sun.COM
21587836SJohn.Forte@Sun.COM risc_address += word_count;
21597836SJohn.Forte@Sun.COM fw_size -= byte_count;
21607836SJohn.Forte@Sun.COM bufp += byte_count;
21617836SJohn.Forte@Sun.COM } while (fw_size != 0);
21627836SJohn.Forte@Sun.COM }
216311924SDaniel.Beauregard@Sun.COM rval = QL_FUNCTION_FAILED;
21647836SJohn.Forte@Sun.COM }
21657836SJohn.Forte@Sun.COM } else {
21667836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
21677836SJohn.Forte@Sun.COM }
21687836SJohn.Forte@Sun.COM
21697836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
21707836SJohn.Forte@Sun.COM EL(ha, "Load RISC code\n");
21717836SJohn.Forte@Sun.COM } else {
21727836SJohn.Forte@Sun.COM /*EMPTY*/
21737836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
21747836SJohn.Forte@Sun.COM }
21757836SJohn.Forte@Sun.COM return (rval);
21767836SJohn.Forte@Sun.COM }
21777836SJohn.Forte@Sun.COM
21787836SJohn.Forte@Sun.COM /*
21797836SJohn.Forte@Sun.COM * Chip diagnostics
21807836SJohn.Forte@Sun.COM * Test chip for proper operation.
21817836SJohn.Forte@Sun.COM *
21827836SJohn.Forte@Sun.COM * Input:
21837836SJohn.Forte@Sun.COM * ha = adapter state pointer.
21847836SJohn.Forte@Sun.COM *
21857836SJohn.Forte@Sun.COM * Returns:
21867836SJohn.Forte@Sun.COM * ql local function return status code.
21877836SJohn.Forte@Sun.COM *
21887836SJohn.Forte@Sun.COM * Context:
21897836SJohn.Forte@Sun.COM * Kernel context.
21907836SJohn.Forte@Sun.COM */
21917836SJohn.Forte@Sun.COM static int
ql_chip_diag(ql_adapter_state_t * ha)21927836SJohn.Forte@Sun.COM ql_chip_diag(ql_adapter_state_t *ha)
21937836SJohn.Forte@Sun.COM {
21947836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
219511924SDaniel.Beauregard@Sun.COM int rval;
21967836SJohn.Forte@Sun.COM int32_t retries = 4;
21977836SJohn.Forte@Sun.COM uint16_t id;
21987836SJohn.Forte@Sun.COM
21997836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
22007836SJohn.Forte@Sun.COM
22017836SJohn.Forte@Sun.COM do {
22027836SJohn.Forte@Sun.COM /* Reset ISP chip. */
22037836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
22047836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
22057836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
22067836SJohn.Forte@Sun.COM
22077836SJohn.Forte@Sun.COM /* For ISP2200A reduce firmware load size. */
22087836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_CTRL_2200) &&
220911924SDaniel.Beauregard@Sun.COM RD16_IO_REG(ha, mailbox_out[7]) == 4) {
22107836SJohn.Forte@Sun.COM ha->fw_transfer_size = 128;
22117836SJohn.Forte@Sun.COM } else {
22127836SJohn.Forte@Sun.COM ha->fw_transfer_size = REQUEST_QUEUE_SIZE;
22137836SJohn.Forte@Sun.COM }
22147836SJohn.Forte@Sun.COM
221511924SDaniel.Beauregard@Sun.COM rval = QL_SUCCESS;
221611924SDaniel.Beauregard@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_8021))) {
221711924SDaniel.Beauregard@Sun.COM ql_reset_chip(ha);
221811924SDaniel.Beauregard@Sun.COM
221911924SDaniel.Beauregard@Sun.COM /* Check product ID of chip */
222011924SDaniel.Beauregard@Sun.COM mr.mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
222111924SDaniel.Beauregard@Sun.COM mr.mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
222211924SDaniel.Beauregard@Sun.COM mr.mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
222311924SDaniel.Beauregard@Sun.COM
222411924SDaniel.Beauregard@Sun.COM if (ha->device_id == 0x5432 ||
222511924SDaniel.Beauregard@Sun.COM ha->device_id == 0x8432) {
222611924SDaniel.Beauregard@Sun.COM id = 0x2432;
222711924SDaniel.Beauregard@Sun.COM } else if (ha->device_id == 0x5422 ||
222811924SDaniel.Beauregard@Sun.COM ha->device_id == 0x8422) {
222911924SDaniel.Beauregard@Sun.COM id = 0x2422;
223011924SDaniel.Beauregard@Sun.COM } else {
223111924SDaniel.Beauregard@Sun.COM id = ha->device_id;
223211924SDaniel.Beauregard@Sun.COM }
223311924SDaniel.Beauregard@Sun.COM
223411924SDaniel.Beauregard@Sun.COM if (mr.mb[1] == PROD_ID_1 &&
223511924SDaniel.Beauregard@Sun.COM (mr.mb[2] == PROD_ID_2 || mr.mb[2] == PROD_ID_2a) &&
223611924SDaniel.Beauregard@Sun.COM (mr.mb[3] == PROD_ID_3 || mr.mb[3] == id)) {
223711924SDaniel.Beauregard@Sun.COM ha->adapter_stats->revlvl.isp2200 =
223811924SDaniel.Beauregard@Sun.COM RD16_IO_REG(ha, mailbox_out[4]);
223911924SDaniel.Beauregard@Sun.COM ha->adapter_stats->revlvl.risc =
224011924SDaniel.Beauregard@Sun.COM RD16_IO_REG(ha, mailbox_out[5]);
224111924SDaniel.Beauregard@Sun.COM ha->adapter_stats->revlvl.frmbfr =
224211924SDaniel.Beauregard@Sun.COM RD16_IO_REG(ha, mailbox_out[6]);
224311924SDaniel.Beauregard@Sun.COM ha->adapter_stats->revlvl.riscrom =
224411924SDaniel.Beauregard@Sun.COM RD16_IO_REG(ha, mailbox_out[7]);
224511924SDaniel.Beauregard@Sun.COM } else {
224611924SDaniel.Beauregard@Sun.COM cmn_err(CE_WARN, "%s(%d) - prod id failed!, "
224711924SDaniel.Beauregard@Sun.COM "mb1=%xh, mb2=%xh, mb3=%xh", QL_NAME,
224811924SDaniel.Beauregard@Sun.COM ha->instance, mr.mb[1], mr.mb[2], mr.mb[3]);
224911924SDaniel.Beauregard@Sun.COM rval = QL_FUNCTION_FAILED;
225011924SDaniel.Beauregard@Sun.COM }
225111924SDaniel.Beauregard@Sun.COM } else if (!(ha->task_daemon_flags & FIRMWARE_LOADED)) {
225211924SDaniel.Beauregard@Sun.COM break;
22537836SJohn.Forte@Sun.COM }
22547836SJohn.Forte@Sun.COM
225511924SDaniel.Beauregard@Sun.COM if (rval == QL_SUCCESS) {
22567836SJohn.Forte@Sun.COM /* Wrap Incoming Mailboxes Test. */
22577836SJohn.Forte@Sun.COM mr.mb[1] = 0xAAAA;
22587836SJohn.Forte@Sun.COM mr.mb[2] = 0x5555;
22597836SJohn.Forte@Sun.COM mr.mb[3] = 0xAA55;
22607836SJohn.Forte@Sun.COM mr.mb[4] = 0x55AA;
22617836SJohn.Forte@Sun.COM mr.mb[5] = 0xA5A5;
22627836SJohn.Forte@Sun.COM mr.mb[6] = 0x5A5A;
22637836SJohn.Forte@Sun.COM mr.mb[7] = 0x2525;
22647836SJohn.Forte@Sun.COM rval = ql_mbx_wrap_test(ha, &mr);
22657836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
22667836SJohn.Forte@Sun.COM if (mr.mb[1] != 0xAAAA ||
22677836SJohn.Forte@Sun.COM mr.mb[2] != 0x5555 ||
22687836SJohn.Forte@Sun.COM mr.mb[3] != 0xAA55 ||
22697836SJohn.Forte@Sun.COM mr.mb[4] != 0x55AA ||
22707836SJohn.Forte@Sun.COM mr.mb[5] != 0xA5A5 ||
22717836SJohn.Forte@Sun.COM mr.mb[6] != 0x5A5A ||
22727836SJohn.Forte@Sun.COM mr.mb[7] != 0x2525) {
22737836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
22747836SJohn.Forte@Sun.COM (void) ql_flash_errlog(ha,
22757836SJohn.Forte@Sun.COM FLASH_ERRLOG_ISP_ERR, 0,
22767836SJohn.Forte@Sun.COM RD16_IO_REG(ha, hccr),
22777836SJohn.Forte@Sun.COM RD16_IO_REG(ha, istatus));
22787836SJohn.Forte@Sun.COM }
22797836SJohn.Forte@Sun.COM } else {
22807836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "%s(%d) - reg test failed="
22817836SJohn.Forte@Sun.COM "%xh!", QL_NAME, ha->instance, rval);
22827836SJohn.Forte@Sun.COM }
22837836SJohn.Forte@Sun.COM }
22847836SJohn.Forte@Sun.COM } while ((retries-- != 0) && (rval != QL_SUCCESS));
22857836SJohn.Forte@Sun.COM
22867836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
22877836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
22887836SJohn.Forte@Sun.COM } else {
22897836SJohn.Forte@Sun.COM /*EMPTY*/
22907836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
22917836SJohn.Forte@Sun.COM }
22927836SJohn.Forte@Sun.COM return (rval);
22937836SJohn.Forte@Sun.COM }
22947836SJohn.Forte@Sun.COM
22957836SJohn.Forte@Sun.COM /*
22967836SJohn.Forte@Sun.COM * ql_load_isp_firmware
22977836SJohn.Forte@Sun.COM * Load and start RISC firmware.
22987836SJohn.Forte@Sun.COM * Uses request ring for DMA buffer.
22997836SJohn.Forte@Sun.COM *
23007836SJohn.Forte@Sun.COM * Input:
23017836SJohn.Forte@Sun.COM * ha = adapter state pointer.
23027836SJohn.Forte@Sun.COM *
23037836SJohn.Forte@Sun.COM * Returns:
23047836SJohn.Forte@Sun.COM * ql local function return status code.
23057836SJohn.Forte@Sun.COM *
23067836SJohn.Forte@Sun.COM * Context:
23077836SJohn.Forte@Sun.COM * Kernel context.
23087836SJohn.Forte@Sun.COM */
23097836SJohn.Forte@Sun.COM int
ql_load_isp_firmware(ql_adapter_state_t * vha)23107836SJohn.Forte@Sun.COM ql_load_isp_firmware(ql_adapter_state_t *vha)
23117836SJohn.Forte@Sun.COM {
23127836SJohn.Forte@Sun.COM caddr_t risc_code_address;
23137836SJohn.Forte@Sun.COM uint32_t risc_address, risc_code_size;
23147836SJohn.Forte@Sun.COM int rval;
23157836SJohn.Forte@Sun.COM uint32_t word_count, cnt;
23167836SJohn.Forte@Sun.COM size_t byte_count;
23177836SJohn.Forte@Sun.COM ql_adapter_state_t *ha = vha->pha;
23187836SJohn.Forte@Sun.COM
231911924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
232011924SDaniel.Beauregard@Sun.COM rval = ql_8021_load_risc(ha);
232111924SDaniel.Beauregard@Sun.COM } else {
232211924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_81XX)) {
232311924SDaniel.Beauregard@Sun.COM ql_mps_reset(ha);
232411924SDaniel.Beauregard@Sun.COM }
232511924SDaniel.Beauregard@Sun.COM
232611924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) {
232711924SDaniel.Beauregard@Sun.COM return (ql_load_flash_fw(ha));
232811924SDaniel.Beauregard@Sun.COM }
232911924SDaniel.Beauregard@Sun.COM
233011924SDaniel.Beauregard@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
233111924SDaniel.Beauregard@Sun.COM
233211924SDaniel.Beauregard@Sun.COM /* Load firmware segments */
233311924SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < MAX_RISC_CODE_SEGMENTS &&
233411924SDaniel.Beauregard@Sun.COM ha->risc_fw[cnt].code != NULL; cnt++) {
233511924SDaniel.Beauregard@Sun.COM
233611924SDaniel.Beauregard@Sun.COM risc_code_address = ha->risc_fw[cnt].code;
233711924SDaniel.Beauregard@Sun.COM risc_address = ha->risc_fw[cnt].addr;
233811924SDaniel.Beauregard@Sun.COM risc_code_size = ha->risc_fw[cnt].length;
233911924SDaniel.Beauregard@Sun.COM
234011924SDaniel.Beauregard@Sun.COM while (risc_code_size) {
234111924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_242581)) {
234211924SDaniel.Beauregard@Sun.COM word_count = ha->fw_transfer_size >> 2;
234311924SDaniel.Beauregard@Sun.COM if (word_count > risc_code_size) {
234411924SDaniel.Beauregard@Sun.COM word_count = risc_code_size;
234511924SDaniel.Beauregard@Sun.COM }
234611924SDaniel.Beauregard@Sun.COM byte_count = word_count << 2;
234711924SDaniel.Beauregard@Sun.COM
234811924SDaniel.Beauregard@Sun.COM ddi_rep_put32(ha->hba_buf.acc_handle,
234911924SDaniel.Beauregard@Sun.COM (uint32_t *)risc_code_address,
235011924SDaniel.Beauregard@Sun.COM (uint32_t *)ha->request_ring_bp,
235111924SDaniel.Beauregard@Sun.COM word_count, DDI_DEV_AUTOINCR);
235211924SDaniel.Beauregard@Sun.COM } else {
235311924SDaniel.Beauregard@Sun.COM word_count = ha->fw_transfer_size >> 1;
235411924SDaniel.Beauregard@Sun.COM if (word_count > risc_code_size) {
235511924SDaniel.Beauregard@Sun.COM word_count = risc_code_size;
235611924SDaniel.Beauregard@Sun.COM }
235711924SDaniel.Beauregard@Sun.COM byte_count = word_count << 1;
235811924SDaniel.Beauregard@Sun.COM
235911924SDaniel.Beauregard@Sun.COM ddi_rep_put16(ha->hba_buf.acc_handle,
236011924SDaniel.Beauregard@Sun.COM (uint16_t *)risc_code_address,
236111924SDaniel.Beauregard@Sun.COM (uint16_t *)ha->request_ring_bp,
236211924SDaniel.Beauregard@Sun.COM word_count, DDI_DEV_AUTOINCR);
23637836SJohn.Forte@Sun.COM }
236411924SDaniel.Beauregard@Sun.COM
236511924SDaniel.Beauregard@Sun.COM (void) ddi_dma_sync(ha->hba_buf.dma_handle,
236611924SDaniel.Beauregard@Sun.COM REQUEST_Q_BUFFER_OFFSET, byte_count,
236711924SDaniel.Beauregard@Sun.COM DDI_DMA_SYNC_FORDEV);
236811924SDaniel.Beauregard@Sun.COM
236911924SDaniel.Beauregard@Sun.COM rval = ql_wrt_risc_ram(ha, risc_address,
237011924SDaniel.Beauregard@Sun.COM ha->request_dvma, word_count);
237111924SDaniel.Beauregard@Sun.COM if (rval != QL_SUCCESS) {
237211924SDaniel.Beauregard@Sun.COM EL(ha, "failed, load=%xh\n", rval);
237311924SDaniel.Beauregard@Sun.COM cnt = MAX_RISC_CODE_SEGMENTS;
237411924SDaniel.Beauregard@Sun.COM break;
23757836SJohn.Forte@Sun.COM }
237611924SDaniel.Beauregard@Sun.COM
237711924SDaniel.Beauregard@Sun.COM risc_address += word_count;
237811924SDaniel.Beauregard@Sun.COM risc_code_size -= word_count;
237911924SDaniel.Beauregard@Sun.COM risc_code_address += byte_count;
23807836SJohn.Forte@Sun.COM }
23817836SJohn.Forte@Sun.COM }
23827836SJohn.Forte@Sun.COM }
23837836SJohn.Forte@Sun.COM
23847836SJohn.Forte@Sun.COM /* Start firmware. */
23857836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
23867836SJohn.Forte@Sun.COM rval = ql_start_firmware(ha);
23877836SJohn.Forte@Sun.COM }
23887836SJohn.Forte@Sun.COM
23897836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
23907836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
23917836SJohn.Forte@Sun.COM } else {
23927836SJohn.Forte@Sun.COM /*EMPTY*/
23937836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
23947836SJohn.Forte@Sun.COM }
23957836SJohn.Forte@Sun.COM
23967836SJohn.Forte@Sun.COM return (rval);
23977836SJohn.Forte@Sun.COM }
23987836SJohn.Forte@Sun.COM
23997836SJohn.Forte@Sun.COM /*
24007836SJohn.Forte@Sun.COM * ql_load_flash_fw
24017836SJohn.Forte@Sun.COM * Gets ISP24xx firmware from flash and loads ISP.
24027836SJohn.Forte@Sun.COM *
24037836SJohn.Forte@Sun.COM * Input:
24047836SJohn.Forte@Sun.COM * ha: adapter state pointer.
24057836SJohn.Forte@Sun.COM *
24067836SJohn.Forte@Sun.COM * Returns:
24079446SDaniel.Beauregard@Sun.COM * ql local function return status code.
24087836SJohn.Forte@Sun.COM */
24097836SJohn.Forte@Sun.COM static int
ql_load_flash_fw(ql_adapter_state_t * ha)24107836SJohn.Forte@Sun.COM ql_load_flash_fw(ql_adapter_state_t *ha)
24117836SJohn.Forte@Sun.COM {
24127836SJohn.Forte@Sun.COM int rval;
24137836SJohn.Forte@Sun.COM uint8_t seg_cnt;
24147836SJohn.Forte@Sun.COM uint32_t risc_address, xfer_size, count, *bp, faddr;
24157836SJohn.Forte@Sun.COM uint32_t risc_code_size = 0;
24167836SJohn.Forte@Sun.COM
24177836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
24187836SJohn.Forte@Sun.COM
24199446SDaniel.Beauregard@Sun.COM faddr = ha->flash_data_addr | ha->flash_fw_addr;
24207836SJohn.Forte@Sun.COM
24217836SJohn.Forte@Sun.COM for (seg_cnt = 0; seg_cnt < 2; seg_cnt++) {
24227836SJohn.Forte@Sun.COM xfer_size = ha->fw_transfer_size >> 2;
24237836SJohn.Forte@Sun.COM do {
24247836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
24257836SJohn.Forte@Sun.COM
24267836SJohn.Forte@Sun.COM /* Read data from flash. */
24277836SJohn.Forte@Sun.COM bp = (uint32_t *)ha->request_ring_bp;
24287836SJohn.Forte@Sun.COM for (count = 0; count < xfer_size; count++) {
24297836SJohn.Forte@Sun.COM rval = ql_24xx_read_flash(ha, faddr++, bp);
24307836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
24317836SJohn.Forte@Sun.COM break;
24327836SJohn.Forte@Sun.COM }
24337836SJohn.Forte@Sun.COM ql_chg_endian((uint8_t *)bp++, 4);
24347836SJohn.Forte@Sun.COM }
24357836SJohn.Forte@Sun.COM
24367836SJohn.Forte@Sun.COM GLOBAL_HW_UNLOCK();
24377836SJohn.Forte@Sun.COM
24387836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
24397836SJohn.Forte@Sun.COM EL(ha, "24xx_read_flash failed=%xh\n", rval);
24407836SJohn.Forte@Sun.COM break;
24417836SJohn.Forte@Sun.COM }
24427836SJohn.Forte@Sun.COM
24437836SJohn.Forte@Sun.COM if (risc_code_size == 0) {
24447836SJohn.Forte@Sun.COM bp = (uint32_t *)ha->request_ring_bp;
24457836SJohn.Forte@Sun.COM risc_address = bp[2];
24467836SJohn.Forte@Sun.COM risc_code_size = bp[3];
24477836SJohn.Forte@Sun.COM ha->risc_fw[seg_cnt].addr = risc_address;
24487836SJohn.Forte@Sun.COM }
24497836SJohn.Forte@Sun.COM
24507836SJohn.Forte@Sun.COM if (risc_code_size < xfer_size) {
24519446SDaniel.Beauregard@Sun.COM faddr -= xfer_size - risc_code_size;
24527836SJohn.Forte@Sun.COM xfer_size = risc_code_size;
24537836SJohn.Forte@Sun.COM }
24547836SJohn.Forte@Sun.COM
24557836SJohn.Forte@Sun.COM (void) ddi_dma_sync(ha->hba_buf.dma_handle,
24567836SJohn.Forte@Sun.COM REQUEST_Q_BUFFER_OFFSET, xfer_size << 2,
24577836SJohn.Forte@Sun.COM DDI_DMA_SYNC_FORDEV);
24587836SJohn.Forte@Sun.COM
24597836SJohn.Forte@Sun.COM rval = ql_wrt_risc_ram(ha, risc_address,
24607836SJohn.Forte@Sun.COM ha->request_dvma, xfer_size);
24617836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
24627836SJohn.Forte@Sun.COM EL(ha, "ql_wrt_risc_ram failed=%xh\n", rval);
24637836SJohn.Forte@Sun.COM break;
24647836SJohn.Forte@Sun.COM }
24657836SJohn.Forte@Sun.COM
24667836SJohn.Forte@Sun.COM risc_address += xfer_size;
24677836SJohn.Forte@Sun.COM risc_code_size -= xfer_size;
24687836SJohn.Forte@Sun.COM } while (risc_code_size);
24697836SJohn.Forte@Sun.COM
24707836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
24717836SJohn.Forte@Sun.COM break;
24727836SJohn.Forte@Sun.COM }
24737836SJohn.Forte@Sun.COM }
24747836SJohn.Forte@Sun.COM
24757836SJohn.Forte@Sun.COM /* Start firmware. */
24767836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
24777836SJohn.Forte@Sun.COM rval = ql_start_firmware(ha);
24787836SJohn.Forte@Sun.COM }
24797836SJohn.Forte@Sun.COM
24807836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
24817836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
24827836SJohn.Forte@Sun.COM } else {
24837836SJohn.Forte@Sun.COM /*EMPTY*/
24847836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
24857836SJohn.Forte@Sun.COM }
24867836SJohn.Forte@Sun.COM return (rval);
24877836SJohn.Forte@Sun.COM }
24887836SJohn.Forte@Sun.COM
24897836SJohn.Forte@Sun.COM /*
24907836SJohn.Forte@Sun.COM * ql_start_firmware
24917836SJohn.Forte@Sun.COM * Starts RISC code.
24927836SJohn.Forte@Sun.COM *
24937836SJohn.Forte@Sun.COM * Input:
24947836SJohn.Forte@Sun.COM * ha = adapter state pointer.
24957836SJohn.Forte@Sun.COM *
24967836SJohn.Forte@Sun.COM * Returns:
24977836SJohn.Forte@Sun.COM * ql local function return status code.
24987836SJohn.Forte@Sun.COM *
24997836SJohn.Forte@Sun.COM * Context:
25007836SJohn.Forte@Sun.COM * Kernel context.
25017836SJohn.Forte@Sun.COM */
25027836SJohn.Forte@Sun.COM int
ql_start_firmware(ql_adapter_state_t * vha)25037836SJohn.Forte@Sun.COM ql_start_firmware(ql_adapter_state_t *vha)
25047836SJohn.Forte@Sun.COM {
25059446SDaniel.Beauregard@Sun.COM int rval, rval2;
25069446SDaniel.Beauregard@Sun.COM uint32_t data;
25077836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
25087836SJohn.Forte@Sun.COM ql_adapter_state_t *ha = vha->pha;
25097836SJohn.Forte@Sun.COM
25107836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
25117836SJohn.Forte@Sun.COM
251211924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
251311924SDaniel.Beauregard@Sun.COM /* Save firmware version. */
251411924SDaniel.Beauregard@Sun.COM rval = ql_get_fw_version(ha, &mr, MAILBOX_TOV);
251511924SDaniel.Beauregard@Sun.COM ha->fw_major_version = mr.mb[1];
251611924SDaniel.Beauregard@Sun.COM ha->fw_minor_version = mr.mb[2];
251711924SDaniel.Beauregard@Sun.COM ha->fw_subminor_version = mr.mb[3];
2518*12279SDaniel.Beauregard@Sun.COM ha->fw_attributes = mr.mb[6];
251911924SDaniel.Beauregard@Sun.COM } else if ((rval = ql_verify_checksum(ha)) == QL_SUCCESS) {
252011924SDaniel.Beauregard@Sun.COM /* Verify checksum of loaded RISC code. */
25217836SJohn.Forte@Sun.COM /* Start firmware execution. */
25227836SJohn.Forte@Sun.COM (void) ql_execute_fw(ha);
25237836SJohn.Forte@Sun.COM
25247836SJohn.Forte@Sun.COM /* Save firmware version. */
252511924SDaniel.Beauregard@Sun.COM (void) ql_get_fw_version(ha, &mr, MAILBOX_TOV);
25267836SJohn.Forte@Sun.COM ha->fw_major_version = mr.mb[1];
25277836SJohn.Forte@Sun.COM ha->fw_minor_version = mr.mb[2];
25287836SJohn.Forte@Sun.COM ha->fw_subminor_version = mr.mb[3];
25297836SJohn.Forte@Sun.COM ha->fw_ext_memory_size = ((SHORT_TO_LONG(mr.mb[4], mr.mb[5]) -
25307836SJohn.Forte@Sun.COM 0x100000) + 1) * 4;
25317836SJohn.Forte@Sun.COM ha->fw_attributes = mr.mb[6];
25327836SJohn.Forte@Sun.COM
25339446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_81XX)) {
25349446SDaniel.Beauregard@Sun.COM ha->phy_fw_major_version = LSB(mr.mb[8]);
25359446SDaniel.Beauregard@Sun.COM ha->phy_fw_minor_version = MSB(mr.mb[9]);
25369446SDaniel.Beauregard@Sun.COM ha->phy_fw_subminor_version = LSB(mr.mb[9]);
25379446SDaniel.Beauregard@Sun.COM ha->mpi_fw_major_version = LSB(mr.mb[10]);
25389446SDaniel.Beauregard@Sun.COM ha->mpi_fw_minor_version = MSB(mr.mb[11]);
25399446SDaniel.Beauregard@Sun.COM ha->mpi_fw_subminor_version = LSB(mr.mb[11]);
25409446SDaniel.Beauregard@Sun.COM ha->mpi_capability_list = SHORT_TO_LONG(mr.mb[13],
25419446SDaniel.Beauregard@Sun.COM mr.mb[12]);
25429446SDaniel.Beauregard@Sun.COM if ((rval2 = ql_flash_access(ha, FAC_GET_SECTOR_SIZE,
25439446SDaniel.Beauregard@Sun.COM 0, 0, &data)) == QL_SUCCESS) {
25449446SDaniel.Beauregard@Sun.COM ha->xioctl->fdesc.block_size = data << 2;
25459446SDaniel.Beauregard@Sun.COM QL_PRINT_10(CE_CONT, "(%d): fdesc.block_size="
25469446SDaniel.Beauregard@Sun.COM "%xh\n", ha->instance,
25479446SDaniel.Beauregard@Sun.COM ha->xioctl->fdesc.block_size);
25489446SDaniel.Beauregard@Sun.COM } else {
25499446SDaniel.Beauregard@Sun.COM EL(ha, "flash_access status=%xh\n", rval2);
25509446SDaniel.Beauregard@Sun.COM }
25519446SDaniel.Beauregard@Sun.COM }
25529446SDaniel.Beauregard@Sun.COM
25537836SJohn.Forte@Sun.COM /* Set Serdes Transmit Parameters. */
25549446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_2422) && ha->serdes_param[0] & BIT_0) {
25557836SJohn.Forte@Sun.COM mr.mb[1] = ha->serdes_param[0];
25567836SJohn.Forte@Sun.COM mr.mb[2] = ha->serdes_param[1];
25577836SJohn.Forte@Sun.COM mr.mb[3] = ha->serdes_param[2];
25587836SJohn.Forte@Sun.COM mr.mb[4] = ha->serdes_param[3];
25597836SJohn.Forte@Sun.COM (void) ql_serdes_param(ha, &mr);
25607836SJohn.Forte@Sun.COM }
25617836SJohn.Forte@Sun.COM }
2562*12279SDaniel.Beauregard@Sun.COM /* ETS workaround */
2563*12279SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_81XX) && ql_enable_ets) {
2564*12279SDaniel.Beauregard@Sun.COM if (ql_get_firmware_option(ha, &mr) == QL_SUCCESS) {
2565*12279SDaniel.Beauregard@Sun.COM mr.mb[2] = (uint16_t)
2566*12279SDaniel.Beauregard@Sun.COM (mr.mb[2] | FO2_FCOE_512_MAX_MEM_WR_BURST);
2567*12279SDaniel.Beauregard@Sun.COM (void) ql_set_firmware_option(ha, &mr);
2568*12279SDaniel.Beauregard@Sun.COM }
2569*12279SDaniel.Beauregard@Sun.COM }
25707836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
25717836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~FIRMWARE_LOADED;
25727836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
25737836SJohn.Forte@Sun.COM } else {
25747836SJohn.Forte@Sun.COM ha->task_daemon_flags |= FIRMWARE_LOADED;
25757836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
25767836SJohn.Forte@Sun.COM }
25777836SJohn.Forte@Sun.COM return (rval);
25787836SJohn.Forte@Sun.COM }
25797836SJohn.Forte@Sun.COM
25807836SJohn.Forte@Sun.COM /*
25817836SJohn.Forte@Sun.COM * ql_set_cache_line
25827836SJohn.Forte@Sun.COM * Sets PCI cache line parameter.
25837836SJohn.Forte@Sun.COM *
25847836SJohn.Forte@Sun.COM * Input:
25857836SJohn.Forte@Sun.COM * ha = adapter state pointer.
25867836SJohn.Forte@Sun.COM *
25877836SJohn.Forte@Sun.COM * Returns:
25887836SJohn.Forte@Sun.COM * ql local function return status code.
25897836SJohn.Forte@Sun.COM *
25907836SJohn.Forte@Sun.COM * Context:
25917836SJohn.Forte@Sun.COM * Kernel context.
25927836SJohn.Forte@Sun.COM */
25937836SJohn.Forte@Sun.COM int
ql_set_cache_line(ql_adapter_state_t * ha)25947836SJohn.Forte@Sun.COM ql_set_cache_line(ql_adapter_state_t *ha)
25957836SJohn.Forte@Sun.COM {
25967836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
25977836SJohn.Forte@Sun.COM
25987836SJohn.Forte@Sun.COM /* Set the cache line. */
25997836SJohn.Forte@Sun.COM if (CFG_IST(ha->pha, CFG_SET_CACHE_LINE_SIZE_1)) {
26007836SJohn.Forte@Sun.COM /* Set cache line register. */
26017836SJohn.Forte@Sun.COM ql_pci_config_put8(ha->pha, PCI_CONF_CACHE_LINESZ, 1);
26027836SJohn.Forte@Sun.COM }
26037836SJohn.Forte@Sun.COM
26047836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
26057836SJohn.Forte@Sun.COM
26067836SJohn.Forte@Sun.COM return (QL_SUCCESS);
26077836SJohn.Forte@Sun.COM }
26087836SJohn.Forte@Sun.COM
26097836SJohn.Forte@Sun.COM /*
26107836SJohn.Forte@Sun.COM * ql_init_rings
26117836SJohn.Forte@Sun.COM * Initializes firmware and ring pointers.
26127836SJohn.Forte@Sun.COM *
26137836SJohn.Forte@Sun.COM * Beginning of response ring has initialization control block
26147836SJohn.Forte@Sun.COM * already built by nvram config routine.
26157836SJohn.Forte@Sun.COM *
26167836SJohn.Forte@Sun.COM * Input:
26177836SJohn.Forte@Sun.COM * ha = adapter state pointer.
26187836SJohn.Forte@Sun.COM * ha->hba_buf = request and response rings
26197836SJohn.Forte@Sun.COM * ha->init_ctrl_blk = initialization control block
26207836SJohn.Forte@Sun.COM *
26217836SJohn.Forte@Sun.COM * Returns:
26227836SJohn.Forte@Sun.COM * ql local function return status code.
26237836SJohn.Forte@Sun.COM *
26247836SJohn.Forte@Sun.COM * Context:
26257836SJohn.Forte@Sun.COM * Kernel context.
26267836SJohn.Forte@Sun.COM */
26277836SJohn.Forte@Sun.COM int
ql_init_rings(ql_adapter_state_t * vha2)26287836SJohn.Forte@Sun.COM ql_init_rings(ql_adapter_state_t *vha2)
26297836SJohn.Forte@Sun.COM {
26307836SJohn.Forte@Sun.COM int rval, rval2;
26317836SJohn.Forte@Sun.COM uint16_t index;
26327836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
26337836SJohn.Forte@Sun.COM ql_adapter_state_t *ha = vha2->pha;
26347836SJohn.Forte@Sun.COM
26357836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
26367836SJohn.Forte@Sun.COM
26377836SJohn.Forte@Sun.COM /* Clear outstanding commands array. */
26387836SJohn.Forte@Sun.COM for (index = 0; index < MAX_OUTSTANDING_COMMANDS; index++) {
26397836SJohn.Forte@Sun.COM ha->outstanding_cmds[index] = NULL;
26407836SJohn.Forte@Sun.COM }
26417836SJohn.Forte@Sun.COM ha->osc_index = 1;
26427836SJohn.Forte@Sun.COM
26437836SJohn.Forte@Sun.COM ha->pending_cmds.first = NULL;
26447836SJohn.Forte@Sun.COM ha->pending_cmds.last = NULL;
26457836SJohn.Forte@Sun.COM
26467836SJohn.Forte@Sun.COM /* Initialize firmware. */
26477836SJohn.Forte@Sun.COM ha->request_ring_ptr = ha->request_ring_bp;
26487836SJohn.Forte@Sun.COM ha->req_ring_index = 0;
26497836SJohn.Forte@Sun.COM ha->req_q_cnt = REQUEST_ENTRY_CNT - 1;
26507836SJohn.Forte@Sun.COM ha->response_ring_ptr = ha->response_ring_bp;
26517836SJohn.Forte@Sun.COM ha->rsp_ring_index = 0;
26527836SJohn.Forte@Sun.COM
26537836SJohn.Forte@Sun.COM if (ha->flags & VP_ENABLED) {
26547836SJohn.Forte@Sun.COM ql_adapter_state_t *vha;
26557836SJohn.Forte@Sun.COM uint16_t cnt;
26567836SJohn.Forte@Sun.COM uint32_t max_vports;
26577836SJohn.Forte@Sun.COM ql_init_24xx_cb_t *icb = &ha->init_ctrl_blk.cb24;
26587836SJohn.Forte@Sun.COM
26597836SJohn.Forte@Sun.COM max_vports = (CFG_IST(ha, CFG_CTRL_2422) ?
26607836SJohn.Forte@Sun.COM MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS);
26617836SJohn.Forte@Sun.COM bzero(icb->vp_count,
26627836SJohn.Forte@Sun.COM ((uintptr_t)icb + sizeof (ql_init_24xx_cb_t)) -
26637836SJohn.Forte@Sun.COM (uintptr_t)icb->vp_count);
26647836SJohn.Forte@Sun.COM icb->vp_count[0] = (uint8_t)max_vports;
26657836SJohn.Forte@Sun.COM
26667836SJohn.Forte@Sun.COM /* Allow connection option 2. */
26677836SJohn.Forte@Sun.COM icb->global_vp_option[0] = BIT_1;
26687836SJohn.Forte@Sun.COM
26697836SJohn.Forte@Sun.COM for (cnt = 0, vha = ha->vp_next; cnt < max_vports &&
26707836SJohn.Forte@Sun.COM vha != NULL; vha = vha->vp_next, cnt++) {
26717836SJohn.Forte@Sun.COM
26727836SJohn.Forte@Sun.COM index = (uint8_t)(vha->vp_index - 1);
26737836SJohn.Forte@Sun.COM bcopy(vha->loginparams.node_ww_name.raw_wwn,
26747836SJohn.Forte@Sun.COM icb->vpc[index].node_name, 8);
26757836SJohn.Forte@Sun.COM bcopy(vha->loginparams.nport_ww_name.raw_wwn,
26767836SJohn.Forte@Sun.COM icb->vpc[index].port_name, 8);
26777836SJohn.Forte@Sun.COM
26787836SJohn.Forte@Sun.COM icb->vpc[index].options = VPO_TARGET_MODE_DISABLED |
26797836SJohn.Forte@Sun.COM VPO_INITIATOR_MODE_ENABLED;
26807836SJohn.Forte@Sun.COM if (vha->flags & VP_ENABLED) {
26817836SJohn.Forte@Sun.COM icb->vpc[index].options = (uint8_t)
26827836SJohn.Forte@Sun.COM (icb->vpc[index].options | VPO_ENABLED);
26837836SJohn.Forte@Sun.COM }
26847836SJohn.Forte@Sun.COM }
26857836SJohn.Forte@Sun.COM }
26867836SJohn.Forte@Sun.COM
268711924SDaniel.Beauregard@Sun.COM for (index = 0; index < 2; index++) {
268811924SDaniel.Beauregard@Sun.COM rval = ql_init_firmware(ha);
268911924SDaniel.Beauregard@Sun.COM if (rval == QL_COMMAND_ERROR) {
269011924SDaniel.Beauregard@Sun.COM EL(ha, "stopping firmware\n");
269111924SDaniel.Beauregard@Sun.COM (void) ql_stop_firmware(ha);
269211924SDaniel.Beauregard@Sun.COM } else {
269311924SDaniel.Beauregard@Sun.COM break;
269411924SDaniel.Beauregard@Sun.COM }
269511924SDaniel.Beauregard@Sun.COM }
269611924SDaniel.Beauregard@Sun.COM
269711924SDaniel.Beauregard@Sun.COM if (rval == QL_SUCCESS && (CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
26987836SJohn.Forte@Sun.COM /* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */
26997836SJohn.Forte@Sun.COM rval = ql_get_firmware_option(ha, &mr);
27007836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
27017836SJohn.Forte@Sun.COM mr.mb[1] = (uint16_t)(mr.mb[1] | BIT_9);
27027836SJohn.Forte@Sun.COM mr.mb[2] = 0;
27037836SJohn.Forte@Sun.COM mr.mb[3] = BIT_10;
27047836SJohn.Forte@Sun.COM rval = ql_set_firmware_option(ha, &mr);
27057836SJohn.Forte@Sun.COM }
27067836SJohn.Forte@Sun.COM }
27077836SJohn.Forte@Sun.COM
27087836SJohn.Forte@Sun.COM if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWFCETRACE))) {
27099156SDaniel.Beauregard@Sun.COM /* Firmware Fibre Channel Event Trace Buffer */
27109156SDaniel.Beauregard@Sun.COM if ((rval2 = ql_get_dma_mem(ha, &ha->fwfcetracebuf, FWFCESIZE,
27119156SDaniel.Beauregard@Sun.COM LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
27127836SJohn.Forte@Sun.COM EL(ha, "fcetrace buffer alloc failed: %xh\n", rval2);
27137836SJohn.Forte@Sun.COM } else {
27147836SJohn.Forte@Sun.COM if ((rval2 = ql_fw_etrace(ha, &ha->fwfcetracebuf,
27159156SDaniel.Beauregard@Sun.COM FTO_FCE_TRACE_ENABLE)) != QL_SUCCESS) {
27167836SJohn.Forte@Sun.COM EL(ha, "fcetrace enable failed: %xh\n", rval2);
27177836SJohn.Forte@Sun.COM ql_free_phys(ha, &ha->fwfcetracebuf);
27187836SJohn.Forte@Sun.COM }
27197836SJohn.Forte@Sun.COM }
27207836SJohn.Forte@Sun.COM }
27217836SJohn.Forte@Sun.COM
27227836SJohn.Forte@Sun.COM if ((rval == QL_SUCCESS) && (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE))) {
27239156SDaniel.Beauregard@Sun.COM /* Firmware Extended Trace Buffer */
27249156SDaniel.Beauregard@Sun.COM if ((rval2 = ql_get_dma_mem(ha, &ha->fwexttracebuf, FWEXTSIZE,
27259156SDaniel.Beauregard@Sun.COM LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
27267836SJohn.Forte@Sun.COM EL(ha, "exttrace buffer alloc failed: %xh\n", rval2);
27277836SJohn.Forte@Sun.COM } else {
27287836SJohn.Forte@Sun.COM if ((rval2 = ql_fw_etrace(ha, &ha->fwexttracebuf,
27299156SDaniel.Beauregard@Sun.COM FTO_EXT_TRACE_ENABLE)) != QL_SUCCESS) {
27307836SJohn.Forte@Sun.COM EL(ha, "exttrace enable failed: %xh\n", rval2);
27317836SJohn.Forte@Sun.COM ql_free_phys(ha, &ha->fwexttracebuf);
27327836SJohn.Forte@Sun.COM }
27337836SJohn.Forte@Sun.COM }
27347836SJohn.Forte@Sun.COM }
27357836SJohn.Forte@Sun.COM
27367836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && CFG_IST(ha, CFG_CTRL_MENLO)) {
27377836SJohn.Forte@Sun.COM ql_mbx_iocb_t *pkt;
27387836SJohn.Forte@Sun.COM clock_t timer;
27397836SJohn.Forte@Sun.COM
27407836SJohn.Forte@Sun.COM /* Wait for firmware login of menlo. */
27417836SJohn.Forte@Sun.COM for (timer = 3000; timer; timer--) {
27427836SJohn.Forte@Sun.COM if (ha->flags & MENLO_LOGIN_OPERATIONAL) {
27437836SJohn.Forte@Sun.COM break;
27447836SJohn.Forte@Sun.COM }
27457836SJohn.Forte@Sun.COM
27467836SJohn.Forte@Sun.COM if (!(ha->flags & INTERRUPTS_ENABLED) ||
27477836SJohn.Forte@Sun.COM ddi_in_panic()) {
274811924SDaniel.Beauregard@Sun.COM if (INTERRUPT_PENDING(ha)) {
27497836SJohn.Forte@Sun.COM (void) ql_isr((caddr_t)ha);
27507836SJohn.Forte@Sun.COM INTR_LOCK(ha);
27517836SJohn.Forte@Sun.COM ha->intr_claimed = B_TRUE;
27527836SJohn.Forte@Sun.COM INTR_UNLOCK(ha);
27537836SJohn.Forte@Sun.COM }
27547836SJohn.Forte@Sun.COM }
27557836SJohn.Forte@Sun.COM
27567836SJohn.Forte@Sun.COM /* Delay for 1 tick (10 milliseconds). */
27577836SJohn.Forte@Sun.COM ql_delay(ha, 10000);
27587836SJohn.Forte@Sun.COM }
27597836SJohn.Forte@Sun.COM
27607836SJohn.Forte@Sun.COM if (timer == 0) {
27617836SJohn.Forte@Sun.COM rval = QL_FUNCTION_TIMEOUT;
27627836SJohn.Forte@Sun.COM } else {
27637836SJohn.Forte@Sun.COM pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
27647836SJohn.Forte@Sun.COM if (pkt == NULL) {
27657836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
27667836SJohn.Forte@Sun.COM rval = QL_MEMORY_ALLOC_FAILED;
27677836SJohn.Forte@Sun.COM } else {
27687836SJohn.Forte@Sun.COM pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
27697836SJohn.Forte@Sun.COM pkt->mvfy.entry_count = 1;
27707836SJohn.Forte@Sun.COM pkt->mvfy.options_status =
27717836SJohn.Forte@Sun.COM LE_16(VMF_DO_NOT_UPDATE_FW);
27727836SJohn.Forte@Sun.COM
27737836SJohn.Forte@Sun.COM rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
27747836SJohn.Forte@Sun.COM sizeof (ql_mbx_iocb_t));
27757836SJohn.Forte@Sun.COM LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
27767836SJohn.Forte@Sun.COM LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
27777836SJohn.Forte@Sun.COM
27787836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS ||
27797836SJohn.Forte@Sun.COM (pkt->mvfy.entry_status & 0x3c) != 0 ||
27807836SJohn.Forte@Sun.COM pkt->mvfy.options_status != CS_COMPLETE) {
27817836SJohn.Forte@Sun.COM EL(ha, "failed, status=%xh, es=%xh, "
27827836SJohn.Forte@Sun.COM "cs=%xh, fc=%xh\n", rval,
27837836SJohn.Forte@Sun.COM pkt->mvfy.entry_status & 0x3c,
27847836SJohn.Forte@Sun.COM pkt->mvfy.options_status,
27857836SJohn.Forte@Sun.COM pkt->mvfy.failure_code);
27867836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
27877836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
27887836SJohn.Forte@Sun.COM }
27897836SJohn.Forte@Sun.COM }
27907836SJohn.Forte@Sun.COM
27917836SJohn.Forte@Sun.COM kmem_free(pkt, sizeof (ql_mbx_iocb_t));
27927836SJohn.Forte@Sun.COM }
27937836SJohn.Forte@Sun.COM }
27947836SJohn.Forte@Sun.COM }
27957836SJohn.Forte@Sun.COM
27967836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
27977836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
27987836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~FIRMWARE_UP;
27997836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
28007836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
28017836SJohn.Forte@Sun.COM } else {
28027836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
28037836SJohn.Forte@Sun.COM ha->task_daemon_flags |= FIRMWARE_UP;
28047836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
28057836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
28067836SJohn.Forte@Sun.COM }
28077836SJohn.Forte@Sun.COM return (rval);
28087836SJohn.Forte@Sun.COM }
28097836SJohn.Forte@Sun.COM
28107836SJohn.Forte@Sun.COM /*
28117836SJohn.Forte@Sun.COM * ql_fw_ready
28127836SJohn.Forte@Sun.COM * Waits for firmware ready. If firmware becomes ready
28137836SJohn.Forte@Sun.COM * device queues and RISC code are synchronized.
28147836SJohn.Forte@Sun.COM *
28157836SJohn.Forte@Sun.COM * Input:
28167836SJohn.Forte@Sun.COM * ha = adapter state pointer.
28177836SJohn.Forte@Sun.COM * secs = max wait time, in seconds (0-255).
28187836SJohn.Forte@Sun.COM *
28197836SJohn.Forte@Sun.COM * Returns:
28207836SJohn.Forte@Sun.COM * ql local function return status code.
28217836SJohn.Forte@Sun.COM *
28227836SJohn.Forte@Sun.COM * Context:
28237836SJohn.Forte@Sun.COM * Kernel context.
28247836SJohn.Forte@Sun.COM */
28257836SJohn.Forte@Sun.COM int
ql_fw_ready(ql_adapter_state_t * ha,uint8_t secs)28267836SJohn.Forte@Sun.COM ql_fw_ready(ql_adapter_state_t *ha, uint8_t secs)
28277836SJohn.Forte@Sun.COM {
28287836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
28297836SJohn.Forte@Sun.COM clock_t timer;
28307836SJohn.Forte@Sun.COM clock_t dly = 250000;
28317836SJohn.Forte@Sun.COM clock_t sec_delay = MICROSEC / dly;
28327836SJohn.Forte@Sun.COM clock_t wait = secs * sec_delay;
28337836SJohn.Forte@Sun.COM int rval = QL_FUNCTION_FAILED;
28347836SJohn.Forte@Sun.COM uint16_t state = 0xffff;
28357836SJohn.Forte@Sun.COM
28367836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
28377836SJohn.Forte@Sun.COM
28387836SJohn.Forte@Sun.COM timer = ha->r_a_tov < secs ? secs : ha->r_a_tov;
28397836SJohn.Forte@Sun.COM timer = (timer + 2) * sec_delay;
28407836SJohn.Forte@Sun.COM
28417836SJohn.Forte@Sun.COM /* Wait for ISP to finish LIP */
28427836SJohn.Forte@Sun.COM while (timer != 0 && wait != 0 &&
28437836SJohn.Forte@Sun.COM !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
28447836SJohn.Forte@Sun.COM
28457836SJohn.Forte@Sun.COM rval = ql_get_firmware_state(ha, &mr);
28467836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
28477836SJohn.Forte@Sun.COM if (ha->task_daemon_flags & (ISP_ABORT_NEEDED |
28487836SJohn.Forte@Sun.COM LOOP_DOWN)) {
28497836SJohn.Forte@Sun.COM wait--;
28507836SJohn.Forte@Sun.COM } else if (mr.mb[1] != FSTATE_READY) {
28517836SJohn.Forte@Sun.COM if (mr.mb[1] != FSTATE_WAIT_LOGIN) {
28527836SJohn.Forte@Sun.COM wait--;
28537836SJohn.Forte@Sun.COM }
28547836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
28557836SJohn.Forte@Sun.COM } else {
28567836SJohn.Forte@Sun.COM /* Firmware is ready. Get 2 * R_A_TOV. */
28577836SJohn.Forte@Sun.COM rval = ql_get_timeout_parameters(ha,
28587836SJohn.Forte@Sun.COM &ha->r_a_tov);
28597836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
28607836SJohn.Forte@Sun.COM EL(ha, "failed, get_timeout_param"
28617836SJohn.Forte@Sun.COM "=%xh\n", rval);
28627836SJohn.Forte@Sun.COM }
28637836SJohn.Forte@Sun.COM
28647836SJohn.Forte@Sun.COM /* Configure loop. */
28657836SJohn.Forte@Sun.COM rval = ql_configure_loop(ha);
28667836SJohn.Forte@Sun.COM (void) ql_marker(ha, 0, 0, MK_SYNC_ALL);
28677836SJohn.Forte@Sun.COM
28687836SJohn.Forte@Sun.COM if (ha->task_daemon_flags &
28697836SJohn.Forte@Sun.COM LOOP_RESYNC_NEEDED) {
28707836SJohn.Forte@Sun.COM wait--;
28717836SJohn.Forte@Sun.COM EL(ha, "loop trans; tdf=%xh\n",
28727836SJohn.Forte@Sun.COM ha->task_daemon_flags);
28737836SJohn.Forte@Sun.COM } else {
28747836SJohn.Forte@Sun.COM break;
28757836SJohn.Forte@Sun.COM }
28767836SJohn.Forte@Sun.COM }
28777836SJohn.Forte@Sun.COM } else {
28787836SJohn.Forte@Sun.COM wait--;
28797836SJohn.Forte@Sun.COM }
28807836SJohn.Forte@Sun.COM
28817836SJohn.Forte@Sun.COM if (state != mr.mb[1]) {
28827836SJohn.Forte@Sun.COM EL(ha, "mailbox_reg[1] = %xh\n", mr.mb[1]);
28837836SJohn.Forte@Sun.COM state = mr.mb[1];
28847836SJohn.Forte@Sun.COM }
28857836SJohn.Forte@Sun.COM
28867836SJohn.Forte@Sun.COM /* Delay for a tick if waiting. */
28877836SJohn.Forte@Sun.COM if (timer-- != 0 && wait != 0) {
28887836SJohn.Forte@Sun.COM if (timer % 4 == 0) {
28897836SJohn.Forte@Sun.COM delay(drv_usectohz(dly));
28907836SJohn.Forte@Sun.COM } else {
28917836SJohn.Forte@Sun.COM drv_usecwait(dly);
28927836SJohn.Forte@Sun.COM }
28937836SJohn.Forte@Sun.COM } else {
28947836SJohn.Forte@Sun.COM rval = QL_FUNCTION_TIMEOUT;
28957836SJohn.Forte@Sun.COM }
28967836SJohn.Forte@Sun.COM }
28977836SJohn.Forte@Sun.COM
28987836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
28997836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
29007836SJohn.Forte@Sun.COM } else {
29017836SJohn.Forte@Sun.COM /*EMPTY*/
29027836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
29037836SJohn.Forte@Sun.COM }
29047836SJohn.Forte@Sun.COM return (rval);
29057836SJohn.Forte@Sun.COM }
29067836SJohn.Forte@Sun.COM
29077836SJohn.Forte@Sun.COM /*
29087836SJohn.Forte@Sun.COM * ql_configure_loop
29097836SJohn.Forte@Sun.COM * Setup configurations based on loop.
29107836SJohn.Forte@Sun.COM *
29117836SJohn.Forte@Sun.COM * Input:
29127836SJohn.Forte@Sun.COM * ha = adapter state pointer.
29137836SJohn.Forte@Sun.COM *
29147836SJohn.Forte@Sun.COM * Returns:
29157836SJohn.Forte@Sun.COM * ql local function return status code.
29167836SJohn.Forte@Sun.COM *
29177836SJohn.Forte@Sun.COM * Context:
29187836SJohn.Forte@Sun.COM * Kernel context.
29197836SJohn.Forte@Sun.COM */
29207836SJohn.Forte@Sun.COM static int
ql_configure_loop(ql_adapter_state_t * ha)29217836SJohn.Forte@Sun.COM ql_configure_loop(ql_adapter_state_t *ha)
29227836SJohn.Forte@Sun.COM {
29237836SJohn.Forte@Sun.COM int rval;
29247836SJohn.Forte@Sun.COM ql_adapter_state_t *vha;
29257836SJohn.Forte@Sun.COM
29267836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
29277836SJohn.Forte@Sun.COM
29287836SJohn.Forte@Sun.COM for (vha = ha; vha != NULL; vha = vha->vp_next) {
29297836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
29307836SJohn.Forte@Sun.COM if (!(vha->task_daemon_flags & LOOP_RESYNC_NEEDED) &&
29317836SJohn.Forte@Sun.COM vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
29327836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
29337836SJohn.Forte@Sun.COM continue;
29347836SJohn.Forte@Sun.COM }
29357836SJohn.Forte@Sun.COM vha->task_daemon_flags &= ~LOOP_RESYNC_NEEDED;
29367836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
29377836SJohn.Forte@Sun.COM
29387836SJohn.Forte@Sun.COM rval = ql_configure_hba(vha);
29397836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
29407836SJohn.Forte@Sun.COM (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
29417836SJohn.Forte@Sun.COM rval = ql_configure_device_d_id(vha);
29427836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && !(ha->task_daemon_flags &
29437836SJohn.Forte@Sun.COM (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
29447836SJohn.Forte@Sun.COM (void) ql_configure_fabric(vha);
29457836SJohn.Forte@Sun.COM }
29467836SJohn.Forte@Sun.COM }
29477836SJohn.Forte@Sun.COM }
29487836SJohn.Forte@Sun.COM
29497836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
29507836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
29517836SJohn.Forte@Sun.COM } else {
29527836SJohn.Forte@Sun.COM /*EMPTY*/
29537836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
29547836SJohn.Forte@Sun.COM }
29557836SJohn.Forte@Sun.COM return (rval);
29567836SJohn.Forte@Sun.COM }
29577836SJohn.Forte@Sun.COM
29587836SJohn.Forte@Sun.COM /*
29599446SDaniel.Beauregard@Sun.COM * ql_configure_n_port_info
29609446SDaniel.Beauregard@Sun.COM * Setup configurations based on N port 2 N port topology.
29619446SDaniel.Beauregard@Sun.COM *
29629446SDaniel.Beauregard@Sun.COM * Input:
29639446SDaniel.Beauregard@Sun.COM * ha = adapter state pointer.
29649446SDaniel.Beauregard@Sun.COM *
29659446SDaniel.Beauregard@Sun.COM * Returns:
29669446SDaniel.Beauregard@Sun.COM * ql local function return status code.
29679446SDaniel.Beauregard@Sun.COM *
29689446SDaniel.Beauregard@Sun.COM * Context:
29699446SDaniel.Beauregard@Sun.COM * Kernel context.
29709446SDaniel.Beauregard@Sun.COM */
29719446SDaniel.Beauregard@Sun.COM static void
ql_configure_n_port_info(ql_adapter_state_t * ha)29729446SDaniel.Beauregard@Sun.COM ql_configure_n_port_info(ql_adapter_state_t *ha)
29739446SDaniel.Beauregard@Sun.COM {
29749446SDaniel.Beauregard@Sun.COM ql_tgt_t tmp_tq;
29759446SDaniel.Beauregard@Sun.COM ql_tgt_t *tq;
29769446SDaniel.Beauregard@Sun.COM uint8_t *cb_port_name;
29779446SDaniel.Beauregard@Sun.COM ql_link_t *link;
29789446SDaniel.Beauregard@Sun.COM int index, rval;
29799446SDaniel.Beauregard@Sun.COM
29809446SDaniel.Beauregard@Sun.COM tq = &tmp_tq;
29819446SDaniel.Beauregard@Sun.COM
29829446SDaniel.Beauregard@Sun.COM /* Free existing target queues. */
29839446SDaniel.Beauregard@Sun.COM for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
29849446SDaniel.Beauregard@Sun.COM link = ha->dev[index].first;
29859446SDaniel.Beauregard@Sun.COM while (link != NULL) {
29869446SDaniel.Beauregard@Sun.COM tq = link->base_address;
29879446SDaniel.Beauregard@Sun.COM link = link->next;
29889446SDaniel.Beauregard@Sun.COM ql_remove_link(&ha->dev[index], &tq->device);
29899446SDaniel.Beauregard@Sun.COM ql_dev_free(ha, tq);
29909446SDaniel.Beauregard@Sun.COM }
29919446SDaniel.Beauregard@Sun.COM }
29929446SDaniel.Beauregard@Sun.COM
29939446SDaniel.Beauregard@Sun.COM /*
29949446SDaniel.Beauregard@Sun.COM * If the N_Port's WWPN is larger than our's then it has the
29959446SDaniel.Beauregard@Sun.COM * N_Port login initiative. It will have determined that and
29969446SDaniel.Beauregard@Sun.COM * logged in with the firmware. This results in a device
29979446SDaniel.Beauregard@Sun.COM * database entry. In this situation we will later send up a PLOGI
29989446SDaniel.Beauregard@Sun.COM * by proxy for the N_Port to get things going.
29999446SDaniel.Beauregard@Sun.COM *
30009446SDaniel.Beauregard@Sun.COM * If the N_Ports WWPN is smaller then the firmware has the
30019446SDaniel.Beauregard@Sun.COM * N_Port login initiative and does a FLOGI in order to obtain the
30029446SDaniel.Beauregard@Sun.COM * N_Ports WWNN and WWPN. These names are required later
30039446SDaniel.Beauregard@Sun.COM * during Leadvilles FLOGI. No PLOGI is done by the firmware in
30049446SDaniel.Beauregard@Sun.COM * anticipation of a PLOGI via the driver from the upper layers.
30059446SDaniel.Beauregard@Sun.COM * Upon reciept of said PLOGI the driver issues an ELS PLOGI
30069446SDaniel.Beauregard@Sun.COM * pass-through command and the firmware assumes the s_id
30079446SDaniel.Beauregard@Sun.COM * and the N_Port assumes the d_id and Bob's your uncle.
30089446SDaniel.Beauregard@Sun.COM */
30099446SDaniel.Beauregard@Sun.COM
30109446SDaniel.Beauregard@Sun.COM /*
30119446SDaniel.Beauregard@Sun.COM * In N port 2 N port topology the FW provides a port database entry at
30129446SDaniel.Beauregard@Sun.COM * loop_id 0x7fe which allows us to acquire the Ports WWPN.
30139446SDaniel.Beauregard@Sun.COM */
30149446SDaniel.Beauregard@Sun.COM tq->d_id.b.al_pa = 0;
30159446SDaniel.Beauregard@Sun.COM tq->d_id.b.area = 0;
30169446SDaniel.Beauregard@Sun.COM tq->d_id.b.domain = 0;
30179446SDaniel.Beauregard@Sun.COM tq->loop_id = 0x7fe;
30189446SDaniel.Beauregard@Sun.COM
30199446SDaniel.Beauregard@Sun.COM rval = ql_get_port_database(ha, tq, PDF_NONE);
30209446SDaniel.Beauregard@Sun.COM if (rval == QL_SUCCESS || rval == QL_NOT_LOGGED_IN) {
30219446SDaniel.Beauregard@Sun.COM ql_dev_id_list_t *list;
30229446SDaniel.Beauregard@Sun.COM uint32_t list_size;
30239446SDaniel.Beauregard@Sun.COM ql_mbx_data_t mr;
30249446SDaniel.Beauregard@Sun.COM port_id_t d_id = {0, 0, 0, 0};
30259446SDaniel.Beauregard@Sun.COM uint16_t loop_id = 0;
30269446SDaniel.Beauregard@Sun.COM
302711924SDaniel.Beauregard@Sun.COM cb_port_name = (uint8_t *)(CFG_IST(ha, CFG_CTRL_24258081) ?
30289446SDaniel.Beauregard@Sun.COM &ha->init_ctrl_blk.cb24.port_name[0] :
30299446SDaniel.Beauregard@Sun.COM &ha->init_ctrl_blk.cb.port_name[0]);
30309446SDaniel.Beauregard@Sun.COM
30319446SDaniel.Beauregard@Sun.COM if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0],
30329446SDaniel.Beauregard@Sun.COM (la_wwn_t *)cb_port_name) == 1)) {
30339446SDaniel.Beauregard@Sun.COM EL(ha, "target port has N_Port login initiative\n");
30349446SDaniel.Beauregard@Sun.COM } else {
30359446SDaniel.Beauregard@Sun.COM EL(ha, "host port has N_Port login initiative\n");
30369446SDaniel.Beauregard@Sun.COM }
30379446SDaniel.Beauregard@Sun.COM
30389446SDaniel.Beauregard@Sun.COM /* Capture the N Ports WWPN */
30399446SDaniel.Beauregard@Sun.COM
30409446SDaniel.Beauregard@Sun.COM bcopy((void *)&tq->port_name[0],
30419446SDaniel.Beauregard@Sun.COM (void *)&ha->n_port->port_name[0], 8);
30429446SDaniel.Beauregard@Sun.COM bcopy((void *)&tq->node_name[0],
30439446SDaniel.Beauregard@Sun.COM (void *)&ha->n_port->node_name[0], 8);
30449446SDaniel.Beauregard@Sun.COM
30459446SDaniel.Beauregard@Sun.COM /* Resolve an n_port_handle */
30469446SDaniel.Beauregard@Sun.COM ha->n_port->n_port_handle = 0x7fe;
30479446SDaniel.Beauregard@Sun.COM
30489446SDaniel.Beauregard@Sun.COM list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
30499446SDaniel.Beauregard@Sun.COM list = (ql_dev_id_list_t *)kmem_zalloc(list_size, KM_SLEEP);
30509446SDaniel.Beauregard@Sun.COM
30519446SDaniel.Beauregard@Sun.COM if (list != NULL &&
30529446SDaniel.Beauregard@Sun.COM ql_get_id_list(ha, (caddr_t)list, list_size, &mr) ==
30539446SDaniel.Beauregard@Sun.COM QL_SUCCESS) {
30549446SDaniel.Beauregard@Sun.COM if (mr.mb[1]) {
30559446SDaniel.Beauregard@Sun.COM EL(ha, "id list entries = %d\n", mr.mb[1]);
30569446SDaniel.Beauregard@Sun.COM for (index = 0; index < mr.mb[1]; index++) {
30579446SDaniel.Beauregard@Sun.COM ql_dev_list(ha, list, index,
30589446SDaniel.Beauregard@Sun.COM &d_id, &loop_id);
30599446SDaniel.Beauregard@Sun.COM ha->n_port->n_port_handle = loop_id;
30609446SDaniel.Beauregard@Sun.COM }
30619446SDaniel.Beauregard@Sun.COM } else {
30629446SDaniel.Beauregard@Sun.COM for (index = 0; index <= LAST_LOCAL_LOOP_ID;
30639446SDaniel.Beauregard@Sun.COM index++) {
30649446SDaniel.Beauregard@Sun.COM /* resuse tq */
30659446SDaniel.Beauregard@Sun.COM tq->loop_id = (uint16_t)index;
30669446SDaniel.Beauregard@Sun.COM rval = ql_get_port_database(ha, tq,
30679446SDaniel.Beauregard@Sun.COM PDF_NONE);
30689446SDaniel.Beauregard@Sun.COM if (rval == QL_NOT_LOGGED_IN) {
30699446SDaniel.Beauregard@Sun.COM if (tq->master_state ==
30709446SDaniel.Beauregard@Sun.COM PD_STATE_PLOGI_PENDING) {
30719446SDaniel.Beauregard@Sun.COM ha->n_port->
30729446SDaniel.Beauregard@Sun.COM n_port_handle =
30739446SDaniel.Beauregard@Sun.COM tq->loop_id;
30749446SDaniel.Beauregard@Sun.COM break;
30759446SDaniel.Beauregard@Sun.COM }
30769446SDaniel.Beauregard@Sun.COM } else {
30779446SDaniel.Beauregard@Sun.COM ha->n_port->n_port_handle =
30789446SDaniel.Beauregard@Sun.COM tq->loop_id;
30799446SDaniel.Beauregard@Sun.COM break;
30809446SDaniel.Beauregard@Sun.COM }
30819446SDaniel.Beauregard@Sun.COM }
30829446SDaniel.Beauregard@Sun.COM }
30839446SDaniel.Beauregard@Sun.COM } else {
30849446SDaniel.Beauregard@Sun.COM cmn_err(CE_WARN, "!%s(%d) didn't get list for %xh",
30859446SDaniel.Beauregard@Sun.COM QL_NAME, ha->instance, d_id.b24);
30869446SDaniel.Beauregard@Sun.COM }
30879446SDaniel.Beauregard@Sun.COM if (list != NULL) {
30889446SDaniel.Beauregard@Sun.COM kmem_free(list, list_size);
30899446SDaniel.Beauregard@Sun.COM }
30909446SDaniel.Beauregard@Sun.COM }
30919446SDaniel.Beauregard@Sun.COM }
30929446SDaniel.Beauregard@Sun.COM
30939446SDaniel.Beauregard@Sun.COM
30949446SDaniel.Beauregard@Sun.COM /*
30957836SJohn.Forte@Sun.COM * ql_configure_hba
30967836SJohn.Forte@Sun.COM * Setup adapter context.
30977836SJohn.Forte@Sun.COM *
30987836SJohn.Forte@Sun.COM * Input:
30997836SJohn.Forte@Sun.COM * ha = adapter state pointer.
31007836SJohn.Forte@Sun.COM *
31017836SJohn.Forte@Sun.COM * Returns:
31027836SJohn.Forte@Sun.COM * ql local function return status code.
31037836SJohn.Forte@Sun.COM *
31047836SJohn.Forte@Sun.COM * Context:
31057836SJohn.Forte@Sun.COM * Kernel context.
31067836SJohn.Forte@Sun.COM */
31077836SJohn.Forte@Sun.COM static int
ql_configure_hba(ql_adapter_state_t * ha)31087836SJohn.Forte@Sun.COM ql_configure_hba(ql_adapter_state_t *ha)
31097836SJohn.Forte@Sun.COM {
31107836SJohn.Forte@Sun.COM uint8_t *bp;
31117836SJohn.Forte@Sun.COM int rval;
31127836SJohn.Forte@Sun.COM uint32_t state;
31137836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
31147836SJohn.Forte@Sun.COM
31157836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
31167836SJohn.Forte@Sun.COM
31177836SJohn.Forte@Sun.COM /* Get host addresses. */
31187836SJohn.Forte@Sun.COM rval = ql_get_adapter_id(ha, &mr);
31197836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
31207836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology &
31217836SJohn.Forte@Sun.COM ~(QL_N_PORT | QL_NL_PORT | QL_F_PORT | QL_FL_PORT));
31227836SJohn.Forte@Sun.COM
31237836SJohn.Forte@Sun.COM /* Save Host d_id, alpa, loop ID. */
31247836SJohn.Forte@Sun.COM ha->loop_id = mr.mb[1];
31257836SJohn.Forte@Sun.COM ha->d_id.b.al_pa = LSB(mr.mb[2]);
31267836SJohn.Forte@Sun.COM ha->d_id.b.area = MSB(mr.mb[2]);
31277836SJohn.Forte@Sun.COM ha->d_id.b.domain = LSB(mr.mb[3]);
31287836SJohn.Forte@Sun.COM
31297836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
31307836SJohn.Forte@Sun.COM ha->flags &= ~FDISC_ENABLED;
31317836SJohn.Forte@Sun.COM
31327836SJohn.Forte@Sun.COM /* Get loop topology. */
31337836SJohn.Forte@Sun.COM switch (mr.mb[6]) {
31347836SJohn.Forte@Sun.COM case CNX_LOOP_NO_FABRIC:
31357836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology | QL_NL_PORT);
31367836SJohn.Forte@Sun.COM break;
31377836SJohn.Forte@Sun.COM case CNX_FLPORT_IN_LOOP:
31387836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology | QL_FL_PORT);
31397836SJohn.Forte@Sun.COM break;
31407836SJohn.Forte@Sun.COM case CNX_NPORT_2_NPORT_P2P:
31417836SJohn.Forte@Sun.COM case CNX_NPORT_2_NPORT_NO_TGT_RSP:
31427836SJohn.Forte@Sun.COM ha->flags |= POINT_TO_POINT;
31437836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology | QL_N_PORT);
31449446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_2425)) {
31459446SDaniel.Beauregard@Sun.COM ql_configure_n_port_info(ha);
31469446SDaniel.Beauregard@Sun.COM }
31477836SJohn.Forte@Sun.COM break;
31487836SJohn.Forte@Sun.COM case CNX_FLPORT_P2P:
31497836SJohn.Forte@Sun.COM ha->flags |= POINT_TO_POINT;
31507836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology | QL_F_PORT);
31517836SJohn.Forte@Sun.COM
31527836SJohn.Forte@Sun.COM /* Get supported option. */
315311924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081) &&
31549446SDaniel.Beauregard@Sun.COM mr.mb[7] & GID_FP_NPIV_SUPPORT) {
31557836SJohn.Forte@Sun.COM ha->flags |= FDISC_ENABLED;
31567836SJohn.Forte@Sun.COM }
31579793SDaniel.Beauregard@Sun.COM /* Get VLAN ID, mac address */
315811924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8081)) {
31599793SDaniel.Beauregard@Sun.COM ha->fabric_params = mr.mb[7];
31609793SDaniel.Beauregard@Sun.COM ha->fcoe_vlan_id = (uint16_t)(mr.mb[9] & 0xfff);
31619793SDaniel.Beauregard@Sun.COM ha->fcoe_fcf_idx = mr.mb[10];
31629793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[0] = MSB(mr.mb[11]);
31639793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[1] = LSB(mr.mb[11]);
31649793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[2] = MSB(mr.mb[12]);
31659793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[3] = LSB(mr.mb[12]);
31669793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[4] = MSB(mr.mb[13]);
31679793SDaniel.Beauregard@Sun.COM ha->fcoe_vnport_mac[5] = LSB(mr.mb[13]);
31689793SDaniel.Beauregard@Sun.COM }
31697836SJohn.Forte@Sun.COM break;
31707836SJohn.Forte@Sun.COM default:
31717836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d,%d): UNKNOWN topology=%xh, "
31727836SJohn.Forte@Sun.COM "d_id=%xh\n", ha->instance, ha->vp_index, mr.mb[6],
31737836SJohn.Forte@Sun.COM ha->d_id.b24);
31747836SJohn.Forte@Sun.COM rval = QL_FUNCTION_FAILED;
31757836SJohn.Forte@Sun.COM break;
31767836SJohn.Forte@Sun.COM }
31777836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
31787836SJohn.Forte@Sun.COM
31799446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 |
318011924SDaniel.Beauregard@Sun.COM CFG_CTRL_24258081))) {
31817836SJohn.Forte@Sun.COM mr.mb[1] = 0;
31827836SJohn.Forte@Sun.COM mr.mb[2] = 0;
31837836SJohn.Forte@Sun.COM rval = ql_data_rate(ha, &mr);
31847836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
31857836SJohn.Forte@Sun.COM EL(ha, "data_rate status=%xh\n", rval);
31867836SJohn.Forte@Sun.COM state = FC_STATE_FULL_SPEED;
31877836SJohn.Forte@Sun.COM } else {
3188*12279SDaniel.Beauregard@Sun.COM ha->iidma_rate = mr.mb[1];
31899446SDaniel.Beauregard@Sun.COM if (mr.mb[1] == IIDMA_RATE_1GB) {
31907836SJohn.Forte@Sun.COM state = FC_STATE_1GBIT_SPEED;
31919446SDaniel.Beauregard@Sun.COM } else if (mr.mb[1] == IIDMA_RATE_2GB) {
31927836SJohn.Forte@Sun.COM state = FC_STATE_2GBIT_SPEED;
31939446SDaniel.Beauregard@Sun.COM } else if (mr.mb[1] == IIDMA_RATE_4GB) {
31947836SJohn.Forte@Sun.COM state = FC_STATE_4GBIT_SPEED;
31959446SDaniel.Beauregard@Sun.COM } else if (mr.mb[1] == IIDMA_RATE_8GB) {
31967836SJohn.Forte@Sun.COM state = FC_STATE_8GBIT_SPEED;
31979446SDaniel.Beauregard@Sun.COM } else if (mr.mb[1] == IIDMA_RATE_10GB) {
31989446SDaniel.Beauregard@Sun.COM state = FC_STATE_10GBIT_SPEED;
31997836SJohn.Forte@Sun.COM } else {
32007836SJohn.Forte@Sun.COM state = 0;
32017836SJohn.Forte@Sun.COM }
32027836SJohn.Forte@Sun.COM }
32037836SJohn.Forte@Sun.COM } else {
3204*12279SDaniel.Beauregard@Sun.COM ha->iidma_rate = IIDMA_RATE_1GB;
32057836SJohn.Forte@Sun.COM state = FC_STATE_FULL_SPEED;
32067836SJohn.Forte@Sun.COM }
32077836SJohn.Forte@Sun.COM ha->state = FC_PORT_STATE_MASK(ha->state) | state;
32089156SDaniel.Beauregard@Sun.COM } else if (rval == MBS_COMMAND_ERROR) {
32099156SDaniel.Beauregard@Sun.COM EL(ha, "mbox cmd error, rval = %xh, mr.mb[1]=%hx\n",
32109156SDaniel.Beauregard@Sun.COM rval, mr.mb[1]);
32117836SJohn.Forte@Sun.COM }
32127836SJohn.Forte@Sun.COM
32137836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
32147836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
32157836SJohn.Forte@Sun.COM } else {
32167836SJohn.Forte@Sun.COM bp = ha->loginparams.nport_ww_name.raw_wwn;
32177836SJohn.Forte@Sun.COM EL(ha, "topology=%xh, d_id=%xh, "
32187836SJohn.Forte@Sun.COM "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n",
32197836SJohn.Forte@Sun.COM ha->topology, ha->d_id.b24, bp[0], bp[1],
32207836SJohn.Forte@Sun.COM bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]);
32217836SJohn.Forte@Sun.COM }
32227836SJohn.Forte@Sun.COM return (rval);
32237836SJohn.Forte@Sun.COM }
32247836SJohn.Forte@Sun.COM
32257836SJohn.Forte@Sun.COM /*
32267836SJohn.Forte@Sun.COM * ql_configure_device_d_id
32277836SJohn.Forte@Sun.COM * Updates device loop ID.
32287836SJohn.Forte@Sun.COM * Also adds to device queue any new devices found on private loop.
32297836SJohn.Forte@Sun.COM *
32307836SJohn.Forte@Sun.COM * Input:
32317836SJohn.Forte@Sun.COM * ha = adapter state pointer.
32327836SJohn.Forte@Sun.COM *
32337836SJohn.Forte@Sun.COM * Returns:
32347836SJohn.Forte@Sun.COM * ql local function return status code.
32357836SJohn.Forte@Sun.COM *
32367836SJohn.Forte@Sun.COM * Context:
32377836SJohn.Forte@Sun.COM * Kernel context.
32387836SJohn.Forte@Sun.COM */
32397836SJohn.Forte@Sun.COM static int
ql_configure_device_d_id(ql_adapter_state_t * ha)32407836SJohn.Forte@Sun.COM ql_configure_device_d_id(ql_adapter_state_t *ha)
32417836SJohn.Forte@Sun.COM {
32427836SJohn.Forte@Sun.COM port_id_t d_id;
32437836SJohn.Forte@Sun.COM ql_link_t *link;
32447836SJohn.Forte@Sun.COM int rval;
32457836SJohn.Forte@Sun.COM int loop;
32467836SJohn.Forte@Sun.COM ql_tgt_t *tq;
32477836SJohn.Forte@Sun.COM ql_dev_id_list_t *list;
32487836SJohn.Forte@Sun.COM uint32_t list_size;
32497836SJohn.Forte@Sun.COM uint16_t index, loop_id;
32507836SJohn.Forte@Sun.COM ql_mbx_data_t mr;
32517836SJohn.Forte@Sun.COM uint8_t retries = MAX_DEVICE_LOST_RETRY;
32527836SJohn.Forte@Sun.COM
32537836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
32547836SJohn.Forte@Sun.COM
32557836SJohn.Forte@Sun.COM list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
32567836SJohn.Forte@Sun.COM list = kmem_zalloc(list_size, KM_SLEEP);
32577836SJohn.Forte@Sun.COM if (list == NULL) {
32587836SJohn.Forte@Sun.COM rval = QL_MEMORY_ALLOC_FAILED;
32597836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
32607836SJohn.Forte@Sun.COM return (rval);
32617836SJohn.Forte@Sun.COM }
32627836SJohn.Forte@Sun.COM
32637836SJohn.Forte@Sun.COM do {
32647836SJohn.Forte@Sun.COM /*
32657836SJohn.Forte@Sun.COM * Get data from RISC code d_id list to init each device queue.
32667836SJohn.Forte@Sun.COM */
32677836SJohn.Forte@Sun.COM rval = ql_get_id_list(ha, (caddr_t)list, list_size, &mr);
32687836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
32697836SJohn.Forte@Sun.COM kmem_free(list, list_size);
32707836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
32717836SJohn.Forte@Sun.COM return (rval);
32727836SJohn.Forte@Sun.COM }
32737836SJohn.Forte@Sun.COM
32747836SJohn.Forte@Sun.COM /* Acquire adapter state lock. */
32757836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
32767836SJohn.Forte@Sun.COM
32777836SJohn.Forte@Sun.COM /* Mark all queues as unusable. */
32787836SJohn.Forte@Sun.COM for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
32797836SJohn.Forte@Sun.COM for (link = ha->dev[index].first; link != NULL;
32807836SJohn.Forte@Sun.COM link = link->next) {
32817836SJohn.Forte@Sun.COM tq = link->base_address;
32827836SJohn.Forte@Sun.COM DEVICE_QUEUE_LOCK(tq);
32839446SDaniel.Beauregard@Sun.COM if (!(tq->flags & TQF_PLOGI_PROGRS) &&
32849446SDaniel.Beauregard@Sun.COM !(ha->topology & QL_N_PORT)) {
32857836SJohn.Forte@Sun.COM tq->loop_id = (uint16_t)
32867836SJohn.Forte@Sun.COM (tq->loop_id | PORT_LOST_ID);
32877836SJohn.Forte@Sun.COM }
32887836SJohn.Forte@Sun.COM DEVICE_QUEUE_UNLOCK(tq);
32897836SJohn.Forte@Sun.COM }
32907836SJohn.Forte@Sun.COM }
32917836SJohn.Forte@Sun.COM
32927836SJohn.Forte@Sun.COM /* If device not in queues add new queue. */
32937836SJohn.Forte@Sun.COM for (index = 0; index < mr.mb[1]; index++) {
32947836SJohn.Forte@Sun.COM ql_dev_list(ha, list, index, &d_id, &loop_id);
32957836SJohn.Forte@Sun.COM
32967836SJohn.Forte@Sun.COM if (VALID_DEVICE_ID(ha, loop_id)) {
32977836SJohn.Forte@Sun.COM tq = ql_dev_init(ha, d_id, loop_id);
32987836SJohn.Forte@Sun.COM if (tq != NULL) {
32997836SJohn.Forte@Sun.COM tq->loop_id = loop_id;
33007836SJohn.Forte@Sun.COM
33017836SJohn.Forte@Sun.COM /* Test for fabric device. */
33027836SJohn.Forte@Sun.COM if (d_id.b.domain !=
33037836SJohn.Forte@Sun.COM ha->d_id.b.domain ||
33047836SJohn.Forte@Sun.COM d_id.b.area != ha->d_id.b.area) {
33057836SJohn.Forte@Sun.COM tq->flags |= TQF_FABRIC_DEVICE;
33067836SJohn.Forte@Sun.COM }
33077836SJohn.Forte@Sun.COM
33087836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
33097836SJohn.Forte@Sun.COM if (ql_get_port_database(ha, tq,
33107836SJohn.Forte@Sun.COM PDF_NONE) == QL_SUCCESS) {
33117836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
33127836SJohn.Forte@Sun.COM tq->loop_id = (uint16_t)
33137836SJohn.Forte@Sun.COM (tq->loop_id &
33147836SJohn.Forte@Sun.COM ~PORT_LOST_ID);
33157836SJohn.Forte@Sun.COM } else {
33167836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
33177836SJohn.Forte@Sun.COM }
33187836SJohn.Forte@Sun.COM }
33197836SJohn.Forte@Sun.COM }
33207836SJohn.Forte@Sun.COM }
33217836SJohn.Forte@Sun.COM
33227836SJohn.Forte@Sun.COM /* 24xx does not report switch devices in ID list. */
332311924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) &&
33247836SJohn.Forte@Sun.COM ha->topology & (QL_F_PORT | QL_FL_PORT)) {
33257836SJohn.Forte@Sun.COM d_id.b24 = 0xfffffe;
33267836SJohn.Forte@Sun.COM tq = ql_dev_init(ha, d_id, FL_PORT_24XX_HDL);
33277836SJohn.Forte@Sun.COM if (tq != NULL) {
33289156SDaniel.Beauregard@Sun.COM tq->flags |= TQF_FABRIC_DEVICE;
33297836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
33307836SJohn.Forte@Sun.COM (void) ql_get_port_database(ha, tq, PDF_NONE);
33317836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
33327836SJohn.Forte@Sun.COM }
33337836SJohn.Forte@Sun.COM d_id.b24 = 0xfffffc;
33347836SJohn.Forte@Sun.COM tq = ql_dev_init(ha, d_id, SNS_24XX_HDL);
33357836SJohn.Forte@Sun.COM if (tq != NULL) {
33369156SDaniel.Beauregard@Sun.COM tq->flags |= TQF_FABRIC_DEVICE;
33377836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
33387836SJohn.Forte@Sun.COM if (ha->vp_index != 0) {
33397836SJohn.Forte@Sun.COM (void) ql_login_fport(ha, tq,
33407836SJohn.Forte@Sun.COM SNS_24XX_HDL, LFF_NONE, NULL);
33417836SJohn.Forte@Sun.COM }
33427836SJohn.Forte@Sun.COM (void) ql_get_port_database(ha, tq, PDF_NONE);
33437836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
33447836SJohn.Forte@Sun.COM }
33457836SJohn.Forte@Sun.COM }
33467836SJohn.Forte@Sun.COM
33477836SJohn.Forte@Sun.COM /* If F_port exists, allocate queue for FL_Port. */
33487836SJohn.Forte@Sun.COM index = ql_alpa_to_index[0xfe];
33497836SJohn.Forte@Sun.COM d_id.b24 = 0;
33507836SJohn.Forte@Sun.COM if (ha->dev[index].first != NULL) {
33517836SJohn.Forte@Sun.COM tq = ql_dev_init(ha, d_id, (uint16_t)
335211924SDaniel.Beauregard@Sun.COM (CFG_IST(ha, CFG_CTRL_24258081) ?
33537836SJohn.Forte@Sun.COM FL_PORT_24XX_HDL : FL_PORT_LOOP_ID));
33547836SJohn.Forte@Sun.COM if (tq != NULL) {
33559156SDaniel.Beauregard@Sun.COM tq->flags |= TQF_FABRIC_DEVICE;
33567836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
33577836SJohn.Forte@Sun.COM (void) ql_get_port_database(ha, tq, PDF_NONE);
33587836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
33597836SJohn.Forte@Sun.COM }
33607836SJohn.Forte@Sun.COM }
33617836SJohn.Forte@Sun.COM
33627836SJohn.Forte@Sun.COM /* Allocate queue for broadcast. */
33637836SJohn.Forte@Sun.COM d_id.b24 = 0xffffff;
33647836SJohn.Forte@Sun.COM (void) ql_dev_init(ha, d_id, (uint16_t)
336511924SDaniel.Beauregard@Sun.COM (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL :
33667836SJohn.Forte@Sun.COM IP_BROADCAST_LOOP_ID));
33677836SJohn.Forte@Sun.COM
33687836SJohn.Forte@Sun.COM /* Check for any devices lost. */
33697836SJohn.Forte@Sun.COM loop = FALSE;
33707836SJohn.Forte@Sun.COM for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
33717836SJohn.Forte@Sun.COM for (link = ha->dev[index].first; link != NULL;
33727836SJohn.Forte@Sun.COM link = link->next) {
33737836SJohn.Forte@Sun.COM tq = link->base_address;
33747836SJohn.Forte@Sun.COM
33757836SJohn.Forte@Sun.COM if ((tq->loop_id & PORT_LOST_ID) &&
33767836SJohn.Forte@Sun.COM !(tq->flags & (TQF_INITIATOR_DEVICE |
33777836SJohn.Forte@Sun.COM TQF_FABRIC_DEVICE))) {
33787836SJohn.Forte@Sun.COM loop = TRUE;
33797836SJohn.Forte@Sun.COM }
33807836SJohn.Forte@Sun.COM }
33817836SJohn.Forte@Sun.COM }
33827836SJohn.Forte@Sun.COM
33837836SJohn.Forte@Sun.COM /* Release adapter state lock. */
33847836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
33857836SJohn.Forte@Sun.COM
33867836SJohn.Forte@Sun.COM /* Give devices time to recover. */
33877836SJohn.Forte@Sun.COM if (loop == TRUE) {
33887836SJohn.Forte@Sun.COM drv_usecwait(1000000);
33897836SJohn.Forte@Sun.COM }
33907836SJohn.Forte@Sun.COM } while (retries-- && loop == TRUE &&
33917836SJohn.Forte@Sun.COM !(ha->pha->task_daemon_flags & LOOP_RESYNC_NEEDED));
33927836SJohn.Forte@Sun.COM
33937836SJohn.Forte@Sun.COM kmem_free(list, list_size);
33947836SJohn.Forte@Sun.COM
33957836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
33967836SJohn.Forte@Sun.COM EL(ha, "failed=%xh\n", rval);
33977836SJohn.Forte@Sun.COM } else {
33987836SJohn.Forte@Sun.COM /*EMPTY*/
33997836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
34007836SJohn.Forte@Sun.COM }
34017836SJohn.Forte@Sun.COM
34027836SJohn.Forte@Sun.COM return (rval);
34037836SJohn.Forte@Sun.COM }
34047836SJohn.Forte@Sun.COM
34057836SJohn.Forte@Sun.COM /*
34067836SJohn.Forte@Sun.COM * ql_dev_list
34077836SJohn.Forte@Sun.COM * Gets device d_id and loop ID from firmware device list.
34087836SJohn.Forte@Sun.COM *
34097836SJohn.Forte@Sun.COM * Input:
34107836SJohn.Forte@Sun.COM * ha: adapter state pointer.
34117836SJohn.Forte@Sun.COM * list device list pointer.
34127836SJohn.Forte@Sun.COM * index: list index of device data.
34137836SJohn.Forte@Sun.COM * d_id: pointer for d_id data.
34147836SJohn.Forte@Sun.COM * id: pointer for loop ID.
34157836SJohn.Forte@Sun.COM *
34167836SJohn.Forte@Sun.COM * Context:
34177836SJohn.Forte@Sun.COM * Kernel context.
34187836SJohn.Forte@Sun.COM */
34197836SJohn.Forte@Sun.COM void
ql_dev_list(ql_adapter_state_t * ha,union ql_dev_id_list * list,uint32_t index,port_id_t * d_id,uint16_t * id)34207836SJohn.Forte@Sun.COM ql_dev_list(ql_adapter_state_t *ha, union ql_dev_id_list *list,
34217836SJohn.Forte@Sun.COM uint32_t index, port_id_t *d_id, uint16_t *id)
34227836SJohn.Forte@Sun.COM {
342311924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
34247836SJohn.Forte@Sun.COM struct ql_24_dev_id *list24 = (struct ql_24_dev_id *)list;
34257836SJohn.Forte@Sun.COM
34267836SJohn.Forte@Sun.COM d_id->b.al_pa = list24[index].al_pa;
34277836SJohn.Forte@Sun.COM d_id->b.area = list24[index].area;
34287836SJohn.Forte@Sun.COM d_id->b.domain = list24[index].domain;
34297836SJohn.Forte@Sun.COM *id = CHAR_TO_SHORT(list24[index].n_port_hdl_l,
34307836SJohn.Forte@Sun.COM list24[index].n_port_hdl_h);
34317836SJohn.Forte@Sun.COM
34327836SJohn.Forte@Sun.COM } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
34337836SJohn.Forte@Sun.COM struct ql_ex_dev_id *list23 = (struct ql_ex_dev_id *)list;
34347836SJohn.Forte@Sun.COM
34357836SJohn.Forte@Sun.COM d_id->b.al_pa = list23[index].al_pa;
34367836SJohn.Forte@Sun.COM d_id->b.area = list23[index].area;
34377836SJohn.Forte@Sun.COM d_id->b.domain = list23[index].domain;
34387836SJohn.Forte@Sun.COM *id = CHAR_TO_SHORT(list23[index].loop_id_l,
34397836SJohn.Forte@Sun.COM list23[index].loop_id_h);
34407836SJohn.Forte@Sun.COM
34417836SJohn.Forte@Sun.COM } else {
34427836SJohn.Forte@Sun.COM struct ql_dev_id *list22 = (struct ql_dev_id *)list;
34437836SJohn.Forte@Sun.COM
34447836SJohn.Forte@Sun.COM d_id->b.al_pa = list22[index].al_pa;
34457836SJohn.Forte@Sun.COM d_id->b.area = list22[index].area;
34467836SJohn.Forte@Sun.COM d_id->b.domain = list22[index].domain;
34477836SJohn.Forte@Sun.COM *id = (uint16_t)list22[index].loop_id;
34487836SJohn.Forte@Sun.COM }
34497836SJohn.Forte@Sun.COM }
34507836SJohn.Forte@Sun.COM
34517836SJohn.Forte@Sun.COM /*
34527836SJohn.Forte@Sun.COM * ql_configure_fabric
34537836SJohn.Forte@Sun.COM * Setup fabric context.
34547836SJohn.Forte@Sun.COM *
34557836SJohn.Forte@Sun.COM * Input:
34567836SJohn.Forte@Sun.COM * ha = adapter state pointer.
34577836SJohn.Forte@Sun.COM *
34587836SJohn.Forte@Sun.COM * Returns:
34597836SJohn.Forte@Sun.COM * ql local function return status code.
34607836SJohn.Forte@Sun.COM *
34617836SJohn.Forte@Sun.COM * Context:
34627836SJohn.Forte@Sun.COM * Kernel context.
34637836SJohn.Forte@Sun.COM */
34647836SJohn.Forte@Sun.COM static int
ql_configure_fabric(ql_adapter_state_t * ha)34657836SJohn.Forte@Sun.COM ql_configure_fabric(ql_adapter_state_t *ha)
34667836SJohn.Forte@Sun.COM {
34677836SJohn.Forte@Sun.COM port_id_t d_id;
34687836SJohn.Forte@Sun.COM ql_tgt_t *tq;
34697836SJohn.Forte@Sun.COM int rval = QL_FUNCTION_FAILED;
34707836SJohn.Forte@Sun.COM
34717836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
34727836SJohn.Forte@Sun.COM
34737836SJohn.Forte@Sun.COM ha->topology = (uint8_t)(ha->topology & ~QL_SNS_CONNECTION);
34747836SJohn.Forte@Sun.COM
34757836SJohn.Forte@Sun.COM /* Test switch fabric controller present. */
34767836SJohn.Forte@Sun.COM d_id.b24 = FS_FABRIC_F_PORT;
34777836SJohn.Forte@Sun.COM tq = ql_d_id_to_queue(ha, d_id);
34787836SJohn.Forte@Sun.COM if (tq != NULL) {
34797836SJohn.Forte@Sun.COM /* Get port/node names of F_Port. */
34807836SJohn.Forte@Sun.COM (void) ql_get_port_database(ha, tq, PDF_NONE);
34817836SJohn.Forte@Sun.COM
34827836SJohn.Forte@Sun.COM d_id.b24 = FS_NAME_SERVER;
34837836SJohn.Forte@Sun.COM tq = ql_d_id_to_queue(ha, d_id);
34847836SJohn.Forte@Sun.COM if (tq != NULL) {
34857836SJohn.Forte@Sun.COM (void) ql_get_port_database(ha, tq, PDF_NONE);
34867836SJohn.Forte@Sun.COM ha->topology = (uint8_t)
34877836SJohn.Forte@Sun.COM (ha->topology | QL_SNS_CONNECTION);
34887836SJohn.Forte@Sun.COM rval = QL_SUCCESS;
34897836SJohn.Forte@Sun.COM }
34907836SJohn.Forte@Sun.COM }
34917836SJohn.Forte@Sun.COM
34927836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
34937836SJohn.Forte@Sun.COM EL(ha, "failed=%xh\n", rval);
34947836SJohn.Forte@Sun.COM } else {
34957836SJohn.Forte@Sun.COM /*EMPTY*/
34967836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
34977836SJohn.Forte@Sun.COM }
34987836SJohn.Forte@Sun.COM return (rval);
34997836SJohn.Forte@Sun.COM }
35007836SJohn.Forte@Sun.COM
35017836SJohn.Forte@Sun.COM /*
35027836SJohn.Forte@Sun.COM * ql_reset_chip
35037836SJohn.Forte@Sun.COM * Reset ISP chip.
35047836SJohn.Forte@Sun.COM *
35057836SJohn.Forte@Sun.COM * Input:
35067836SJohn.Forte@Sun.COM * ha = adapter block pointer.
35077836SJohn.Forte@Sun.COM * All activity on chip must be already stopped.
35087836SJohn.Forte@Sun.COM * ADAPTER_STATE_LOCK must be released.
35097836SJohn.Forte@Sun.COM *
35107836SJohn.Forte@Sun.COM * Context:
35117836SJohn.Forte@Sun.COM * Interrupt or Kernel context, no mailbox commands allowed.
35127836SJohn.Forte@Sun.COM */
35137836SJohn.Forte@Sun.COM void
ql_reset_chip(ql_adapter_state_t * vha)35147836SJohn.Forte@Sun.COM ql_reset_chip(ql_adapter_state_t *vha)
35157836SJohn.Forte@Sun.COM {
35167836SJohn.Forte@Sun.COM uint32_t cnt;
35177836SJohn.Forte@Sun.COM uint16_t cmd;
35187836SJohn.Forte@Sun.COM ql_adapter_state_t *ha = vha->pha;
35197836SJohn.Forte@Sun.COM
35207836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
35217836SJohn.Forte@Sun.COM
35227836SJohn.Forte@Sun.COM /*
35237836SJohn.Forte@Sun.COM * accessing pci space while not powered can cause panic's
35247836SJohn.Forte@Sun.COM * on some platforms (i.e. Sunblade 1000's)
35257836SJohn.Forte@Sun.COM */
35267836SJohn.Forte@Sun.COM if (ha->power_level == PM_LEVEL_D3) {
35277836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d): Low Power exit\n", ha->instance);
35287836SJohn.Forte@Sun.COM return;
35297836SJohn.Forte@Sun.COM }
35307836SJohn.Forte@Sun.COM
35317836SJohn.Forte@Sun.COM /* Reset all outbound mailbox registers */
35327836SJohn.Forte@Sun.COM for (cnt = 0; cnt < ha->reg_off->mbox_cnt; cnt++) {
353311924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
353411924SDaniel.Beauregard@Sun.COM }
353511924SDaniel.Beauregard@Sun.COM
353611924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
3537*12279SDaniel.Beauregard@Sun.COM ha->timeout_cnt = 0;
353811924SDaniel.Beauregard@Sun.COM ql_8021_reset_chip(ha);
353911924SDaniel.Beauregard@Sun.COM QL_PRINT_3(CE_CONT, "(%d): 8021 exit\n", ha->instance);
354011924SDaniel.Beauregard@Sun.COM return;
35417836SJohn.Forte@Sun.COM }
35427836SJohn.Forte@Sun.COM
35437836SJohn.Forte@Sun.COM /* Disable ISP interrupts. */
35447836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ictrl, 0);
35457836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
35467836SJohn.Forte@Sun.COM ha->flags &= ~INTERRUPTS_ENABLED;
35477836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
35487836SJohn.Forte@Sun.COM
35499446SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_242581)) {
35507836SJohn.Forte@Sun.COM RD32_IO_REG(ha, ictrl);
35517836SJohn.Forte@Sun.COM ql_reset_24xx_chip(ha);
35527836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): 24xx exit\n", ha->instance);
35537836SJohn.Forte@Sun.COM return;
35547836SJohn.Forte@Sun.COM }
35557836SJohn.Forte@Sun.COM
35567836SJohn.Forte@Sun.COM /*
35577836SJohn.Forte@Sun.COM * We are going to reset the chip in case of 2300. That might cause
35587836SJohn.Forte@Sun.COM * a PBM ERR if a DMA transaction is in progress. One way of
35597836SJohn.Forte@Sun.COM * avoiding it is to disable Bus Master operation before we start
35607836SJohn.Forte@Sun.COM * the reset activity.
35617836SJohn.Forte@Sun.COM */
35627836SJohn.Forte@Sun.COM cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
35637836SJohn.Forte@Sun.COM cmd = (uint16_t)(cmd & ~PCI_COMM_ME);
35647836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
35657836SJohn.Forte@Sun.COM
35667836SJohn.Forte@Sun.COM /* Pause RISC. */
35677836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
35687836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 30000; cnt++) {
35697836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
35707836SJohn.Forte@Sun.COM break;
35717836SJohn.Forte@Sun.COM }
35727836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
35737836SJohn.Forte@Sun.COM }
35747836SJohn.Forte@Sun.COM
35757836SJohn.Forte@Sun.COM /*
35767836SJohn.Forte@Sun.COM * A call to ql_isr() can still happen through
35777836SJohn.Forte@Sun.COM * ql_mailbox_command(). So Mark that we are/(will-be)
35787836SJohn.Forte@Sun.COM * running from rom code now.
35797836SJohn.Forte@Sun.COM */
35807836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
35817836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(FIRMWARE_UP | FIRMWARE_LOADED);
35827836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
35837836SJohn.Forte@Sun.COM
35847836SJohn.Forte@Sun.COM /* Select FPM registers. */
35857836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0x20);
35867836SJohn.Forte@Sun.COM
35877836SJohn.Forte@Sun.COM /* FPM Soft Reset. */
35887836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, fpm_diag_config, 0x100);
35897836SJohn.Forte@Sun.COM
35907836SJohn.Forte@Sun.COM /* Toggle FPM reset for 2300 */
35917836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
35927836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, fpm_diag_config, 0);
35937836SJohn.Forte@Sun.COM }
35947836SJohn.Forte@Sun.COM
35957836SJohn.Forte@Sun.COM /* Select frame buffer registers. */
35967836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0x10);
35977836SJohn.Forte@Sun.COM
35987836SJohn.Forte@Sun.COM /* Reset frame buffer FIFOs. */
35997836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
36007836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, fb_cmd, 0x00fc);
36017836SJohn.Forte@Sun.COM /* read back fb_cmd until zero or 3 seconds max */
36027836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 300000; cnt++) {
36037836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, fb_cmd) & 0xff) == 0) {
36047836SJohn.Forte@Sun.COM break;
36057836SJohn.Forte@Sun.COM }
36067836SJohn.Forte@Sun.COM drv_usecwait(10);
36077836SJohn.Forte@Sun.COM }
36087836SJohn.Forte@Sun.COM } else {
36097836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, fb_cmd, 0xa000);
36107836SJohn.Forte@Sun.COM }
36117836SJohn.Forte@Sun.COM
36127836SJohn.Forte@Sun.COM /* Select RISC module registers. */
36137836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0);
36147836SJohn.Forte@Sun.COM
36157836SJohn.Forte@Sun.COM /* Reset RISC module. */
36167836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
36177836SJohn.Forte@Sun.COM
36187836SJohn.Forte@Sun.COM /* Reset ISP semaphore. */
36197836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, semaphore, 0);
36207836SJohn.Forte@Sun.COM
36217836SJohn.Forte@Sun.COM /* Release RISC module. */
36227836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
36237836SJohn.Forte@Sun.COM
36247836SJohn.Forte@Sun.COM /* Insure mailbox registers are free. */
36257836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
36267836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_CLR_HOST_INT);
362710240SDaniel.Beauregard@Sun.COM
362810240SDaniel.Beauregard@Sun.COM /* clear the mailbox command pointer. */
362910240SDaniel.Beauregard@Sun.COM ql_clear_mcp(ha);
363010240SDaniel.Beauregard@Sun.COM
36317836SJohn.Forte@Sun.COM ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
36327836SJohn.Forte@Sun.COM ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
36337836SJohn.Forte@Sun.COM
36347836SJohn.Forte@Sun.COM /* Bus Master is disabled so chip reset is safe. */
36357836SJohn.Forte@Sun.COM if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
36367836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, ISP_RESET);
36377836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
36387836SJohn.Forte@Sun.COM
36397836SJohn.Forte@Sun.COM /* Wait for reset to finish. */
36407836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 30000; cnt++) {
36417836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
36427836SJohn.Forte@Sun.COM break;
36437836SJohn.Forte@Sun.COM }
36447836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
36457836SJohn.Forte@Sun.COM }
36467836SJohn.Forte@Sun.COM }
36477836SJohn.Forte@Sun.COM
36487836SJohn.Forte@Sun.COM /* Wait for RISC to recover from reset. */
36497836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 30000; cnt++) {
365011924SDaniel.Beauregard@Sun.COM if (RD16_IO_REG(ha, mailbox_out[0]) != MBS_BUSY) {
36517836SJohn.Forte@Sun.COM break;
36527836SJohn.Forte@Sun.COM }
36537836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
36547836SJohn.Forte@Sun.COM }
36557836SJohn.Forte@Sun.COM
36567836SJohn.Forte@Sun.COM /* restore bus master */
36577836SJohn.Forte@Sun.COM cmd = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
36587836SJohn.Forte@Sun.COM cmd = (uint16_t)(cmd | PCI_COMM_ME);
36597836SJohn.Forte@Sun.COM ql_pci_config_put16(ha, PCI_CONF_COMM, cmd);
36607836SJohn.Forte@Sun.COM
36617836SJohn.Forte@Sun.COM /* Disable RISC pause on FPM parity error. */
36627836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_DISABLE_PARITY_PAUSE);
36637836SJohn.Forte@Sun.COM
36647836SJohn.Forte@Sun.COM /* Initialize probe registers */
36657836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_SBUS_CARD)) {
36667836SJohn.Forte@Sun.COM /* Pause RISC. */
36677836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_PAUSE_RISC);
36687836SJohn.Forte@Sun.COM for (cnt = 0; cnt < 30000; cnt++) {
36697836SJohn.Forte@Sun.COM if ((RD16_IO_REG(ha, hccr) & HC_RISC_PAUSE) != 0) {
36707836SJohn.Forte@Sun.COM break;
36717836SJohn.Forte@Sun.COM } else {
36727836SJohn.Forte@Sun.COM drv_usecwait(MILLISEC);
36737836SJohn.Forte@Sun.COM }
36747836SJohn.Forte@Sun.COM }
36757836SJohn.Forte@Sun.COM
36767836SJohn.Forte@Sun.COM /* Select FPM registers. */
36777836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0x30);
36787836SJohn.Forte@Sun.COM
36797836SJohn.Forte@Sun.COM /* Set probe register */
368011924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, mailbox_in[23], 0x204c);
36817836SJohn.Forte@Sun.COM
36827836SJohn.Forte@Sun.COM /* Select RISC module registers. */
36837836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, ctrl_status, 0);
36847836SJohn.Forte@Sun.COM
36857836SJohn.Forte@Sun.COM /* Release RISC module. */
36867836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
36877836SJohn.Forte@Sun.COM }
36887836SJohn.Forte@Sun.COM
36897836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
36907836SJohn.Forte@Sun.COM }
36917836SJohn.Forte@Sun.COM
36927836SJohn.Forte@Sun.COM /*
36937836SJohn.Forte@Sun.COM * ql_reset_24xx_chip
36947836SJohn.Forte@Sun.COM * Reset ISP24xx chip.
36957836SJohn.Forte@Sun.COM *
36967836SJohn.Forte@Sun.COM * Input:
36977836SJohn.Forte@Sun.COM * ha = adapter block pointer.
36987836SJohn.Forte@Sun.COM * All activity on chip must be already stopped.
36997836SJohn.Forte@Sun.COM *
37007836SJohn.Forte@Sun.COM * Context:
37017836SJohn.Forte@Sun.COM * Interrupt or Kernel context, no mailbox commands allowed.
37027836SJohn.Forte@Sun.COM */
37037836SJohn.Forte@Sun.COM void
ql_reset_24xx_chip(ql_adapter_state_t * ha)37047836SJohn.Forte@Sun.COM ql_reset_24xx_chip(ql_adapter_state_t *ha)
37057836SJohn.Forte@Sun.COM {
37067836SJohn.Forte@Sun.COM uint32_t timer, stat;
37077836SJohn.Forte@Sun.COM
37087836SJohn.Forte@Sun.COM /* Shutdown DMA. */
37097836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN | MWB_4096_BYTES);
37107836SJohn.Forte@Sun.COM
37117836SJohn.Forte@Sun.COM /* Wait for DMA to stop. */
37127836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
37137836SJohn.Forte@Sun.COM if ((RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE) == 0) {
37147836SJohn.Forte@Sun.COM break;
37157836SJohn.Forte@Sun.COM }
37167836SJohn.Forte@Sun.COM drv_usecwait(100);
37177836SJohn.Forte@Sun.COM }
37187836SJohn.Forte@Sun.COM
37197836SJohn.Forte@Sun.COM /* Stop the firmware. */
37207836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
372111924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
37227836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
37237836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
372411924SDaniel.Beauregard@Sun.COM stat = RD32_IO_REG(ha, risc2host);
37257836SJohn.Forte@Sun.COM if (stat & BIT_15) {
37267836SJohn.Forte@Sun.COM if ((stat & 0xff) < 0x12) {
37277836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
37287836SJohn.Forte@Sun.COM break;
37297836SJohn.Forte@Sun.COM }
37307836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
37317836SJohn.Forte@Sun.COM }
37327836SJohn.Forte@Sun.COM drv_usecwait(100);
37337836SJohn.Forte@Sun.COM }
37347836SJohn.Forte@Sun.COM
37357836SJohn.Forte@Sun.COM /* Reset the chip. */
37367836SJohn.Forte@Sun.COM WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
37377836SJohn.Forte@Sun.COM MWB_4096_BYTES);
37387836SJohn.Forte@Sun.COM drv_usecwait(100);
37397836SJohn.Forte@Sun.COM
37407836SJohn.Forte@Sun.COM /* Wait for idle status from ROM firmware. */
37417836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
374211924SDaniel.Beauregard@Sun.COM if (RD16_IO_REG(ha, mailbox_out[0]) == 0) {
37437836SJohn.Forte@Sun.COM break;
37447836SJohn.Forte@Sun.COM }
37457836SJohn.Forte@Sun.COM drv_usecwait(100);
37467836SJohn.Forte@Sun.COM }
37477836SJohn.Forte@Sun.COM
37487836SJohn.Forte@Sun.COM /* Wait for reset to finish. */
37497836SJohn.Forte@Sun.COM for (timer = 0; timer < 30000; timer++) {
37507836SJohn.Forte@Sun.COM if ((RD32_IO_REG(ha, ctrl_status) & ISP_RESET) == 0) {
37517836SJohn.Forte@Sun.COM break;
37527836SJohn.Forte@Sun.COM }
37537836SJohn.Forte@Sun.COM drv_usecwait(100);
37547836SJohn.Forte@Sun.COM }
37557836SJohn.Forte@Sun.COM
375610240SDaniel.Beauregard@Sun.COM /* clear the mailbox command pointer. */
375710240SDaniel.Beauregard@Sun.COM ql_clear_mcp(ha);
375810240SDaniel.Beauregard@Sun.COM
37597836SJohn.Forte@Sun.COM /* Insure mailbox registers are free. */
37607836SJohn.Forte@Sun.COM ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
37617836SJohn.Forte@Sun.COM ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
37627836SJohn.Forte@Sun.COM
37639611SDaniel.Beauregard@Sun.COM if (ha->flags & MPI_RESET_NEEDED) {
37649611SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
376511924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, mailbox_in[0], MBC_RESTART_MPI);
37669611SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
37679611SDaniel.Beauregard@Sun.COM for (timer = 0; timer < 30000; timer++) {
376811924SDaniel.Beauregard@Sun.COM stat = RD32_IO_REG(ha, risc2host);
37699611SDaniel.Beauregard@Sun.COM if (stat & BIT_15) {
37709611SDaniel.Beauregard@Sun.COM if ((stat & 0xff) < 0x12) {
37719611SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, hccr,
37729611SDaniel.Beauregard@Sun.COM HC24_CLR_RISC_INT);
37739611SDaniel.Beauregard@Sun.COM break;
37749611SDaniel.Beauregard@Sun.COM }
37759611SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
37769611SDaniel.Beauregard@Sun.COM }
37779611SDaniel.Beauregard@Sun.COM drv_usecwait(100);
37789611SDaniel.Beauregard@Sun.COM }
37799611SDaniel.Beauregard@Sun.COM ADAPTER_STATE_LOCK(ha);
37809611SDaniel.Beauregard@Sun.COM ha->flags &= ~MPI_RESET_NEEDED;
37819611SDaniel.Beauregard@Sun.COM ADAPTER_STATE_UNLOCK(ha);
37829611SDaniel.Beauregard@Sun.COM }
37839611SDaniel.Beauregard@Sun.COM
37847836SJohn.Forte@Sun.COM /*
37857836SJohn.Forte@Sun.COM * Set flash write-protection.
37867836SJohn.Forte@Sun.COM */
37877836SJohn.Forte@Sun.COM if ((ha->flags & ONLINE) == 0) {
37887836SJohn.Forte@Sun.COM ql_24xx_protect_flash(ha);
37897836SJohn.Forte@Sun.COM }
37907836SJohn.Forte@Sun.COM }
37917836SJohn.Forte@Sun.COM
37927836SJohn.Forte@Sun.COM /*
379310240SDaniel.Beauregard@Sun.COM * ql_clear_mcp
379410240SDaniel.Beauregard@Sun.COM * Carefully clear the mailbox command pointer in the ha struct.
379510240SDaniel.Beauregard@Sun.COM *
379610240SDaniel.Beauregard@Sun.COM * Input:
379710240SDaniel.Beauregard@Sun.COM * ha = adapter block pointer.
379810240SDaniel.Beauregard@Sun.COM *
379910240SDaniel.Beauregard@Sun.COM * Context:
380010240SDaniel.Beauregard@Sun.COM * Interrupt or Kernel context, no mailbox commands allowed.
380110240SDaniel.Beauregard@Sun.COM */
380210240SDaniel.Beauregard@Sun.COM
380310240SDaniel.Beauregard@Sun.COM static void
ql_clear_mcp(ql_adapter_state_t * ha)380410240SDaniel.Beauregard@Sun.COM ql_clear_mcp(ql_adapter_state_t *ha)
380510240SDaniel.Beauregard@Sun.COM {
380610240SDaniel.Beauregard@Sun.COM uint32_t cnt;
380710240SDaniel.Beauregard@Sun.COM
380810240SDaniel.Beauregard@Sun.COM /* Don't null ha->mcp without the lock, but don't hang either. */
380910240SDaniel.Beauregard@Sun.COM if (MBX_REGISTER_LOCK_OWNER(ha) == curthread) {
381010240SDaniel.Beauregard@Sun.COM ha->mcp = NULL;
381110240SDaniel.Beauregard@Sun.COM } else {
381210240SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < 300000; cnt++) {
381310240SDaniel.Beauregard@Sun.COM if (TRY_MBX_REGISTER_LOCK(ha) != 0) {
381410240SDaniel.Beauregard@Sun.COM ha->mcp = NULL;
381510240SDaniel.Beauregard@Sun.COM MBX_REGISTER_UNLOCK(ha);
381610240SDaniel.Beauregard@Sun.COM break;
381710240SDaniel.Beauregard@Sun.COM } else {
381810240SDaniel.Beauregard@Sun.COM drv_usecwait(10);
381910240SDaniel.Beauregard@Sun.COM }
382010240SDaniel.Beauregard@Sun.COM }
382110240SDaniel.Beauregard@Sun.COM }
382210240SDaniel.Beauregard@Sun.COM }
382310240SDaniel.Beauregard@Sun.COM
382410240SDaniel.Beauregard@Sun.COM
382510240SDaniel.Beauregard@Sun.COM /*
38267836SJohn.Forte@Sun.COM * ql_abort_isp
38277836SJohn.Forte@Sun.COM * Resets ISP and aborts all outstanding commands.
38287836SJohn.Forte@Sun.COM *
38297836SJohn.Forte@Sun.COM * Input:
38307836SJohn.Forte@Sun.COM * ha = adapter state pointer.
38317836SJohn.Forte@Sun.COM * DEVICE_QUEUE_LOCK must be released.
38327836SJohn.Forte@Sun.COM *
38337836SJohn.Forte@Sun.COM * Returns:
38347836SJohn.Forte@Sun.COM * ql local function return status code.
38357836SJohn.Forte@Sun.COM *
38367836SJohn.Forte@Sun.COM * Context:
38377836SJohn.Forte@Sun.COM * Kernel context.
38387836SJohn.Forte@Sun.COM */
38397836SJohn.Forte@Sun.COM int
ql_abort_isp(ql_adapter_state_t * vha)38407836SJohn.Forte@Sun.COM ql_abort_isp(ql_adapter_state_t *vha)
38417836SJohn.Forte@Sun.COM {
38427836SJohn.Forte@Sun.COM ql_link_t *link, *link2;
38437836SJohn.Forte@Sun.COM ddi_devstate_t state;
38447836SJohn.Forte@Sun.COM uint16_t index;
38457836SJohn.Forte@Sun.COM ql_tgt_t *tq;
38467836SJohn.Forte@Sun.COM ql_lun_t *lq;
38477836SJohn.Forte@Sun.COM ql_srb_t *sp;
38487836SJohn.Forte@Sun.COM int rval = QL_SUCCESS;
38497836SJohn.Forte@Sun.COM ql_adapter_state_t *ha = vha->pha;
38507836SJohn.Forte@Sun.COM
38517836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
38527836SJohn.Forte@Sun.COM
38537836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
38547836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~ISP_ABORT_NEEDED;
38557836SJohn.Forte@Sun.COM if (ha->task_daemon_flags & ABORT_ISP_ACTIVE ||
38567836SJohn.Forte@Sun.COM (ha->flags & ONLINE) == 0 || ha->flags & ADAPTER_SUSPENDED) {
38577836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
38587836SJohn.Forte@Sun.COM return (rval);
38597836SJohn.Forte@Sun.COM }
38607836SJohn.Forte@Sun.COM
38617836SJohn.Forte@Sun.COM ha->task_daemon_flags |= ABORT_ISP_ACTIVE;
38627836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(RESET_MARKER_NEEDED | FIRMWARE_UP |
38637836SJohn.Forte@Sun.COM FIRMWARE_LOADED);
38647836SJohn.Forte@Sun.COM for (vha = ha; vha != NULL; vha = vha->vp_next) {
38657836SJohn.Forte@Sun.COM vha->task_daemon_flags |= LOOP_DOWN;
38667836SJohn.Forte@Sun.COM vha->task_daemon_flags &= ~(COMMAND_WAIT_NEEDED |
38677836SJohn.Forte@Sun.COM LOOP_RESYNC_NEEDED);
38687836SJohn.Forte@Sun.COM }
38697836SJohn.Forte@Sun.COM
38707836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
38717836SJohn.Forte@Sun.COM
38727836SJohn.Forte@Sun.COM if (ha->mailbox_flags & MBX_BUSY_FLG) {
38737836SJohn.Forte@Sun.COM /* Acquire mailbox register lock. */
38747836SJohn.Forte@Sun.COM MBX_REGISTER_LOCK(ha);
38757836SJohn.Forte@Sun.COM
38767836SJohn.Forte@Sun.COM /* Wake up mailbox box routine. */
38777836SJohn.Forte@Sun.COM ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_ABORT);
38787836SJohn.Forte@Sun.COM cv_broadcast(&ha->cv_mbx_intr);
38797836SJohn.Forte@Sun.COM
38807836SJohn.Forte@Sun.COM /* Release mailbox register lock. */
38817836SJohn.Forte@Sun.COM MBX_REGISTER_UNLOCK(ha);
38827836SJohn.Forte@Sun.COM
38837836SJohn.Forte@Sun.COM /* Wait for mailbox. */
38847836SJohn.Forte@Sun.COM for (index = 100; index &&
38857836SJohn.Forte@Sun.COM ha->mailbox_flags & MBX_ABORT; index--) {
38867836SJohn.Forte@Sun.COM drv_usecwait(50000);
38877836SJohn.Forte@Sun.COM }
38887836SJohn.Forte@Sun.COM }
38897836SJohn.Forte@Sun.COM
38907836SJohn.Forte@Sun.COM /* Wait for commands to end gracefully if not in panic. */
38917836SJohn.Forte@Sun.COM if (ha->flags & PARITY_ERROR) {
38927836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
38937836SJohn.Forte@Sun.COM ha->flags &= ~PARITY_ERROR;
38947836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
38957836SJohn.Forte@Sun.COM } else if (ddi_in_panic() == 0) {
38967836SJohn.Forte@Sun.COM ql_cmd_wait(ha);
38977836SJohn.Forte@Sun.COM }
38987836SJohn.Forte@Sun.COM
38997836SJohn.Forte@Sun.COM /* Shutdown IP. */
39007836SJohn.Forte@Sun.COM if (ha->flags & IP_INITIALIZED) {
39017836SJohn.Forte@Sun.COM (void) ql_shutdown_ip(ha);
39027836SJohn.Forte@Sun.COM }
39037836SJohn.Forte@Sun.COM
39047836SJohn.Forte@Sun.COM /* Reset the chip. */
39057836SJohn.Forte@Sun.COM ql_reset_chip(ha);
39067836SJohn.Forte@Sun.COM
390710240SDaniel.Beauregard@Sun.COM /*
390810240SDaniel.Beauregard@Sun.COM * Even though we have waited for outstanding commands to complete,
390910240SDaniel.Beauregard@Sun.COM * except for ones marked SRB_COMMAND_TIMEOUT, and reset the ISP,
391010240SDaniel.Beauregard@Sun.COM * there could still be an interrupt thread active. The interrupt
391110240SDaniel.Beauregard@Sun.COM * lock will prevent us from getting an sp from the outstanding
391210240SDaniel.Beauregard@Sun.COM * cmds array that the ISR may be using.
391310240SDaniel.Beauregard@Sun.COM */
391410240SDaniel.Beauregard@Sun.COM
39157836SJohn.Forte@Sun.COM /* Place all commands in outstanding cmd list on device queue. */
39167836SJohn.Forte@Sun.COM for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
39177836SJohn.Forte@Sun.COM REQUEST_RING_LOCK(ha);
391810240SDaniel.Beauregard@Sun.COM INTR_LOCK(ha);
39197836SJohn.Forte@Sun.COM if ((link = ha->pending_cmds.first) != NULL) {
39207836SJohn.Forte@Sun.COM sp = link->base_address;
39217836SJohn.Forte@Sun.COM ql_remove_link(&ha->pending_cmds, &sp->cmd);
39227836SJohn.Forte@Sun.COM
39237836SJohn.Forte@Sun.COM REQUEST_RING_UNLOCK(ha);
39247836SJohn.Forte@Sun.COM index = 0;
39257836SJohn.Forte@Sun.COM } else {
39267836SJohn.Forte@Sun.COM REQUEST_RING_UNLOCK(ha);
39277836SJohn.Forte@Sun.COM if ((sp = ha->outstanding_cmds[index]) == NULL) {
392810240SDaniel.Beauregard@Sun.COM INTR_UNLOCK(ha);
39297836SJohn.Forte@Sun.COM continue;
39307836SJohn.Forte@Sun.COM }
39317836SJohn.Forte@Sun.COM }
39327836SJohn.Forte@Sun.COM
393310240SDaniel.Beauregard@Sun.COM /*
393410240SDaniel.Beauregard@Sun.COM * It's not obvious but the index for commands pulled from
393510240SDaniel.Beauregard@Sun.COM * pending will be zero and that entry in the outstanding array
393610240SDaniel.Beauregard@Sun.COM * is not used so nulling it is "no harm, no foul".
393710240SDaniel.Beauregard@Sun.COM */
393810240SDaniel.Beauregard@Sun.COM
393910240SDaniel.Beauregard@Sun.COM ha->outstanding_cmds[index] = NULL;
394010240SDaniel.Beauregard@Sun.COM sp->handle = 0;
394110240SDaniel.Beauregard@Sun.COM sp->flags &= ~SRB_IN_TOKEN_ARRAY;
394210240SDaniel.Beauregard@Sun.COM
394310240SDaniel.Beauregard@Sun.COM INTR_UNLOCK(ha);
394410240SDaniel.Beauregard@Sun.COM
39457836SJohn.Forte@Sun.COM /* If command timeout. */
39467836SJohn.Forte@Sun.COM if (sp->flags & SRB_COMMAND_TIMEOUT) {
39477836SJohn.Forte@Sun.COM sp->pkt->pkt_reason = CS_TIMEOUT;
39487836SJohn.Forte@Sun.COM sp->flags &= ~SRB_RETRY;
39497836SJohn.Forte@Sun.COM sp->flags |= SRB_ISP_COMPLETED;
39507836SJohn.Forte@Sun.COM
39517836SJohn.Forte@Sun.COM /* Call done routine to handle completion. */
39527836SJohn.Forte@Sun.COM ql_done(&sp->cmd);
39537836SJohn.Forte@Sun.COM continue;
39547836SJohn.Forte@Sun.COM }
39557836SJohn.Forte@Sun.COM
39567836SJohn.Forte@Sun.COM /* Acquire target queue lock. */
39577836SJohn.Forte@Sun.COM lq = sp->lun_queue;
39587836SJohn.Forte@Sun.COM tq = lq->target_queue;
39597836SJohn.Forte@Sun.COM DEVICE_QUEUE_LOCK(tq);
39607836SJohn.Forte@Sun.COM
39617836SJohn.Forte@Sun.COM /* Reset watchdog time. */
39627836SJohn.Forte@Sun.COM sp->wdg_q_time = sp->init_wdg_q_time;
39637836SJohn.Forte@Sun.COM
39647836SJohn.Forte@Sun.COM /* Place request back on top of device queue. */
39657836SJohn.Forte@Sun.COM sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED |
39667836SJohn.Forte@Sun.COM SRB_RETRY);
39677836SJohn.Forte@Sun.COM
39687836SJohn.Forte@Sun.COM ql_add_link_t(&lq->cmd, &sp->cmd);
39697836SJohn.Forte@Sun.COM sp->flags |= SRB_IN_DEVICE_QUEUE;
39707836SJohn.Forte@Sun.COM
39717836SJohn.Forte@Sun.COM /* Release target queue lock. */
39727836SJohn.Forte@Sun.COM DEVICE_QUEUE_UNLOCK(tq);
39737836SJohn.Forte@Sun.COM }
39747836SJohn.Forte@Sun.COM
39757836SJohn.Forte@Sun.COM /*
39767836SJohn.Forte@Sun.COM * Clear per LUN active count, because there should not be
39777836SJohn.Forte@Sun.COM * any IO outstanding at this time.
39787836SJohn.Forte@Sun.COM */
39797836SJohn.Forte@Sun.COM for (vha = ha; vha != NULL; vha = vha->vp_next) {
39807836SJohn.Forte@Sun.COM for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
39817836SJohn.Forte@Sun.COM link = vha->dev[index].first;
39827836SJohn.Forte@Sun.COM while (link != NULL) {
39837836SJohn.Forte@Sun.COM tq = link->base_address;
39847836SJohn.Forte@Sun.COM link = link->next;
39857836SJohn.Forte@Sun.COM DEVICE_QUEUE_LOCK(tq);
39867836SJohn.Forte@Sun.COM tq->outcnt = 0;
39877836SJohn.Forte@Sun.COM tq->flags &= ~TQF_QUEUE_SUSPENDED;
39887836SJohn.Forte@Sun.COM for (link2 = tq->lun_queues.first;
39897836SJohn.Forte@Sun.COM link2 != NULL; link2 = link2->next) {
39907836SJohn.Forte@Sun.COM lq = link2->base_address;
39917836SJohn.Forte@Sun.COM lq->lun_outcnt = 0;
39927836SJohn.Forte@Sun.COM lq->flags &= ~LQF_UNTAGGED_PENDING;
39937836SJohn.Forte@Sun.COM }
39947836SJohn.Forte@Sun.COM DEVICE_QUEUE_UNLOCK(tq);
39957836SJohn.Forte@Sun.COM }
39967836SJohn.Forte@Sun.COM }
39977836SJohn.Forte@Sun.COM }
39987836SJohn.Forte@Sun.COM
399911924SDaniel.Beauregard@Sun.COM if ((rval = ql_check_isp_firmware(ha)) != QL_SUCCESS) {
400011924SDaniel.Beauregard@Sun.COM if ((rval = ql_chip_diag(ha)) == QL_SUCCESS) {
400111924SDaniel.Beauregard@Sun.COM rval = ql_load_isp_firmware(ha);
400211924SDaniel.Beauregard@Sun.COM }
40037836SJohn.Forte@Sun.COM }
40047836SJohn.Forte@Sun.COM
40057836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && (rval = ql_set_cache_line(ha)) ==
40067836SJohn.Forte@Sun.COM QL_SUCCESS && (rval = ql_init_rings(ha)) == QL_SUCCESS &&
40077836SJohn.Forte@Sun.COM (rval = ql_fw_ready(ha, 10)) == QL_SUCCESS) {
40087836SJohn.Forte@Sun.COM
40097836SJohn.Forte@Sun.COM /* If reset abort needed that may have been set. */
40107836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
40117836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED |
40127836SJohn.Forte@Sun.COM ABORT_ISP_ACTIVE);
40137836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
40147836SJohn.Forte@Sun.COM
40157836SJohn.Forte@Sun.COM /* Enable ISP interrupts. */
401611924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
401711924SDaniel.Beauregard@Sun.COM ql_8021_enable_intrs(ha);
401811924SDaniel.Beauregard@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_242581)) {
401911924SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
402011924SDaniel.Beauregard@Sun.COM } else {
402111924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
402211924SDaniel.Beauregard@Sun.COM }
40237836SJohn.Forte@Sun.COM
40247836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
40257836SJohn.Forte@Sun.COM ha->flags |= INTERRUPTS_ENABLED;
40267836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
40277836SJohn.Forte@Sun.COM
40287836SJohn.Forte@Sun.COM /* Set loop online, if it really is. */
40297836SJohn.Forte@Sun.COM ql_loop_online(ha);
40307836SJohn.Forte@Sun.COM
40317836SJohn.Forte@Sun.COM state = ddi_get_devstate(ha->dip);
40327836SJohn.Forte@Sun.COM if (state != DDI_DEVSTATE_UP) {
40337836SJohn.Forte@Sun.COM /*EMPTY*/
40347836SJohn.Forte@Sun.COM ddi_dev_report_fault(ha->dip, DDI_SERVICE_RESTORED,
40357836SJohn.Forte@Sun.COM DDI_DEVICE_FAULT, "Device reset succeeded");
40367836SJohn.Forte@Sun.COM }
40377836SJohn.Forte@Sun.COM } else {
40387836SJohn.Forte@Sun.COM /* Enable ISP interrupts. */
403911924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_8021)) {
404011924SDaniel.Beauregard@Sun.COM ql_8021_enable_intrs(ha);
404111924SDaniel.Beauregard@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_242581)) {
404211924SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
404311924SDaniel.Beauregard@Sun.COM } else {
404411924SDaniel.Beauregard@Sun.COM WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
404511924SDaniel.Beauregard@Sun.COM }
40467836SJohn.Forte@Sun.COM
40477836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
40487836SJohn.Forte@Sun.COM ha->flags |= INTERRUPTS_ENABLED;
40497836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
40507836SJohn.Forte@Sun.COM
40517836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
40527836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE);
40537836SJohn.Forte@Sun.COM ha->task_daemon_flags |= LOOP_DOWN;
40547836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
40557836SJohn.Forte@Sun.COM
40567836SJohn.Forte@Sun.COM ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
40577836SJohn.Forte@Sun.COM }
40587836SJohn.Forte@Sun.COM
40597836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
40607836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
40617836SJohn.Forte@Sun.COM } else {
40627836SJohn.Forte@Sun.COM /*EMPTY*/
40637836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d): done\n", ha->instance);
40647836SJohn.Forte@Sun.COM }
40657836SJohn.Forte@Sun.COM return (rval);
40667836SJohn.Forte@Sun.COM }
40677836SJohn.Forte@Sun.COM
40687836SJohn.Forte@Sun.COM /*
40697836SJohn.Forte@Sun.COM * ql_vport_control
40707836SJohn.Forte@Sun.COM * Issue Virtual Port Control command.
40717836SJohn.Forte@Sun.COM *
40727836SJohn.Forte@Sun.COM * Input:
40737836SJohn.Forte@Sun.COM * ha = virtual adapter state pointer.
40747836SJohn.Forte@Sun.COM * cmd = control command.
40757836SJohn.Forte@Sun.COM *
40767836SJohn.Forte@Sun.COM * Returns:
40777836SJohn.Forte@Sun.COM * ql local function return status code.
40787836SJohn.Forte@Sun.COM *
40797836SJohn.Forte@Sun.COM * Context:
40807836SJohn.Forte@Sun.COM * Kernel context.
40817836SJohn.Forte@Sun.COM */
40827836SJohn.Forte@Sun.COM int
ql_vport_control(ql_adapter_state_t * ha,uint8_t cmd)40837836SJohn.Forte@Sun.COM ql_vport_control(ql_adapter_state_t *ha, uint8_t cmd)
40847836SJohn.Forte@Sun.COM {
40857836SJohn.Forte@Sun.COM ql_mbx_iocb_t *pkt;
40867836SJohn.Forte@Sun.COM uint8_t bit;
40877836SJohn.Forte@Sun.COM int rval;
40887836SJohn.Forte@Sun.COM uint32_t pkt_size;
40897836SJohn.Forte@Sun.COM
40907836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
40917836SJohn.Forte@Sun.COM
40927836SJohn.Forte@Sun.COM if (ha->vp_index != 0) {
40937836SJohn.Forte@Sun.COM pkt_size = sizeof (ql_mbx_iocb_t);
40947836SJohn.Forte@Sun.COM pkt = kmem_zalloc(pkt_size, KM_SLEEP);
40957836SJohn.Forte@Sun.COM if (pkt == NULL) {
40967836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
40977836SJohn.Forte@Sun.COM return (QL_MEMORY_ALLOC_FAILED);
40987836SJohn.Forte@Sun.COM }
40997836SJohn.Forte@Sun.COM
41007836SJohn.Forte@Sun.COM pkt->vpc.entry_type = VP_CONTROL_TYPE;
41017836SJohn.Forte@Sun.COM pkt->vpc.entry_count = 1;
41027836SJohn.Forte@Sun.COM pkt->vpc.command = cmd;
41037836SJohn.Forte@Sun.COM pkt->vpc.vp_count = 1;
41047836SJohn.Forte@Sun.COM bit = (uint8_t)(ha->vp_index - 1);
41057836SJohn.Forte@Sun.COM pkt->vpc.vp_index[bit / 8] = (uint8_t)
41067836SJohn.Forte@Sun.COM (pkt->vpc.vp_index[bit / 8] | BIT_0 << bit % 8);
41077836SJohn.Forte@Sun.COM
41087836SJohn.Forte@Sun.COM rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
41097836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && pkt->vpc.status != 0) {
41107836SJohn.Forte@Sun.COM rval = QL_COMMAND_ERROR;
41117836SJohn.Forte@Sun.COM }
41127836SJohn.Forte@Sun.COM
41137836SJohn.Forte@Sun.COM kmem_free(pkt, pkt_size);
41147836SJohn.Forte@Sun.COM } else {
41157836SJohn.Forte@Sun.COM rval = QL_SUCCESS;
41167836SJohn.Forte@Sun.COM }
41177836SJohn.Forte@Sun.COM
41187836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
41197836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
41207836SJohn.Forte@Sun.COM } else {
41217836SJohn.Forte@Sun.COM /*EMPTY*/
41227836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
41237836SJohn.Forte@Sun.COM ha->vp_index);
41247836SJohn.Forte@Sun.COM }
41257836SJohn.Forte@Sun.COM return (rval);
41267836SJohn.Forte@Sun.COM }
41277836SJohn.Forte@Sun.COM
41287836SJohn.Forte@Sun.COM /*
41297836SJohn.Forte@Sun.COM * ql_vport_modify
41307836SJohn.Forte@Sun.COM * Issue of Modify Virtual Port command.
41317836SJohn.Forte@Sun.COM *
41327836SJohn.Forte@Sun.COM * Input:
41337836SJohn.Forte@Sun.COM * ha = virtual adapter state pointer.
41347836SJohn.Forte@Sun.COM * cmd = command.
41357836SJohn.Forte@Sun.COM * opt = option.
41367836SJohn.Forte@Sun.COM *
41377836SJohn.Forte@Sun.COM * Context:
41387836SJohn.Forte@Sun.COM * Interrupt or Kernel context, no mailbox commands allowed.
41397836SJohn.Forte@Sun.COM */
41407836SJohn.Forte@Sun.COM int
ql_vport_modify(ql_adapter_state_t * ha,uint8_t cmd,uint8_t opt)41417836SJohn.Forte@Sun.COM ql_vport_modify(ql_adapter_state_t *ha, uint8_t cmd, uint8_t opt)
41427836SJohn.Forte@Sun.COM {
41437836SJohn.Forte@Sun.COM ql_mbx_iocb_t *pkt;
41447836SJohn.Forte@Sun.COM int rval;
41457836SJohn.Forte@Sun.COM uint32_t pkt_size;
41467836SJohn.Forte@Sun.COM
41477836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
41487836SJohn.Forte@Sun.COM
41497836SJohn.Forte@Sun.COM pkt_size = sizeof (ql_mbx_iocb_t);
41507836SJohn.Forte@Sun.COM pkt = kmem_zalloc(pkt_size, KM_SLEEP);
41517836SJohn.Forte@Sun.COM if (pkt == NULL) {
41527836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
41537836SJohn.Forte@Sun.COM return (QL_MEMORY_ALLOC_FAILED);
41547836SJohn.Forte@Sun.COM }
41557836SJohn.Forte@Sun.COM
41567836SJohn.Forte@Sun.COM pkt->vpm.entry_type = VP_MODIFY_TYPE;
41577836SJohn.Forte@Sun.COM pkt->vpm.entry_count = 1;
41587836SJohn.Forte@Sun.COM pkt->vpm.command = cmd;
41597836SJohn.Forte@Sun.COM pkt->vpm.vp_count = 1;
41607836SJohn.Forte@Sun.COM pkt->vpm.first_vp_index = ha->vp_index;
41617836SJohn.Forte@Sun.COM pkt->vpm.first_options = opt;
41627836SJohn.Forte@Sun.COM bcopy(ha->loginparams.nport_ww_name.raw_wwn, pkt->vpm.first_port_name,
41637836SJohn.Forte@Sun.COM 8);
41647836SJohn.Forte@Sun.COM bcopy(ha->loginparams.node_ww_name.raw_wwn, pkt->vpm.first_node_name,
41657836SJohn.Forte@Sun.COM 8);
41667836SJohn.Forte@Sun.COM
41677836SJohn.Forte@Sun.COM rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
41687836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS && pkt->vpm.status != 0) {
41697836SJohn.Forte@Sun.COM EL(ha, "failed, ql_issue_mbx_iocb=%xh, status=%xh\n", rval,
41707836SJohn.Forte@Sun.COM pkt->vpm.status);
41717836SJohn.Forte@Sun.COM rval = QL_COMMAND_ERROR;
41727836SJohn.Forte@Sun.COM }
41737836SJohn.Forte@Sun.COM
41747836SJohn.Forte@Sun.COM kmem_free(pkt, pkt_size);
41757836SJohn.Forte@Sun.COM
41767836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
41777836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
41787836SJohn.Forte@Sun.COM } else {
41797836SJohn.Forte@Sun.COM /*EMPTY*/
41807836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
41817836SJohn.Forte@Sun.COM ha->vp_index);
41827836SJohn.Forte@Sun.COM }
41837836SJohn.Forte@Sun.COM return (rval);
41847836SJohn.Forte@Sun.COM }
41857836SJohn.Forte@Sun.COM
41867836SJohn.Forte@Sun.COM /*
41877836SJohn.Forte@Sun.COM * ql_vport_enable
41887836SJohn.Forte@Sun.COM * Enable virtual port.
41897836SJohn.Forte@Sun.COM *
41907836SJohn.Forte@Sun.COM * Input:
41917836SJohn.Forte@Sun.COM * ha = virtual adapter state pointer.
41927836SJohn.Forte@Sun.COM *
41937836SJohn.Forte@Sun.COM * Context:
41947836SJohn.Forte@Sun.COM * Kernel context.
41957836SJohn.Forte@Sun.COM */
41967836SJohn.Forte@Sun.COM int
ql_vport_enable(ql_adapter_state_t * ha)41977836SJohn.Forte@Sun.COM ql_vport_enable(ql_adapter_state_t *ha)
41987836SJohn.Forte@Sun.COM {
41997836SJohn.Forte@Sun.COM int timer;
42007836SJohn.Forte@Sun.COM
42017836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
42027836SJohn.Forte@Sun.COM
42037836SJohn.Forte@Sun.COM ha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
42047836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
42057836SJohn.Forte@Sun.COM ha->task_daemon_flags |= LOOP_DOWN;
42067836SJohn.Forte@Sun.COM ha->task_daemon_flags &= ~(FC_STATE_CHANGE | STATE_ONLINE);
42077836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
42087836SJohn.Forte@Sun.COM
42097836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
42107836SJohn.Forte@Sun.COM ha->flags |= VP_ENABLED;
42117836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
42127836SJohn.Forte@Sun.COM
42137836SJohn.Forte@Sun.COM if (ql_vport_modify(ha, VPM_MODIFY_ENABLE, VPO_TARGET_MODE_DISABLED |
42147836SJohn.Forte@Sun.COM VPO_INITIATOR_MODE_ENABLED | VPO_ENABLED) != QL_SUCCESS) {
42157836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d): failed to enable virtual port=%d\n",
42167836SJohn.Forte@Sun.COM ha->instance, ha->vp_index);
42177836SJohn.Forte@Sun.COM return (QL_FUNCTION_FAILED);
42187836SJohn.Forte@Sun.COM }
42197836SJohn.Forte@Sun.COM if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) {
42207836SJohn.Forte@Sun.COM /* Wait for loop to come up. */
42217836SJohn.Forte@Sun.COM for (timer = 0; timer < 3000 &&
42227836SJohn.Forte@Sun.COM !(ha->task_daemon_flags & STATE_ONLINE);
42237836SJohn.Forte@Sun.COM timer++) {
42247836SJohn.Forte@Sun.COM delay(1);
42257836SJohn.Forte@Sun.COM }
42267836SJohn.Forte@Sun.COM }
42277836SJohn.Forte@Sun.COM
42287836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
42297836SJohn.Forte@Sun.COM
42307836SJohn.Forte@Sun.COM return (QL_SUCCESS);
42317836SJohn.Forte@Sun.COM }
42327836SJohn.Forte@Sun.COM
42337836SJohn.Forte@Sun.COM /*
42347836SJohn.Forte@Sun.COM * ql_vport_create
42357836SJohn.Forte@Sun.COM * Create virtual port context.
42367836SJohn.Forte@Sun.COM *
42377836SJohn.Forte@Sun.COM * Input:
42387836SJohn.Forte@Sun.COM * ha: parent adapter state pointer.
42397836SJohn.Forte@Sun.COM * index: virtual port index number.
42407836SJohn.Forte@Sun.COM *
42417836SJohn.Forte@Sun.COM * Context:
42427836SJohn.Forte@Sun.COM * Kernel context.
42437836SJohn.Forte@Sun.COM */
42447836SJohn.Forte@Sun.COM ql_adapter_state_t *
ql_vport_create(ql_adapter_state_t * ha,uint8_t index)42457836SJohn.Forte@Sun.COM ql_vport_create(ql_adapter_state_t *ha, uint8_t index)
42467836SJohn.Forte@Sun.COM {
42477836SJohn.Forte@Sun.COM ql_adapter_state_t *vha;
42487836SJohn.Forte@Sun.COM
42497836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
42507836SJohn.Forte@Sun.COM
42517836SJohn.Forte@Sun.COM /* Inherit the parents data. */
42527836SJohn.Forte@Sun.COM vha = kmem_alloc(sizeof (ql_adapter_state_t), KM_SLEEP);
42537836SJohn.Forte@Sun.COM
42547836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
42557836SJohn.Forte@Sun.COM bcopy(ha, vha, sizeof (ql_adapter_state_t));
42567836SJohn.Forte@Sun.COM vha->pi_attrs = NULL;
42577836SJohn.Forte@Sun.COM vha->ub_outcnt = 0;
42587836SJohn.Forte@Sun.COM vha->ub_allocated = 0;
42597836SJohn.Forte@Sun.COM vha->flags = 0;
42607836SJohn.Forte@Sun.COM vha->task_daemon_flags = 0;
42617836SJohn.Forte@Sun.COM ha->vp_next = vha;
42627836SJohn.Forte@Sun.COM vha->pha = ha;
42637836SJohn.Forte@Sun.COM vha->vp_index = index;
42647836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
42657836SJohn.Forte@Sun.COM
42667836SJohn.Forte@Sun.COM vha->hba.next = NULL;
42677836SJohn.Forte@Sun.COM vha->hba.prev = NULL;
42687836SJohn.Forte@Sun.COM vha->hba.base_address = vha;
42697836SJohn.Forte@Sun.COM vha->state = FC_PORT_SPEED_MASK(ha->state) | FC_STATE_OFFLINE;
42707836SJohn.Forte@Sun.COM vha->dev = kmem_zalloc(sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE,
42717836SJohn.Forte@Sun.COM KM_SLEEP);
42727836SJohn.Forte@Sun.COM vha->ub_array = kmem_zalloc(sizeof (*vha->ub_array) * QL_UB_LIMIT,
42737836SJohn.Forte@Sun.COM KM_SLEEP);
42747836SJohn.Forte@Sun.COM
42757836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
42767836SJohn.Forte@Sun.COM
42777836SJohn.Forte@Sun.COM return (vha);
42787836SJohn.Forte@Sun.COM }
42797836SJohn.Forte@Sun.COM
42807836SJohn.Forte@Sun.COM /*
42817836SJohn.Forte@Sun.COM * ql_vport_destroy
42827836SJohn.Forte@Sun.COM * Destroys virtual port context.
42837836SJohn.Forte@Sun.COM *
42847836SJohn.Forte@Sun.COM * Input:
42857836SJohn.Forte@Sun.COM * ha = virtual adapter state pointer.
42867836SJohn.Forte@Sun.COM *
42877836SJohn.Forte@Sun.COM * Context:
42887836SJohn.Forte@Sun.COM * Kernel context.
42897836SJohn.Forte@Sun.COM */
42907836SJohn.Forte@Sun.COM void
ql_vport_destroy(ql_adapter_state_t * ha)42917836SJohn.Forte@Sun.COM ql_vport_destroy(ql_adapter_state_t *ha)
42927836SJohn.Forte@Sun.COM {
42937836SJohn.Forte@Sun.COM ql_adapter_state_t *vha;
42947836SJohn.Forte@Sun.COM
42957836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
42967836SJohn.Forte@Sun.COM
42977836SJohn.Forte@Sun.COM /* Remove port from list. */
42987836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
42997836SJohn.Forte@Sun.COM for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
43007836SJohn.Forte@Sun.COM if (vha->vp_next == ha) {
43017836SJohn.Forte@Sun.COM vha->vp_next = ha->vp_next;
43027836SJohn.Forte@Sun.COM break;
43037836SJohn.Forte@Sun.COM }
43047836SJohn.Forte@Sun.COM }
43057836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
43067836SJohn.Forte@Sun.COM
43077836SJohn.Forte@Sun.COM if (ha->ub_array != NULL) {
43087836SJohn.Forte@Sun.COM kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
43097836SJohn.Forte@Sun.COM }
43107836SJohn.Forte@Sun.COM if (ha->dev != NULL) {
43117836SJohn.Forte@Sun.COM kmem_free(ha->dev, sizeof (*vha->dev) * DEVICE_HEAD_LIST_SIZE);
43127836SJohn.Forte@Sun.COM }
43137836SJohn.Forte@Sun.COM kmem_free(ha, sizeof (ql_adapter_state_t));
43147836SJohn.Forte@Sun.COM
43157836SJohn.Forte@Sun.COM QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
43167836SJohn.Forte@Sun.COM }
431710736SDaniel.Beauregard@Sun.COM
431810736SDaniel.Beauregard@Sun.COM /*
431910736SDaniel.Beauregard@Sun.COM * ql_mps_reset
432010736SDaniel.Beauregard@Sun.COM * Reset MPS for FCoE functions.
432110736SDaniel.Beauregard@Sun.COM *
432210736SDaniel.Beauregard@Sun.COM * Input:
432310736SDaniel.Beauregard@Sun.COM * ha = virtual adapter state pointer.
432410736SDaniel.Beauregard@Sun.COM *
432510736SDaniel.Beauregard@Sun.COM * Context:
432610736SDaniel.Beauregard@Sun.COM * Kernel context.
432710736SDaniel.Beauregard@Sun.COM */
432810736SDaniel.Beauregard@Sun.COM static void
ql_mps_reset(ql_adapter_state_t * ha)432910736SDaniel.Beauregard@Sun.COM ql_mps_reset(ql_adapter_state_t *ha)
433010736SDaniel.Beauregard@Sun.COM {
433110736SDaniel.Beauregard@Sun.COM uint32_t data, dctl = 1000;
433210736SDaniel.Beauregard@Sun.COM
433310736SDaniel.Beauregard@Sun.COM do {
433410736SDaniel.Beauregard@Sun.COM if (dctl-- == 0 || ql_wrt_risc_ram_word(ha, 0x7c00, 1) !=
433510736SDaniel.Beauregard@Sun.COM QL_SUCCESS) {
433610736SDaniel.Beauregard@Sun.COM return;
433710736SDaniel.Beauregard@Sun.COM }
433810736SDaniel.Beauregard@Sun.COM if (ql_rd_risc_ram_word(ha, 0x7c00, &data) != QL_SUCCESS) {
433911387SSurya.Prakki@Sun.COM (void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
434010736SDaniel.Beauregard@Sun.COM return;
434110736SDaniel.Beauregard@Sun.COM }
434210736SDaniel.Beauregard@Sun.COM } while (!(data & BIT_0));
434310736SDaniel.Beauregard@Sun.COM
434410736SDaniel.Beauregard@Sun.COM if (ql_rd_risc_ram_word(ha, 0x7A15, &data) == QL_SUCCESS) {
434510736SDaniel.Beauregard@Sun.COM dctl = (uint16_t)ql_pci_config_get16(ha, 0x54);
434610736SDaniel.Beauregard@Sun.COM if ((data & 0xe0) != (dctl & 0xe0)) {
434710736SDaniel.Beauregard@Sun.COM data &= 0xff1f;
434810736SDaniel.Beauregard@Sun.COM data |= dctl & 0xe0;
434911387SSurya.Prakki@Sun.COM (void) ql_wrt_risc_ram_word(ha, 0x7A15, data);
435010736SDaniel.Beauregard@Sun.COM }
435110736SDaniel.Beauregard@Sun.COM }
435211387SSurya.Prakki@Sun.COM (void) ql_wrt_risc_ram_word(ha, 0x7c00, 0);
435310736SDaniel.Beauregard@Sun.COM }
4354