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