diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | bochsrc | 1 | ||||
-rw-r--r-- | stage2/paging.asm | 2 | ||||
-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 |
7 files changed, 135 insertions, 2 deletions
@@ -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 \ @@ -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 |