xref: /DragonOS/kernel/src/driver/base/char/mod.rs (revision 0663027b111ffb6ff93becd60ffef1e2b8fbd4c6)
1*0663027bSTingHuang use super::{
2*0663027bSTingHuang     device::{mkdev, DeviceNumber, KObject},
3*0663027bSTingHuang     map::{kobj_map, kobj_unmap, LockedKObjMap},
4*0663027bSTingHuang };
5*0663027bSTingHuang use crate::{filesystem::vfs::IndexNode, kerror, libs::spinlock::SpinLock, syscall::SystemError};
6*0663027bSTingHuang use alloc::{sync::Arc, vec::Vec};
7*0663027bSTingHuang use core::cmp::Ordering;
8*0663027bSTingHuang 
9*0663027bSTingHuang const CHARDEV_MAJOR_HASH_SIZE: usize = 255;
10*0663027bSTingHuang const CHARDEV_MAJOR_MAX: usize = 512;
11*0663027bSTingHuang const MINOR_BITS: usize = 20;
12*0663027bSTingHuang const MINOR_MASK: usize = 1 << MINOR_BITS - 1;
13*0663027bSTingHuang /* Marks the bottom of the first segment of free char majors */
14*0663027bSTingHuang const CHARDEV_MAJOR_DYN_END: usize = 234;
15*0663027bSTingHuang /* Marks the top and bottom of the second segment of free char majors */
16*0663027bSTingHuang const CHARDEV_MAJOR_DYN_EXT_START: usize = 511;
17*0663027bSTingHuang const CHARDEV_MAJOR_DYN_EXT_END: usize = 384;
18*0663027bSTingHuang 
19*0663027bSTingHuang lazy_static! {
20*0663027bSTingHuang     // 全局字符设备号管理实例
21*0663027bSTingHuang     pub static ref CHARDEVS: Arc<LockedChrDevs> = Arc::new(LockedChrDevs::default());
22*0663027bSTingHuang 
23*0663027bSTingHuang     // 全局字符设备管理实例
24*0663027bSTingHuang     pub static ref CDEVMAP: Arc<LockedKObjMap> = Arc::new(LockedKObjMap::default());
25*0663027bSTingHuang }
26*0663027bSTingHuang 
27*0663027bSTingHuang pub trait CharDevice: KObject {
28*0663027bSTingHuang     /// @brief: 打开设备
29*0663027bSTingHuang     /// @parameter: file: devfs inode
30*0663027bSTingHuang     /// @return: 打开成功,返回OK(()),失败,返回错误代码
31*0663027bSTingHuang     fn open(&self, file: Arc<dyn IndexNode>) -> Result<(), SystemError>;
32*0663027bSTingHuang 
33*0663027bSTingHuang     /// @brief: 关闭设备
34*0663027bSTingHuang     /// @parameter: file: devfs inode
35*0663027bSTingHuang     /// @return: 关闭成功,返回OK(()),失败,返回错误代码
36*0663027bSTingHuang     fn close(&self, file: Arc<dyn IndexNode>) -> Result<(), SystemError>;
37*0663027bSTingHuang }
38*0663027bSTingHuang 
39*0663027bSTingHuang // 管理字符设备号的map(加锁)
40*0663027bSTingHuang pub struct LockedChrDevs(SpinLock<ChrDevs>);
41*0663027bSTingHuang 
42*0663027bSTingHuang impl Default for LockedChrDevs {
43*0663027bSTingHuang     fn default() -> Self {
44*0663027bSTingHuang         LockedChrDevs(SpinLock::new(ChrDevs::default()))
45*0663027bSTingHuang     }
46*0663027bSTingHuang }
47*0663027bSTingHuang 
48*0663027bSTingHuang // 管理字符设备号的map
49*0663027bSTingHuang #[derive(Debug)]
50*0663027bSTingHuang struct ChrDevs(Vec<Vec<CharDeviceStruct>>);
51*0663027bSTingHuang 
52*0663027bSTingHuang impl Default for ChrDevs {
53*0663027bSTingHuang     fn default() -> Self {
54*0663027bSTingHuang         ChrDevs(vec![Vec::new(); CHARDEV_MAJOR_HASH_SIZE])
55*0663027bSTingHuang     }
56*0663027bSTingHuang }
57*0663027bSTingHuang 
58*0663027bSTingHuang // 字符设备在系统中的实例,devfs通过该结构与实际字符设备进行联系
59*0663027bSTingHuang #[allow(dead_code)]
60*0663027bSTingHuang #[derive(Debug, Clone)]
61*0663027bSTingHuang pub struct CharDeviceStruct {
62*0663027bSTingHuang     dev_t: DeviceNumber, //起始设备号
63*0663027bSTingHuang     minorct: usize,      // 次设备号数量
64*0663027bSTingHuang     name: &'static str,  //字符设备名
65*0663027bSTingHuang }
66*0663027bSTingHuang 
67*0663027bSTingHuang impl CharDeviceStruct {
68*0663027bSTingHuang     /// @brief: 创建实例
69*0663027bSTingHuang     /// @parameter: dev_t: 设备号
70*0663027bSTingHuang     ///             minorct: 次设备号数量
71*0663027bSTingHuang     ///             name: 字符设备名
72*0663027bSTingHuang     ///             char: 字符设备实例
73*0663027bSTingHuang     /// @return: 实例
74*0663027bSTingHuang     ///
75*0663027bSTingHuang     #[allow(dead_code)]
76*0663027bSTingHuang     pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self {
77*0663027bSTingHuang         Self {
78*0663027bSTingHuang             dev_t,
79*0663027bSTingHuang             minorct,
80*0663027bSTingHuang             name,
81*0663027bSTingHuang         }
82*0663027bSTingHuang     }
83*0663027bSTingHuang 
84*0663027bSTingHuang     /// @brief: 获取起始次设备号
85*0663027bSTingHuang     /// @parameter: None
86*0663027bSTingHuang     /// @return: 起始设备号
87*0663027bSTingHuang     ///
88*0663027bSTingHuang     #[allow(dead_code)]
89*0663027bSTingHuang     pub fn device_number(&self) -> DeviceNumber {
90*0663027bSTingHuang         self.dev_t
91*0663027bSTingHuang     }
92*0663027bSTingHuang 
93*0663027bSTingHuang     /// @brief: 获取起始次设备号
94*0663027bSTingHuang     /// @parameter: None
95*0663027bSTingHuang     /// @return: 起始设备号
96*0663027bSTingHuang     ///
97*0663027bSTingHuang     #[allow(dead_code)]
98*0663027bSTingHuang     pub fn base_minor(&self) -> usize {
99*0663027bSTingHuang         self.dev_t.minor()
100*0663027bSTingHuang     }
101*0663027bSTingHuang 
102*0663027bSTingHuang     /// @brief: 获取次设备号数量
103*0663027bSTingHuang     /// @parameter: None
104*0663027bSTingHuang     /// @return: 次设备号数量
105*0663027bSTingHuang     #[allow(dead_code)]
106*0663027bSTingHuang     pub fn minorct(&self) -> usize {
107*0663027bSTingHuang         self.minorct
108*0663027bSTingHuang     }
109*0663027bSTingHuang }
110*0663027bSTingHuang 
111*0663027bSTingHuang /// @brief 字符设备框架函数集
112*0663027bSTingHuang pub struct CharDevOps;
113*0663027bSTingHuang 
114*0663027bSTingHuang impl CharDevOps {
115*0663027bSTingHuang     /// @brief: 主设备号转下标
116*0663027bSTingHuang     /// @parameter: major: 主设备号
117*0663027bSTingHuang     /// @return: 返回下标
118*0663027bSTingHuang     #[allow(dead_code)]
119*0663027bSTingHuang     fn major_to_index(major: usize) -> usize {
120*0663027bSTingHuang         return major % CHARDEV_MAJOR_HASH_SIZE;
121*0663027bSTingHuang     }
122*0663027bSTingHuang 
123*0663027bSTingHuang     /// @brief: 动态获取主设备号
124*0663027bSTingHuang     /// @parameter: None
125*0663027bSTingHuang     /// @return: 如果成功,返回主设备号,否则,返回错误码
126*0663027bSTingHuang     #[allow(dead_code)]
127*0663027bSTingHuang     fn find_dynamic_major() -> Result<usize, SystemError> {
128*0663027bSTingHuang         let chardevs = CHARDEVS.0.lock();
129*0663027bSTingHuang         // 寻找主设备号为234~255的设备
130*0663027bSTingHuang         for index in (CHARDEV_MAJOR_DYN_END..CHARDEV_MAJOR_HASH_SIZE).rev() {
131*0663027bSTingHuang             if let Some(item) = chardevs.0.get(index) {
132*0663027bSTingHuang                 if item.is_empty() {
133*0663027bSTingHuang                     return Ok(index); // 返回可用的主设备号
134*0663027bSTingHuang                 }
135*0663027bSTingHuang             }
136*0663027bSTingHuang         }
137*0663027bSTingHuang         // 寻找主设备号在384~511的设备
138*0663027bSTingHuang         for index in (CHARDEV_MAJOR_DYN_EXT_END + 1..CHARDEV_MAJOR_DYN_EXT_START + 1).rev() {
139*0663027bSTingHuang             if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) {
140*0663027bSTingHuang                 let mut flag = true;
141*0663027bSTingHuang                 for item in chardevss {
142*0663027bSTingHuang                     if item.device_number().major() == index {
143*0663027bSTingHuang                         flag = false;
144*0663027bSTingHuang                         break;
145*0663027bSTingHuang                     }
146*0663027bSTingHuang                 }
147*0663027bSTingHuang                 if flag {
148*0663027bSTingHuang                     // 如果数组中不存在主设备号等于index的设备
149*0663027bSTingHuang                     return Ok(index); // 返回可用的主设备号
150*0663027bSTingHuang                 }
151*0663027bSTingHuang             }
152*0663027bSTingHuang         }
153*0663027bSTingHuang         return Err(SystemError::EBUSY);
154*0663027bSTingHuang     }
155*0663027bSTingHuang 
156*0663027bSTingHuang     /// @brief: 注册设备号,该函数需要指定主设备号
157*0663027bSTingHuang     /// @parameter: from: 主设备号
158*0663027bSTingHuang     ///             count: 次设备号数量
159*0663027bSTingHuang     ///             name: 字符设备名
160*0663027bSTingHuang     /// @return: 如果注册成功,返回设备号,否则,返回错误码
161*0663027bSTingHuang     #[allow(dead_code)]
162*0663027bSTingHuang     pub fn register_chardev_region(
163*0663027bSTingHuang         from: DeviceNumber,
164*0663027bSTingHuang         count: usize,
165*0663027bSTingHuang         name: &'static str,
166*0663027bSTingHuang     ) -> Result<DeviceNumber, SystemError> {
167*0663027bSTingHuang         Self::__register_chardev_region(from, count, name)
168*0663027bSTingHuang     }
169*0663027bSTingHuang 
170*0663027bSTingHuang     /// @brief: 注册设备号,该函数自动分配主设备号
171*0663027bSTingHuang     /// @parameter: baseminor: 主设备号
172*0663027bSTingHuang     ///             count: 次设备号数量
173*0663027bSTingHuang     ///             name: 字符设备名
174*0663027bSTingHuang     /// @return: 如果注册成功,返回,否则,返回false
175*0663027bSTingHuang     #[allow(dead_code)]
176*0663027bSTingHuang     pub fn alloc_chardev_region(
177*0663027bSTingHuang         baseminor: usize,
178*0663027bSTingHuang         count: usize,
179*0663027bSTingHuang         name: &'static str,
180*0663027bSTingHuang     ) -> Result<DeviceNumber, SystemError> {
181*0663027bSTingHuang         Self::__register_chardev_region(mkdev(0, baseminor), count, name)
182*0663027bSTingHuang     }
183*0663027bSTingHuang 
184*0663027bSTingHuang     /// @brief: 注册设备号
185*0663027bSTingHuang     /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
186*0663027bSTingHuang     ///             minorct: 次设备号数量
187*0663027bSTingHuang     ///             name: 字符设备名
188*0663027bSTingHuang     /// @return: 如果注册成功,返回设备号,否则,返回错误码
189*0663027bSTingHuang     fn __register_chardev_region(
190*0663027bSTingHuang         device_number: DeviceNumber,
191*0663027bSTingHuang         minorct: usize,
192*0663027bSTingHuang         name: &'static str,
193*0663027bSTingHuang     ) -> Result<DeviceNumber, SystemError> {
194*0663027bSTingHuang         let mut major = device_number.major();
195*0663027bSTingHuang         let baseminor = device_number.minor();
196*0663027bSTingHuang         if major >= CHARDEV_MAJOR_MAX {
197*0663027bSTingHuang             kerror!(
198*0663027bSTingHuang                 "CHARDEV {} major requested {} is greater than the maximum {}\n",
199*0663027bSTingHuang                 name,
200*0663027bSTingHuang                 major,
201*0663027bSTingHuang                 CHARDEV_MAJOR_MAX - 1
202*0663027bSTingHuang             );
203*0663027bSTingHuang         }
204*0663027bSTingHuang         if minorct > MINOR_MASK + 1 - baseminor {
205*0663027bSTingHuang             kerror!("CHARDEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
206*0663027bSTingHuang                 name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
207*0663027bSTingHuang         }
208*0663027bSTingHuang         let chardev = CharDeviceStruct::new(mkdev(major, baseminor), minorct, name);
209*0663027bSTingHuang         if major == 0 {
210*0663027bSTingHuang             // 如果主设备号为0,则自动分配主设备号
211*0663027bSTingHuang             major = Self::find_dynamic_major().expect("Find synamic major error.\n");
212*0663027bSTingHuang         }
213*0663027bSTingHuang         if let Some(items) = CHARDEVS.0.lock().0.get_mut(Self::major_to_index(major)) {
214*0663027bSTingHuang             let mut insert_index: usize = 0;
215*0663027bSTingHuang             for (index, item) in items.iter().enumerate() {
216*0663027bSTingHuang                 insert_index = index;
217*0663027bSTingHuang                 match item.device_number().major().cmp(&major) {
218*0663027bSTingHuang                     Ordering::Less => continue,
219*0663027bSTingHuang                     Ordering::Greater => {
220*0663027bSTingHuang                         break; // 大于则向后插入
221*0663027bSTingHuang                     }
222*0663027bSTingHuang                     Ordering::Equal => {
223*0663027bSTingHuang                         if item.device_number().minor() + item.minorct() <= baseminor {
224*0663027bSTingHuang                             continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
225*0663027bSTingHuang                         }
226*0663027bSTingHuang                         if item.base_minor() >= baseminor + minorct {
227*0663027bSTingHuang                             break; // 在此处插入
228*0663027bSTingHuang                         }
229*0663027bSTingHuang                         return Err(SystemError::EBUSY); // 存在重合的次设备号
230*0663027bSTingHuang                     }
231*0663027bSTingHuang                 }
232*0663027bSTingHuang             }
233*0663027bSTingHuang             items.insert(insert_index, chardev);
234*0663027bSTingHuang         }
235*0663027bSTingHuang         return Ok(mkdev(major, baseminor));
236*0663027bSTingHuang     }
237*0663027bSTingHuang 
238*0663027bSTingHuang     /// @brief: 注销设备号
239*0663027bSTingHuang     /// @parameter: major: 主设备号,如果为0,动态分配
240*0663027bSTingHuang     ///             baseminor: 起始次设备号
241*0663027bSTingHuang     ///             minorct: 次设备号数量
242*0663027bSTingHuang     /// @return: 如果注销成功,返回(),否则,返回错误码
243*0663027bSTingHuang     fn __unregister_chardev_region(
244*0663027bSTingHuang         device_number: DeviceNumber,
245*0663027bSTingHuang         minorct: usize,
246*0663027bSTingHuang     ) -> Result<(), SystemError> {
247*0663027bSTingHuang         if let Some(items) = CHARDEVS
248*0663027bSTingHuang             .0
249*0663027bSTingHuang             .lock()
250*0663027bSTingHuang             .0
251*0663027bSTingHuang             .get_mut(Self::major_to_index(device_number.major()))
252*0663027bSTingHuang         {
253*0663027bSTingHuang             for (index, item) in items.iter().enumerate() {
254*0663027bSTingHuang                 if item.device_number() == device_number && item.minorct() == minorct {
255*0663027bSTingHuang                     // 设备号和数量都相等
256*0663027bSTingHuang                     items.remove(index);
257*0663027bSTingHuang                     return Ok(());
258*0663027bSTingHuang                 }
259*0663027bSTingHuang             }
260*0663027bSTingHuang         }
261*0663027bSTingHuang         return Err(SystemError::EBUSY);
262*0663027bSTingHuang     }
263*0663027bSTingHuang 
264*0663027bSTingHuang     /// @brief: 字符设备注册
265*0663027bSTingHuang     /// @parameter: cdev: 字符设备实例
266*0663027bSTingHuang     ///             dev_t: 字符设备号
267*0663027bSTingHuang     ///             range: 次设备号范围
268*0663027bSTingHuang     /// @return: none
269*0663027bSTingHuang     #[allow(dead_code)]
270*0663027bSTingHuang     pub fn cdev_add(cdev: Arc<dyn CharDevice>, dev_t: DeviceNumber, range: usize) {
271*0663027bSTingHuang         if Into::<usize>::into(dev_t) == 0 {
272*0663027bSTingHuang             kerror!("Device number can't be 0!\n");
273*0663027bSTingHuang         }
274*0663027bSTingHuang         kobj_map(CDEVMAP.clone(), dev_t, range, cdev);
275*0663027bSTingHuang     }
276*0663027bSTingHuang 
277*0663027bSTingHuang     /// @brief: 字符设备注销
278*0663027bSTingHuang     /// @parameter: dev_t: 字符设备号
279*0663027bSTingHuang     ///             range: 次设备号范围
280*0663027bSTingHuang     /// @return: none
281*0663027bSTingHuang     #[allow(dead_code)]
282*0663027bSTingHuang     pub fn cdev_del(dev_t: DeviceNumber, range: usize) {
283*0663027bSTingHuang         kobj_unmap(CDEVMAP.clone(), dev_t, range);
284*0663027bSTingHuang     }
285*0663027bSTingHuang }
286