idt_load:
Code: Select all
global idt_load
global enable_interrupts
section .text
idt_load:
cli
lidt [rdi]
ret
enable_interrupts:
sti
ret
Code: Select all
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
#define PIC_EOI 0x20
#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01
struct idt_entry idt[IDT_ENTRIES];
struct idt_ptr idtp;
extern void load_segment_selectors();
extern void idt_load(uint64_t);
static void idt_set_gate(int num, uint64_t base, uint16_t sel, uint8_t flags) {
idt[num].base_low = base & 0xFFFF;
idt[num].base_mid = (base >> 16) & 0xFFFF;
idt[num].base_high = (base >> 32) & 0xFFFFFFFF;
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
idt[num].reserved = 0;
}
static void pic_remap(int offset1, int offset2) {
uint8_t a1, a2;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
outb(PIC1_DATA, offset1);
outb(PIC2_DATA, offset2);
outb(PIC1_DATA, 4);
outb(PIC2_DATA, 2);
outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086);
outb(PIC1_DATA, a1); // Restore saved masks
outb(PIC2_DATA, a2);
}
void init_idt() {
idtp.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1;
idtp.base = (uint64_t)&idt;
for (int i = 0; i < IDT_ENTRIES; i++) {
idt_set_gate(i, 0, 0, 0);
}
idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E);
idt_set_gate(1, (uint64_t)isr1, 0x08, 0x8E);
idt_set_gate(8, (uint64_t)isr8, 0x08, 0x8E);
idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E);
idt_set_gate(14, (uint64_t)isr14, 0x08, 0x8E);
idt_set_gate(32, (uint64_t)isr32, 0x08, 0x8E);
idt_load((uint64_t)&idtp);
pic_remap(0x20, 0x28);
load_segment_selectors();
enable_interrupts();
Code: Select all
#define IDT_ENTRIES 256
struct idt_entry {
uint16_t base_low;
uint16_t sel;
uint8_t always0;
uint8_t flags;
uint16_t base_mid;
uint32_t base_high;
uint32_t reserved;
} __attribute__((packed));
struct idt_ptr {
uint16_t limit;
uint64_t base;
} __attribute__((packed));