diff options
author | dzwdz | 2023-01-25 21:49:14 +0100 |
---|---|---|
committer | dzwdz | 2023-01-25 21:49:14 +0100 |
commit | f9ce893e143a7c2356a0f2204afac1f37d3e54d2 (patch) | |
tree | e93e569328ea61b71e785a52964238dc032aeefd /src/kernel/arch/amd64 | |
parent | c24a9376b4a048a3f9408df2d47eaad367459bd7 (diff) |
kernel/irq: use a lookup table for irqs
Diffstat (limited to 'src/kernel/arch/amd64')
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 3 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.h | 1 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/ps2.c | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/rtl8139.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/serial.c | 4 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts.h (renamed from src/kernel/arch/amd64/interrupts/irq.h) | 7 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/idt.c | 9 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/irq.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 63 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.h | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/pci.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/time.c | 6 |
12 files changed, 48 insertions, 67 deletions
diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 32d0452..bc9a675 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -5,7 +5,7 @@ #include <kernel/arch/amd64/driver/ps2.h> #include <kernel/arch/amd64/driver/serial.h> #include <kernel/arch/amd64/driver/video.h> -#include <kernel/arch/amd64/interrupts/irq.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/pci.h> #include <kernel/arch/amd64/tty/tty.h> #include <kernel/arch/generic.h> @@ -37,6 +37,7 @@ void kmain_early(void *mbi) { idt_init(); kprintf("irq..."); irq_init(); + timer_init(); { kprintf("mem...\n"); diff --git a/src/kernel/arch/amd64/boot.h b/src/kernel/arch/amd64/boot.h index b68f52b..7c36cd3 100644 --- a/src/kernel/arch/amd64/boot.h +++ b/src/kernel/arch/amd64/boot.h @@ -16,6 +16,7 @@ enum gdt_segs { void kmain_early(void *mbi); void gdt_init(void); void idt_init(void); +void timer_init(void); /* used from asm */ extern struct lgdt_arg lgdt_arg; diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c index 971d7d1..4aa17ff 100644 --- a/src/kernel/arch/amd64/driver/ps2.c +++ b/src/kernel/arch/amd64/driver/ps2.c @@ -1,7 +1,7 @@ #include <camellia/errno.h> #include <kernel/arch/amd64/driver/ps2.h> #include <kernel/arch/amd64/driver/util.h> -#include <kernel/arch/amd64/interrupts/irq.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/panic.h> #include <kernel/proc.h> @@ -50,8 +50,12 @@ void ps2_init(void) { wait_out(); port_out8(PS2, 0xF4); /* packet streaming */ wait_in(); - if (port_in8(PS2) != 0xFA) /* check ACK */ + if (port_in8(PS2) != 0xFA) { /* check ACK */ panic_unimplemented(); + } + + irq_fn[IRQ_PS2KB] = ps2_irq; + irq_fn[IRQ_PS2MOUSE] = ps2_irq; vfs_root_register("/ps2", accept); } diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c index d0e4d90..bf8a67a 100644 --- a/src/kernel/arch/amd64/driver/rtl8139.c +++ b/src/kernel/arch/amd64/driver/rtl8139.c @@ -1,5 +1,6 @@ #include <kernel/arch/amd64/driver/rtl8139.h> #include <kernel/arch/amd64/driver/util.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/pci.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/panic.h> @@ -47,6 +48,7 @@ static void rx_irq_enable(bool v) { void rtl8139_init(uint32_t bdf) { if (iobase) panic_unimplemented(); /* multiple devices */ iobase = pcicfg_iobase(bdf); + irq_fn[IRQ_RTL8139] = rtl8139_irq; /* also includes the status, because i have only implemented w32 */ uint32_t cmd = pcicfg_r32(bdf, PCICFG_CMD); diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c index 5004c31..e8774b6 100644 --- a/src/kernel/arch/amd64/driver/serial.c +++ b/src/kernel/arch/amd64/driver/serial.c @@ -1,6 +1,6 @@ #include <kernel/arch/amd64/driver/serial.h> #include <kernel/arch/amd64/driver/util.h> -#include <kernel/arch/amd64/interrupts/irq.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/panic.h> #include <kernel/proc.h> @@ -25,6 +25,8 @@ static void serial_selftest(void) { } void serial_preinit(void) { + irq_fn[IRQ_COM1] = serial_irq; + // see https://www.sci.muni.cz/docs/pc/serport.txt // set baud rate divisor port_out8(COM1 + 3, 0b10000000); // enable DLAB diff --git a/src/kernel/arch/amd64/interrupts/irq.h b/src/kernel/arch/amd64/interrupts.h index f949824..262ea16 100644 --- a/src/kernel/arch/amd64/interrupts/irq.h +++ b/src/kernel/arch/amd64/interrupts.h @@ -2,13 +2,16 @@ #include <stdbool.h> #include <stdint.h> +#define IRQ_COM1 4 #define IRQ_IBASE 0x20 #define IRQ_PIT 0 #define IRQ_PS2KB 1 -#define IRQ_COM1 4 #define IRQ_PS2MOUSE 12 - #define IRQ_RTL8139 11 +extern void (*irq_fn[16])(void); +extern const char _isr_stubs; + void irq_init(void); void irq_eoi(uint8_t line); +void isr_stage3(uint8_t interrupt, uint64_t *stackframe); diff --git a/src/kernel/arch/amd64/interrupts/idt.c b/src/kernel/arch/amd64/interrupts/idt.c index 622ac1a..8f37cb9 100644 --- a/src/kernel/arch/amd64/interrupts/idt.c +++ b/src/kernel/arch/amd64/interrupts/idt.c @@ -1,5 +1,5 @@ #include <kernel/arch/amd64/boot.h> -#include <kernel/arch/amd64/interrupts/isr.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/panic.h> #include <stdbool.h> #include <stdint.h> @@ -30,7 +30,6 @@ static struct lidt_arg lidt_arg; static void idt_prepare(void); static void idt_load(void); -static void idt_test(void); static void idt_prepare(void) { @@ -55,13 +54,7 @@ static void idt_load(void) { asm("lidt (%0)" : : "r" (&lidt_arg) : "memory"); } -static void idt_test(void) { - asm("int $0x34" : : : "memory"); - assert(isr_test_interrupt_called); -} - void idt_init(void) { idt_prepare(); idt_load(); - idt_test(); } diff --git a/src/kernel/arch/amd64/interrupts/irq.c b/src/kernel/arch/amd64/interrupts/irq.c index 818ea8e..e900450 100644 --- a/src/kernel/arch/amd64/interrupts/irq.c +++ b/src/kernel/arch/amd64/interrupts/irq.c @@ -1,4 +1,4 @@ -#include <kernel/arch/amd64/interrupts/irq.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/port_io.h> #include <stdint.h> diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c index 1059530..ff00f2f 100644 --- a/src/kernel/arch/amd64/interrupts/isr.c +++ b/src/kernel/arch/amd64/interrupts/isr.c @@ -1,21 +1,15 @@ -#include <kernel/arch/amd64/driver/ps2.h> -#include <kernel/arch/amd64/driver/rtl8139.h> -#include <kernel/arch/amd64/driver/serial.h> -#include <kernel/arch/amd64/interrupts/irq.h> -#include <kernel/arch/amd64/interrupts/isr.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/port_io.h> -#include <kernel/arch/amd64/time.h> #include <kernel/arch/generic.h> -#include <kernel/mem/alloc.h> #include <kernel/panic.h> #include <kernel/proc.h> #include <stdbool.h> #include <stdint.h> -bool isr_test_interrupt_called = false; +void (*irq_fn[16])(void) = {0}; static void log_interrupt(int interrupt, uint64_t *stackframe) { - kprintf("interrupt %x, rip = k/%08x, cs 0x%x, code 0x%x\n", + kprintf("interrupt %d, rip = k/%08x, cs 0x%x, code 0x%x\n", interrupt, stackframe[0], stackframe[1], stackframe[-1]); if ((stackframe[1] & 0x3) == 0) { uint64_t *stack = (void*)stackframe[3]; @@ -28,42 +22,25 @@ static void log_interrupt(int interrupt, uint64_t *stackframe) { } } -void isr_stage3(int interrupt, uint64_t *stackframe) { - if (interrupt == 0xe || interrupt == 0xd) stackframe++; - switch (interrupt) { - case 0x34: - isr_test_interrupt_called = true; - return; - - case IRQ_IBASE + IRQ_PIT: - pit_irq(); - irq_eoi(IRQ_PIT); - return; - - case IRQ_IBASE + IRQ_PS2KB: - case IRQ_IBASE + IRQ_PS2MOUSE: - ps2_irq(); - irq_eoi(interrupt - IRQ_IBASE); - return; - - case IRQ_IBASE + IRQ_COM1: - serial_irq(); - irq_eoi(IRQ_COM1); +void isr_stage3(uint8_t interrupt, uint64_t *stackframe) { + uint8_t irqn = interrupt - IRQ_IBASE; + if (irqn < 16) { + if (irq_fn[irqn]) { + irq_fn[irqn](); + irq_eoi(irqn); return; + } + } - case IRQ_IBASE + IRQ_RTL8139: - rtl8139_irq(); - irq_eoi(interrupt - IRQ_IBASE); - return; + if (interrupt == 0xe || interrupt == 0xd) { + stackframe++; + } - default: - if ((stackframe[1] & 0x3) == 0) { - // mem_debugprint(); - log_interrupt(interrupt, stackframe); - cpu_halt(); - } else { - proc_kill(proc_cur, interrupt); - proc_switch_any(); - } + if ((stackframe[1] & 0x3) == 0) { /* in kernel */ + log_interrupt(interrupt, stackframe); + cpu_halt(); + } else { /* in user */ + proc_kill(proc_cur, interrupt); + proc_switch_any(); } } diff --git a/src/kernel/arch/amd64/interrupts/isr.h b/src/kernel/arch/amd64/interrupts/isr.h deleted file mode 100644 index 01f5236..0000000 --- a/src/kernel/arch/amd64/interrupts/isr.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include <stdbool.h> -#include <stdint.h> - -extern bool isr_test_interrupt_called; // used in the self-test in idt.c -extern const char _isr_stubs; - -void isr_stage3(int interrupt, uint64_t *stackframe); diff --git a/src/kernel/arch/amd64/pci.c b/src/kernel/arch/amd64/pci.c index 92e2697..23cd457 100644 --- a/src/kernel/arch/amd64/pci.c +++ b/src/kernel/arch/amd64/pci.c @@ -1,5 +1,5 @@ #include <kernel/arch/amd64/driver/rtl8139.h> -#include <kernel/arch/amd64/interrupts/irq.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/pci.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/arch/generic.h> diff --git a/src/kernel/arch/amd64/time.c b/src/kernel/arch/amd64/time.c index 0e40521..aa7603c 100644 --- a/src/kernel/arch/amd64/time.c +++ b/src/kernel/arch/amd64/time.c @@ -1,3 +1,5 @@ +#include <kernel/arch/amd64/boot.h> +#include <kernel/arch/amd64/interrupts.h> #include <kernel/arch/amd64/time.h> #include <kernel/panic.h> #include <kernel/proc.h> @@ -48,3 +50,7 @@ void timer_deschedule(Proc *p) { update_goal(); } + +void timer_init(void) { + irq_fn[IRQ_PIT] = pit_irq; +} |