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 crate::storage::detection::StorageProtocol;
use crate::storage::hw;
use core::sync::atomic::{AtomicU8, Ordering};

static DRIVER_STATE: AtomicU8 = AtomicU8::new(0);

const STATE_PROBED: u8 = 1;
const STATE_ACTIVE: u8 = 2;

pub struct AhciDriver {
    pub base: usize,
    pub port_count: u8,
    pub ports_implemented: u32,
}

pub struct NvmeDriver {
    pub base: usize,
    pub version_major: u16,
    pub version_minor: u16,
}

pub enum StorageDriver {
    Ahci(AhciDriver),
    Nvme(NvmeDriver),
}

pub fn probe(base: usize, protocol: StorageProtocol) -> Option<StorageDriver> {
    match protocol {
        StorageProtocol::Ahci => {
            let ports = hw::ahci_port_count(base);
            let implemented = hw::ahci_ports_implemented(base);
            DRIVER_STATE.store(STATE_PROBED, Ordering::Release);
            Some(StorageDriver::Ahci(AhciDriver {
                base,
                port_count: ports,
                ports_implemented: implemented,
            }))
        }
        StorageProtocol::Nvme => {
            let (major, minor, _) = hw::nvme_version(base);
            DRIVER_STATE.store(STATE_PROBED, Ordering::Release);
            Some(StorageDriver::Nvme(NvmeDriver {
                base,
                version_major: major,
                version_minor: minor as u16,
            }))
        }
        _ => None,
    }
}

pub fn init(driver: &StorageDriver) -> bool {
    match driver {
        StorageDriver::Ahci(ahci) => {
            hw::ahci_enable(ahci.base);
            DRIVER_STATE.store(STATE_ACTIVE, Ordering::Release);
            true
        }
        StorageDriver::Nvme(nvme) => {
            hw::nvme_enable(nvme.base);
            let ready = hw::nvme_ready(nvme.base);
            if ready {
                DRIVER_STATE.store(STATE_ACTIVE, Ordering::Release);
            }
            ready
        }
    }
}

pub fn state() -> u8 {
    DRIVER_STATE.load(Ordering::Acquire)
}