diff options
Diffstat (limited to 'src/idt.cc')
-rw-r--r-- | src/idt.cc | 30 |
1 files changed, 21 insertions, 9 deletions
@@ -1,22 +1,24 @@ #include "idt.h" #include <stdlib.h> #include "cpu/irq.h" +#include "cpu/registers.h" #include "ports.h" static_assert(sizeof(IDT::Pointer) == 6); +constexpr uint8_t irq_base = 0x20; static InterruptHandler* handlers[256] = {nullptr}; bool IDT::install(uint8_t irq, InterruptHandler* h) { - if (h != nullptr && handlers[irq] == nullptr) { - handlers[irq] = h; + if (h != nullptr && handlers[irq + irq_base] == nullptr) { + handlers[irq + irq_base] = h; return true; } return false; } bool IDT::uninstall(uint8_t irq, InterruptHandler* h) { - if (handlers[irq] == h) { - handlers[irq] = nullptr; + if (handlers[irq + irq_base] == h) { + handlers[irq + irq_base] = nullptr; return true; } return false; @@ -37,18 +39,28 @@ bool IDT::uninstall(uint8_t irq, InterruptHandler* h) { #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ #define ICW4_SFNM 0x10 /* Special fully nested (not) */ -extern "C" uint32_t handle_interrupt(uint8_t irq, uint32_t esp) { - if (handlers[irq] != nullptr) { - handlers[irq]->trigger(); +extern "C" void print_exception(cpu_state_t* r) { + printk("exception ", uhex{r->irq}, " error ", uhex{r->error}, '\n'); + asm volatile("cli"); + while (true) asm volatile("hlt"); + __builtin_unreachable(); +}; + +extern "C" uint32_t handle_interrupt(cpu_state_t* r) { + if (r->irq < irq_base) print_exception(r); + + if (handlers[r->irq] != nullptr) { + handlers[r->irq]->trigger(); } pic1_t pic1; pic1.write(0x20); - if (irq > 7) { + if (r->irq > 7 + irq_base) { pic2_t pic2; pic2.write(0x20); } - return esp; + + return reinterpret_cast<uint32_t>(r); }; IDT::IDT(const uint16_t selector) { |