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