diff options
-rw-r--r-- | arch/i386/include/kernel/asm.h | 4 | ||||
-rw-r--r-- | arch/i386/include/kernel/syscall.h | 2 | ||||
-rw-r--r-- | arch/i386/kernel/idt.c | 27 | ||||
-rw-r--r-- | arch/i386/kernel/syscall.c | 2 | ||||
-rw-r--r-- | include/kernel/interrupt.h | 13 | ||||
-rw-r--r-- | kernel/interrupt.c | 20 |
6 files changed, 50 insertions, 18 deletions
diff --git a/arch/i386/include/kernel/asm.h b/arch/i386/include/kernel/asm.h index d692917..cc570c5 100644 --- a/arch/i386/include/kernel/asm.h +++ b/arch/i386/include/kernel/asm.h @@ -9,6 +9,8 @@ #define COM_PORT 0x3F8 +#define MAX_ISR 256 + struct regs { uint32_t eax; uint32_t ebx; @@ -95,7 +97,7 @@ void irq_stub_13(void); void irq_stub_14(void); void irq_stub_15(void); -void syscall_stub(void); +void isr_stub_128(void); void aquire_lock(int *lock); void release_lock(int *lock); diff --git a/arch/i386/include/kernel/syscall.h b/arch/i386/include/kernel/syscall.h index a689183..a657527 100644 --- a/arch/i386/include/kernel/syscall.h +++ b/arch/i386/include/kernel/syscall.h @@ -29,6 +29,6 @@ #define SYS_HALT 87 #define SYS_REBOOT 88 -int handle_syscall(struct isr_frame *frame); +void handle_syscall(struct isr_frame *frame); #endif diff --git a/arch/i386/kernel/idt.c b/arch/i386/kernel/idt.c index 1a06631..a178801 100644 --- a/arch/i386/kernel/idt.c +++ b/arch/i386/kernel/idt.c @@ -1,4 +1,5 @@ #include <kernel/idt.h> +#include <kernel/interrupt.h> #include <kernel/syscall.h> #include <kernel/panic.h> #include <kernel/gdt.h> @@ -67,20 +68,10 @@ void exception_handler(struct isr_frame *frame) { } } -void interrupt_handler(struct isr_frame frame) { - if (frame.isr_vector < 32) { - exception_handler(&frame); - } else if (frame.isr_vector < 48) { - irq_dispatch(&frame); - } else { - switch (frame.isr_vector) { - case 0x80: - handle_syscall(&frame); - break; - default: - panic("Unmapped interrupt"); - } - } +void generic_handler(struct isr_frame *frame) { + kprintf("No handler registered for IRQ %d\n", frame->isr_vector); + if (frame->isr_vector > 32 && frame->isr_vector < 48) + pic_eoi(frame->isr_vector-32); } void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) { @@ -96,6 +87,12 @@ void idt_install(void) { idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1; idtr.base = (uint32_t)idt; + for (int i = 0; i < 32; i++) + register_isr_handler(i, exception_handler); + for (int i = 32; i < 224; i++) + register_isr_handler(i, generic_handler); + register_isr_handler(0x80, handle_syscall); + idt_set_gate(0x0, isr_stub_0, 0x08, IDT_EXCEPTION); idt_set_gate(0x1, isr_stub_1, 0x08, IDT_EXCEPTION); idt_set_gate(0x2, isr_stub_2, 0x08, IDT_EXCEPTION); @@ -146,7 +143,7 @@ void idt_install(void) { idt_set_gate(0x2E, irq_stub_14, 0x08, IDT_INTERRUPT); idt_set_gate(0x2F, irq_stub_15, 0x08, IDT_INTERRUPT); - idt_set_gate(0x80, syscall_stub, 0x08, IDT_INTERRUPT); + idt_set_gate(0x80, isr_stub_128, 0x08, IDT_INTERRUPT); __asm__ volatile("lidt %0" : : "memory"(idtr)); } diff --git a/arch/i386/kernel/syscall.c b/arch/i386/kernel/syscall.c index e8b69a2..200af4f 100644 --- a/arch/i386/kernel/syscall.c +++ b/arch/i386/kernel/syscall.c @@ -10,7 +10,7 @@ void sys_read(struct isr_frame *frame) { void sys_write(struct isr_frame *frame) { } -int handle_syscall(struct isr_frame *frame) { +void handle_syscall(struct isr_frame *frame) { switch (frame->eax) { case SYS_READ: sys_read(frame); diff --git a/include/kernel/interrupt.h b/include/kernel/interrupt.h new file mode 100644 index 0000000..b707fe7 --- /dev/null +++ b/include/kernel/interrupt.h @@ -0,0 +1,13 @@ +#ifndef KERNEL_INTERRUPT_H +#define KERNEL_INTERRUPT_H + +#include <kernel/asm.h> +#include <stdint.h> +#include <stddef.h> + +void register_isr_handler(unsigned int isr, void (*handler)(struct isr_frame *frame)); +void clear_isr_handler(unsigned int isr); + +void isr_dispatch(struct isr_frame frame); + +#endif diff --git a/kernel/interrupt.c b/kernel/interrupt.c new file mode 100644 index 0000000..9639aea --- /dev/null +++ b/kernel/interrupt.c @@ -0,0 +1,20 @@ +#include <kernel/interrupt.h> +#include <kernel/asm.h> + +static void (*isr_handlers[MAX_ISR])(struct isr_frame *frame); + +void register_isr_handler(unsigned int isr, void (*handler)(struct isr_frame *frame)) { + if (isr > MAX_ISR) + panic("Attempted to set non-existant interrupt vector"); + isr_handlers[isr] = handler; +} + +void clear_isr_handler(unsigned int isr) { + if (isr > MAX_ISR) + panic("Attempted to clear non-existant interrupt vector"); + isr_handlers[isr] = NULL; +} + +void isr_dispatch(struct isr_frame frame) { + (*isr_handlers[frame.isr_vector])(&frame); +} |