summaryrefslogtreecommitdiff
path: root/kernel/idt.c
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2010-01-09 17:56:48 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2010-01-09 17:56:48 +0100
commit51a6ac67b761182d67eeb2f625d8476a2e79e632 (patch)
tree829809e758bfd3e0005dc0905ac9ad4cbf5f0ef9 /kernel/idt.c
parent5fe4102bc546b95d42d357f418f64c372d26b903 (diff)
Rudimentary interrupt handling.
Diffstat (limited to 'kernel/idt.c')
-rw-r--r--kernel/idt.c63
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)
+ );
+}