/** * APIC (Advanced Programmable Interrupt Controller) functionality. */ module hulk.apic; import hulk.klog; import hulk.hurl; import hulk.acpi; struct apic { static struct ApicRegister { public uint value; alias value this; private ubyte[12] _padding; } static struct ApicRegisters { ApicRegister[2] _reserved0; ApicRegister lapic_id; ApicRegister lapic_version; ApicRegister[4] _reserved1; ApicRegister task_priority; ApicRegister arbitration_priority; ApicRegister processor_priority; ApicRegister eoi; ApicRegister remote_read; ApicRegister logical_destination; ApicRegister destination_format; ApicRegister spurious_interrupt_vector; ApicRegister[8] in_service; ApicRegister[8] trigger_mode; ApicRegister[8] interrupt_request; ApicRegister error_status; ApicRegister[6] _reserved2; ApicRegister lvt_cmci; ApicRegister[2] interrupt_command; ApicRegister lvt_timer; ApicRegister lvt_thermal_sensor; ApicRegister lvt_performance_monitoring_counters; ApicRegister[2] lvt_lint; ApicRegister lvt_error; ApicRegister initial_count; ApicRegister current_count; ApicRegister[4] _reserved3; ApicRegister divide_configuration; } public static void initialize() { ApicRegisters * apic_registers = cast(ApicRegisters *)acpi.apic_address; hurl.map(cast(ulong)apic_registers, cast(ulong)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 = 0x70u; apic_registers.lvt_lint[0].value = 0x71u; apic_registers.lvt_lint[1].value = 0x72u; } }