rdrive/
lib.rs

1#![no_std]
2
3#[macro_use]
4extern crate alloc;
5#[macro_use]
6extern crate log;
7
8use core::ptr::NonNull;
9
10pub use fdt_parser::Phandle;
11use register::{DriverRegister, ProbeLevel};
12use spin::{Mutex, Once};
13
14mod descriptor;
15pub mod driver;
16pub mod error;
17mod id;
18mod lock;
19mod manager;
20mod osal;
21
22pub mod probe;
23pub mod register;
24
25pub use descriptor::*;
26pub use driver::PlatformDevice;
27pub use lock::*;
28pub use manager::*;
29pub use osal::*;
30pub use probe::ProbeError;
31pub use rdif_base::{DriverGeneric, KError, irq::IrqId};
32pub use rdrive_macros::*;
33
34use crate::{error::DriverError, probe::OnProbeError};
35
36static CONTAINER: Once<Mutex<Manager>> = Once::new();
37
38#[derive(Debug, Clone)]
39pub enum Platform {
40    Fdt { addr: NonNull<u8> },
41}
42
43unsafe impl Send for Platform {}
44
45pub(crate) fn container() -> &'static Mutex<Manager> {
46    CONTAINER.get().expect("rdrive not init")
47}
48
49pub fn init(platform: Platform) -> Result<(), DriverError> {
50    match platform {
51        Platform::Fdt { addr } => {
52            probe::fdt::init(addr)?;
53        }
54    }
55
56    let m = Manager::new()?;
57    CONTAINER.call_once(|| Mutex::new(m));
58    Ok(())
59}
60
61pub(crate) fn edit<F, T>(f: F) -> T
62where
63    F: FnOnce(&mut Manager) -> T,
64{
65    let mut g = container().lock();
66    f(&mut g)
67}
68
69pub(crate) fn read<F, T>(f: F) -> T
70where
71    F: FnOnce(&Manager) -> T,
72{
73    let g = container().lock();
74    f(&g)
75}
76
77pub fn register_add(register: DriverRegister) {
78    edit(|manager| manager.registers.add(register));
79}
80
81pub fn register_append(registers: &[DriverRegister]) {
82    edit(|manager| manager.registers.append(registers))
83}
84
85pub fn probe_pre_kernel() -> Result<(), ProbeError> {
86    let unregistered = edit(|manager| manager.unregistered())?;
87
88    let ls = unregistered
89        .iter()
90        .filter(|one| matches!(one.level, ProbeLevel::PreKernel));
91
92    probe_system(ls, true)?;
93
94    Ok(())
95}
96
97fn probe_system<'a>(
98    registers: impl Iterator<Item = &'a DriverRegister>,
99    stop_if_fail: bool,
100) -> Result<(), ProbeError> {
101    for one in registers {
102        // let system = edit(|manager| manager.enum_system.clone());
103
104        // let res = system.probe_register(one)?;
105
106        let res = probe::fdt::probe_register(one)?;
107
108        for r in res {
109            match r {
110                Ok(_) => {}
111                Err(OnProbeError::NotMatch) => {
112                    // Not a match, skip to the next probe
113                }
114                Err(e) => {
115                    if stop_if_fail {
116                        return Err(e.into());
117                    } else {
118                        warn!("Probe failed for [{}]: {}", one.name, e);
119                    }
120                }
121            }
122        }
123    }
124
125    Ok(())
126}
127
128pub fn probe_all(stop_if_fail: bool) -> Result<(), ProbeError> {
129    let unregistered = edit(|manager| manager.unregistered())?;
130    probe_system(unregistered.iter(), stop_if_fail)?;
131
132    debug!("probe pci devices");
133    probe::pci::probe_with(&unregistered, stop_if_fail)?;
134
135    Ok(())
136}
137
138pub fn get_list<T: DriverGeneric>() -> Vec<Device<T>> {
139    read(|manager| manager.dev_container.devices())
140}
141
142pub fn get<T: DriverGeneric>(id: DeviceId) -> Result<Device<T>, GetDeviceError> {
143    read(|manager| manager.dev_container.get_typed(id))
144}
145
146pub fn get_one<T: DriverGeneric>() -> Option<Device<T>> {
147    read(|manager| manager.dev_container.get_one())
148}
149
150pub fn fdt_phandle_to_device_id(phandle: Phandle) -> Option<DeviceId> {
151    probe::fdt::system().phandle_to_device_id(phandle)
152}
153
154/// Macro for generating a driver module.
155///
156/// This macro automatically generates a driver registration module that creates a static
157/// `DriverRegister` struct containing driver metadata (such as name, probe level, priority,
158/// and probe types). The generated static variable is placed in the special linker section
159/// `.driver.register` to be automatically discovered and registered by the driver manager
160/// at runtime.
161///
162/// # Parameters
163/// - `$i:ident`: Field identifier (e.g., `name`, `level`, `priority`, `probe_kinds`)
164/// - `$t:expr`: Expression for the corresponding field value
165///
166/// # Generated Code
167///
168/// The macro generates a module containing a static `DriverRegister` that:
169/// - Uses `#[link_section = ".driver.register"]` attribute to place it in a special linker section
170/// - Uses `#[no_mangle]` and `#[used]` to prevent compiler optimization
171/// - Contains all driver registration information
172///
173/// # Example
174///
175/// ```rust
176/// use rdrive::{
177///     module_driver,
178///     driver::*,
179///     register::FdtInfo,
180///     probe::OnProbeError,
181///     PlatformDevice,
182/// };
183///
184/// struct UartDriver {}
185///
186/// impl DriverGeneric for UartDriver {
187///     fn open(&mut self) -> Result<(), rdrive::KError> { todo!() }
188///     fn close(&mut self) -> Result<(), rdrive::KError> { todo!() }
189/// }
190///
191/// impl rdif_serial::Interface for UartDriver {
192///     fn handle_irq(&mut self) { todo!() }
193///     fn take_tx(&mut self) -> Option<Box<(dyn rdif_serial::io::Write + 'static)>> { todo!() }
194///     fn take_rx(&mut self) -> Option<Box<(dyn rdif_serial::io::Read + 'static)>> { todo!() }
195/// }
196///
197/// // Define probe function
198/// fn probe_uart(fdt: FdtInfo<'_>, dev: PlatformDevice) -> Result<(), OnProbeError> {
199///     // Implement specific device probing logic
200///     dev.register(rdif_serial::Serial::new(UartDriver{}));
201///     Ok(())
202/// }
203///
204/// // Use macro to generate driver registration module
205/// module_driver! {
206///     name: "UART Driver",
207///     level: ProbeLevel::PostKernel,
208///     priority: ProbePriority::DEFAULT,
209///     probe_kinds: &[ProbeKind::Fdt {
210///         compatibles: &["ns16550a", "arm,pl011"],
211///         // Use `probe_uart` above; this usage is because doctests cannot find the parent module.
212///         on_probe: |fdt, dev|{
213///             Ok(())
214///         },
215///     }],
216/// }
217/// ```
218///
219/// # Notes
220///
221/// - This macro can only be used once per driver module
222/// - The generated module name is automatically derived from the driver name
223/// - All fields must be properly set, especially the `probe_kinds` array
224/// - Probe functions must implement the correct signature and error handling
225#[macro_export]
226macro_rules! module_driver {
227    (
228        $($i:ident : $t:expr),+,
229    ) => {
230        /// Auto-generated driver registration module.
231        #[allow(unused)]
232        $crate::__mod_maker!{
233            pub mod some {
234                use super::*;
235                use $crate::register::*;
236
237                /// Static instance of driver registration information.
238                ///
239                /// This static variable is placed in the `.driver.register` linker section
240                /// so that the driver manager can automatically discover and load it during
241                /// system startup.
242                #[unsafe(link_section = ".driver.register")]
243                #[unsafe(no_mangle)]
244                // #[used(linker)]
245                pub static DRIVER: DriverRegister = DriverRegister {
246                    $($i : $t),+
247                };
248            }
249        }
250    };
251}