#include "irq.h" #include "i8259.h" #include "arch/x86_64/cpu/io.h" #include #include "libk/arrays.h" #include "libk/stdio.h" #include "libk/debug.h" #include "apic.h" #include "ioapic.h" #define PIC_REMAP_OFFSET 0x20 #define MODULE "PIC" IRQHandler g_IRQHandlers[16]; static IRQHandler g_APICHandlers[256]; const PICDriver* g_Driver = NULL; extern bool g_IOAPIC; void x86_64_IRQ_Handler(Registers *regs) { int irq = regs->interrupt - PIC_REMAP_OFFSET; if (g_IRQHandlers[irq] != NULL) { // handle IRQ g_IRQHandlers[irq](regs); } else { log_warn(MODULE, "Unhandled IRQ %d...", irq); } g_Driver->SendEndOfInterrupt(irq); } void x86_64_APIC_IRQ_Handler(Registers* regs) { uint8_t vector = regs->interrupt; if (g_APICHandlers[vector] != NULL) { g_APICHandlers[vector](regs); } else { log_warn("APIC", "Unhandled vector 0x%02x", vector); } lapic_eoi(); // ← This is the key difference from PIC! } void x86_64_IRQ_Initialize(void) { const PICDriver* drivers[] = { i8259_GetDriver(), }; for (int i = 0; i < SIZE(drivers); i++) { if (drivers[i]->Probe()) { g_Driver = drivers[i]; } } if (g_Driver == NULL) { log_warn(MODULE, "No PIC found!"); return; } log_info(MODULE, "Found %s PIC.", g_Driver->Name); g_Driver->Initialize(PIC_REMAP_OFFSET, PIC_REMAP_OFFSET + 8, false); // register ISR handlers for each of the 16 irq lines for (int i = 0; i < 16; i++) x86_64_ISR_RegisterHandler(PIC_REMAP_OFFSET + i, x86_64_IRQ_Handler); g_Driver->Unmask(0); } void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler) { g_IRQHandlers[irq] = handler; } void x86_64_APIC_IRQ_RegisterHandler(uint8_t vector, IRQHandler handler) { if (vector < 32) { printf("[APIC] Warning: vector %u is in reserved range!\n", vector); } g_APICHandlers[vector] = handler; x86_64_ISR_RegisterHandler(vector, x86_64_APIC_IRQ_Handler); } void x86_64_APIC_IRQ_RedirectAndRegister(uint8_t isa_irq, uint8_t vector, IRQHandler handler) { x86_64_APIC_IRQ_RegisterHandler(vector, handler); irq_redirect_to_apic(isa_irq, vector, lapic_id(), false); } void x86_64_IRQ_Unmask(int irq) { if (g_Driver) g_Driver->Unmask(irq); }