summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-10 18:07:35 +0100
committerLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-10 18:07:35 +0100
commit4210c4ae384753825e10c5ea4ad1e99e9bba2c1f (patch)
tree4406242c6b6e6eb4658c1bc3cbe927b378f11dbc
parentbc00cb0649167958aed2f481580af3b4f21043b0 (diff)
downloadcuddles-4210c4ae384753825e10c5ea4ad1e99e9bba2c1f.tar.xz
handle IRQs
-rw-r--r--Makefile1
-rw-r--r--bochsrc1
-rw-r--r--stage2/paging.asm2
-rw-r--r--stage3/interrupts.c5
-rw-r--r--stage3/main.c5
-rw-r--r--stage3/pic.c92
-rw-r--r--stage3/pic.h31
7 files changed, 135 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index f04dd50..8e09152 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@ STAGE3 = \
stage3/halt.o \
stage3/interrupts.o \
stage3/isr.o \
+ stage3/pic.o \
stage3/memory.o \
stage3/paging.o \
stage3/heap.o \
diff --git a/bochsrc b/bochsrc
index eedf187..fcda911 100644
--- a/bochsrc
+++ b/bochsrc
@@ -2,3 +2,4 @@ floppya: 1_44=cuddles.img, status=inserted
boot: a
#display_library: x, options="gui_debug"
megs: 32
+#debug: PIC=report
diff --git a/stage2/paging.asm b/stage2/paging.asm
index 91ed0ac..cedc1e9 100644
--- a/stage2/paging.asm
+++ b/stage2/paging.asm
@@ -30,6 +30,7 @@ paging:
mov di, PAGETABLE
+ ; mask all IRQs
mov al, 0xFF
out 0xA1, al
out 0x21, al
@@ -47,7 +48,6 @@ paging:
mov ecx, 0xC0000080
rdmsr
-
or eax, 0x00000100
wrmsr
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