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