1#![no_std]
2
3extern crate alloc;
4
5use core::ptr::NonNull;
6pub use fdt_parser::Phandle;
7
8use log::info;
9use register::{DriverRegister, DriverRegisterData, ProbeLevel};
10use spin::Mutex;
11
12mod device;
13pub mod error;
14mod id;
15mod manager;
16pub mod probe;
17pub mod register;
18pub use device::*;
19pub use manager::*;
20pub use probe::ProbeError;
21pub use rdif_base::{DriverGeneric, ErrorBase, IrqId, io};
22
23static MANAGER: Mutex<Option<Manager>> = Mutex::new(None);
24
25#[derive(Debug, Clone)]
26pub enum DriverInfoKind {
27 Fdt { addr: NonNull<u8> },
28}
29
30unsafe impl Send for DriverInfoKind {}
31
32pub fn init(probe_kind: DriverInfoKind) {
33 MANAGER.lock().replace(Manager::new(probe_kind));
34}
35
36pub fn edit<F, T>(f: F) -> T
37where
38 F: FnOnce(&mut Manager) -> T,
39{
40 let mut g = MANAGER.lock();
41 f(g.as_mut().expect("manager not init"))
42}
43
44pub fn read<F, T>(f: F) -> T
45where
46 F: FnOnce(&Manager) -> T,
47{
48 let g = MANAGER.lock();
49 f(g.as_ref().expect("manager not init"))
50}
51
52pub fn register_add(register: DriverRegister) {
53 edit(|manager| manager.registers.add(register));
54}
55
56pub fn register_append(registers: &[DriverRegister]) {
57 edit(|manager| manager.registers.append(registers))
58}
59
60pub fn probe_pre_kernel() -> Result<(), ProbeError> {
61 let unregistered = edit(|manager| manager.unregistered())?;
62
63 let ls = unregistered
64 .iter()
65 .filter(|one| matches!(one.register.level, ProbeLevel::PreKernel));
66
67 probe_with(ls, true)?;
68
69 Ok(())
70}
71
72fn probe_with<'a>(
73 registers: impl Iterator<Item = &'a DriverRegisterData>,
74 stop_if_fail: bool,
75) -> Result<(), ProbeError> {
76 macro_rules! handle_error {
77 ($e: expr, $m: expr) => {
78 if stop_if_fail {
79 $e?
80 } else {
81 match $e {
82 Ok(v) => v,
83 Err(e) => {
84 log::warn!("{}: {}", $m, e);
85 continue;
86 }
87 }
88 }
89 };
90 }
91
92 for one in registers {
93 let to_probe = edit(|manager| manager.to_unprobed(one))?;
94
95 if let Some(to_probe) = to_probe {
96 let probed = handle_error!(to_probe(), "probe fail");
97 info!("open [{}]", probed.descriptor.name);
98 handle_error!(probed.dev.open(), "open fail");
99 edit(|manager| manager.add_probed(probed));
100 }
101 }
102
103 Ok(())
104}
105
106pub fn probe_all(stop_if_fail: bool) -> Result<(), ProbeError> {
107 let unregistered = edit(|manager| manager.unregistered())?;
108
109 probe_with(unregistered.iter(), stop_if_fail)
110}
111
112#[macro_export]
113macro_rules! dev_list {
114 ($k: ident) => {
115 $crate::read(|manager| {
116 extern crate alloc;
117
118 manager
119 .dev_map
120 .iter()
121 .filter_map(|(_, v)| {
122 if let $crate::DeviceKind::$k(dev) = v {
123 Some(dev.weak())
124 } else {
125 None
126 }
127 })
128 .collect::<alloc::vec::Vec<_>>()
129 })
130 };
131}
132#[macro_export]
133macro_rules! get_dev {
134 ($k:ident) => {
135 $crate::read(|m| {
136 m.dev_map
137 .iter()
138 .filter_map(|(_, v)| {
139 if let $crate::DeviceKind::$k(dev) = v {
140 Some(dev.weak())
141 } else {
142 None
143 }
144 })
145 .next()
146 })
147 };
148 ($id:expr, $k:ident) => {
149 $crate::read(|m| {
150 let dev = m.dev_map.get(&$id)?;
151 if let $crate::DeviceKind::$k(dev) = dev {
152 Some(dev.weak())
153 } else {
154 None
155 }
156 })
157 };
158}