diff --git a/src/hulk/apic.d b/src/hulk/apic.d index 59d552e..e35543d 100644 --- a/src/hulk/apic.d +++ b/src/hulk/apic.d @@ -7,11 +7,14 @@ import hulk.klog; import hulk.hurl; import hulk.acpi; import hulk.idt; +import hulk.rtc; struct apic { private enum uint PERIODIC_MODE = 0x2_0000u; + private enum ulong IRQ_RTC = 8u; + static struct ApicRegister { public uint value; @@ -52,31 +55,60 @@ struct apic ApicRegister divide_configuration; } + static struct IoApicRegisters + { + ApicRegister address; + ApicRegister data; + } + private static __gshared ApicRegisters * apic_registers; + private static __gshared IoApicRegisters * io_apic_registers; public static void initialize() { apic_registers = cast(ApicRegisters *)acpi.apic_address; + io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u; hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers, PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE); + hurl.map(cast(ulong)io_apic_registers, cast(ulong)io_apic_registers, + PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE); klog.writefln("LAPIC ID: 0x%08x", apic_registers.lapic_id.value); klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.value); /* Enable local APIC to receive interrupts and set spurious interrupt * vector to 0xFF. */ - apic_registers.spurious_interrupt_vector.value = 0x1FFu; - apic_registers.lvt_timer.value = idt.EXCEPTION_LAPIC_TIMER | PERIODIC_MODE; - apic_registers.lvt_lint[0].value = idt.EXCEPTION_LAPIC_LINT0; - apic_registers.lvt_lint[1].value = idt.EXCEPTION_LAPIC_LINT1; - apic_registers.divide_configuration.value = 3u; + apic_registers.spurious_interrupt_vector.value = 0x100u | idt.INT_APIC_SPURIOUS; + apic_registers.lvt_timer.value = idt.INT_APIC_TIMER; + apic_registers.lvt_lint[0].value = idt.INT_APIC_LINT0; + apic_registers.lvt_lint[1].value = idt.INT_APIC_LINT1; + /* Enable RTC interrupt. */ + configure_io_apic_irq(IRQ_RTC, idt.INT_APIC_BASE + IRQ_RTC); } - private static void eoi() + private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id) + { + ulong entry = interrupt_id; + io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u); + io_apic_registers.data.value = entry & 0xFFFF_FFFFu; + io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u + 1u); + io_apic_registers.data.value = entry >> 32u; + } + + public static void eoi() { apic_registers.eoi.value = 0u; } public static void isr(ulong vector) { + switch (vector) + { + case idt.INT_APIC_BASE + IRQ_RTC: + rtc.isr(); + break; + + default: + break; + } eoi(); } } diff --git a/src/hulk/idt.d b/src/hulk/idt.d index 192f860..9bb1c8c 100644 --- a/src/hulk/idt.d +++ b/src/hulk/idt.d @@ -12,9 +12,14 @@ import hulk.apic; struct idt { - public static enum ulong EXCEPTION_LAPIC_TIMER = 0x70u; - public static enum ulong EXCEPTION_LAPIC_LINT0 = 0x71u; - public static enum ulong EXCEPTION_LAPIC_LINT1 = 0x72u; + /* The I/O APIC is configured to map IRQ 0 to interrupt 64 (0x40). */ + public static enum ulong INT_APIC_BASE = 0x40u; /* IRQ 0 */ + public static enum ulong INT_APIC_COUNT = 24u; + + public static enum ulong INT_APIC_TIMER = 0x70u; + public static enum ulong INT_APIC_LINT0 = 0x71u; + public static enum ulong INT_APIC_LINT1 = 0x72u; + public static enum ulong INT_APIC_SPURIOUS = 0xFFu; struct idtr_t { @@ -99,19 +104,30 @@ struct idt public extern(C) void isr(ulong vector, ulong arg) { - if ((idt.EXCEPTION_LAPIC_TIMER <= vector) && (vector <= idt.EXCEPTION_LAPIC_LINT1)) + if ((vector >= idt.INT_APIC_BASE) && (vector < (idt.INT_APIC_BASE + idt.INT_APIC_COUNT))) { apic.isr(vector); } else { - console.clear(); - fb.clear(0xFF8000u); - klog.writefln("ISR %u, 0x%x", vector, arg); - __asm("cli", ""); - for (;;) + switch (vector) { - __asm("hlt", ""); + case idt.INT_APIC_TIMER: + case idt.INT_APIC_LINT0: + case idt.INT_APIC_LINT1: + case idt.INT_APIC_SPURIOUS: + apic.isr(vector); + break; + + default: + console.clear(); + fb.clear(0xFF8000u); + klog.writefln("ISR %u, 0x%x", vector, arg); + __asm("cli", ""); + for (;;) + { + __asm("hlt", ""); + } } } }