aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mubios/core/post.c1
-rw-r--r--mubios/drivers/ata.c54
-rw-r--r--mubios/drivers/ioapic.c22
-rw-r--r--mubios/include/bios.h1
4 files changed, 57 insertions, 21 deletions
diff --git a/mubios/core/post.c b/mubios/core/post.c
index 15d07ed..8d12369 100644
--- a/mubios/core/post.c
+++ b/mubios/core/post.c
@@ -37,6 +37,7 @@ post_main (void)
pic_init ();
pit_init ();
ioapic_init ();
+ ata_init ();
volatile u8 *mbr;
u8 ata_status;
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)
{
diff --git a/mubios/drivers/ioapic.c b/mubios/drivers/ioapic.c
index 552f497..6f1de64 100644
--- a/mubios/drivers/ioapic.c
+++ b/mubios/drivers/ioapic.c
@@ -28,14 +28,6 @@
#define IOAPIC_REDIRECTION_BASE 0x10u
#define IOAPIC_REDIRECTION_MASK 0x00010000u
-#define IOAPIC_IRQ0_LOW 0x10u
-#define IOAPIC_IRQ0_HIGH 0x11u
-#define IOAPIC_IRQ1_LOW 0x12u
-#define IOAPIC_IRQ1_HIGH 0x13u
-
-#define IOAPIC_IRQ0_EXTINT 0x00000700u
-#define IOAPIC_IRQ1_EXTINT 0x00000700u
-
#define IA32_APIC_BASE_MSR 0x0000001Bu
#define APIC_BASE 0xFEE00000u
#define APIC_SVR_OFFSET 0x000000F0u
@@ -111,19 +103,7 @@ ioapic_init (void)
*(volatile u32 *)(APIC_BASE + APIC_LVT0_OFFSET) = 0x00000700u;
/*
- * Mask every IOAPIC input before enabling the explicitly configured lines.
+ * Keep every IOAPIC input masked so legacy interrupts use only LVT0.
*/
ioapic_mask_all ();
-
- /*
- * Route IOAPIC pin 0 to the legacy PIC ExtINT path.
- */
- ioapic_write (IOAPIC_IRQ0_HIGH, 0x00000000u);
- ioapic_write (IOAPIC_IRQ0_LOW, IOAPIC_IRQ0_EXTINT);
-
- /*
- * Route the keyboard IRQ through the legacy PIC ExtINT path.
- */
- ioapic_write (IOAPIC_IRQ1_HIGH, 0x00000000u);
- ioapic_write (IOAPIC_IRQ1_LOW, IOAPIC_IRQ1_EXTINT);
}
diff --git a/mubios/include/bios.h b/mubios/include/bios.h
index 979e445..c52af80 100644
--- a/mubios/include/bios.h
+++ b/mubios/include/bios.h
@@ -60,6 +60,7 @@ void vga_text_mode_init (void);
void ivt_init (void);
+void ata_init (void);
u8 ata_read_sectors28 (u32 lba, u16 *buffer, u16 count);
u8 ata_reset (void);
u8 ata_identify (u16 *cylinders, u16 *heads, u16 *sectors_per_track,