Handle all APIC IRQ redirects specified in MADT
This commit is contained in:
parent
31bf82e2ae
commit
f2839cdd0f
@ -17,7 +17,7 @@ struct Apic
|
||||
private enum DEFAULT_IO_APIC_ADDRESS = 0xFEC0_0000u;
|
||||
private enum uint PERIODIC_MODE = 0x2_0000u;
|
||||
|
||||
private enum ulong IRQ_PIT = 2u;
|
||||
private enum ulong IRQ_PIT = 0u;
|
||||
private enum ulong IRQ_RTC = 8u;
|
||||
|
||||
/**
|
||||
@ -180,6 +180,14 @@ struct Apic
|
||||
|
||||
case Entry.IO_APIC_INTERRUPT_SOURCE_OVERRIDE:
|
||||
Entry2 * e = cast(Entry2 *)entry;
|
||||
if (e.global_system_interrupt < Idt.INT_APIC_COUNT)
|
||||
{
|
||||
irq_redirects[e.irq_source] = cast(ubyte)e.global_system_interrupt;
|
||||
}
|
||||
else
|
||||
{
|
||||
Klog.writefln("Warning: unexpected interrupt source override global system interrupt value: %u", e.global_system_interrupt);
|
||||
}
|
||||
if (DEBUG)
|
||||
{
|
||||
Klog.writefln(" Bus %u IRQ %u GSI %u Flags: 0x%x",
|
||||
@ -296,8 +304,11 @@ struct Apic
|
||||
ApicRegister data;
|
||||
}
|
||||
|
||||
alias ISRHandler = void function();
|
||||
private static __gshared ApicRegisters * apic_registers;
|
||||
private static __gshared IoApicRegisters * io_apic_registers;
|
||||
private static __gshared ISRHandler[Idt.INT_APIC_COUNT] irq_handlers;
|
||||
private static __gshared ubyte[Idt.INT_APIC_COUNT] irq_redirects;
|
||||
|
||||
/**
|
||||
* Initialize APIC.
|
||||
@ -306,6 +317,10 @@ struct Apic
|
||||
{
|
||||
Klog.writefln("\a3Initializing APIC");
|
||||
io_apic_registers = cast(IoApicRegisters *)DEFAULT_IO_APIC_ADDRESS;
|
||||
for (ubyte i = 0u; i < Idt.INT_APIC_COUNT; i++)
|
||||
{
|
||||
irq_redirects[i] = i;
|
||||
}
|
||||
MADT * madt = cast(MADT *)Acpi.get_table("APIC");
|
||||
madt.scan();
|
||||
Klog.writefln("APIC found at %p", apic_registers);
|
||||
@ -321,21 +336,23 @@ struct Apic
|
||||
apic_registers.lvt_lint[0].value = Idt.INT_APIC_LINT0;
|
||||
apic_registers.lvt_lint[1].value = Idt.INT_APIC_LINT1;
|
||||
/* Enable PIT interrupt. */
|
||||
configure_io_apic_irq(IRQ_PIT, Idt.INT_APIC_BASE + IRQ_PIT);
|
||||
configure_io_apic_irq(IRQ_PIT, &Pit.isr);
|
||||
/* Enable RTC interrupt. */
|
||||
configure_io_apic_irq(IRQ_RTC, Idt.INT_APIC_BASE + IRQ_RTC);
|
||||
configure_io_apic_irq(IRQ_RTC, &Rtc.isr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure routing for an I/O APIC IRQ.
|
||||
*/
|
||||
private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id)
|
||||
private static void configure_io_apic_irq(size_t orig_irq, ISRHandler isr_handler)
|
||||
{
|
||||
ulong entry = interrupt_id;
|
||||
size_t io_apic_irq = irq_redirects[orig_irq];
|
||||
ulong entry = Idt.INT_APIC_BASE + io_apic_irq;
|
||||
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;
|
||||
irq_handlers[io_apic_irq] = isr_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,19 +368,14 @@ struct Apic
|
||||
*/
|
||||
public static void isr(ulong vector)
|
||||
{
|
||||
switch (vector)
|
||||
ulong io_apic_irq = vector - Idt.INT_APIC_BASE;
|
||||
if ((io_apic_irq < Idt.INT_APIC_COUNT) && (irq_handlers[io_apic_irq] != null))
|
||||
{
|
||||
irq_handlers[io_apic_irq]();
|
||||
}
|
||||
else
|
||||
{
|
||||
case Idt.INT_APIC_BASE + IRQ_PIT:
|
||||
Pit.isr();
|
||||
break;
|
||||
|
||||
case Idt.INT_APIC_BASE + IRQ_RTC:
|
||||
Rtc.isr();
|
||||
break;
|
||||
|
||||
default:
|
||||
Klog.writefln("Unhandled APIC ISR %u", vector);
|
||||
break;
|
||||
}
|
||||
eoi();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user