aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.com>2017-07-03 19:21:02 +0200
committerHannes Reinecke <hare@suse.com>2021-03-14 11:57:49 +0100
commit9187b657e2257f892f70f96ae1e79e3d64a2e712 (patch)
treea9dfb395e17e8885cb24ecd4d1934b3b22f01ff5
parent66215c55d4bc633a83910fb6ee5fa1464e6e9c08 (diff)
downloadscsi-devel-9187b657e2257f892f70f96ae1e79e3d64a2e712.tar.gz
megaraid_mbox: add ioport support
Older boards only support I/O ports. Signed-off-by: Hannes Reinecke <hare@suse.com>
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c98
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h38
2 files changed, 105 insertions, 31 deletions
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 9bfdee06ec9b8..ed8b492116bb2 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -755,17 +755,19 @@ megaraid_init_mbox(adapter_t *adapter)
goto out_free_raid_dev;
}
+ if (pci_resource_flags(pdev, 0) & IORESOURCE_MEM) {
+ raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128);
- raid_dev->baseaddr = ioremap(raid_dev->baseport, 128);
-
- if (!raid_dev->baseaddr) {
-
- con_log(CL_ANN, (KERN_WARNING
- "megaraid: could not map hba memory\n") );
+ if (!raid_dev->baseaddr) {
+ con_log(CL_ANN, (KERN_WARNING
+ "megaraid: could not map hba memory\n") );
- goto out_release_regions;
+ goto out_release_regions;
+ }
+ } else {
+ raid_dev->baseport += 0x10;
+ raid_dev->baseaddr = NULL;
}
-
/* initialize the mutual exclusion lock for the mailbox */
spin_lock_init(&raid_dev->mailbox_lock);
@@ -778,8 +780,9 @@ megaraid_init_mbox(adapter_t *adapter)
* and initialize its internal state
*/
- if (megaraid_mbox_fire_sync_cmd(adapter))
- con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
+ if (raid_dev->baseaddr)
+ if (megaraid_mbox_fire_sync_cmd(adapter))
+ con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
/*
* Setup the rest of the soft state using the library of
@@ -918,7 +921,8 @@ out_free_irq:
out_alloc_cmds:
megaraid_free_cmd_packets(adapter);
out_iounmap:
- iounmap(raid_dev->baseaddr);
+ if (raid_dev->baseaddr)
+ iounmap(raid_dev->baseaddr);
out_release_regions:
pci_release_regions(pdev);
out_free_raid_dev:
@@ -948,7 +952,8 @@ megaraid_fini_mbox(adapter_t *adapter)
free_irq(adapter->irq, adapter);
- iounmap(raid_dev->baseaddr);
+ if (raid_dev->baseaddr)
+ iounmap(raid_dev->baseaddr);
pci_release_regions(adapter->pdev);
@@ -1439,12 +1444,17 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb)
adapter->outstanding_cmds++;
mbox->busy = 1; // Set busy
- mbox->poll = 0;
- mbox->ack = 0;
- wmb();
- WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+ if (raid_dev->baseaddr) {
+ mbox->poll = 0;
+ mbox->ack = 0;
+ wmb();
+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+ } else {
+ irq_enable(adapter);
+ issue_command(adapter);
+ }
spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
return 0;
@@ -2082,12 +2092,19 @@ megaraid_ack_sequence(adapter_t *adapter)
* Check if a valid interrupt is pending. If found, force the
* interrupt line low.
*/
- dword = RDOUTDOOR(raid_dev);
- if (dword != 0x10001234) break;
-
- handled = 1;
-
- WROUTDOOR(raid_dev, 0x10001234);
+ if (raid_dev->baseaddr) {
+ dword = RDOUTDOOR(raid_dev);
+ if (dword != 0x10001234)
+ break;
+ handled = 1;
+ WROUTDOOR(raid_dev, 0x10001234);
+ } else {
+ byte = irq_state(adapter);
+ if ( (byte & VALID_INTR_BYTE) == 0)
+ break;
+ handled = 1;
+ set_irq_state(adapter, byte);
+ }
nstatus = 0;
// wait for valid numstatus to post
@@ -2135,9 +2152,11 @@ megaraid_ack_sequence(adapter_t *adapter)
list_add_tail(&scb->list, &clist);
}
- // Acknowledge interrupt
- WRINDOOR(raid_dev, 0x02);
-
+ /* Acknowledge interrupt */
+ if (raid_dev->baseaddr)
+ WRINDOOR(raid_dev, 0x02);
+ else
+ irq_ack(adapter);
} while(1);
spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
@@ -2716,6 +2735,19 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
mbox->cmdid = 0xFE;
mbox->busy = 1;
+ if (!raid_dev->baseaddr) {
+ irq_disable(adapter);
+ issue_command(adapter);
+
+ while (!((byte = irq_state(adapter)) & INTR_VALID))
+ cpu_relax();
+
+ set_irq_state(adapter, byte);
+ irq_enable(adapter);
+ irq_ack(adapter);
+
+ return mbox->status;
+ }
mbox->poll = 0;
mbox->ack = 0;
mbox->numstatus = 0xFF;
@@ -2724,10 +2756,14 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
wmb();
WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
- // wait for maximum 1 second for status to post. If the status is not
- // available within 1 second, assume FW is initializing and wait
- // for an extended amount of time
- if (mbox->numstatus == 0xFF) { // status not yet available
+ /*
+ * wait for maximum 1 second for status to post.
+ * If the status is not available within 1 second,
+ * assume FW is initializing and wait for an extended
+ * amount of time.
+ */
+ if (mbox->numstatus == 0xFF) {
+ /* status not yet available */
udelay(25);
for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) {
@@ -2741,10 +2777,10 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
"megaraid mailbox: wait for FW to boot "));
for (i = 0; (mbox->numstatus == 0xFF) &&
- (i < MBOX_RESET_WAIT); i++) {
+ (i < MBOX_RESET_WAIT); i++) {
rmb();
con_log(CL_ANN, ("\b\b\b\b\b[%03d]",
- MBOX_RESET_WAIT - i));
+ MBOX_RESET_WAIT - i));
msleep(1000);
}
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 3e4347c6dab1c..3afa54e4d7fbe 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -107,6 +107,27 @@
*/
#define MBOX_IBUF_SIZE 4096
+/* I/O Port offsets */
+#define CMD_PORT 0x00
+#define ACK_PORT 0x00
+#define TOGGLE_PORT 0x01
+#define INTR_PORT 0x0a
+
+#define MBOX_BUSY_PORT 0x00
+#define MBOX_PORT0 0x04
+#define MBOX_PORT1 0x05
+#define MBOX_PORT2 0x06
+#define MBOX_PORT3 0x07
+#define ENABLE_MBOX_REGION 0x0B
+
+/* I/O Port Values */
+#define ISSUE_BYTE 0x10
+#define ACK_BYTE 0x08
+#define ENABLE_INTR_BYTE 0xc0
+#define DISABLE_INTR_BYTE 0x00
+#define VALID_INTR_BYTE 0x40
+#define MBOX_BUSY_BYTE 0x10
+#define ENABLE_MBOX_BYTE 0x00
/**
* mbox_ccb_t - command control block specific to mailbox based controllers
@@ -229,6 +250,23 @@ typedef struct {
#define WRINDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x20)
#define WROUTDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x2C)
+#define issue_command(adapter) \
+ outb_p(ISSUE_BYTE, (adapter)->baseport + CMD_PORT)
+
+#define irq_state(adapter) inb_p((adapter)->baseport + INTR_PORT)
+
+#define set_irq_state(adapter, value) \
+ outb_p((value), (adapter)->baseport + INTR_PORT)
+
+#define irq_ack(adapter) \
+ outb_p(ACK_BYTE, (adapter)->baseport + ACK_PORT)
+
+#define irq_enable(adapter) \
+ outb_p(ENABLE_INTR_BYTE, (adapter)->baseport + TOGGLE_PORT)
+
+#define irq_disable(adapter) \
+ outb_p(DISABLE_INTR_BYTE, (adapter)->baseport + TOGGLE_PORT)
+
#endif // _MEGARAID_H_
// vim: set ts=8 sw=8 tw=78: