orion/src/idt.c

80 lines
1.8 KiB
C

#include <idt.h>
#include <asm.h>
#include <stdio.h>
static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance
static idtr_t idtr;
isr_t interrupt_handlers[256];
void isr_handler(registers_t regs) {
if (interrupt_handlers[regs.int_no] != 0) {
isr_t handler = interrupt_handlers[regs.int_no];
handler(regs);
} else {
kprintf("Unhandled interrupt: %d\n", regs.int_no);
}
}
void irq_handler(registers_t regs) {
if (regs.int_no >= 40) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
if (interrupt_handlers[regs.int_no] != 0) {
isr_t handler = interrupt_handlers[regs.int_no];
handler(regs);
} else {
kprintf("Unhandled IRQ interrupt: %d\n", regs.int_no);
}
}
void register_interrupt_handler(uint8_t n, isr_t handler) {
interrupt_handlers[n] = handler;
}
void idt_set_gate(uint8_t num, uint32_t base, uint8_t flags) {
idt[num].isr_low = base & 0xFFFF;
idt[num].isr_high = (base >> 16) & 0xFFFF;
idt[num].kernel_cs = 0x08;
idt[num].reserved = 0;
idt[num].attributes = flags;
}
extern void* isr_stub_table[];
extern void* irq_stub_table[];
void idt_init() {
idtr.base = (uintptr_t)&idt;
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
for (uint8_t vector = 0; vector < 32; vector++) {
idt_set_gate(vector, (uint32_t)isr_stub_table[vector], 0x8E);
}
extern void idt_flush(uint32_t);
idt_flush((uint32_t)&idtr);
// Remap the irq table.
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
for (uint8_t vector = 32; vector < 48; vector++) {
idt_set_gate(vector, (uint32_t)irq_stub_table[vector], 0x8E);
}
outb(0x21,0xfc);
outb(0xa1,0xff);
__asm__("sti");
}