Fix ATA iobase2 access on PCI native mode interfaces.
The ctrl register is iorange + 2 not iorange + 6.
Rework port definitions to be based on PCI offsets instead of ISA.
Also, properly define ATA irqs when in PCI compatibility mode.
diff --git a/src/ata.c b/src/ata.c
index cf54d0f..6c2fc98 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -766,6 +766,9 @@
run_thread(ata_detect, atachannel);
}
+#define IRQ_ATA1 14
+#define IRQ_ATA2 15
+
static void
ata_init()
{
@@ -779,15 +782,17 @@
if (count >= ARRAY_SIZE(ATA_channels))
break;
- u8 irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
+ u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG);
- u32 port1, port2;
+ u32 port1, port2, irq;
if (prog_if & 1) {
port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3;
port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3;
+ irq = pciirq;
} else {
port1 = PORT_ATA1_CMD_BASE;
port2 = PORT_ATA1_CTRL_BASE;
+ irq = IRQ_ATA1;
}
init_controller(&ATA_channels[count], bdf, irq, port1, port2);
count++;
@@ -795,9 +800,11 @@
if (prog_if & 4) {
port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3;
port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3;
+ irq = pciirq;
} else {
port1 = PORT_ATA2_CMD_BASE;
port2 = PORT_ATA2_CTRL_BASE;
+ irq = IRQ_ATA2;
}
init_controller(&ATA_channels[count], bdf, irq, port1, port2);
count++;
@@ -807,9 +814,9 @@
// No PCI devices found - probably a QEMU "-M isapc" machine.
// Try using ISA ports for ATA controllers.
init_controller(&ATA_channels[0]
- , -1, 14, PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE);
+ , -1, IRQ_ATA1, PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE);
init_controller(&ATA_channels[1]
- , -1, 15, PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE);
+ , -1, IRQ_ATA2, PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE);
}
}
diff --git a/src/ata.h b/src/ata.h
index 406c284..f8d86aa 100644
--- a/src/ata.h
+++ b/src/ata.h
@@ -34,9 +34,10 @@
#define ATA_CB_DH 6 // device head in/out pio_base_addr1+6
#define ATA_CB_STAT 7 // primary status in pio_base_addr1+7
#define ATA_CB_CMD 7 // command out pio_base_addr1+7
-#define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6
-#define ATA_CB_DC 6 // device control out pio_base_addr2+6
-#define ATA_CB_DA 7 // device address in pio_base_addr2+7
+
+#define ATA_CB_ASTAT 2 // alternate status in pio_base_addr2+2
+#define ATA_CB_DC 2 // device control out pio_base_addr2+2
+#define ATA_CB_DA 3 // device address in pio_base_addr2+3
#define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
#define ATA_CB_ER_BBK 0x80 // ATA bad block
diff --git a/src/ioport.h b/src/ioport.h
index f31e377..ba099a7 100644
--- a/src/ioport.h
+++ b/src/ioport.h
@@ -39,10 +39,10 @@
#define PORT_LPT2 0x0278
#define PORT_SERIAL4 0x02e8
#define PORT_SERIAL2 0x02f8
-#define PORT_ATA2_CTRL_BASE 0x0370
+#define PORT_ATA2_CTRL_BASE 0x0374
#define PORT_LPT1 0x0378
#define PORT_SERIAL3 0x03e8
-#define PORT_ATA1_CTRL_BASE 0x03f0
+#define PORT_ATA1_CTRL_BASE 0x03f4
#define PORT_FD_DOR 0x03f2
#define PORT_FD_STATUS 0x03f4
#define PORT_FD_DATA 0x03f5
diff --git a/src/pciinit.c b/src/pciinit.c
index 9fa2c6b..1e8e9b6 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -99,9 +99,9 @@
} else {
/* IDE: we map it as in ISA mode */
pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
- pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE + 4);
+ pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
- pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE + 4);
+ pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
}
break;
case PCI_CLASS_SYSTEM_PIC: