From 4ccb23125e8653e9dc1c42f2f2ae57594ef072c3 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 5 Dec 2009 11:25:09 -0500 Subject: [PATCH] Support ISA ATA devices for qemu's "-M isapc" mode. Add probing for ISA ATA devices when no pci devices found. Also, add defines for common ATA ports. Also, make sure irq and pci_bdf are defined for both pci ata controllers. --- src/ata.c | 49 ++++++++++++++++++++++++++++++------------------- src/ata.h | 8 ++++---- src/disk.c | 28 +++++++++++++++++++--------- src/ioport.h | 4 ++++ src/pciinit.c | 8 ++++---- 5 files changed, 61 insertions(+), 36 deletions(-) diff --git a/src/ata.c b/src/ata.c index 9453830..cf54d0f 100644 --- a/src/ata.c +++ b/src/ata.c @@ -753,53 +753,64 @@ ata_detect(void *data) } } +static void +init_controller(struct ata_channel_s *atachannel + , int bdf, int irq, u32 port1, u32 port2) +{ + SET_GLOBAL(atachannel->irq, irq); + SET_GLOBAL(atachannel->pci_bdf, bdf); + SET_GLOBAL(atachannel->iobase1, port1); + SET_GLOBAL(atachannel->iobase2, port2); + dprintf(1, "ATA controller %d at %x/%x (irq %d dev %x)\n" + , atachannel - ATA_channels, port1, port2, irq, bdf); + run_thread(ata_detect, atachannel); +} + static void ata_init() { // Scan PCI bus for ATA adapters - int count=0; + int count=0, pcicount=0; int bdf, max; foreachpci(bdf, max) { + pcicount++; if (pci_config_readw(bdf, PCI_CLASS_DEVICE) != PCI_CLASS_STORAGE_IDE) continue; if (count >= ARRAY_SIZE(ATA_channels)) break; u8 irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); - SET_GLOBAL(ATA_channels[count].irq, irq); - SET_GLOBAL(ATA_channels[count].pci_bdf, bdf); - u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG); u32 port1, port2; - if (prog_if & 1) { port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3; port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3; } else { - port1 = 0x1f0; - port2 = 0x3f0; + port1 = PORT_ATA1_CMD_BASE; + port2 = PORT_ATA1_CTRL_BASE; } - SET_GLOBAL(ATA_channels[count].iobase1, port1); - SET_GLOBAL(ATA_channels[count].iobase2, port2); - dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n" - , count, port1, port2, bdf, prog_if); - run_thread(ata_detect, &ATA_channels[count]); + init_controller(&ATA_channels[count], bdf, irq, port1, port2); count++; if (prog_if & 4) { port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3; port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3; } else { - port1 = 0x170; - port2 = 0x370; + port1 = PORT_ATA2_CMD_BASE; + port2 = PORT_ATA2_CTRL_BASE; } - dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n" - , count, port1, port2, bdf, prog_if); - SET_GLOBAL(ATA_channels[count].iobase1, port1); - SET_GLOBAL(ATA_channels[count].iobase2, port2); - run_thread(ata_detect, &ATA_channels[count]); + init_controller(&ATA_channels[count], bdf, irq, port1, port2); count++; } + + if (!CONFIG_COREBOOT && !pcicount && ARRAY_SIZE(ATA_channels) >= 2) { + // 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); + init_controller(&ATA_channels[1] + , -1, 15, PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE); + } } void diff --git a/src/ata.h b/src/ata.h index 65d67b0..406c284 100644 --- a/src/ata.h +++ b/src/ata.h @@ -5,10 +5,10 @@ #include "config.h" // CONFIG_MAX_ATA_INTERFACES struct ata_channel_s { - u16 iobase1; // IO Base 1 - u16 iobase2; // IO Base 2 - u16 pci_bdf; - u8 irq; // IRQ + u16 iobase1; + u16 iobase2; + u8 irq; + int pci_bdf; }; // ata.c diff --git a/src/disk.c b/src/disk.c index 30b6e7b..ef4866f 100644 --- a/src/disk.c +++ b/src/disk.c @@ -602,15 +602,25 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g) SET_INT13DPT(regs, reserved1, 0); SET_INT13DPT(regs, reserved2, 0); - SET_INT13DPT(regs, host_bus[0], 'P'); - SET_INT13DPT(regs, host_bus[1], 'C'); - SET_INT13DPT(regs, host_bus[2], 'I'); - SET_INT13DPT(regs, host_bus[3], 0); - - u32 bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf); - u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8) - | (pci_bdf_to_fn(bdf) << 16)); - SET_INT13DPT(regs, iface_path, path); + int bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf); + if (bdf != -1) { + SET_INT13DPT(regs, host_bus[0], 'P'); + SET_INT13DPT(regs, host_bus[1], 'C'); + SET_INT13DPT(regs, host_bus[2], 'I'); + SET_INT13DPT(regs, host_bus[3], 0); + + u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8) + | (pci_bdf_to_fn(bdf) << 16)); + SET_INT13DPT(regs, iface_path, path); + } else { + // ISA + SET_INT13DPT(regs, host_bus[0], 'I'); + SET_INT13DPT(regs, host_bus[1], 'S'); + SET_INT13DPT(regs, host_bus[2], 'A'); + SET_INT13DPT(regs, host_bus[3], 0); + + SET_INT13DPT(regs, iface_path, iobase1); + } SET_INT13DPT(regs, iface_type[0], 'A'); SET_INT13DPT(regs, iface_type[1], 'T'); diff --git a/src/ioport.h b/src/ioport.h index f22b665..f31e377 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -34,11 +34,15 @@ #define PORT_DMA2_MODE_REG 0x00d6 #define PORT_DMA2_MASTER_CLEAR 0x00da #define PORT_MATH_CLEAR 0x00f0 +#define PORT_ATA2_CMD_BASE 0x0170 +#define PORT_ATA1_CMD_BASE 0x01f0 #define PORT_LPT2 0x0278 #define PORT_SERIAL4 0x02e8 #define PORT_SERIAL2 0x02f8 +#define PORT_ATA2_CTRL_BASE 0x0370 #define PORT_LPT1 0x0378 #define PORT_SERIAL3 0x03e8 +#define PORT_ATA1_CTRL_BASE 0x03f0 #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 fe7575c..9fa2c6b 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -98,10 +98,10 @@ static void pci_bios_init_device(u16 bdf) goto default_map; } else { /* IDE: we map it as in ISA mode */ - pci_set_io_region_addr(bdf, 0, 0x1f0); - pci_set_io_region_addr(bdf, 1, 0x3f4); - pci_set_io_region_addr(bdf, 2, 0x170); - pci_set_io_region_addr(bdf, 3, 0x374); + 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, 2, PORT_ATA2_CMD_BASE); + pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE + 4); } break; case PCI_CLASS_SYSTEM_PIC: -- 2.25.1