ql_init.c revision 5dfd244acc8f144280c5bc8f69ed941185fc3ccc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright 2009 QLogic Corporation */
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "Copyright 2009 QLogic Corporation; ql_init.c"
/*
* ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
*
* ***********************************************************************
* * **
* * NOTICE **
* * COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION **
* * ALL RIGHTS RESERVED **
* * **
* ***********************************************************************
*
*/
#include <ql_apps.h>
#include <ql_api.h>
#include <ql_debug.h>
#include <ql_init.h>
#include <ql_iocb.h>
#include <ql_isr.h>
#include <ql_mbx.h>
#include <ql_xioctl.h>
/*
* Local data
*/
/*
* Local prototypes
*/
static int ql_nvram_24xx_config(ql_adapter_state_t *);
static int ql_check_isp_firmware(ql_adapter_state_t *);
static int ql_chip_diag(ql_adapter_state_t *);
static int ql_load_flash_fw(ql_adapter_state_t *);
static int ql_configure_loop(ql_adapter_state_t *);
static int ql_configure_hba(ql_adapter_state_t *);
static int ql_configure_fabric(ql_adapter_state_t *);
static int ql_configure_device_d_id(ql_adapter_state_t *);
static void ql_set_max_read_req(ql_adapter_state_t *);
static void ql_configure_n_port_info(ql_adapter_state_t *);
/*
* ql_initialize_adapter
* Initialize board.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval;
int retries = 5;
do {
/* Clear adapter flags. */
msg = "Loop OFFLINE";
if (rval != QL_SUCCESS) {
}
continue;
}
(void) ql_setup_fcache(ha);
/* Reset ISP chip. */
/* Get NVRAM configuration if needed. */
(void) ql_nvram_config(ha);
}
/* Set login parameters. */
} else {
}
/* Determine which RISC code to use. */
(void) ql_check_isp_firmware(ha);
if (rval == QL_SUCCESS) {
}
msg = "Loop ONLINE";
msg = "Link ONLINE";
} else {
msg = "Unknown Link state";
}
}
} else {
}
}
/* Enable ISP interrupts and login parameters. */
/*
* Setup login parameters.
*/
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_pci_sbus_config
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
w16 & 0xf);
} else {
/*
* we want to respect framework's setting of PCI
* configuration space command register and also
* want to make sure that all bits of interest to us
* are properly set in command register.
*/
/*
* If this is a 2300 card and not 2312, reset the
* MEMWR_INVAL due to a bug in the 2300. Unfortunately, the
* 2310 also reports itself as a 2300 so we need to get the
* fb revision level -- a 6 indicates it really is a 2300 and
* not a 2310.
*/
/* Pause RISC. */
0) {
break;
} else {
}
}
/* Select FPM registers. */
/* Get the fb rev level */
}
/* Deselect FPM registers. */
/* Release RISC module. */
0) {
break;
} else {
}
}
/*
* cPCI ISP2312 specific code to service function 1
* hot-swap registers.
*/
!= 0) {
}
}
/* max memory read byte cnt override */
if (ha->pci_max_read_req != 0) {
}
/* Set cache line register. */
/* Set latency register. */
/* Reset expansion ROM address decode enable. */
}
return (QL_SUCCESS);
}
/*
* Set the PCI max read request value.
*
* Input:
* ha: adapter state pointer.
*
* Output:
* none.
*
* Returns:
*
* Context:
* Kernel context.
*/
static void
{
/* check for vaild override value */
tmp == 4096) {
/* shift away the don't cares */
/* convert bit pos to request value */
}
} else {
"'pci-max-read-request': %d; using system "
"default\n", tmp);
}
/* check for vaild override value */
/* shift away the don't cares */
/* convert bit pos to request value */
}
BIT_12));
} else {
"'pci-max-read-request': %d; using system "
"default\n", tmp);
}
}
}
/*
* NVRAM configuration.
*
* Input:
* ha: adapter state pointer.
* ha->hba_buf = request and response rings
*
* Output:
* ha->init_ctrl_blk = initialization control block
* host adapters parameters in host adapter block
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval;
int idpromlen;
char idprombuf[32];
return (ql_nvram_24xx_config(ha));
}
start_addr = 0;
QL_SUCCESS) {
/* Verify valid NVRAM checksum. */
wptr++;
}
}
/* Bad NVRAM data, set defaults parameters. */
"id=%02x%02x%02x%02xh, flsz=%xh, pciconfvid=%xh, "
/* Don't print nvram message if it's an on-board 2200 */
}
/* Reset NVRAM data. */
/*
* Set default initialization control block.
*/
/*
* Allow 2048 byte frames for 2300
*/
}
idpromlen = 32;
/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
&idpromlen) != DDI_PROP_SUCCESS) {
} else {
}
/* Don't print nvram message if it's an on-board 2200 */
" default HBA parameters and temporary WWPN:"
" %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
}
/* Set default connection options for the 23xx to 2 */
BIT_5);
}
/*
* Set default host adapter parameters
*/
}
/* Check for adapter node name (big endian). */
break;
}
}
/* Copy port name if no node name (big endian). */
if (cnt == 8) {
}
/* Reset initialization control blocks. */
/* Get driver properties. */
"%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
/*
* Copy over NVRAM RISC parameter block
* to initialization control block.
*/
while (cnt-- != 0) {
}
/* Copy 2nd half. */
while (cnt-- != 0) {
}
/*
* Setup driver firmware options.
*/
/*
* There is no use enabling fast post for SBUS or 2300
* Always enable 64bit addressing, except SBUS cards.
*/
}
} else {
}
/* RIO and ZIO not supported. */
}
}
}
/*
* Set host adapter parameters
*/
if (ha->maximum_luns_per_target == 0) {
}
/*
* Setup ring parameters in initialization control block
*/
/*
* Setup IP initialization control block
*/
} else {
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* Get NVRAM data word
* Calculates word position in NVRAM and calls request routine to
* get the word from NVRAM.
*
* Input:
* ha = adapter state pointer.
* address = NVRAM word address.
*
* Returns:
* data word.
*
* Context:
* Kernel context.
*/
{
return (rval);
}
/*
* NVRAM request
* Sends read command to NVRAM and gets data from NVRAM.
*
* Input:
* ha = adapter state pointer.
* nv_cmd = Bit 26= start bit
* Bit 25, 24 = opcode
* Bit 23-16 = address
* Bit 15-0 = write data
*
* Returns:
* data word.
*
* Context:
* Kernel context.
*/
static uint16_t
{
/* Send command to NVRAM. */
nv_cmd <<= 5;
} else {
ql_nv_write(ha, 0);
}
nv_cmd <<= 1;
}
/* Read data from NVRAM. */
ql_nv_delay();
data <<= 1;
if (reg_data & NV_DATA_IN) {
}
ql_nv_delay();
}
/* Deselect chip. */
ql_nv_delay();
return (data);
}
void
{
ql_nv_delay();
ql_nv_delay();
ql_nv_delay();
}
void
ql_nv_delay(void)
{
}
/*
* ql_nvram_24xx_config
* ISP2400 nvram.
*
* Input:
* ha: adapter state pointer.
* ha->hba_buf = request and response rings
*
* Output:
* ha->init_ctrl_blk = initialization control block
* host adapters parameters in host adapter block
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int idpromlen;
char idprombuf[32];
int rval;
/* Get NVRAM data and calculate checksum. */
chksum = saved_chksum = 0;
if (rval != QL_SUCCESS) {
break;
}
longptr++;
}
}
/* Bad NVRAM data, set defaults parameters. */
/* Reset NVRAM data. */
/*
* Set default initialization control block.
*/
idpromlen = 32;
/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
&idpromlen) != DDI_PROP_SUCCESS) {
} else {
}
"HBA parameters and temporary "
"WWPN: %02x%02x%02x%02x%02x%02x%02x%02x", QL_NAME,
/*
* Set default host adapter parameters
*/
}
}
/* Check for adapter node name (big endian). */
break;
}
}
/* Copy port name if no node name (big endian). */
if (index == 8) {
}
/* Reset initialization control blocks. */
/* Get driver properties. */
"%02x%02x%02x%02x : WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
/*
* Copy over NVRAM Firmware Initialization Control Block.
*/
while (index--) {
}
while (index--) {
}
/*
* Setup driver firmware options.
*/
while (index--) {
}
index = sizeof (ql_ext_icb_8100_t);
while (index--) {
}
} else {
}
BIT_6);
} else {
}
~BIT_7);
/* enable special N port 2 N port login behaviour */
}
/*
* Set host adapter parameters
*/
if (ha->maximum_luns_per_target == 0) {
}
/* ISP2422 Serial Link Control */
}
/*
* Setup ring parameters in initialization control block
*/
/*
* Setup IP initialization control block
*/
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_lock_nvram
* Locks NVRAM access and returns starting address of NVRAM.
*
* Input:
* ha: adapter state pointer.
* addr: pointer for start address.
* flags: Are mutually exclusive:
* LNF_NVRAM_DATA --> get nvram
* LNF_VPD_DATA --> get vpd data (24/25xx only).
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int i;
return (QL_FUNCTION_FAILED);
}
if ((flags & LNF_NVRAM_DATA) == 0) {
return (QL_FUNCTION_FAILED);
}
/* if function number is non-zero, then adjust offset */
/* Try to get resource lock. Wait for 10 seconds max */
for (i = 0; i < 10000; i++) {
/* if nvram busy bit is reset, acquire sema */
break;
}
}
}
return (QL_FUNCTION_FAILED);
}
if (flags & LNF_VPD_DATA) {
} else if (flags & LNF_NVRAM_DATA) {
} else {
return (QL_FUNCTION_FAILED);
}
if (flags & LNF_VPD_DATA) {
} else if (flags & LNF_NVRAM_DATA) {
} else {
return (QL_FUNCTION_FAILED);
}
} else {
if ((flags & LNF_NVRAM_DATA) == 0) {
return (QL_FUNCTION_FAILED);
}
*addr = 0;
}
return (QL_SUCCESS);
}
/*
* ql_release_nvram
* Releases NVRAM access.
*
* Input:
* ha: adapter state pointer.
*
* Context:
* Kernel context.
*/
void
{
/* Release resource lock */
} else {
}
}
/*
* ql_23_properties
* Copies driver properties to NVRAM or adapter structure.
*
* Driver properties are by design global variables and hidden
* completely from administrators. Knowledgeable folks can
* override the default values using driver.conf
*
* Input:
* ha: adapter state pointer.
* nv: NVRAM structure pointer.
*
* Context:
* Kernel context.
*/
static void
{
/* Get frame payload size. */
data = 2048;
}
} else {
}
/* Get max IOCB allocation. */
nv->max_iocb_allocation[0] = 0;
/* Get execution throttle. */
data = 32;
}
} else {
}
/* Get Login timeout. */
data = 3;
}
if (data < 256) {
} else {
}
/* Get retry count. */
data = 4;
}
if (data < 256) {
} else {
"%d; using nvram value of %d\n", data,
}
/* Get adapter hard loop ID enable. */
if (data == 0) {
nv->firmware_options[0] =
} else if (data == 1) {
nv->firmware_options[0] =
} else if (data != 0xffffffff) {
"'enable-adapter-hard-loop-ID': %d; using nvram value "
}
/* Get adapter hard loop ID. */
if (data < 126) {
} else if (data != 0xffffffff) {
"%d; using nvram value of %d\n",
}
/* Get LIP reset. */
0xffffffff) {
data = 0;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-LIP-reset-on-bus-reset': %d; using nvram value "
}
/* Get LIP full login. */
0xffffffff) {
data = 1;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-LIP-full-login-on-bus-reset': %d; using nvram "
}
/* Get target reset. */
0xffffffff) {
data = 0;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-target-reset-on-bus-reset': %d; using nvram "
}
/* Get reset delay. */
data = 5;
}
} else {
}
/* Get port down retry count. */
data = 8;
}
if (data < 256) {
} else {
" %d; using nvram value of %d\n", data,
}
/* Get connection mode setting. */
data = 2;
}
} else {
"%d; using nvram value of %d\n", data,
}
/* Get data rate setting. */
data = 2;
}
if (data < 3) {
} else {
"%d; using nvram value of %d\n", data,
}
}
/* Get adapter id string for Sun branded 23xx only */
}
/* Get IP FW container count. */
/* Get IP low water mark. */
/* Get IP fast register post count. */
}
/*
* ql_common_properties
* Driver properties adapter structure.
*
* Driver properties are by design global variables and hidden
* completely from administrators. Knowledgeable folks can
* override the default values using driver.conf
*
* Input:
* ha: adapter state pointer.
*
* Context:
* Kernel context.
*/
void
{
/* Get extended logging trace buffer size. */
0xffffffff && data != 0) {
char *new_trace;
" trace buffer",
} else {
/* free the previous */
/* Use the new one */
}
}
}
/* Get extended logging enable. */
data == 0) {
} else if (data == 1) {
} else {
" using default value of 0\n", data);
}
/* Get extended logging trace disable. */
0xffffffff || data == 0) {
} else if (data == 1) {
} else {
"'disable-extended-logging-trace': %d;"
" using default value of 0\n", data);
}
/* Get FCP 2 Error Recovery. */
} else if (data == 0) {
} else {
"'enable-FCP-2-error-recovery': %d; using nvram value of "
"1\n", data);
}
#ifdef QL_DEBUG_LEVEL_2
#endif
/* Get port down retry delay. */
} else if (data < 256) {
} else {
}
/* Get queue full retry count. */
} else if (data < 256) {
} else {
" %d; using default value of 16", data);
}
/* Get queue full retry delay. */
} else if (data < 256) {
} else {
}
/* Get loop down timeout. */
data = 0;
} else if (data > 255) {
" using nvram value of 0\n", data);
data = 0;
}
}
/* Get link down error enable. */
data == 1) {
} else if (data == 0) {
} else {
" using default value of 1\n", data);
}
/*
* Get firmware dump flags.
* TAKE_FW_DUMP_ON_MAILBOX_TIMEOUT BIT_0
* TAKE_FW_DUMP_ON_ISP_SYSTEM_ERROR BIT_1
* TAKE_FW_DUMP_ON_DRIVER_COMMAND_TIMEOUT BIT_2
* TAKE_FW_DUMP_ON_LOOP_OFFLINE_TIMEOUT BIT_3
*/
}
}
}
}
}
/* Get the PCI max read request size override. */
ha->pci_max_read_req = 0;
data != 0) {
}
/* Get the attach fw_ready override value. */
} else {
"'init-loop-sync-wait': %d; using default "
}
}
}
/*
* ql_24xx_properties
* Copies driver properties to NVRAM or adapter structure.
*
* Driver properties are by design global variables and hidden
* completely from administrators. Knowledgeable folks can
*
* Input:
* ha: adapter state pointer.
* nv: NVRAM structure pointer.
*
* Context:
* Kernel context.
*/
static void
{
/* Get frame size */
data = 2048;
}
} else {
}
/* Get execution throttle. */
data = 32;
}
} else {
}
/* Get Login timeout. */
data = 3;
}
if (data < 65536) {
} else {
}
/* Get retry count. */
data = 4;
}
if (data < 65536) {
} else {
}
/* Get adapter hard loop ID enable. */
if (data == 0) {
nv->firmware_options_1[0] =
} else if (data == 1) {
nv->firmware_options_1[0] =
} else if (data != 0xffffffff) {
"'enable-adapter-hard-loop-ID': %d; using nvram value "
"of %d\n", data,
}
/* Get adapter hard loop ID. */
if (data < 126) {
} else if (data != 0xffffffff) {
}
/* Get LIP reset. */
0xffffffff) {
data = 0;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-LIP-reset-on-bus-reset': %d; using value of 0\n",
data);
}
/* Get LIP full login. */
0xffffffff) {
data = 1;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-LIP-full-login-on-bus-reset': %d; using nvram "
}
/* Get target reset. */
0xffffffff) {
data = 0;
}
if (data == 0) {
} else if (data == 1) {
} else {
"'enable-target-reset-on-bus-reset': %d; using nvram "
}
/* Get reset delay. */
data = 5;
}
} else {
}
/* Get port down retry count. */
data = 8;
}
if (data < 256) {
} else {
nv->port_down_retry_count[0],
}
/* Get connection mode setting. */
data = 2;
}
if (data <= 2) {
} else {
" %d; using nvram value of %d\n", data,
}
/* Get data rate setting. */
data = 2;
}
} else {
"using nvram value of %d\n", data,
}
/* Get IP FW container count. */
/* Get IP low water mark. */
/* Get enable flash load. */
data == 0) {
} else if (data == 1) {
} else {
"%d; using default value of 0\n", data);
}
/* Enable firmware extended tracing */
if (data != 0) {
}
}
/* Enable firmware fc tracing */
}
}
/*
* ql_get_prop
* Get property value from configuration file.
*
* Input:
* ha= adapter state pointer.
* string = property string pointer.
*
* Returns:
* 0xFFFFFFFF = no property else property value.
*
* Context:
* Kernel context.
*/
{
char buf[256];
/*
* Look for a adapter instance NPIV (virtual port) specific parameter
*/
/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
buf, (int)0xffffffff);
}
/*
* Get adapter instance parameter if a vp specific one isn't found.
*/
if (data == 0xffffffff) {
/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
0, buf, (int)0xffffffff);
}
/* Adapter instance parameter found? */
if (data == 0xffffffff) {
/* No, get default parameter. */
/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
string, (int)0xffffffff);
}
return (data);
}
/*
* ql_check_isp_firmware
* Checks if using already loaded RISC code or drivers copy.
* If using already loaded code, save a copy of it.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
int rval;
ha->risc_code_size = 0;
}
/* Get RISC code length. */
1);
if (rval == QL_SUCCESS) {
/* Dump RISC code. */
do {
} else {
}
if (rval != QL_SUCCESS) {
ha->risc_code_size);
ha->risc_code_size = 0;
break;
}
(void) ddi_dma_sync(
fw_size -= byte_count;
bufp += byte_count;
} while (fw_size != 0);
}
}
} else {
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* Chip diagnostics
* Test chip for proper operation.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
do {
/* Reset ISP chip. */
/* For ISP2200A reduce firmware load size. */
} else {
}
/* Check product ID of chip */
id = 0x2432;
id = 0x2422;
} else {
}
mailbox[4]);
mailbox[5]);
mailbox[6]);
mailbox[7]);
strlen(QL_VERSION));
/* Wrap Incoming Mailboxes Test. */
if (rval == QL_SUCCESS) {
(void) ql_flash_errlog(ha,
}
} else {
}
} else {
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_load_isp_firmware
* Load and start RISC firmware.
* Uses request ring for DMA buffer.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval;
return (ql_load_flash_fw(ha));
}
/* Load firmware segments */
while (risc_code_size) {
if (word_count > risc_code_size) {
}
} else {
if (word_count > risc_code_size) {
}
}
if (rval != QL_SUCCESS) {
break;
}
}
}
/* Start firmware. */
if (rval == QL_SUCCESS) {
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_load_flash_fw
* Gets ISP24xx firmware from flash and loads ISP.
*
* Input:
* ha: adapter state pointer.
*
* Returns:
* ql local function return status code.
*/
static int
{
int rval;
uint32_t risc_code_size = 0;
do {
/* Read data from flash. */
if (rval != QL_SUCCESS) {
break;
}
}
if (rval != QL_SUCCESS) {
break;
}
if (risc_code_size == 0) {
}
if (risc_code_size < xfer_size) {
}
if (rval != QL_SUCCESS) {
break;
}
} while (risc_code_size);
if (rval != QL_SUCCESS) {
break;
}
}
/* Start firmware. */
if (rval == QL_SUCCESS) {
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_start_firmware
* Starts RISC code.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
/* Verify checksum of loaded RISC code. */
if (rval == QL_SUCCESS) {
/* Start firmware execution. */
(void) ql_execute_fw(ha);
/* Save firmware version. */
0x100000) + 1) * 4;
0, 0, &data)) == QL_SUCCESS) {
} else {
}
}
/* Set Serdes Transmit Parameters. */
}
}
if (rval != QL_SUCCESS) {
} else {
}
return (rval);
}
/*
* ql_set_cache_line
* Sets PCI cache line parameter.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
/* Set the cache line. */
/* Set cache line register. */
}
return (QL_SUCCESS);
}
/*
* ql_init_rings
* Initializes firmware and ring pointers.
*
* Beginning of response ring has initialization control block
* already built by nvram config routine.
*
* Input:
* ha = adapter state pointer.
* ha->hba_buf = request and response rings
* ha->init_ctrl_blk = initialization control block
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
/* Clear outstanding commands array. */
}
/* Initialize firmware. */
ha->req_ring_index = 0;
ha->rsp_ring_index = 0;
/* Allow connection option 2. */
}
}
}
/* Tell firmware to enable MBA_PORT_BYPASS_CHANGED event */
if (rval == QL_SUCCESS) {
}
}
/* Firmware Fibre Channel Event Trace Buffer */
} else {
FTO_FCE_TRACE_ENABLE)) != QL_SUCCESS) {
}
}
}
/* Firmware Extended Trace Buffer */
} else {
FTO_EXT_TRACE_ENABLE)) != QL_SUCCESS) {
}
}
}
/* Wait for firmware login of menlo. */
break;
}
ddi_in_panic()) {
}
}
/* Delay for 1 tick (10 milliseconds). */
}
if (timer == 0) {
} else {
} else {
sizeof (ql_mbx_iocb_t));
if (rval != QL_SUCCESS ||
"cs=%xh, fc=%xh\n", rval,
if (rval == QL_SUCCESS) {
}
}
}
}
}
if (rval != QL_SUCCESS) {
} else {
}
return (rval);
}
/*
* ql_fw_ready
* Waits for firmware ready. If firmware becomes ready
* device queues and RISC code are synchronized.
*
* Input:
* ha = adapter state pointer.
* secs = max wait time, in seconds (0-255).
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval = QL_FUNCTION_FAILED;
/* Wait for ISP to finish LIP */
if (rval == QL_SUCCESS) {
LOOP_DOWN)) {
wait--;
wait--;
}
} else {
/* Firmware is ready. Get 2 * R_A_TOV. */
if (rval != QL_SUCCESS) {
"=%xh\n", rval);
}
/* Configure loop. */
if (ha->task_daemon_flags &
wait--;
} else {
break;
}
}
} else {
wait--;
}
}
/* Delay for a tick if waiting. */
if (timer % 4 == 0) {
} else {
}
} else {
}
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_configure_loop
* Setup configurations based on loop.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
int rval;
continue;
}
(LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
(LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
(void) ql_configure_fabric(vha);
}
}
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_configure_n_port_info
* Setup configurations based on N port 2 N port topology.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static void
{
/* Free existing target queues. */
}
}
/*
* If the N_Port's WWPN is larger than our's then it has the
* N_Port login initiative. It will have determined that and
* logged in with the firmware. This results in a device
* database entry. In this situation we will later send up a PLOGI
* by proxy for the N_Port to get things going.
*
* If the N_Ports WWPN is smaller then the firmware has the
* N_Port login initiative and does a FLOGI in order to obtain the
* N_Ports WWNN and WWPN. These names are required later
* during Leadvilles FLOGI. No PLOGI is done by the firmware in
* anticipation of a PLOGI via the driver from the upper layers.
* Upon reciept of said PLOGI the driver issues an ELS PLOGI
* pass-through command and the firmware assumes the s_id
* and the N_Port assumes the d_id and Bob's your uncle.
*/
/*
* In N port 2 N port topology the FW provides a port database entry at
* loop_id 0x7fe which allows us to acquire the Ports WWPN.
*/
} else {
}
/* Capture the N Ports WWPN */
/* Resolve an n_port_handle */
QL_SUCCESS) {
}
} else {
index++) {
/* resuse tq */
PDF_NONE);
if (rval == QL_NOT_LOGGED_IN) {
if (tq->master_state ==
break;
}
} else {
break;
}
}
}
} else {
}
}
}
}
/*
* ql_configure_hba
* Setup adapter context.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
int rval;
/* Get host addresses. */
if (rval == QL_SUCCESS) {
/* Save Host d_id, alpa, loop ID. */
/* Get loop topology. */
case CNX_LOOP_NO_FABRIC:
break;
case CNX_FLPORT_IN_LOOP:
break;
case CNX_NPORT_2_NPORT_P2P:
}
break;
case CNX_FLPORT_P2P:
/* Get supported option. */
}
break;
default:
break;
}
CFG_CTRL_242581))) {
if (rval != QL_SUCCESS) {
} else {
} else {
state = 0;
}
}
} else {
}
} else if (rval == MBS_COMMAND_ERROR) {
}
if (rval != QL_SUCCESS) {
} else {
"wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n",
}
return (rval);
}
/*
* ql_configure_device_d_id
* Updates device loop ID.
* Also adds to device queue any new devices found on private loop.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
int rval;
int loop;
return (rval);
}
do {
/*
* Get data from RISC code d_id list to init each device queue.
*/
if (rval != QL_SUCCESS) {
return (rval);
}
/* Acquire adapter state lock. */
/* Mark all queues as unusable. */
}
}
}
/* If device not in queues add new queue. */
/* Test for fabric device. */
}
PDF_NONE) == QL_SUCCESS) {
~PORT_LOST_ID);
} else {
}
}
}
}
/* 24xx does not report switch devices in ID list. */
}
}
}
}
/* If F_port exists, allocate queue for FL_Port. */
}
}
/* Allocate queue for broadcast. */
/* Check for any devices lost. */
TQF_FABRIC_DEVICE))) {
}
}
}
/* Release adapter state lock. */
/* Give devices time to recover. */
drv_usecwait(1000000);
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_dev_list
* Gets device d_id and loop ID from firmware device list.
*
* Input:
* ha: adapter state pointer.
* list device list pointer.
* index: list index of device data.
* d_id: pointer for d_id data.
* id: pointer for loop ID.
*
* Context:
* Kernel context.
*/
void
{
} else {
}
}
/*
* ql_configure_fabric
* Setup fabric context.
*
* Input:
* ha = adapter state pointer.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
static int
{
int rval = QL_FUNCTION_FAILED;
/* Test switch fabric controller present. */
rval = QL_SUCCESS;
}
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_reset_chip
* Reset ISP chip.
*
* Input:
* ha = adapter block pointer.
* All activity on chip must be already stopped.
* ADAPTER_STATE_LOCK must be released.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
void
{
/*
* accessing pci space while not powered can cause panic's
* on some platforms (i.e. Sunblade 1000's)
*/
return;
}
/* Reset all outbound mailbox registers */
}
/* Disable ISP interrupts. */
return;
}
/*
* We are going to reset the chip in case of 2300. That might cause
* a PBM ERR if a DMA transaction is in progress. One way of
* avoiding it is to disable Bus Master operation before we start
* the reset activity.
*/
/* Pause RISC. */
break;
}
}
/*
* A call to ql_isr() can still happen through
* ql_mailbox_command(). So Mark that we are/(will-be)
* running from rom code now.
*/
/* Select FPM registers. */
/* FPM Soft Reset. */
/* Toggle FPM reset for 2300 */
}
/* Select frame buffer registers. */
/* Reset frame buffer FIFOs. */
/* read back fb_cmd until zero or 3 seconds max */
break;
}
drv_usecwait(10);
}
} else {
}
/* Select RISC module registers. */
/* Reset RISC module. */
/* Reset ISP semaphore. */
/* Release RISC module. */
/* Insure mailbox registers are free. */
/* Bus Master is disabled so chip reset is safe. */
/* Wait for reset to finish. */
break;
}
}
}
/* Wait for RISC to recover from reset. */
break;
}
}
/* restore bus master */
/* Disable RISC pause on FPM parity error. */
/* Initialize probe registers */
/* Pause RISC. */
break;
} else {
}
}
/* Select FPM registers. */
/* Set probe register */
/* Select RISC module registers. */
/* Release RISC module. */
}
}
/*
* ql_reset_24xx_chip
* Reset ISP24xx chip.
*
* Input:
* ha = adapter block pointer.
* All activity on chip must be already stopped.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
void
{
/* Shutdown DMA. */
/* Wait for DMA to stop. */
break;
}
drv_usecwait(100);
}
/* Stop the firmware. */
break;
}
}
drv_usecwait(100);
}
/* Reset the chip. */
drv_usecwait(100);
/* Wait for idle status from ROM firmware. */
break;
}
drv_usecwait(100);
}
/* Wait for reset to finish. */
break;
}
drv_usecwait(100);
}
/* Insure mailbox registers are free. */
/*
* Set flash write-protection.
*/
}
}
/*
* ql_abort_isp
* Resets ISP and aborts all outstanding commands.
*
* Input:
* ha = adapter state pointer.
* DEVICE_QUEUE_LOCK must be released.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval = QL_SUCCESS;
return (rval);
}
}
/* Acquire mailbox register lock. */
/* Wake up mailbox box routine. */
/* Release mailbox register lock. */
/* Wait for mailbox. */
drv_usecwait(50000);
}
}
/* Wait for commands to end gracefully if not in panic. */
} else if (ddi_in_panic() == 0) {
}
/* Shutdown IP. */
(void) ql_shutdown_ip(ha);
}
/* Reset the chip. */
/* Place all commands in outstanding cmd list on device queue. */
index = 0;
} else {
continue;
}
}
/* If command timeout. */
/* Call done routine to handle completion. */
continue;
}
/* Acquire target queue lock. */
/* Reset watchdog time. */
/* Place request back on top of device queue. */
/* Release target queue lock. */
}
/*
* Clear per LUN active count, because there should not be
* any IO outstanding at this time.
*/
lq->lun_outcnt = 0;
}
}
}
}
if (rval == QL_SUCCESS) {
(void) ql_load_isp_firmware(ha);
}
/* If reset abort needed that may have been set. */
/* Enable ISP interrupts. */
/* Set loop online, if it really is. */
if (state != DDI_DEVSTATE_UP) {
/*EMPTY*/
DDI_DEVICE_FAULT, "Device reset succeeded");
}
} else {
/* Enable ISP interrupts. */
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_vport_control
* Issue Virtual Port Control command.
*
* Input:
* ha = virtual adapter state pointer.
* cmd = control command.
*
* Returns:
* ql local function return status code.
*
* Context:
* Kernel context.
*/
int
{
int rval;
pkt_size = sizeof (ql_mbx_iocb_t);
return (QL_MEMORY_ALLOC_FAILED);
}
}
} else {
rval = QL_SUCCESS;
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_vport_modify
* Issue of Modify Virtual Port command.
*
* Input:
* ha = virtual adapter state pointer.
* cmd = command.
* opt = option.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
int
{
int rval;
pkt_size = sizeof (ql_mbx_iocb_t);
return (QL_MEMORY_ALLOC_FAILED);
}
8);
8);
}
if (rval != QL_SUCCESS) {
} else {
/*EMPTY*/
}
return (rval);
}
/*
* ql_vport_enable
* Enable virtual port.
*
* Input:
* ha = virtual adapter state pointer.
*
* Context:
* Kernel context.
*/
int
{
int timer;
return (QL_FUNCTION_FAILED);
}
/* Wait for loop to come up. */
timer++) {
delay(1);
}
}
return (QL_SUCCESS);
}
/*
* ql_vport_create
* Create virtual port context.
*
* Input:
* ha: parent adapter state pointer.
* index: virtual port index number.
*
* Context:
* Kernel context.
*/
{
/* Inherit the parents data. */
vha->ub_allocated = 0;
vha->task_daemon_flags = 0;
KM_SLEEP);
KM_SLEEP);
return (vha);
}
/*
* ql_vport_destroy
* Destroys virtual port context.
*
* Input:
* ha = virtual adapter state pointer.
*
* Context:
* Kernel context.
*/
void
{
/* Remove port from list. */
break;
}
}
}
}
}