aboutsummaryrefslogtreecommitdiff
path: root/core/idt.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/idt.c')
-rw-r--r--core/idt.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/core/idt.c b/core/idt.c
new file mode 100644
index 0000000..a20eb69
--- /dev/null
+++ b/core/idt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 Robin Krahl <robin.krahl@ireas.org>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <garmos/arch.h>
+#include <garmos/gdt.h>
+#include <garmos/idt.h>
+#include <garmos/kernel.h>
+#include <garmos/types.h>
+
+#define IDT_GATE_COUNT 256
+
+struct idt_gate {
+ uint16_t handler_lo;
+ uint16_t gdt_offset;
+ uint8_t reserved;
+ uint8_t access;
+ uint16_t handler_hi;
+} __attribute__((packed));
+
+struct idt_gate idt[IDT_GATE_COUNT];
+
+struct idtp idtp = {
+ .limit = IDT_GATE_COUNT * sizeof(*idt) - 1,
+ .pointer = idt,
+};
+
+static void idt_set(uint8_t no, uint16_t offset, uint32_t handler,
+ uint8_t access, uint8_t flags);
+
+void idt_init(void)
+{
+ uint32_t offset = gdt_get_code_offset();
+ uint32_t i;
+ uint8_t *no = irqnos;
+ uint32_t *addr = irqhdls;
+
+ ker_dbg("Initializing IDT ...");
+
+ for (i = 0; i < IDT_GATE_COUNT; i++)
+ idt_set(i, offset, (uint32_t) &irqign, 0, 0xE);
+
+ for (; *no; no++, addr++) {
+ if (!*addr)
+ continue;
+ ker_dbg("Registerung IRQ handler ...");
+ idt_set(*no, offset, *addr, 0, 0xE);
+ }
+
+ idtset(idtp);
+}
+
+void idt_activate(void)
+{
+ idtact();
+}
+
+static void idt_set(uint8_t no, uint16_t offset, uint32_t handler,
+ uint8_t access, uint8_t flags)
+{
+ idt[no].handler_lo = handler & 0xFFFF;
+ idt[no].handler_hi = (handler >> 16) & 0xFFFF;
+ idt[no].gdt_offset = offset;
+ idt[no].reserved = 0;
+ idt[no].access = 0x80 | flags | ((access & 0x3) << 5);
+}