patch-2.2.13 linux/drivers/scsi/qlogicisp.c
Next file: linux/drivers/scsi/qlogicpti.c
Previous file: linux/drivers/scsi/qlogicfc_asm.c
Back to the patch index
Back to the overall index
- Lines: 444
- Date:
Tue Oct 19 17:14:01 1999
- Orig file:
v2.2.12/linux/drivers/scsi/qlogicisp.c
- Orig date:
Mon Aug 9 16:05:57 1999
diff -u --recursive --new-file v2.2.12/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
@@ -126,11 +126,30 @@
#define PCI_ID_LOW 0x00 /* vendor id */
#define PCI_ID_HIGH 0x02 /* device id */
#define ISP_CFG0 0x04 /* configuration register #0 */
+#define ISP_CFG0_HWMSK 0x000f /* Hardware revision mask */
+#define ISP_CFG0_1020 0x0001 /* ISP1020 */
+#define ISP_CFG0_1020A 0x0002 /* ISP1020A */
+#define ISP_CFG0_1040 0x0003 /* ISP1040 */
+#define ISP_CFG0_1040A 0x0004 /* ISP1040A */
+#define ISP_CFG0_1040B 0x0005 /* ISP1040B */
+#define ISP_CFG0_1040C 0x0006 /* ISP1040C */
#define ISP_CFG1 0x06 /* configuration register #1 */
+#define ISP_CFG1_F128 0x0040 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F64 0x0030 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F32 0x0020 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F16 0x0010 /* 128-byte FIFO threshold */
+#define ISP_CFG1_BENAB 0x0004 /* Global Bus burst enable */
+#define ISP_CFG1_SXP 0x0001 /* SXP register select */
#define PCI_INTF_CTL 0x08 /* pci interface control */
#define PCI_INTF_STS 0x0a /* pci interface status */
#define PCI_SEMAPHORE 0x0c /* pci semaphore */
#define PCI_NVRAM 0x0e /* pci nvram interface */
+#define CDMA_CONF 0x20 /* Command DMA Config */
+#define DDMA_CONF 0x40 /* Data DMA Config */
+#define DMA_CONF_SENAB 0x0008 /* SXP to DMA Data enable */
+#define DMA_CONF_RIRQ 0x0004 /* RISC interrupt enable */
+#define DMA_CONF_BENAB 0x0002 /* Bus burst enable */
+#define DMA_CONF_DIR 0x0001 /* DMA direction (0=fifo->host 1=host->fifo) */
/* mailbox registers */
#define MBOX0 0x70 /* mailbox 0 */
@@ -489,6 +508,7 @@
#define QUEUE_ENTRY_LEN 64
struct isp1020_hostdata {
+ u_long memaddr;
u_char revision;
struct host_param host_param;
struct dev_param dev_param[MAX_TARGETS];
@@ -540,16 +560,33 @@
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
+static inline u_short isp_inw(struct Scsi_Host *host, long offset)
+{
+ struct isp1020_hostdata *h = (struct isp1020_hostdata *)host->hostdata;
+ if (h->memaddr)
+ return readw(h->memaddr + offset);
+ else
+ return inw(host->io_port + offset);
+}
+
+static inline void isp_outw(u_short val, struct Scsi_Host *host, long offset)
+{
+ struct isp1020_hostdata *h = (struct isp1020_hostdata *)host->hostdata;
+ if (h->memaddr)
+ writew(val, h->memaddr + offset);
+ else
+ outw(val, host->io_port + offset);
+}
static inline void isp1020_enable_irqs(struct Scsi_Host *host)
{
- outw(ISP_EN_INT|ISP_EN_RISC, host->io_port + PCI_INTF_CTL);
+ isp_outw(ISP_EN_INT|ISP_EN_RISC, host, PCI_INTF_CTL);
}
static inline void isp1020_disable_irqs(struct Scsi_Host *host)
{
- outw(0x0, host->io_port + PCI_INTF_CTL);
+ isp_outw(0x0, host, PCI_INTF_CTL);
}
@@ -599,7 +636,8 @@
continue;
}
- if (check_region(host->io_port, 0xff)) {
+ if (host->io_port != 0UL &&
+ check_region(host->io_port, 0xff)) {
printk("qlogicisp : i/o region 0x%lx-0x%lx already "
"in use\n",
host->io_port, host->io_port + 0xff);
@@ -610,8 +648,8 @@
request_region(host->io_port, 0xff, "qlogicisp");
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+ isp_outw(0x0, host, PCI_SEMAPHORE);
+ isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR);
isp1020_enable_irqs(host);
hosts++;
@@ -631,7 +669,7 @@
hostdata = (struct isp1020_hostdata *) host->hostdata;
- outw(0x0, host->io_port + PCI_INTF_CTL);
+ isp_outw(0x0, host, PCI_INTF_CTL);
free_irq(host->irq, host);
release_region(host->io_port, 0xff);
@@ -651,9 +689,10 @@
hostdata = (struct isp1020_hostdata *) host->hostdata;
sprintf(buf,
- "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
+ "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d %s base 0x%lx",
hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
- host->io_port);
+ (host->io_port ? "I/O" : "MEM"),
+ (host->io_port ? host->io_port : hostdata->memaddr));
LEAVE("isp1020_info");
@@ -686,7 +725,7 @@
DEBUG(isp1020_print_scsi_cmd(Cmnd));
- out_ptr = inw(host->io_port + MBOX4);
+ out_ptr = isp_inw(host, + MBOX4);
in_ptr = hostdata->req_in_ptr;
DEBUG(printk("qlogicisp : request queue depth %d\n",
@@ -715,7 +754,7 @@
hostdata->send_marker = 0;
if (((in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN) == out_ptr) {
- outw(in_ptr, host->io_port + MBOX4);
+ isp_outw(in_ptr, host, MBOX4);
hostdata->req_in_ptr = in_ptr;
printk("qlogicisp : request queue overflow\n");
return 1;
@@ -791,7 +830,7 @@
cmd->segment_cnt = cpu_to_le16(1);
}
- outw(in_ptr, host->io_port + MBOX4);
+ isp_outw(in_ptr, host, MBOX4);
hostdata->req_in_ptr = in_ptr;
num_free = QLOGICISP_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
@@ -830,16 +869,16 @@
DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq));
- if (!(inw(host->io_port + PCI_INTF_STS) & 0x04)) {
+ if (!(isp_inw(host, PCI_INTF_STS) & 0x04)) {
/* spurious interrupts can happen legally */
DEBUG_INTR(printk("qlogicisp: got spurious interrupt\n"));
return;
}
- in_ptr = inw(host->io_port + MBOX5);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+ in_ptr = isp_inw(host, MBOX5);
+ isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR);
- if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
- status = inw(host->io_port + MBOX0);
+ if ((isp_inw(host, PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
+ status = isp_inw(host, MBOX0);
DEBUG_INTR(printk("qlogicisp : mbox completion status: %x\n",
status));
@@ -856,7 +895,7 @@
printk("qlogicisp : bad mailbox return status\n");
break;
}
- outw(0x0, host->io_port + PCI_SEMAPHORE);
+ isp_outw(0x0, host, PCI_SEMAPHORE);
}
out_ptr = hostdata->res_out_ptr;
@@ -888,7 +927,7 @@
else
Cmnd->result = DID_ERROR << 16;
- outw(out_ptr, host->io_port + MBOX5);
+ isp_outw(out_ptr, host, MBOX5);
(*Cmnd->scsi_done)(Cmnd);
}
hostdata->res_out_ptr = out_ptr;
@@ -1084,28 +1123,28 @@
ENTER("isp1020_reset_hardware");
- outw(ISP_RESET, host->io_port + PCI_INTF_CTL);
+ isp_outw(ISP_RESET, host, PCI_INTF_CTL);
udelay(100);
- outw(HCCR_RESET, host->io_port + HOST_HCCR);
+ isp_outw(HCCR_RESET, host, HOST_HCCR);
udelay(100);
- outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
- outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
+ isp_outw(HCCR_RELEASE, host, HOST_HCCR);
+ isp_outw(HCCR_BIOS_DISABLE, host, HOST_HCCR);
loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY)
+ while (--loop_count && isp_inw(host, HOST_HCCR) == RISC_BUSY)
barrier();
if (!loop_count)
printk("qlogicisp: reset_hardware loop timeout\n");
- outw(0, host->io_port + ISP_CFG1);
+ isp_outw(0, host, ISP_CFG1);
#if DEBUG_ISP1020
- printk("qlogicisp : mbox 0 0x%04x \n", inw(host->io_port + MBOX0));
- printk("qlogicisp : mbox 1 0x%04x \n", inw(host->io_port + MBOX1));
- printk("qlogicisp : mbox 2 0x%04x \n", inw(host->io_port + MBOX2));
- printk("qlogicisp : mbox 3 0x%04x \n", inw(host->io_port + MBOX3));
- printk("qlogicisp : mbox 4 0x%04x \n", inw(host->io_port + MBOX4));
- printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));
+ printk("qlogicisp : mbox 0 0x%04x \n", isp_inw(host, MBOX0));
+ printk("qlogicisp : mbox 1 0x%04x \n", isp_inw(host, MBOX1));
+ printk("qlogicisp : mbox 2 0x%04x \n", isp_inw(host, MBOX2));
+ printk("qlogicisp : mbox 3 0x%04x \n", isp_inw(host, MBOX3));
+ printk("qlogicisp : mbox 4 0x%04x \n", isp_inw(host, MBOX4));
+ printk("qlogicisp : mbox 5 0x%04x \n", isp_inw(host, MBOX5));
#endif /* DEBUG_ISP1020 */
param[0] = MBOX_NO_OP;
@@ -1170,7 +1209,7 @@
static int isp1020_init(struct Scsi_Host *sh)
{
- u_long io_base;
+ u_long io_base, mem_base;
struct isp1020_hostdata *hostdata;
u_char revision;
u_int irq;
@@ -1189,6 +1228,7 @@
return 1;
}
io_base = pdev->base_address[0];
+ mem_base = pdev->base_address[1];
irq = pdev->irq;
if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
@@ -1204,6 +1244,8 @@
}
#ifdef __sparc__
+ if (mem_base)
+ mem_base = __pa(mem_base);
command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY|
PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR);
pci_write_config_word(pdev, PCI_COMMAND, command);
@@ -1221,11 +1263,22 @@
}
#endif
- if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
- io_base &= PCI_BASE_ADDRESS_IO_MASK;
- else {
- printk("qlogicisp : i/o mapping is disabled\n");
- return 1;
+ if ((command & PCI_COMMAND_MEMORY) &&
+ ((mem_base & 1) == 0)) {
+ mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
+ mem_base = (u_long) ioremap(mem_base, PAGE_SIZE);
+ hostdata->memaddr = mem_base;
+ io_base = 0;
+ } else {
+ if ((command & PCI_COMMAND_IO) && (io_base & 3) == 1)
+ io_base &= PCI_BASE_ADDRESS_IO_MASK;
+ else {
+ printk("qlogicisp : i/o mapping is disabled\n");
+ return 1;
+ }
+ hostdata->memaddr = 0;
+ sh->io_port = io_base;
+ mem_base = 0;
}
if (!(command & PCI_COMMAND_MASTER)) {
@@ -1236,18 +1289,18 @@
if (revision != ISP1020_REV_ID)
printk("qlogicisp : new isp1020 revision ID (%d)\n", revision);
- if (inw(io_base + PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC
- || inw(io_base + PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020)
+ if (isp_inw(sh, PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC
+ || isp_inw(sh, PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020)
{
- printk("qlogicisp : can't decode i/o address space 0x%lx\n",
- io_base);
+ printk("qlogicisp : can't decode %s address space 0x%lx\n",
+ (io_base ? "I/O" : "MEM"),
+ (io_base ? io_base : mem_base));
return 1;
}
hostdata->revision = revision;
sh->irq = irq;
- sh->io_port = io_base;
sh->max_id = MAX_TARGETS;
sh->max_lun = MAX_LUNS;
@@ -1404,20 +1457,20 @@
for (i = 8; i >= 0; i--) {
output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
- outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
- outw(output | 0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY();
- outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(output | 0x2, host, PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(output | 0x3, host, PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(output | 0x2, host, PCI_NVRAM); NVRAM_DELAY();
}
for (i = 0xf, value = 0; i >= 0; i--) {
value <<= 1;
- outw(0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY();
- input = inw(host->io_port + PCI_NVRAM); NVRAM_DELAY();
- outw(0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(0x3, host, PCI_NVRAM); NVRAM_DELAY();
+ input = isp_inw(host, PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(0x2, host, PCI_NVRAM); NVRAM_DELAY();
if (input & 0x8) value |= 1;
}
- outw(0x0, host->io_port + PCI_NVRAM); NVRAM_DELAY();
+ isp_outw(0x0, host, PCI_NVRAM); NVRAM_DELAY();
return value;
}
@@ -1467,7 +1520,7 @@
int i, k;
u_int queue_addr;
u_short param[6];
- u_short isp_cfg1;
+ u_short isp_cfg1, hwrev;
unsigned long flags;
struct isp1020_hostdata *hostdata =
(struct isp1020_hostdata *) host->hostdata;
@@ -1477,7 +1530,16 @@
save_flags(flags);
cli();
- outw(hostdata->host_param.fifo_threshold, host->io_port + ISP_CFG1);
+ hwrev = isp_inw(host, ISP_CFG0) & ISP_CFG0_HWMSK;
+ isp_cfg1 = ISP_CFG1_F64 | ISP_CFG1_BENAB;
+ if (hwrev == ISP_CFG0_1040A) {
+ /* Busted fifo, says mjacob. */
+ isp_cfg1 &= ISP_CFG1_BENAB;
+ }
+
+ isp_outw(isp_inw(host, ISP_CFG1) | isp_cfg1, host, ISP_CFG1);
+ isp_outw(isp_inw(host, CDMA_CONF) | DMA_CONF_BENAB, host, CDMA_CONF);
+ isp_outw(isp_inw(host, DDMA_CONF) | DMA_CONF_BENAB, host, DDMA_CONF);
param[0] = MBOX_SET_INIT_SCSI_ID;
param[1] = hostdata->host_param.initiator_scsi_id;
@@ -1537,16 +1599,6 @@
return 1;
}
- isp_cfg1 = inw(host->io_port + ISP_CFG1);
-
- if (hostdata->host_param.data_dma_burst_enable
- || hostdata->host_param.command_dma_burst_enable)
- isp_cfg1 |= 0x0004;
- else
- isp_cfg1 &= 0xfffb;
-
- outw(isp_cfg1, host->io_port + ISP_CFG1);
-
param[0] = MBOX_SET_TAG_AGE_LIMIT;
param[1] = hostdata->host_param.tag_aging;
@@ -1659,47 +1711,47 @@
return 1;
loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080)
+ while (--loop_count && isp_inw(host, HOST_HCCR) & 0x0080)
barrier();
if (!loop_count)
printk("qlogicisp: mbox_command loop timeout #1\n");
switch(mbox_param[param[0]] >> 4) {
- case 6: outw(param[5], host->io_port + MBOX5);
- case 5: outw(param[4], host->io_port + MBOX4);
- case 4: outw(param[3], host->io_port + MBOX3);
- case 3: outw(param[2], host->io_port + MBOX2);
- case 2: outw(param[1], host->io_port + MBOX1);
- case 1: outw(param[0], host->io_port + MBOX0);
+ case 6: isp_outw(param[5], host, MBOX5);
+ case 5: isp_outw(param[4], host, MBOX4);
+ case 4: isp_outw(param[3], host, MBOX3);
+ case 3: isp_outw(param[2], host, MBOX2);
+ case 2: isp_outw(param[1], host, MBOX1);
+ case 1: isp_outw(param[0], host, MBOX0);
}
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
+ isp_outw(0x0, host, PCI_SEMAPHORE);
+ isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR);
+ isp_outw(HCCR_SET_HOST_INTR, host, HOST_HCCR);
loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && !(inw(host->io_port + PCI_INTF_STS) & 0x04))
+ while (--loop_count && !(isp_inw(host, PCI_INTF_STS) & 0x04))
barrier();
if (!loop_count)
printk("qlogicisp: mbox_command loop timeout #2\n");
loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + MBOX0) == 0x04)
+ while (--loop_count && isp_inw(host, MBOX0) == 0x04)
barrier();
if (!loop_count)
printk("qlogicisp: mbox_command loop timeout #3\n");
switch(mbox_param[param[0]] & 0xf) {
- case 6: param[5] = inw(host->io_port + MBOX5);
- case 5: param[4] = inw(host->io_port + MBOX4);
- case 4: param[3] = inw(host->io_port + MBOX3);
- case 3: param[2] = inw(host->io_port + MBOX2);
- case 2: param[1] = inw(host->io_port + MBOX1);
- case 1: param[0] = inw(host->io_port + MBOX0);
+ case 6: param[5] = isp_inw(host, MBOX5);
+ case 5: param[4] = isp_inw(host, MBOX4);
+ case 4: param[3] = isp_inw(host, MBOX3);
+ case 3: param[2] = isp_inw(host, MBOX2);
+ case 2: param[1] = isp_inw(host, MBOX1);
+ case 1: param[0] = isp_inw(host, MBOX0);
}
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+ isp_outw(0x0, host, PCI_SEMAPHORE);
+ isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR);
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)