aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-28 22:39:25 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-28 22:39:25 +0200
commitae4265ea5d77b68757af39d73fe47df1a3563b42 (patch)
tree7282e3d43c471b195bb5a4742ed911c7b7626dcb /src
parentFix interrupts causing exception 0xd (diff)
downloadkernel.cpp-ae4265ea5d77b68757af39d73fe47df1a3563b42.tar.xz
Add keyboard driver
Diffstat (limited to 'src')
-rw-r--r--src/idt.cc24
-rw-r--r--src/idt.h27
-rw-r--r--src/idt/interruptgate.cc10
-rw-r--r--src/idt/interrupthandler.cc14
-rw-r--r--src/kernel.cc6
-rw-r--r--src/makefile3
6 files changed, 73 insertions, 11 deletions
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<uint32_t>(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 <types.h>
+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<uint32_t>(handler) & 0xffff;
- offset_16_31 = (reinterpret_cast<uint32_t>(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<uint32_t>(handler) & 0xffff;
+ offset_16_31 = (reinterpret_cast<uint32_t>(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 <stdlib.h>
+#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 $@"