#![no_std]
#[macro_use]
extern crate alloc;
#[macro_use]
extern crate log;
use core::ptr::NonNull;
pub use fdt_edit::Phandle;
use register::{DriverRegister, ProbeLevel};
use spin::{Mutex, Once};
mod descriptor;
pub mod driver;
pub mod error;
mod id;
mod lock;
mod manager;
mod osal;
pub mod probe;
pub mod register;
pub use descriptor::*;
pub use driver::PlatformDevice;
pub use lock::*;
pub use manager::*;
pub use osal::*;
pub use probe::ProbeError;
pub use rdif_base::{DriverGeneric, KError, irq::IrqId};
pub use rdrive_macros::*;
use crate::{error::DriverError, probe::OnProbeError};
static CONTAINER: Once<Mutex<Manager>> = Once::new();
#[derive(Debug, Clone)]
pub enum Platform {
Fdt { addr: NonNull<u8> },
}
unsafe impl Send for Platform {}
pub(crate) fn container() -> &'static Mutex<Manager> {
CONTAINER.get().expect("rdrive not init")
}
pub fn init(platform: Platform) -> Result<(), DriverError> {
match platform {
Platform::Fdt { addr } => {
probe::fdt::init(addr)?;
}
}
let m = Manager::new()?;
CONTAINER.call_once(|| Mutex::new(m));
Ok(())
}
pub(crate) fn edit<F, T>(f: F) -> T
where
F: FnOnce(&mut Manager) -> T,
{
let mut g = container().lock();
f(&mut g)
}
pub(crate) fn read<F, T>(f: F) -> T
where
F: FnOnce(&Manager) -> T,
{
let g = container().lock();
f(&g)
}
pub fn register_add(register: DriverRegister) {
edit(|manager| manager.registers.add(register));
}
pub fn register_append(registers: &[DriverRegister]) {
edit(|manager| manager.registers.append(registers))
}
pub fn probe_pre_kernel() -> Result<(), ProbeError> {
let unregistered = edit(|manager| manager.unregistered())?;
let ls = unregistered
.iter()
.filter(|one| matches!(one.level, ProbeLevel::PreKernel));
probe_system(ls, true)?;
Ok(())
}
fn probe_system<'a>(
registers: impl Iterator<Item = &'a DriverRegister>,
stop_if_fail: bool,
) -> Result<(), ProbeError> {
for one in registers {
let res = probe::fdt::probe_register(one)?;
for r in res {
match r {
Ok(_) => {}
Err(OnProbeError::NotMatch) => {
}
Err(e) => {
if stop_if_fail {
return Err(e.into());
} else {
warn!("Probe failed for [{}]: {}", one.name, e);
}
}
}
}
}
Ok(())
}
pub fn probe_all(stop_if_fail: bool) -> Result<(), ProbeError> {
let unregistered = edit(|manager| manager.unregistered())?;
probe_system(unregistered.iter(), stop_if_fail)?;
debug!("probe pci devices");
probe::pci::probe_with(&unregistered, stop_if_fail)?;
Ok(())
}
pub fn get_list<T: DriverGeneric>() -> Vec<Device<T>> {
read(|manager| manager.dev_container.devices())
}
pub fn get<T: DriverGeneric>(id: DeviceId) -> Result<Device<T>, GetDeviceError> {
read(|manager| manager.dev_container.get_typed(id))
}
pub fn get_one<T: DriverGeneric>() -> Option<Device<T>> {
read(|manager| manager.dev_container.get_one())
}
pub fn fdt_phandle_to_device_id(phandle: Phandle) -> Option<DeviceId> {
probe::fdt::system().phandle_to_device_id(phandle)
}
#[macro_export]
macro_rules! module_driver {
(
$($i:ident : $t:expr),+,
) => {
#[allow(unused)]
$crate::__mod_maker!{
pub mod some {
use super::*;
use $crate::register::*;
#[unsafe(link_section = ".driver.register")]
#[unsafe(no_mangle)]
#[used(linker)]
pub static DRIVER: DriverRegister = DriverRegister {
$($i : $t),+
};
}
}
};
}