diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2023-12-10 18:07:35 +0100 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2023-12-10 18:07:35 +0100 |
| commit | 4210c4ae384753825e10c5ea4ad1e99e9bba2c1f (patch) | |
| tree | 4406242c6b6e6eb4658c1bc3cbe927b378f11dbc /stage3 | |
| parent | bc00cb0649167958aed2f481580af3b4f21043b0 (diff) | |
| download | cuddles-4210c4ae384753825e10c5ea4ad1e99e9bba2c1f.tar.xz | |
handle IRQs
Diffstat (limited to 'stage3')
| -rw-r--r-- | stage3/interrupts.c | 5 | ||||
| -rw-r--r-- | stage3/main.c | 5 | ||||
| -rw-r--r-- | stage3/pic.c | 92 | ||||
| -rw-r--r-- | stage3/pic.h | 31 |
4 files changed, 132 insertions, 1 deletions
diff --git a/stage3/interrupts.c b/stage3/interrupts.c index fa4e59d..e7b819e 100644 --- a/stage3/interrupts.c +++ b/stage3/interrupts.c @@ -2,6 +2,7 @@ #include "halt.h" #include "font.h" #include "heap.h" +#include "pic.h" extern u64 idt_entries[256]; // isr.asm @@ -91,6 +92,10 @@ void interrupt_handler(interrupt_frame *frame) dump_frame(frame); halt(); + } else if (frame->which-32 < 16) { + u64 irq = frame->which-32; + print("IRQ "); print_num(irq, 10, 0); print("\n"); + ack_irq(irq); } else { print("Spurious Interrupt "); print_num(frame->which, 10, 0); print("\n"); dump_frame(frame); diff --git a/stage3/main.c b/stage3/main.c index 9ddcacf..630379b 100644 --- a/stage3/main.c +++ b/stage3/main.c @@ -6,6 +6,7 @@ #include "font.h" #include "letters.h" #include "interrupts.h" +#include "pic.h" void init() { @@ -67,8 +68,10 @@ void init() } init_interrupts(); + pic_init(); - int a = 1/0; + unmask_irq(IRQ_PIT); + enable_irqs(); halt(); } diff --git a/stage3/pic.c b/stage3/pic.c new file mode 100644 index 0000000..726a6da --- /dev/null +++ b/stage3/pic.c @@ -0,0 +1,92 @@ +#include "pic.h" +#include "io.h" + +void disable_irqs() +{ + asm volatile("cli"); +} + +void enable_irqs() +{ + asm volatile("sti"); +} + +void ack_irq(u8 lane) +{ + if (lane >= 8) + outb(IO_PIC2_CTRL, 1 << 5); + + outb(IO_PIC1_CTRL, 1 << 5); +} + +void unmask_irq(u8 lane) +{ + u8 port = IO_PIC1_DATA; + + if (lane >= 8) { + port = IO_PIC2_DATA; + lane -= 8; + } + + outb(port, inb(port) & ~(1 << lane)); +} + +void pic_init() +{ + typedef struct { + bool ic4 : 1; + bool single : 1; + bool addr_interval : 1; + bool level_triggered : 1; + bool init : 1; + unsigned int zeros : 3; + } __attribute__((packed)) pic_icw1; + + u8 icw1 = BITCAST(((pic_icw1) { + .ic4 = true, + .single = false, + .addr_interval = false, + .level_triggered = false, + .init = true, + .zeros = 0, + }), pic_icw1, u8); + + outb(IO_PIC1_CTRL, icw1); + outb(IO_PIC2_CTRL, icw1); + + // map IRQs 0-15 to 0x20-0x2F + // 0x1F is the highest reserved interrupt + outb(IO_PIC1_DATA, 0x20); + outb(IO_PIC2_DATA, 0x28); + + // pic2 is connected to IRQ2 + outb(IO_PIC1_DATA, 1 << 2); + outb(IO_PIC2_DATA, 2); + + typedef struct { + bool x86 : 1; + bool auto_eoi : 1; + bool primary_buffered : 1; + bool buffered : 1; + bool fully_nested : 1; + unsigned int zeros : 3; + } __attribute__((packed)) pic_icw4; + + u8 icw4 = BITCAST(((pic_icw4) { + .x86 = true, + .auto_eoi = false, + .primary_buffered = false, + .buffered = false, + .fully_nested = false, + .zeros = 0, + }), pic_icw4, u8); + + outb(IO_PIC1_DATA, icw4); + outb(IO_PIC2_DATA, icw4); + + // mask all interrupts + outb(IO_PIC1_DATA, 0xff); + outb(IO_PIC2_DATA, 0xff); + + disable_irqs(); +} diff --git a/stage3/pic.h b/stage3/pic.h new file mode 100644 index 0000000..eebe119 --- /dev/null +++ b/stage3/pic.h @@ -0,0 +1,31 @@ +#ifndef PIC_H +#define PIC_H + +#include "def.h" + +typedef enum { + IRQ_PIT = 0, + IRQ_KEYBOARD, + IRQ_CASCADE, + IRQ_COM2, + IRQ_COM1, + IRQ_LPT2, + IRQ_FLOPPY, + IRQ_LPT1, + IRQ_CMOS_CLOCK, + IRQ_MOUSE, + IRQ_FREE1, + IRQ_FREE2, + IRQ_FREE3, + IRQ_FPU, + IRQ_ATA_HDD1, + IRQ_ATA_HDD2, +} irq_lane; + +void disable_irqs(); +void enable_irqs(); +void unmask_irq(u8 lane); +void ack_irq(u8 lane); +void pic_init(); + +#endif |
