hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use core::ptr;

pub const INPUT_STATUS: usize = 0x00;
pub const INPUT_CTRL: usize = 0x04;
pub const INPUT_DATA: usize = 0x08;
pub const INPUT_SCANCODE: usize = 0x0C;
pub const INPUT_INT_CTRL: usize = 0x10;
pub const INPUT_INT_STATUS: usize = 0x14;
pub const INPUT_FIFO_STATUS: usize = 0x18;

pub const PS2_DATA: u16 = 0x60;
pub const PS2_STATUS: u16 = 0x64;
pub const PS2_COMMAND: u16 = 0x64;

pub const PS2_STS_OUTPUT_FULL: u8 = 1 << 0;
pub const PS2_STS_INPUT_FULL: u8 = 1 << 1;

pub const CTRL_ENABLE: u32 = 1 << 0;
pub const CTRL_INT_ENABLE: u32 = 1 << 1;
pub const CTRL_FIFO_ENABLE: u32 = 1 << 2;
pub const CTRL_RESET: u32 = 1 << 7;

pub fn read_reg(base: usize, offset: usize) -> u32 {
    unsafe { ptr::read_volatile((base + offset) as *const u32) }
}

pub fn write_reg(base: usize, offset: usize, val: u32) {
    unsafe { ptr::write_volatile((base + offset) as *mut u32, val) }
}

pub fn read_port8(port: u16) -> u8 {
    unsafe { crate::arch::x86_64::io::inb(port) }
}

pub fn write_port8(port: u16, val: u8) {
    unsafe { crate::arch::x86_64::io::outb(port, val) }
}

pub fn ps2_data_available() -> bool {
    read_port8(PS2_STATUS) & PS2_STS_OUTPUT_FULL != 0
}

pub fn ps2_read_data() -> u8 {
    read_port8(PS2_DATA)
}

pub fn ps2_send_command(cmd: u8) {
    loop {
        if read_port8(PS2_STATUS) & PS2_STS_INPUT_FULL == 0 {
            break;
        }
    }
    write_port8(PS2_COMMAND, cmd);
}

pub fn ps2_send_data(data: u8) {
    loop {
        if read_port8(PS2_STATUS) & PS2_STS_INPUT_FULL == 0 {
            break;
        }
    }
    write_port8(PS2_DATA, data);
}

pub fn mmio_enable(base: usize) {
    let ctrl = read_reg(base, INPUT_CTRL);
    write_reg(base, INPUT_CTRL, ctrl | CTRL_ENABLE | CTRL_INT_ENABLE);
}

pub fn mmio_disable(base: usize) {
    let ctrl = read_reg(base, INPUT_CTRL);
    write_reg(base, INPUT_CTRL, ctrl & !CTRL_ENABLE);
}

pub fn mmio_reset(base: usize) {
    write_reg(base, INPUT_CTRL, CTRL_RESET);
    loop {
        let ctrl = read_reg(base, INPUT_CTRL);
        if ctrl & CTRL_RESET == 0 {
            break;
        }
    }
}

pub fn mmio_read_scancode(base: usize) -> u32 {
    read_reg(base, INPUT_SCANCODE)
}

pub fn mmio_fifo_level(base: usize) -> u32 {
    read_reg(base, INPUT_FIFO_STATUS) & 0x3F
}