From 05b9ca73793047e795e46a2ae13db02c34b8a7c3 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 6 Mar 2017 02:52:05 +0100 Subject: idt: add interruption handling The Interruption Descriptor Table (IDT) is implemented in idt.{c,h} as part of the core, but the setup and activation of the IDT and the registration of specific interruption request handlers is part of arch.{c,h}. The request handlers are implemented in idt.s and delegate to kernel_handle_interrupt. --- core/idt.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core/idt.c (limited to 'core/idt.c') 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 + * + * 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 +#include +#include +#include +#include + +#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); +} -- cgit v1.2.1