From c3c996300c7c9231363ed1450ef63c9bd7a52f46 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Tue, 10 Nov 2026 03:10:57 +0800 Subject: [mubios] Fix legacy interrupt routing and enable PIIX IDE channels Keep IOAPIC inputs masked and deliver legacy PIC interrupts through LVT0 only, avoiding extra ExtINT routes that leave PIC and APIC interrupts in service. Enumerate the root PCI bus for the PIIX3 IDE controller during POST. Enable I/O decoding and both IDE channels while preserving their timing configuration so Linux ata_piix probes the disks. Signed-off-by: Richard Qin --- mubios/drivers/ata.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'mubios/drivers/ata.c') diff --git a/mubios/drivers/ata.c b/mubios/drivers/ata.c index 7d23a9c..c31c06e 100644 --- a/mubios/drivers/ata.c +++ b/mubios/drivers/ata.c @@ -22,6 +22,16 @@ #include "bios.h" #include "io.h" +#define PCI_CONFIG_ADDRESS 0x0CF8u +#define PCI_CONFIG_DATA 0x0CFCu +#define PCI_VENDOR_DEVICE 0x00u +#define PCI_COMMAND 0x04u +#define PCI_COMMAND_IO 0x0001u +#define PIIX3_IDE_ID 0x70108086u +#define PIIX_IDETIM_PRIMARY 0x40u +#define PIIX_IDETIM_SECONDARY 0x42u +#define PIIX_IDETIM_ENABLE 0x8000u + #define ATA_DATA 0x1F0u #define ATA_SECTOR_COUNT 0x1F2u #define ATA_LBA_LOW 0x1F3u @@ -40,6 +50,50 @@ #define ATA_CMD_IDENTIFY 0xECu #define ATA_CONTROL_SRST 0x04u +static u32 +ata_pci_read (u16 devfn, u8 offset) +{ + io_out32 (PCI_CONFIG_ADDRESS, + 0x80000000u | ((u32)devfn << 8) | (offset & 0xFCu)); + return io_in32 (PCI_CONFIG_DATA); +} + +static void +ata_pci_write16 (u16 devfn, u8 offset, u16 value) +{ + io_out32 (PCI_CONFIG_ADDRESS, + 0x80000000u | ((u32)devfn << 8) | (offset & 0xFCu)); + io_out16 ((u16)(PCI_CONFIG_DATA + (offset & 2u)), value); +} + +void +ata_init (void) +{ + u16 devfn; + u16 command; + u32 timing; + + /* Enumerate the root PCI bus used by QEMU's pc machine. */ + for (devfn = 0; devfn < 256u; ++devfn) + { + /* IDETIM is specific to the PIIX3 IDE controller. */ + if (ata_pci_read (devfn, PCI_VENDOR_DEVICE) != PIIX3_IDE_ID) + continue; + + command = (u16)ata_pci_read (devfn, PCI_COMMAND); + /* Use a word write to leave the write-one-to-clear status untouched. */ + ata_pci_write16 (devfn, PCI_COMMAND, (u16)(command | PCI_COMMAND_IO)); + + /* Linux's ata_piix requires IDETIM bit 15 to probe each channel. */ + timing = ata_pci_read (devfn, PIIX_IDETIM_PRIMARY); + ata_pci_write16 (devfn, PIIX_IDETIM_PRIMARY, + (u16)((u16)timing | PIIX_IDETIM_ENABLE)); + ata_pci_write16 (devfn, PIIX_IDETIM_SECONDARY, + (u16)((timing >> 16) | PIIX_IDETIM_ENABLE)); + return; + } +} + static u8 ata_wait_not_busy (void) { -- cgit v1.2.3