qlt.c revision 3fb517f786391b507780c78aabb8d98bfea9efe9
/*
* 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. All rights reserved.
* Use is subject to license terms.
*/
/*
*/
#include <sys/byteorder.h>
#include <stmf_defines.h>
#include <fct_defines.h>
#include <stmf.h>
#include <portif.h>
#include <fct.h>
#include <qlt.h>
#include <qlt_dma.h>
#include <qlt_ioctl.h>
#include <qlt_open.h>
#include <stmf_ioctl.h>
static void qlt_enable_intr(qlt_state_t *);
static void qlt_disable_intr(qlt_state_t *);
char **prop_val);
static int qlt_read_int_instance_prop(qlt_state_t *, char *, int);
uint32_t);
uint32_t *);
int qlt_enable_msix = 0;
int qlt_enable_msi = 1;
/* Array to quickly calculate next free buf index to use */
#if 0
#endif
static struct cb_ops qlt_cb_ops = {
0,
};
0,
NULL,
};
#ifndef PORT_SPEED_10G
#define PORT_SPEED_10G 16
#endif
&qlt_ops,
};
static struct modlinkage modlinkage = {
};
static uint32_t qlt_loaded_counter = 0;
"-X Mode 1 133", "--Invalid--",
"-X Mode 2 66", "-X Mode 2 100",
"-X Mode 2 133", " 66" };
/* Always use 64 bit DMA. */
static ddi_dma_attr_t qlt_queue_dma_attr = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* low DMA address range */
0xffffffffffffffff, /* high DMA address range */
0xffffffff, /* DMA counter register */
64, /* DMA address alignment */
0xff, /* DMA burstsizes */
1, /* min effective DMA size */
0xffffffff, /* max DMA xfer size */
0xffffffff, /* segment boundary */
1, /* s/g list length */
1, /* granularity of device */
0 /* DMA transfer flags */
};
/* qlogic logging */
int enable_extended_logging = 0;
static char qlt_provider_name[] = "qlt";
static struct stmf_port_provider *qlt_pp;
int
_init(void)
{
int ret;
if (ret == 0) {
STMF_STRUCT_PORT_PROVIDER, 0, 0);
return (EIO);
}
if (ret != 0) {
(void) stmf_deregister_port_provider(qlt_pp);
}
}
return (ret);
}
int
_fini(void)
{
int ret;
if (qlt_loaded_counter)
return (EBUSY);
if (ret == 0) {
(void) stmf_deregister_port_provider(qlt_pp);
}
return (ret);
}
int
{
}
static int
{
int instance;
int max_read_size;
int max_payload_size;
/* No support for suspend resume yet */
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
return (DDI_FAILURE);
}
NULL) {
goto attach_fail_1;
}
goto attach_fail_1;
}
goto attach_fail_2;
}
(did != 0x8001)) {
goto attach_fail_4;
}
goto attach_fail_4;
}
if (did == 0x2422) {
pci_bits >>= 8;
pci_bits &= 0xf;
"!qlt(%d): HBA running at PCI%sMHz (%d)",
} else {
"qlt(%d): HBA running at PCI%sMHz %s(%d)",
"(Invalid)", ((pci_bits == 0) ||
}
}
(unsigned long long)ret);
goto attach_fail_5;
}
goto attach_fail_5;
}
DDI_SUCCESS) {
goto attach_fail_6;
}
goto attach_fail_7;
}
if (ncookies != 1)
goto attach_fail_8;
/* mutex are inited in this function */
goto attach_fail_8;
"qlt%d", instance);
goto attach_fail_9;
}
/* Setup PCI cfg space registers */
if (max_read_size == 11)
if (did == 0x2422) {
if (max_read_size == 512)
val = 0;
else if (max_read_size == 1024)
val = 1;
else if (max_read_size == 2048)
val = 2;
else if (max_read_size == 4096)
val = 3;
else {
"pci-max-read-request in qlt.conf. Valid values "
"for this HBA are 512/1024/2048/4096", instance);
}
if (max_read_size == 128)
val = 0;
else if (max_read_size == 256)
val = 1;
else if (max_read_size == 512)
val = 2;
else if (max_read_size == 1024)
val = 3;
else if (max_read_size == 2048)
val = 4;
else if (max_read_size == 4096)
val = 5;
else {
"pci-max-read-request in qlt.conf. Valid values "
"for this HBA are 128/256/512/1024/2048/4096",
instance);
}
} else {
"pci-max-read-request for this device (%x)",
}
if (max_payload_size == 11)
goto over_max_payload_setting;
if (max_payload_size == 128)
val = 0;
else if (max_payload_size == 256)
val = 1;
else if (max_payload_size == 512)
val = 2;
else if (max_payload_size == 1024)
val = 3;
else {
"pcie-max-payload-size in qlt.conf. Valid values "
"for this HBA are 128/256/512/1024",
instance);
goto over_max_payload_setting;
}
} else {
"pcie-max-payload-size for this device (%x)",
}
goto attach_fail_10;
return (DDI_SUCCESS);
(void) qlt_el_trace_desc_dtor(qlt);
return (DDI_FAILURE);
}
#define FCT_I_EVENT_BRING_PORT_OFFLINE 0x83
/* ARGSUSED */
static int
{
int instance;
NULL) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
(void) qlt_el_trace_desc_dtor(qlt);
return (DDI_SUCCESS);
}
/*
* qlt_quiesce quiesce a device attached to the system.
*/
static int
{
/* Oh well.... */
return (DDI_SUCCESS);
}
if (stat & RISC_HOST_INTR_REQUEST) {
break;
}
}
drv_usecwait(100);
}
/* Reset the chip. */
drv_usecwait(100);
return (DDI_SUCCESS);
}
static void
{
} else {
int i;
}
}
static void
{
} else {
int i;
}
qlt->qlt_intr_enabled = 0;
}
static void
{
int i;
}
}
}
static void
{
}
static void
{
}
static int
{
int ret;
int itype = DDI_INTR_TYPE_MSIX;
int i;
count);
return (DDI_FAILURE);
}
avail);
return (DDI_FAILURE);
}
}
/* we need at least 2 interrupt vectors */
actual);
ret = DDI_FAILURE;
goto release_intr;
}
}
if (ret != DDI_SUCCESS) {
ret = DDI_FAILURE;
goto release_intr;
}
for (i = 0; i < actual; i++) {
if (ret != DDI_SUCCESS) {
goto release_mutex;
}
}
return (DDI_SUCCESS);
for (i = 0; i < actual; i++)
#if 0
#endif
return (ret);
}
static int
{
int itype = DDI_INTR_TYPE_MSI;
int ret;
int i;
/* get the # of interrupts */
count);
return (DDI_FAILURE);
}
avail);
return (DDI_FAILURE);
}
}
/* MSI requires only 1 interrupt. */
count = 1;
/* allocate interrupt */
actual);
ret = DDI_FAILURE;
goto free_mem;
}
}
/*
* Get priority for first msi, assume remaining are all the same.
*/
if (ret != DDI_SUCCESS) {
ret = DDI_FAILURE;
goto release_intr;
}
/* add handler */
for (i = 0; i < actual; i++) {
if (ret != DDI_SUCCESS) {
goto release_mutex;
}
}
return (DDI_SUCCESS);
for (i = 0; i < actual; i++)
return (ret);
}
static int
{
int count;
int actual;
int ret;
int itype = DDI_INTR_TYPE_FIXED;
/* Fixed interrupts can only have one interrupt. */
count);
return (DDI_FAILURE);
}
actual);
ret = DDI_FAILURE;
goto free_mem;
}
if (ret != DDI_SUCCESS) {
ret = DDI_FAILURE;
goto release_intr;
}
if (ret != DDI_SUCCESS) {
goto release_mutex;
}
return (DDI_SUCCESS);
return (ret);
}
static int
{
int itypes = 0;
/*
* x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
*/
#ifndef __sparc
if (qlt_enable_msi != 0) {
#endif
}
return (DDI_SUCCESS);
}
if (itypes & DDI_INTR_TYPE_MSI) {
return (DDI_SUCCESS);
}
#ifndef __sparc
}
#endif
return (qlt_setup_fixed(qlt));
}
/*
* Filling the hba attributes
*/
void
struct fct_port_attrs *port_attrs)
{
int len;
"QLogic Corp.");
"%s", QLT_NAME);
"%s", QLT_VERSION);
/* Get FCode version */
(int *)&len) == DDI_PROP_SUCCESS) {
} else {
#ifdef __sparc
FCHBA_OPTION_ROM_VERSION_LEN, "No Fcode found");
#else
FCHBA_OPTION_ROM_VERSION_LEN, "N/A");
#endif
}
if (qlt->qlt_25xx_chip)
if (qlt->qlt_81xx_chip)
/* limit string length to nvr model_name length */
}
/* ARGSUSED */
{
uint8_t *p;
switch (cmd) {
case FC_TGT_PORT_RLS:
if ((*bufsizep) < sizeof (fct_port_link_status_t)) {
"fct_port_link_status_t=%xh\n", *bufsizep,
sizeof (fct_port_link_status_t));
ret = FCT_FAILURE;
break;
}
/* send mailbox command to get link status */
break;
}
/* GET LINK STATUS count */
if (ret != QLT_SUCCESS) {
break;
}
break;
default:
ret = FCT_FAILURE;
break;
}
return (ret);
}
{
return (FCT_FAILURE);
}
/* Initialize the ddi_dma_handle free pool */
goto qlt_pstart_fail_1;
}
goto qlt_pstart_fail_2;
}
/*
* Since we keep everything in the state struct and dont allocate any
* port private area, just use that pointer to point to the
* state struct.
*/
goto qlt_pstart_fail_2_5;
}
return (QLT_SUCCESS);
#if 0
(void) fct_deregister_local_port(port);
#endif
return (QLT_FAILURE);
}
{
return (QLT_FAILURE);
}
return (QLT_SUCCESS);
}
/*
* Called by framework to init the HBA.
* Can be called in the middle of I/O. (Why ??)
* Should make sure sane state both before and after the initialization
*/
{
int instance, i;
/* XXX Make sure a sane state */
return (ret);
}
/* Get resource count */
if (ret != QLT_SUCCESS) {
return (ret);
}
/* Enable PUREX */
if (ret != QLT_SUCCESS) {
return (ret);
}
/* Pass ELS bitmap to fw */
if (ret != QLT_SUCCESS) {
elsbmp[1]);
return (ret);
}
/* Init queue pointers */
/*
* XXX support for tunables. Also should we cache icb ?
*/
if (qlt->qlt_81xx_chip) {
/* allocate extra 64 bytes for Extended init control block */
} else {
}
return (STMF_ALLOC_FAILURE);
}
if (qlt->qlt_81xx_chip) {
} else {
}
if (!qlt->qlt_81xx_chip) {
}
if (qlt->qlt_81xx_chip) {
} else {
BIT_4);
}
if (qlt->qlt_81xx_chip) {
index = sizeof (qlt_ext_icb_81xx_t);
/* Use defaults for cases where we find nothing in NVR */
if (*src == 0) {
instance);
/*
* not yet, for !FIP firmware at least
*
* qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
*/
#ifdef _LITTLE_ENDIAN
#else
#endif
}
while (index--) {
}
0xffff);
/* eicb enable */
}
/*
* This is the 1st command after adapter initialize which will
* use interrupts and regular mailbox interface.
*/
/* Issue mailbox to firmware */
if (ret != QLT_SUCCESS) {
}
if (ret != QLT_SUCCESS) {
(long long)ret);
}
/*
* Report FW versions for 81xx - MPI rev is useful
*/
if (qlt->qlt_81xx_chip) {
if (ret != QLT_SUCCESS) {
} else {
}
}
for (i = 0; i < 5; i++) {
qlt->qlt_bufref[i] = 0;
}
qlt->qlt_bumpbucket = 0;
qlt->qlt_pmintry = 0;
qlt->qlt_pmin_ok = 0;
if (ret != QLT_SUCCESS)
return (ret);
return (FCT_SUCCESS);
}
{
int retries;
goto poff_mbox_done;
}
/* Wait to grab the mailboxes */
retries++) {
if ((retries > 5) ||
goto poff_mbox_done;
}
}
(void) qlt_reset_chip(qlt);
drv_usecwait(20);
qlt->intr_sneak_counter = 0;
return (FCT_SUCCESS);
}
static fct_status_t
{
/* Issue mailbox to firmware */
if (ret != QLT_SUCCESS) {
/* Firmware is not ready */
if (ddi_get_lbolt() < et) {
goto link_info_retry;
}
}
} else {
case 1:
break;
case 0:
break;
case 3:
break;
case 2: /*FALLTHROUGH*/
case 4:
break;
default:
}
}
if (fc_ret != QLT_SUCCESS) {
fc_ret);
"database for F_port failed, ret = %llx", fc_ret);
} else {
uint8_t *p;
}
}
return (fc_ret);
}
static int
{
int instance;
return (EINVAL);
}
/*
* Since this is for debugging only, only allow root to issue ioctl now
*/
return (EPERM);
}
return (ENXIO);
}
/*
* It is already open for exclusive access.
* So shut the door on this caller.
*/
return (EBUSY);
}
/*
* Exclusive operation not possible
* as it is already opened
*/
return (EBUSY);
}
}
return (0);
}
/* ARGSUSED */
static int
{
int instance;
return (EINVAL);
}
return (ENXIO);
}
return (ENODEV);
}
/*
* It looks there's one hole here, maybe there could several concurrent
* shareed open session, but we never check this case.
* But it will not hurt too much, disregard it now.
*/
return (0);
}
/*
* All of these ioctls are unstable interfaces which are meant to be used
* in a controlled lab env. No formal testing will be (or needs to be) done
* for these ioctls. Specially note that running with an additional
* uploaded firmware is not supported and is provided here for test
* purposes only.
*/
/* ARGSUSED */
static int
{
int ret = 0;
#ifdef _LITTLE_ENDIAN
int i;
#endif
char info[80];
return (EPERM);
if (ret)
return (ret);
iocd->stmf_error = 0;
switch (cmd) {
case QLT_IOCTL_FETCH_FWDUMP:
break;
}
break;
}
break;
}
break;
}
break;
case QLT_IOCTL_TRIGGER_FWDUMP:
break;
}
"user triggered FWDUMP with RFLAG_RESET", (void *)qlt);
info[79] = 0;
"%llxh\n", ret2);
}
break;
case QLT_IOCTL_UPLOAD_FW:
break;
}
#ifdef _LITTLE_ENDIAN
}
#endif
iocd->stmf_ibuf_size)) {
break;
}
break;
}
/* Everything looks ok, lets copy this firmware */
} else {
}
KM_SLEEP);
break;
case QLT_IOCTL_CLEAR_FW:
}
break;
case QLT_IOCTL_GET_FW_INFO:
break;
}
if (qlt->qlt_stay_offline) {
}
}
}
if (qlt->qlt_81xx_chip) {
} else if (qlt->qlt_25xx_chip) {
} else {
}
break;
case QLT_IOCTL_STAY_OFFLINE:
if (!iocd->stmf_ibuf_size) {
break;
}
if (*((char *)ibuf)) {
} else {
qlt->qlt_stay_offline = 0;
}
break;
case QLT_IOCTL_MBOX:
break;
}
break;
}
if (st != QLT_SUCCESS) {
st = QLT_SUCCESS;
}
if (st != QLT_SUCCESS) {
switch (st) {
case QLT_MBOX_NOT_INITIALIZED:
break;
case QLT_MBOX_BUSY:
break;
case QLT_MBOX_TIMEOUT:
break;
case QLT_MBOX_ABORTED:
break;
}
}
break;
case QLT_IOCTL_ELOG:
break;
default:
}
if (ret == 0) {
} else if (iocd->stmf_error) {
}
if (obuf) {
}
if (ibuf) {
}
return (ret);
}
static fct_status_t
{
if (rval != FCT_SUCCESS) {
} else {
rval = FCT_FAILURE;
}
}
return (rval);
}
static void
{
(cmd == FCT_CMD_PORT_OFFLINE) ||
(cmd == FCT_CMD_FORCE_LIP) ||
(cmd == FCT_ACK_PORT_ONLINE_COMPLETE) ||
(cmd == FCT_ACK_PORT_OFFLINE_COMPLETE));
switch (cmd) {
case FCT_CMD_PORT_ONLINE:
qlt->qlt_state_not_acked = 0;
} else {
}
}
qlt->qlt_change_state_flags = 0;
break;
case FCT_CMD_PORT_OFFLINE:
}
}
qlt->qlt_state_not_acked = 0;
} else {
}
}
break;
qlt->qlt_state_not_acked = 0;
break;
qlt->qlt_state_not_acked = 0;
(qlt->qlt_stay_offline == 0)) {
"qlt_ctl FCT_ACK_PORT_OFFLINE_COMPLETE "
"with RLFLAG_RESET")) != FCT_SUCCESS) {
ret);
"fct_port_initialize failed, please use "
"stmfstate to start the port-%s manualy",
}
}
break;
case FCT_CMD_FORCE_LIP:
if (qlt->qlt_81xx_chip) {
"for this adapter type\n");
} else {
}
break;
default:
break;
}
}
/* ARGSUSED */
static fct_status_t
{
return (FCT_FAILURE);
}
/*
* Return a pointer to n entries in the request queue. Assumes that
* request queue lock is held. Does a very short busy wait if
* fullfill the request.
* **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK**
*/
{
int try = 0;
while (qlt->req_available < n) {
continue;
(REQUEST_QUEUE_ENTRIES - 1));
if (qlt->req_available < n) {
if (try < 2) {
drv_usecwait(100);
try++;
continue;
} else {
"Req Q is full");
return (NULL);
}
}
break;
}
/* We dont change anything until the entries are sumitted */
}
/*
* updates the req in ptr to fw. Assumes that req lock is held.
*/
void
{
ASSERT(n >= 1);
qlt->req_ndx_to_fw += n;
qlt->req_available -= n;
}
/*
* Return a pointer to n entries in the priority request queue. Assumes that
* priority request queue lock is held. Does a very short busy wait if
* fullfill the request.
* **CALL qlt_submit_preq_entries() BEFORE DROPPING THE LOCK**
*/
{
int try = 0;
(PRIORITY_QUEUE_ENTRIES - 1));
while (req_available < n) {
continue;
(PRIORITY_QUEUE_ENTRIES - 1));
if (req_available < n) {
if (try < 2) {
drv_usecwait(100);
try++;
continue;
} else {
return (NULL);
}
}
break;
}
/* We dont change anything until the entries are sumitted */
}
/*
* updates the req in ptr to fw. Assumes that req lock is held.
*/
void
{
ASSERT(n >= 1);
qlt->preq_ndx_to_fw += n;
}
/*
* - Should not be called from Interrupt.
* - A very hardware specific function. Does not touch driver state.
* - Assumes that interrupts are disabled or not there.
* - Expects that the caller makes sure that all activity has stopped
* and its ok now to go ahead and reset the chip. Also the caller
* takes care of post reset damage control.
* - called by initialize adapter() and dump_fw(for reset only).
* - During attach() nothing much is happening and during initialize_adapter()
* the function (caller) does all the housekeeping so that this function
* can execute in peace.
* - Returns 0 on success.
*/
static fct_status_t
{
int cntr;
/* XXX: Switch off LEDs */
/* Disable Interrupts */
/* Stop DMA */
/* Wait for DMA to be stopped */
cntr = 0;
cntr++;
/* 3 sec should be more than enough */
if (cntr == 300)
return (QLT_DMA_STUCK);
}
/* Reset the Chip */
qlt->qlt_link_up = 0;
drv_usecwait(100);
/* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */
cntr = 0;
cntr++;
/* 3 sec should be more than enough */
if (cntr == 300)
return (QLT_ROM_STUCK);
}
/* Disable Interrupts (Probably not needed) */
return (QLT_SUCCESS);
}
/*
* - Should not be called from Interrupt.
* - A very hardware specific function. Does not touch driver state.
* - Assumes that interrupts are disabled or not there.
* - Expects that the caller makes sure that all activity has stopped
* and its ok now to go ahead and reset the chip. Also the caller
* takes care of post reset damage control.
* - called by initialize adapter() and dump_fw(for reset only).
* - During attach() nothing much is happening and during initialize_adapter()
* the function (caller) does all the housekeeping so that this function
* can execute in peace.
* - Returns 0 on success.
*/
static fct_status_t
{
(void) qlt_reset_chip(qlt);
if (qlt->qlt_81xx_chip) {
}
/* Load the two segments */
if (ret == QLT_SUCCESS) {
}
} else if (qlt->qlt_81xx_chip) {
if (ret == QLT_SUCCESS) {
}
} else if (qlt->qlt_25xx_chip) {
if (ret == QLT_SUCCESS) {
}
} else {
if (ret == QLT_SUCCESS) {
}
}
if (ret != QLT_SUCCESS) {
return (ret);
}
/* Verify Checksum */
if (ret != QLT_SUCCESS) {
return (ret);
}
/* Execute firmware */
if (ret != QLT_SUCCESS) {
return (ret);
}
/* Get revisions (About Firmware) */
if (ret != QLT_SUCCESS) {
return (ret);
}
return (QLT_SUCCESS);
}
/*
* Used only from qlt_download_fw().
*/
static fct_status_t
{
uint32_t words_sent = 0;
while (words_sent < word_count) {
TOTAL_DMA_MEM_SIZE >> 2);
if (ret != QLT_SUCCESS) {
ret);
return (ret);
}
}
return (QLT_SUCCESS);
}
/*
* Not used during normal operation. Only during driver init.
* Assumes that interrupts are disabled and mailboxes are loaded.
* Just triggers the mailbox command an waits for the completion.
* Also expects that There is nothing else going on and we will only
* get back a mailbox completion from firmware.
* ---DOES NOT CLEAR INTERRUPT---
* Used only from the code path originating from
* qlt_reset_chip_and_download_fw()
*/
static fct_status_t
{
int cntr = 0;
cntr++;
if (cntr == 100) {
return (QLT_MAILBOX_STUCK);
}
}
if ((status == ROM_MBX_CMD_SUCCESSFUL) ||
(status == ROM_MBX_CMD_NOT_SUCCESSFUL) ||
(status == MBX_CMD_SUCCESSFUL) ||
(status == MBX_CMD_NOT_SUCCESSFUL)) {
if (mbox0 == QLT_MBX_CMD_SUCCESS) {
return (QLT_SUCCESS);
} else {
return (QLT_MBOX_FAILED | mbox0);
}
}
/* This is unexpected, dump a message */
return (QLT_UNEXPECTED_RESPONSE);
}
static mbox_cmd_t *
{
if (dma_size) {
return (NULL);
}
/* This is the most common initialization of dma ptrs */
}
return (mcp);
}
void
{
}
/*
* This can sleep. Should never be called from interrupt context.
*/
static fct_status_t
{
int retries;
int i;
char info[80];
ASSERT(0);
return (QLT_MBOX_FAILED);
}
/* See if mailboxes are still uninitialized */
return (QLT_MBOX_NOT_INITIALIZED);
}
/* Wait to grab the mailboxes */
retries++) {
if ((retries > 5) ||
return (QLT_MBOX_BUSY);
}
}
/* Make sure we always ask for mailbox 0 */
/* Load mailboxes, set state and generate RISC interrupt */
for (i = 0; i < MAX_MBOXES; i++) {
}
/* Wait for mailbox command completion */
+ drv_usectohz(MBOX_TIMEOUT)) < 0) {
info[79] = 0;
/*
* XXX Throw HBA fatal error event
*/
return (QLT_MBOX_TIMEOUT);
}
goto qlt_mbox_wait_loop;
/* Make sure its a completion */
return (QLT_MBOX_ABORTED);
}
/* MBox command completed. Clear state, retuen based on mbox 0 */
/* Mailboxes are already loaded by interrupt routine */
return (QLT_SUCCESS);
}
/*
* **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
*/
/* ARGSUSED */
static uint_t
{
int i;
int intr_loop_count;
char info[80];
/*
* Normally we will always get this lock. If tryenter is
* failing then it means that driver is trying to do
* some cleanup and is masking the intr but some intr
* has sneaked in between. See if our device has generated
* this intr. If so then wait a bit and return claimed.
* If not then return claimed if this is the 1st instance
* of a interrupt after driver has grabbed the lock.
*/
if (risc_status & BIT_15) {
drv_usecwait(10);
return (DDI_INTR_CLAIMED);
} else if (qlt->intr_sneak_counter) {
return (DDI_INTR_CLAIMED);
} else {
return (DDI_INTR_UNCLAIMED);
}
}
if (((risc_status & BIT_15) == 0) ||
(qlt->qlt_intr_enabled == 0)) {
/*
* This might be a pure coincedence that we are operating
* in a interrupt disabled mode and another device
* sharing the interrupt line has generated an interrupt
* while an interrupt from our device might be pending. Just
* ignore it and let the code handling the interrupt
* disabled mode handle it.
*/
return (DDI_INTR_UNCLAIMED);
}
/*
* XXX take care for MSI case. disable intrs
* Its gonna be complicated because of the max iterations.
* as hba will have posted the intr which did not go on PCI
* but we did not service it either because of max iterations.
* Maybe offload the intr on a different thread.
*/
intr_loop_count = 0;
/* check for risc pause */
if (risc_status & BIT_8) {
info[79] = 0;
}
/* First check for high performance path */
if (intr_type == 0x1D) {
} else if (intr_type == 0x1C) {
} else if (intr_type == 0x13) {
} else if (intr_type == 0x12) {
if (qlt->qlt_link_up) {
FCT_EVENT_LINK_RESET, 0, 0);
}
} else if (code == 0x8012) {
qlt->qlt_link_up = 0;
0, 0);
} else if (code == 0x8011) {
switch (mbox1) {
break;
break;
break;
break;
break;
default:
}
0, 0);
"Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
info[79] = 0;
} else if (code == 0x800F) {
"Got 800F, mb1=%x mb2=%x mb3=%x",
if (mbox1 != 1) {
/* issue "verify fw" */
}
} else if (code == 0x8101) {
"IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
info[79] = 0;
/* check if "ACK" is required (timeout != 0) */
if (mbox1 & 0x0f00) {
/*
* Ack the request (queue work to do it?)
* using a mailbox iocb
*/
if (req) {
} else {
"IDC ACK failed");
info[79] = 0;
}
}
}
/* Handle mailbox completion */
" when driver wasn't waiting for it %d",
} else {
for (i = 0; i < MAX_MBOXES; i++) {
(((uint32_t)1) << i)) {
}
}
}
} else {
}
if ((risc_status & BIT_15) &&
goto intr_again;
}
return (DDI_INTR_CLAIMED);
}
/* **************** NVRAM Functions ********************** */
{
/* Clear access error flag */
/* Wait for READ cycle to complete. */
break;
}
drv_usecwait(10);
}
if (timer == 0) {
return (QLT_FLASH_TIMEOUT);
return (QLT_FLASH_ACCESS_ERROR);
}
return (QLT_SUCCESS);
}
{
uint64_t empty_node_name = 0;
if (qlt->qlt_81xx_chip) {
} else if (qlt->qlt_25xx_chip) {
} else {
}
/* Pause RISC. */
/* Get NVRAM data and calculate checksum. */
chksum = 0;
if (ret != QLT_SUCCESS) {
return (ret);
}
ptr++;
}
/* Release RISC Pause */
/* Sanity check NVRAM Data */
return (QLT_BAD_NVRAM_DATA);
}
/* If node name is zero, hand craft it from port name */
}
return (QLT_SUCCESS);
}
{
} else {
}
return (total_ent);
}
void
{
return;
do {
break;
}
case 0x0d: /* INOT */
break;
case 0x06: /* ATIO */
break;
default:
break;
}
} while (total_ent > 0);
}
{
} else {
}
return (total_ent);
}
void
{
uint8_t c;
return;
do {
break;
}
case 0x12: /* CTIO completion */
break;
case 0x0e: /* NACK */
/* Do Nothing */
break;
case 0x1b: /* Verify FW */
break;
case 0x29: /* CT PassThrough */
break;
case 0x33: /* Abort IO IOCB completion */
break;
case 0x51: /* PUREX */
break;
case 0x52:
break;
case 0x53: /* ELS passthrough */
if (c == 0) {
} else if (c == 3) {
} else {
}
break;
case 0x54: /* ABTS received */
break;
case 0x55: /* ABTS completion */
break;
default:
break;
}
(RESPONSE_QUEUE_ENTRIES - 1);
} while (total_ent > 0);
}
{
uint16_t n;
uint16_t h;
uint8_t *p;
int found = 0;
return (STMF_ALLOC_FAILURE);
}
if (ret != QLT_SUCCESS) {
return (ret);
}
found = 1;
*ret_handle = h;
if ((cmd_handle != FCT_HANDLE_NONE) &&
(cmd_handle != h)) {
"with handle %x, while the portid was "
"already using a different handle %x",
id, cmd_handle, h);
return (QLT_FAILURE);
}
break;
}
"handle %x, while the handle was already in use "
return (QLT_FAILURE);
}
p += 8;
}
if (!found) {
*ret_handle = cmd_handle;
}
return (FCT_SUCCESS);
}
/* ARGSUSED */
{
uint8_t *p;
p[0] = ELS_OP_PLOGI;
p[7] = 3;
p[8] = 0x88;
p[10] = 8;
p[13] = 0xff; p[15] = 0x1f;
p[18] = 7; p[19] = 0xd0;
p[68] = 0x80;
p[74] = 8;
p[77] = 0xff;
p[81] = 1;
return (FCT_SUCCESS);
}
/* ARGSUSED */
{
return (FCT_SUCCESS);
}
{
uint16_t h;
case 0xFFFFFC: h = 0x7FC; break;
case 0xFFFFFD: h = 0x7FD; break;
case 0xFFFFFE: h = 0x7FE; break;
case 0xFFFFFF: h = 0x7FF; break;
default:
login->cmd_rp_handle, &h);
if (ret != FCT_SUCCESS) {
return (ret);
}
}
} else {
}
if (ret != FCT_SUCCESS) {
return (ret);
}
if (h == FCT_HANDLE_NONE)
return (FCT_SUCCESS);
return (FCT_SUCCESS);
}
return (FCT_SUCCESS);
return (FCT_FAILURE);
}
/* invoked in single thread */
{
return (FCT_SUCCESS);
return (FCT_BUSY);
}
/* QMEM_WR32(qlt, (&req[4]), 0xffffffff); */
} else {
}
qlt->rp_dereg_status = 0;
qlt->rp_id_in_dereg = 0;
return (ret);
}
/*
* Pass received ELS up to framework.
*/
static void
{
int i, off;
char info[160];
if (iocb_flags & BIT_15) {
} else {
}
goto cmd_null;
}
cmd_null:;
"allocate space for fct_cmd", (void *)qlt);
info[159] = 0;
return;
}
}
/* Take care of fw's swapping of payload */
pldptr += 4;
off += 4;
off = 4;
pldptr += 4;
}
}
fct_post_rcvd_cmd(cmd, 0);
}
{
char info[160];
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto fatal_panic;
} else {
}
}
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto fatal_panic;
} else {
}
}
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
cmd->cmd_handle = 0;
}
} else {
ASSERT(0);
return (FCT_FAILURE);
}
"FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd,
ioflags);
info[159] = 0;
return (FCT_FAILURE);
}
/* ARGSUSED */
{
} else {
}
/*
*/
} else {
cookie_count = 1;
rcnt = 1;
}
return (FCT_BUSY);
}
req[0] = 0x12;
/*
* See if the dma cookies are in simple array format.
*/
/*
* Program the first segment into main record.
*/
if (ckp) {
} else {
}
/*
* Program remaining segments into continuation records.
*/
while (cookie_resid) {
}
req[0] = 0x0a;
for (cont_segs = CONT_A64_DATA_SEGMENTS;
if (ckp) {
++ckp; /* next cookie */
ckp->dmac_laddress);
} else {
}
cookie_resid--;
}
/*
* zero unused remainder of IOCB
*/
if (cont_segs) {
}
}
} else {
/* Single, contiguous buffer */
}
return (STMF_SUCCESS);
}
/*
* We must construct proper FCP_RSP_IU now. Here we only focus on
* the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO),
* we could have catched them before we enter here.
*/
{
int use_mode2;
int ndx;
/*
* Enter fast channel for non check condition
*/
/*
* We will use mode1
*/
}
/*
* Fillout CTIO type 7 IOCB
*/
return (FCT_BUSY);
}
/*
* Common fields
*/
/*
* Mode-specific fields
*/
/*
* Trigger FW to send SCSI status out
*/
return (STMF_SUCCESS);
}
/*
* Decide the SCSI status mode, that should be used
*/
/*
* Prepare required information per the SCSI status mode
*/
if (use_mode2) {
if (!qcmd->dbuf_rsp_iu) {
return (FCT_ALLOC_FAILURE);
}
/*
* Start to construct FCP_RSP IU
*/
/*
* FCP_RSP IU flags, byte10
*/
}
/*
* SCSI status code, byte11
*/
/*
* FCP_RESID (Overrun or underrun)
*/
/*
* FCP_SNS_LEN
*/
0xFF);
0xFF);
/*
* FCP_RSP_LEN
*/
/*
* no FCP_RSP_INFO
*/
/*
* FCP_SNS_INFO
*/
/*
* Ensure dma data consistency
*/
} else {
}
if (task->task_sense_length) {
}
}
/*
* Fillout CTIO type 7 IOCB
*/
if (use_mode2) {
qcmd->dbuf_rsp_iu);
}
return (FCT_BUSY);
}
/*
* Common fields
*/
if (use_mode2) {
}
/*
* Mode-specific fields
*/
if (!use_mode2) {
}
if (use_mode2) {
} else {
/*
* Data in sense buf is always big-endian, data in IOCB
* should always be little-endian, so we must do swapping.
*/
}
}
/*
* Trigger FW to send SCSI status out
*/
return (STMF_SUCCESS);
}
{
return (FCT_BUSY);
} else {
}
}
return (FCT_BUSY);
}
}
return (FCT_SUCCESS);
}
{
int i;
return (FCT_BUSY);
}
else
if (terminate) {
}
req[0x23]++;
for (i = 0; i < 12; i += 4) {
/* Take care of firmware's LE requirement */
}
return (FCT_SUCCESS);
}
static void
{
int i;
uint32_t d;
/* Just put it on the request queue */
/* XXX handle this */
return;
}
for (i = 0; i < 16; i++) {
inot += 4;
req += 4;
}
req -= 64;
req[0] = 0x0e;
}
static void
{
char info[160];
/*
* If either bidirection xfer is requested of there is extended
* CDB, atio[0x20 + 11] will be greater than or equal to 3.
*/
cdb_size = 16;
if ((b & 3) == 3) {
"received, dropping the cmd as bidirectional "
/* XXX abort the I/O */
return;
}
/*
* Verify that we have enough entries. Without additional CDB
* Everything will fit nicely within the same 64 bytes. So the
* additional cdb size is essentially the # of additional bytes
* we need.
*/
" cdb (cdb size = %d bytes), however the firmware "
" did not DMAed the entire FCP_CMD IU, entry count "
/* XXX abort the I/O */
return;
}
}
if (fw_xchg_addr == 0xFFFFFFFF) {
} else {
}
}
/* Abort this IO */
"qlt_handle_atio: qlt-%p, can't "
"allocate space for scsi_task", (void *)qlt);
info[159] = 0;
return;
}
rportid));
return;
}
/* Dont do a 64 byte read as this is IOMMU */
q = atio+0x28;
/* XXX Handle fcp_cntl */
tm = *q++;
if (tm) {
else
}
*p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
*p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
*p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
*p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
if (cdb_size > 16) {
uint16_t i;
while (xtra) {
*p++ = *q++;
xtra--;
}
}
for (i = 0; i < 4; i++) {
cb[i] = *q++;
}
}
} else {
}
fct_post_rcvd_cmd(cmd, 0);
}
static void
{
" received when driver wasn't waiting for it",
return;
}
if (status != 0) {
subcode2);
} else {
}
} else {
}
}
/*
* Note that when an ELS is aborted, the regular or aborted completion
* (if any) gets posted before the abort IOCB comes back on response queue.
*/
static void
{
char info[160];
if (!CMD_HANDLE_VALID(hndl)) {
/*
* This cannot happen for unsol els completion. This can
* only happen when abort for an unsol els completes.
* This condition indicates a firmware bug.
*/
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
info[159] = 0;
return;
}
if (status == 5) {
/*
* When an unsolicited els is aborted, the abort is done
* by a ELSPT iocb with abort control. This is the aborted IOCB
* and not the abortee. We will do the cleanup when the
* IOCB which caused the abort, returns.
*/
stmf_trace(0, "--UNSOL ELS returned with status 5 --");
return;
}
/*
* Now why would this happen ???
*/
"qlt_handle_unsol_els_completion: can not "
(void *)rsp);
info[159] = 0;
return;
}
/*
* This is the same case as "if (status == 5)" above. The
* only difference is that in this case the firmware actually
* finished sending the response. So the abort attempt will
* come back with status ?. We will handle it there.
*/
stmf_trace(0, "--UNSOL ELS finished while we are trying to "
"abort it");
return;
}
}
if (status == 0) {
} else {
}
}
static void
{
char info[160];
if (!CMD_HANDLE_VALID(hndl)) {
/*
* Someone has requested to abort it, but no one is waiting for
* this completion.
*/
/*
* There could be exchange resource leakage, so
* throw HBA fatal error event now
*/
"qlt_handle_unsol_els_abort_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
info[159] = 0;
return;
}
return;
}
/*
* Why would this happen ??
*/
"qlt_handle_unsol_els_abort_completion: can not get "
(void *)rsp);
info[159] = 0;
return;
}
}
if (status == 0) {
} else if (status == 8) {
} else {
}
}
static void
{
char info[160];
if (!CMD_HANDLE_VALID(hndl)) {
/*
* This cannot happen for sol els completion.
*/
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
info[159] = 0;
return;
}
"qlt_handle_sol_els_completion: can not "
(void *)rsp);
info[159] = 0;
return;
}
/*
* We will handle it when the ABORT IO IOCB returns.
*/
return;
}
if (status == 0) {
}
}
if (status == 0) {
} else {
}
}
static void
{
char info[160];
if (!CMD_HANDLE_VALID(hndl)) {
/*
* Solicited commands will always have a valid handle.
*/
info[159] = 0;
return;
}
"qlt_handle_ct_completion: cannot find "
(void *)rsp);
info[159] = 0;
return;
}
/*
* We will handle it when ABORT IO IOCB returns;
*/
return;
}
if (status == 0) {
}
if (status == 0) {
} else {
}
}
static void
{
uint8_t n;
char info[160];
/* XXX: Check validity of the IOCB by checking 4th byte. */
n = rsp[2];
if (!CMD_HANDLE_VALID(hndl)) {
/*
* Someone has requested to abort it, but no one is waiting for
* this completion.
*/
(void *)rsp);
/*
* There could be exchange resource leakage, so
* throw HBA fatal error event now
*/
"qlt_handle_ctio_completion: hndl-"
info[159] = 0;
}
return;
}
abort_req = 1;
(void *)rsp);
} else {
abort_req = 0;
}
"qlt_handle_ctio_completion: cannot find "
(void *)rsp);
info[159] = 0;
return;
}
if (qcmd->dbuf_rsp_iu) {
}
if (abort_req) {
} else {
fc_st = FCT_SUCCESS;
}
}
} else {
} else {
}
}
/* A completion of data xfer */
if (n == 0) {
} else {
}
}
return;
}
if (!abort_req) {
/*
* This was just a pure status xfer.
*/
return;
}
}
static void
{
char info[80];
uint32_t h;
if (!CMD_HANDLE_VALID(h)) {
/*
* Solicited commands always have a valid handle.
*/
"qlt_handle_sol_abort_completion: hndl-"
info[79] = 0;
return;
}
/*
* What happened to the cmd ??
*/
"qlt_handle_sol_abort_completion: cannot "
"find cmd, hndl-%x, status-%x, rsp-%p", h, status,
(void *)rsp);
info[79] = 0;
return;
}
}
if (status == 0) {
} else if (status == 0x31) {
} else {
}
}
static void
{
char info[160];
sizeof (qlt_abts_cmd_t), 0);
"qlt_handle_rcvd_abts: qlt-%p, can't "
"allocate space for fct_cmd", (void *)qlt);
info[159] = 0;
return;
}
fct_post_rcvd_cmd(cmd, 0);
}
static void
{
char info[80];
return;
}
info[79] = 0;
}
#ifdef DEBUG
#endif
{
return (FCT_NOT_FOUND);
}
#ifdef DEBUG
if (qlt_drop_abort_counter > 0) {
return (FCT_SUCCESS);
}
#endif
}
if (flags & FCT_IOF_FORCE_FCA_DONE) {
cmd->cmd_handle = 0;
}
}
}
}
ASSERT(0);
return (FCT_FAILURE);
}
{
return (FCT_BUSY);
}
} else {
}
return (FCT_SUCCESS);
}
{
elsop);
}
return (FCT_BUSY);
}
} else {
}
return (FCT_SUCCESS);
}
{
return (FCT_BUSY);
}
return (FCT_SUCCESS);
}
{
}
ASSERT(0);
return (FCT_FAILURE);
}
{
return (FCT_BUSY);
}
els->els_req_size);
return (FCT_BUSY);
}
}
return (FCT_SUCCESS);
}
{
return (FCT_BUSY);
}
ct->ct_req_size);
return (FCT_BUSY);
}
return (FCT_SUCCESS);
}
/*
* All QLT_FIRMWARE_* will mainly be handled in this function
* It can not be called in interrupt context
*
* FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
* and qlt_ioctl_lock
*/
static fct_status_t
{
int i;
int retries, n;
char c = ' ';
/*
* To make sure that there's no outstanding dumping task
*/
return (FCT_FAILURE);
}
/*
* To make sure not to overwrite existing dump
*/
/*
* If we have alreay one dump, but it's not triggered by user
* and the user hasn't fetched it, we shouldn't dump again.
*/
return (FCT_FAILURE);
}
} else {
}
if (!qlt->qlt_fwdump_buf) {
/*
* It's the only place that we allocate buf for dumping. After
* it's allocated, we will use it until the port is detached.
*/
}
/*
* Start to dump firmware
*/
/*
* Print the ISP firmware revision number and attributes information
* Read the RISC to Host Status register
*/
"Attributes %04x\n\nR2H Status Register\n%08x",
/*
* Before pausing the RISC, make sure no mailbox can execute
*/
/*
* Wait to grab the mailboxes
*/
if (retries > 5) {
goto dump_fail;
}
}
}
/*
* Pause the RISC processor
*/
/*
* Wait for the RISC processor to pause
*/
for (i = 0; i < 200; i++) {
break;
}
drv_usecwait(1000);
}
if (i == 200) {
return (FCT_FAILURE);
}
goto over_25xx_specific_dump;
}
/*
* Capture data from 32 regsiters
*/
/*
* Disable interrupts
*/
/*
* Shadow registers
*/
addr = 0xb0000000;
for (i = 0; i < 0xb; i++) {
if ((!qlt->qlt_25xx_chip) &&
(!qlt->qlt_81xx_chip) &&
(i >= 7)) {
break;
}
if (i && ((i & 7) == 0)) {
}
addr += 0x100000;
}
}
/*
* Mailbox registers
*/
for (i = 0; i < 32; i += 2) {
if ((i + 2) & 15) {
c = ' ';
} else {
c = '\n';
}
}
/*
* Transfer sequence registers
*/
}
/*
* Receive sequence registers
*/
}
goto over_aseq_regs;
/*
* Auxiliary sequencer registers
*/
/*
* Command DMA registers
*/
/*
* Queues
*/
"\nRequest0 Queue DMA Channel registers\n");
"\n\nResponse0 Queue DMA Channel registers\n");
"\n\nRequest1 Queue DMA Channel registers\n");
/*
* Transmit DMA registers
*/
/*
* Receive DMA registers
*/
"\nRCV Thread 0 Data DMA registers\n");
"\nRCV Thread 1 Data DMA registers\n");
/*
* RISC registers
*/
/*
* Local memory controller registers
*/
}
/*
* Fibre protocol module regsiters
*/
if (qlt->qlt_81xx_chip) {
}
/*
* Fibre buffer registers
*/
if (qlt->qlt_81xx_chip) {
}
}
(void) qlt_reset_chip(qlt);
drv_usecwait(20);
qlt->intr_sneak_counter = 0;
/*
* Memory
*/
addr = 0x20000;
endaddr = 0x22000;
words_to_read = 0;
}
QLT_SUCCESS) {
"%llxh\n", ret);
goto dump_fail;
}
if (size_left < 100000) {
goto dump_ok;
}
addr += words_to_read;
}
addr = 0x100000;
endaddr++;
if (endaddr & 7) {
}
words_to_read = 0;
}
QLT_SUCCESS) {
"%llxh\n", ret);
goto dump_fail;
}
if (size_left < 100000) {
goto dump_ok;
}
addr += words_to_read;
}
/*
* Label the end tag
*/
/*
* Queue dumping
*/
/*
* Label dump reason
*/
qlt->qlt_ioctl_flags &=
return (FCT_SUCCESS);
return (FCT_FAILURE);
}
static int
{
int i;
int n;
char c = ' ';
for (i = 0, n = 0; i < count; i++) {
if ((i + 1) & 7) {
c = ' ';
} else {
c = '\n';
}
}
return (n);
}
static int
{
int i;
int n;
char c = ' ';
for (i = 0, n = 0; i < words; i++) {
if ((i & 7) == 0) {
}
if ((i + 1) & 7) {
c = ' ';
} else {
c = '\n';
}
"%08x%c", ptr[i], c));
}
return (n);
}
static int
{
int i;
int n;
char c = ' ';
int words;
uint16_t w;
for (i = 0, n = 0; i < words; i++) {
if ((i & 7) == 0) {
}
if ((i + 1) & 7) {
c = ' ';
} else {
c = '\n';
}
w, c));
}
return (n);
}
/*
* Only called by debug dump. Interrupts are disabled and mailboxes alongwith
* mailbox ram is available.
* Copy data from RISC RAM to system memory
*/
static fct_status_t
{
/* System destination address */
/* Length */
/* RISC source address */
if (ret == QLT_SUCCESS) {
} else {
}
return (ret);
}
static void
{
/* Just put it on the request queue */
/* XXX handle this */
return;
}
req[0] = 0x1b;
}
static void
{
char info[80];
if (status != 0) {
if (status == 3) {
"completion: error code:%x", error_code);
}
}
}
/*
* qlt_el_trace_desc_ctor - Construct an extended logging trace descriptor.
*
* Input: Pointer to the adapter state structure.
* Returns: Success or Failure.
* Context: Kernel context.
*/
static int
{
int rval = DDI_SUCCESS;
rval = DDI_FAILURE;
} else {
sizeof (qlt_el_trace_desc_t));
rval = DDI_FAILURE;
} else {
MUTEX_DRIVER, NULL);
}
}
return (rval);
}
/*
* qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
*
* Input: Pointer to the adapter state structure.
* Returns: Success or Failure.
* Context: Kernel context.
*/
static int
{
int rval = DDI_SUCCESS;
rval = DDI_FAILURE;
} else {
}
}
return (rval);
}
/*
* qlt_el_msg
* Extended logging message
*
* Input:
* qlt: adapter state pointer.
* fn: function name.
* ce: level
* ...: Variable argument list.
*
* Context:
*/
void
{
char fmt2[EL_BUFFER_RESERVE];
int tracing = 0;
/* Tracing is the default but it can be disabled. */
tracing = 1;
/*
* Ensure enough space for the string. Wrap to
* start when default message allocation size
* would overrun the end.
*/
} else {
}
}
/* if no buffer use the stack */
}
/*
* Calculate the offset where the next message will go,
* skipping the NULL.
*/
if (tracing) {
}
if (enable_extended_logging) {
}
}
/*
* qlt_dump_el_trace_buffer
* Outputs extended logging trace buffer.
*
* Input:
* qlt: adapter state pointer.
*/
void
{
char *dump_start = NULL;
char *dump_current = NULL;
char *trace_start;
char *trace_end;
int wrapped = 0;
int rval;
trace_end = trace_start +
(void *)dump_start, (void *)trace_start);
/* Show it... */
/* Make the next the current */
/* check for wrap */
wrapped = 1;
} else if (wrapped) {
/* Don't go past next. */
dump_current) {
break;
}
} else if (*dump_current == NULL) {
break;
}
}
}
}
/*
* qlt_validate_trace_desc
* Ensures the extended logging trace descriptor is good.
*
* Input:
* qlt: adapter state pointer.
*
* Returns:
* ql local function return status code.
*/
static int
{
int rval = DDI_SUCCESS;
rval = DDI_FAILURE;
rval = DDI_FAILURE;
}
return (rval);
}
/*
* qlt_find_trace_start
* Locate the oldest extended logging trace entry.
*
* Input:
* qlt: adapter state pointer.
*
* Returns:
* Pointer to a string.
*
* Context:
*/
static char *
{
char *trace_start = 0;
char *trace_next = 0;
/*
* If the buffer has not wrapped next will point at a null so
* start is the beginning of the buffer. If next points at a char
* then we must traverse the buffer until a null is detected and
* that will be the beginning of the oldest whole object in the buffer
* which is the start.
*/
if ((trace_next + EL_BUFFER_RESERVE) >=
} else if (*trace_next != NULL) {
} else {
}
return (trace_start);
}
static int
{
}
static int
{
}
static int
{
char inst_prop[256];
int val;
/*
* Get adapter instance specific parameters. If the instance
* specific parameter isn't there, try the global parameter.
*/
}
return (val);
}
static int
{
char instance_prop[256];
/* Get adapter instance specific parameter. */
}
static int
{
}
static boolean_t
{
char *prop_val = 0;
int rval;
int radix;
radix = 16;
if (rval == DDI_PROP_SUCCESS) {
}
if (rval == DDI_PROP_SUCCESS) {
&prop_val);
if (rval == DDI_PROP_SUCCESS) {
&wwpn);
}
}
if (rval == DDI_PROP_SUCCESS) {
overloaded = TRUE;
}
return (overloaded);
}
/*
* prop_text - Return a pointer to a string describing the status
*
* Input: prop_status = the return status from a property function.
* Returns: pointer to a string.
* Context: Kernel context.
*/
char *
prop_text(int prop_status)
{
}
/*
* value2string Return a pointer to a string associated with the value
*
* Input: entry = the value to string table
* value = the value
* Returns: pointer to a string.
* Context: Kernel context.
*/
char *
{
break;
}
}
}
/*
* qlt_chg_endian Change endianess of byte array.
*
* Input: buf = array pointer.
* size = size of array in bytes.
*
* Context: Interrupt or Kernel context.
*/
void
{
cnt1--;
}
}
/*
* ql_mps_reset
* Reset MPS for FCoE functions.
*
* Input:
* ha = virtual adapter state pointer.
*
* Context:
* Kernel context.
*/
static void
{
do {
QLT_SUCCESS) {
return;
}
QLT_SUCCESS) {
return;
}
data &= 0xff1f;
}
}
}
/*
* qlt_raw_wrt_risc_ram_word
* Write RISC RAM word.
*
* Input: qlt: adapter state pointer.
* risc_address: risc ram word address.
* data: data.
*
* Returns: qlt local function return status code.
*
* Context: Kernel context.
*/
static fct_status_t
{
if (ret != QLT_SUCCESS) {
"=%llxh\n", ret);
}
return (ret);
}
/*
* ql_raw_rd_risc_ram_word
* Read RISC RAM word.
*
* Input: qlt: adapter state pointer.
* risc_address: risc ram word address.
* data: data pointer.
*
* Returns: ql local function return status code.
*
* Context: Kernel context.
*/
static fct_status_t
{
if (ret != QLT_SUCCESS) {
"=%llxh\n", ret);
}
return (ret);
}
static void
{
}
defval) {
}
defval) {
}
defval) {
}
defval) {
}
defval) {
}
}