336af1c2ad
We have reorganized all the file directories that previously looked ugly as hell (cough cough arch/x86_64 cough) Now it looks much cleaner Signed-off-by: kaguya <vpshinomiya@protonmail.com>
109 lines
2.4 KiB
C
109 lines
2.4 KiB
C
#include "irq.h"
|
|
#include "i8259.h"
|
|
#include "arch/x86_64/cpu/io.h"
|
|
#include <stddef.h>
|
|
#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);
|
|
} |