diff --git a/kernel/src/driver/base/char/mod.rs b/kernel/src/driver/base/char/mod.rs new file mode 100644 index 00000000..7637069d --- /dev/null +++ b/kernel/src/driver/base/char/mod.rs @@ -0,0 +1,285 @@ +use super::{ + device::{mkdev, DeviceNumber, KObject}, + map::{kobj_map, kobj_unmap, LockedKObjMap}, +}; +use crate::{filesystem::vfs::IndexNode, kerror, libs::spinlock::SpinLock, syscall::SystemError}; +use alloc::{sync::Arc, vec::Vec}; +use core::cmp::Ordering; + +const CHARDEV_MAJOR_HASH_SIZE: usize = 255; +const CHARDEV_MAJOR_MAX: usize = 512; +const MINOR_BITS: usize = 20; +const MINOR_MASK: usize = 1 << MINOR_BITS - 1; +/* Marks the bottom of the first segment of free char majors */ +const CHARDEV_MAJOR_DYN_END: usize = 234; +/* Marks the top and bottom of the second segment of free char majors */ +const CHARDEV_MAJOR_DYN_EXT_START: usize = 511; +const CHARDEV_MAJOR_DYN_EXT_END: usize = 384; + +lazy_static! { + // 全局字符设备号管理实例 + pub static ref CHARDEVS: Arc = Arc::new(LockedChrDevs::default()); + + // 全局字符设备管理实例 + pub static ref CDEVMAP: Arc = Arc::new(LockedKObjMap::default()); +} + +pub trait CharDevice: KObject { + /// @brief: 打开设备 + /// @parameter: file: devfs inode + /// @return: 打开成功,返回OK(()),失败,返回错误代码 + fn open(&self, file: Arc) -> Result<(), SystemError>; + + /// @brief: 关闭设备 + /// @parameter: file: devfs inode + /// @return: 关闭成功,返回OK(()),失败,返回错误代码 + fn close(&self, file: Arc) -> Result<(), SystemError>; +} + +// 管理字符设备号的map(加锁) +pub struct LockedChrDevs(SpinLock); + +impl Default for LockedChrDevs { + fn default() -> Self { + LockedChrDevs(SpinLock::new(ChrDevs::default())) + } +} + +// 管理字符设备号的map +#[derive(Debug)] +struct ChrDevs(Vec>); + +impl Default for ChrDevs { + fn default() -> Self { + ChrDevs(vec![Vec::new(); CHARDEV_MAJOR_HASH_SIZE]) + } +} + +// 字符设备在系统中的实例,devfs通过该结构与实际字符设备进行联系 +#[allow(dead_code)] +#[derive(Debug, Clone)] +pub struct CharDeviceStruct { + dev_t: DeviceNumber, //起始设备号 + minorct: usize, // 次设备号数量 + name: &'static str, //字符设备名 +} + +impl CharDeviceStruct { + /// @brief: 创建实例 + /// @parameter: dev_t: 设备号 + /// minorct: 次设备号数量 + /// name: 字符设备名 + /// char: 字符设备实例 + /// @return: 实例 + /// + #[allow(dead_code)] + pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self { + Self { + dev_t, + minorct, + name, + } + } + + /// @brief: 获取起始次设备号 + /// @parameter: None + /// @return: 起始设备号 + /// + #[allow(dead_code)] + pub fn device_number(&self) -> DeviceNumber { + self.dev_t + } + + /// @brief: 获取起始次设备号 + /// @parameter: None + /// @return: 起始设备号 + /// + #[allow(dead_code)] + pub fn base_minor(&self) -> usize { + self.dev_t.minor() + } + + /// @brief: 获取次设备号数量 + /// @parameter: None + /// @return: 次设备号数量 + #[allow(dead_code)] + pub fn minorct(&self) -> usize { + self.minorct + } +} + +/// @brief 字符设备框架函数集 +pub struct CharDevOps; + +impl CharDevOps { + /// @brief: 主设备号转下标 + /// @parameter: major: 主设备号 + /// @return: 返回下标 + #[allow(dead_code)] + fn major_to_index(major: usize) -> usize { + return major % CHARDEV_MAJOR_HASH_SIZE; + } + + /// @brief: 动态获取主设备号 + /// @parameter: None + /// @return: 如果成功,返回主设备号,否则,返回错误码 + #[allow(dead_code)] + fn find_dynamic_major() -> Result { + let chardevs = CHARDEVS.0.lock(); + // 寻找主设备号为234~255的设备 + for index in (CHARDEV_MAJOR_DYN_END..CHARDEV_MAJOR_HASH_SIZE).rev() { + if let Some(item) = chardevs.0.get(index) { + if item.is_empty() { + return Ok(index); // 返回可用的主设备号 + } + } + } + // 寻找主设备号在384~511的设备 + for index in (CHARDEV_MAJOR_DYN_EXT_END + 1..CHARDEV_MAJOR_DYN_EXT_START + 1).rev() { + if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) { + let mut flag = true; + for item in chardevss { + if item.device_number().major() == index { + flag = false; + break; + } + } + if flag { + // 如果数组中不存在主设备号等于index的设备 + return Ok(index); // 返回可用的主设备号 + } + } + } + return Err(SystemError::EBUSY); + } + + /// @brief: 注册设备号,该函数需要指定主设备号 + /// @parameter: from: 主设备号 + /// count: 次设备号数量 + /// name: 字符设备名 + /// @return: 如果注册成功,返回设备号,否则,返回错误码 + #[allow(dead_code)] + pub fn register_chardev_region( + from: DeviceNumber, + count: usize, + name: &'static str, + ) -> Result { + Self::__register_chardev_region(from, count, name) + } + + /// @brief: 注册设备号,该函数自动分配主设备号 + /// @parameter: baseminor: 主设备号 + /// count: 次设备号数量 + /// name: 字符设备名 + /// @return: 如果注册成功,返回,否则,返回false + #[allow(dead_code)] + pub fn alloc_chardev_region( + baseminor: usize, + count: usize, + name: &'static str, + ) -> Result { + Self::__register_chardev_region(mkdev(0, baseminor), count, name) + } + + /// @brief: 注册设备号 + /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配 + /// minorct: 次设备号数量 + /// name: 字符设备名 + /// @return: 如果注册成功,返回设备号,否则,返回错误码 + fn __register_chardev_region( + device_number: DeviceNumber, + minorct: usize, + name: &'static str, + ) -> Result { + let mut major = device_number.major(); + let baseminor = device_number.minor(); + if major >= CHARDEV_MAJOR_MAX { + kerror!( + "CHARDEV {} major requested {} is greater than the maximum {}\n", + name, + major, + CHARDEV_MAJOR_MAX - 1 + ); + } + if minorct > MINOR_MASK + 1 - baseminor { + kerror!("CHARDEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n", + name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK); + } + let chardev = CharDeviceStruct::new(mkdev(major, baseminor), minorct, name); + if major == 0 { + // 如果主设备号为0,则自动分配主设备号 + major = Self::find_dynamic_major().expect("Find synamic major error.\n"); + } + if let Some(items) = CHARDEVS.0.lock().0.get_mut(Self::major_to_index(major)) { + let mut insert_index: usize = 0; + for (index, item) in items.iter().enumerate() { + insert_index = index; + match item.device_number().major().cmp(&major) { + Ordering::Less => continue, + Ordering::Greater => { + break; // 大于则向后插入 + } + Ordering::Equal => { + if item.device_number().minor() + item.minorct() <= baseminor { + continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值 + } + if item.base_minor() >= baseminor + minorct { + break; // 在此处插入 + } + return Err(SystemError::EBUSY); // 存在重合的次设备号 + } + } + } + items.insert(insert_index, chardev); + } + return Ok(mkdev(major, baseminor)); + } + + /// @brief: 注销设备号 + /// @parameter: major: 主设备号,如果为0,动态分配 + /// baseminor: 起始次设备号 + /// minorct: 次设备号数量 + /// @return: 如果注销成功,返回(),否则,返回错误码 + fn __unregister_chardev_region( + device_number: DeviceNumber, + minorct: usize, + ) -> Result<(), SystemError> { + if let Some(items) = CHARDEVS + .0 + .lock() + .0 + .get_mut(Self::major_to_index(device_number.major())) + { + for (index, item) in items.iter().enumerate() { + if item.device_number() == device_number && item.minorct() == minorct { + // 设备号和数量都相等 + items.remove(index); + return Ok(()); + } + } + } + return Err(SystemError::EBUSY); + } + + /// @brief: 字符设备注册 + /// @parameter: cdev: 字符设备实例 + /// dev_t: 字符设备号 + /// range: 次设备号范围 + /// @return: none + #[allow(dead_code)] + pub fn cdev_add(cdev: Arc, dev_t: DeviceNumber, range: usize) { + if Into::::into(dev_t) == 0 { + kerror!("Device number can't be 0!\n"); + } + kobj_map(CDEVMAP.clone(), dev_t, range, cdev); + } + + /// @brief: 字符设备注销 + /// @parameter: dev_t: 字符设备号 + /// range: 次设备号范围 + /// @return: none + #[allow(dead_code)] + pub fn cdev_del(dev_t: DeviceNumber, range: usize) { + kobj_unmap(CDEVMAP.clone(), dev_t, range); + } +} diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index 8074df1e..48617577 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -175,8 +175,8 @@ impl LockedBusManager { /// @parameter bus: Bus设备实体 /// @return: 成功:() 失败:DeviceError pub fn bus_register(bus: Arc) -> Result<(), DeviceError> { - BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone()); - match sys_bus_register(&bus.get_id_table().to_name()) { + BUS_MANAGER.add_bus(bus.id_table(), bus.clone()); + match sys_bus_register(&bus.id_table().to_name()) { Ok(inode) => { let _ = sys_bus_init(&inode); return device_register(bus); @@ -190,7 +190,7 @@ pub fn bus_register(bus: Arc) -> Result<(), DeviceError> { /// @return: 成功:() 失败:DeviceError #[allow(dead_code)] pub fn bus_unregister(bus: Arc) -> Result<(), DeviceError> { - BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone()); + BUS_MANAGER.add_bus(bus.id_table(), bus.clone()); return device_unregister(bus); } @@ -198,7 +198,7 @@ pub fn bus_unregister(bus: Arc) -> Result<(), DeviceError> { /// @parameter bus: Bus设备驱动实体 /// @return: 成功:() 失败:DeviceError pub fn bus_driver_register(bus_driver: Arc) -> Result<(), DriverError> { - BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone()); + BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone()); return driver_register(bus_driver); } @@ -207,6 +207,6 @@ pub fn bus_driver_register(bus_driver: Arc) -> Result<(), Drive /// @return: 成功:() 失败:DeviceError #[allow(dead_code)] pub fn bus_driver_unregister(bus_driver: Arc) -> Result<(), DriverError> { - BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone()); + BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone()); return driver_unregister(bus_driver); } diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index d7a5ba39..79d3daff 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -1,7 +1,7 @@ -use super::IdTable; +use super::{IdTable, KObject}; use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError}; use alloc::{collections::BTreeMap, sync::Arc}; -use core::{any::Any, fmt::Debug}; +use core::fmt::Debug; lazy_static! { pub static ref DRIVER_MANAGER: Arc = Arc::new(LockedDriverManager::new()); @@ -25,16 +25,16 @@ impl Into for DriverError { } /// @brief: 所有驱动驱动都应该实现该trait -pub trait Driver: Any + Send + Sync + Debug { +pub trait Driver: KObject { /// @brief: 本函数用于实现动态转换 /// @parameter: None - /// @return: 该驱动驱动唯一标识符 + /// @return: any fn as_any_ref(&'static self) -> &'static dyn core::any::Any; /// @brief: 获取驱动驱动标识符 /// @parameter: None /// @return: 该驱动驱动唯一标识符 - fn get_id_table(&self) -> IdTable; + fn id_table(&self) -> IdTable; /// @brief: 设置驱动的sys information /// @parameter id_table: 驱动标识符,用于唯一标识该驱动 @@ -125,7 +125,7 @@ impl DriverManager { /// @parameter: name: 驱动名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn driver_register(driver: Arc) -> Result<(), DriverError> { - DRIVER_MANAGER.add_driver(driver.get_id_table(), driver); + DRIVER_MANAGER.add_driver(driver.id_table(), driver); return Ok(()); } @@ -134,6 +134,6 @@ pub fn driver_register(driver: Arc) -> Result<(), DriverError> { /// @return: 操作成功,返回(),操作失败,返回错误码 #[allow(dead_code)] pub fn driver_unregister(driver: Arc) -> Result<(), DriverError> { - DRIVER_MANAGER.add_driver(driver.get_id_table(), driver); + DRIVER_MANAGER.add_driver(driver.id_table(), driver); return Ok(()); } diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index aa4bf943..ccce9758 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -1,5 +1,3 @@ -use alloc::{collections::BTreeMap, string::String, sync::Arc}; - use crate::{ filesystem::{ sysfs::{ @@ -11,6 +9,7 @@ use crate::{ libs::spinlock::SpinLock, syscall::SystemError, }; +use alloc::{collections::BTreeMap, string::String, sync::Arc}; use core::{any::Any, fmt::Debug}; pub mod bus; @@ -20,6 +19,61 @@ lazy_static! { pub static ref DEVICE_MANAGER: Arc = Arc::new(LockedDeviceManager::new()); } +pub trait KObject: Any + Send + Sync + Debug {} + +/// @brief: 设备号实例 +#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] +pub struct DeviceNumber(usize); + +impl Default for DeviceNumber { + fn default() -> Self { + DeviceNumber(0) + } +} + +impl From for DeviceNumber { + fn from(dev_t: usize) -> Self { + DeviceNumber(dev_t) + } +} + +impl Into for DeviceNumber { + fn into(self) -> usize { + self.0 + } +} + +impl DeviceNumber { + /// @brief: 设备号创建 + /// @parameter: dev_t: 设备号 + /// @return: 设备号实例 + pub fn new(dev_t: usize) -> DeviceNumber { + Self(dev_t) + } + + /// @brief: 获取主设备号 + /// @parameter: none + /// @return: 主设备号 + pub fn major(&self) -> usize { + (self.0 >> 20) & 0xfff + } + + /// @brief: 获取次设备号 + /// @parameter: none + /// @return: 次设备号 + pub fn minor(&self) -> usize { + self.0 & 0xfffff + } +} + +/// @brief: 根据主次设备号创建设备号实例 +/// @parameter: major: 主设备号 +/// minor: 次设备号 +/// @return: 设备号实例 +pub fn mkdev(major: usize, minor: usize) -> DeviceNumber { + DeviceNumber(((major & 0xfff) << 20) | (minor & 0xfffff)) +} + /// @brief: 设备类型 #[allow(dead_code)] #[derive(Debug, Eq, PartialEq)] @@ -112,16 +166,21 @@ impl From for u32 { } /// @brief: 所有设备都应该实现该trait -pub trait Device: Any + Send + Sync + Debug { +pub trait Device: KObject { + /// @brief: 本函数用于实现动态转换 + /// @parameter: None + /// @return: any + fn as_any_ref(&'static self) -> &'static dyn core::any::Any; + /// @brief: 获取设备类型 /// @parameter: None /// @return: 实现该trait的设备所属类型 - fn get_type(&self) -> DeviceType; + fn dev_type(&self) -> DeviceType; /// @brief: 获取设备标识 /// @parameter: None /// @return: 该设备唯一标识 - fn get_id_table(&self) -> IdTable; + fn id_table(&self) -> IdTable; /// @brief: 设置sysfs info /// @parameter: None @@ -208,8 +267,8 @@ impl DeviceManager { /// @parameter: name: 设备名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_register(device: Arc) -> Result<(), DeviceError> { - DEVICE_MANAGER.add_device(device.get_id_table(), device.clone()); - match sys_device_register(&device.get_id_table().to_name()) { + DEVICE_MANAGER.add_device(device.id_table(), device.clone()); + match sys_device_register(&device.id_table().to_name()) { Ok(sys_info) => { device.set_sys_info(Some(sys_info)); return Ok(()); @@ -222,8 +281,8 @@ pub fn device_register(device: Arc) -> Result<(), DeviceError> { /// @parameter: name: 设备名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_unregister(device: Arc) -> Result<(), DeviceError> { - DEVICE_MANAGER.add_device(device.get_id_table(), device.clone()); - match sys_device_unregister(&device.get_id_table().to_name()) { + DEVICE_MANAGER.add_device(device.id_table(), device.clone()); + match sys_device_unregister(&device.id_table().to_name()) { Ok(_) => { device.set_sys_info(None); return Ok(()); diff --git a/kernel/src/driver/base/map/mod.rs b/kernel/src/driver/base/map/mod.rs new file mode 100644 index 00000000..2b2e0359 --- /dev/null +++ b/kernel/src/driver/base/map/mod.rs @@ -0,0 +1,98 @@ +use super::device::{mkdev, DeviceNumber, KObject}; +use crate::libs::spinlock::SpinLock; +use alloc::{collections::BTreeMap, sync::Arc, vec::Vec}; + +const KOBJMAP_HASH_SIZE: usize = 255; + +/// @brief: 字符设备与块设备管理结构体 +#[derive(Debug, Clone)] +struct Probe(Arc); + +impl Probe { + /// @brief: 新建probe实例 + /// @parameter: data: probe实例 + /// @return: probe实例 + pub fn new(data: Arc) -> Self { + Self(data) + } +} + +/// @brief: 字符设备和块设备管理实例(锁) +#[derive(Debug)] +pub struct LockedKObjMap(SpinLock); + +impl Default for LockedKObjMap { + fn default() -> Self { + Self(SpinLock::new(KObjMap::default())) + } +} + +/// @brief: 字符设备和块设备管理实例 +#[derive(Debug, Clone)] +struct KObjMap(Vec>); + +impl Default for KObjMap { + fn default() -> Self { + Self(vec![BTreeMap::new(); KOBJMAP_HASH_SIZE]) + } +} + +/// @brief: obj设备注册 +/// @parameter: domain: 管理实例 +/// dev_t: 设备号 +/// range: 次设备号范围 +/// data: 设备实例 +/// @return: none +pub fn kobj_map( + domain: Arc, + dev_t: DeviceNumber, + range: usize, + data: Arc, +) { + if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) { + for i in 0..range { + map.insert( + mkdev(dev_t.major(), dev_t.minor() + i), + Probe::new(data.clone()), + ); + } + } +} + +/// @brief: obj设备注销 +/// @parameter: domain: 管理实例 +/// dev_t: 设备号 +/// range: 次设备号范围 +/// @return: none +pub fn kobj_unmap(domain: Arc, dev_t: DeviceNumber, range: usize) { + if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) { + for i in 0..range { + let rm_dev_t = &DeviceNumber::new(Into::::into(dev_t) + i); + match map.get(rm_dev_t) { + Some(_) => { + map.remove(rm_dev_t); + } + None => {} + } + } + } +} + +/// @brief: 设备查找 +/// @parameter: domain: 管理实例 +/// dev_t: 设备号 +/// @return: 查找成功,返回设备实例,否则返回None +#[allow(dead_code)] +pub fn kobj_lookup(domain: Arc, dev_t: DeviceNumber) -> Option> { + if let Some(map) = domain.0.lock().0.get(dev_t.major() % 255) { + match map.get(&dev_t) { + Some(value) => { + return Some(value.0.clone()); + } + None => { + return None; + } + } + } + return None; +} diff --git a/kernel/src/driver/base/mod.rs b/kernel/src/driver/base/mod.rs index 9ea87935..d6880d08 100644 --- a/kernel/src/driver/base/mod.rs +++ b/kernel/src/driver/base/mod.rs @@ -1,2 +1,4 @@ +pub mod char; pub mod device; +pub mod map; pub mod platform; diff --git a/kernel/src/driver/base/platform/mod.rs b/kernel/src/driver/base/platform/mod.rs index 76817906..3aac0a8d 100644 --- a/kernel/src/driver/base/platform/mod.rs +++ b/kernel/src/driver/base/platform/mod.rs @@ -1,7 +1,7 @@ use super::device::{ bus::{bus_driver_register, bus_register, Bus, BusDriver, BusState}, driver::Driver, - Device, DeviceError, DeviceState, DeviceType, IdTable, + Device, DeviceError, DeviceState, DeviceType, IdTable, KObject, }; use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError}; use alloc::{ @@ -94,7 +94,7 @@ impl LockedPlatformBusDriver { /// @return: 注册成功,返回Ok(()),,注册失败,返回BusError类型 #[allow(dead_code)] fn register_platform_driver(&self, driver: Arc) -> Result<(), DeviceError> { - let id_table = driver.get_id_table(); + let id_table = driver.id_table(); let drivers = &mut self.0.lock().drivers; // 如果存在同类型的驱动,返回错误 @@ -112,7 +112,7 @@ impl LockedPlatformBusDriver { #[allow(dead_code)] #[inline] fn unregister_platform_driver(&mut self, driver: Arc) { - let id_table = driver.get_id_table(); + let id_table = driver.id_table(); self.0.lock().drivers.remove(&id_table); } @@ -124,7 +124,7 @@ impl LockedPlatformBusDriver { &mut self, device: Arc, ) -> Result<(), DeviceError> { - let id_table = device.get_id_table(); + let id_table = device.id_table(); let devices = &mut self.0.lock().devices; if devices.contains_key(&id_table) { @@ -141,7 +141,7 @@ impl LockedPlatformBusDriver { #[inline] #[allow(dead_code)] fn unregister_platform_device(&mut self, device: Arc) { - let id_table = device.get_id_table(); + let id_table = device.id_table(); self.0.lock().devices.remove(&id_table); } @@ -155,8 +155,8 @@ impl LockedPlatformBusDriver { for (_dev_id_table, device) in devices.iter() { if device - .get_compatible_table() - .matches(&driver.get_compatible_table()) + .compatible_table() + .matches(&driver.compatible_table()) { if !device.is_initialized() { // 设备未初始化,调用驱动probe函数 @@ -186,8 +186,8 @@ impl LockedPlatformBusDriver { let drivers = &mut self.0.lock().drivers; for (_drv_id_table, driver) in drivers.into_iter() { if driver - .get_compatible_table() - .matches(&device.get_compatible_table()) + .compatible_table() + .matches(&device.compatible_table()) { match driver.probe(device.clone()) { Ok(_driver) => { @@ -234,7 +234,7 @@ impl Driver for LockedPlatformBusDriver { } #[inline] - fn get_id_table(&self) -> IdTable { + fn id_table(&self) -> IdTable { IdTable::new("PlatformBusDriver", 0) } @@ -262,6 +262,8 @@ impl BusDriver for LockedPlatformBusDriver { } } +impl KObject for LockedPlatformBusDriver {} + #[derive(Debug)] pub struct LockedPlatform(SpinLock); @@ -278,7 +280,7 @@ impl LockedPlatform { /// @return: platform总线匹配表 #[inline] #[allow(dead_code)] - fn get_compatible_table(&self) -> CompatibleTable { + fn compatible_table(&self) -> CompatibleTable { CompatibleTable::new(vec!["platform"]) } @@ -350,13 +352,13 @@ impl Platform { impl Device for LockedPlatform { #[inline] #[allow(dead_code)] - fn get_type(&self) -> DeviceType { + fn dev_type(&self) -> DeviceType { return DeviceType::Bus; } #[inline] #[allow(dead_code)] - fn get_id_table(&self) -> IdTable { + fn id_table(&self) -> IdTable { IdTable::new("platform", 0) } @@ -370,11 +372,17 @@ impl Device for LockedPlatform { fn sys_info(&self) -> Option> { return self.0.lock().sys_info.clone(); } + + fn as_any_ref(&'static self) -> &'static dyn core::any::Any { + self + } } /// @brief: 为Platform实现Bus trait,platform总线是一种总线设备 impl Bus for LockedPlatform {} +impl KObject for LockedPlatform {} + /// @brief: 初始化platform总线 /// @parameter: None /// @return: None diff --git a/kernel/src/driver/base/platform/platform_device.rs b/kernel/src/driver/base/platform/platform_device.rs index f02f88ae..6fc2657f 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -1,5 +1,5 @@ use super::{ - super::device::{Device, DeviceState, DeviceType}, + super::device::{Device, DeviceState}, platform_driver::PlatformDriver, CompatibleTable, }; @@ -8,14 +8,10 @@ use alloc::sync::Arc; /// @brief: 实现该trait的设备实例应挂载在platform总线上, /// 同时应该实现Device trait pub trait PlatformDevice: Device { - fn get_type(&self) -> DeviceType { - DeviceType::PlatformDev - } - /// @brief: 获取设备匹配表 /// @parameter: None /// @return: 设备匹配表 - fn get_compatible_table(&self) -> CompatibleTable; + fn compatible_table(&self) -> CompatibleTable; /// @brief: 判断设备是否初始化 /// @parameter: None diff --git a/kernel/src/driver/base/platform/platform_driver.rs b/kernel/src/driver/base/platform/platform_driver.rs index e0d305bf..fd5110e4 100644 --- a/kernel/src/driver/base/platform/platform_driver.rs +++ b/kernel/src/driver/base/platform/platform_driver.rs @@ -16,5 +16,5 @@ pub trait PlatformDriver: Driver { /// @brief: 获取驱动匹配表 /// @parameter: None /// @return: 驱动匹配表 - fn get_compatible_table(&self) -> CompatibleTable; + fn compatible_table(&self) -> CompatibleTable; } diff --git a/kernel/src/driver/uart/uart.rs b/kernel/src/driver/uart/uart.rs index 0f21484b..15fefbca 100644 --- a/kernel/src/driver/uart/uart.rs +++ b/kernel/src/driver/uart/uart.rs @@ -1,4 +1,21 @@ -use crate::include::bindings::bindings::{io_in8, io_out8}; +use super::super::base::device::Device; +use crate::{ + driver::base::{ + char::CharDevice, + device::{driver::Driver, DeviceState, DeviceType, IdTable, KObject}, + platform::{ + self, platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable, + }, + }, + filesystem::{ + sysfs::bus::{bus_device_register, bus_driver_register}, + vfs::IndexNode, + }, + include::bindings::bindings::{io_in8, io_out8}, + libs::spinlock::SpinLock, + syscall::SystemError, +}; +use alloc::sync::Arc; use core::{char, intrinsics::offset, str}; const UART_SUCCESS: i32 = 0; @@ -6,9 +23,17 @@ const E_UART_BITS_RATE_ERROR: i32 = 1; const E_UART_SERIAL_FAULT: i32 = 2; const UART_MAX_BITS_RATE: u32 = 115200; +lazy_static! { + // 串口设备 + pub static ref UART_DEV: Arc = Arc::new(LockedUart::default()); + // 串口驱动 + pub static ref UART_DRV: Arc = Arc::new(LockedUartDriver::default()); +} + +// @brief 串口端口 #[allow(dead_code)] #[repr(u16)] -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum UartPort { COM1 = 0x3f8, COM2 = 0x2f8, @@ -57,6 +82,7 @@ impl UartPort { } } +// @brief 串口寄存器 #[allow(dead_code)] #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -71,10 +97,88 @@ struct UartRegister { reg_scartch: u8, } +// @brief 串口设备结构体 +#[derive(Debug)] +pub struct Uart { + state: DeviceState, // 设备状态 + sys_info: Option>, + driver: Option>, +} + +impl Default for Uart { + fn default() -> Self { + Self { + state: DeviceState::NotInitialized, + sys_info: None, + driver: None, + } + } +} + +// @brief 串口设备结构体(加锁) +#[derive(Debug)] +pub struct LockedUart(SpinLock); + +impl Default for LockedUart { + fn default() -> Self { + Self(SpinLock::new(Uart::default())) + } +} + +impl KObject for LockedUart {} + +impl PlatformDevice for LockedUart { + fn compatible_table(&self) -> platform::CompatibleTable { + platform::CompatibleTable::new(vec!["uart"]) + } + + fn is_initialized(&self) -> bool { + let state = self.0.lock().state; + match state { + DeviceState::Initialized => true, + _ => false, + } + } + + fn set_state(&self, set_state: DeviceState) { + let state = &mut self.0.lock().state; + *state = set_state; + } + + fn set_driver(&self, driver: Option>) { + self.0.lock().driver = driver; + } +} + +impl Device for LockedUart { + fn id_table(&self) -> IdTable { + IdTable::new("uart", 0) + } + + fn set_sys_info(&self, sys_info: Option>) { + self.0.lock().sys_info = sys_info; + } + + fn sys_info(&self) -> Option> { + self.0.lock().sys_info.clone() + } + + fn dev_type(&self) -> DeviceType { + DeviceType::Serial + } + + fn as_any_ref(&'static self) -> &'static dyn core::any::Any { + self + } +} + +// @brief 串口驱动结构体 #[repr(C)] +#[derive(Debug)] pub struct UartDriver { port: UartPort, baud_rate: u32, + sys_info: Option>, } impl Default for UartDriver { @@ -82,11 +186,91 @@ impl Default for UartDriver { Self { port: UartPort::COM1, baud_rate: 115200, + sys_info: None, } } } +// @brief 串口驱动结构体(加锁) +#[derive(Debug)] +pub struct LockedUartDriver(SpinLock); + +impl Default for LockedUartDriver { + fn default() -> Self { + Self(SpinLock::new(UartDriver::default())) + } +} + +impl KObject for LockedUartDriver {} + +impl Driver for LockedUartDriver { + fn as_any_ref(&'static self) -> &'static dyn core::any::Any { + self + } + + fn id_table(&self) -> IdTable { + return IdTable::new("uart_driver", 0); + } + + fn set_sys_info(&self, sys_info: Option>) { + self.0.lock().sys_info = sys_info; + } + + fn sys_info(&self) -> Option> { + return self.0.lock().sys_info.clone(); + } +} + +impl CharDevice for LockedUartDriver { + fn open(&self, _file: Arc) -> Result<(), crate::syscall::SystemError> { + return Ok(()); + } + + fn close(&self, _file: Arc) -> Result<(), crate::syscall::SystemError> { + return Ok(()); + } +} + +impl LockedUartDriver { + /// @brief 创建串口驱动 + /// @param port 端口号 + /// baud_rate 波特率 + /// sys_info: sys文件系统inode + /// @return + #[allow(dead_code)] + pub fn new(port: UartPort, baud_rate: u32, sys_info: Option>) -> Self { + Self(SpinLock::new(UartDriver::new(port, baud_rate, sys_info))) + } +} + +impl PlatformDriver for LockedUartDriver { + fn probe( + &self, + _device: Arc, + ) -> Result<(), crate::driver::base::device::driver::DriverError> { + return Ok(()); + } + + fn compatible_table(&self) -> platform::CompatibleTable { + return CompatibleTable::new(vec!["uart"]); + } +} + impl UartDriver { + /// @brief 创建串口驱动 + /// @param port 端口号 + /// baud_rate 波特率 + /// sys_info: sys文件系统inode + /// @return 返回串口驱动 + #[allow(dead_code)] + pub fn new(port: UartPort, baud_rate: u32, sys_info: Option>) -> Self { + Self { + port, + baud_rate, + sys_info, + } + } + /// @brief 串口初始化 /// @param uart_port 端口号 /// @param baud_rate 波特率 @@ -176,6 +360,11 @@ impl UartDriver { while UartDriver::serial_received(port) == false {} //TODO:pause unsafe { io_in8(port) as char } } + + #[allow(dead_code)] + fn port() -> u16 { + UartPort::COM1.to_u16() + } } ///@brief 发送数据 @@ -231,7 +420,7 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 { let divisor = UART_MAX_BITS_RATE / baud_rate; io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) - io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte) + io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // CompatibleTable(hi byte) io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR) @@ -261,3 +450,18 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 { clears the DLAB again as well as setting various other bits. */ } + +/// @brief 串口初始化,注册串口 +/// @param none +/// @return 初始化成功,返回(),失败,返回错误码 +pub fn uart_init() -> Result<(), SystemError> { + let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().to_name()) + .expect("uart device register error"); + UART_DEV.set_sys_info(Some(device_inode)); + let driver_inode = bus_driver_register("platform:0", &UART_DRV.id_table().to_name()) + .expect("uart driver register error"); + UART_DRV.set_sys_info(Some(driver_inode)); + UART_DEV.set_driver(Some(UART_DRV.clone())); + UART_DEV.set_state(DeviceState::Initialized); + return Ok(()); +} diff --git a/kernel/src/filesystem/sysfs/bus.rs b/kernel/src/filesystem/sysfs/bus.rs index 0df220f1..1676a66e 100644 --- a/kernel/src/filesystem/sysfs/bus.rs +++ b/kernel/src/filesystem/sysfs/bus.rs @@ -1,5 +1,9 @@ use super::{LockedSysFSInode, SYS_BUS_INODE}; -use crate::{filesystem::vfs::IndexNode, kdebug, syscall::SystemError}; +use crate::{ + filesystem::vfs::IndexNode, + kdebug, + syscall::SystemError, +}; use alloc::sync::Arc; /// @brief: 注册bus,在sys/bus下生成文件夹 @@ -49,3 +53,51 @@ pub fn sys_bus_init( None => Err(SystemError::E2BIG), } } + +/// @brief: 在相应总线的device下生成设备文件夹 +/// @parameter bus_name: 总线名 +/// name: 设备名 +/// @return: 操作成功,返回device inode,操作失败,返回错误码 +pub fn bus_driver_register( + bus_name: &str, + name: &str, +) -> Result, SystemError> { + match SYS_BUS_INODE().find(bus_name) { + Ok(platform) => match platform.find("drivers") { + Ok(device) => { + device + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::E2BIG) + .unwrap() + .add_dir(name) + } + Err(_) => return Err(SystemError::EXDEV), + }, + Err(_) => return Err(SystemError::EXDEV), + } +} + +/// @brief: 在相应总线的driver下生成驱动文件夹 +/// @parameter bus_name: 总线名 +/// name: 驱动名 +/// @return: 操作成功,返回drivers inode,操作失败,返回错误码 +pub fn bus_device_register( + bus_name: &str, + name: &str, +) -> Result, SystemError> { + match SYS_BUS_INODE().find(bus_name) { + Ok(platform) => match platform.find("devices") { + Ok(device) => { + device + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::E2BIG) + .unwrap() + .add_dir(name) + } + Err(_) => return Err(SystemError::EXDEV), + }, + Err(_) => return Err(SystemError::EXDEV), + } +} diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index cee12fdc..bc0093e9 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -138,6 +138,8 @@ impl SysFS { } // 初始化platform总线 crate::driver::base::platform::platform_bus_init().expect("platform bus init failed"); + // 初始化串口 + crate::driver::uart::uart::uart_init().expect("initilize uart error"); return sysfs; } }