From f84ec140433d4439be35710ca8bd06994a114111 Mon Sep 17 00:00:00 2001 From: longjin Date: Tue, 19 Dec 2023 09:02:30 +0000 Subject: [PATCH] =?UTF-8?q?feature:=20=E5=AE=8C=E5=96=84=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E6=A8=A1=E5=9E=8B=E4=B8=ADDevice=E5=AF=B9cla?= =?UTF-8?q?ss=E7=9A=84=E5=A4=84=E7=90=86,=E4=BD=BF=E5=BE=97=E8=83=BD?= =?UTF-8?q?=E5=A4=9F=E5=9C=A8class=E4=B8=8B=E6=B3=A8=E5=86=8C=E8=AE=BE?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 目前注册了fbcon设备,但是由于虚拟终端还没写,因此fbcon的到终端以及帧缓冲区的映射还没加上去. --- kernel/src/driver/base/class.rs | 8 +- kernel/src/driver/base/cpu.rs | 7 +- kernel/src/driver/base/device/init.rs | 18 +- kernel/src/driver/base/device/mod.rs | 233 +++++++++++-- kernel/src/driver/base/kset.rs | 5 + kernel/src/driver/base/platform/mod.rs | 2 +- .../driver/base/platform/platform_device.rs | 7 +- kernel/src/driver/disk/ahci/ahcidisk.rs | 5 + kernel/src/driver/tty/mod.rs | 1 + .../src/driver/tty/serial/serial8250/mod.rs | 7 +- kernel/src/driver/tty/vt/mod.rs | 10 + kernel/src/driver/video/fbdev/base/fbcon.rs | 330 ++++++++++++++++++ kernel/src/driver/video/fbdev/base/fbmem.rs | 11 +- kernel/src/driver/video/fbdev/base/mod.rs | 1 + 14 files changed, 609 insertions(+), 36 deletions(-) create mode 100644 kernel/src/driver/tty/vt/mod.rs create mode 100644 kernel/src/driver/video/fbdev/base/fbcon.rs diff --git a/kernel/src/driver/base/class.rs b/kernel/src/driver/base/class.rs index f3fed04d4..5fae0eec2 100644 --- a/kernel/src/driver/base/class.rs +++ b/kernel/src/driver/base/class.rs @@ -111,6 +111,10 @@ impl dyn Class { } } +#[inline(always)] +pub fn class_manager() -> &'static ClassManager { + return &ClassManager; +} pub struct ClassManager; impl ClassManager { @@ -122,7 +126,7 @@ impl ClassManager { /// ## 参数 /// /// - `class` - 设备类 - pub fn class_register(class: &Arc) -> Result<(), SystemError> { + pub fn class_register(&self, class: &Arc) -> Result<(), SystemError> { let subsystem = class.subsystem(); let subsys = subsystem.subsys(); subsys.set_name(class.name().to_string()); @@ -143,7 +147,7 @@ impl ClassManager { /// 注销一个设备类 #[allow(dead_code)] - pub fn class_unregister(class: &Arc) { + pub fn class_unregister(&self, class: &Arc) { let subsystem = class.subsystem(); let subsys = subsystem.subsys(); sysfs_instance().remove_groups(&(subsys.clone() as Arc), class.class_groups()); diff --git a/kernel/src/driver/base/cpu.rs b/kernel/src/driver/base/cpu.rs index 4bbd25f91..09675290f 100644 --- a/kernel/src/driver/base/cpu.rs +++ b/kernel/src/driver/base/cpu.rs @@ -13,6 +13,7 @@ use crate::{ }; use super::{ + class::Class, device::{ bus::{subsystem_manager, Bus}, driver::Driver, @@ -148,7 +149,7 @@ impl Device for CpuSubSystemFakeRootDevice { } fn id_table(&self) -> IdTable { - IdTable::new("cpu".to_string(), DeviceNumber::new(0)) + IdTable::new("cpu".to_string(), Some(DeviceNumber::new(0))) } fn set_bus(&self, bus: Option>) { @@ -178,6 +179,10 @@ impl Device for CpuSubSystemFakeRootDevice { fn state_synced(&self) -> bool { true } + + fn set_class(&self, _class: Option>) { + todo!() + } } impl KObject for CpuSubSystemFakeRootDevice { diff --git a/kernel/src/driver/base/device/init.rs b/kernel/src/driver/base/device/init.rs index fa4451626..fbbab5665 100644 --- a/kernel/src/driver/base/device/init.rs +++ b/kernel/src/driver/base/device/init.rs @@ -3,8 +3,9 @@ use alloc::{string::ToString, sync::Arc}; use crate::{ driver::base::{ device::{ - set_sys_dev_block_kset, set_sys_dev_char_kset, sys_dev_kset, DeviceManager, - DEVICES_KSET_INSTANCE, DEVICE_MANAGER, DEV_KSET_INSTANCE, + set_sys_dev_block_kset, set_sys_dev_char_kset, set_sys_devices_virtual_kset, + sys_dev_kset, sys_devices_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, + DEV_KSET_INSTANCE, }, kobject::KObject, kset::KSet, @@ -28,6 +29,19 @@ pub fn devices_init() -> Result<(), SystemError> { } } + // 创建 `/sys/devices/virtual` 目录 + { + let devices_kset = sys_devices_kset(); + let virtual_kset = KSet::new("virtual".to_string()); + let parent = devices_kset.clone() as Arc; + virtual_kset.set_parent(Some(Arc::downgrade(&parent))); + + virtual_kset + .register(Some(devices_kset)) + .expect("register virtual kset failed"); + unsafe { set_sys_devices_virtual_kset(virtual_kset) }; + } + // 创建 `/sys/dev` 目录 { let dev_kset = KSet::new("dev".to_string()); diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 2ec3dbd78..be95f9b3a 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -27,6 +27,7 @@ use self::{ }; use super::{ + class::Class, kobject::{KObjType, KObject, KObjectManager, KObjectState}, kset::KSet, swnode::software_node_notify, @@ -65,22 +66,29 @@ static mut DEV_BLOCK_KSET_INSTANCE: Option> = None; /// `/sys/dev/char` 的 kset 实例 static mut DEV_CHAR_KSET_INSTANCE: Option> = None; +/// `/sys/devices/virtual` 的 kset 实例 +static mut DEVICES_VIRTUAL_KSET_INSTANCE: Option> = None; + +/// 获取`/sys/devices`的kset实例 #[inline(always)] pub(super) fn sys_devices_kset() -> Arc { unsafe { DEVICES_KSET_INSTANCE.as_ref().unwrap().clone() } } +/// 获取`/sys/dev`的kset实例 #[inline(always)] pub(super) fn sys_dev_kset() -> Arc { unsafe { DEV_KSET_INSTANCE.as_ref().unwrap().clone() } } +/// 获取`/sys/dev/block`的kset实例 #[inline(always)] #[allow(dead_code)] pub fn sys_dev_block_kset() -> Arc { unsafe { DEV_BLOCK_KSET_INSTANCE.as_ref().unwrap().clone() } } +/// 获取`/sys/dev/char`的kset实例 #[inline(always)] pub fn sys_dev_char_kset() -> Arc { unsafe { DEV_CHAR_KSET_INSTANCE.as_ref().unwrap().clone() } @@ -94,6 +102,15 @@ pub(self) unsafe fn set_sys_dev_char_kset(kset: Arc) { DEV_CHAR_KSET_INSTANCE = Some(kset); } +/// 获取`/sys/devices/virtual`的kset实例 +pub fn sys_devices_virtual_kset() -> Arc { + unsafe { DEVICES_VIRTUAL_KSET_INSTANCE.as_ref().unwrap().clone() } +} + +pub(self) unsafe fn set_sys_devices_virtual_kset(kset: Arc) { + DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset); +} + /// 设备应该实现的操作 /// /// ## 注意 @@ -134,6 +151,14 @@ pub trait Device: KObject { /// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Weak指针) fn set_bus(&self, bus: Option>); + /// 获取当前设备所属的类 + fn class(&self) -> Option> { + return None; + } + + /// 设置当前设备所属的类 + fn set_class(&self, class: Option>); + /// 返回已经与当前设备匹配好的驱动程序 fn driver(&self) -> Option>; @@ -155,6 +180,10 @@ pub trait Device: KObject { /// the software state of this device by calling the driver/bus /// sync_state() callback. fn state_synced(&self) -> bool; + + fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { + None + } } impl dyn Device { @@ -260,11 +289,15 @@ pub enum DeviceType { Serial, Intc, PlatformDev, + Char, } /// @brief: 设备标识符类型 #[derive(Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)] -pub struct IdTable(String, DeviceNumber); +pub struct IdTable { + basename: String, + id: Option, +} /// @brief: 设备标识符操作方法集 impl IdTable { @@ -272,25 +305,29 @@ impl IdTable { /// @parameter name: 设备名 /// @parameter id: 设备id /// @return: 设备标识符 - pub fn new(name: String, id: DeviceNumber) -> IdTable { - Self(name, id) + pub fn new(basename: String, id: Option) -> IdTable { + return IdTable { basename, id }; } /// @brief: 将设备标识符转换成name /// @parameter None /// @return: 设备名 pub fn name(&self) -> String { - return format!("{}:{}", self.0, self.1 .0); + if self.id.is_none() { + return self.basename.clone(); + } else { + return format!("{}:{}", self.basename, self.id.unwrap().data()); + } } pub fn device_number(&self) -> DeviceNumber { - return self.1; + return self.id.unwrap_or(DeviceNumber::new(0)); } } impl Default for IdTable { fn default() -> Self { - IdTable("unknown".to_string(), DeviceNumber::new(0)) + IdTable::new("unknown".to_string(), None) } } @@ -443,7 +480,25 @@ impl DeviceManager { #[inline] #[allow(dead_code)] pub fn add_device(&self, device: Arc) -> Result<(), SystemError> { - // todo: 引入class后,在这里处理与parent相关的逻辑 + // 在这里处理与parent相关的逻辑 + + let current_parent = device + .parent() + .map(|x| x.upgrade()) + .flatten() + .map(|x| x.arc_any().cast::().ok()) + .flatten(); + + let actual_parent = self.get_device_parent(&device, current_parent)?; + if let Some(actual_parent) = actual_parent { + // kdebug!( + // "device '{}' parent is '{}', strong_count: {}", + // device.name().to_string(), + // actual_parent.name(), + // Arc::strong_count(&actual_parent) + // ); + device.set_parent(Some(Arc::downgrade(&actual_parent))); + } KObjectManager::add_kobj(device.clone() as Arc, None).map_err(|e| { kerror!("add device '{:?}' failed: {:?}", device.name(), e); @@ -464,18 +519,85 @@ impl DeviceManager { self.create_sys_dev_entry(&device)?; } - // todo: Notify clients of device addition.This call must come - // after dpm_sysfs_add() and before kobject_uevent(). - // 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#3491 + // 通知客户端有关设备添加的信息。此调用必须在 dpm_sysfs_add() 之后且在 kobject_uevent() 之前执行。 + if let Some(bus) = device.bus() { + bus.subsystem().bus_notifier().call_chain( + bus::BusNotifyEvent::AddDevice, + Some(&device), + None, + ); + } - // todo: 发送uevent + // todo: 发送uevent: KOBJ_ADD // probe drivers for a new device bus_probe_device(&device); + if let Some(class) = device.class() { + class.subsystem().add_device_to_vec(&device)?; + + for class_interface in class.subsystem().interfaces() { + class_interface.add_device(&device).ok(); + } + } + return Ok(()); } + /// 获取设备真实的parent kobject + /// + /// ## 参数 + /// + /// - `device`: 设备 + /// - `current_parent`: 当前的parent kobject + /// + /// ## 返回值 + /// + /// - `Ok(Some(kobj))`: 如果找到了真实的parent kobject,那么返回它 + /// - `Ok(None)`: 如果没有找到真实的parent kobject,那么返回None + /// - `Err(e)`: 如果发生错误,那么返回错误 + fn get_device_parent( + &self, + device: &Arc, + current_parent: Option>, + ) -> Result>, SystemError> { + kdebug!("get_device_parent() device:{:?}", device.name()); + if let Some(_) = device.class() { + let parent_kobj: Arc; + kdebug!("current_parent:{:?}", current_parent); + if current_parent.is_none() { + parent_kobj = sys_devices_virtual_kset() as Arc; + } else { + let cp = current_parent.unwrap(); + + if cp.class().is_some() { + return Ok(Some(cp.clone() as Arc)); + } else { + parent_kobj = cp.clone() as Arc; + } + } + + // 是否需要glue dir? + + return Ok(Some(parent_kobj)); + } + + // subsystems can specify a default root directory for their devices + if current_parent.is_none() { + if let Some(bus) = device.bus() { + if let Some(root) = bus.root_device().map(|x| x.upgrade()).flatten() { + return Ok(Some(root as Arc)); + } + } + } + + if current_parent.is_some() { + return Ok(Some(current_parent.unwrap().clone() as Arc)); + } + + return Ok(None); + } + /// @brief: 卸载设备 /// @parameter id_table: 总线标识符,用于唯一标识该设备 /// @return: None @@ -504,9 +626,32 @@ impl DeviceManager { software_node_notify(dev); } - fn add_class_symlinks(&self, _dev: &Arc) -> Result<(), SystemError> { - // todo: 引入class后,在这里处理与class相关的逻辑 - // https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#3224 + fn add_class_symlinks(&self, dev: &Arc) -> Result<(), SystemError> { + let class = dev.class(); + if class.is_none() { + return Ok(()); + } + + // 定义错误处理函数,用于在添加符号链接失败时,移除已经添加的符号链接 + + let err_remove_subsystem = |dev_kobj: &Arc| { + sysfs_instance().remove_link(dev_kobj, "subsystem".to_string()); + }; + + let class = class.unwrap(); + let dev_kobj = dev.clone() as Arc; + let subsys_kobj = class.subsystem().subsys() as Arc; + sysfs_instance().create_link(Some(&dev_kobj), &subsys_kobj, "subsystem".to_string())?; + + // todo: 这里需要处理class的parent逻辑, 添加device链接 + // https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3245 + + sysfs_instance() + .create_link(Some(&subsys_kobj), &dev_kobj, dev.name()) + .map_err(|e| { + err_remove_subsystem(&dev_kobj); + e + })?; return Ok(()); } @@ -517,20 +662,45 @@ impl DeviceManager { /// /// - `dev`: 设备 fn add_attrs(&self, dev: &Arc) -> Result<(), SystemError> { - let kobj_type = dev.kobj_type(); - if kobj_type.is_none() { - return Ok(()); + // 定义错误处理函数,用于在添加属性文件失败时,移除已经添加的属性组 + let err_remove_class_groups = |dev: &Arc| { + if let Some(class) = dev.class() { + let attr_groups = class.dev_groups(); + self.remove_groups(dev, attr_groups); + } + }; + + let err_remove_kobj_type_groups = |dev: &Arc| { + if let Some(kobj_type) = dev.kobj_type() { + let attr_groups = kobj_type.attribute_groups().unwrap_or(&[]); + self.remove_groups(dev, attr_groups); + } + }; + + // 真正开始添加属性文件 + + // 添加设备类的属性文件 + if let Some(class) = dev.class() { + let attr_groups = class.dev_groups(); + self.add_groups(dev, attr_groups)?; } - let kobj_type = kobj_type.unwrap(); - - let attr_groups = kobj_type.attribute_groups(); - - if attr_groups.is_none() { - return Ok(()); + // 添加kobj_type的属性文件 + if let Some(kobj_type) = dev.kobj_type() { + self.add_groups(dev, kobj_type.attribute_groups().unwrap_or(&[])) + .map_err(|e| { + err_remove_class_groups(dev); + e + })?; } - self.add_groups(dev, attr_groups.unwrap())?; + // 添加设备本身的属性文件 + self.add_groups(dev, dev.attribute_groups().unwrap_or(&[])) + .map_err(|e| { + err_remove_kobj_type_groups(dev); + err_remove_class_groups(dev); + e + })?; return Ok(()); } @@ -550,6 +720,21 @@ impl DeviceManager { return sysfs_instance().create_groups(&kobj, attr_groups); } + /// 在sysfs中,为指定的设备移除属性组,以及属性组中的属性文件 + /// + /// ## 参数 + /// + /// - `dev`: 设备 + /// - `attr_groups`: 要移除的属性组 + pub fn remove_groups( + &self, + dev: &Arc, + attr_groups: &'static [&dyn AttributeGroup], + ) { + let kobj = dev.clone() as Arc; + sysfs_instance().remove_groups(&kobj, attr_groups); + } + /// 为设备在sysfs中创建属性文件 /// /// ## 参数 diff --git a/kernel/src/driver/base/kset.rs b/kernel/src/driver/base/kset.rs index 310b7a4bc..65f53cfb1 100644 --- a/kernel/src/driver/base/kset.rs +++ b/kernel/src/driver/base/kset.rs @@ -116,6 +116,7 @@ impl KSet { /// 把一个kobject从当前kset中移除。 pub fn leave(&self, kobj: &Arc) { let mut kobjects = self.kobjects.write(); + kobjects.retain(|x| x.upgrade().is_some()); let index = kobjects.iter().position(|x| { if let Some(x) = x.upgrade() { return Arc::ptr_eq(&x, kobj); @@ -140,6 +141,10 @@ impl KSet { pub fn as_kobject(&self) -> Arc { return self.self_ref.upgrade().unwrap(); } + + pub fn kobjects(&self) -> RwLockReadGuard>> { + return self.kobjects.read(); + } } impl KObject for KSet { diff --git a/kernel/src/driver/base/platform/mod.rs b/kernel/src/driver/base/platform/mod.rs index 12e3141aa..398992dd1 100644 --- a/kernel/src/driver/base/platform/mod.rs +++ b/kernel/src/driver/base/platform/mod.rs @@ -73,7 +73,7 @@ impl CompatibleTable { pub fn platform_bus_init() -> Result<(), SystemError> { let platform_device: Arc = PlatformBusDevice::new( DevicePrivateData::new( - IdTable::new("platform".to_string(), DeviceNumber::new(0)), + IdTable::new("platform".to_string(), Some(DeviceNumber::new(0))), BusState::NotInitialized.into(), ), Some(Arc::downgrade(&(sys_devices_kset() as Arc))), diff --git a/kernel/src/driver/base/platform/platform_device.rs b/kernel/src/driver/base/platform/platform_device.rs index 4b4bb28f3..6792df159 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -6,6 +6,7 @@ use ida::IdAllocator; use crate::{ driver::base::{ + class::Class, device::{ bus::{Bus, BusState}, device_manager, @@ -287,7 +288,7 @@ impl Device for PlatformBusDevice { #[inline] #[allow(dead_code)] fn id_table(&self) -> IdTable { - IdTable::new("platform".to_string(), DeviceNumber::new(0)) + IdTable::new("platform".to_string(), Some(DeviceNumber::new(0))) } fn bus(&self) -> Option> { @@ -322,4 +323,8 @@ impl Device for PlatformBusDevice { fn state_synced(&self) -> bool { todo!() } + + fn set_class(&self, _class: Option>) { + todo!() + } } diff --git a/kernel/src/driver/disk/ahci/ahcidisk.rs b/kernel/src/driver/disk/ahci/ahcidisk.rs index 48f9aaccb..07aa02631 100644 --- a/kernel/src/driver/disk/ahci/ahcidisk.rs +++ b/kernel/src/driver/disk/ahci/ahcidisk.rs @@ -2,6 +2,7 @@ use super::{_port, hba::HbaCmdTable, virt_2_phys}; use crate::driver::base::block::block_device::{BlockDevice, BlockId}; use crate::driver::base::block::disk_info::Partition; use crate::driver::base::block::SeekFrom; +use crate::driver::base::class::Class; use crate::driver::base::device::bus::Bus; use crate::driver::base::device::driver::Driver; @@ -529,6 +530,10 @@ impl Device for LockedAhciDisk { fn state_synced(&self) -> bool { todo!() } + + fn set_class(&self, _class: Option>) { + todo!() + } } impl BlockDevice for LockedAhciDisk { diff --git a/kernel/src/driver/tty/mod.rs b/kernel/src/driver/tty/mod.rs index c32bd6b4a..692ea4ecd 100644 --- a/kernel/src/driver/tty/mod.rs +++ b/kernel/src/driver/tty/mod.rs @@ -13,6 +13,7 @@ pub mod init; pub mod serial; pub mod tty_device; pub mod tty_driver; +pub mod vt; bitflags! { pub struct TtyCoreState: u32{ diff --git a/kernel/src/driver/tty/serial/serial8250/mod.rs b/kernel/src/driver/tty/serial/serial8250/mod.rs index fa13faeb9..2792ec30f 100644 --- a/kernel/src/driver/tty/serial/serial8250/mod.rs +++ b/kernel/src/driver/tty/serial/serial8250/mod.rs @@ -12,6 +12,7 @@ use alloc::{ use crate::{ driver::{ base::{ + class::Class, device::{ bus::Bus, device_manager, driver::Driver, Device, DeviceKObjType, DeviceNumber, DeviceState, DeviceType, IdTable, @@ -228,7 +229,7 @@ impl Device for Serial8250ISADevices { } fn id_table(&self) -> IdTable { - return IdTable::new(self.name.to_string(), DeviceNumber::new(0)); + return IdTable::new(self.name.to_string(), Some(DeviceNumber::new(0))); } fn driver(&self) -> Option> { @@ -250,6 +251,10 @@ impl Device for Serial8250ISADevices { fn state_synced(&self) -> bool { true } + + fn set_class(&self, _class: Option>) { + todo!() + } } impl KObject for Serial8250ISADevices { diff --git a/kernel/src/driver/tty/vt/mod.rs b/kernel/src/driver/tty/vt/mod.rs new file mode 100644 index 000000000..dcbb36b0f --- /dev/null +++ b/kernel/src/driver/tty/vt/mod.rs @@ -0,0 +1,10 @@ +//! Virtual terminal driver. +//! +//! (TODO) This driver is not implemented yet. + +/// The minimum number of virtual terminals. +#[allow(dead_code)] +pub const MIN_NR_CONSOLES: usize = 1; +/// The maximum number of virtual terminals. +#[allow(dead_code)] +pub const MAX_NR_CONSOLES: usize = 63; diff --git a/kernel/src/driver/video/fbdev/base/fbcon.rs b/kernel/src/driver/video/fbdev/base/fbcon.rs new file mode 100644 index 000000000..dfbe8ebe3 --- /dev/null +++ b/kernel/src/driver/video/fbdev/base/fbcon.rs @@ -0,0 +1,330 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; + +use crate::{ + driver::base::{ + class::Class, + device::{bus::Bus, device_manager, driver::Driver, Device, DeviceType, IdTable}, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + }, + filesystem::{ + kernfs::KernFSInode, + sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport}, + vfs::syscall::ModeType, + }, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::SpinLock, + }, + syscall::SystemError, +}; + +use super::fbmem::sys_class_graphics_instance; + +/// framebuffer console设备管理器实例 +static mut FB_CONSOLE_MANAGER: Option = None; + +pub fn fb_console_manager() -> &'static FbConsoleManager { + unsafe { FB_CONSOLE_MANAGER.as_ref().unwrap() } +} + +/// 初始化framebuffer console +pub(super) fn fb_console_init() -> Result<(), SystemError> { + // todo: 对全局的console信号量加锁(linux中是console_lock) + + let fbcon_device: Arc = FbConsoleDevice::new(); + + { + let fbcon_manager = FbConsoleManager::new(fbcon_device.clone()); + unsafe { FB_CONSOLE_MANAGER = Some(fbcon_manager) }; + } + + device_manager().register(fbcon_device.clone() as Arc)?; + fb_console_manager().init_device()?; + + return Ok(()); +} + +/// framebuffer console设备管理器 +#[derive(Debug)] +pub struct FbConsoleManager { + _inner: SpinLock, + /// framebuffer console设备实例 + /// (对应`/sys/class/graphics/fbcon`) + device: Arc, +} + +impl FbConsoleManager { + pub fn new(device: Arc) -> Self { + return Self { + _inner: SpinLock::new(InnerFbConsoleManager {}), + device, + }; + } + + #[allow(dead_code)] + #[inline(always)] + pub fn device(&self) -> &Arc { + &self.device + } + + /// 初始化设备 + fn init_device(&self) -> Result<(), SystemError> { + return Ok(()); // todo + } +} + +#[derive(Debug)] +struct InnerFbConsoleManager {} + +#[derive(Debug)] +struct InnerFbConsoleDevice { + kernfs_inode: Option>, + parent: Option>, + kset: Option>, + bus: Option>, + driver: Option>, + ktype: Option<&'static dyn KObjType>, +} + +/// `/sys/class/graphics/fbcon`代表的 framebuffer console 设备 +#[derive(Debug)] +#[cast_to([sync] Device)] +pub struct FbConsoleDevice { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +impl FbConsoleDevice { + const NAME: &'static str = "fbcon"; + + pub fn new() -> Arc { + return Arc::new(Self { + inner: SpinLock::new(InnerFbConsoleDevice { + kernfs_inode: None, + parent: None, + kset: None, + bus: None, + ktype: None, + driver: None, + }), + kobj_state: LockedKObjectState::new(None), + }); + } +} + +impl KObject for FbConsoleDevice { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.lock().kernfs_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.lock().kernfs_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.lock().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.lock().parent = parent; + } + + fn kset(&self) -> Option> { + self.inner.lock().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.lock().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.lock().ktype + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock().ktype = ktype; + } + + fn name(&self) -> String { + Self::NAME.to_string() + } + + fn set_name(&self, _name: String) { + // 不允许修改 + kwarn!("fbcon name can not be changed"); + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} +impl Device for FbConsoleDevice { + fn dev_type(&self) -> DeviceType { + DeviceType::Char + } + + fn id_table(&self) -> IdTable { + IdTable::new(Self::NAME.to_string(), None) + } + + fn set_bus(&self, bus: Option>) { + self.inner.lock().bus = bus; + } + + fn set_class(&self, _class: Option>) { + // 不允许修改 + kwarn!("fbcon's class can not be changed"); + } + + fn class(&self) -> Option> { + sys_class_graphics_instance().map(|ins| ins.clone() as Arc) + } + + fn driver(&self) -> Option> { + self.inner + .lock() + .driver + .clone() + .and_then(|driver| driver.upgrade()) + } + + fn set_driver(&self, driver: Option>) { + self.inner.lock().driver = driver; + } + + fn is_dead(&self) -> bool { + todo!() + } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { + todo!() + } + + fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { + return Some(&[&AnonymousAttributeGroup]); + } +} + +/// framebuffer console设备的匿名属性组 +#[derive(Debug)] +struct AnonymousAttributeGroup; + +impl AttributeGroup for AnonymousAttributeGroup { + fn name(&self) -> Option<&str> { + None + } + + fn attrs(&self) -> &[&'static dyn Attribute] { + return &[&AttrRotate, &AttrRotateAll, &AttrCursorBlink]; + } + + fn is_visible( + &self, + _kobj: Arc, + attr: &'static dyn Attribute, + ) -> Option { + return Some(attr.mode()); + } +} + +#[derive(Debug)] +struct AttrRotate; + +impl Attribute for AttrRotate { + fn name(&self) -> &str { + "rotate" + } + + fn mode(&self) -> ModeType { + ModeType::S_IRUGO | ModeType::S_IWUSR + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::WRITE | SysFSOpsSupport::READ + } + + /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3226 + fn show(&self, _kobj: Arc, buf: &mut [u8]) -> Result { + kwarn!("fbcon rotate show not implemented"); + return sysfs_emit_str(buf, "0\n"); + } + + /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3182 + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + kwarn!("fbcon rotate store not implemented"); + return Err(SystemError::ENOSYS); + } +} + +#[derive(Debug)] +struct AttrRotateAll; + +impl Attribute for AttrRotateAll { + fn name(&self) -> &str { + "rotate_all" + } + + fn mode(&self) -> ModeType { + ModeType::S_IWUSR + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::WRITE + } + + /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3204 + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + kwarn!("fbcon rotate_all store not implemented"); + return Err(SystemError::ENOSYS); + } +} + +#[derive(Debug)] +struct AttrCursorBlink; + +impl Attribute for AttrCursorBlink { + fn name(&self) -> &str { + "cursor_blink" + } + + fn mode(&self) -> ModeType { + ModeType::S_IRUGO | ModeType::S_IWUSR + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::WRITE | SysFSOpsSupport::READ + } + + /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3245 + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + todo!() + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } +} diff --git a/kernel/src/driver/video/fbdev/base/fbmem.rs b/kernel/src/driver/video/fbdev/base/fbmem.rs index 20ad6d100..3a4e69120 100644 --- a/kernel/src/driver/video/fbdev/base/fbmem.rs +++ b/kernel/src/driver/video/fbdev/base/fbmem.rs @@ -5,7 +5,7 @@ use alloc::{ use crate::{ driver::base::{ - class::{Class, ClassManager}, + class::{class_manager, Class}, device::sys_dev_char_kset, kobject::KObject, subsys::SubSysPrivate, @@ -13,25 +13,28 @@ use crate::{ syscall::SystemError, }; +use super::fbcon::fb_console_init; + /// `/sys/class/graphics` 的 class 实例 static mut CLASS_GRAPHICS_INSTANCE: Option> = None; /// 获取 `/sys/class/graphics` 的 class 实例 #[inline(always)] #[allow(dead_code)] -pub fn sys_class_graphics_instance() -> &'static Arc { - unsafe { CLASS_GRAPHICS_INSTANCE.as_ref().unwrap() } +pub fn sys_class_graphics_instance() -> Option<&'static Arc> { + unsafe { CLASS_GRAPHICS_INSTANCE.as_ref() } } /// 初始化帧缓冲区子系统 pub fn fbmem_init() -> Result<(), SystemError> { let graphics_class = GraphicsClass::new(); - ClassManager::class_register(&(graphics_class.clone() as Arc))?; + class_manager().class_register(&(graphics_class.clone() as Arc))?; unsafe { CLASS_GRAPHICS_INSTANCE = Some(graphics_class); } + fb_console_init()?; return Ok(()); } diff --git a/kernel/src/driver/video/fbdev/base/mod.rs b/kernel/src/driver/video/fbdev/base/mod.rs index 756b34899..cb81f93fd 100644 --- a/kernel/src/driver/video/fbdev/base/mod.rs +++ b/kernel/src/driver/video/fbdev/base/mod.rs @@ -6,6 +6,7 @@ use crate::{ syscall::SystemError, }; +pub mod fbcon; pub mod fbmem; /// 帧缓冲区应该实现的接口