* General Public License for more details.
*
******************************************************************************/
-#define QLA1280_VERSION "3.24.4"
+#define QLA1280_VERSION "3.25"
/*****************************************************************************
Revision History:
+ Rev 3.25, September 28, 2004, Christoph Hellwig
+ - add support for ISP1020/1040
+ - don't include "scsi.h" anymore for 2.6.x
Rev 3.24.4 June 7, 2004 Christoph Hellwig
- restructure firmware loading, cleanup initialization code
- prepare support for ISP1020/1040 chips
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#include "scsi.h"
#else
#include <linux/blk.h>
#include "scsi.h"
#include "sd.h"
#endif
+#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
+#include <asm/sn/io.h>
+#endif
+
#if LINUX_VERSION_CODE < 0x020407
#error "Kernels older than 2.4.7 are no longer supported"
#endif
#include "qla1280.h"
#include "ql12160_fw.h" /* ISP RISC codes */
#include "ql1280_fw.h"
+#include "ql1040_fw.h"
/*
#define QLA_64BIT_PTR 1
#endif
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
-#include <asm/sn/pci/pciio.h>
-/* Ugly hack needed for the virtual channel fix on SN2 */
-extern int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
- int *count_vchan0, int *count_vchan1);
-#endif
-
#ifdef QLA_64BIT_PTR
#define pci_dma_hi32(a) ((a >> 16) >> 16)
#else
struct list_head *);
static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t);
static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t);
-static uint16_t qla1280_debounce_register(volatile uint16_t *);
+static uint16_t qla1280_debounce_register(volatile uint16_t __iomem *);
static request_t *qla1280_req_pkt(struct scsi_qla_host *);
static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *,
unsigned int);
static int qla1280_set_target_parameters(struct scsi_qla_host *, int, int);
-static struct qla_driver_setup driver_setup __initdata;
+static struct qla_driver_setup driver_setup;
/*
* convert scsi data direction to request_t control flags
static char *qla1280;
/* insmod qla1280 options=verbose" */
-MODULE_PARM(qla1280, "s");
+module_param(qla1280, charp, 0);
#else
__setup("qla1280=", qla1280_setup);
#endif
unsigned char *fwver; /* Ptr to F/W version array */
};
-/* NOTE: qla1280_pci_tbl and ql1280_board_tbl must be in the same order */
+/* NOTE: the last argument in each entry is used to index ql1280_board_tbl */
static struct pci_device_id qla1280_pci_tbl[] = {
{PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP12160,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080,
+#ifdef CONFIG_SCSI_QLOGIC_1280_1040
+ {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240,
+#endif
+ {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280,
+ {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160,
+ {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+ {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
{0,}
};
MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
/* Name , Number of ports, FW details */
{"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01,
&fw12160i_addr01, &fw12160i_version_str[0]},
+ {"QLA1040", 1, &risc_code01[0], &risc_code_length01,
+ &risc_code_addr01, &firmware_version[0]},
{"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01,
static void qla1280_mailbox_timeout(unsigned long __data)
{
struct scsi_qla_host *ha = (struct scsi_qla_host *)__data;
- struct device_reg *reg;
+ struct device_reg __iomem *reg;
reg = ha->iobase;
ha->mailbox_out[0] = RD_REG_WORD(®->mailbox0);
qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct scsi_qla_host *ha;
- struct device_reg *reg;
+ struct device_reg __iomem *reg;
u16 data;
int handled = 0;
static inline void
qla1280_enable_intrs(struct scsi_qla_host *ha)
{
- struct device_reg *reg;
+ struct device_reg __iomem *reg;
reg = ha->iobase;
/* enable risc and host interrupts */
static inline void
qla1280_disable_intrs(struct scsi_qla_host *ha)
{
- struct device_reg *reg;
+ struct device_reg __iomem *reg;
reg = ha->iobase;
/* disable risc and host interrupts */
static int __devinit
qla1280_initialize_adapter(struct scsi_qla_host *ha)
{
- struct device_reg *reg;
+ struct device_reg __iomem *reg;
int status;
int bus;
#if LINUX_VERSION_CODE > 0x020500
ha->flags.ints_enabled = 0;
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ia64_platform_is("sn2")) {
- int count1, count2;
- int c;
-
- count1 = 3;
- count2 = 3;
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
"dual channel lockup workaround\n", ha->host_no);
- if ((c = snia_pcibr_rrb_alloc(ha->pdev, &count1, &count2)) < 0)
- printk(KERN_ERR "scsi(%li): Unable to allocate SN2 "
- "virtual DMA channels\n", ha->host_no);
- else
- ha->flags.use_pci_vchannel = 1;
-
+ ha->flags.use_pci_vchannel = 1;
driver_setup.no_nvram = 1;
}
#endif
+ /* TODO: implement support for the 1040 nvram format */
+ if (IS_ISP1040(ha))
+ driver_setup.no_nvram = 1;
+
dprintk(1, "Configure PCI space for adapter...\n");
reg = ha->iobase;
qla1280_chip_diag(struct scsi_qla_host *ha)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
int status = 0;
int cnt;
uint16_t data;
#if 1 /* Some SCSI Processors do not seem to like this */
nv->bus[bus].target[target].parameter.f.enable_wide = 1;
#endif
- if (!IS_ISP1040(ha))
- nv->bus[bus].target[target].parameter.f.parity_checking = 1;
-
+ nv->bus[bus].target[target].parameter.f.parity_checking = 1;
nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
nv->bus[bus].target[target].execution_throttle =
nv->bus[bus].max_queue_depth - 1;
static int
qla1280_nvram_config(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
struct nvram *nv = &ha->nvram;
int bus, target, status = 0;
uint16_t mb[MAILBOX_REGISTER_COUNT];
static uint16_t
qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
int cnt;
uint16_t data = 0;
uint16_t reg_data;
static void
qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
WRT_REG_WORD(®->nvram, data | NV_SELECT);
RD_REG_WORD(®->id_l); /* Flush PCI write */
static int
qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
#if 0
LIST_HEAD(done_q);
#endif
int status = 0;
int cnt;
uint16_t *optr, *iptr;
+ uint16_t __iomem *mptr;
uint16_t data;
DECLARE_COMPLETION(wait);
struct timer_list timer;
* available before starting sending the command data
*/
/* Load mailbox registers. */
- optr = (uint16_t *) ®->mailbox0;
+ mptr = (uint16_t __iomem *) ®->mailbox0;
iptr = mb;
for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) {
if (mr & BIT_0) {
- WRT_REG_WORD(optr, (*iptr));
+ WRT_REG_WORD(mptr, (*iptr));
}
mr >>= 1;
- optr++;
+ mptr++;
iptr++;
}
static void
qla1280_poll(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
uint16_t data;
LIST_HEAD(done_q);
static void
qla1280_reset_adapter(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
ENTER("qla1280_reset_adapter");
static int
qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
struct scsi_cmnd *cmd = sp->cmd;
cmd_a64_entry_t *pkt;
struct scatterlist *sg = NULL;
dma_handle = sg_dma_address(sg);
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
- sn_pci_set_vchan(ha->pdev, &dma_handle,
+ sn_pci_set_vchan(ha->pdev,
+ (unsigned long *)&dma_handle,
SCSI_BUS_32(cmd));
#endif
*dword_ptr++ =
dma_handle = sg_dma_address(sg);
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
- sn_pci_set_vchan(ha->pdev, &dma_handle,
+ sn_pci_set_vchan(ha->pdev,
+ (unsigned long *)&dma_handle,
SCSI_BUS_32(cmd));
#endif
*dword_ptr++ =
sp->saved_dma_handle = dma_handle;
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
- sn_pci_set_vchan(ha->pdev, &dma_handle,
+ sn_pci_set_vchan(ha->pdev,
+ (unsigned long *)&dma_handle,
SCSI_BUS_32(cmd));
#endif
*dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle));
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(®->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
static int
qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
struct scsi_cmnd *cmd = sp->cmd;
struct cmd_entry *pkt;
struct scatterlist *sg = NULL;
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(®->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
static request_t *
qla1280_req_pkt(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
request_t *pkt = NULL;
int cnt;
uint32_t timer;
static void
qla1280_isp_cmd(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
ENTER("qla1280_isp_cmd");
} else
ha->request_ring_ptr++;
- /* Set chip new ring index. */
+ /*
+ * Update request index to mailbox4 (Request Queue In).
+ * The mmiowb() ensures that this write is ordered with writes by other
+ * CPUs. Without the mmiowb(), it is possible for the following:
+ * CPUA posts write of index 5 to mailbox4
+ * CPUA releases host lock
+ * CPUB acquires host lock
+ * CPUB posts write of index 6 to mailbox4
+ * On PCI bus, order reverses and write of 6 posts, then index 5,
+ * causing chip to issue full queue of stale commands
+ * The mmiowb() prevents future writes from crossing the barrier.
+ * See Documentation/DocBook/deviceiobook.tmpl for more information.
+ */
WRT_REG_WORD(®->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */
+ mmiowb();
LEAVE("qla1280_isp_cmd");
}
static void
qla1280_isr(struct scsi_qla_host *ha, struct list_head *done_q)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
struct response *pkt;
struct srb *sp = NULL;
uint16_t mailbox[MAILBOX_REGISTER_COUNT];
static int
qla1280_abort_isp(struct scsi_qla_host *ha)
{
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
struct srb *sp;
int status = 0;
int cnt;
* register value.
*/
static u16
-qla1280_debounce_register(volatile u16 * addr)
+qla1280_debounce_register(volatile u16 __iomem * addr)
{
volatile u16 ret;
volatile u16 ret2;
qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus)
{
uint16_t config_reg, scsi_control;
- struct device_reg *reg = ha->iobase;
+ struct device_reg __iomem *reg = ha->iobase;
if (ha->bus_settings[bus].scsi_bus_dead) {
WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC);
#if LINUX_VERSION_CODE >= 0x020600
static struct scsi_host_template qla1280_driver_template = {
+ .module = THIS_MODULE,
.proc_name = "qla1280",
.name = "Qlogic ISP 1280/12160",
.info = qla1280_info,
}
host->base = (unsigned long)ha->mmpbase;
- ha->iobase = (struct device_reg *)ha->mmpbase;
+ ha->iobase = (struct device_reg __iomem *)ha->mmpbase;
#else
host->io_port = pci_resource_start(ha->pdev, 0);
if (!request_region(host->io_port, 0xff, "qla1280")) {