diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2010-01-09 17:56:48 +0100 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2010-01-09 17:56:48 +0100 |
commit | 51a6ac67b761182d67eeb2f625d8476a2e79e632 (patch) | |
tree | 829809e758bfd3e0005dc0905ac9ad4cbf5f0ef9 /kernel/idt.c | |
parent | 5fe4102bc546b95d42d357f418f64c372d26b903 (diff) |
Rudimentary interrupt handling.
Diffstat (limited to 'kernel/idt.c')
-rw-r--r-- | kernel/idt.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/kernel/idt.c b/kernel/idt.c new file mode 100644 index 0000000..3fdc3dc --- /dev/null +++ b/kernel/idt.c @@ -0,0 +1,63 @@ +#include "idt.h" + +#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port)); + +#define isr_panic(num) void isr_ ## num(); \ +asm( \ + ".globl isr_" #num "\n" \ + "isr_" #num ":\n" \ + "push $" #num "\n" \ + "call panic\n" \ + "iret\n" \ +) + +char* panic_msg[] = { + [0] = "Divide error.", + [8] = "Double fault.", + [14] = "Page fault." +}; + +isr_panic(0); +isr_panic(8); +isr_panic(14); + +void panic(uint32_t num) { + char* str = panic_msg[num]; + while(*str) { + outb(0x3f8, *str++); + } + outb(0x3f8, '\r'); + outb(0x3f8, '\n'); + asm volatile( + "cli\n" + "hlt\n" + ); + while(1); +} + +idt_entry idt[] = { + {.base_low = 1}, // Keep IDT in .data. + [1 ... 255] = idt_entry_null +}; + +idt_ptr idtr = { + .base = idt, + .limit = sizeof(idt) - 1 +}; + +void idt_set_gate(uint8_t num, uint32_t base, uint16_t segment, uint16_t flags) { + idt[num].base_low = base & 0xffff; + idt[num].base_high = base >> 16 & 0xffff; + idt[num].segment = segment; + idt[num].flags = flags; +} + +void idt_init() { + idt_set_gate(0, (uint32_t)isr_0, 0x08, 0x8e00); + idt_set_gate(8, (uint32_t)isr_8, 0x08, 0x8e00); + idt_set_gate(14, (uint32_t)isr_14, 0x08, 0x8e00); + asm volatile( + "lidt (%0)\n" + : : "r" (&idtr) + ); +} |