1 #include <arch/x86/interrupts.h>
2 #include <hal/ioapic.h>
3 #include <hal/acpi/acpi.h>
6 #define IOAPIC_REG_SEL *((volatile uint32_t*)(IOAPIC_BASE_VADDR + IOAPIC_IOREGSEL))
7 #define IOAPIC_REG_WIN *((volatile uint32_t*)(IOAPIC_BASE_VADDR + IOAPIC_IOWIN))
10 ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq);
16 acpi_context* acpi_ctx = acpi_get_context();
18 // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic
19 // (Remarks IRQ 8 is pin INTIN8)
20 // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ
21 // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN mapping config.
23 // The ioapic_get_irq is to make sure we capture those overriden IRQs
25 // grab ourselves these irq numbers
26 uint8_t irq_rtc = ioapic_get_irq(acpi_ctx, PC_AT_IRQ_RTC);
27 uint8_t irq_kbd = ioapic_get_irq(acpi_ctx, PC_AT_IRQ_KBD);
29 // PC_AT_IRQ_RTC -> RTC_TIMER_IV, fixed, edge trigged, polarity=high, physical, APIC ID 0
30 ioapic_redirect(irq_rtc, RTC_TIMER_IV, 0, IOAPIC_DELMOD_FIXED);
32 ioapic_redirect(irq_kbd, PC_KBD_IV, 0, IOAPIC_DELMOD_FIXED);
36 ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq) {
40 acpi_intso_t* int_override = acpi_ctx->madt.irq_exception[old_irq];
41 return int_override ? (uint8_t)int_override->gsi : old_irq;
45 ioapic_write(uint8_t sel, uint32_t val) {
51 ioapic_read(uint8_t sel) {
53 return IOAPIC_REG_WIN;
57 ioapic_redirect(uint8_t irq, uint8_t vector, uint8_t dest, uint32_t flags) {
58 uint8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2;
61 ioapic_write(reg_sel, (vector | flags) & 0x1FFFF);
64 ioapic_write(reg_sel + 1, (dest << 24));