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::sync::atomic::{AtomicUsize, Ordering};

static LAST_CAP_OFFSET: AtomicUsize = AtomicUsize::new(0);

pub fn find_capability(bus: u8, dev: u8, func: u8, cap_id: u8) -> Option<u8> {
    let status = crate::bus::pci::api::read_config_u32(bus, dev, func, 0x06)?;
    if status & (1 << 20) == 0 {
        return None;
    }
    let cap_ptr_raw = crate::bus::pci::api::read_config_u32(bus, dev, func, 0x34)?;
    let mut offset = (cap_ptr_raw & 0xFF) as u8;
    let mut iterations = 0u8;
    while offset != 0 && iterations < 48 {
        let cap_header = crate::bus::pci::api::read_config_u32(bus, dev, func, offset)?;
        let id = (cap_header & 0xFF) as u8;
        if id == cap_id {
            LAST_CAP_OFFSET.store(offset as usize, Ordering::Release);
            return Some(offset);
        }
        offset = ((cap_header >> 8) & 0xFF) as u8;
        iterations += 1;
    }
    None
}

pub fn read_cap_u32(bus: u8, dev: u8, func: u8, cap_offset: u8, reg_offset: u8) -> Option<u32> {
    crate::bus::pci::api::read_config_u32(bus, dev, func, cap_offset.wrapping_add(reg_offset))
}