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