xref: /DragonOS/kernel/src/driver/base/device/dd.rs (revision 06d5e247267cb65b84a80f219853ccd0f384b16e)
1*06d5e247SLoGin use core::intrinsics::unlikely;
2*06d5e247SLoGin 
3*06d5e247SLoGin use alloc::sync::Arc;
4*06d5e247SLoGin 
5*06d5e247SLoGin use crate::{driver::Driver, syscall::SystemError};
6*06d5e247SLoGin 
7*06d5e247SLoGin use super::{bus::BusNotifyEvent, driver::driver_manager, Device, DeviceManager};
8*06d5e247SLoGin 
9*06d5e247SLoGin impl DeviceManager {
10*06d5e247SLoGin     /// 尝试把一个设备与一个驱动匹配
11*06d5e247SLoGin     ///
12*06d5e247SLoGin     /// 当前函数会遍历整个bus的驱动列表,并且尝试把设备与每一个驱动进行匹配。
13*06d5e247SLoGin     /// 一旦有一个驱动匹配成功,就会返回。
14*06d5e247SLoGin     ///
15*06d5e247SLoGin     /// ## 参数
16*06d5e247SLoGin     ///
17*06d5e247SLoGin     /// - `dev`: 设备
18*06d5e247SLoGin     ///
19*06d5e247SLoGin     /// ## 返回
20*06d5e247SLoGin     ///
21*06d5e247SLoGin     /// - Ok(true): 匹配成功
22*06d5e247SLoGin     /// - Ok(false): 没有匹配成功
23*06d5e247SLoGin     /// - Err(SystemError::ENODEV): 设备还没被注册
24*06d5e247SLoGin     ///
25*06d5e247SLoGin     /// ## 参考
26*06d5e247SLoGin     ///
27*06d5e247SLoGin     /// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#1049
28*06d5e247SLoGin     pub fn device_attach(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
29*06d5e247SLoGin         return self.do_device_attach(dev, false);
30*06d5e247SLoGin     }
31*06d5e247SLoGin 
32*06d5e247SLoGin     pub fn device_initial_probe(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
33*06d5e247SLoGin         return self.do_device_attach(dev, true);
34*06d5e247SLoGin     }
35*06d5e247SLoGin 
36*06d5e247SLoGin     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#978
37*06d5e247SLoGin     fn do_device_attach(
38*06d5e247SLoGin         &self,
39*06d5e247SLoGin         dev: &Arc<dyn Device>,
40*06d5e247SLoGin         allow_async: bool,
41*06d5e247SLoGin     ) -> Result<bool, SystemError> {
42*06d5e247SLoGin         if unlikely(allow_async) {
43*06d5e247SLoGin             todo!("do_device_attach: allow_async")
44*06d5e247SLoGin         }
45*06d5e247SLoGin         if dev.is_dead() {
46*06d5e247SLoGin             return Ok(false);
47*06d5e247SLoGin         }
48*06d5e247SLoGin 
49*06d5e247SLoGin         let mut do_async = false;
50*06d5e247SLoGin         let mut r = Ok(false);
51*06d5e247SLoGin 
52*06d5e247SLoGin         if dev.driver().is_some() {
53*06d5e247SLoGin             if self.device_is_bound(dev) {
54*06d5e247SLoGin                 return Ok(true);
55*06d5e247SLoGin             }
56*06d5e247SLoGin 
57*06d5e247SLoGin             if self.device_bind_driver(dev).is_ok() {
58*06d5e247SLoGin                 return Ok(true);
59*06d5e247SLoGin             } else {
60*06d5e247SLoGin                 dev.set_driver(None);
61*06d5e247SLoGin                 return Ok(false);
62*06d5e247SLoGin             }
63*06d5e247SLoGin         } else {
64*06d5e247SLoGin             let bus = dev.bus().ok_or(SystemError::EINVAL)?;
65*06d5e247SLoGin             let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
66*06d5e247SLoGin             let mut flag = true;
67*06d5e247SLoGin             for driver in bus.subsystem().drivers().read().iter() {
68*06d5e247SLoGin                 if let Some(driver) = driver.upgrade() {
69*06d5e247SLoGin                     let r = self.do_device_attach_driver(&driver, &mut data);
70*06d5e247SLoGin                     if unlikely(r.is_err()) {
71*06d5e247SLoGin                         flag = false;
72*06d5e247SLoGin                         break;
73*06d5e247SLoGin                     }
74*06d5e247SLoGin                 }
75*06d5e247SLoGin             }
76*06d5e247SLoGin 
77*06d5e247SLoGin             if flag {
78*06d5e247SLoGin                 r = Ok(true);
79*06d5e247SLoGin             }
80*06d5e247SLoGin 
81*06d5e247SLoGin             if !flag && allow_async && data.have_async {
82*06d5e247SLoGin                 // If we could not find appropriate driver
83*06d5e247SLoGin                 // synchronously and we are allowed to do
84*06d5e247SLoGin                 // async probes and there are drivers that
85*06d5e247SLoGin                 // want to probe asynchronously, we'll
86*06d5e247SLoGin                 // try them.
87*06d5e247SLoGin 
88*06d5e247SLoGin                 do_async = true;
89*06d5e247SLoGin                 kdebug!(
90*06d5e247SLoGin                     "do_device_attach: try scheduling asynchronous probe for device: {}",
91*06d5e247SLoGin                     dev.name()
92*06d5e247SLoGin                 );
93*06d5e247SLoGin             }
94*06d5e247SLoGin         }
95*06d5e247SLoGin 
96*06d5e247SLoGin         if do_async {
97*06d5e247SLoGin             todo!("do_device_attach: do_async")
98*06d5e247SLoGin         }
99*06d5e247SLoGin         return r;
100*06d5e247SLoGin     }
101*06d5e247SLoGin 
102*06d5e247SLoGin     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#899
103*06d5e247SLoGin     fn do_device_attach_driver(
104*06d5e247SLoGin         &self,
105*06d5e247SLoGin         _driver: &Arc<dyn Driver>,
106*06d5e247SLoGin         _data: &mut DeviceAttachData,
107*06d5e247SLoGin     ) -> Result<(), SystemError> {
108*06d5e247SLoGin         todo!("do_device_attach_driver")
109*06d5e247SLoGin     }
110*06d5e247SLoGin 
111*06d5e247SLoGin     /// 检查设备是否绑定到驱动程序
112*06d5e247SLoGin     ///
113*06d5e247SLoGin     /// ## 参数
114*06d5e247SLoGin     ///
115*06d5e247SLoGin     /// - `dev`: 设备
116*06d5e247SLoGin     ///
117*06d5e247SLoGin     /// ## 返回
118*06d5e247SLoGin     ///
119*06d5e247SLoGin     /// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
120*06d5e247SLoGin     pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
121*06d5e247SLoGin         if dev.driver().is_some() {
122*06d5e247SLoGin             return true;
123*06d5e247SLoGin         } else {
124*06d5e247SLoGin             return false;
125*06d5e247SLoGin         }
126*06d5e247SLoGin     }
127*06d5e247SLoGin 
128*06d5e247SLoGin     /// 把一个驱动绑定到设备上
129*06d5e247SLoGin     ///
130*06d5e247SLoGin     /// 允许手动绑定驱动到设备上。调用者需要设置好dev.driver(),保证其不为None
131*06d5e247SLoGin     ///
132*06d5e247SLoGin     /// ## 参数
133*06d5e247SLoGin     ///
134*06d5e247SLoGin     /// - `dev`: 设备
135*06d5e247SLoGin     ///
136*06d5e247SLoGin     /// ## 建议
137*06d5e247SLoGin     ///
138*06d5e247SLoGin     /// 使用device_manager().driver_attach()会更好
139*06d5e247SLoGin     ///
140*06d5e247SLoGin     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#496
141*06d5e247SLoGin     pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
142*06d5e247SLoGin         let r = driver_manager().driver_sysfs_add(dev);
143*06d5e247SLoGin         if let Err(e) = r {
144*06d5e247SLoGin             self.device_links_force_bind(dev);
145*06d5e247SLoGin             self.driver_bound(dev);
146*06d5e247SLoGin             return Err(e);
147*06d5e247SLoGin         } else {
148*06d5e247SLoGin             if let Some(bus) = dev.bus() {
149*06d5e247SLoGin                 bus.subsystem().bus_notifier().call_chain(
150*06d5e247SLoGin                     BusNotifyEvent::DriverNotBound,
151*06d5e247SLoGin                     Some(dev),
152*06d5e247SLoGin                     None,
153*06d5e247SLoGin                 );
154*06d5e247SLoGin             }
155*06d5e247SLoGin         }
156*06d5e247SLoGin         return r;
157*06d5e247SLoGin     }
158*06d5e247SLoGin 
159*06d5e247SLoGin     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
160*06d5e247SLoGin     fn driver_bound(&self, _dev: &Arc<dyn Device>) {
161*06d5e247SLoGin         todo!("driver_bound")
162*06d5e247SLoGin     }
163*06d5e247SLoGin }
164*06d5e247SLoGin 
165*06d5e247SLoGin /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#866
166*06d5e247SLoGin #[derive(Debug)]
167*06d5e247SLoGin #[allow(dead_code)]
168*06d5e247SLoGin struct DeviceAttachData {
169*06d5e247SLoGin     dev: Arc<dyn Device>,
170*06d5e247SLoGin 
171*06d5e247SLoGin     ///  Indicates whether we are considering asynchronous probing or
172*06d5e247SLoGin     ///  not. Only initial binding after device or driver registration
173*06d5e247SLoGin     ///  (including deferral processing) may be done asynchronously, the
174*06d5e247SLoGin     ///  rest is always synchronous, as we expect it is being done by
175*06d5e247SLoGin     ///  request from userspace.
176*06d5e247SLoGin     check_async: bool,
177*06d5e247SLoGin 
178*06d5e247SLoGin     /// Indicates if we are binding synchronous or asynchronous drivers.
179*06d5e247SLoGin     /// When asynchronous probing is enabled we'll execute 2 passes
180*06d5e247SLoGin     /// over drivers: first pass doing synchronous probing and second
181*06d5e247SLoGin     /// doing asynchronous probing (if synchronous did not succeed -
182*06d5e247SLoGin     /// most likely because there was no driver requiring synchronous
183*06d5e247SLoGin     /// probing - and we found asynchronous driver during first pass).
184*06d5e247SLoGin     /// The 2 passes are done because we can't shoot asynchronous
185*06d5e247SLoGin     /// probe for given device and driver from bus_for_each_drv() since
186*06d5e247SLoGin     /// driver pointer is not guaranteed to stay valid once
187*06d5e247SLoGin     /// bus_for_each_drv() iterates to the next driver on the bus.
188*06d5e247SLoGin     want_async: bool,
189*06d5e247SLoGin 
190*06d5e247SLoGin     /// We'll set have_async to 'true' if, while scanning for matching
191*06d5e247SLoGin     /// driver, we'll encounter one that requests asynchronous probing.
192*06d5e247SLoGin     have_async: bool,
193*06d5e247SLoGin }
194*06d5e247SLoGin 
195*06d5e247SLoGin impl DeviceAttachData {
196*06d5e247SLoGin     pub fn new(dev: Arc<dyn Device>, check_async: bool, want_async: bool) -> Self {
197*06d5e247SLoGin         Self {
198*06d5e247SLoGin             dev,
199*06d5e247SLoGin             check_async,
200*06d5e247SLoGin             want_async,
201*06d5e247SLoGin             have_async: false,
202*06d5e247SLoGin         }
203*06d5e247SLoGin     }
204*06d5e247SLoGin 
205*06d5e247SLoGin     #[allow(dead_code)]
206*06d5e247SLoGin     #[inline(always)]
207*06d5e247SLoGin     fn set_have_async(&mut self) {
208*06d5e247SLoGin         self.have_async = true;
209*06d5e247SLoGin     }
210*06d5e247SLoGin }
211