const arch = @import("../x86_64.zig"); const libk = @import("libk"); const Pio = arch.Pio; const Interrupt = arch.interrupt.Interrupt; const StackFrame = arch.interrupt.InterruptStackFrame; const WriteOnly = libk.io.WriteOnly; pub const Command = enum(u8) { init = 0x11, end_of_interrupt = 0x20, }; pub const Mode = enum(u8) { @"8086" = 0x01, }; pub fn Pic(comptime Offset: u8) type { return struct { command: WriteOnly(Pio(u8)), data: Pio(u8), pub inline fn init(self: *@This()) void { self.data.write(Offset); } pub inline fn notify(self: *@This()) void { self.command.write(@intFromEnum(Command.end_of_interrupt)); } pub inline fn contains(_: *@This(), id: u8) bool { return Offset <= id and id < Offset + 8; } }; } pub const ChainedPics = struct { var pic1: Pic(0x20) = .{ .command = .open(0x20), .data = .open(0x21) }; var pic2: Pic(0x28) = .{ .command = .open(0xA0), .data = .open(0xA1) }; pub fn enable() void { Timer.attach(); Keyboard.attach(); // Initiate initialization sequence pic1.command.write(@intFromEnum(Command.init)); pic2.command.write(@intFromEnum(Command.init)); // Setup base offsets pic1.init(); pic2.init(); // Configure PIC chaining pic1.data.write(4); pic2.data.write(2); // Set mode pic1.data.write(@intFromEnum(Mode.@"8086")); pic2.data.write(@intFromEnum(Mode.@"8086")); // Unmask interrupts pic1.data.write(0); pic2.data.write(0); // Ack remaining interrupts pic1.notify(); pic2.notify(); } pub fn disable() void { pic1.data.write(0xff); pic2.data.write(0xff); } pub inline fn contains(id: u8) bool { return pic1.contains(id) or pic2.contains(id); } pub inline fn notify(id: u8) void { if (contains(id)) { if (pic2.contains(id)) { pic2.notify(); } pic1.notify(); } } pub const Timer = Interrupt(struct { pub const Vector = 0x20; pub const HasErrorCode = false; pub fn handler(_: *StackFrame) callconv(.C) void { arch.machine.time.Pit.tick(); notify(Vector); } }); pub const Keyboard = Interrupt(struct { pub const Vector = 0x21; pub const HasErrorCode = false; pub fn handler(_: *StackFrame) callconv(.C) void { arch.machine.ps2.Keyboard.read(); notify(Vector); } }); };