Microkernel thing OS experiment (Zig ⚡)
1/// Remap the 8259 PIC to an interrupt base of 0x32 2const arch = @import("../root.zig"); 3const std = @import("std"); 4const log = std.log.scoped(.pic); 5const out = arch.port.out; 6const in = arch.port.in; 7 8const PIC_ONE_CMD_PORT = 0x20; 9const PIC_ONE_DATA_PORT = 0x21; 10const PIC_ONE_IDT_BASE = 32; 11 12const PIC_TWO_CMD_PORT = 0xA0; 13const PIC_TWO_DATA_PORT = 0xA1; 14const PIC_TWO_IDT_BASE = 40; 15 16const CMD_INIT = 0x11; 17const CMD_EOI = 0x20; 18 19// Remap the sixteen 8259 interrupts out of the way to 20// base interrupt number 32, and mask all interrupts 21// except the 8254 PIT 22pub fn init() void { 23 // Init the 8259's 24 out(u8, PIC_ONE_CMD_PORT, CMD_INIT); 25 wait(); 26 out(u8, PIC_TWO_CMD_PORT, CMD_INIT); 27 wait(); 28 29 // Write the interrupt base numbers for both 30 out(u8, PIC_ONE_DATA_PORT, PIC_ONE_IDT_BASE); 31 wait(); 32 out(u8, PIC_TWO_DATA_PORT, PIC_TWO_IDT_BASE); 33 wait(); 34 35 // Tell first 8259 that there's a second 8259 at IRQ 2, and tell 36 // the second 8259 that it is at that position. 37 out(u8, PIC_ONE_DATA_PORT, 1 << 2); 38 wait(); 39 out(u8, PIC_TWO_DATA_PORT, 2); 40 wait(); 41 42 // Tell the PICs to use 8086 mode 43 out(u8, PIC_ONE_DATA_PORT, 1); 44 wait(); 45 out(u8, PIC_ONE_DATA_PORT, 1); 46 wait(); 47 48 // Unmask only the 8254 49 out(u8, PIC_ONE_DATA_PORT, 0b1111_1111); 50 wait(); 51 out(u8, PIC_TWO_DATA_PORT, 0b1111_1111); 52 wait(); 53 54 // Set up a spurious IRQ7 handler 55 arch.interrupts.idt.add_handler(.{ .interrupt = 32 + 7 }, spurious_handler, 3, 0); 56} 57 58inline fn wait() void { 59 out(u8, 0x80, 0); 60} 61 62// Notify the first 8259 that we're done with the timer interrupt 63pub fn end_of_timer_interrupt() void { 64 out(u8, PIC_ONE_CMD_PORT, CMD_EOI); 65} 66 67pub fn spurious_handler(_: *arch.interrupts.idt.InterruptFrame(u64)) callconv(.{ .x86_64_sysv = .{} }) void { 68 std.log.warn("Got a spurious IRQ7 (8259)", .{}); 69}