Commit afaf5a2d authored by David Somayajulu's avatar David Somayajulu Committed by James Bottomley
Browse files

[SCSI] Initial Commit of qla4xxx



open-iSCSI driver for Qlogic Corporation's iSCSI HBAs
Signed-off-by: default avatarRavi Anand <ravi.anand@qlogic.com>
Signed-off-by: default avatarDavid Somayajulu <david.somayajulu@qlogic.com>
Signed-off-by: default avatarDoug Maxey <dwm@bubba.enoyolf.org>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent ed542bed
......@@ -1244,6 +1244,7 @@ config SCSI_QLOGICPTI
module will be called qlogicpti.
source "drivers/scsi/qla2xxx/Kconfig"
source "drivers/scsi/qla4xxx/Kconfig"
config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
......
......@@ -84,6 +84,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx/
obj-$(CONFIG_SCSI_LPFC) += lpfc/
obj-$(CONFIG_SCSI_PAS16) += pas16.o
obj-$(CONFIG_SCSI_SEAGATE) += seagate.o
......
config SCSI_QLA_ISCSI
tristate "QLogic ISP4XXX host adapter family support"
depends on PCI && SCSI
select SCSI_ISCSI_ATTRS
---help---
This driver supports the QLogic 40xx (ISP4XXX) iSCSI host
adapter family.
qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
ql4_nvram.o ql4_dbg.o
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2006 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
#include <scsi/scsi_dbg.h>
static void qla4xxx_print_srb_info(struct srb * srb)
{
printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
__func__, srb->cmd, (unsigned long) srb->dma_handle);
printk("%s: fw_ddb_index = %d, lun = %d\n",
__func__, srb->fw_ddb_index, srb->cmd->device->lun);
printk("%s: iocb_tov = %d\n",
__func__, srb->iocb_tov);
printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
__func__, srb->cc_stat, srb->r_start, srb->u_start);
}
void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
{
printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
printk(" b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
cmd->device->channel, cmd->device->id, cmd->device->lun,
cmd->cmd_len);
scsi_print_command(cmd);
printk(" seg_cnt = %d\n", cmd->use_sg);
printk(" request buffer = 0x%p, request buffer len = 0x%x\n",
cmd->request_buffer, cmd->request_bufflen);
if (cmd->use_sg) {
struct scatterlist *sg;
sg = (struct scatterlist *)cmd->request_buffer;
printk(" SG buffer: \n");
qla4xxx_dump_buffer((caddr_t) sg,
(cmd->use_sg * sizeof(*sg)));
}
printk(" tag = %d, transfersize = 0x%x \n", cmd->tag,
cmd->transfersize);
printk(" Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
cmd->sc_data_direction);
printk(" Current time (jiffies) = 0x%lx, "
"timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
}
void __dump_registers(struct scsi_qla_host *ha)
{
uint8_t i;
for (i = 0; i < MBOX_REG_COUNT; i++) {
printk(KERN_INFO "0x%02X mailbox[%d] = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
readw(&ha->reg->mailbox[i]));
}
printk(KERN_INFO "0x%02X flash_address = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, flash_address),
readw(&ha->reg->flash_address));
printk(KERN_INFO "0x%02X flash_data = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, flash_data),
readw(&ha->reg->flash_data));
printk(KERN_INFO "0x%02X ctrl_status = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, ctrl_status),
readw(&ha->reg->ctrl_status));
if (is_qla4010(ha)) {
printk(KERN_INFO "0x%02X nvram = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
readw(&ha->reg->u1.isp4010.nvram));
}
else if (is_qla4022(ha)) {
printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u1.isp4022.intr_mask),
readw(&ha->reg->u1.isp4022.intr_mask));
printk(KERN_INFO "0x%02X nvram = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
readw(&ha->reg->u1.isp4022.nvram));
printk(KERN_INFO "0x%02X semaphore = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u1.isp4022.semaphore),
readw(&ha->reg->u1.isp4022.semaphore));
}
printk(KERN_INFO "0x%02X req_q_in = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, req_q_in),
readw(&ha->reg->req_q_in));
printk(KERN_INFO "0x%02X rsp_q_out = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, rsp_q_out),
readw(&ha->reg->rsp_q_out));
if (is_qla4010(ha)) {
printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4010.ext_hw_conf),
readw(&ha->reg->u2.isp4010.ext_hw_conf));
printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4010.port_ctrl),
readw(&ha->reg->u2.isp4010.port_ctrl));
printk(KERN_INFO "0x%02X port_status = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4010.port_status),
readw(&ha->reg->u2.isp4010.port_status));
printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4010.req_q_out),
readw(&ha->reg->u2.isp4010.req_q_out));
printk(KERN_INFO "0x%02X gp_out = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
readw(&ha->reg->u2.isp4010.gp_out));
printk(KERN_INFO "0x%02X gp_in = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
readw(&ha->reg->u2.isp4010.gp_in));
printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4010.port_err_status),
readw(&ha->reg->u2.isp4010.port_err_status));
}
else if (is_qla4022(ha)) {
printk(KERN_INFO "Page 0 Registers:\n");
printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p0.ext_hw_conf),
readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p0.port_ctrl),
readw(&ha->reg->u2.isp4022.p0.port_ctrl));
printk(KERN_INFO "0x%02X port_status = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p0.port_status),
readw(&ha->reg->u2.isp4022.p0.port_status));
printk(KERN_INFO "0x%02X gp_out = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p0.gp_out),
readw(&ha->reg->u2.isp4022.p0.gp_out));
printk(KERN_INFO "0x%02X gp_in = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
readw(&ha->reg->u2.isp4022.p0.gp_in));
printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p0.port_err_status),
readw(&ha->reg->u2.isp4022.p0.port_err_status));
printk(KERN_INFO "Page 1 Registers:\n");
writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
&ha->reg->ctrl_status);
printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n",
(uint8_t) offsetof(struct isp_reg,
u2.isp4022.p1.req_q_out),
readw(&ha->reg->u2.isp4022.p1.req_q_out));
writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
&ha->reg->ctrl_status);
}
}
void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
{
unsigned long flags = 0;
int i = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
for (i = 1; i < MBOX_REG_COUNT; i++)
printk(KERN_INFO " Mailbox[%d] = %08x\n", i,
readw(&ha->reg->mailbox[i]));
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
void qla4xxx_dump_registers(struct scsi_qla_host *ha)
{
unsigned long flags = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
__dump_registers(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
void qla4xxx_dump_buffer(void *b, uint32_t size)
{
uint32_t cnt;
uint8_t *c = b;
printk(" 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh "
"Fh\n");
printk("------------------------------------------------------------"
"--\n");
for (cnt = 0; cnt < size; cnt++, c++) {
printk(KERN_DEBUG "%02x", *c);
if (!(cnt % 16))
printk(KERN_DEBUG "\n");
else
printk(KERN_DEBUG " ");
}
if (cnt % 16)
printk(KERN_DEBUG "\n");
}
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2006 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
/*
* Driver debug definitions.
*/
/* #define QL_DEBUG */ /* DEBUG messages */
/* #define QL_DEBUG_LEVEL_3 */ /* Output function tracing */
/* #define QL_DEBUG_LEVEL_4 */
/* #define QL_DEBUG_LEVEL_5 */
/* #define QL_DEBUG_LEVEL_9 */
#define QL_DEBUG_LEVEL_2 /* ALways enable error messagess */
#if defined(QL_DEBUG)
#define DEBUG(x) do {x;} while (0);
#else
#define DEBUG(x) do {} while (0);
#endif
#if defined(QL_DEBUG_LEVEL_2)
#define DEBUG2(x) do {if(extended_error_logging == 2) x;} while (0);
#define DEBUG2_3(x) do {x;} while (0);
#else /* */
#define DEBUG2(x) do {} while (0);
#endif /* */
#if defined(QL_DEBUG_LEVEL_3)
#define DEBUG3(x) do {if(extended_error_logging == 3) x;} while (0);
#else /* */
#define DEBUG3(x) do {} while (0);
#if !defined(QL_DEBUG_LEVEL_2)
#define DEBUG2_3(x) do {} while (0);
#endif /* */
#endif /* */
#if defined(QL_DEBUG_LEVEL_4)
#define DEBUG4(x) do {x;} while (0);
#else /* */
#define DEBUG4(x) do {} while (0);
#endif /* */
#if defined(QL_DEBUG_LEVEL_5)
#define DEBUG5(x) do {x;} while (0);
#else /* */
#define DEBUG5(x) do {} while (0);
#endif /* */
#if defined(QL_DEBUG_LEVEL_9)
#define DEBUG9(x) do {x;} while (0);
#else /* */
#define DEBUG9(x) do {} while (0);
#endif /* */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2006 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QL4_DEF_H
#define __QL4_DEF_H
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/dmapool.h>
#include <linux/mempool.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_iscsi.h>
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
#define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4022
#define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022
#endif /* */
#define QLA_SUCCESS 0
#define QLA_ERROR 1
/*
* Data bit definitions
*/
#define BIT_0 0x1
#define BIT_1 0x2
#define BIT_2 0x4
#define BIT_3 0x8
#define BIT_4 0x10
#define BIT_5 0x20
#define BIT_6 0x40
#define BIT_7 0x80
#define BIT_8 0x100
#define BIT_9 0x200
#define BIT_10 0x400
#define BIT_11 0x800
#define BIT_12 0x1000
#define BIT_13 0x2000
#define BIT_14 0x4000
#define BIT_15 0x8000
#define BIT_16 0x10000
#define BIT_17 0x20000
#define BIT_18 0x40000
#define BIT_19 0x80000
#define BIT_20 0x100000
#define BIT_21 0x200000
#define BIT_22 0x400000
#define BIT_23 0x800000
#define BIT_24 0x1000000
#define BIT_25 0x2000000
#define BIT_26 0x4000000
#define BIT_27 0x8000000
#define BIT_28 0x10000000
#define BIT_29 0x20000000
#define BIT_30 0x40000000
#define BIT_31 0x80000000
/*
* Host adapter default definitions
***********************************/
#define MAX_HBAS 16
#define MAX_BUSES 1
#define MAX_TARGETS (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES)
#define MAX_LUNS 0xffff
#define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */
#define MAX_DDB_ENTRIES (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES)
#define MAX_PDU_ENTRIES 32
#define INVALID_ENTRY 0xFFFF
#define MAX_CMDS_TO_RISC 1024
#define MAX_SRBS MAX_CMDS_TO_RISC
#define MBOX_AEN_REG_COUNT 5
#define MAX_INIT_RETRIES 5
#define IOCB_HIWAT_CUSHION 16
/*
* Buffer sizes
*/
#define REQUEST_QUEUE_DEPTH MAX_CMDS_TO_RISC
#define RESPONSE_QUEUE_DEPTH 64
#define QUEUE_SIZE 64
#define DMA_BUFFER_SIZE 512
/*
* Misc
*/
#define MAC_ADDR_LEN 6 /* in bytes */
#define IP_ADDR_LEN 4 /* in bytes */
#define DRIVER_NAME "qla4xxx"
#define MAX_LINKED_CMDS_PER_LUN 3
#define MAX_REQS_SERVICED_PER_INTR 16
#define ISCSI_IPADDR_SIZE 4 /* IP address size */
#define ISCSI_ALIAS_SIZE 32 /* ISCSI Alais name size */
#define ISCSI_NAME_SIZE 255 /* ISCSI Name size -
* usually a string */
#define LSDW(x) ((u32)((u64)(x)))
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
/*
* Retry & Timeout Values
*/
#define MBOX_TOV 60
#define SOFT_RESET_TOV 30
#define RESET_INTR_TOV 3
#define SEMAPHORE_TOV 10
#define ADAPTER_INIT_TOV 120
#define ADAPTER_RESET_TOV 180
#define EXTEND_CMD_TOV 60
#define WAIT_CMD_TOV 30
#define EH_WAIT_CMD_TOV 120
#define FIRMWARE_UP_TOV 60
#define RESET_FIRMWARE_TOV 30
#define LOGOUT_TOV 10
#define IOCB_TOV_MARGIN 10
#define RELOGIN_TOV 18
#define ISNS_DEREG_TOV 5
#define MAX_RESET_HA_RETRIES 2
/*
* SCSI Request Block structure (srb) that is placed
* on cmd->SCp location of every I/O [We have 22 bytes available]
*/
struct srb {
struct list_head list; /* (8) */
struct scsi_qla_host *ha; /* HA the SP is queued on */
struct ddb_entry *ddb;
uint16_t flags; /* (1) Status flags. */
#define SRB_DMA_VALID BIT_3 /* DMA Buffer mapped. */
#define SRB_GOT_SENSE BIT_4 /* sense data recieved. */
uint8_t state; /* (1) Status flags. */
#define SRB_NO_QUEUE_STATE 0 /* Request is in between states */
#define SRB_FREE_STATE 1
#define SRB_ACTIVE_STATE 3
#define SRB_ACTIVE_TIMEOUT_STATE 4
#define SRB_SUSPENDED_STATE 7 /* Request in suspended state */
struct scsi_cmnd *cmd; /* (4) SCSI command block */
dma_addr_t dma_handle; /* (4) for unmap of single transfers */
atomic_t ref_count; /* reference count for this srb */
uint32_t fw_ddb_index;
uint8_t err_id; /* error id */
#define SRB_ERR_PORT 1 /* Request failed because "port down" */
#define SRB_ERR_LOOP 2 /* Request failed because "loop down" */
#define SRB_ERR_DEVICE 3 /* Request failed because "device error" */
#define SRB_ERR_OTHER 4
uint16_t reserved;
uint16_t iocb_tov;
uint16_t iocb_cnt; /* Number of used iocbs */
uint16_t cc_stat;
u_long r_start; /* Time we recieve a cmd from OS */
u_long u_start; /* Time when we handed the cmd to F/W */
};
/*
* Device Database (DDB) structure
*/
struct ddb_entry {
struct list_head list; /* ddb list */
struct scsi_qla_host *ha;
struct iscsi_cls_session *sess;
struct iscsi_cls_conn *conn;
atomic_t state; /* DDB State */
unsigned long flags; /* DDB Flags */
unsigned long dev_scan_wait_to_start_relogin;
unsigned long dev_scan_wait_to_complete_relogin;
uint16_t os_target_id; /* Target ID */
uint16_t fw_ddb_index; /* DDB firmware index */
uint8_t reserved[2];
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
uint32_t CmdSn;
uint16_t target_session_id;
uint16_t connection_id;
uint16_t exe_throttle; /* Max mumber of cmds outstanding
* simultaneously */
uint16_t task_mgmt_timeout; /* Min time for task mgmt cmds to
* complete */
uint16_t default_relogin_timeout; /* Max time to wait for
* relogin to complete */
uint16_t tcp_source_port_num;
uint32_t default_time2wait; /* Default Min time between
* relogins (+aens) */
atomic_t port_down_timer; /* Device connection timer */
atomic_t retry_relogin_timer; /* Min Time between relogins
* (4000 only) */
atomic_t relogin_timer; /* Max Time to wait for relogin to complete */
atomic_t relogin_retry_count; /* Num of times relogin has been
* retried */
uint16_t port;
uint32_t tpgt;
uint8_t ip_addr[ISCSI_IPADDR_SIZE];
uint8_t iscsi_name[ISCSI_NAME_SIZE]; /* 72 x48 */
uint8_t iscsi_alias[0x20];
};
/*
* DDB states.
*/
#define DDB_STATE_DEAD 0 /* We can no longer talk to
* this device */
#define DDB_STATE_ONLINE 1 /* Device ready to accept
* commands */
#define DDB_STATE_MISSING 2 /* Device logged off, trying
* to re-login */
/*
* DDB flags.
*/
#define DF_RELOGIN 0 /* Relogin to device */
#define DF_NO_RELOGIN 1 /* Do not relogin if IOCTL
* logged it out */
#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
#define DF_FO_MASKED 3
/*
* Asynchronous Event Queue structure
*/
struct aen {
uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
};
#include "ql4_fw.h"
#include "ql4_nvram.h"
/*
* Linux Host Adapter structure
*/
struct scsi_qla_host {
/* Linux adapter configuration data */
struct Scsi_Host *host; /* pointer to host data */
uint32_t tot_ddbs;
unsigned long flags;
#define AF_ONLINE 0 /* 0x00000001 */
#define AF_INIT_DONE 1 /* 0x00000002 */
#define AF_MBOX_COMMAND 2 /* 0x00000004 */
#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */
#define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */
#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */
#define AF_LINK_UP 8 /* 0x00000100 */
#define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
#define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */
#define AF_ISNS_CMD_DONE 13 /* 0x00002000 */
unsigned long dpc_flags;
#define DPC_RESET_HA 1 /* 0x00000002 */
#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */
#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */
#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */
#define DPC_RESET_HA_INTR 5 /* 0x00000020 */
#define DPC_ISNS_RESTART 7 /* 0x00000080 */
#define DPC_AEN 9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
uint16_t iocb_cnt;
uint16_t iocb_hiwat;
/* SRB cache. */
#define SRB_MIN_REQ 128
mempool_t *srb_mempool;
/* pci information */
struct pci_dev *pdev;
struct isp_reg __iomem *reg; /* Base I/O address */
unsigned long pio_address;
unsigned long pio_length;
#define MIN_IOBASE_LEN 0x100
uint16_t req_q_count;
uint8_t marker_needed;
uint8_t rsvd1;
unsigned long host_no;
/* NVRAM registers */
struct eeprom_data *nvram;
spinlock_t hardware_lock ____cacheline_aligned;
spinlock_t list_lock;
uint32_t eeprom_cmd_data;
/* Counters for general statistics */
uint64_t adapter_error_count;
uint64_t device_error_count;
uint64_t total_io_count;
uint64_t total_mbytes_xferred;
uint64_t link_failure_count;
uint64_t invalid_crc_count;
uint32_t spurious_int_count;
uint32_t aborted_io_count;
uint32_t io_timeout_count;
uint32_t mailbox_timeout_count;
uint32_t seconds_since_last_intr;