2025-05-09 23:16:25 +08:00

114 lines
2.6 KiB
Zig

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);
}
});
};