diff --git a/.vscode/settings.json b/.vscode/settings.json index 3a29d413..2c5cfc47 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -180,6 +180,7 @@ "rust-analyzer.cargo.target": "x86_64-unknown-none", "rust-analyzer.checkOnSave.allTargets": false, "rust-analyzer.linkedProjects": [ - "./kernel/Cargo.toml" + "./kernel/Cargo.toml", + "./kernel/src/libs/ida/Cargo.toml" ], } \ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index ef0ed0d0..7f7bedb0 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -34,6 +34,7 @@ raw-cpuid = "11.0.1" acpi = "5.0.0" intertrait = { path = "src/libs/intertrait" } linkme = "0.2" +ida = { path = "src/libs/ida" } # 构建时依赖项 [build-dependencies] diff --git a/kernel/src/arch/io.rs b/kernel/src/arch/io.rs new file mode 100644 index 00000000..498f5793 --- /dev/null +++ b/kernel/src/arch/io.rs @@ -0,0 +1,9 @@ +/// 每个架构都需要实现的IO接口 +pub trait PortIOArch { + unsafe fn in8(port: u16) -> u8; + unsafe fn in16(port: u16) -> u16; + unsafe fn in32(port: u16) -> u32; + unsafe fn out8(port: u16, data: u8); + unsafe fn out16(port: u16, data: u16); + unsafe fn out32(port: u16, data: u32); +} diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index c66f65d2..3fe4d8f5 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -7,6 +7,8 @@ use crate::{ mm::PhysAddr, }; +pub mod io; + /// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数 pub trait TraitPciArch { /// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现 diff --git a/kernel/src/arch/x86_64/asm/mod.rs b/kernel/src/arch/x86_64/asm/mod.rs index 37094b0e..71c3a58a 100644 --- a/kernel/src/arch/x86_64/asm/mod.rs +++ b/kernel/src/arch/x86_64/asm/mod.rs @@ -1,2 +1,3 @@ pub mod bitops; pub mod irqflags; +pub mod pio; diff --git a/kernel/src/arch/x86_64/asm/pio.rs b/kernel/src/arch/x86_64/asm/pio.rs new file mode 100644 index 00000000..c12a41e1 --- /dev/null +++ b/kernel/src/arch/x86_64/asm/pio.rs @@ -0,0 +1,35 @@ +use crate::arch::io::PortIOArch; + +pub struct X86_64PortIOArch; + +impl PortIOArch for X86_64PortIOArch { + #[inline(always)] + unsafe fn in8(port: u16) -> u8 { + x86::io::inb(port) + } + + #[inline(always)] + unsafe fn in16(port: u16) -> u16 { + x86::io::inw(port) + } + + #[inline(always)] + unsafe fn in32(port: u16) -> u32 { + x86::io::inl(port) + } + + #[inline(always)] + unsafe fn out8(port: u16, data: u8) { + x86::io::outb(port, data) + } + + #[inline(always)] + unsafe fn out16(port: u16, data: u16) { + x86::io::outw(port, data) + } + + #[inline(always)] + unsafe fn out32(port: u16, data: u32) { + x86::io::outl(port, data) + } +} diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 70fd95b0..ab9a86ea 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -5,7 +5,7 @@ use hashbrown::HashSet; use x86::time::rdtsc; use x86_64::registers::model_specific::EferFlags; -use crate::driver::uart::uart_device::c_uart_send_str; +use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port; use crate::include::bindings::bindings::{ multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t, }; @@ -148,7 +148,7 @@ impl MemoryManagementArch for X86_64MMArch { // 初始化物理内存区域(从multiboot2中获取) let areas_count = Self::init_memory_area_from_multiboot2().expect("init memory area failed"); - c_uart_send_str(0x3f8, "x86 64 init end\n\0".as_ptr()); + send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes()); return &PHYS_MEMORY_AREAS[0..areas_count]; } @@ -229,7 +229,7 @@ impl X86_64MMArch { unsafe fn init_memory_area_from_multiboot2() -> Result { // 这个数组用来存放内存区域的信息(从C获取) let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed(); - c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 begin\n\0".as_ptr()); + send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes()); let mut mb2_count: u32 = 0; multiboot2_iter( @@ -237,7 +237,7 @@ impl X86_64MMArch { &mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void, &mut mb2_count, ); - c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 2\n\0".as_ptr()); + send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes()); let mb2_count = mb2_count as usize; let mut areas_count = 0usize; @@ -255,7 +255,7 @@ impl X86_64MMArch { areas_count += 1; } } - c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 end\n\0".as_ptr()); + send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes()); kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024); return Ok(areas_count); @@ -291,7 +291,7 @@ impl VirtAddr { /// @brief 初始化内存管理模块 pub fn mm_init() { - c_uart_send_str(0x3f8, "mm_init\n\0".as_ptr()); + send_to_default_serial8250_port("mm_init\n\0".as_bytes()); PrintkWriter .write_fmt(format_args!("mm_init() called\n")) .unwrap(); @@ -301,7 +301,7 @@ pub fn mm_init() { .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) .is_err() { - c_uart_send_str(0x3f8, "mm_init err\n\0".as_ptr()); + send_to_default_serial8250_port("mm_init err\n\0".as_bytes()); panic!("mm_init() can only be called once"); } diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 6fa338cd..5f3b850d 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -20,3 +20,5 @@ pub use self::pci::pci::X86_64PciArch as PciArch; pub use self::mm::X86_64MMArch as MMArch; pub use interrupt::X86_64InterruptArch as CurrentIrqArch; + +pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch; diff --git a/kernel/src/driver/acpi/bus.rs b/kernel/src/driver/acpi/bus.rs new file mode 100644 index 00000000..46f2cac6 --- /dev/null +++ b/kernel/src/driver/acpi/bus.rs @@ -0,0 +1,23 @@ +use alloc::sync::Arc; + +use crate::{ + driver::base::device::{driver::Driver, Device}, + syscall::SystemError, +}; + +use super::AcpiManager; + +impl AcpiManager { + /// 通过acpi来匹配驱动 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#949 + pub fn driver_match_device( + &self, + _driver: &Arc, + _device: &Arc, + ) -> Result { + // todo: + + return Ok(false); + } +} diff --git a/kernel/src/driver/acpi/mod.rs b/kernel/src/driver/acpi/mod.rs index 640ff303..4feffc46 100644 --- a/kernel/src/driver/acpi/mod.rs +++ b/kernel/src/driver/acpi/mod.rs @@ -14,6 +14,7 @@ use crate::{ }, }; +pub mod bus; mod c_adapter; pub mod glue; pub mod old; @@ -22,6 +23,11 @@ extern crate acpi; static mut __ACPI_TABLE: Option> = None; +#[inline(always)] +pub fn acpi_manager() -> &'static AcpiManager { + &AcpiManager +} + #[derive(Debug)] pub struct AcpiManager; diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index b37b0966..ad1b0439 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -1,8 +1,19 @@ -use super::{sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState}; +use super::{ + driver::{Driver, DriverMatchName, DriverMatcher}, + sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState, +}; use crate::{ - driver::base::{device::device_manager, kobject::KObject, kset::KSet, subsys::SubSysPrivate}, + driver::base::{ + device::{device_manager, driver::driver_manager}, + kobject::{KObjType, KObject, KObjectManager}, + kset::KSet, + subsys::SubSysPrivate, + }, filesystem::{ - sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOpsSupport}, + sysfs::{ + file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps, + SysFSOpsSupport, + }, vfs::syscall::ModeType, }, libs::rwlock::RwLock, @@ -14,6 +25,7 @@ use alloc::{ }; use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely}; use hashbrown::HashMap; +use intertrait::cast::CastArc; /// `/sys/bus`的kset static mut BUS_KSET_INSTANCE: Option> = None; @@ -105,6 +117,46 @@ pub trait Bus: Debug + Send + Sync { &[] } + /// 检查设备是否可以被总线绑定,如果可以,就绑定它们。 + /// 绑定之后,device的driver字段会被设置为驱动实例。 + /// + /// ## 参数 + /// + /// - `device` - 设备实例 + /// + /// ## 默认实现 + /// + /// 如果总线不支持该操作,返回`SystemError::EOPNOTSUPP_OR_ENOTSUP` + fn probe(&self, _device: &Arc) -> Result<(), SystemError> { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + fn remove(&self, _device: &Arc) -> Result<(), SystemError>; + fn sync_state(&self, _device: &Arc) {} + fn shutdown(&self, _device: &Arc); + fn suspend(&self, _device: &Arc) { + // todo: implement suspend + } + + fn resume(&self, device: &Arc) -> Result<(), SystemError>; + + /// match platform device to platform driver. + /// + /// ## 参数 + /// + /// * `device` - platform device + /// * `driver` - platform driver + /// + /// ## 返回 + /// + /// - `Ok(true)` - 匹配成功 + /// - `Ok(false)` - 匹配失败 + /// - `Err(_)` - 由于内部错误导致匹配失败 + fn match_device( + &self, + device: &Arc, + driver: &Arc, + ) -> Result; + fn subsystem(&self) -> &SubSysPrivate; /// 对当前总线操作的时候需要获取父级总线的锁 @@ -126,7 +178,7 @@ impl dyn Bus { data: T, ) -> Option> { let subsys = self.subsystem(); - let guard = subsys.devices().read(); + let guard = subsys.devices(); for dev in guard.iter() { let dev = dev.upgrade(); if let Some(dev) = dev { @@ -146,6 +198,35 @@ impl dyn Bus { pub fn find_device_by_name(&self, name: &str) -> Option> { return self.find_device(&DeviceMatchName, name); } + + /// 在bus上,根据条件寻找一个特定的驱动 + /// + /// ## 参数 + /// + /// - `matcher` - 匹配器 + /// - `data` - 传给匹配器的数据 + pub fn find_driver( + &self, + matcher: &dyn DriverMatcher, + data: T, + ) -> Option> { + let subsys = self.subsystem(); + let guard = subsys.drivers(); + for drv in guard.iter() { + let drv = drv.upgrade(); + if let Some(drv) = drv { + if matcher.match_driver(&drv, data) { + return Some(drv.clone()); + } + } + } + return None; + } + + /// 根据名称在bus上匹配驱动 + pub fn find_driver_by_name(&self, name: &str) -> Option> { + return self.find_driver(&DriverMatchName, name); + } } /// @brief: 总线管理结构体 @@ -162,6 +243,94 @@ impl BusManager { }; } + /// 把一个设备添加到总线上 + /// + /// ## 描述 + /// + /// - 添加一个设备的与bus相关的属性 + /// - 在bus和设备文件夹下,创建软链接 + /// - 把设备添加到它的总线的设备列表中 + /// + /// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_device#441 + /// + /// ## 参数 + /// + /// - `dev` - 要被添加的设备 + pub fn add_device(&self, dev: &Arc) -> Result<(), SystemError> { + let bus = dev.bus(); + if let Some(bus) = bus { + device_manager().add_groups(dev, bus.dev_groups())?; + + // 增加符号链接 + let bus_devices_kset = bus + .subsystem() + .devices_kset() + .expect("bus devices kset is none, maybe bus is not registered"); + let dev_kobj = dev.clone() as Arc; + + sysfs_instance().create_link( + Some(&bus_devices_kset.as_kobject()), + &dev_kobj, + dev.name(), + )?; + sysfs_instance().create_link( + Some(&dev_kobj), + &(&bus.subsystem().subsys().as_kobject()), + "subsystem".to_string(), + )?; + bus.subsystem().add_device_to_vec(dev)?; + } + return Ok(()); + } + + /// 在总线上添加一个驱动 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_driver#590 + pub fn add_driver(&self, driver: &Arc) -> Result<(), SystemError> { + let bus = driver.bus().ok_or(SystemError::EINVAL)?; + kdebug!("bus '{}' add driver '{}'", bus.name(), driver.name()); + + driver.set_kobj_type(Some(&BusDriverKType)); + let kobj = driver.clone() as Arc; + KObjectManager::add_kobj(kobj, bus.subsystem().drivers_kset())?; + + bus.subsystem().add_driver_to_vec(driver)?; + if bus.subsystem().drivers_autoprobe() { + let r = driver_manager().driver_attach(driver); + if let Err(e) = r { + bus.subsystem().remove_driver_from_vec(driver); + return Err(e); + } + } + + driver_manager() + .add_groups(driver, bus.drv_groups()) + .or_else(|e| { + kerror!( + "BusManager::add_driver: driver '{:?}' add_groups failed, err: '{:?}", + driver.name(), + e + ); + Err(e) + }) + .ok(); + + if !driver.suppress_bind_attrs() { + self.add_bind_files(driver) + .or_else(|e| { + kerror!( + "BusManager::add_driver: driver '{:?}' add_bind_files failed, err: '{:?}", + driver.name(), + e + ); + Err(e) + }) + .ok(); + } + + return Ok(()); + } + /// /// bus_register - register a driver-core subsystem /// @@ -257,7 +426,7 @@ impl BusManager { /// - `bus` - bus实例 #[allow(dead_code)] pub fn rescan_devices(&self, bus: &Arc) -> Result<(), SystemError> { - for dev in bus.subsystem().devices().read().iter() { + for dev in bus.subsystem().devices().iter() { let dev = dev.upgrade(); if let Some(dev) = dev { rescan_devices_helper(dev)?; @@ -283,21 +452,32 @@ impl BusManager { } } - /// 在bus上,根据条件寻找一个特定的设备 + /// 从总线上移除一个驱动 + /// + /// Detach the driver from the devices it controls, and remove + /// it from its bus's list of drivers. Finally, we drop the reference + /// to the bus. /// /// ## 参数 /// - /// - `matcher` - 匹配器 - /// - `data` - 传给匹配器的数据 - #[inline] - #[allow(dead_code)] - pub fn find_device( - &self, - bus: &Arc, - matcher: &dyn DeviceMatcher, - data: T, - ) -> Option> { - return bus.find_device(matcher, data); + /// - `driver` - 驱动实例 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_remove_driver#666 + pub fn remove_driver(&self, _driver: &Arc) { + todo!("BusManager::remove_driver") + } + + fn add_bind_files(&self, driver: &Arc) -> Result<(), SystemError> { + driver_manager().create_attr_file(driver, &DriverAttrUnbind)?; + + driver_manager() + .create_attr_file(driver, &DriverAttrBind) + .map_err(|e| { + driver_manager().remove_attr_file(driver, &DriverAttrUnbind); + e + })?; + + return Ok(()); } } @@ -376,13 +556,7 @@ pub fn buses_init() -> Result<(), SystemError> { /// /// - `dev` - 要被添加的设备 pub fn bus_add_device(dev: &Arc) -> Result<(), SystemError> { - let bus = dev.bus(); - if let Some(bus) = bus { - device_manager().add_groups(dev, bus.dev_groups())?; - // todo: 增加符号链接 - todo!("bus_add_device") - } - return Ok(()); + return bus_manager().add_device(dev); } /// 自动为设备在总线上寻找可用的驱动程序 @@ -507,3 +681,129 @@ pub enum BusNotifyEvent { /// 驱动绑定失败 DriverNotBound, } + +#[derive(Debug)] +struct BusDriverKType; + +impl KObjType for BusDriverKType { + fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { + Some(&BusDriverSysFSOps) + } + + fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { + None + } +} + +#[derive(Debug)] +struct BusDriverSysFSOps; + +impl SysFSOps for BusDriverSysFSOps { + #[inline] + fn show( + &self, + kobj: Arc, + attr: &dyn Attribute, + buf: &mut [u8], + ) -> Result { + attr.show(kobj, buf) + } + + #[inline] + fn store( + &self, + kobj: Arc, + attr: &dyn Attribute, + buf: &[u8], + ) -> Result { + attr.store(kobj, buf) + } +} + +#[derive(Debug)] +struct DriverAttrUnbind; + +impl Attribute for DriverAttrUnbind { + fn mode(&self) -> ModeType { + ModeType::from_bits_truncate(0o200) + } + + fn name(&self) -> &str { + "unbind" + } + + fn store(&self, kobj: Arc, buf: &[u8]) -> Result { + let driver = kobj.cast::().map_err(|kobj| { + kerror!( + "Intertrait casting not implemented for kobj: {}", + kobj.name() + ); + SystemError::EOPNOTSUPP_OR_ENOTSUP + })?; + + let bus = driver.bus().ok_or(SystemError::ENODEV)?; + + let s = CStr::from_bytes_with_nul(buf) + .map_err(|_| SystemError::EINVAL)? + .to_str() + .map_err(|_| SystemError::EINVAL)?; + let dev = bus.find_device_by_name(s).ok_or(SystemError::ENODEV)?; + let p = dev.driver().ok_or(SystemError::ENODEV)?; + if Arc::ptr_eq(&p, &driver) { + device_manager().device_driver_detach(&dev); + return Ok(buf.len()); + } + return Err(SystemError::ENODEV); + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::STORE + } +} + +#[derive(Debug)] +struct DriverAttrBind; + +impl Attribute for DriverAttrBind { + fn name(&self) -> &str { + "bind" + } + + fn mode(&self) -> ModeType { + ModeType::from_bits_truncate(0o200) + } + + /* + * Manually attach a device to a driver. + * Note: the driver must want to bind to the device, + * it is not possible to override the driver's id table. + */ + fn store(&self, kobj: Arc, buf: &[u8]) -> Result { + let driver = kobj.cast::().map_err(|kobj| { + kerror!( + "Intertrait casting not implemented for kobj: {}", + kobj.name() + ); + SystemError::EOPNOTSUPP_OR_ENOTSUP + })?; + + let bus = driver.bus().ok_or(SystemError::ENODEV)?; + let device = bus + .find_device_by_name( + CStr::from_bytes_with_nul(buf) + .map_err(|_| SystemError::EINVAL)? + .to_str() + .map_err(|_| SystemError::EINVAL)?, + ) + .ok_or(SystemError::ENODEV)?; + + if driver_manager().match_device(&driver, &device)? { + device_manager().device_driver_attach(&driver, &device)?; + return Ok(buf.len()); + } + return Err(SystemError::ENODEV); + } + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::STORE + } +} diff --git a/kernel/src/driver/base/device/dd.rs b/kernel/src/driver/base/device/dd.rs index 9dcc777b..00633934 100644 --- a/kernel/src/driver/base/device/dd.rs +++ b/kernel/src/driver/base/device/dd.rs @@ -1,10 +1,26 @@ use core::intrinsics::unlikely; -use alloc::sync::Arc; +use alloc::{string::ToString, sync::Arc}; +use intertrait::cast::CastArc; -use crate::{driver::Driver, syscall::SystemError}; +use crate::{ + driver::base::kobject::KObject, + filesystem::{ + sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport}, + vfs::syscall::ModeType, + }, + libs::wait_queue::WaitQueue, + syscall::SystemError, +}; -use super::{bus::BusNotifyEvent, driver::driver_manager, Device, DeviceManager}; +use super::{ + bus::BusNotifyEvent, + device_manager, + driver::{driver_manager, Driver, DriverManager}, + Device, DeviceManager, +}; + +static PROBE_WAIT_QUEUE: WaitQueue = WaitQueue::INIT; impl DeviceManager { /// 尝试把一个设备与一个驱动匹配 @@ -40,7 +56,8 @@ impl DeviceManager { allow_async: bool, ) -> Result { if unlikely(allow_async) { - todo!("do_device_attach: allow_async") + // todo!("do_device_attach: allow_async") + kwarn!("do_device_attach: allow_async is true, but currently not supported"); } if dev.is_dead() { return Ok(false); @@ -64,7 +81,7 @@ impl DeviceManager { let bus = dev.bus().ok_or(SystemError::EINVAL)?; let mut data = DeviceAttachData::new(dev.clone(), allow_async, false); let mut flag = true; - for driver in bus.subsystem().drivers().read().iter() { + for driver in bus.subsystem().drivers().iter() { if let Some(driver) = driver.upgrade() { let r = self.do_device_attach_driver(&driver, &mut data); if unlikely(r.is_err()) { @@ -142,7 +159,7 @@ impl DeviceManager { let r = driver_manager().driver_sysfs_add(dev); if let Err(e) = r { self.device_links_force_bind(dev); - self.driver_bound(dev); + driver_manager().driver_bound(dev); return Err(e); } else { if let Some(bus) = dev.bus() { @@ -156,9 +173,10 @@ impl DeviceManager { return r; } - /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393 - fn driver_bound(&self, _dev: &Arc) { - todo!("driver_bound") + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528 + fn unbind_cleanup(&self, dev: &Arc) { + dev.set_driver(None); + // todo: 添加更多操作,清理数据 } } @@ -208,3 +226,368 @@ impl DeviceAttachData { self.have_async = true; } } + +impl DriverManager { + /// 尝试把驱动绑定到现有的设备上 + /// + /// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。 + /// 一旦有一个设备匹配成功,就会返回,并且设备的driver字段会被设置。 + pub fn driver_attach(&self, driver: &Arc) -> Result<(), SystemError> { + let bus = driver.bus().ok_or(SystemError::EINVAL)?; + for dev in bus.subsystem().devices().iter() { + if let Some(dev) = dev.upgrade() { + if self.do_driver_attach(&dev, &driver) { + // 匹配成功 + return Ok(()); + } + } + } + + return Ok(()); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#1134 + fn do_driver_attach(&self, device: &Arc, driver: &Arc) -> bool { + let r = self.match_device(driver, device).unwrap_or(false); + if r == false { + // 不匹配 + return false; + } + + if driver.allows_async_probing() { + unimplemented!( + "do_driver_attach: probe driver '{}' asynchronously", + driver.name() + ); + } + + if self.probe_device(driver, device).is_err() { + return false; + } + + return true; + } + + #[inline(always)] + pub fn match_device( + &self, + driver: &Arc, + device: &Arc, + ) -> Result { + return driver.bus().unwrap().match_device(device, driver); + } + + /// 尝试把设备和驱动绑定在一起 + /// + /// + /// ## 返回 + /// + /// - Ok(): 绑定成功 + /// - Err(ENODEV): 设备未注册 + /// - Err(EBUSY): 设备已经绑定到驱动上 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#802 + fn probe_device( + &self, + driver: &Arc, + device: &Arc, + ) -> Result<(), SystemError> { + let r = self.do_probe_device(driver, device); + PROBE_WAIT_QUEUE.wakeup_all(None); + return r; + } + + fn do_probe_device( + &self, + driver: &Arc, + device: &Arc, + ) -> Result<(), SystemError> { + if device.is_dead() || (!device.is_registered()) { + return Err(SystemError::ENODEV); + } + if device.driver().is_some() { + return Err(SystemError::EBUSY); + } + + device.set_can_match(true); + + self.really_probe(driver, device)?; + + return Ok(()); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#584 + fn really_probe( + &self, + driver: &Arc, + device: &Arc, + ) -> Result<(), SystemError> { + let bind_failed = || { + device_manager().unbind_cleanup(device); + }; + + let sysfs_failed = || { + if let Some(bus) = device.bus() { + bus.subsystem().bus_notifier().call_chain( + BusNotifyEvent::DriverNotBound, + Some(device), + None, + ); + } + }; + + let probe_failed = || { + self.remove_from_sysfs(device); + }; + + let dev_groups_failed = || { + device_manager().remove(device); + }; + + device.set_driver(Some(Arc::downgrade(driver))); + + self.add_to_sysfs(device).map_err(|e| { + kerror!( + "really_probe: add_to_sysfs failed, dev: '{}', err: {:?}", + device.name(), + e + ); + sysfs_failed(); + bind_failed(); + e + })?; + + self.call_driver_probe(device, driver).map_err(|e| { + kerror!( + "really_probe: call_driver_probe failed, dev: '{}', err: {:?}", + device.name(), + e + ); + + probe_failed(); + sysfs_failed(); + bind_failed(); + e + })?; + + device_manager() + .add_groups(device, driver.dev_groups()) + .map_err(|e| { + kerror!( + "really_probe: add_groups failed, dev: '{}', err: {:?}", + device.name(), + e + ); + dev_groups_failed(); + probe_failed(); + sysfs_failed(); + bind_failed(); + e + })?; + + // 我们假设所有的设备都有sync_state这个属性。如果没有的话,也创建属性文件。 + device_manager() + .create_file(device, &DeviceAttrStateSynced) + .map_err(|e| { + kerror!( + "really_probe: create_file failed, dev: '{}', err: {:?}", + device.name(), + e + ); + dev_groups_failed(); + probe_failed(); + sysfs_failed(); + bind_failed(); + e + })?; + + self.driver_bound(device); + + return Ok(()); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#434 + fn add_to_sysfs(&self, device: &Arc) -> Result<(), SystemError> { + let driver = device.driver().ok_or(SystemError::EINVAL)?; + + if let Some(bus) = device.bus() { + bus.subsystem().bus_notifier().call_chain( + BusNotifyEvent::BindDriver, + Some(&device), + None, + ); + } + + let driver_kobj = driver.clone() as Arc; + let device_kobj = device.clone() as Arc; + + sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device.name())?; + + let fail_rm_dev_link = || { + sysfs_instance().remove_link(&driver_kobj, device.name()); + }; + + sysfs_instance() + .create_link(Some(&device_kobj), &driver_kobj, "driver".to_string()) + .map_err(|e| { + fail_rm_dev_link(); + e + })?; + + device_manager() + .create_file(device, &DeviceAttrCoredump) + .map_err(|e| { + sysfs_instance().remove_link(&device_kobj, "driver".to_string()); + fail_rm_dev_link(); + e + })?; + + return Ok(()); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#469 + fn remove_from_sysfs(&self, _device: &Arc) { + todo!("remove_from_sysfs") + } + + fn call_driver_probe( + &self, + device: &Arc, + driver: &Arc, + ) -> Result<(), SystemError> { + let bus = device.bus().ok_or(SystemError::EINVAL)?; + let r = bus.probe(device); + if r == Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) { + kerror!( + "call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}", + device.name(), + r + ); + return r; + } + + if r.is_ok() { + return Ok(()); + } + + let err = r.unwrap_err(); + match err { + SystemError::ENODEV | SystemError::ENXIO => { + kdebug!( + "driver'{}': probe of {} rejects match {:?}", + driver.name(), + device.name(), + err + ); + } + + _ => { + kwarn!( + "driver'{}': probe of {} failed with error {:?}", + driver.name(), + device.name(), + err + ); + } + } + + return Err(err); + } + + /// 当设备被成功探测,进行了'设备->驱动'绑定后,调用这个函数,完成'驱动->设备'的绑定 + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393 + fn driver_bound(&self, device: &Arc) { + if self.driver_is_bound(device) { + kwarn!("driver_bound: device '{}' is already bound.", device.name()); + return; + } + + let driver = device.driver().unwrap(); + driver.add_device(device.clone()); + + if let Some(bus) = device.bus() { + bus.subsystem().bus_notifier().call_chain( + BusNotifyEvent::BoundDriver, + Some(device), + None, + ); + } + + // todo: 发送kobj bind的uevent + } + + fn driver_is_bound(&self, device: &Arc) -> bool { + if let Some(driver) = device.driver() { + if driver.find_device_by_name(&device.name()).is_some() { + return true; + } + } + + return false; + } +} + +/// 设备文件夹下的`dev`文件的属性 +#[derive(Debug, Clone, Copy)] +pub struct DeviceAttrStateSynced; + +impl Attribute for DeviceAttrStateSynced { + fn mode(&self) -> ModeType { + // 0o444 + return ModeType::S_IRUGO; + } + + fn name(&self) -> &str { + "state_synced" + } + + fn show(&self, kobj: Arc, buf: &mut [u8]) -> Result { + let dev = kobj.cast::().map_err(|kobj| { + kerror!( + "Intertrait casting not implemented for kobj: {}", + kobj.name() + ); + SystemError::EOPNOTSUPP_OR_ENOTSUP + })?; + + let val = dev.state_synced(); + let val = if val { 1 } else { 0 }; + return sysfs_emit_str(buf, format!("{}\n", val).as_str()); + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::SHOW + } +} + +#[derive(Debug)] +struct DeviceAttrCoredump; + +impl Attribute for DeviceAttrCoredump { + fn name(&self) -> &str { + "coredump" + } + + fn mode(&self) -> ModeType { + ModeType::from_bits_truncate(0o200) + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::STORE + } + + fn store(&self, kobj: Arc, buf: &[u8]) -> Result { + let dev = kobj.cast::().map_err(|kobj| { + kerror!( + "Intertrait casting not implemented for kobj: {}", + kobj.name() + ); + SystemError::EOPNOTSUPP_OR_ENOTSUP + })?; + + let drv = dev.driver().ok_or(SystemError::EINVAL)?; + drv.coredump(&dev)?; + + return Ok(buf.len()); + } +} diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index d6afc34f..f7b4b8ba 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -1,6 +1,13 @@ -use super::Device; -use crate::syscall::SystemError; -use alloc::sync::Arc; +use super::{ + bus::{bus_manager, Bus}, + Device, DeviceMatchName, DeviceMatcher, IdTable, +}; +use crate::{ + driver::base::kobject::KObject, + filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup}, + syscall::SystemError, +}; +use alloc::{sync::Arc, vec::Vec}; use core::fmt::Debug; /// @brief: Driver error @@ -31,13 +38,278 @@ pub fn driver_manager() -> &'static DriverManager { &DriverManager } +/// 驱动程序应当实现的trait +/// +/// ## 注意 +/// +/// 由于设备驱动模型需要从Arc转换为Arc, +/// 因此,所有的实现了 Driver trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Driver)]`, +/// 否则在运行时会报错 +pub trait Driver: Sync + Send + Debug + KObject { + fn coredump(&self, _device: &Arc) -> Result<(), SystemError> { + Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + } + + /// @brief: 获取驱动标识符 + /// @parameter: None + /// @return: 该驱动驱动唯一标识符 + fn id_table(&self) -> Option; + + fn devices(&self) -> Vec>; + + /// 把设备加入当前驱动管理的列表中 + fn add_device(&self, device: Arc); + + /// 从当前驱动管理的列表中删除设备 + fn delete_device(&self, device: &Arc); + + /// 根据设备名称查找绑定到驱动的设备 + /// + /// 该方法是一个快速查找方法,要求驱动开发者自行实现。 + /// + /// 如果开发者没有实现该方法,则应当返回None + /// + /// ## 注意 + /// + /// 这是一个内部方法,不应当被外部调用,若要查找设备,请使用`find_device_by_name()` + fn __find_device_by_name_fast(&self, _name: &str) -> Option> { + None + } + + /// 是否禁用sysfs的bind/unbind属性 + /// + /// ## 返回 + /// + /// - true: 禁用 + /// - false: 不禁用(默认) + fn suppress_bind_attrs(&self) -> bool { + false + } + + fn bus(&self) -> Option> { + None + } + + fn set_bus(&self, bus: Option>); + + fn groups(&self) -> &'static [&'static dyn AttributeGroup] { + &[] + } + + fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { + &[] + } + + /// 使用什么样的策略来探测设备 + fn probe_type(&self) -> DriverProbeType { + DriverProbeType::DefaultStrategy + } +} + +impl dyn Driver { + pub fn allows_async_probing(&self) -> bool { + match self.probe_type() { + DriverProbeType::PreferAsync => true, + DriverProbeType::ForceSync => false, + DriverProbeType::DefaultStrategy => { + // todo: 判断是否请求异步探测,如果是的话,就返回true + + // 由于目前还没有支持异步探测,因此这里暂时返回false + false + } + } + } + + /// 根据条件寻找一个绑定到这个驱动的设备(低效实现) + /// + /// ## 参数 + /// + /// - `matcher` - 匹配器 + /// - `data` - 传给匹配器的数据 + /// + /// ## 注意 + /// + /// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询 + fn find_device_slow( + &self, + matcher: &dyn DeviceMatcher, + data: T, + ) -> Option> { + for dev in self.devices() { + if matcher.match_device(&dev, data) { + return Some(dev); + } + } + + return None; + } + + /// 根据设备名称查找绑定到驱动的设备 + /// + /// ## 注意 + /// + /// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询 + pub fn find_device_by_name(&self, name: &str) -> Option> { + if let Some(r) = self.__find_device_by_name_fast(name) { + return Some(r); + } + + return self.find_device_slow(&DeviceMatchName, name); + } +} + /// @brief: 驱动管理器 #[derive(Debug, Clone)] pub struct DriverManager; impl DriverManager { + /// 注册设备驱动。该设备驱动应当已经设置好其bus字段 + /// + /// ## 参数 + /// + /// - driver: 驱动 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/driver.c#222 + pub fn register(&self, driver: Arc) -> Result<(), SystemError> { + let bus = driver.bus().ok_or_else(|| { + kerror!( + "DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'", + driver.name() + ); + SystemError::EINVAL + })?; + + let drv_name = driver.name(); + let other = bus.find_driver_by_name(&drv_name); + if other.is_some() { + kerror!( + "DriverManager::register() failed: driver '{}' already registered", + drv_name + ); + return Err(SystemError::EBUSY); + } + + bus_manager().add_driver(&driver)?; + + self.add_groups(&driver, driver.groups()).map_err(|e| { + bus_manager().remove_driver(&driver); + e + })?; + + // todo: 发送uevent + + return Ok(()); + } + + /// 从系统中删除一个驱动程序 + #[allow(dead_code)] + pub fn unregister(&self, driver: &Arc) { + self.remove_groups(driver, driver.groups()); + bus_manager().remove_driver(driver); + } + /// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#434 pub fn driver_sysfs_add(&self, _dev: &Arc) -> Result<(), SystemError> { todo!("DriverManager::driver_sysfs_add()"); } + + pub fn add_groups( + &self, + driver: &Arc, + groups: &'static [&dyn AttributeGroup], + ) -> Result<(), SystemError> { + let kobj = driver.clone() as Arc; + return sysfs_instance().create_groups(&kobj, groups); + } + + pub fn remove_groups(&self, driver: &Arc, groups: &'static [&dyn AttributeGroup]) { + let kobj = driver.clone() as Arc; + sysfs_instance().remove_groups(&kobj, groups); + } + + /// 为指定的驱动创建一个属性文件 + /// + /// ## 参数 + /// + /// - `driver` 要创建属性文件的驱动 + /// - `attr` 属性 + pub fn create_attr_file( + &self, + driver: &Arc, + attr: &'static dyn Attribute, + ) -> Result<(), SystemError> { + let kobj = driver.clone() as Arc; + return sysfs_instance().create_file(&kobj, attr); + } + + /// 为指定的驱动删除一个属性文件 + /// + /// 如果属性不存在,也不会报错 + /// + /// ## 参数 + /// + /// - `driver` 要删除属性文件的驱动 + /// - `attr` 属性 + pub fn remove_attr_file(&self, driver: &Arc, attr: &'static dyn Attribute) { + let kobj = driver.clone() as Arc; + sysfs_instance().remove_file(&kobj, attr); + } +} + +/// 驱动匹配器 +/// +/// 用于匹配驱动是否符合某个条件 +/// +/// ## 参数 +/// +/// - `T` - 匹配器的数据类型 +/// - `data` - 匹配器的数据 +pub trait DriverMatcher: Debug { + fn match_driver(&self, driver: &Arc, data: T) -> bool; +} + +/// 根据名称匹配驱动 +#[derive(Debug)] +pub struct DriverMatchName; + +impl DriverMatcher<&str> for DriverMatchName { + #[inline(always)] + fn match_driver(&self, driver: &Arc, data: &str) -> bool { + driver.name() == data + } +} + +/// enum probe_type - device driver probe type to try +/// Device drivers may opt in for special handling of their +/// respective probe routines. This tells the core what to +/// expect and prefer. +/// +/// Note that the end goal is to switch the kernel to use asynchronous +/// probing by default, so annotating drivers with +/// %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us +/// to speed up boot process while we are validating the rest of the +/// drivers. +#[allow(dead_code)] +#[derive(Debug)] +pub enum DriverProbeType { + /// Used by drivers that work equally well + /// whether probed synchronously or asynchronously. + DefaultStrategy, + + /// Drivers for "slow" devices which + /// probing order is not essential for booting the system may + /// opt into executing their probes asynchronously. + PreferAsync, + + /// Use this to annotate drivers that need + /// their probe routines to run synchronously with driver and + /// device registration (with the exception of -EPROBE_DEFER + /// handling - re-probing always ends up being done asynchronously). + ForceSync, +} + +impl Default for DriverProbeType { + fn default() -> Self { + DriverProbeType::DefaultStrategy + } } diff --git a/kernel/src/driver/base/device/init.rs b/kernel/src/driver/base/device/init.rs index 65b8f4eb..2b07014c 100644 --- a/kernel/src/driver/base/device/init.rs +++ b/kernel/src/driver/base/device/init.rs @@ -1,27 +1,17 @@ use alloc::{string::ToString, sync::Arc}; use crate::{ - driver::{ - base::{ - device::{ - sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, - DEV_KSET_INSTANCE, - }, - kobject::KObject, - kset::KSet, + driver::base::{ + device::{ + sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, DEV_KSET_INSTANCE, }, - uart::uart_device::uart_init, + kobject::KObject, + kset::KSet, }, kdebug, kinfo, syscall::SystemError, }; -pub fn device_init() -> Result<(), SystemError> { - uart_init()?; - kinfo!("device init success"); - return Ok(()); -} - pub fn devices_init() -> Result<(), SystemError> { // 创建 `/sys/devices` 目录 { @@ -73,6 +63,6 @@ pub fn devices_init() -> Result<(), SystemError> { } kinfo!("devices init success"); - device_init()?; + return Ok(()); } diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 98ad788b..42a63025 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -1,6 +1,6 @@ use alloc::{ string::{String, ToString}, - sync::Arc, + sync::{Arc, Weak}, }; use intertrait::cast::CastArc; @@ -8,10 +8,12 @@ use crate::{ driver::{ acpi::glue::acpi_device_notify, base::map::{LockedDevsMap, LockedKObjMap}, - Driver, }, filesystem::{ - sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport}, + sysfs::{ + file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps, + SysFSOpsSupport, + }, vfs::syscall::ModeType, }, syscall::SystemError, @@ -19,12 +21,14 @@ use crate::{ use core::fmt::Debug; use core::intrinsics::unlikely; -use self::bus::{bus_add_device, bus_probe_device, Bus}; +use self::{ + bus::{bus_add_device, bus_probe_device, Bus}, + driver::Driver, +}; use super::{ - kobject::{KObjType, KObject, KObjectManager}, + kobject::{KObjType, KObject, KObjectManager, KObjectState}, kset::KSet, - platform::CompatibleTable, swnode::software_node_notify, }; @@ -87,7 +91,7 @@ pub(self) fn sys_dev_char_kset() -> Arc { /// ## 注意 /// /// 由于设备驱动模型需要从Arc转换为Arc, -/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[[sync] Device]`, +/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Device)]`, /// /// 否则在释放设备资源的时候,会由于无法转换为Arc而导致资源泄露,并且release回调函数也不会被调用。 pub trait Device: KObject { @@ -117,13 +121,39 @@ pub trait Device: KObject { return None; } + /// 设置当前设备所属的总线 + /// + /// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Weak指针) + fn set_bus(&self, bus: Option>); + /// 返回已经与当前设备匹配好的驱动程序 fn driver(&self) -> Option>; - fn set_driver(&self, driver: Option>); + fn set_driver(&self, driver: Option>); /// 当前设备是否已经挂掉了 fn is_dead(&self) -> bool; + + /// 当前设备是否处于可以被匹配的状态 + /// + /// The device has matched with a driver at least once or it is in + /// a bus (like AMBA) which can't check for matching drivers until + /// other devices probe successfully. + fn can_match(&self) -> bool; + + fn set_can_match(&self, can_match: bool); + + /// The hardware state of this device has been synced to match + /// the software state of this device by calling the driver/bus + /// sync_state() callback. + fn state_synced(&self) -> bool; +} + +impl dyn Device { + #[inline(always)] + pub fn is_registered(&self) -> bool { + self.kobj_state().contains(KObjectState::IN_SYSFS) + } } // 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息 @@ -131,24 +161,13 @@ pub trait Device: KObject { #[derive(Debug, Clone)] pub struct DevicePrivateData { id_table: IdTable, - resource: Option, - compatible_table: CompatibleTable, state: DeviceState, } +#[allow(dead_code)] impl DevicePrivateData { - pub fn new( - id_table: IdTable, - resource: Option, - compatible_table: CompatibleTable, - state: DeviceState, - ) -> Self { - Self { - id_table, - resource, - compatible_table, - state, - } + pub fn new(id_table: IdTable, state: DeviceState) -> Self { + Self { id_table, state } } pub fn id_table(&self) -> &IdTable { @@ -159,31 +178,11 @@ impl DevicePrivateData { self.state } - #[allow(dead_code)] - pub fn resource(&self) -> Option<&DeviceResource> { - self.resource.as_ref() - } - - pub fn compatible_table(&self) -> &CompatibleTable { - &self.compatible_table - } - pub fn set_state(&mut self, state: DeviceState) { self.state = state; } } -#[derive(Debug, Clone)] -pub struct DeviceResource { - //可能会用来保存例如 IRQ PWM 内存地址等需要申请的资源,将来由资源管理器+Framework框架进行管理。 -} - -impl Default for DeviceResource { - fn default() -> Self { - return Self {}; - } -} - int_like!(DeviceNumber, usize); impl Default for DeviceNumber { @@ -225,6 +224,8 @@ impl DeviceNumber { self.0 & 0xff } + #[inline] + #[allow(dead_code)] pub fn from_major_minor(major: usize, minor: usize) -> usize { ((major & 0xffffff) << 8) | (minor & 0xff) } @@ -287,7 +288,7 @@ impl Default for IdTable { // 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉 /// @brief: 设备当前状态 -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DeviceState { NotInitialized = 0, Initialized = 1, @@ -465,6 +466,11 @@ impl DeviceManager { todo!() } + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#542 + fn remove(&self, _dev: &Arc) { + todo!("DeviceManager::remove") + } + /// @brief: 获取设备 /// @parameter id_table: 设备标识符,用于唯一标识该设备 /// @return: 设备实例 @@ -521,10 +527,8 @@ impl DeviceManager { dev: &Arc, attr_groups: &'static [&dyn AttributeGroup], ) -> Result<(), SystemError> { - let dev = dev.clone(); - let binding = dev.arc_any(); - let kobj: &Arc = binding.downcast_ref().unwrap(); - return sysfs_instance().create_groups(kobj, attr_groups); + let kobj = dev.clone() as Arc; + return sysfs_instance().create_groups(&kobj, attr_groups); } /// 为设备在sysfs中创建属性文件 @@ -567,15 +571,15 @@ impl DeviceManager { let target_kobj = self.device_to_dev_kobj(dev); let name = dev.id_table().name(); let current_kobj = dev.clone() as Arc; - return sysfs_instance().create_link(¤t_kobj, &target_kobj, name); + return sysfs_instance().create_link(Some(¤t_kobj), &target_kobj, name); } /// Delete symlink for device in `/sys/dev` or `/sys/class/` #[allow(dead_code)] - fn remove_sys_dev_entry(&self, dev: &Arc) -> Result<(), SystemError> { + fn remove_sys_dev_entry(&self, dev: &Arc) { let kobj = self.device_to_dev_kobj(dev); let name = dev.id_table().name(); - return sysfs_instance().remove_link(&kobj, name); + sysfs_instance().remove_link(&kobj, name); } /// device_to_dev_kobj - select a /sys/dev/ directory for the device @@ -595,6 +599,28 @@ impl DeviceManager { pub fn device_links_force_bind(&self, _dev: &Arc) { todo!("device_links_force_bind") } + + /// 把device对象的一些结构进行默认初始化 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_initialize#2976 + pub fn device_default_initialize(&self, dev: &Arc) { + dev.set_kset(Some(sys_devices_kset())); + return; + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=29885&fi=1100#1100 + pub fn device_driver_attach( + &self, + _driver: &Arc, + _dev: &Arc, + ) -> Result<(), SystemError> { + todo!("device_driver_attach") + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=35401&fi=1313#1313 + pub fn device_driver_detach(&self, _dev: &Arc) { + todo!("device_driver_detach") + } } /// @brief: 设备注册 @@ -633,7 +659,7 @@ impl Attribute for DeviceAttrDev { "dev" } - fn show(&self, kobj: Arc, _buf: &mut [u8]) -> Result { + fn show(&self, kobj: Arc, buf: &mut [u8]) -> Result { let dev = kobj.cast::().map_err(|kobj| { kerror!( "Intertrait casting not implemented for kobj: {}", @@ -642,7 +668,10 @@ impl Attribute for DeviceAttrDev { SystemError::EOPNOTSUPP_OR_ENOTSUP })?; - return Ok(dev.id_table().device_number().into()); + let device_number = dev.id_table().device_number(); + let s = format!("{}:{}\n", device_number.major(), device_number.minor()); + + return sysfs_emit_str(buf, &s); } fn support(&self) -> SysFSOpsSupport { diff --git a/kernel/src/driver/base/init.rs b/kernel/src/driver/base/init.rs index 62c40737..7c522735 100644 --- a/kernel/src/driver/base/init.rs +++ b/kernel/src/driver/base/init.rs @@ -1,4 +1,4 @@ -use crate::syscall::SystemError; +use crate::{driver::tty::tty_device::tty_init, syscall::SystemError}; use super::{ class::classes_init, @@ -15,5 +15,15 @@ pub(super) fn driver_init() -> Result<(), SystemError> { firmware_init()?; hypervisor_init()?; platform_bus_init()?; + + // 至此,已完成设备驱动模型的初始化 + // 接下来,初始化设备 + actual_device_init()?; + return Ok(()); +} + +fn actual_device_init() -> Result<(), SystemError> { + tty_init()?; + return Ok(()); } diff --git a/kernel/src/driver/base/kobject.rs b/kernel/src/driver/base/kobject.rs index e845a8c1..111df93e 100644 --- a/kernel/src/driver/base/kobject.rs +++ b/kernel/src/driver/base/kobject.rs @@ -43,6 +43,8 @@ pub trait KObject: Any + Send + Sync + Debug + CastFromSync { fn kobj_type(&self) -> Option<&'static dyn KObjType>; + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>); + fn name(&self) -> String; fn set_name(&self, name: String); @@ -70,7 +72,7 @@ impl DowncastArc for dyn KObject { } } -pub trait KObjType: Debug { +pub trait KObjType: Debug + Send + Sync { fn release(&self, _kobj: Arc) {} fn sysfs_ops(&self) -> Option<&dyn SysFSOps>; @@ -91,7 +93,8 @@ bitflags! { pub struct LockedKObjectState(RwLock); impl LockedKObjectState { - pub const fn new(state: KObjectState) -> LockedKObjectState { + pub fn new(state: Option) -> LockedKObjectState { + let state = state.unwrap_or(KObjectState::empty()); LockedKObjectState(RwLock::new(state)) } } diff --git a/kernel/src/driver/base/kset.rs b/kernel/src/driver/base/kset.rs index a59898bb..5a1304e0 100644 --- a/kernel/src/driver/base/kset.rs +++ b/kernel/src/driver/base/kset.rs @@ -52,7 +52,7 @@ impl KSet { let r = Self { kobjects: RwLock::new(Vec::new()), inner: RwLock::new(InnerKSet::new(name)), - kobj_state: LockedKObjectState::new(KObjectState::empty()), + kobj_state: LockedKObjectState::new(None), parent_data: RwLock::new(KSetParentData::new(None, None)), self_ref: Weak::default(), }; @@ -167,6 +167,10 @@ impl KObject for KSet { Some(&KSetKObjType) } + fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { + todo!("KSet::set_kobj_type") + } + fn kset(&self) -> Option> { self.parent_data.read().kset.clone() } diff --git a/kernel/src/driver/base/platform/mod.rs b/kernel/src/driver/base/platform/mod.rs index 7c00f5b3..12e3141a 100644 --- a/kernel/src/driver/base/platform/mod.rs +++ b/kernel/src/driver/base/platform/mod.rs @@ -74,8 +74,6 @@ pub fn platform_bus_init() -> Result<(), SystemError> { let platform_device: Arc = PlatformBusDevice::new( DevicePrivateData::new( IdTable::new("platform".to_string(), DeviceNumber::new(0)), - None, - CompatibleTable::new(vec!["platform"]), 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 78d02021..227d1302 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -2,31 +2,64 @@ use alloc::{ string::{String, ToString}, sync::{Arc, Weak}, }; +use ida::IdAllocator; use crate::{ - driver::{ - base::{ - device::{ - bus::{Bus, BusState}, - Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable, - }, - kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, - kset::KSet, + driver::base::{ + device::{ + bus::{Bus, BusState}, + device_manager, + driver::Driver, + Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable, }, - Driver, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, }, filesystem::kernfs::KernFSInode, libs::{ rwlock::{RwLockReadGuard, RwLockWriteGuard}, spinlock::SpinLock, }, + syscall::SystemError, }; -use super::{super::device::DeviceState, CompatibleTable}; +use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable}; + +/// 平台设备id分配器 +static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(i32::MAX as usize); + +#[inline(always)] +pub fn platform_device_manager() -> &'static PlatformDeviceManager { + &PlatformDeviceManager +} + +/// 没有平台设备id +pub const PLATFORM_DEVID_NONE: i32 = -1; +/// 请求自动分配这个平台设备id +pub const PLATFORM_DEVID_AUTO: i32 = -2; /// @brief: 实现该trait的设备实例应挂载在platform总线上, /// 同时应该实现Device trait +/// +/// ## 注意 +/// +/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`, +/// 否则运行时将报错“该对象不是PlatformDriver” pub trait PlatformDevice: Device { + fn pdev_name(&self) -> &str; + /// 返回平台设备id,以及这个id是否是自动生成的 + /// + /// 请注意,如果当前设备还没有id,应该返回 + /// (PLATFORM_DEVID_NONE, false) + fn pdev_id(&self) -> (i32, bool) { + (PLATFORM_DEVID_NONE, false) + } + + /// 设置平台设备id + fn set_pdev_id(&self, id: i32); + /// 设置id是否为自动分配 + fn set_pdev_id_auto(&self, id_auto: bool); + fn compatible_table(&self) -> CompatibleTable; /// @brief: 判断设备是否初始化 /// @parameter: None @@ -39,6 +72,54 @@ pub trait PlatformDevice: Device { fn set_state(&self, set_state: DeviceState); } +#[derive(Debug)] +pub struct PlatformDeviceManager; + +impl PlatformDeviceManager { + /// platform_device_add - add a platform device to device hierarchy + pub fn device_add(&self, pdev: Arc) -> Result<(), SystemError> { + if pdev.parent().is_none() { + pdev.set_parent(Some(Arc::downgrade( + &(platform_bus_device() as Arc), + ))); + } + + pdev.set_bus(Some(platform_bus() as Arc)); + + let id = pdev.pdev_id().0; + match id { + PLATFORM_DEVID_NONE => { + pdev.set_name(format!("{}", pdev.pdev_name())); + } + PLATFORM_DEVID_AUTO => { + let id = PLATFORM_DEVID_IDA.alloc().ok_or(SystemError::EOVERFLOW)?; + pdev.set_pdev_id(id as i32); + pdev.set_pdev_id_auto(true); + pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0)); + } + _ => { + pdev.set_name(format!("{}.{}", pdev.pdev_name(), id)); + } + } + + // todo: 插入资源: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=platform_device_add#691 + let r = device_manager().add_device(pdev.clone() as Arc); + if r.is_ok() { + pdev.set_state(DeviceState::Initialized); + return Ok(()); // success + } else { + // failed + let pdevid = pdev.pdev_id(); + if pdevid.1 { + PLATFORM_DEVID_IDA.free(pdevid.0 as usize); + pdev.set_pdev_id(PLATFORM_DEVID_AUTO); + } + + return r; + } + } +} + #[derive(Debug)] #[cast_to([sync] Device)] pub struct PlatformBusDevice { @@ -56,7 +137,7 @@ impl PlatformBusDevice { ) -> Arc { return Arc::new(PlatformBusDevice { inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)), - kobj_state: LockedKObjectState::new(KObjectState::empty()), + kobj_state: LockedKObjectState::new(None), }); } @@ -101,18 +182,8 @@ impl PlatformBusDevice { let state = self.inner.lock().state; return state; } - - // /// @brief: - // /// @parameter: None - // /// @return: 总线状态 - // #[inline] - // #[allow(dead_code)] - // fn set_driver(&self, driver: Option>) { - // self.0.lock().driver = driver; - // } } -/// @brief: platform总线 #[allow(dead_code)] #[derive(Debug, Clone)] pub struct InnerPlatformBusDevice { @@ -125,14 +196,10 @@ pub struct InnerPlatformBusDevice { /// 当前设备挂载到的总线 bus: Option>, /// 当前设备已经匹配的驱动 - driver: Option>, + driver: Option>, } -/// @brief: platform方法集 impl InnerPlatformBusDevice { - /// @brief: 创建一个platform总线实例 - /// @parameter: None - /// @return: platform总线实例 pub fn new(data: DevicePrivateData, parent: Option>) -> Self { Self { data, @@ -167,6 +234,10 @@ impl KObject for PlatformBusDevice { None } + fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { + todo!("platform_bus_device::set_kobj_type") + } + fn kset(&self) -> Option> { None } @@ -218,8 +289,12 @@ impl Device for PlatformBusDevice { self.inner.lock().bus.clone() } + fn set_bus(&self, bus: Option>) { + self.inner.lock().bus = bus; + } + fn driver(&self) -> Option> { - self.inner.lock().driver.clone() + self.inner.lock().driver.clone()?.upgrade() } #[inline] @@ -227,7 +302,19 @@ impl Device for PlatformBusDevice { false } - fn set_driver(&self, driver: Option>) { + fn set_driver(&self, driver: Option>) { self.inner.lock().driver = driver; } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { + todo!() + } } diff --git a/kernel/src/driver/base/platform/platform_driver.rs b/kernel/src/driver/base/platform/platform_driver.rs index 403c0e3c..46501018 100644 --- a/kernel/src/driver/base/platform/platform_driver.rs +++ b/kernel/src/driver/base/platform/platform_driver.rs @@ -1,21 +1,54 @@ -use crate::driver::{base::device::DevicePrivateData, Driver}; +use alloc::sync::Arc; -use super::{super::device::driver::DriverError, CompatibleTable}; +use crate::{ + driver::base::device::{ + bus::Bus, + driver::{driver_manager, Driver}, + }, + syscall::SystemError, +}; + +use super::{platform_bus, platform_device::PlatformDevice}; -lazy_static! { - static ref PLATFORM_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["platform"]); -} /// @brief: 实现该trait的设备驱动实例应挂载在platform总线上, /// 同时应该实现Driver trait +/// +/// ## 注意 +/// +/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`, +/// 否则运行时将报错“该对象不是PlatformDriver” pub trait PlatformDriver: Driver { - fn compatible_table(&self) -> CompatibleTable; - /// @brief 探测设备 - /// @param data 设备初始拥有的基本信息 - fn probe(&self, data: DevicePrivateData) -> Result<(), DriverError> { - if data.compatible_table().matches(&PLATFORM_COMPAT_TABLE) { - return Ok(()); - } else { - return Err(DriverError::UnsupportedOperation); - } + /// 检测设备是否能绑定到这个驱动 + /// + /// 如果能,则把设备的driver指向这个驱动。 + /// 请注意,这个函数不应该把driver加入驱动的devices列表,相关工作会在外部的函数里面处理。 + fn probe(&self, device: &Arc) -> Result<(), SystemError>; + fn remove(&self, device: &Arc) -> Result<(), SystemError>; + fn shutdown(&self, device: &Arc) -> Result<(), SystemError>; + fn suspend(&self, device: &Arc) -> Result<(), SystemError>; + fn resume(&self, device: &Arc) -> Result<(), SystemError>; +} + +#[inline(always)] +pub fn platform_driver_manager() -> &'static PlatformDriverManager { + &PlatformDriverManager +} + +#[derive(Debug)] +pub struct PlatformDriverManager; + +impl PlatformDriverManager { + /// 注册平台设备驱动 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=__platform_driver_register#861 + pub fn register(&self, driver: Arc) -> Result<(), SystemError> { + driver.set_bus(Some(platform_bus() as Arc)); + return driver_manager().register(driver as Arc); + } + + /// 卸载平台设备驱动 + #[allow(dead_code)] + pub fn unregister(&self, driver: &Arc) { + driver_manager().unregister(&(driver.clone() as Arc)); } } diff --git a/kernel/src/driver/base/platform/subsys.rs b/kernel/src/driver/base/platform/subsys.rs index 085d9bd0..a057236b 100644 --- a/kernel/src/driver/base/platform/subsys.rs +++ b/kernel/src/driver/base/platform/subsys.rs @@ -2,15 +2,26 @@ use alloc::{ string::{String, ToString}, sync::{Arc, Weak}, }; +use intertrait::cast::CastArc; use crate::{ - driver::base::{device::bus::Bus, kobject::KObject, subsys::SubSysPrivate}, + driver::{ + acpi::acpi_manager, + base::{ + device::{bus::Bus, driver::Driver, Device}, + kobject::KObject, + subsys::SubSysPrivate, + }, + }, filesystem::{ sysfs::{Attribute, AttributeGroup}, vfs::syscall::ModeType, }, + syscall::SystemError, }; +use super::{platform_device::PlatformDevice, platform_driver::PlatformDriver}; + #[derive(Debug)] pub struct PlatformBus { private: SubSysPrivate, @@ -44,6 +55,92 @@ impl Bus for PlatformBus { fn subsystem(&self) -> &SubSysPrivate { return &self.private; } + + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let drv = device.driver().ok_or(SystemError::EINVAL)?; + let pdrv = drv.cast::().map_err(|_|{ + kerror!("PlatformBus::probe() failed: device.driver() is not a PlatformDriver. Device: '{:?}'", device.name()); + SystemError::EINVAL + })?; + + let pdev = device.clone().cast::().map_err(|_| { + kerror!( + "PlatformBus::probe() failed: device is not a PlatformDevice. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + return pdrv.probe(&pdev); + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn sync_state(&self, _device: &Arc) { + todo!() + } + + fn shutdown(&self, _device: &Arc) { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + /// + /// match platform device to platform driver. + /// + /// ## 参数 + /// + /// * `device` - platform device + /// * `driver` - platform driver + /// + /// ## 返回 + /// + /// - `Ok(true)` - 匹配成功 + /// - `Ok(false)` - 匹配失败 + /// - `Err(_)` - 由于内部错误导致匹配失败 + /// + /// Platform device IDs are assumed to be encoded like this: + /// "", where is a short description of the type of + /// device, like "pci" or "floppy", and is the enumerated + /// instance of the device, like '0' or '42'. Driver IDs are simply + /// "". So, extract the from the platform_device structure, + /// and compare it against the name of the driver. Return whether they match + /// or not. + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c#1331 + /// + /// + fn match_device( + &self, + device: &Arc, + driver: &Arc, + ) -> Result { + // 尝试从 ACPI 中匹配 + if let Ok(x) = acpi_manager().driver_match_device(driver, device) { + if x { + return Ok(true); + } + } + + // 尝试从 ID table 中匹配 + if let Some(drv_id_table) = driver.id_table() { + let pdev = device + .clone() + .cast::() + .map_err(|_| SystemError::EINVAL)?; + if drv_id_table.name().eq(&pdev.name()) { + return Ok(true); + } + } + + // 尝试根据设备名称匹配 + return Ok(device.name().eq(&driver.name())); + } } #[derive(Debug)] diff --git a/kernel/src/driver/base/subsys.rs b/kernel/src/driver/base/subsys.rs index 21b99f2d..5849c53a 100644 --- a/kernel/src/driver/base/subsys.rs +++ b/kernel/src/driver/base/subsys.rs @@ -10,14 +10,18 @@ use alloc::{ }; use crate::{ - driver::Driver, - libs::{notifier::AtomicNotifierChain, rwlock::RwLock, spinlock::SpinLock}, + libs::{ + notifier::AtomicNotifierChain, + rwlock::{RwLock, RwLockReadGuard}, + spinlock::SpinLock, + }, syscall::SystemError, }; use super::{ device::{ bus::{Bus, BusNotifyEvent}, + driver::Driver, Device, }, kset::KSet, @@ -90,12 +94,12 @@ impl SubSysPrivate { *self.bus.lock() = bus; } - pub fn devices(&self) -> &RwLock>> { - return &self.devices; + pub fn devices(&self) -> RwLockReadGuard>> { + return self.devices.read(); } - pub fn drivers(&self) -> &RwLock>> { - return &self.drivers; + pub fn drivers(&self) -> RwLockReadGuard>> { + return self.drivers.read(); } pub fn drivers_autoprobe(&self) -> bool { @@ -136,6 +140,45 @@ impl SubSysPrivate { pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] { return self.interfaces; } + + pub fn add_driver_to_vec(&self, driver: &Arc) -> Result<(), SystemError> { + let mut drivers = self.drivers.write(); + let driver_weak = Arc::downgrade(driver); + if drivers.iter().any(|d| d.ptr_eq(&driver_weak)) { + return Err(SystemError::EEXIST); + } + drivers.push(driver_weak); + return Ok(()); + } + + pub fn remove_driver_from_vec(&self, driver: &Arc) { + let mut drivers = self.drivers.write(); + let driver_weak = Arc::downgrade(driver); + let index = drivers.iter().position(|d| d.ptr_eq(&driver_weak)); + if let Some(index) = index { + drivers.remove(index); + } + } + + pub fn add_device_to_vec(&self, device: &Arc) -> Result<(), SystemError> { + let mut devices = self.devices.write(); + let device_weak = Arc::downgrade(device); + if devices.iter().any(|d| d.ptr_eq(&device_weak)) { + return Err(SystemError::EEXIST); + } + devices.push(device_weak); + return Ok(()); + } + + #[allow(dead_code)] + pub fn remove_device_from_vec(&self, device: &Arc) { + let mut devices = self.devices.write(); + let device_weak = Arc::downgrade(device); + let index = devices.iter().position(|d| d.ptr_eq(&device_weak)); + if let Some(index) = index { + devices.remove(index); + } + } } /// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device.h#63 diff --git a/kernel/src/driver/disk/ahci/ahcidisk.rs b/kernel/src/driver/disk/ahci/ahcidisk.rs index 93ab9105..7f581ea0 100644 --- a/kernel/src/driver/disk/ahci/ahcidisk.rs +++ b/kernel/src/driver/disk/ahci/ahcidisk.rs @@ -3,11 +3,12 @@ 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::device::bus::Bus; +use crate::driver::base::device::driver::Driver; use crate::driver::base::device::{Device, DeviceType, IdTable}; use crate::driver::base::kobject::{KObjType, KObject, KObjectState}; use crate::driver::base::kset::KSet; use crate::driver::disk::ahci::HBA_PxIS_TFES; -use crate::driver::Driver; + use crate::filesystem::kernfs::KernFSInode; use crate::filesystem::mbr::MbrDiskPartionTable; use crate::include::bindings::bindings::verify_area; @@ -489,6 +490,10 @@ impl KObject for LockedAhciDisk { fn set_parent(&self, _parent: Option>) { todo!() } + + fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { + todo!() + } } impl Device for LockedAhciDisk { @@ -504,6 +509,10 @@ impl Device for LockedAhciDisk { todo!("LockedAhciDisk::bus()") } + fn set_bus(&self, _bus: Option>) { + todo!("LockedAhciDisk::set_bus()") + } + fn driver(&self) -> Option> { todo!("LockedAhciDisk::driver()") } @@ -512,9 +521,21 @@ impl Device for LockedAhciDisk { false } - fn set_driver(&self, _driver: Option>) { + fn set_driver(&self, _driver: Option>) { todo!("LockedAhciDisk::set_driver()") } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { + todo!() + } } impl BlockDevice for LockedAhciDisk { diff --git a/kernel/src/driver/interrupt/apic/apic.c b/kernel/src/driver/interrupt/apic/apic.c index 48438fc3..42b160d6 100644 --- a/kernel/src/driver/interrupt/apic/apic.c +++ b/kernel/src/driver/interrupt/apic/apic.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index ba92592e..ee5767ac 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -6,50 +6,5 @@ pub mod net; pub mod pci; pub mod timers; pub mod tty; -pub mod uart; pub mod video; pub mod virtio; - -use core::fmt::Debug; - -use alloc::sync::Arc; - -use self::base::{ - device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable}, - kobject::KObject, - platform::CompatibleTable, -}; -pub trait Driver: Sync + Send + Debug + KObject { - /// @brief: 获取驱动匹配表 - /// @parameter: None - /// @return: 驱动匹配表 - /// 对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表 - fn compatible_table(&self) -> CompatibleTable { - //TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除 - return CompatibleTable::new(vec!["unknown"]); - } - - /// @brief 添加可支持的设备 - /// @parameter: device 新增的匹配项 - fn append_compatible_table(&self, _device: &CompatibleTable) -> Result<(), DriverError> { - Err(DriverError::UnsupportedOperation) - } - - /// @brief 探测设备 - /// @param data 设备初始拥有的基本信息 - fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError>; - - /// @brief 加载设备,包括检查资源可用性,和注册到相应的管理器中。 - /// @param data 设备初始拥有的信息 - /// @param resource 设备可能申请的资源(或者像伪设备不需要就为None) - fn load( - &self, - data: DevicePrivateData, - resource: Option, - ) -> Result, DriverError>; - - /// @brief: 获取驱动标识符 - /// @parameter: None - /// @return: 该驱动驱动唯一标识符 - fn id_table(&self) -> IdTable; -} diff --git a/kernel/src/driver/net/mod.rs b/kernel/src/driver/net/mod.rs index 52638031..ea12ebef 100644 --- a/kernel/src/driver/net/mod.rs +++ b/kernel/src/driver/net/mod.rs @@ -6,7 +6,7 @@ use smoltcp::{ use crate::{libs::spinlock::SpinLock, syscall::SystemError}; -use super::Driver; +use super::base::device::driver::Driver; pub mod virtio_net; diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 118b49b6..b2a0ba6c 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -11,11 +11,10 @@ use virtio_drivers::{device::net::VirtIONet, transport::Transport}; use crate::{ driver::{ base::{ - device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable}, - kobject::KObject, + device::{bus::Bus, driver::Driver, Device, IdTable}, + kobject::{KObjType, KObject, KObjectState}, }, virtio::virtio_impl::HalImpl, - Driver, }, kerror, kinfo, libs::spinlock::SpinLock, @@ -245,19 +244,27 @@ pub fn virtio_net(transport: T) { } impl Driver for VirtioInterface { - fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> { + fn id_table(&self) -> Option { todo!() } - fn load( - &self, - _data: DevicePrivateData, - _resource: Option, - ) -> Result, DriverError> { + fn add_device(&self, _device: Arc) { todo!() } - fn id_table(&self) -> IdTable { + fn delete_device(&self, _device: &Arc) { + todo!() + } + + fn devices(&self) -> alloc::vec::Vec> { + todo!() + } + + fn bus(&self) -> Option> { + todo!() + } + + fn set_bus(&self, _bus: Option>) { todo!() } } @@ -372,7 +379,11 @@ impl KObject for VirtioInterface { todo!() } - fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) { + fn set_kobj_state(&self, _state: KObjectState) { + todo!() + } + + fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { todo!() } } diff --git a/kernel/src/driver/tty/init.rs b/kernel/src/driver/tty/init.rs new file mode 100644 index 00000000..5262f414 --- /dev/null +++ b/kernel/src/driver/tty/init.rs @@ -0,0 +1,8 @@ +use crate::syscall::SystemError; + +use super::serial::serial_early_init; + +pub fn tty_early_init() -> Result<(), SystemError> { + serial_early_init()?; + return Ok(()); +} diff --git a/kernel/src/driver/tty/mod.rs b/kernel/src/driver/tty/mod.rs index 932ff786..ea4db91f 100644 --- a/kernel/src/driver/tty/mod.rs +++ b/kernel/src/driver/tty/mod.rs @@ -9,7 +9,10 @@ use thingbuf::mpsc::{ use crate::libs::rwlock::RwLock; +pub mod init; +pub mod serial; pub mod tty_device; +pub mod tty_driver; bitflags! { pub struct TtyCoreState: u32{ diff --git a/kernel/src/driver/tty/serial/mod.rs b/kernel/src/driver/tty/serial/mod.rs new file mode 100644 index 00000000..b641b1b5 --- /dev/null +++ b/kernel/src/driver/tty/serial/mod.rs @@ -0,0 +1,71 @@ +use core::{fmt::Debug, sync::atomic::AtomicU32}; + +use alloc::sync::Arc; + +use crate::{driver::base::device::DeviceNumber, mm::VirtAddr, syscall::SystemError}; + +use self::serial8250::serial8250_manager; + +use super::tty_driver::TtyDriver; + +pub mod serial8250; + +pub trait UartDriver: Debug + Send + Sync + TtyDriver { + fn device_number(&self) -> DeviceNumber; + + /// 获取最大的设备数量 + fn max_devs_num(&self) -> i32; + + // todo: 获取指向console的指针(在我们系统里面,将来可能是改进后的Textui Window) +} + +/// 串口端口应当实现的trait +/// +/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/serial_core.h#428 +pub trait UartPort { + fn iobase(&self) -> Option { + None + } + fn membase(&self) -> Option { + None + } + fn serial_in(&self, offset: u32) -> u32; + fn serial_out(&self, offset: u32, value: u32); + fn divisor(&self, baud: BaudRate) -> (u32, DivisorFraction); + fn set_divisor(&self, baud: BaudRate) -> Result<(), SystemError>; + fn baud_rate(&self) -> Option; + fn startup(&self) -> Result<(), SystemError>; + fn shutdown(&self); + fn handle_irq(&self) -> Result<(), SystemError>; +} + +int_like!(BaudRate, AtomicBaudRate, u32, AtomicU32); +int_like!(DivisorFraction, u32); + +#[inline(always)] +#[allow(dead_code)] +pub(super) fn uart_manager() -> &'static UartManager { + &UartManager +} + +#[derive(Debug)] +pub(super) struct UartManager; + +impl UartManager { + /// todo: 把uart设备注册到tty层 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720 + pub fn register_driver(&self, _driver: &Arc) -> Result<(), SystemError> { + return Ok(()); + } +} + +pub fn serial_early_init() -> Result<(), SystemError> { + serial8250_manager().early_init()?; + return Ok(()); +} + +pub(super) fn serial_init() -> Result<(), SystemError> { + serial8250_manager().init()?; + return Ok(()); +} diff --git a/kernel/src/driver/tty/serial/serial8250/mod.rs b/kernel/src/driver/tty/serial/serial8250/mod.rs new file mode 100644 index 00000000..6342e946 --- /dev/null +++ b/kernel/src/driver/tty/serial/serial8250/mod.rs @@ -0,0 +1,543 @@ +use core::{ + any::Any, + sync::atomic::{AtomicBool, AtomicI32, Ordering}, +}; + +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, + vec::Vec, +}; + +use crate::{ + driver::{ + base::{ + device::{ + bus::Bus, device_manager, driver::Driver, Device, DeviceKObjType, DeviceNumber, + DeviceState, DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + platform::{ + platform_device::{platform_device_manager, PlatformDevice}, + platform_driver::{platform_driver_manager, PlatformDriver}, + }, + }, + tty::{ + tty_device::TtyDevice, + tty_driver::{TtyDriver, TtyDriverMetadata, TtyDriverOperations}, + }, + }, + filesystem::kernfs::KernFSInode, + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, + syscall::SystemError, +}; + +use self::serial8250_pio::{send_to_serial8250_pio_com1, serial8250_pio_port_early_init}; + +use super::{uart_manager, UartDriver, UartPort}; + +mod serial8250_pio; + +static mut SERIAL8250_ISA_DEVICES: Option> = None; +static mut SERIAL8250_ISA_DRIVER: Option> = None; + +#[inline(always)] +#[allow(dead_code)] +fn serial8250_isa_devices() -> &'static Arc { + unsafe { SERIAL8250_ISA_DEVICES.as_ref().unwrap() } +} + +#[inline(always)] +#[allow(dead_code)] +fn serial8250_isa_driver() -> &'static Arc { + unsafe { SERIAL8250_ISA_DRIVER.as_ref().unwrap() } +} + +#[inline(always)] +pub(super) fn serial8250_manager() -> &'static Serial8250Manager { + &Serial8250Manager +} + +#[derive(Debug)] +pub(super) struct Serial8250Manager; + +impl Serial8250Manager { + /// 初始化串口设备(在内存管理初始化之前) + pub fn early_init(&self) -> Result<(), SystemError> { + serial8250_pio_port_early_init()?; + return Ok(()); + } + + /// 初始化serial8250设备、驱动 + /// + /// 应当在设备驱动模型初始化之后调用这里 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#1169 + pub fn init(&self) -> Result<(), SystemError> { + // 初始化serial8250 isa设备 + let serial8250_isa_dev = Serial8250ISADevices::new(); + unsafe { + SERIAL8250_ISA_DEVICES = Some(serial8250_isa_dev.clone()); + } + + let serial8250_isa_driver = Serial8250ISADriver::new(); + unsafe { + SERIAL8250_ISA_DRIVER = Some(serial8250_isa_driver.clone()); + } + // todo: 把端口绑定到isa_dev、 isa_driver上 + self.register_ports(&serial8250_isa_driver, &serial8250_isa_dev); + + // todo: 把驱动注册到uart层、tty层 + uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc))?; + + // 注册isa设备到platform总线 + platform_device_manager() + .device_add(serial8250_isa_dev.clone() as Arc) + .map_err(|e| { + unsafe { + SERIAL8250_ISA_DEVICES = None; + } + return e; + })?; + + // todo: 把驱动注册到platform总线 + platform_driver_manager() + .register(serial8250_isa_driver.clone() as Arc)?; + + return Ok(()); + } + + /// 把uart端口与uart driver、uart device绑定 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#553 + fn register_ports( + &self, + uart_driver: &Arc, + devs: &Arc, + ) { + self.bind_pio_ports(uart_driver, devs); + } + + /// 把uart端口与uart driver绑定 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_add_one_port#3048 + pub(self) fn uart_add_one_port( + &self, + _uart_driver: &Arc, + _port: &dyn UartPort, + ) -> Result<(), SystemError> { + return Ok(()); + // todo!("Serial8250Manager::uart_add_one_port") + } +} + +/// 所有的8250串口设备都应该实现的trait +trait Serial8250Port: UartPort { + fn device(&self) -> Option> { + None + } + fn set_device(&self, device: Option<&Arc>); +} + +#[derive(Debug)] +#[cast_to([sync] Device, PlatformDevice)] +struct Serial8250ISADevices { + /// 设备id是否自动分配 + id_auto: AtomicBool, + /// 平台设备id + id: AtomicI32, + + inner: RwLock, + name: &'static str, + kobj_state: LockedKObjectState, +} + +impl Serial8250ISADevices { + pub fn new() -> Arc { + let r = Arc::new(Self { + id_auto: AtomicBool::new(false), + id: AtomicI32::new(Serial8250PlatformDeviceID::Legacy as i32), + inner: RwLock::new(InnerSerial8250ISADevices::new()), + name: "serial8250", + kobj_state: LockedKObjectState::new(None), + }); + + device_manager().device_default_initialize(&(r.clone() as Arc)); + + return r; + } +} + +impl PlatformDevice for Serial8250ISADevices { + fn compatible_table(&self) -> crate::driver::base::platform::CompatibleTable { + unimplemented!() + } + + fn pdev_id(&self) -> (i32, bool) { + return ( + self.id.load(Ordering::SeqCst), + self.id_auto.load(Ordering::SeqCst), + ); + } + + fn set_pdev_id(&self, id: i32) { + self.id.store(id, Ordering::SeqCst); + } + + fn set_pdev_id_auto(&self, id_auto: bool) { + self.id_auto.store(id_auto, Ordering::SeqCst); + } + + fn pdev_name(&self) -> &str { + return self.name; + } + + fn is_initialized(&self) -> bool { + return self.inner.read().device_state == DeviceState::Initialized; + } + + fn set_state(&self, set_state: DeviceState) { + self.inner.write().device_state = set_state; + } +} + +impl Device for Serial8250ISADevices { + fn is_dead(&self) -> bool { + false + } + fn bus(&self) -> Option> { + self.inner.read().bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner.write().bus = bus; + } + + fn dev_type(&self) -> DeviceType { + DeviceType::Serial + } + + fn id_table(&self) -> IdTable { + return IdTable::new(self.name.to_string(), DeviceNumber::new(0)); + } + + fn driver(&self) -> Option> { + self.inner.read().driver.clone()?.upgrade() + } + + fn set_driver(&self, driver: Option>) { + self.inner.write().driver = driver; + } + + fn can_match(&self) -> bool { + self.inner.read().can_match + } + + fn set_can_match(&self, can_match: bool) { + self.inner.write().can_match = can_match; + } + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for Serial8250ISADevices { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.write().inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.read().inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.read().parent_kobj.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.write().parent_kobj = parent; + } + + fn kset(&self) -> Option> { + self.inner.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + Some(&DeviceKObjType) + } + + fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { + todo!() + } + + fn name(&self) -> String { + self.name.to_string() + } + + fn set_name(&self, _name: String) {} + + 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; + } +} + +#[derive(Debug)] +struct InnerSerial8250ISADevices { + /// 当前设备所述的kset + kset: Option>, + parent_kobj: Option>, + /// 当前设备所述的总线 + bus: Option>, + inode: Option>, + driver: Option>, + device_state: DeviceState, + can_match: bool, +} + +impl InnerSerial8250ISADevices { + fn new() -> Self { + Self { + kset: None, + parent_kobj: None, + bus: None, + inode: None, + driver: None, + device_state: DeviceState::NotInitialized, + can_match: false, + } + } +} + +/// Serial 8250平台设备的id +/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/serial_8250.h?fi=PLAT8250_DEV_LEGACY#49 +#[derive(Debug)] +#[repr(i32)] +enum Serial8250PlatformDeviceID { + Legacy = -1, +} + +#[derive(Debug)] + +struct InnerSerial8250ISADriver { + bus: Option>, + kobj_type: Option<&'static dyn KObjType>, + kset: Option>, + parent_kobj: Option>, + kern_inode: Option>, + devices: Vec>, +} + +impl InnerSerial8250ISADriver { + fn new() -> Self { + Self { + bus: None, + kobj_type: None, + kset: None, + parent_kobj: None, + kern_inode: None, + devices: Vec::new(), + } + } +} + +#[derive(Debug)] +#[cast_to([sync] Driver, PlatformDriver)] +struct Serial8250ISADriver { + inner: RwLock, + name: &'static str, + kobj_state: LockedKObjectState, + self_ref: Weak, +} + +impl Serial8250ISADriver { + pub fn new() -> Arc { + let r = Arc::new(Self { + inner: RwLock::new(InnerSerial8250ISADriver::new()), + name: "serial8250", + kobj_state: LockedKObjectState::new(None), + self_ref: Weak::default(), + }); + + unsafe { + let p = r.as_ref() as *const Self as *mut Self; + (*p).self_ref = Arc::downgrade(&r); + } + + return r; + } +} + +impl TtyDriver for Serial8250ISADriver { + fn driver_name(&self) -> &str { + self.name + } + + fn dev_name(&self) -> &str { + todo!() + } + + fn metadata(&self) -> &TtyDriverMetadata { + todo!() + } + + fn other(&self) -> Option<&Arc> { + todo!() + } + + fn ttys(&self) -> &[Arc] { + todo!() + } + + fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> { + None + } +} + +impl UartDriver for Serial8250ISADriver { + fn device_number(&self) -> DeviceNumber { + todo!() + } + + fn max_devs_num(&self) -> i32 { + todo!() + } +} + +impl PlatformDriver for Serial8250ISADriver { + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let isa_dev = device + .clone() + .arc_any() + .downcast::() + .map_err(|_| { + kerror!("Serial8250ISADriver::probe: device is not a Serial8250ISADevices"); + SystemError::EINVAL + })?; + isa_dev.set_driver(Some(self.self_ref.clone())); + + return Ok(()); + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn shutdown(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn suspend(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } +} + +impl Driver for Serial8250ISADriver { + fn id_table(&self) -> Option { + None + } + + fn devices(&self) -> Vec> { + self.inner.read().devices.clone() + } + + fn add_device(&self, device: Arc) { + self.inner.write().devices.push(device); + } + + fn delete_device(&self, device: &Arc) { + let mut inner = self.inner.write(); + + inner.devices.drain_filter(|d| Arc::ptr_eq(d, device)); + } + + fn bus(&self) -> Option> { + self.inner.read().bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner.write().bus = bus; + } +} + +impl KObject for Serial8250ISADriver { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.write().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.read().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.read().parent_kobj.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.write().parent_kobj = parent; + } + + fn kset(&self) -> Option> { + self.inner.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.read().kobj_type.clone() + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.write().kobj_type = ktype; + } + + fn name(&self) -> String { + "serial8250".to_string() + } + + fn set_name(&self, _name: String) {} + + 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; + } +} + +/// 临时函数,用于向默认的串口发送数据 +pub fn send_to_default_serial8250_port(s: &[u8]) { + send_to_serial8250_pio_com1(s); +} diff --git a/kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs b/kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs new file mode 100644 index 00000000..68cc3872 --- /dev/null +++ b/kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs @@ -0,0 +1,297 @@ +//! PIO的串口驱动 + +use core::{ + hint::spin_loop, + sync::atomic::{AtomicBool, Ordering}, +}; + +use alloc::sync::{Arc, Weak}; + +use crate::{ + arch::{io::PortIOArch, CurrentPortIOArch}, + driver::tty::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort}, + libs::rwlock::RwLock, + syscall::SystemError, +}; + +use super::{Serial8250ISADevices, Serial8250ISADriver, Serial8250Manager, Serial8250Port}; + +static mut PIO_PORTS: [Option; 8] = + [None, None, None, None, None, None, None, None]; + +impl Serial8250Manager { + pub(super) fn bind_pio_ports( + &self, + uart_driver: &Arc, + devs: &Arc, + ) { + for i in 0..8 { + if let Some(port) = unsafe { PIO_PORTS[i].as_ref() } { + port.set_device(Some(devs)); + self.uart_add_one_port(uart_driver, port).ok(); + } + } + } +} + +macro_rules! init_port { + ($port_num:expr, $baudrate:expr) => { + unsafe { + let port = Serial8250PIOPort::new( + match $port_num { + 1 => Serial8250PortBase::COM1, + 2 => Serial8250PortBase::COM2, + 3 => Serial8250PortBase::COM3, + 4 => Serial8250PortBase::COM4, + 5 => Serial8250PortBase::COM5, + 6 => Serial8250PortBase::COM6, + 7 => Serial8250PortBase::COM7, + 8 => Serial8250PortBase::COM8, + _ => panic!("invalid port number"), + }, + BaudRate::new($baudrate), + ); + if let Ok(port) = port { + if port.init().is_ok() { + PIO_PORTS[$port_num - 1] = Some(port); + } + } + } + }; +} + +/// 在内存管理初始化之前,初始化串口设备 +pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> { + for i in 1..=8 { + init_port!(i, 115200); + } + return Ok(()); +} + +#[derive(Debug)] +pub struct Serial8250PIOPort { + iobase: Serial8250PortBase, + baudrate: AtomicBaudRate, + initialized: AtomicBool, + inner: RwLock, +} + +impl Serial8250PIOPort { + const SERIAL8250PIO_MAX_BAUD_RATE: BaudRate = BaudRate::new(115200); + pub fn new(iobase: Serial8250PortBase, baudrate: BaudRate) -> Result { + let r = Self { + iobase, + baudrate: AtomicBaudRate::new(baudrate), + initialized: AtomicBool::new(false), + inner: RwLock::new(Serial8250PIOPortInner::new()), + }; + + if let Err(e) = r.check_baudrate(&baudrate) { + return Err(e); + } + + return Ok(r); + } + + pub fn init(&self) -> Result<(), SystemError> { + let r = self + .initialized + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst); + if r.is_err() { + // 已经初始化 + return Ok(()); + } + + let port = self.iobase as u16; + + unsafe { + CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts + self.set_divisor(self.baudrate.load(Ordering::SeqCst)) + .unwrap(); // Set baud rate + + CurrentPortIOArch::out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + CurrentPortIOArch::out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR) + CurrentPortIOArch::out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip + CurrentPortIOArch::out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if CurrentPortIOArch::in8(port + 0) != 0xAE { + self.initialized.store(false, Ordering::SeqCst); + return Err(SystemError::ENODEV); + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + CurrentPortIOArch::out8(port + 4, 0x08); + } + + return Ok(()); + /* + Notice that the initialization code above writes to [PORT + 1] + twice with different values. This is once to write to the Divisor + register along with [PORT + 0] and once to write to the Interrupt + register as detailed in the previous section. + The second write to the Line Control register [PORT + 3] + clears the DLAB again as well as setting various other bits. + */ + } + + const fn check_baudrate(&self, baudrate: &BaudRate) -> Result<(), SystemError> { + // 错误的比特率 + if baudrate.data() > Self::SERIAL8250PIO_MAX_BAUD_RATE.data() + || Self::SERIAL8250PIO_MAX_BAUD_RATE.data() % baudrate.data() != 0 + { + return Err(SystemError::EINVAL); + } + + return Ok(()); + } + + #[allow(dead_code)] + fn serial_received(&self) -> bool { + if self.serial_in(5) & 1 != 0 { + true + } else { + false + } + } + + fn is_transmit_empty(&self) -> bool { + if self.serial_in(5) & 0x20 != 0 { + true + } else { + false + } + } + + /// 发送字节 + /// + /// ## 参数 + /// + /// - `s`:待发送的字节 + fn send_bytes(&self, s: &[u8]) { + while self.is_transmit_empty() == false { + spin_loop(); + } + + for c in s { + self.serial_out(0, (*c).into()); + } + } + + /// 读取一个字节 + #[allow(dead_code)] + fn read_one_byte(&self) -> u8 { + while self.serial_received() == false { + spin_loop(); + } + return self.serial_in(0) as u8; + } +} + +impl Serial8250Port for Serial8250PIOPort { + fn device(&self) -> Option> { + self.inner.read().device() + } + + fn set_device(&self, device: Option<&Arc>) { + self.inner.write().set_device(device); + } +} + +impl UartPort for Serial8250PIOPort { + fn serial_in(&self, offset: u32) -> u32 { + unsafe { CurrentPortIOArch::in8(self.iobase as u16 + offset as u16).into() } + } + + fn serial_out(&self, offset: u32, value: u32) { + // warning: pio的串口只能写入8位,因此这里丢弃高24位 + unsafe { CurrentPortIOArch::out8(self.iobase as u16 + offset as u16, value as u8) } + } + + fn divisor(&self, baud: BaudRate) -> (u32, DivisorFraction) { + let divisor = Self::SERIAL8250PIO_MAX_BAUD_RATE.data() / baud.data(); + return (divisor, DivisorFraction::new(0)); + } + + fn set_divisor(&self, baud: BaudRate) -> Result<(), SystemError> { + self.check_baudrate(&baud)?; + + let port = self.iobase as u16; + unsafe { + CurrentPortIOArch::out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) + + let divisor = self.divisor(baud).0; + + CurrentPortIOArch::out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) + CurrentPortIOArch::out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte) + CurrentPortIOArch::out8(port + 3, 0x03); // 8 bits, no parity, one stop bit + } + + self.baudrate.store(baud, Ordering::SeqCst); + + return Ok(()); + } + + fn startup(&self) -> Result<(), SystemError> { + todo!("serial8250_pio::startup") + } + + fn shutdown(&self) { + todo!("serial8250_pio::shutdown") + } + + fn baud_rate(&self) -> Option { + Some(self.baudrate.load(Ordering::SeqCst)) + } + + fn handle_irq(&self) -> Result<(), SystemError> { + todo!("serial8250_pio::handle_irq") + } +} + +#[derive(Debug)] +struct Serial8250PIOPortInner { + /// 当前端口绑定的设备 + /// + /// ps: 存储weak以避免循环引用 + device: Option>, +} + +impl Serial8250PIOPortInner { + pub const fn new() -> Self { + Self { device: None } + } + + pub fn device(&self) -> Option> { + if let Some(device) = self.device.as_ref() { + return device.upgrade(); + } + return None; + } + + fn set_device(&mut self, device: Option<&Arc>) { + self.device = device.map(|d| Arc::downgrade(d)); + } +} + +#[allow(dead_code)] +#[repr(u16)] +#[derive(Clone, Debug, Copy)] +pub enum Serial8250PortBase { + COM1 = 0x3f8, + COM2 = 0x2f8, + COM3 = 0x3e8, + COM4 = 0x2e8, + COM5 = 0x5f8, + COM6 = 0x4f8, + COM7 = 0x5e8, + COM8 = 0x4e8, +} + +/// 临时函数,用于向COM1发送数据 +pub fn send_to_serial8250_pio_com1(s: &[u8]) { + if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } { + port.send_bytes(s); + } +} diff --git a/kernel/src/driver/tty/tty_device.rs b/kernel/src/driver/tty/tty_device.rs index a988a07a..012ba4a8 100644 --- a/kernel/src/driver/tty/tty_device.rs +++ b/kernel/src/driver/tty/tty_device.rs @@ -20,7 +20,7 @@ use crate::{ syscall::SystemError, }; -use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; +use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData}; lazy_static! { /// 所有TTY设备的B树。用于根据名字,找到Arc @@ -283,17 +283,6 @@ impl TtyDevicePrivateData { } } -/// @brief 导出到C的tty初始化函数 -#[no_mangle] -pub extern "C" fn rs_tty_init() -> i32 { - let r = tty_init(); - if r.is_ok() { - return 0; - } else { - return r.unwrap_err().to_posix_errno(); - } -} - /// @brief 初始化TTY设备 pub fn tty_init() -> Result<(), SystemError> { let tty: Arc = TtyDevice::new("tty0"); @@ -322,5 +311,6 @@ pub fn tty_init() -> Result<(), SystemError> { return Err(devfs_root_inode.unwrap_err()); } + serial_init()?; return Ok(()); } diff --git a/kernel/src/driver/tty/tty_driver.rs b/kernel/src/driver/tty/tty_driver.rs new file mode 100644 index 00000000..839a532c --- /dev/null +++ b/kernel/src/driver/tty/tty_driver.rs @@ -0,0 +1,61 @@ +use core::fmt::Debug; + +use alloc::sync::Arc; + +use crate::driver::base::device::driver::Driver; + +use super::tty_device::TtyDevice; + +/// TTY 驱动 +/// +/// +/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#434 +pub trait TtyDriver: Debug + Send + Sync + Driver { + fn driver_name(&self) -> &str; + fn dev_name(&self) -> &str; + + fn metadata(&self) -> &TtyDriverMetadata; + + fn other(&self) -> Option<&Arc>; + + fn ttys(&self) -> &[Arc]; + + fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> { + None + } +} + +#[derive(Debug, Clone, Copy)] +#[allow(dead_code)] +pub struct TtyDriverMetadata { + /// name of the driver used in /proc/tty + driver_name: &'static str, + /// used for constructing /dev node name + dev_name: &'static str, + /// used as a number base for constructing /dev node name + name_base: i32, + /// major /dev device number (zero for autoassignment) + major: i32, + /// the first minor /dev device number + minor_start: i32, + drv_type: TtyDriverType, + subtype: TtyDriverSubtype, +} + +/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#411 +#[derive(Debug, Clone, Copy)] +pub enum TtyDriverType {} + +/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#412 +#[derive(Debug, Clone, Copy)] +pub enum TtyDriverSubtype {} + +bitflags! { + /// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h?fi=SERIAL_TYPE_NORMAL#492 + pub struct TtyDriverFlags: u64 { + + } +} + +/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#350 +pub trait TtyDriverOperations {} diff --git a/kernel/src/driver/uart/mod.rs b/kernel/src/driver/uart/mod.rs deleted file mode 100644 index 59f95bb5..00000000 --- a/kernel/src/driver/uart/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod uart_device; -pub mod uart_driver; diff --git a/kernel/src/driver/uart/uart.h b/kernel/src/driver/uart/uart.h deleted file mode 100644 index 0531d769..00000000 --- a/kernel/src/driver/uart/uart.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -//driver/uart/uart.rs --rust function -enum uart_port_io_addr -{ - COM1 = 0x3f8, - COM2 = 0x2f8, - COM3 = 0x3e8, - COM4 = 0x2e8, - COM5 = 0x5f8, - COM6 = 0x4f8, - COM7 = 0x5e8, - COM8 = 0x4E8, -}; -extern int c_uart_init(uint16_t port, uint32_t baud_rate); -extern void c_uart_send(uint16_t port, char c); -extern void c_uart_send_str(uint16_t port, const char *str); \ No newline at end of file diff --git a/kernel/src/driver/uart/uart_device.rs b/kernel/src/driver/uart/uart_device.rs deleted file mode 100644 index 071567df..00000000 --- a/kernel/src/driver/uart/uart_device.rs +++ /dev/null @@ -1,805 +0,0 @@ -use crate::{ - driver::{ - base::{ - char::CharDevice, - device::{ - bus::Bus, driver::DriverError, Device, DeviceError, DeviceNumber, - DevicePrivateData, DeviceResource, DeviceState, DeviceType, IdTable, - }, - kobject::{KObjType, KObject, KObjectState}, - kset::KSet, - platform::{ - platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable, - }, - }, - Driver, - }, - filesystem::{ - devfs::{devfs_register, DevFS, DeviceINode}, - kernfs::KernFSInode, - vfs::{ - syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, - PollStatus, - }, - }, - include::bindings::bindings::{io_in8, io_out8}, - kinfo, - libs::{ - rwlock::{RwLockReadGuard, RwLockWriteGuard}, - spinlock::SpinLock, - }, - syscall::SystemError, -}; -use alloc::{ - string::{String, ToString}, - sync::{Arc, Weak}, - vec::Vec, -}; -use core::{ - any::Any, - char, - intrinsics::offset, - str::{self, from_utf8}, -}; - -const UART_SUCCESS: i32 = 0; -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, Debug)] -pub enum UartPort { - COM1 = 0x3f8, - COM2 = 0x2f8, - COM3 = 0x3e8, - COM4 = 0x2e8, - COM5 = 0x5f8, - COM6 = 0x4f8, - COM7 = 0x5e8, - COM8 = 0x4e8, -} - -impl UartPort { - ///@brief 将u16转换为UartPort枚举类型 - ///@param val 要转换的u16类型 - ///@return 输入的端口地址正确,返回UartPort类型,错误,返回错误信息 - #[allow(dead_code)] - pub fn from_u16(val: u16) -> Result { - match val { - 0x3f8 => Ok(Self::COM1), - 0x2f8 => Ok(Self::COM2), - 0x3e8 => Ok(Self::COM3), - 0x2e8 => Ok(Self::COM4), - 0x5f8 => Ok(Self::COM5), - 0x4f8 => Ok(Self::COM6), - 0x5e8 => Ok(Self::COM7), - 0x4e8 => Ok(Self::COM8), - _ => Err("port error!"), - } - } - - ///@brief 将UartPort枚举类型转换为u16类型 - ///@param self 要转换的UartPort - ///@return 转换的u16值 - #[allow(dead_code)] - pub fn to_u16(self: &Self) -> u16 { - match self { - Self::COM1 => 0x3f8, - Self::COM2 => 0x2f8, - Self::COM3 => 0x3e8, - Self::COM4 => 0x2e8, - Self::COM5 => 0x5f8, - Self::COM6 => 0x4f8, - Self::COM7 => 0x5e8, - Self::COM8 => 0x4e8, - } - } -} - -// @brief 串口寄存器 -#[allow(dead_code)] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -struct UartRegister { - reg_data: u8, - reg_interrupt_enable: u8, - reg_ii_fifo: u8, // Interrupt Identification and FIFO control registers - reg_line_config: u8, - reg_modem_config: u8, - reg_line_status: u8, - reg_modem_statue: u8, - reg_scartch: u8, -} - -// @brief 串口设备结构体 -#[derive(Debug)] -pub struct Uart { - private_data: DevicePrivateData, // 设备状态 - fs: Weak, // 文件系统 - port: UartPort, - baud_rate: u32, - metadata: Metadata, -} - -impl Default for Uart { - fn default() -> Self { - let mut metadata = Metadata::default(); - metadata.file_type = FileType::CharDevice; - c_uart_init(UartPort::COM1.to_u16(), 115200); - Self { - private_data: DevicePrivateData::new( - IdTable::new( - "uart".to_string(), - DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)), - ), - None, - CompatibleTable::new(vec!["uart"]), - DeviceState::NotInitialized, - ), - fs: Weak::default(), - port: UartPort::COM1, - baud_rate: 115200, - metadata, - } - } -} - -// @brief 串口设备结构体(加锁) -#[derive(Debug)] -pub struct LockedUart(SpinLock); - -impl Default for LockedUart { - fn default() -> Self { - Self(SpinLock::new(Uart::default())) - } -} - -impl KObject for LockedUart { - fn as_any_ref(&self) -> &dyn core::any::Any { - self - } - - fn inode(&self) -> Option> { - todo!() - } - - fn kobj_type(&self) -> Option<&'static dyn KObjType> { - todo!() - } - - fn kset(&self) -> Option> { - todo!() - } - - fn parent(&self) -> Option> { - todo!() - } - - fn set_inode(&self, _inode: Option>) { - todo!() - } - - fn kobj_state(&self) -> RwLockReadGuard { - todo!() - } - - fn kobj_state_mut(&self) -> RwLockWriteGuard { - todo!() - } - - fn set_kobj_state(&self, _state: KObjectState) { - todo!() - } - - fn name(&self) -> alloc::string::String { - todo!() - } - - fn set_name(&self, _name: alloc::string::String) { - todo!() - } - - fn set_kset(&self, _kset: Option>) { - todo!() - } - - fn set_parent(&self, _parent: Option>) { - todo!() - } -} - -impl PlatformDevice for LockedUart { - fn is_initialized(&self) -> bool { - let state = self.0.lock().private_data.state(); - match state { - DeviceState::Initialized => true, - _ => false, - } - } - - fn set_state(&self, set_state: DeviceState) { - self.0.lock().private_data.set_state(set_state); - } - - fn compatible_table(&self) -> CompatibleTable { - return self.0.lock().private_data.compatible_table().clone(); - } -} - -impl Device for LockedUart { - fn id_table(&self) -> IdTable { - return IdTable::new( - "uart".to_string(), - DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)), - ); - } - - fn dev_type(&self) -> DeviceType { - DeviceType::Serial - } - - fn bus(&self) -> Option> { - todo!("LockedUart::bus()") - } - - fn driver(&self) -> Option> { - todo!("LockedUart::driver()") - } - - fn is_dead(&self) -> bool { - false - } - - fn set_driver(&self, _driver: Option>) { - todo!("LockedUart::set_driver()") - } -} - -impl CharDevice for LockedUart { - fn read(&self, len: usize, buf: &mut [u8]) -> Result { - let device = self.0.lock(); - if len > buf.len() { - return Err(SystemError::E2BIG); - } - kinfo!("------len: {:?}", len); - for i in 0..len { - buf[i] = Self::uart_read_byte(&device.port) as u8; - kinfo!("------buf[{:?}] = {:?}", i, buf[i]); - } - return Ok(len); - } - - fn write(&self, len: usize, buf: &[u8]) -> Result { - let device = self.0.lock(); - if len > buf.len() { - return Err(SystemError::E2BIG); - } - Self::uart_send( - &device.port, - from_utf8(&buf[0..len]).map_err(|_| SystemError::EIO)?, - ); - - return Ok(len); - } - - fn sync(&self) -> Result<(), SystemError> { - todo!() - } -} - -// impl TtyDevice for LockedUart { -// fn ioctl(&self, cmd: String) -> Result<(), DeviceError> { -// //TODO 补充详细信息 -// Err(DeviceError::UnsupportedOperation) -// } -// fn state(&self) -> Result { -// todo!() -// } -// } - -impl IndexNode for LockedUart { - fn read_at( - &self, - _offset: usize, - len: usize, - buf: &mut [u8], - _data: &mut FilePrivateData, - ) -> Result { - CharDevice::read(self, len, buf) - } - - fn write_at( - &self, - _offset: usize, - len: usize, - buf: &[u8], - _data: &mut FilePrivateData, - ) -> Result { - CharDevice::write(self, len, buf) - } - - fn poll(&self) -> Result { - todo!() - } - - fn fs(&self) -> Arc { - return self - .0 - .lock() - .fs - .clone() - .upgrade() - .expect("DevFS is not initialized inside Uart Device"); - } - - fn as_any_ref(&self) -> &dyn Any { - todo!() - } - - fn list(&self) -> Result, SystemError> { - todo!() - } - - fn metadata(&self) -> Result { - return Ok(self.0.lock().metadata.clone()); - } - - fn open( - &self, - _data: &mut FilePrivateData, - _mode: &crate::filesystem::vfs::file::FileMode, - ) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Ok(()); - } - - fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Ok(()); - } - - fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Ok(self.0.lock().metadata = _metadata.clone()); - } - fn create( - &self, - name: &str, - file_type: FileType, - mode: ModeType, - ) -> Result, SystemError> { - // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值 - return self.create_with_data(name, file_type, mode, 0); - } - - fn create_with_data( - &self, - _name: &str, - _file_type: FileType, - _mode: ModeType, - _data: usize, - ) -> Result, SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn link(&self, _name: &str, _other: &Arc) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn unlink(&self, _name: &str) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn rmdir(&self, _name: &str) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn move_( - &self, - _old_name: &str, - _target: &Arc, - _new_name: &str, - ) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn find(&self, _name: &str) -> Result, SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn get_entry_name(&self, _ino: crate::filesystem::vfs::InodeId) -> Result { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn get_entry_name_and_metadata( - &self, - ino: crate::filesystem::vfs::InodeId, - ) -> Result<(String, Metadata), SystemError> { - // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 - let name = self.get_entry_name(ino)?; - let entry = self.find(&name)?; - return Ok((name, entry.metadata()?)); - } - - fn ioctl(&self, _cmd: u32, _data: usize) -> Result { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn mount( - &self, - _fs: Arc, - ) -> Result, SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn truncate(&self, _len: usize) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - fn sync(&self) -> Result<(), SystemError> { - return Ok(()); - } -} - -impl DeviceINode for LockedUart { - fn set_fs(&self, fs: Weak) { - self.0.lock().fs = fs; - } -} - -impl LockedUart { - /// @brief 串口初始化 - /// @param uart_port 端口号 - /// @param baud_rate 波特率 - /// @return 初始化成功,返回0,失败,返回错误信息 - #[allow(dead_code)] - pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<(), DeviceError> { - let message: &'static str = "uart init."; - let port = uart_port.to_u16(); - // 错误的比特率 - if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 { - return Err(DeviceError::InitializeFailed); - } - - unsafe { - io_out8(port + 1, 0x00); // Disable all interrupts - io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) - - 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 + 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) - io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip - io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) - - // Check if serial is faulty (i.e: not same byte as sent) - if io_in8(port + 0) != 0xAE { - return Err(DeviceError::InitializeFailed); - } - - // If serial is not faulty set it in normal operation mode - // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) - io_out8(port + 4, 0x08); - } - Self::uart_send(uart_port, message); - Ok(()) - /* - Notice that the initialization code above writes to [PORT + 1] - twice with different values. This is once to write to the Divisor - register along with [PORT + 0] and once to write to the Interrupt - register as detailed in the previous section. - The second write to the Line Control register [PORT + 3] - clears the DLAB again as well as setting various other bits. - */ - } - - fn serial_received(offset: u16) -> bool { - if unsafe { io_in8(offset + 5) } & 1 != 0 { - true - } else { - false - } - } - - fn is_transmit_empty(offset: u16) -> bool { - if unsafe { io_in8(offset + 5) } & 0x20 != 0 { - true - } else { - false - } - } - - /// @brief 串口发送 - /// @param uart_port 端口号 - /// @param str 发送字符切片 - /// @return None - #[allow(dead_code)] - fn uart_send(uart_port: &UartPort, s: &str) { - let port = uart_port.to_u16(); - while Self::is_transmit_empty(port) == false {} //TODO:pause - for c in s.bytes() { - unsafe { - io_out8(port, c); - } - } - } - - /// @brief 串口接收一个字节 - /// @param uart_port 端口号 - /// @return 接收的字节 - #[allow(dead_code)] - fn uart_read_byte(uart_port: &UartPort) -> char { - let port = uart_port.to_u16(); - while Self::serial_received(port) == false {} //TODO:pause - return unsafe { io_in8(port) as char }; - } - - #[allow(dead_code)] - fn port() -> u16 { - UartPort::COM1.to_u16() - } -} - -// @brief 串口驱动结构体 -#[repr(C)] -#[derive(Debug)] -pub struct UartDriver { - id_table: IdTable, - - sys_info: Option>, -} - -impl Default for UartDriver { - fn default() -> Self { - Self { - id_table: IdTable::new( - "ttyS".to_string(), - DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)), - ), - - 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 { - fn as_any_ref(&self) -> &dyn core::any::Any { - self - } - - fn inode(&self) -> Option> { - todo!() - } - - fn kobj_type(&self) -> Option<&'static dyn KObjType> { - todo!() - } - - fn kset(&self) -> Option> { - todo!() - } - - fn parent(&self) -> Option> { - todo!() - } - - fn set_inode(&self, _inode: Option>) { - todo!() - } - - fn kobj_state(&self) -> RwLockReadGuard { - todo!() - } - - fn kobj_state_mut(&self) -> RwLockWriteGuard { - todo!() - } - - fn set_kobj_state(&self, _state: KObjectState) { - todo!() - } - - fn name(&self) -> alloc::string::String { - todo!() - } - - fn set_name(&self, _name: alloc::string::String) { - todo!() - } - - fn set_kset(&self, _kset: Option>) { - todo!() - } - - fn set_parent(&self, _parent: Option>) { - todo!() - } -} - -impl Driver for LockedUartDriver { - fn id_table(&self) -> IdTable { - return IdTable::new("uart_driver".to_string(), DeviceNumber::new(0)); - } - - fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> { - let table = data.compatible_table(); - if table.matches(&CompatibleTable::new(vec!["uart"])) { - return Ok(()); - } - return Err(DriverError::ProbeError); - } - - fn load( - &self, - _data: DevicePrivateData, - _resource: Option, - ) -> Result, DriverError> { - return Err(DriverError::UnsupportedOperation); - } -} - -impl LockedUartDriver { - /// @brief 创建串口驱动 - /// @param sys_info: sys文件系统inode - /// @return - #[allow(dead_code)] - pub fn new(sys_info: Option>) -> Self { - Self(SpinLock::new(UartDriver::new(sys_info))) - } -} - -impl PlatformDriver for LockedUartDriver { - fn compatible_table(&self) -> CompatibleTable { - return CompatibleTable::new(vec!["uart"]); - } -} - -impl UartDriver { - /// @brief 创建串口驱动 - /// @param sys_info: sys文件系统inode - /// @return 返回串口驱动 - #[allow(dead_code)] - pub fn new(sys_info: Option>) -> Self { - Self { - id_table: IdTable::new( - "ttyS".to_string(), - DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)), - ), - sys_info, - } - } -} - -///@brief 发送数据 -///@param port 端口号 -///@param c 要发送的数据 -#[no_mangle] -pub extern "C" fn c_uart_send(port: u16, c: u8) { - while LockedUart::is_transmit_empty(port) == false {} //TODO:pause - unsafe { - io_out8(port, c); - } -} - -///@brief 从uart接收数据 -///@param port 端口号 -///@return u8 接收到的数据 -#[no_mangle] -pub extern "C" fn c_uart_read(port: u16) -> u8 { - while LockedUart::serial_received(port) == false {} //TODO:pause - unsafe { io_in8(port) } -} - -///@brief 通过串口发送整个字符串 -///@param port 串口端口 -///@param str 字符串S -#[no_mangle] -pub extern "C" fn c_uart_send_str(port: u16, s: *const u8) { - unsafe { - let mut i = 0isize; - while *offset(s, i) != '\0' as u8 { - c_uart_send(port, *offset(s, i)); - i = i + 1; - } - } -} - -/// @brief 串口初始化 -/// @param u16 端口号 -/// @param baud_rate 波特率 -/// @return 初始化成功,返回0,失败,返回错误码 -#[no_mangle] -pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 { - let message: &'static str = "uart init\n"; - // 错误的比特率 - if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 { - return -E_UART_BITS_RATE_ERROR; - } - - unsafe { - io_out8(port + 1, 0x00); // Disable all interrupts - io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) - - 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); // 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) - io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip - io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) - - // Check if serial is faulty (i.e: not same byte as sent) - if io_in8(port + 0) != 0xAE { - return -E_UART_SERIAL_FAULT; - } - - // If serial is not faulty set it in normal operation mode - // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) - io_out8(port + 4, 0x08); - let bytes = message.as_bytes(); - for c in bytes { - c_uart_send(port, *c); - } - } - return UART_SUCCESS; - /* - Notice that the initialization code above writes to [PORT + 1] - twice with different values. This is once to write to the Divisor - register along with [PORT + 0] and once to write to the Interrupt - register as detailed in the previous section. - The second write to the Line Control register [PORT + 3] - clears the DLAB again as well as setting various other bits. - */ -} - -/// @brief 串口初始化,注册串口 -/// @param none -/// @return 初始化成功,返回(),失败,返回错误码 -pub fn uart_init() -> Result<(), SystemError> { - // 以后设备管理初始化完善后不应该出现这种代码,应该在 Driver load 一个设备,即返回设备实例之前就完成设备的 init ,不应该用 lazy_init 在设备上 - let dev = UART_DEV.0.lock(); - LockedUart::uart_init(&dev.port, dev.baud_rate).map_err(|_| SystemError::ENODEV)?; - drop(dev); - // let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().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().name()) - // .expect("uart driver register error"); - // UART_DRV.set_sys_info(Some(driver_inode)); - UART_DEV.set_state(DeviceState::Initialized); - devfs_register(&UART_DEV.id_table().name(), UART_DEV.clone())?; - // DEVICE_MANAGER.add_device(UART_DEV.id_table().clone(), UART_DEV.clone()); - return Ok(()); -} diff --git a/kernel/src/driver/uart/uart_driver.rs b/kernel/src/driver/uart/uart_driver.rs deleted file mode 100644 index a1898fc5..00000000 --- a/kernel/src/driver/uart/uart_driver.rs +++ /dev/null @@ -1,129 +0,0 @@ -use alloc::sync::Arc; - -use crate::driver::base::char::CharDevOps; -use crate::driver::base::device::{device_manager, Device, DeviceResource}; -use crate::driver::base::kobject::KObject; -use crate::driver::base::platform::CompatibleTable; -use crate::{ - driver::{ - base::device::{driver::DriverError, DevicePrivateData, IdTable}, - Driver, - }, - libs::spinlock::SpinLock, -}; - -use super::uart_device::LockedUart; - -lazy_static! { - pub static ref UART_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["uart"]); -} - -#[derive(Debug)] -pub struct InnerUartDriver { - id_table: IdTable, -} - -#[derive(Debug)] -pub struct UartDriver(SpinLock); - -impl Default for UartDriver { - fn default() -> Self { - Self(SpinLock::new(InnerUartDriver { - id_table: IdTable::default(), - })) - } -} -impl KObject for UartDriver { - fn as_any_ref(&self) -> &dyn core::any::Any { - self - } - - fn set_inode(&self, _inode: Option>) { - todo!() - } - - fn inode(&self) -> Option> { - todo!() - } - - fn parent(&self) -> Option> { - todo!() - } - - fn set_parent(&self, _parent: Option>) { - todo!() - } - - fn kset(&self) -> Option> { - todo!() - } - - fn set_kset(&self, _kset: Option>) { - todo!() - } - - fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> { - todo!() - } - - fn name(&self) -> alloc::string::String { - todo!() - } - - fn set_name(&self, _name: alloc::string::String) { - todo!() - } - - fn kobj_state( - &self, - ) -> crate::libs::rwlock::RwLockReadGuard { - todo!() - } - - fn kobj_state_mut( - &self, - ) -> crate::libs::rwlock::RwLockWriteGuard { - todo!() - } - - fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) { - todo!() - } -} -impl Driver for UartDriver { - fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> { - let compatible_table = data.compatible_table(); - if compatible_table.matches(&UART_COMPAT_TABLE) { - return Ok(()); - } - - return Err(DriverError::ProbeError); - } - - fn load( - &self, - data: DevicePrivateData, - _resource: Option, - ) -> Result, DriverError> { - if let Some(device) = device_manager().find_device_by_idtable(data.id_table()) { - return Ok(device.clone()); - } - let compatible_table = data.compatible_table(); - if compatible_table.matches(&UART_COMPAT_TABLE) { - let device = LockedUart::default(); - let arc_device = Arc::new(device); - device_manager() - .add_device(arc_device.clone()) - .map_err(|_| DriverError::RegisterError)?; - CharDevOps::cdev_add(arc_device.clone(), data.id_table().clone(), 1) - .map_err(|_| DriverError::RegisterError)?; - } - - return Err(DriverError::RegisterError); - } - - fn id_table(&self) -> IdTable { - let driver = self.0.lock(); - return driver.id_table.clone(); - } -} diff --git a/kernel/src/driver/video/mod.rs b/kernel/src/driver/video/mod.rs index 79cd37ba..590cc160 100644 --- a/kernel/src/driver/video/mod.rs +++ b/kernel/src/driver/video/mod.rs @@ -8,8 +8,7 @@ use alloc::{boxed::Box, sync::Arc}; use crate::{ arch::MMArch, - driver::uart::uart_device::c_uart_send_str, - driver::uart::uart_device::UartPort::COM1, + driver::tty::serial::serial8250::send_to_default_serial8250_port, include::bindings::bindings::{ multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t, FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE, @@ -226,7 +225,7 @@ impl VideoRefreshManager { .unwrap(); let init_text = "Video driver to map.\n\0"; - c_uart_send_str(COM1 as u16, init_text.as_ptr()); + send_to_default_serial8250_port(init_text.as_bytes()); //地址映射 let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize); @@ -245,7 +244,7 @@ impl VideoRefreshManager { __MAMAGER = Some(result); let init_text = "Video driver initialized.\n\0"; - c_uart_send_str(COM1 as u16, init_text.as_ptr()); + send_to_default_serial8250_port(init_text.as_bytes()); return Ok(()); } } diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs index b582a946..dc194563 100644 --- a/kernel/src/filesystem/kernfs/mod.rs +++ b/kernel/src/filesystem/kernfs/mod.rs @@ -1,4 +1,4 @@ -use core::{fmt::Debug, intrinsics::unlikely}; +use core::{cmp::min, fmt::Debug, intrinsics::unlikely}; use alloc::{ string::String, @@ -64,7 +64,7 @@ impl KernFS { (*ptr).self_ref = Arc::downgrade(&root_inode); } } - root_inode.inner.lock().parent = Arc::downgrade(&root_inode); + root_inode.inner.write().parent = Arc::downgrade(&root_inode); *root_inode.fs.write() = Arc::downgrade(&fs); return fs; } @@ -88,9 +88,11 @@ impl KernFS { }; let root_inode = Arc::new(KernFSInode { name: String::from(""), - inner: SpinLock::new(InnerKernFSInode { + inner: RwLock::new(InnerKernFSInode { parent: Weak::new(), metadata, + symlink_target: None, + symlink_target_absolute_path: None, }), self_ref: Weak::new(), fs: RwLock::new(Weak::new()), @@ -106,7 +108,7 @@ impl KernFS { #[derive(Debug)] pub struct KernFSInode { - inner: SpinLock, + inner: RwLock, /// 指向当前Inode所属的文件系统的弱引用 fs: RwLock>, /// 指向自身的弱引用 @@ -129,6 +131,9 @@ pub struct InnerKernFSInode { /// 当前inode的元数据 metadata: Metadata, + /// 符号链接指向的inode(仅当inode_type为SymLink时有效) + symlink_target: Option>, + symlink_target_absolute_path: Option, } impl IndexNode for KernFSInode { @@ -151,7 +156,7 @@ impl IndexNode for KernFSInode { } fn metadata(&self) -> Result { - return Ok(self.inner.lock().metadata.clone()); + return Ok(self.inner.read().metadata.clone()); } fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { @@ -214,7 +219,7 @@ impl IndexNode for KernFSInode { ".." => { return Ok(self .inner - .lock() + .read() .parent .upgrade() .ok_or(SystemError::ENOENT)?); @@ -300,6 +305,25 @@ impl IndexNode for KernFSInode { buf: &mut [u8], _data: &mut FilePrivateData, ) -> Result { + if self.inode_type == KernInodeType::SymLink { + let inner = self.inner.read(); + if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() { + return Ok(0); + } + let len = min(len, buf.len()); + let len = min( + len, + inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset, + ); + buf[0..len].copy_from_slice( + &inner + .symlink_target_absolute_path + .as_ref() + .unwrap() + .as_bytes()[offset..offset + len], + ); + return Ok(len); + } if self.inode_type != KernInodeType::File { return Err(SystemError::EISDIR); } @@ -344,6 +368,51 @@ impl IndexNode for KernFSInode { } impl KernFSInode { + pub fn new( + parent: Option>, + name: String, + mut metadata: Metadata, + inode_type: KernInodeType, + private_data: Option, + callback: Option<&'static dyn KernFSCallback>, + ) -> Arc { + metadata.file_type = inode_type.into(); + let parent: Weak = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default(); + + let inode = Arc::new(KernFSInode { + name, + inner: RwLock::new(InnerKernFSInode { + parent: parent.clone(), + metadata, + symlink_target: None, + symlink_target_absolute_path: None, + }), + self_ref: Weak::new(), + fs: RwLock::new(Weak::new()), + private_data: SpinLock::new(private_data), + callback, + children: SpinLock::new(HashMap::new()), + inode_type, + }); + + { + let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode; + unsafe { + (*ptr).self_ref = Arc::downgrade(&inode); + } + } + if parent.strong_count() > 0 { + let kernfs = parent + .upgrade() + .unwrap() + .fs() + .downcast_arc::() + .expect("KernFSInode::new: parent is not a KernFS instance"); + *inode.fs.write() = Arc::downgrade(&kernfs); + } + return inode; + } + /// 在当前inode下增加子目录 /// /// ## 参数 @@ -410,11 +479,15 @@ impl KernFSInode { private_data: Option, callback: Option<&'static dyn KernFSCallback>, ) -> Result, SystemError> { - let size = if file_type == KernInodeType::File { - 4096 - } else { - 0 - }; + let size; + match file_type { + KernInodeType::Dir | KernInodeType::SymLink => { + size = 0; + } + KernInodeType::File => { + size = 4096; + } + } let metadata = Metadata { size, @@ -475,47 +548,35 @@ impl KernFSInode { } } - pub fn new( - parent: Option>, + /// add_link - create a symlink in kernfs + /// + /// ## 参数 + /// + /// - `parent`: directory to create the symlink in + /// - `name`: name of the symlink + /// - `target`: target node for the symlink to point to + /// + /// Returns the created node on success + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25 + pub fn add_link( + &self, name: String, - mut metadata: Metadata, - inode_type: KernInodeType, - private_data: Option, - callback: Option<&'static dyn KernFSCallback>, - ) -> Arc { - metadata.file_type = inode_type.into(); - let parent: Weak = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default(); - - let inode = Arc::new(KernFSInode { + target: &Arc, + target_absolute_path: String, + ) -> Result, SystemError> { + // kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}"); + let inode = self.inner_create( name, - inner: SpinLock::new(InnerKernFSInode { - parent: parent.clone(), - metadata, - }), - self_ref: Weak::new(), - fs: RwLock::new(Weak::new()), - private_data: SpinLock::new(private_data), - callback, - children: SpinLock::new(HashMap::new()), - inode_type, - }); + KernInodeType::SymLink, + ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777), + None, + None, + )?; - { - let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode; - unsafe { - (*ptr).self_ref = Arc::downgrade(&inode); - } - } - if parent.strong_count() > 0 { - let kernfs = parent - .upgrade() - .unwrap() - .fs() - .downcast_arc::() - .expect("KernFSInode::new: parent is not a KernFS instance"); - *inode.fs.write() = Arc::downgrade(&kernfs); - } - return inode; + inode.inner.write().symlink_target = Some(Arc::downgrade(target)); + inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path); + return Ok(inode); } pub fn name(&self) -> &str { @@ -523,13 +584,18 @@ impl KernFSInode { } pub fn parent(&self) -> Option> { - return self.inner.lock().parent.upgrade(); + return self.inner.read().parent.upgrade(); } pub fn private_data_mut(&self) -> SpinLockGuard> { return self.private_data.lock(); } + #[allow(dead_code)] + pub fn symlink_target(&self) -> Option> { + return self.inner.read().symlink_target.as_ref()?.upgrade(); + } + /// remove a kernfs_node recursively pub fn remove_recursive(&self) { let mut children = self.children.lock().drain().collect::>(); @@ -552,6 +618,7 @@ impl KernFSInode { pub enum KernInodeType { Dir, File, + SymLink, } impl Into for KernInodeType { @@ -559,6 +626,7 @@ impl Into for KernInodeType { match self { KernInodeType::Dir => FileType::Dir, KernInodeType::File => FileType::File, + KernInodeType::SymLink => FileType::SymLink, } } } diff --git a/kernel/src/filesystem/sysfs/group.rs b/kernel/src/filesystem/sysfs/group.rs index 54bc89c8..ce8729f9 100644 --- a/kernel/src/filesystem/sysfs/group.rs +++ b/kernel/src/filesystem/sysfs/group.rs @@ -34,7 +34,14 @@ impl SysFS { ) -> Result<(), SystemError> { for i in 0..groups.len() { let group = groups[i]; + if group.attrs().is_empty() { + continue; + } if let Err(e) = self.do_create_group(kobj, group, update) { + kerror!( + "Failed to create group '{}', err={e:?}", + group.name().unwrap_or("") + ); for j in (0..=i).rev() { self.remove_group(kobj, groups[j]).ok(); } @@ -98,6 +105,16 @@ impl SysFS { return Ok(()); } + pub fn remove_groups( + &self, + kobj: &Arc, + groups: &'static [&'static dyn AttributeGroup], + ) { + for group in groups.iter() { + self.remove_group(kobj, *group).ok(); + } + } + /// 从一个kobject中移除一个group /// /// This function removes a group of attributes from a kobject. The attributes @@ -187,6 +204,10 @@ impl SysFS { } if let Err(e) = e { + kerror!( + "Failed to create sysfs files for group '{}', err={e:?}", + group.name().unwrap_or("") + ); self.group_remove_files(&parent, group); return Err(e); } diff --git a/kernel/src/filesystem/sysfs/symlink.rs b/kernel/src/filesystem/sysfs/symlink.rs index 3954db92..a7e2d2ad 100644 --- a/kernel/src/filesystem/sysfs/symlink.rs +++ b/kernel/src/filesystem/sysfs/symlink.rs @@ -1,6 +1,12 @@ -use alloc::{string::String, sync::Arc}; +use alloc::{ + borrow::ToOwned, + string::{String, ToString}, + sync::Arc, +}; -use crate::{driver::base::kobject::KObject, syscall::SystemError}; +use crate::{ + driver::base::kobject::KObject, filesystem::kernfs::KernFSInode, syscall::SystemError, +}; use super::SysFS; @@ -9,18 +15,19 @@ impl SysFS { /// /// ## 参数 /// - /// - `kobj`: 要创建符号链接的kobject - /// - `target`: 符号链接的目标(在目标目录下创建) + /// - `kobj`: object whose directory we're creating the link in. (符号链接所在目录) + /// 如果为None,则创建在sysfs的根目录下 + /// - `target`: object we're pointing to. /// - `name`: 符号链接的名称 /// /// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89 pub fn create_link( &self, - _kobj: &Arc, - _target: &Arc, - _name: String, + kobj: Option<&Arc>, + target: &Arc, + name: String, ) -> Result<(), SystemError> { - todo!("sysfs create link") + return self.do_create_link(kobj, target, name, true); } /// 在sysfs中删除一个符号链接 @@ -32,7 +39,67 @@ impl SysFS { /// /// /// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143 - pub fn remove_link(&self, _kobj: &Arc, _name: String) -> Result<(), SystemError> { + pub fn remove_link(&self, _kobj: &Arc, _name: String) { todo!("sysfs remove link") } + + fn do_create_link( + &self, + kobj: Option<&Arc>, + target: &Arc, + name: String, + warn: bool, + ) -> Result<(), SystemError> { + let parent = if let Some(kobj) = kobj { + kobj.inode() + } else { + Some(self.root_inode().clone()) + }; + + // 没有parent,返回错误 + let parent = parent.ok_or(SystemError::EFAULT)?; + return self.do_create_link_sd(&parent, target, name, warn); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#20 + fn do_create_link_sd( + &self, + inode: &Arc, + target: &Arc, + name: String, + warn: bool, + ) -> Result<(), SystemError> { + let target_inode = target.inode().ok_or(SystemError::ENOENT)?; + + let target_abs_path = "/sys".to_string() + &self.kernfs_path(&target_inode).to_owned(); + // let current_path = self.kernfs_path(inode); + // kdebug!("sysfs: create link {} to {}", current_path, target_abs_path); + + let kn = inode.add_link(name.clone(), &target_inode, target_abs_path); + if kn.is_ok() { + return Ok(()); + } + let err = kn.unwrap_err(); + if warn && err == SystemError::EEXIST { + self.warn_duplicate(inode, &name); + } + return Err(err); + } + + /// sysfs_create_link_sd - create symlink to a given object. + /// + /// ## 参数 + /// + /// - `inode`: 目录inode,在这个目录下创建符号链接 + /// - `target`: object we're pointing to. + /// - `name`: 符号链接的名称 + #[allow(dead_code)] + pub(super) fn create_link_sd( + &self, + inode: &Arc, + target: &Arc, + name: String, + ) -> Result<(), SystemError> { + return self.do_create_link_sd(inode, target, name, true); + } } diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index a3638f42..f01d69b8 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -78,6 +78,9 @@ pub const DT_SOCK: u16 = 12; pub const DT_WHT: u16 = 14; pub const DT_MAX: u16 = 16; +/// vfs容许的最大的符号链接跳转次数 +pub const VFS_MAX_FOLLOW_SYMLINK_TIMES: usize = 8; + impl FileType { pub fn get_file_type_num(&self) -> u16 { return match self { diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 55784bda..bdcd6611 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -23,7 +23,7 @@ use super::{ fcntl::{FcntlCommand, FD_CLOEXEC}, file::{File, FileMode}, utils::rsplit_path, - Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, + Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, }; pub const SEEK_SET: u32 = 0; @@ -156,7 +156,8 @@ impl Syscall { return Err(SystemError::ENAMETOOLONG); } - let inode: Result, SystemError> = ROOT_INODE().lookup(path); + let inode: Result, SystemError> = + ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); let inode: Arc = if inode.is_err() { let errno = inode.unwrap_err(); @@ -344,13 +345,14 @@ impl Syscall { new_path = String::from("/"); } } - let inode = match ROOT_INODE().lookup(&new_path) { - Err(e) => { - kerror!("Change Directory Failed, Error = {:?}", e); - return Err(SystemError::ENOENT); - } - Ok(i) => i, - }; + let inode = + match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) { + Err(e) => { + kerror!("Change Directory Failed, Error = {:?}", e); + return Err(SystemError::ENOENT); + } + Ok(i) => i, + }; let metadata = inode.metadata()?; if metadata.file_type == FileType::Dir { proc.basic_mut().set_cwd(String::from(new_path)); @@ -730,7 +732,8 @@ impl Syscall { return Err(SystemError::ENAMETOOLONG); } - let inode: Result, SystemError> = ROOT_INODE().lookup(path); + let inode: Result, SystemError> = + ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); if inode.is_ok() { return Err(SystemError::EEXIST); @@ -739,7 +742,8 @@ impl Syscall { let (filename, parent_path) = rsplit_path(path); // 查找父目录 - let parent_inode: Arc = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; + let parent_inode: Arc = ROOT_INODE() + .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; // 创建nod parent_inode.mknod(filename, mode, dev_t)?; diff --git a/kernel/src/init/c_adapter.rs b/kernel/src/init/c_adapter.rs index ec125f67..376477a7 100644 --- a/kernel/src/init/c_adapter.rs +++ b/kernel/src/init/c_adapter.rs @@ -1,6 +1,11 @@ -use super::init_intertrait; +use super::{init_before_mem_init, init_intertrait}; #[no_mangle] unsafe extern "C" fn rs_init_intertrait() { init_intertrait(); } + +#[no_mangle] +unsafe extern "C" fn rs_init_before_mem_init() { + init_before_mem_init(); +} diff --git a/kernel/src/init/mod.rs b/kernel/src/init/mod.rs index fc08b638..767ff185 100644 --- a/kernel/src/init/mod.rs +++ b/kernel/src/init/mod.rs @@ -1,5 +1,17 @@ +use crate::{ + driver::{tty::init::tty_early_init, video::VideoRefreshManager}, + libs::lib_ui::screen_manager::scm_init, +}; + pub mod c_adapter; fn init_intertrait() { intertrait::init_caster_map(); } + +/// 在内存管理初始化之前,执行的初始化 +fn init_before_mem_init() { + tty_early_init().expect("tty early init failed"); + unsafe { VideoRefreshManager::video_init().ok() }; + scm_init(); +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index a515d31f..5f2caac8 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -5,6 +5,7 @@ #![feature(asm_const)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] +#![feature(const_refs_to_cell)] #![feature(core_intrinsics)] #![feature(c_void_variant)] #![feature(drain_filter)] diff --git a/kernel/src/libs/ida/Cargo.toml b/kernel/src/libs/ida/Cargo.toml new file mode 100644 index 00000000..9c69cd2e --- /dev/null +++ b/kernel/src/libs/ida/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ida" +version = "0.1.0" +edition = "2021" +authors = ["longjin "] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/kernel/src/libs/ida/src/lib.rs b/kernel/src/libs/ida/src/lib.rs new file mode 100644 index 00000000..c6697fa6 --- /dev/null +++ b/kernel/src/libs/ida/src/lib.rs @@ -0,0 +1,50 @@ +#![no_std] +#![feature(core_intrinsics)] + +use core::intrinsics::unlikely; +use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + +/// id分配器 +/// +/// TODO: 当前只是为了简单实现功能,将来这里应使用类似linux的ida的方式去实现 +#[derive(Debug)] +pub struct IdAllocator { + current_id: AtomicUsize, + max_id: usize, + dead: AtomicBool, +} + +impl IdAllocator { + /// 创建一个新的id分配器 + pub const fn new(max_id: usize) -> Self { + Self { + current_id: AtomicUsize::new(0), + max_id, + dead: AtomicBool::new(false), + } + } + + /// 分配一个新的id + /// + /// ## 返回 + /// + /// 如果分配成功,返回Some(id),否则返回None + pub fn alloc(&self) -> Option { + if unlikely(self.dead.load(Ordering::SeqCst)) { + return None; + } + + let ret = self.current_id.fetch_add(1, Ordering::SeqCst); + // 如果id溢出,panic + if ret == self.max_id { + self.dead.store(true, Ordering::SeqCst); + return None; + } + + return Some(ret); + } + + pub fn free(&self, _id: usize) { + // todo: free + } +} diff --git a/kernel/src/libs/int_like.rs b/kernel/src/libs/int_like.rs index 37628101..c7e903df 100644 --- a/kernel/src/libs/int_like.rs +++ b/kernel/src/libs/int_like.rs @@ -44,6 +44,11 @@ macro_rules! int_like { pub const fn new(x: $backing_type) -> Self { Self::from(x) } + + #[allow(dead_code)] + pub const fn data(&self) -> $backing_type { + self.0 + } } }; diff --git a/kernel/src/libs/lib_ui/screen_manager.h b/kernel/src/libs/lib_ui/screen_manager.h index 22ff60ed..8693e8c7 100644 --- a/kernel/src/libs/lib_ui/screen_manager.h +++ b/kernel/src/libs/lib_ui/screen_manager.h @@ -1,11 +1,5 @@ #pragma once -/** - * @brief 初始化屏幕管理模块 - * - */ -extern void scm_init(); - /** * @brief 当内存管理单元被初始化之后,重新处理帧缓冲区问题 * diff --git a/kernel/src/libs/lib_ui/screen_manager.rs b/kernel/src/libs/lib_ui/screen_manager.rs index 4b9f4567..bfb18f90 100644 --- a/kernel/src/libs/lib_ui/screen_manager.rs +++ b/kernel/src/libs/lib_ui/screen_manager.rs @@ -8,8 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc}; use crate::{ driver::{ - uart::uart_device::{c_uart_send_str, UartPort}, - video::video_refresh_manager, + tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager, }, libs::{rwlock::RwLock, spinlock::SpinLock}, mm::VirtAddr, @@ -275,13 +274,12 @@ pub trait ScmUiFramework: Sync + Send + Debug { /// ## 调用时机 /// /// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。 -#[no_mangle] -pub extern "C" fn scm_init() { +pub fn scm_init() { SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲 textui_init_no_alloc(); - c_uart_send_str(UartPort::COM1.to_u16(), "\nfinish_scm_init\n\0".as_ptr()); + send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes()); } /// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上 @@ -381,10 +379,7 @@ pub fn scm_enable_put_to_window() { .enable() .unwrap_or_else(|e| e.to_posix_errno()); if r.is_negative() { - c_uart_send_str( - UartPort::COM1.to_u16(), - "scm_enable_put_to_window() failed.\n\0".as_ptr(), - ); + send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes()); } } } @@ -402,10 +397,7 @@ pub fn scm_disable_put_to_window() { .disable() .unwrap_or_else(|e| e.to_posix_errno()); if r.is_negative() { - c_uart_send_str( - UartPort::COM1.to_u16(), - "scm_disable_put_to_window() failed.\n\0".as_ptr(), - ); + send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes()); } } } @@ -414,7 +406,7 @@ pub fn scm_disable_put_to_window() { pub extern "C" fn scm_reinit() -> i32 { let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno()); if r.is_negative() { - c_uart_send_str(UartPort::COM1.to_u16(), "scm reinit failed.\n\0".as_ptr()); + send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes()); } return r; } diff --git a/kernel/src/libs/lib_ui/textui.rs b/kernel/src/libs/lib_ui/textui.rs index 2d95985b..9b65f3e6 100644 --- a/kernel/src/libs/lib_ui/textui.rs +++ b/kernel/src/libs/lib_ui/textui.rs @@ -1,7 +1,6 @@ use crate::{ driver::{ - uart::uart_device::{c_uart_send, c_uart_send_str, UartPort}, - video::video_refresh_manager, + tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager, }, kdebug, kinfo, libs::{ @@ -86,10 +85,7 @@ pub unsafe fn textui_framwork_init() { scm_register(textui_framework()).expect("register textui framework failed"); kdebug!("textui framework init success"); - c_uart_send_str( - UartPort::COM1.to_u16(), - "\ntext ui initialized\n\0".as_ptr(), - ); + send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes()); unsafe { TEXTUI_IS_INIT = true }; } else { panic!("Try to init TEXTUI_FRAMEWORK twice!"); @@ -756,7 +752,7 @@ impl TextuiWindow { //进行换行操作 if character == '\n' { // 换行时还需要输出\r - c_uart_send(UartPort::COM1.to_u16(), b'\r'); + send_to_default_serial8250_port(&[b'\r']); if is_enable_window == true { self.textui_new_line()?; } @@ -837,7 +833,7 @@ impl TextuiWindow { } else { // 输出其他字符 - c_uart_send(UartPort::COM1.to_u16(), character as u8); + send_to_default_serial8250_port(&[character as u8]); if is_enable_window == true { if let TextuiVline::Chromatic(vline) = @@ -902,10 +898,7 @@ impl TextUiFramework { impl ScmUiFramework for TextUiFramework { // 安装ui框架的回调函数 fn install(&self) -> Result { - c_uart_send_str( - UartPort::COM1.to_u16(), - "\ntextui_install_handler\n\0".as_ptr(), - ); + send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes()); return Ok(0); } // 卸载ui框架的回调函数 @@ -1015,7 +1008,7 @@ pub fn textui_putchar( pub extern "C" fn rs_textui_init() -> i32 { let r = textui_init().unwrap_or_else(|e| e.to_posix_errno()); if r.is_negative() { - c_uart_send_str(UartPort::COM1.to_u16(), "textui init failed.\n\0".as_ptr()); + send_to_default_serial8250_port("textui init failed.\n\0".as_bytes()); } return r; } diff --git a/kernel/src/libs/lib_ui/textui_no_alloc.rs b/kernel/src/libs/lib_ui/textui_no_alloc.rs index 8e0fa467..2c0c332f 100644 --- a/kernel/src/libs/lib_ui/textui_no_alloc.rs +++ b/kernel/src/libs/lib_ui/textui_no_alloc.rs @@ -5,8 +5,7 @@ use core::{ use crate::{ driver::{ - uart::uart_device::{c_uart_send, UartPort}, - video::video_refresh_manager, + tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager, }, syscall::SystemError, }; @@ -43,13 +42,12 @@ pub fn no_init_textui_putchar_window( if unlikely(character == '\0') { return Ok(()); } - - c_uart_send(UartPort::COM1.to_u16(), character as u8); + send_to_default_serial8250_port(&[character as u8]); // 进行换行操作 if unlikely(character == '\n') { // 换行时还需要输出\r - c_uart_send(UartPort::COM1.to_u16(), b'\r'); + send_to_default_serial8250_port(&[b'\r']); if is_put_to_window == true { NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst); NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst); diff --git a/kernel/src/libs/wait_queue.rs b/kernel/src/libs/wait_queue.rs index 2bb3093a..71376f8f 100644 --- a/kernel/src/libs/wait_queue.rs +++ b/kernel/src/libs/wait_queue.rs @@ -201,16 +201,25 @@ impl WaitQueue { let mut to_push_back: Vec> = Vec::new(); // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 while let Some(to_wakeup) = guard.wait_list.pop_front() { + let mut wake = false; if let Some(state) = state { if to_wakeup.sched_info().state() == state { - ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| { - kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e); - }); - continue; + wake = true; } + } else { + wake = true; + } + + if wake { + ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| { + kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e); + }); + continue; + } else { + to_push_back.push(to_wakeup); } - to_push_back.push(to_wakeup); } + for to_wakeup in to_push_back { guard.wait_list.push_back(to_wakeup); } diff --git a/kernel/src/main.c b/kernel/src/main.c index cce8bca4..44646567 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -27,18 +27,16 @@ #include "driver/mouse/ps2_mouse.h" #include "driver/multiboot2/multiboot2.h" #include -#include #include