Route I/O APIC interrupts, enable RTC tick interrupt
This commit is contained in:
parent
9adc248225
commit
4081a220ef
@ -7,11 +7,14 @@ import hulk.klog;
|
|||||||
import hulk.hurl;
|
import hulk.hurl;
|
||||||
import hulk.acpi;
|
import hulk.acpi;
|
||||||
import hulk.idt;
|
import hulk.idt;
|
||||||
|
import hulk.rtc;
|
||||||
|
|
||||||
struct apic
|
struct apic
|
||||||
{
|
{
|
||||||
private enum uint PERIODIC_MODE = 0x2_0000u;
|
private enum uint PERIODIC_MODE = 0x2_0000u;
|
||||||
|
|
||||||
|
private enum ulong IRQ_RTC = 8u;
|
||||||
|
|
||||||
static struct ApicRegister
|
static struct ApicRegister
|
||||||
{
|
{
|
||||||
public uint value;
|
public uint value;
|
||||||
@ -52,31 +55,60 @@ struct apic
|
|||||||
ApicRegister divide_configuration;
|
ApicRegister divide_configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct IoApicRegisters
|
||||||
|
{
|
||||||
|
ApicRegister address;
|
||||||
|
ApicRegister data;
|
||||||
|
}
|
||||||
|
|
||||||
private static __gshared ApicRegisters * apic_registers;
|
private static __gshared ApicRegisters * apic_registers;
|
||||||
|
private static __gshared IoApicRegisters * io_apic_registers;
|
||||||
|
|
||||||
public static void initialize()
|
public static void initialize()
|
||||||
{
|
{
|
||||||
apic_registers = cast(ApicRegisters *)acpi.apic_address;
|
apic_registers = cast(ApicRegisters *)acpi.apic_address;
|
||||||
|
io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u;
|
||||||
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
||||||
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
|
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 ID: 0x%08x", apic_registers.lapic_id.value);
|
||||||
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.value);
|
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.value);
|
||||||
/* Enable local APIC to receive interrupts and set spurious interrupt
|
/* Enable local APIC to receive interrupts and set spurious interrupt
|
||||||
* vector to 0xFF. */
|
* vector to 0xFF. */
|
||||||
apic_registers.spurious_interrupt_vector.value = 0x1FFu;
|
apic_registers.spurious_interrupt_vector.value = 0x100u | idt.INT_APIC_SPURIOUS;
|
||||||
apic_registers.lvt_timer.value = idt.EXCEPTION_LAPIC_TIMER | PERIODIC_MODE;
|
apic_registers.lvt_timer.value = idt.INT_APIC_TIMER;
|
||||||
apic_registers.lvt_lint[0].value = idt.EXCEPTION_LAPIC_LINT0;
|
apic_registers.lvt_lint[0].value = idt.INT_APIC_LINT0;
|
||||||
apic_registers.lvt_lint[1].value = idt.EXCEPTION_LAPIC_LINT1;
|
apic_registers.lvt_lint[1].value = idt.INT_APIC_LINT1;
|
||||||
apic_registers.divide_configuration.value = 3u;
|
/* 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;
|
apic_registers.eoi.value = 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void isr(ulong vector)
|
public static void isr(ulong vector)
|
||||||
{
|
{
|
||||||
|
switch (vector)
|
||||||
|
{
|
||||||
|
case idt.INT_APIC_BASE + IRQ_RTC:
|
||||||
|
rtc.isr();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
eoi();
|
eoi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,14 @@ import hulk.apic;
|
|||||||
|
|
||||||
struct idt
|
struct idt
|
||||||
{
|
{
|
||||||
public static enum ulong EXCEPTION_LAPIC_TIMER = 0x70u;
|
/* The I/O APIC is configured to map IRQ 0 to interrupt 64 (0x40). */
|
||||||
public static enum ulong EXCEPTION_LAPIC_LINT0 = 0x71u;
|
public static enum ulong INT_APIC_BASE = 0x40u; /* IRQ 0 */
|
||||||
public static enum ulong EXCEPTION_LAPIC_LINT1 = 0x72u;
|
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
|
struct idtr_t
|
||||||
{
|
{
|
||||||
@ -99,19 +104,30 @@ struct idt
|
|||||||
|
|
||||||
public extern(C) void isr(ulong vector, ulong arg)
|
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);
|
apic.isr(vector);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.clear();
|
switch (vector)
|
||||||
fb.clear(0xFF8000u);
|
|
||||||
klog.writefln("ISR %u, 0x%x", vector, arg);
|
|
||||||
__asm("cli", "");
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
__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", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user