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}