diff options
| -rw-r--r-- | mirai/common/constants/idt.zig | 10 | ||||
| -rw-r--r-- | mirai/common/constants/pic.zig | 20 | ||||
| -rw-r--r-- | mirai/interrupts/handlers.zig | 9 | ||||
| -rw-r--r-- | mirai/interrupts/idt.zig | 96 | ||||
| -rw-r--r-- | mirai/interrupts/pic.zig | 30 | ||||
| -rw-r--r-- | mirai/interrupts/types.zig | 16 |
6 files changed, 107 insertions, 74 deletions
diff --git a/mirai/common/constants/idt.zig b/mirai/common/constants/idt.zig new file mode 100644 index 0000000..d7c7bac --- /dev/null +++ b/mirai/common/constants/idt.zig @@ -0,0 +1,10 @@ +//! IDT constants + +pub const NUM_ENTRIES: usize = 256; +pub const NUM_EXCEPTIONS: u8 = 32; + +pub const GATE_INTERRUPT: u8 = 0x8E; +pub const GATE_TRAP: u8 = 0x8F; + +pub const VECTOR_TIMER: u8 = 32; +pub const VECTOR_KEYBOARD: u8 = 33; diff --git a/mirai/common/constants/pic.zig b/mirai/common/constants/pic.zig new file mode 100644 index 0000000..656e9a1 --- /dev/null +++ b/mirai/common/constants/pic.zig @@ -0,0 +1,20 @@ +//! PIC constants + +pub const MASTER_CMD: u16 = 0x20; +pub const MASTER_DATA: u16 = 0x21; +pub const SLAVE_CMD: u16 = 0xA0; +pub const SLAVE_DATA: u16 = 0xA1; + +pub const ICW1_INIT: u8 = 0x11; +pub const ICW4_8086: u8 = 0x01; + +pub const MASTER_OFFSET: u8 = 0x20; +pub const SLAVE_OFFSET: u8 = 0x28; + +pub const MASTER_CASCADE: u8 = 0x04; +pub const SLAVE_CASCADE: u8 = 0x02; + +pub const MASK_TIMER_KEYBOARD: u8 = 0xFC; +pub const MASK_ALL: u8 = 0xFF; + +pub const EOI: u8 = 0x20; diff --git a/mirai/interrupts/handlers.zig b/mirai/interrupts/handlers.zig new file mode 100644 index 0000000..7f8ea06 --- /dev/null +++ b/mirai/interrupts/handlers.zig @@ -0,0 +1,9 @@ +//! IRQ handlers + +const pic = @import("pic.zig"); +const sensei = @import("../kata/sensei/sensei.zig"); + +export fn timer_handler() void { + pic.send_eoi_master(); + sensei.on_tick(); +} diff --git a/mirai/interrupts/idt.zig b/mirai/interrupts/idt.zig index 53a425c..326f441 100644 --- a/mirai/interrupts/idt.zig +++ b/mirai/interrupts/idt.zig @@ -1,31 +1,19 @@ -//! Interrupt Descriptor Table - IDT setup and IRQ routing +//! Interrupt Descriptor Table const cpu = @import("../asm/cpu.zig"); -const io = @import("../asm/io.zig"); +const gdt_const = @import("../common/constants/gdt.zig"); +const idt_const = @import("../common/constants/idt.zig"); const isr = @import("../asm/isr.zig"); -const sensei = @import("../kata/sensei/sensei.zig"); +const pic = @import("pic.zig"); const serial = @import("../drivers/serial/serial.zig"); +const types = @import("types.zig"); comptime { _ = @import("../crimson/exception.zig"); + _ = @import("handlers.zig"); } -const IDTEntry = packed struct { - offset_low: u16, - selector: u16, - ist: u8, - type_attr: u8, - offset_mid: u16, - offset_high: u32, - reserved: u32, -}; - -const IDTPointer = packed struct { - limit: u16, - base: u64, -}; - -var idt: [256]IDTEntry align(16) = [_]IDTEntry{.{ +var table: [idt_const.NUM_ENTRIES]types.Entry align(16) = [_]types.Entry{.{ .offset_low = 0, .selector = 0, .ist = 0, @@ -33,46 +21,37 @@ var idt: [256]IDTEntry align(16) = [_]IDTEntry{.{ .offset_mid = 0, .offset_high = 0, .reserved = 0, -}} ** 256; +}} ** idt_const.NUM_ENTRIES; -var idt_ptr: IDTPointer = undefined; +var pointer: types.Pointer = undefined; pub fn init() void { - serial.print("\n=== Interrupt Descriptor Table ===\n"); + serial.print("\n=== IDT ===\n"); - // Setup exception handlers (0-31) - var i: u8 = 0; - while (i < 32) : (i += 1) { - const handler_addr = @intFromPtr(isr.get_exception_handler(i)); - set_gate(i, handler_addr, 0x08, 0x8E); + for (0..idt_const.NUM_EXCEPTIONS) |i| { + const handler_addr = @intFromPtr(isr.get_exception_handler(@intCast(i))); + set_gate(@intCast(i), handler_addr, gdt_const.KERNEL_CODE, idt_const.GATE_INTERRUPT); } - // Setup IRQ handlers - // IRQ 0 = Timer (vector 32) - set_gate(32, @intFromPtr(isr.get_irq_handler(0)), 0x08, 0x8E); - // IRQ 1 = Keyboard (vector 33) - set_gate(33, @intFromPtr(isr.get_irq_handler(1)), 0x08, 0x8E); + set_gate(idt_const.VECTOR_TIMER, @intFromPtr(isr.get_irq_handler(0)), gdt_const.KERNEL_CODE, idt_const.GATE_INTERRUPT); + set_gate(idt_const.VECTOR_KEYBOARD, @intFromPtr(isr.get_irq_handler(1)), gdt_const.KERNEL_CODE, idt_const.GATE_INTERRUPT); - // Setup IDT pointer - idt_ptr = IDTPointer{ - .limit = @sizeOf(@TypeOf(idt)) - 1, - .base = @intFromPtr(&idt), + pointer = types.Pointer{ + .limit = @sizeOf(@TypeOf(table)) - 1, + .base = @intFromPtr(&table), }; - // Load IDT - cpu.load_interrupt_descriptor_table(@intFromPtr(&idt_ptr)); + cpu.load_interrupt_descriptor_table(@intFromPtr(&pointer)); - // Remap PIC - remap_pic(); + pic.remap(); - // Enable interrupts cpu.enable_interrupts(); - serial.print("IDT loaded, interrupts enabled\n"); + serial.print("IDT loaded\n"); } fn set_gate(num: u8, handler: u64, selector: u16, type_attr: u8) void { - idt[num] = IDTEntry{ + table[num] = types.Entry{ .offset_low = @truncate(handler & 0xFFFF), .selector = selector, .ist = 0, @@ -82,34 +61,3 @@ fn set_gate(num: u8, handler: u64, selector: u16, type_attr: u8) void { .reserved = 0, }; } - -fn remap_pic() void { - // ICW1: Initialize + ICW4 needed - io.out_byte(0x20, 0x11); - io.out_byte(0xA0, 0x11); - - // ICW2: Vector offsets - io.out_byte(0x21, 0x20); // Master PIC: IRQ 0-7 -> vectors 32-39 - io.out_byte(0xA1, 0x28); // Slave PIC: IRQ 8-15 -> vectors 40-47 - - // ICW3: Cascade setup - io.out_byte(0x21, 0x04); // Master: slave on IRQ2 - io.out_byte(0xA1, 0x02); // Slave: cascade identity - - // ICW4: 8086 mode - io.out_byte(0x21, 0x01); - io.out_byte(0xA1, 0x01); - - // Mask all interrupts except IRQ0 (timer) and IRQ1 (keyboard) - io.out_byte(0x21, 0xFC); // 11111100 - enable IRQ0, IRQ1 - io.out_byte(0xA1, 0xFF); // Mask all slave IRQs -} - -// Timer interrupt handler -export fn timer_handler() void { - // Send EOI to PIC - io.out_byte(0x20, 0x20); - - // Update scheduler - sensei.on_tick(); -} diff --git a/mirai/interrupts/pic.zig b/mirai/interrupts/pic.zig new file mode 100644 index 0000000..df26eb3 --- /dev/null +++ b/mirai/interrupts/pic.zig @@ -0,0 +1,30 @@ +//! PIC remapping + +const io = @import("../asm/io.zig"); +const pic = @import("../common/constants/pic.zig"); + +pub fn remap() void { + io.out_byte(pic.MASTER_CMD, pic.ICW1_INIT); + io.out_byte(pic.SLAVE_CMD, pic.ICW1_INIT); + + io.out_byte(pic.MASTER_DATA, pic.MASTER_OFFSET); + io.out_byte(pic.SLAVE_DATA, pic.SLAVE_OFFSET); + + io.out_byte(pic.MASTER_DATA, pic.MASTER_CASCADE); + io.out_byte(pic.SLAVE_DATA, pic.SLAVE_CASCADE); + + io.out_byte(pic.MASTER_DATA, pic.ICW4_8086); + io.out_byte(pic.SLAVE_DATA, pic.ICW4_8086); + + io.out_byte(pic.MASTER_DATA, pic.MASK_TIMER_KEYBOARD); + io.out_byte(pic.SLAVE_DATA, pic.MASK_ALL); +} + +pub fn send_eoi_master() void { + io.out_byte(pic.MASTER_CMD, pic.EOI); +} + +pub fn send_eoi_slave() void { + io.out_byte(pic.SLAVE_CMD, pic.EOI); + io.out_byte(pic.MASTER_CMD, pic.EOI); +} diff --git a/mirai/interrupts/types.zig b/mirai/interrupts/types.zig new file mode 100644 index 0000000..ecd8513 --- /dev/null +++ b/mirai/interrupts/types.zig @@ -0,0 +1,16 @@ +//! IDT type definitions + +pub const Entry = packed struct { + offset_low: u16, + selector: u16, + ist: u8, + type_attr: u8, + offset_mid: u16, + offset_high: u32, + reserved: u32, +}; + +pub const Pointer = packed struct { + limit: u16, + base: u64, +}; |
