114 lines
2.6 KiB
Zig
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);
|
|
}
|
|
});
|
|
};
|