From d49f9e32cd0f046c878d573e9d40a7b6dfc36c28 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 14 Dec 2022 19:40:22 -0500 Subject: [PATCH] dev checkpoint --- src/hulk/apic.d | 7 +++--- src/hulk/hulk.d | 2 ++ src/hulk/idt.d | 25 ++++++++++++++++------ src/hulk/rtc.d | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 src/hulk/rtc.d diff --git a/src/hulk/apic.d b/src/hulk/apic.d index 59d552e..0dcb877 100644 --- a/src/hulk/apic.d +++ b/src/hulk/apic.d @@ -64,9 +64,9 @@ struct apic /* 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.lvt_timer.value = idt.INT_LAPIC_TIMER | PERIODIC_MODE; + apic_registers.lvt_lint[0].value = idt.INT_LAPIC_LINT0; + apic_registers.lvt_lint[1].value = idt.INT_LAPIC_LINT1; apic_registers.divide_configuration.value = 3u; } @@ -77,6 +77,7 @@ struct apic public static void isr(ulong vector) { + klog.writefln("APIC ISR 0x%x", vector); eoi(); } } diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index f63eee9..b6300ac 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -20,6 +20,7 @@ import ldc.llvmasm; import hulk.pic; import hulk.acpi; import hulk.apic; +import hulk.rtc; extern extern(C) __gshared ubyte _hulk_bss_size; @@ -73,6 +74,7 @@ void hulk_start() pic.initialize(); acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys); apic.initialize(); + rtc.initialize(); sti(); for (;;) diff --git a/src/hulk/idt.d b/src/hulk/idt.d index 192f860..686119c 100644 --- a/src/hulk/idt.d +++ b/src/hulk/idt.d @@ -9,12 +9,16 @@ import hulk.fb; import hulk.console; import hulk.klog; import hulk.apic; +import hulk.rtc; 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; + /* IRQ 0 is interrupt 32 (0x20). */ + public static enum ulong INT_RTC = 0x28u; /* IRQ 8 */ + + public static enum ulong INT_LAPIC_TIMER = 0x70u; + public static enum ulong INT_LAPIC_LINT0 = 0x71u; + public static enum ulong INT_LAPIC_LINT1 = 0x72u; struct idtr_t { @@ -99,12 +103,19 @@ struct idt public extern(C) void isr(ulong vector, ulong arg) { - if ((idt.EXCEPTION_LAPIC_TIMER <= vector) && (vector <= idt.EXCEPTION_LAPIC_LINT1)) + switch (vector) { + case idt.INT_RTC: + rtc.isr(); + break; + + case idt.INT_LAPIC_TIMER: + case idt.INT_LAPIC_LINT0: + case idt.INT_LAPIC_LINT1: apic.isr(vector); - } - else - { + break; + + default: console.clear(); fb.clear(0xFF8000u); klog.writefln("ISR %u, 0x%x", vector, arg); diff --git a/src/hulk/rtc.d b/src/hulk/rtc.d new file mode 100644 index 0000000..a5a6ed1 --- /dev/null +++ b/src/hulk/rtc.d @@ -0,0 +1,57 @@ +/** + * RTC (Real-Time Clock) functionality. + */ +module hulk.rtc; + +import hulk.cpu; +import hulk.klog; + +struct rtc +{ + private enum ubyte PORT_SELECT = 0x70u; + private enum ubyte PORT_DATA = 0x71u; + + private enum ubyte DISABLE_NMI = 0x80u; + + private enum ubyte SR_A = 0xAu; + private enum ubyte SR_B = 0xBu; + private enum ubyte SR_C = 0xCu; + + private enum ubyte SR_B_ENABLE_IRQ = 0x40u; + + public static void initialize() + { + /* Enable IRQ 8 to receive RTC interrupts. */ + out8(PORT_SELECT, DISABLE_NMI | SR_B); + ubyte sr_b = in8(PORT_DATA); + out8(PORT_SELECT, DISABLE_NMI | SR_B); + out8(PORT_DATA, sr_b | SR_B_ENABLE_IRQ); + + out8(PORT_SELECT, DISABLE_NMI | SR_A); + klog.writefln("SR_A = 0x%x", in8(PORT_DATA)); + + /* Send EOI to enable more RTC interrupts and re-enable NMIs. */ + eoi(); + } + + private static void eoi() + { + /* Read from status register C to clear the interrupt. */ + out8(PORT_SELECT, SR_C); + in8(PORT_DATA); + } + + public static void isr() + { + static __gshared ulong count; + static __gshared ulong seconds; + klog.writefln("RTC ISR!"); + count++; + if ((count % 1024) == 0u) + { + seconds++; + klog.writefln("Seconds: %u", seconds); + } + eoi(); + } +}