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