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
pub fn read_reg(base: usize, offset: usize) -> u32 {
    let ptr = (base + offset) as *const u32;
    unsafe { core::ptr::read_volatile(ptr) }
}

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

pub const GCAP: usize = 0x00;
pub const GCTL: usize = 0x08;
pub const GSTS: usize = 0x10;
pub const INTCTL: usize = 0x20;
pub const INTSTS: usize = 0x24;
pub const CORBLBASE: usize = 0x40;
pub const CORBUBASE: usize = 0x44;
pub const CORBWP: usize = 0x48;
pub const CORBRP: usize = 0x4A;
pub const RIRBLBASE: usize = 0x50;
pub const RIRBUBASE: usize = 0x54;
pub const RIRBWP: usize = 0x58;

pub fn global_capabilities(base: usize) -> u32 {
    read_reg(base, GCAP)
}

pub fn output_stream_count(gcap: u32) -> u8 {
    ((gcap >> 12) & 0xF) as u8
}

pub fn input_stream_count(gcap: u32) -> u8 {
    ((gcap >> 8) & 0xF) as u8
}

pub fn reset_controller(base: usize) {
    write_reg(base, GCTL, 0);
    let mut timeout = 1000u32;
    while (read_reg(base, GCTL) & 1) != 0 && timeout > 0 {
        timeout -= 1;
    }
    write_reg(base, GCTL, 1);
    timeout = 1000;
    while (read_reg(base, GCTL) & 1) == 0 && timeout > 0 {
        timeout -= 1;
    }
}

pub fn enable_interrupts(base: usize) {
    write_reg(base, INTCTL, 0x8000_FFFF);
}

pub fn disable_interrupts(base: usize) {
    write_reg(base, INTCTL, 0);
}

pub fn clear_status(base: usize) {
    write_reg(base, INTSTS, read_reg(base, INTSTS));
    write_reg(base, GSTS, read_reg(base, GSTS));
}