xref: /DragonOS/kernel/src/driver/base/map/mod.rs (revision b087521e07f601b30e3d48df788fcc2f09f19566)
1 use core::cmp::Ordering;
2 
3 use super::{
4     block::block_device::BlockDevice,
5     char::CharDevice,
6     device::{mkdev, DeviceNumber, IdTable, KObject, BLOCKDEVS, CHARDEVS, DEVICE_MANAGER, DEVMAP},
7 };
8 use crate::{kerror, libs::spinlock::SpinLock, syscall::SystemError};
9 use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
10 
11 const KOBJMAP_HASH_SIZE: usize = 255;
12 const DEV_MAJOR_HASH_SIZE: usize = 255;
13 const DEV_MAJOR_MAX: usize = 512;
14 const MINOR_BITS: usize = 20;
15 const MINOR_MASK: usize = 1 << MINOR_BITS - 1;
16 /* Marks the bottom of the first segment of free char majors */
17 const DEV_MAJOR_DYN_END: usize = 234;
18 /* Marks the top and bottom of the second segment of free char majors */
19 const DEV_MAJOR_DYN_EXT_START: usize = 511;
20 const DEV_MAJOR_DYN_EXT_END: usize = 384;
21 
22 /// @brief: 字符设备与块设备管理结构体
23 #[derive(Debug, Clone)]
24 struct Probe(Arc<dyn KObject>);
25 
26 impl Probe {
27     /// @brief: 新建probe实例
28     /// @parameter: data: probe实例
29     /// @return: probe实例
30     pub fn new(data: Arc<dyn KObject>) -> Self {
31         Self(data)
32     }
33 }
34 
35 /// @brief: 字符设备和块设备管理实例(锁)
36 #[derive(Debug)]
37 pub struct LockedKObjMap(SpinLock<KObjMap>);
38 
39 impl Default for LockedKObjMap {
40     fn default() -> Self {
41         Self(SpinLock::new(KObjMap::default()))
42     }
43 }
44 
45 /// @brief: 字符设备和块设备管理实例
46 #[derive(Debug, Clone)]
47 struct KObjMap(Vec<BTreeMap<DeviceNumber, Probe>>);
48 
49 impl Default for KObjMap {
50     fn default() -> Self {
51         Self(vec![BTreeMap::new(); KOBJMAP_HASH_SIZE])
52     }
53 }
54 
55 /// @brief: obj设备注册
56 /// @parameter: domain: 管理实例
57 ///             dev_t: 设备号
58 ///             range: 次设备号范围
59 ///             data: 设备实例
60 /// @return: none
61 pub fn kobj_map(
62     domain: Arc<LockedKObjMap>,
63     dev_t: DeviceNumber,
64     range: usize,
65     data: Arc<dyn KObject>,
66 ) {
67     if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
68         for i in 0..range {
69             map.insert(
70                 mkdev(dev_t.major(), dev_t.minor() + i),
71                 Probe::new(data.clone()),
72             );
73         }
74     }
75 }
76 
77 /// @brief: obj设备注销
78 /// @parameter: domain: 管理实例
79 ///             dev_t: 设备号
80 ///             range: 次设备号范围
81 /// @return: none
82 pub fn kobj_unmap(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber, range: usize) {
83     if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
84         for i in 0..range {
85             let rm_dev_t = &DeviceNumber::new(Into::<usize>::into(dev_t) + i);
86             match map.get(rm_dev_t) {
87                 Some(_) => {
88                     map.remove(rm_dev_t);
89                 }
90                 None => {}
91             }
92         }
93     }
94 }
95 
96 /// @brief: 设备查找
97 /// @parameter: domain: 管理实例
98 ///             dev_t: 设备号
99 /// @return: 查找成功,返回设备实例,否则返回None
100 #[allow(dead_code)]
101 pub fn kobj_lookup(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber) -> Option<Arc<dyn KObject>> {
102     if let Some(map) = domain.0.lock().0.get(dev_t.major() % 255) {
103         match map.get(&dev_t) {
104             Some(value) => {
105                 return Some(value.0.clone());
106             }
107             None => {
108                 return None;
109             }
110         }
111     }
112     return None;
113 }
114 
115 // 管理字符设备号的map(加锁)
116 pub struct LockedDevsMap(SpinLock<DevsMap>);
117 
118 impl Default for LockedDevsMap {
119     fn default() -> Self {
120         LockedDevsMap(SpinLock::new(DevsMap::default()))
121     }
122 }
123 
124 // 管理字符设备号的map
125 #[derive(Debug)]
126 struct DevsMap(Vec<Vec<DeviceStruct>>);
127 
128 impl Default for DevsMap {
129     fn default() -> Self {
130         DevsMap(vec![Vec::new(); DEV_MAJOR_HASH_SIZE])
131     }
132 }
133 
134 // 字符设备在系统中的实例,devfs通过该结构与实际字符设备进行联系
135 #[allow(dead_code)]
136 #[derive(Debug, Clone)]
137 pub struct DeviceStruct {
138     dev_t: DeviceNumber, //起始设备号
139     minorct: usize,      // 次设备号数量
140     name: &'static str,  //字符设备名
141 }
142 
143 impl DeviceStruct {
144     /// @brief: 创建实例
145     /// @parameter: dev_t: 设备号
146     ///             minorct: 次设备号数量
147     ///             name: 字符设备名
148     ///             char: 字符设备实例
149     /// @return: 实例
150     ///
151     #[allow(dead_code)]
152     pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self {
153         Self {
154             dev_t,
155             minorct,
156             name,
157         }
158     }
159 
160     /// @brief: 获取起始次设备号
161     /// @parameter: None
162     /// @return: 起始设备号
163     ///
164     #[allow(dead_code)]
165     pub fn device_number(&self) -> DeviceNumber {
166         self.dev_t
167     }
168 
169     /// @brief: 获取起始次设备号
170     /// @parameter: None
171     /// @return: 起始设备号
172     ///
173     #[allow(dead_code)]
174     pub fn base_minor(&self) -> usize {
175         self.dev_t.minor()
176     }
177 
178     /// @brief: 获取次设备号数量
179     /// @parameter: None
180     /// @return: 次设备号数量
181     #[allow(dead_code)]
182     pub fn minorct(&self) -> usize {
183         self.minorct
184     }
185 }
186 
187 // 这下面是考虑到 块设备的注册和字符设备的注册在设备号的自动分配上要有所区别,
188 // 暂时没有去查具体是怎么做区分的,因此暂时还是一样的
189 
190 /// @brief 块设备框架函数集
191 pub struct BlockDeviceOps;
192 
193 impl BlockDeviceOps {
194     /// @brief: 主设备号转下标
195     /// @parameter: major: 主设备号
196     /// @return: 返回下标
197     #[allow(dead_code)]
198     fn major_to_index(major: usize) -> usize {
199         return major % DEV_MAJOR_HASH_SIZE;
200     }
201 
202     /// @brief: 动态获取主设备号
203     /// @parameter: None
204     /// @return: 如果成功,返回主设备号,否则,返回错误码
205     #[allow(dead_code)]
206     fn find_dynamic_major() -> Result<usize, SystemError> {
207         let blockdevs = BLOCKDEVS.0.lock();
208         // 寻找主设备号为234~255的设备
209         for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
210             if let Some(item) = blockdevs.0.get(index) {
211                 if item.is_empty() {
212                     return Ok(index); // 返回可用的主设备号
213                 }
214             }
215         }
216         // 寻找主设备号在384~511的设备
217         for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() {
218             if let Some(blockdevss) = blockdevs.0.get(Self::major_to_index(index)) {
219                 let mut flag = true;
220                 for item in blockdevss {
221                     if item.device_number().major() == index {
222                         flag = false;
223                         break;
224                     }
225                 }
226                 if flag {
227                     // 如果数组中不存在主设备号等于index的设备
228                     return Ok(index); // 返回可用的主设备号
229                 }
230             }
231         }
232         return Err(SystemError::EBUSY);
233     }
234 
235     /// @brief: 注册设备号,该函数需要指定主设备号
236     /// @parameter: from: 主设备号
237     ///             count: 次设备号数量
238     ///             name: 字符设备名
239     /// @return: 如果注册成功,返回设备号,否则,返回错误码
240     #[allow(dead_code)]
241     pub fn register_blockdev_region(
242         from: DeviceNumber,
243         count: usize,
244         name: &'static str,
245     ) -> Result<DeviceNumber, SystemError> {
246         Self::__register_blockdev_region(from, count, name)
247     }
248 
249     /// @brief: 注册设备号,该函数自动分配主设备号
250     /// @parameter: baseminor: 主设备号
251     ///             count: 次设备号数量
252     ///             name: 字符设备名
253     /// @return: 如果注册成功,返回,否则,返回false
254     #[allow(dead_code)]
255     pub fn alloc_blockdev_region(
256         baseminor: usize,
257         count: usize,
258         name: &'static str,
259     ) -> Result<DeviceNumber, SystemError> {
260         Self::__register_blockdev_region(mkdev(0, baseminor), count, name)
261     }
262 
263     /// @brief: 注册设备号
264     /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
265     ///             minorct: 次设备号数量
266     ///             name: 字符设备名
267     /// @return: 如果注册成功,返回设备号,否则,返回错误码
268     fn __register_blockdev_region(
269         device_number: DeviceNumber,
270         minorct: usize,
271         name: &'static str,
272     ) -> Result<DeviceNumber, SystemError> {
273         let mut major = device_number.major();
274         let baseminor = device_number.minor();
275         if major >= DEV_MAJOR_MAX {
276             kerror!(
277                 "DEV {} major requested {} is greater than the maximum {}\n",
278                 name,
279                 major,
280                 DEV_MAJOR_MAX - 1
281             );
282         }
283         if minorct > MINOR_MASK + 1 - baseminor {
284             kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
285                 name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
286         }
287         let blockdev = DeviceStruct::new(mkdev(major, baseminor), minorct, name);
288         if major == 0 {
289             // 如果主设备号为0,则自动分配主设备号
290             major = Self::find_dynamic_major().expect("Find synamic major error.\n");
291         }
292         if let Some(items) = BLOCKDEVS.0.lock().0.get_mut(Self::major_to_index(major)) {
293             let mut insert_index: usize = 0;
294             for (index, item) in items.iter().enumerate() {
295                 insert_index = index;
296                 match item.device_number().major().cmp(&major) {
297                     Ordering::Less => continue,
298                     Ordering::Greater => {
299                         break; // 大于则向后插入
300                     }
301                     Ordering::Equal => {
302                         if item.device_number().minor() + item.minorct() <= baseminor {
303                             continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
304                         }
305                         if item.base_minor() >= baseminor + minorct {
306                             break; // 在此处插入
307                         }
308                         return Err(SystemError::EBUSY); // 存在重合的次设备号
309                     }
310                 }
311             }
312             items.insert(insert_index, blockdev);
313         }
314         return Ok(mkdev(major, baseminor));
315     }
316 
317     /// @brief: 注销设备号
318     /// @parameter: major: 主设备号,如果为0,动态分配
319     ///             baseminor: 起始次设备号
320     ///             minorct: 次设备号数量
321     /// @return: 如果注销成功,返回(),否则,返回错误码
322     fn __unregister_blockdev_region(
323         device_number: DeviceNumber,
324         minorct: usize,
325     ) -> Result<(), SystemError> {
326         if let Some(items) = BLOCKDEVS
327             .0
328             .lock()
329             .0
330             .get_mut(Self::major_to_index(device_number.major()))
331         {
332             for (index, item) in items.iter().enumerate() {
333                 if item.device_number() == device_number && item.minorct() == minorct {
334                     // 设备号和数量都相等
335                     items.remove(index);
336                     return Ok(());
337                 }
338             }
339         }
340         return Err(SystemError::EBUSY);
341     }
342 
343     /// @brief: 块设备注册
344     /// @parameter: cdev: 字符设备实例
345     ///             dev_t: 字符设备号
346     ///             range: 次设备号范围
347     /// @return: none
348     #[allow(dead_code)]
349     pub fn bdev_add(bdev: Arc<dyn BlockDevice>, id_table: IdTable) {
350         if Into::<usize>::into(id_table.device_number()) == 0 {
351             kerror!("Device number can't be 0!\n");
352         }
353         DEVICE_MANAGER.add_device(id_table, bdev.device())
354     }
355 
356     /// @brief: block设备注销
357     /// @parameter: dev_t: 字符设备号
358     ///             range: 次设备号范围
359     /// @return: none
360     #[allow(dead_code)]
361     pub fn bdev_del(_devnum: DeviceNumber, _range: usize) {}
362 }
363 
364 /// @brief 字符设备框架函数集
365 pub struct CharDevOps;
366 
367 impl CharDevOps {
368     /// @brief: 主设备号转下标
369     /// @parameter: major: 主设备号
370     /// @return: 返回下标
371     #[allow(dead_code)]
372     fn major_to_index(major: usize) -> usize {
373         return major % DEV_MAJOR_HASH_SIZE;
374     }
375 
376     /// @brief: 动态获取主设备号
377     /// @parameter: None
378     /// @return: 如果成功,返回主设备号,否则,返回错误码
379     #[allow(dead_code)]
380     fn find_dynamic_major() -> Result<usize, SystemError> {
381         let chardevs = CHARDEVS.0.lock();
382         // 寻找主设备号为234~255的设备
383         for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
384             if let Some(item) = chardevs.0.get(index) {
385                 if item.is_empty() {
386                     return Ok(index); // 返回可用的主设备号
387                 }
388             }
389         }
390         // 寻找主设备号在384~511的设备
391         for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() {
392             if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) {
393                 let mut flag = true;
394                 for item in chardevss {
395                     if item.device_number().major() == index {
396                         flag = false;
397                         break;
398                     }
399                 }
400                 if flag {
401                     // 如果数组中不存在主设备号等于index的设备
402                     return Ok(index); // 返回可用的主设备号
403                 }
404             }
405         }
406         return Err(SystemError::EBUSY);
407     }
408 
409     /// @brief: 注册设备号,该函数需要指定主设备号
410     /// @parameter: from: 主设备号
411     ///             count: 次设备号数量
412     ///             name: 字符设备名
413     /// @return: 如果注册成功,返回设备号,否则,返回错误码
414     #[allow(dead_code)]
415     pub fn register_chardev_region(
416         from: DeviceNumber,
417         count: usize,
418         name: &'static str,
419     ) -> Result<DeviceNumber, SystemError> {
420         Self::__register_chardev_region(from, count, name)
421     }
422 
423     /// @brief: 注册设备号,该函数自动分配主设备号
424     /// @parameter: baseminor: 次设备号
425     ///             count: 次设备号数量
426     ///             name: 字符设备名
427     /// @return: 如果注册成功,返回,否则,返回false
428     #[allow(dead_code)]
429     pub fn alloc_chardev_region(
430         baseminor: usize,
431         count: usize,
432         name: &'static str,
433     ) -> Result<DeviceNumber, SystemError> {
434         Self::__register_chardev_region(mkdev(0, baseminor), count, name)
435     }
436 
437     /// @brief: 注册设备号
438     /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
439     ///             minorct: 次设备号数量
440     ///             name: 字符设备名
441     /// @return: 如果注册成功,返回设备号,否则,返回错误码
442     fn __register_chardev_region(
443         device_number: DeviceNumber,
444         minorct: usize,
445         name: &'static str,
446     ) -> Result<DeviceNumber, SystemError> {
447         let mut major = device_number.major();
448         let baseminor = device_number.minor();
449         if major >= DEV_MAJOR_MAX {
450             kerror!(
451                 "DEV {} major requested {} is greater than the maximum {}\n",
452                 name,
453                 major,
454                 DEV_MAJOR_MAX - 1
455             );
456         }
457         if minorct > MINOR_MASK + 1 - baseminor {
458             kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
459                 name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
460         }
461         let chardev = DeviceStruct::new(mkdev(major, baseminor), minorct, name);
462         if major == 0 {
463             // 如果主设备号为0,则自动分配主设备号
464             major = Self::find_dynamic_major().expect("Find synamic major error.\n");
465         }
466         if let Some(items) = CHARDEVS.0.lock().0.get_mut(Self::major_to_index(major)) {
467             let mut insert_index: usize = 0;
468             for (index, item) in items.iter().enumerate() {
469                 insert_index = index;
470                 match item.device_number().major().cmp(&major) {
471                     Ordering::Less => continue,
472                     Ordering::Greater => {
473                         break; // 大于则向后插入
474                     }
475                     Ordering::Equal => {
476                         if item.device_number().minor() + item.minorct() <= baseminor {
477                             continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
478                         }
479                         if item.base_minor() >= baseminor + minorct {
480                             break; // 在此处插入
481                         }
482                         return Err(SystemError::EBUSY); // 存在重合的次设备号
483                     }
484                 }
485             }
486             items.insert(insert_index, chardev);
487         }
488         return Ok(mkdev(major, baseminor));
489     }
490 
491     /// @brief: 注销设备号
492     /// @parameter: major: 主设备号,如果为0,动态分配
493     ///             baseminor: 起始次设备号
494     ///             minorct: 次设备号数量
495     /// @return: 如果注销成功,返回(),否则,返回错误码
496     fn __unregister_chardev_region(
497         device_number: DeviceNumber,
498         minorct: usize,
499     ) -> Result<(), SystemError> {
500         if let Some(items) = CHARDEVS
501             .0
502             .lock()
503             .0
504             .get_mut(Self::major_to_index(device_number.major()))
505         {
506             for (index, item) in items.iter().enumerate() {
507                 if item.device_number() == device_number && item.minorct() == minorct {
508                     // 设备号和数量都相等
509                     items.remove(index);
510                     return Ok(());
511                 }
512             }
513         }
514         return Err(SystemError::EBUSY);
515     }
516 
517     /// @brief: 字符设备注册
518     /// @parameter: cdev: 字符设备实例
519     ///             dev_t: 字符设备号
520     ///             range: 次设备号范围
521     /// @return: none
522     #[allow(dead_code)]
523     pub fn cdev_add(cdev: Arc<dyn CharDevice>, id_table: IdTable, range: usize) {
524         if Into::<usize>::into(id_table.device_number()) == 0 {
525             kerror!("Device number can't be 0!\n");
526         }
527         DEVICE_MANAGER.add_device(id_table.clone(), cdev.clone());
528         kobj_map(
529             DEVMAP.clone(),
530             id_table.device_number(),
531             range,
532             cdev.clone(),
533         )
534     }
535 
536     /// @brief: 字符设备注销
537     /// @parameter: dev_t: 字符设备号
538     ///             range: 次设备号范围
539     /// @return: none
540     #[allow(dead_code)]
541     pub fn cdev_del(id_table: IdTable, range: usize) {
542         DEVICE_MANAGER.remove_device(&id_table);
543         kobj_unmap(DEVMAP.clone(), id_table.device_number(), range);
544     }
545 }
546