diff options
| author | Franklin Wei <frankhwei536@gmail.com> | 2015-02-01 16:40:00 -0500 |
|---|---|---|
| committer | Franklin Wei <frankhwei536@gmail.com> | 2015-02-01 16:40:00 -0500 |
| commit | 957b031689658c1ff67ea8a8a04640be9bec2d7d (patch) | |
| tree | 231c46b390d8d242461a0c571b8fbcf671e8c370 /kernel/irq.c | |
| parent | 439d724ce5939cab7a5c858d1829f212e01e0402 (diff) | |
| download | kappa-957b031689658c1ff67ea8a8a04640be9bec2d7d.zip kappa-957b031689658c1ff67ea8a8a04640be9bec2d7d.tar.gz kappa-957b031689658c1ff67ea8a8a04640be9bec2d7d.tar.bz2 kappa-957b031689658c1ff67ea8a8a04640be9bec2d7d.tar.xz | |
a lot of kernel work
Diffstat (limited to 'kernel/irq.c')
| -rw-r--r-- | kernel/irq.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/kernel/irq.c b/kernel/irq.c new file mode 100644 index 0000000..5f0a3f5 --- /dev/null +++ b/kernel/irq.c @@ -0,0 +1,84 @@ +#include <stdint.h> +#include <stddef.h> +#include <stdio.h> +#include "idt.h" +#include "io.h" +#include "irq.h" +#include "isr.h" + +static void *irq_callbacks[16] = { NULL }; + +void irq_set_handler(int irq, void (*handler)(struct regs_t*)) +{ + if(irq < 16 && irq >= 0) + irq_callbacks[irq] = handler; +} + +void irq_reset_handler(int irq) +{ + if(irq < 16 && irq >= 0) + irq_callbacks[irq] = NULL; +} + +void irq_remap(void) +{ + 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); +} + +void irq_init(void) +{ + irq_remap(); + + printf("irq_init()"); + + idt_set_gate(32, (uint32_t)_irq0, 0x08, 0x8E); + idt_set_gate(33, (uint32_t)_irq1, 0x08, 0x8E); + idt_set_gate(34, (uint32_t)_irq2, 0x08, 0x8E); + idt_set_gate(35, (uint32_t)_irq3, 0x08, 0x8E); + idt_set_gate(36, (uint32_t)_irq4, 0x08, 0x8E); + idt_set_gate(37, (uint32_t)_irq5, 0x08, 0x8E); + idt_set_gate(38, (uint32_t)_irq6, 0x08, 0x8E); + idt_set_gate(39, (uint32_t)_irq7, 0x08, 0x8E); + idt_set_gate(40, (uint32_t)_irq8, 0x08, 0x8E); + idt_set_gate(41, (uint32_t)_irq9, 0x08, 0x8E); + idt_set_gate(42, (uint32_t)_irq10, 0x08, 0x8E); + idt_set_gate(43, (uint32_t)_irq11, 0x08, 0x8E); + idt_set_gate(44, (uint32_t)_irq12, 0x08, 0x8E); + idt_set_gate(45, (uint32_t)_irq13, 0x08, 0x8E); + idt_set_gate(46, (uint32_t)_irq14, 0x08, 0x8E); + idt_set_gate(47, (uint32_t)_irq15, 0x08, 0x8E); +} + +void irq_handler(struct regs_t *regs) +{ + void (*handler)(struct regs_t *r); + + handler = irq_callbacks[regs->int_no - 32]; + + printf("IRQ called\n"); + + if(handler) + { + handler(regs); + } + + /* If the IDT entry that was invoked was greater than 40 + * (meaning IRQ8 - 15), then we need to send an EOI to + * the slave controller */ + if (regs->int_no >= 40) + { + outb(0xA0, 0x20); + } + + /* send an EOI to the master controller */ + outb(0x20, 0x20); +} |