From ae4265ea5d77b68757af39d73fe47df1a3563b42 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 28 Feb 2021 22:39:25 +0200 Subject: Add keyboard driver --- src/idt.cc | 24 +++++++++++++++++++++--- src/idt.h | 27 ++++++++++++++++++++------- src/idt/interruptgate.cc | 10 ++++++++++ src/idt/interrupthandler.cc | 14 ++++++++++++++ src/kernel.cc | 6 ++++++ src/makefile | 3 ++- 6 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 src/idt/interruptgate.cc create mode 100644 src/idt/interrupthandler.cc (limited to 'src') diff --git a/src/idt.cc b/src/idt.cc index fefe53e..68ae260 100644 --- a/src/idt.cc +++ b/src/idt.cc @@ -4,7 +4,23 @@ #include "ports.h" static_assert(sizeof(IDT::Pointer) == 6); -static_assert(sizeof(IDT::Entry) == 8); // size of IDT::Entry in protected mode is 64 bits + +static InterruptHandler* handlers[256] = {nullptr}; + +bool IDT::install(uint8_t irq, InterruptHandler* h) { + if (h != nullptr && handlers[irq] == nullptr) { + handlers[irq] = h; + return true; + } + return false; +} +bool IDT::uninstall(uint8_t irq, InterruptHandler* h) { + if (handlers[irq] == h) { + handlers[irq] = nullptr; + return true; + } + return false; +} /* reinitialize the PIC controllers, giving them specified vector offsets rather than 8h and 70h, as configured by default */ @@ -22,7 +38,10 @@ static_assert(sizeof(IDT::Entry) == 8); // size of IDT::Entry in protected mode #define ICW4_SFNM 0x10 /* Special fully nested (not) */ extern "C" uint32_t handle_interrupt(uint8_t irq, uint32_t esp) { - printk("interrupt ", uhex{irq}, '\n'); + if (handlers[irq] != nullptr) { + handlers[irq]->trigger(); + } + pic1_t pic1; pic1.write(0x20); if (irq > 7) { @@ -91,7 +110,6 @@ IDT::IDT(const uint16_t selector) { Pointer ptr{.limit = sizeof(table), .base = reinterpret_cast(table)}; asm volatile("lidt %0" : : "m"(ptr)); - asm volatile("sti"); printk("IDT installed at ", uhex{ptr.base}, '\n'); } diff --git a/src/idt.h b/src/idt.h index bc71f05..3a9848f 100644 --- a/src/idt.h +++ b/src/idt.h @@ -2,7 +2,21 @@ #include +class InterruptHandler { +private: + const uint8_t m_irq; + +protected: + InterruptHandler(uint8_t irq); + ~InterruptHandler(); + +public: + virtual void trigger(); +}; + class IDT { + friend class InterruptHandler; + public: struct Pointer { uint16_t limit; @@ -19,24 +33,23 @@ public: class Entry { public: constexpr Entry() = default; - Entry(void (*handler)(), uint16_t select, InterruptType t) { - offset_0_15 = reinterpret_cast(handler) & 0xffff; - offset_16_31 = (reinterpret_cast(handler) >> 16) & 0xffff; - selector = select; - type = t; - } + Entry(void (*handler)(), uint16_t select, InterruptType t); private: uint16_t offset_0_15 = 0; // 0-15 offset in the segment uint16_t selector = 0; // 16-31 selector of the code segment [[maybe_unused]] uint8_t null = 0; // 32-39 unused in protected mode InterruptType type = Null; // 40-43 type - uint16_t offset_16_31 = 0; // 48-63 offset high + uint16_t offset_16_31 = 0; // 48-63 offset high } __attribute__((packed)); IDT(const uint16_t selector); + void enable() { asm volatile("sti"); } private: Entry table[256]; + + static bool install(uint8_t, InterruptHandler*); + static bool uninstall(uint8_t, InterruptHandler*); }; diff --git a/src/idt/interruptgate.cc b/src/idt/interruptgate.cc new file mode 100644 index 0000000..0dbcce2 --- /dev/null +++ b/src/idt/interruptgate.cc @@ -0,0 +1,10 @@ +#include "../idt.h" + +static_assert(sizeof(IDT::Entry) == 8); // size of IDT::Entry in protected mode is 64 bits + +IDT::Entry::Entry(void (*handler)(), uint16_t select, IDT::InterruptType t) { + offset_0_15 = reinterpret_cast(handler) & 0xffff; + offset_16_31 = (reinterpret_cast(handler) >> 16) & 0xffff; + selector = select; + type = t; +} diff --git a/src/idt/interrupthandler.cc b/src/idt/interrupthandler.cc new file mode 100644 index 0000000..7af830b --- /dev/null +++ b/src/idt/interrupthandler.cc @@ -0,0 +1,14 @@ +#include +#include "../idt.h" + +InterruptHandler::InterruptHandler(uint8_t irq) : m_irq(irq) { + IDT::install(m_irq, this); +} + +InterruptHandler::~InterruptHandler() { + IDT::uninstall(m_irq, this); +} + +void InterruptHandler::trigger() { + printk("Unhandled interrupt ", uhex{m_irq}, '\n'); +} diff --git a/src/kernel.cc b/src/kernel.cc index 6bfb021..ff8e6bd 100644 --- a/src/kernel.cc +++ b/src/kernel.cc @@ -15,6 +15,8 @@ #include "idt.h" #include "serial.h" +#include "keyboard.h" + #include "hardware.h" typedef void (*constructor)(); @@ -48,6 +50,10 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m GDT gdt; IDT idt{gdt.codeDescriptor()}; + Keyboard kb; + + idt.enable(); + while (true) asm volatile("hlt"); } } // extern "C" diff --git a/src/makefile b/src/makefile index 8b21640..dda24af 100644 --- a/src/makefile +++ b/src/makefile @@ -7,7 +7,8 @@ CXX_OBJ += src/kernel.o \ src/memory.o \ src/gdt.o \ src/gdt/segmentdescriptor.o \ - src/idt.o + src/idt.o \ + src/idt/interruptgate.o src/idt/interrupthandler.o src/cpu/irq.h: $(OBJ_DIR)/src/cpu/exceptions.o $(OBJ_DIR)/src/cpu/interrupts.o @echo " GEN $@" -- cgit v1.2.1