use core::arch::asm;
use polished_serial_logging::kprint;
use x86_64::structures::idt::InterruptStackFrame;
pub fn setup_hardware_interrupts(idt: &mut x86_64::structures::idt::InterruptDescriptorTable) {
idt[32].set_handler_fn(timer_interrupt_handler);
idt[33].set_handler_fn(keyboard_interrupt_handler);
idt[44].set_handler_fn(mouse_interrupt_handler);
idt[46].set_handler_fn(disk_interrupt_handler);
idt[43].set_handler_fn(network_interrupt_handler);
idt[55].set_handler_fn(usb_interrupt_handler);
idt[47].set_handler_fn(other_hardware_interrupt_handler);
}
fn send_eoi() {
unsafe {
asm!(
"mov al, 0x20",
"out 0x20, al",
options(nomem, nostack, preserves_flags)
);
}
}
pub extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
send_eoi();
}
pub extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
let scancode: u8;
unsafe {
asm!(
"in al, 0x60",
out("al") scancode,
options(nomem, nostack, preserves_flags)
);
}
if scancode == 0xFA {
kprint!(
"[INFO] INT 0x21: Keyboard interrupt, received 0xFA (possible ACK, not a keypress)\r\n"
);
} else if scancode & 0x80 == 0 {
let converted = polished_scancodes::scancode_to_ascii(scancode);
match converted {
Some(ascii) if ascii.is_ascii_graphic() || ascii == b' ' => {
kprint!(
"[INFO] INT 0x21: Keyboard interrupt, scancode: {:#x} | ASCII: '{}'\r\n",
scancode,
ascii as char
);
}
_ => {
kprint!(
"[INFO] INT 0x21: Keyboard interrupt, scancode: {:#x} | ASCII: Unknown\r\n",
scancode
);
}
}
}
send_eoi();
}
pub extern "x86-interrupt" fn mouse_interrupt_handler(_stack_frame: InterruptStackFrame) {
kprint!("[INFO] INT 0x2C: Mouse interrupt\r\n");
}
pub extern "x86-interrupt" fn disk_interrupt_handler(_stack_frame: InterruptStackFrame) {
kprint!("[INFO] INT 0x2E: Disk controller interrupt\r\n");
}
pub extern "x86-interrupt" fn network_interrupt_handler(_stack_frame: InterruptStackFrame) {
kprint!("[INFO] INT 0x2B: Network card interrupt\r\n");
}
pub extern "x86-interrupt" fn usb_interrupt_handler(_stack_frame: InterruptStackFrame) {
kprint!("[INFO] INT 0x37: USB controller interrupt\r\n");
}
pub extern "x86-interrupt" fn other_hardware_interrupt_handler(_stack_frame: InterruptStackFrame) {
kprint!("[INFO] INT 0x2F: Other hardware device interrupt\r\n");
}