diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 2281d124c..3208936a5 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -75,7 +75,7 @@ static mut DEVICES_VIRTUAL_KSET_INSTANCE: Option> = None; /// 获取`/sys/devices`的kset实例 #[inline(always)] -pub(super) fn sys_devices_kset() -> Arc { +pub fn sys_devices_kset() -> Arc { unsafe { DEVICES_KSET_INSTANCE.as_ref().unwrap().clone() } } @@ -287,6 +287,7 @@ pub enum DeviceType { Intc, PlatformDev, Char, + Pci, } /// @brief: 设备标识符类型 diff --git a/kernel/src/driver/pci/attr.rs b/kernel/src/driver/pci/attr.rs new file mode 100644 index 000000000..ae22e3746 --- /dev/null +++ b/kernel/src/driver/pci/attr.rs @@ -0,0 +1,159 @@ +use alloc::sync::Arc; +use intertrait::cast::CastArc; +use system_error::SystemError; + +use crate::{ + driver::base::kobject::KObject, + filesystem::{ + sysfs::{ + file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO, + }, + vfs::syscall::ModeType, + }, +}; + +use super::device::PciDevice; +#[derive(Debug)] +pub struct BasicPciReadOnlyAttrs; + +impl AttributeGroup for BasicPciReadOnlyAttrs { + fn name(&self) -> Option<&str> { + None + } + + fn attrs(&self) -> &[&'static dyn Attribute] { + &[&Vendor, &DeviceID, &SubsystemVendor, &SubsystemDevice] + } + + fn is_visible( + &self, + _kobj: Arc, + attr: &'static dyn Attribute, + ) -> Option { + return Some(attr.mode()); + } +} + +#[derive(Debug)] +pub struct Vendor; + +impl Attribute for Vendor { + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn name(&self) -> &str { + "vendor" + } + + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + let dev = _kobj + .cast::() + .map_err(|e: Arc| { + kwarn!("device:{:?} is not a pci device!", e); + SystemError::EINVAL + })?; + return sysfs_emit_str(_buf, &format!("0x{:04x}", dev.vendor())); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } +} + +#[derive(Debug)] +pub struct DeviceID; + +impl Attribute for DeviceID { + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn name(&self) -> &str { + "device" + } + + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + let dev = _kobj + .cast::() + .map_err(|e: Arc| { + kwarn!("device:{:?} is not a pci device!", e); + SystemError::EINVAL + })?; + return sysfs_emit_str(_buf, &format!("0x{:04x}", dev.device_id())); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } +} + +#[derive(Debug)] +pub struct SubsystemVendor; + +impl Attribute for SubsystemVendor { + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn name(&self) -> &str { + "subsystem_vendor" + } + + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + let dev = _kobj + .cast::() + .map_err(|e: Arc| { + kwarn!("device:{:?} is not a pci device!", e); + SystemError::EINVAL + })?; + return sysfs_emit_str(_buf, &format!("0x{:04x}", dev.subsystem_vendor())); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } +} + +#[derive(Debug)] +pub struct SubsystemDevice; + +impl Attribute for SubsystemDevice { + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn name(&self) -> &str { + "subsystem_device" + } + + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + let dev = _kobj + .cast::() + .map_err(|e: Arc| { + kwarn!("device:{:?} is not a pci device!", e); + SystemError::EINVAL + })?; + return sysfs_emit_str(_buf, &format!("0x{:04x}", dev.subsystem_device())); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } +} diff --git a/kernel/src/driver/pci/dev_id.rs b/kernel/src/driver/pci/dev_id.rs new file mode 100644 index 000000000..f79904179 --- /dev/null +++ b/kernel/src/driver/pci/dev_id.rs @@ -0,0 +1,109 @@ +use alloc::sync::Arc; + +use super::device::PciDevice; +const PCI_ANY_ID: u32 = 0xffff_ffff; + +/// # 结构功能 +/// 该结构用于驱动和设备之间的识别,驱动会有一个支持的设备ID列表,而设备会自带一个ID,如果设备的ID在驱动的支持列表中,则驱动和设备就可以识别了 +/// 见https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/mod_devicetable.h#43 +#[derive(Debug, Copy, Clone)] +pub struct PciDeviceID { + vendor: u32, + device_id: u32, + subvendor: u32, + subdevice: u32, + class: u32, + class_mask: u32, + _driver_data: u64, + _override_only: u32, + /// 可能有些设备的识别方式比较特殊,那么可以通过设置该字段进行自定义的识别方式,只需要在PciSpecifiedData枚举中加入一个类型即可 + /// 若该字段不为None,则优先使用special_data进行识别; + /// 该字段是为了增加灵活性 + special_data: Option, +} + +impl PciDeviceID { + #[allow(dead_code)] + pub fn set_special(&mut self, data: PciSpecifiedData) { + self.special_data = Some(data); + } + + pub fn dummpy() -> Self { + return Self { + vendor: PCI_ANY_ID, + device_id: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + class: PCI_ANY_ID, + class_mask: PCI_ANY_ID, + _driver_data: 0, + _override_only: PCI_ANY_ID, + special_data: None, + }; + } + pub fn match_dev(&self, dev: &Arc) -> bool { + if let Some(d_data) = &dev.dynid().special_data { + return d_data.match_dev(self.special_data); + } + if let Some(s_data) = &self.special_data { + return s_data.match_dev(dev.dynid().special_data); + } else { + let d_id = dev.dynid(); + return self.general_match(d_id); + } + } + + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/pci/pci.h?fi=pci_match_one_device#195 + pub fn general_match(&self, id: PciDeviceID) -> bool { + if (self.vendor == id.vendor() || self.vendor == PCI_ANY_ID) + && (self.device_id == id.device_id() || self.device_id == PCI_ANY_ID) + && (self.subvendor == id.subvendor() || self.subvendor == PCI_ANY_ID) + && (self.subdevice == id.subdevice() || self.subdevice == PCI_ANY_ID) + && self.class_check(&id) + { + return true; + } + return false; + } + + pub fn class_check(&self, id: &Self) -> bool { + return (self.class ^ id.class()) & self.class_mask == 0; + } + + pub fn vendor(&self) -> u32 { + self.vendor + } + + pub fn device_id(&self) -> u32 { + self.device_id + } + + pub fn subvendor(&self) -> u32 { + self.subvendor + } + + pub fn subdevice(&self) -> u32 { + self.subdevice + } + + pub fn class(&self) -> u32 { + self.class + } + + pub fn _class_mask(&self) -> u32 { + self.class_mask + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)] +pub enum PciSpecifiedData {} + +impl PciSpecifiedData { + pub fn match_dev(&self, data: Option) -> bool { + if let Some(data) = data { + return *self == data; + } else { + return false; + } + } +} diff --git a/kernel/src/driver/pci/device.rs b/kernel/src/driver/pci/device.rs new file mode 100644 index 000000000..2d139f52a --- /dev/null +++ b/kernel/src/driver/pci/device.rs @@ -0,0 +1,219 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use system_error::SystemError; + +use crate::{ + driver::base::{ + device::{ + bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + filesystem::kernfs::KernFSInode, + libs::{rwlock::RwLockWriteGuard, spinlock::SpinLock}, +}; + +use super::{ + dev_id::PciDeviceID, + subsys::{pci_bus, pci_bus_device}, +}; + +/// # 结构功能 +/// 该结构为Pci设备的管理器,使用该结构可以将pci设备添加到sysfs中 +pub struct PciDeviceManager; + +pub fn pci_device_manager() -> &'static PciDeviceManager { + &PciDeviceManager +} + +impl PciDeviceManager { + /// #函数的功能 + /// 将pci设备注册到sysfs中 + /// + /// ## 参数: + /// - 'pci_dev':需要添加的pci设备 + /// + /// ## 返回值: + /// - OK(()) :表示成功 + /// - Err(e) :失败原因 + pub fn device_add(&self, pci_dev: Arc) -> Result<(), SystemError> { + // pci设备一般放置在/sys/device/pci:xxxx下 + if pci_dev.parent().is_none() { + pci_dev.set_parent(Some(Arc::downgrade( + &(pci_bus_device() as Arc), + ))); + } + // 设置设备的总线 + pci_dev.set_bus(Some(Arc::downgrade(&(pci_bus() as Arc)))); + // 对设备进行默认的初始化 + device_manager().device_default_initialize(&(pci_dev.clone() as Arc)); + // 使用设备管理器注册设备,当设备被注册后,会根据它的总线字段,在对应的总线上扫描驱动,并尝试进行匹配 + let r = device_manager().add_device(pci_dev.clone() as Arc); + + if r.is_ok() { + //todo:这里可能还要处理一些设置成功后设备状态的变化 + return Ok(()); + } else { + //todo:这里可能有一些添加失败的处理 + return r; + } + } +} + +/// #trait功能 +/// 要进入sysfs的Pci设备应当实现的trait +pub trait PciDevice: Device { + /// # 函数的功能 + /// 返回本设备的PciDeviceID,该ID用于driver和device之间的匹配 + /// + /// ## 返回值 + /// - 'PciDeviceID' :本设备的PciDeviceID + fn dynid(&self) -> PciDeviceID; + + /// # 函数的功能 + /// 返回本设备的供应商(vendor)ID + /// + /// ## 返回值 + /// - u16 :表示供应商ID + fn vendor(&self) -> u16; + fn device_id(&self) -> u16; + fn subsystem_vendor(&self) -> u16; + fn subsystem_device(&self) -> u16; +} + +/// #结构功能 +/// 由于Pci总线本身就属于一个设备,故该结构代表Pci总线(控制器)本身 +/// 它对应/sys/device/pci +#[derive(Debug)] +#[cast_to([sync] Device)] +pub struct PciBusDevice { + // inner: SpinLock, + device_data: SpinLock, + kobj_data: SpinLock, + kobj_state: LockedKObjectState, + name: String, +} + +impl PciBusDevice { + pub fn new(parent: Option>) -> Arc { + let common_device = DeviceCommonData::default(); + let common_kobj = KObjectCommonData::default(); + let bus_device = Self { + device_data: SpinLock::new(common_device), + kobj_data: SpinLock::new(common_kobj), + kobj_state: LockedKObjectState::new(None), + name: "pci".to_string(), + }; + bus_device.set_parent(parent); + return Arc::new(bus_device); + } +} + +impl KObject for PciBusDevice { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn parent(&self) -> Option> { + self.kobj_data.lock().parent.clone() + } + + fn inode(&self) -> Option> { + self.kobj_data.lock().kern_inode.clone() + } + + fn set_inode(&self, inode: Option>) { + self.kobj_data.lock().kern_inode = inode; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.kobj_data.lock().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.kobj_data.lock().kobj_type = ktype + } + + fn kset(&self) -> Option> { + self.kobj_data.lock().kset.clone() + } + + fn kobj_state( + &self, + ) -> crate::libs::rwlock::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; + } + + fn name(&self) -> String { + self.name.clone() + } + + fn set_name(&self, _name: String) { + //do nothing; it's not supposed to change this struct's name + } + + fn set_kset(&self, kset: Option>) { + self.kobj_data.lock().kset = kset; + } + + fn set_parent(&self, parent: Option>) { + self.kobj_data.lock().parent = parent; + } +} + +impl Device for PciBusDevice { + fn dev_type(&self) -> DeviceType { + return DeviceType::Bus; + } + + fn id_table(&self) -> IdTable { + IdTable::new("pci".to_string(), None) + } + + fn bus(&self) -> Option> { + self.device_data.lock().bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.device_data.lock().bus = bus + } + + fn driver(&self) -> Option> { + self.device_data.lock().driver.clone()?.upgrade() + } + + fn is_dead(&self) -> bool { + false + } + + fn set_driver(&self, driver: Option>) { + self.device_data.lock().driver = driver; + } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn set_class(&self, _class: Option>) { + todo!() + } + + fn state_synced(&self) -> bool { + todo!() + } +} diff --git a/kernel/src/driver/pci/driver.rs b/kernel/src/driver/pci/driver.rs new file mode 100644 index 000000000..27d7b91a8 --- /dev/null +++ b/kernel/src/driver/pci/driver.rs @@ -0,0 +1,83 @@ +use alloc::{sync::Arc, vec::Vec}; +use system_error::SystemError; + +use crate::driver::base::device::{ + bus::Bus, + driver::{driver_manager, Driver}, +}; + +use super::{dev_id::PciDeviceID, device::PciDevice, subsys::pci_bus}; + +/// # trait功能 +/// Pci驱动应该实现的trait +/// +/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/pci.h#907 +pub trait PciDriver: Driver { + /// # 函数的功能 + /// 对设备进行probe操作 + /// + /// ## 参数: + /// - 'device' :要进行probe的设备 + /// - 'id' :设备的ID(暂时不清楚为什么需要这个,依Linux实现是有ID的) + /// + /// ## 返回值: + /// - Ok:probe成功 + /// - Err:probe失败 + fn probe(&self, device: &Arc, id: &PciDeviceID) -> 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>; + /// # 函数的功能 + /// 向驱动中加入一个PciDeviceID,表示该驱动可以支持该ID的设备 + /// + /// ## 参数: + /// - 'id' :要添加的ID + /// + /// ## 返回值: + /// - 'Ok':添加成功 + /// - 'Err':添加失败 + fn add_dynid(&mut self, id: PciDeviceID) -> Result<(), SystemError>; + /// # 函数的功能 + /// 每个Pci驱动都应该持有一个支持ID的列表,并通过该函数进行访问 + /// + /// ## 返回值: + /// - 'Some(Vec)': 支持ID的列表 + /// - 'None':未能获取列表 + fn locked_dynid_list(&self) -> Option>>; + /// # 函数的功能 + /// 检测当前驱动是否支持目标设备 + /// + /// ## 参数: + /// - 'dev' :要检测的设备 + /// + /// ## 返回值: + /// - 'Some(Arc)': 如果支持,则返回支持的ID + /// - 'None': 不支持的设备 + fn match_dev(&self, dev: &Arc) -> Option> { + for i in self.locked_dynid_list()?.iter() { + if i.match_dev(dev) { + return Some(i.clone()); + } + } + return None; + } +} + +pub struct PciDriverManager; + +pub fn pci_driver_manager() -> &'static PciDriverManager { + &PciDriverManager +} + +impl PciDriverManager { + pub fn register(&self, driver: Arc) -> Result<(), SystemError> { + driver.set_bus(Some(Arc::downgrade(&(pci_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/pci/mod.rs b/kernel/src/driver/pci/mod.rs index 9973b1225..d443a4123 100644 --- a/kernel/src/driver/pci/mod.rs +++ b/kernel/src/driver/pci/mod.rs @@ -1,5 +1,12 @@ +pub mod attr; +pub mod dev_id; +pub mod device; +pub mod driver; pub mod ecam; #[allow(clippy::module_inception)] pub mod pci; pub mod pci_irq; +pub mod raw_device; pub mod root; +pub mod subsys; +pub mod test; diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 0f37e59ec..12168e207 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -1,9 +1,13 @@ #![allow(dead_code)] // 目前仅支持单主桥单Segment +use super::device::pci_device_manager; use super::pci_irq::{IrqType, PciIrqError}; +use super::raw_device::PciGeneralDevice; use super::root::{pci_root_0, PciRoot}; + use crate::arch::{PciArch, TraitPciArch}; +use crate::driver::pci::subsys::pci_bus_subsys_init; use crate::exception::IrqNumber; use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -11,6 +15,7 @@ use crate::mm::mmio_buddy::{mmio_pool, MMIOSpaceGuard}; use crate::mm::VirtAddr; use crate::{kdebug, kerror, kinfo, kwarn}; +use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; use alloc::{boxed::Box, collections::LinkedList}; @@ -716,11 +721,18 @@ fn pci_read_header( }; match HeaderType::from(header_type & 0x7f) { HeaderType::Standard => { - let general_device = pci_read_general_device_header(header, &bus_device_function); - let box_general_device = Box::new(general_device); + let general_device: PciDeviceStructureGeneralDevice = + pci_read_general_device_header(header, &bus_device_function); + let box_general_device = Box::new(general_device.clone()); let box_general_device_clone = box_general_device.clone(); if add_to_list { PCI_DEVICE_LINKEDLIST.add(box_general_device); + //这里实际上不应该使用clone,因为raw是用于sysfs的结构,但是实际上pci设备是在PCI_DEVICE_LINKEDLIST链表上的, + //这就导致sysfs呈现的对pci设备的操控接口实际上操控的是pci设备描述符是一个副本 + //但是无奈这里没有使用Arc + //todo:修改pci设备描述符在静态链表中存在的方式,并修改这里的clone操作 + let raw = PciGeneralDevice::from(&general_device); + let _ = pci_device_manager().device_add(Arc::new(raw)); } Ok(box_general_device_clone) } @@ -1045,6 +1057,7 @@ fn pci_check_bus(bus: u8) -> Result { #[inline(never)] pub fn pci_init() { kinfo!("Initializing PCI bus..."); + pci_bus_subsys_init().expect("Failed to init pci bus subsystem"); if let Err(e) = pci_check_all_buses() { kerror!("pci init failed when checking bus because of error: {}", e); return; @@ -1090,6 +1103,7 @@ pub fn pci_init() { HeaderType::Unrecognised(_) => {} } } + kinfo!("PCI bus initialized."); } @@ -1114,6 +1128,19 @@ impl BusDeviceFunction { self.device < 32 && self.function < 8 } } + +impl From for String { + /// # 函数的功能 + /// 这里提供一个由BusDeviceFunction到dddd:bb:vv.f字符串的转换函数,主要用于转换成设备的名称(pci设备的名称一般是诸如0000:00:00.1这种) + fn from(value: BusDeviceFunction) -> Self { + //需要注意,这里的0000应该是所谓的“域号”(Domain ID),但是尚不知道是如何获得的,故硬编码在这里 + //todo:实现域号的获取 + format!( + "0000:{:02x}:{:02x}.{}", + value.bus, value.device, value.function + ) + } +} ///实现BusDeviceFunction的Display trait,使其可以直接输出 impl Display for BusDeviceFunction { fn fmt(&self, f: &mut Formatter) -> fmt::Result { diff --git a/kernel/src/driver/pci/raw_device.rs b/kernel/src/driver/pci/raw_device.rs new file mode 100644 index 000000000..c2be0700e --- /dev/null +++ b/kernel/src/driver/pci/raw_device.rs @@ -0,0 +1,194 @@ +use core::any::Any; + +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; + +use crate::{ + driver::base::{ + class::Class, + device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup}, + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; + +use super::{ + attr::BasicPciReadOnlyAttrs, dev_id::PciDeviceID, device::PciDevice, + pci::PciDeviceStructureGeneralDevice, +}; +#[derive(Debug)] +#[cast_to([sync] Device)] +#[cast_to([sync] PciDevice)] +pub struct PciGeneralDevice { + device_data: RwLock, + kobj_data: RwLock, + name: RwLock>, + kobj_state: LockedKObjectState, + dev_id: PciDeviceID, + header: Arc, +} + +impl From<&PciDeviceStructureGeneralDevice> for PciGeneralDevice { + fn from(value: &PciDeviceStructureGeneralDevice) -> Self { + let value = Arc::new(value.clone()); + let name: String = value.common_header.bus_device_function.into(); + let kobj_state = LockedKObjectState::new(None); + let common_dev = RwLock::new(DeviceCommonData::default()); + let common_kobj = RwLock::new(KObjectCommonData::default()); + let dev_id = PciDeviceID::dummpy(); + + // dev_id.set_special(PciSpecifiedData::Virtio()); + let res = Self { + device_data: common_dev, + kobj_data: common_kobj, + kobj_state, + dev_id, + header: value, + name: RwLock::new(None), + }; + res.set_name(name); + res + } +} + +impl PciDevice for PciGeneralDevice { + fn dynid(&self) -> PciDeviceID { + self.dev_id + } + + fn vendor(&self) -> u16 { + self.header.common_header.vendor_id + } + + fn device_id(&self) -> u16 { + self.header.common_header.device_id + } + + fn subsystem_vendor(&self) -> u16 { + self.header.subsystem_vendor_id + } + + fn subsystem_device(&self) -> u16 { + self.header.subsystem_id + } +} + +impl Device for PciGeneralDevice { + fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { + Some(&[&BasicPciReadOnlyAttrs]) + } + + fn bus(&self) -> Option> { + self.device_data.read().bus.clone() + } + + fn class(&self) -> Option> { + let mut guard = self.device_data.write(); + let r = guard.class.clone()?.upgrade(); + if r.is_none() { + guard.class = None; + } + + return r; + } + + fn driver(&self) -> Option> { + self.device_data.read().driver.clone()?.upgrade() + } + + fn dev_type(&self) -> DeviceType { + DeviceType::Pci + } + + fn id_table(&self) -> IdTable { + IdTable::new("testPci".to_string(), None) + } + + fn can_match(&self) -> bool { + true + } + + fn is_dead(&self) -> bool { + false + } + + fn set_bus(&self, bus: Option>) { + self.device_data.write().bus = bus; + } + + fn set_can_match(&self, _can_match: bool) {} + + fn set_class(&self, class: Option>) { + self.device_data.write().class = class; + } + + fn set_driver(&self, driver: Option>) { + self.device_data.write().driver = driver + } + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for PciGeneralDevice { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.kobj_data.write().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.kobj_data.read().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.kobj_data.read().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.kobj_data.write().parent = parent; + } + + fn kset(&self) -> Option> { + self.kobj_data.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.kobj_data.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.kobj_data.read().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.kobj_data.write().kobj_type = ktype; + } + + fn name(&self) -> String { + self.name.read().clone().unwrap() + } + + fn set_name(&self, name: String) { + *self.name.write() = Some(name); + } + + 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; + } +} diff --git a/kernel/src/driver/pci/subsys.rs b/kernel/src/driver/pci/subsys.rs new file mode 100644 index 000000000..4b9aa9a9d --- /dev/null +++ b/kernel/src/driver/pci/subsys.rs @@ -0,0 +1,190 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use intertrait::cast::CastArc; +use system_error::SystemError; + +use crate::{ + driver::base::{ + device::{ + bus::{bus_register, Bus}, + device_register, + driver::Driver, + sys_devices_kset, Device, + }, + kobject::KObject, + subsys::SubSysPrivate, + }, + filesystem::sysfs::AttributeGroup, +}; + +use super::{ + device::{PciBusDevice, PciDevice}, + driver::PciDriver, + test::pt_init, +}; + +static mut PCI_BUS_DEVICE: Option> = None; +static mut PCI_BUS: Option> = None; + +pub(super) fn set_pci_bus_device(device: Arc) { + unsafe { + PCI_BUS_DEVICE = Some(device); + } +} + +pub(super) fn set_pci_bus(bus: Arc) { + unsafe { + PCI_BUS = Some(bus); + } +} + +pub fn pci_bus_device() -> Arc { + unsafe { + return PCI_BUS_DEVICE.clone().unwrap(); + } +} + +pub fn pci_bus() -> Arc { + unsafe { + return PCI_BUS.clone().unwrap(); + } +} + +/// # 结构功能 +/// 该结构为Pci总线,由于总线也属于设备,故设此结构; +/// 此结构对应/sys/bus/pci +#[derive(Debug)] +pub struct PciBus { + private: SubSysPrivate, +} + +impl PciBus { + pub fn new() -> Arc { + let w: Weak = Weak::new(); + let private = SubSysPrivate::new("pci".to_string(), Some(w), None, &[]); + let bus = Arc::new(Self { private }); + bus + } +} + +impl Bus for PciBus { + fn name(&self) -> String { + return "pci".to_string(); + } + + fn dev_name(&self) -> String { + return self.name(); + } + + fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { + return &[&PciDeviceAttrGroup]; + } + + fn subsystem(&self) -> &SubSysPrivate { + return &self.private; + } + + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let drv = device.driver().ok_or(SystemError::EINVAL)?; + let pci_drv = drv.cast::().map_err(|_| { + kerror!( + "PciBus::probe() failed: device.driver() is not a PciDriver. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + let pci_dev = device.clone().cast::().map_err(|_| { + kerror!( + "PciBus::probe() failed: device is not a PciDevice. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + //见https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/pci/pci-driver.c#324 + let id = pci_drv.match_dev(&pci_dev).ok_or(SystemError::EINVAL)?; + pci_drv.probe(&pci_dev, &id) + } + + 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!() + } + + fn match_device( + &self, + device: &Arc, + driver: &Arc, + ) -> Result { + //首先将设备和驱动映射为pci设备和pci驱动 + let pci_driver = driver.clone().cast::().map_err(|_| { + return SystemError::EINVAL; + })?; + let pci_dev = device.clone().cast::().map_err(|_| { + return SystemError::EINVAL; + })?; + //pci_driver需要实现一个match_dev函数,即driver需要识别是否支持给定的pci设备 + //这是主要的match方式 + if pci_driver.match_dev(&pci_dev).is_some() { + return Ok(true); + } + + //todo:这里似乎需要一个driver_override_only的支持,但是目前不清楚driver_override_only 的用途,故暂时参考platform总线的match方法 + //override_only相关代码在 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/pci/pci-driver.c#159 + if let Some(driver_id_table) = driver.id_table() { + if driver_id_table.name().eq(&pci_dev.name()) { + return Ok(true); + } + }; + return Ok(pci_dev.name().eq(&pci_driver.name())); + } +} + +#[derive(Debug)] +pub struct PciDeviceAttrGroup; + +impl AttributeGroup for PciDeviceAttrGroup { + fn name(&self) -> Option<&str> { + return None; + } + + fn attrs(&self) -> &[&'static dyn crate::filesystem::sysfs::Attribute] { + return &[]; + } + + fn is_visible( + &self, + _kobj: Arc, + attr: &'static dyn crate::filesystem::sysfs::Attribute, + ) -> Option { + return Some(attr.mode()); + } +} + +pub(super) fn pci_bus_subsys_init() -> Result<(), SystemError> { + let pci_bus_device: Arc = PciBusDevice::new(Some(Arc::downgrade( + &(sys_devices_kset() as Arc), + ))); + + set_pci_bus_device(pci_bus_device.clone()); + + device_register(pci_bus_device.clone())?; + let pci_bus = PciBus::new(); + + set_pci_bus(pci_bus.clone()); + let r = bus_register(pci_bus.clone() as Arc); + pt_init()?; + return r; +} diff --git a/kernel/src/driver/pci/test/mod.rs b/kernel/src/driver/pci/test/mod.rs new file mode 100644 index 000000000..4f0da79f2 --- /dev/null +++ b/kernel/src/driver/pci/test/mod.rs @@ -0,0 +1,30 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use self::{pt_device::TestDevice, pt_driver::TestDriver}; + +use super::{ + dev_id::PciDeviceID, + device::pci_device_manager, + driver::{pci_driver_manager, PciDriver}, +}; + +pub mod pt_device; +pub mod pt_driver; + +static mut TEST_DRIVER: Option> = None; +static mut TEST_DEVICE: Option> = None; +pub fn pt_init() -> Result<(), SystemError> { + let tdev = Arc::new(TestDevice::new()); + let mut drv = TestDriver::new(); + drv.add_dynid(PciDeviceID::dummpy())?; + let tdrv = Arc::new(drv); + + let _ = pci_device_manager().device_add(tdev.clone()); + let _ = pci_driver_manager().register(tdrv.clone()); + unsafe { + TEST_DEVICE = Some(tdev); + TEST_DRIVER = Some(tdrv); + } + Ok(()) +} diff --git a/kernel/src/driver/pci/test/pt_device.rs b/kernel/src/driver/pci/test/pt_device.rs new file mode 100644 index 000000000..65d1a05b0 --- /dev/null +++ b/kernel/src/driver/pci/test/pt_device.rs @@ -0,0 +1,236 @@ +use core::any::Any; + +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use system_error::SystemError; + +use crate::{ + driver::{ + base::{ + class::Class, + device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + pci::{dev_id::PciDeviceID, device::PciDevice}, + }, + filesystem::{ + kernfs::KernFSInode, + sysfs::{ + file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO, + }, + vfs::syscall::ModeType, + }, + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; +#[derive(Debug)] +#[cast_to([sync] Device)] +#[cast_to([sync] PciDevice)] +/// # 结构功能 +/// 这是一个测试用的PciDevice,也可以作为新PciDevice的参考 +/// 它需要实现KObject PciDevice Device这些接口 +/// 并通过函数pci_device_manager().device_add()来将设备进行接入 +pub struct TestDevice { + device_data: RwLock, + kobj_data: RwLock, + kobj_state: LockedKObjectState, +} + +impl TestDevice { + pub fn new() -> Self { + let common_dev = RwLock::new(DeviceCommonData::default()); + let common_kobj = RwLock::new(KObjectCommonData::default()); + Self { + device_data: common_dev, + kobj_data: common_kobj, + kobj_state: LockedKObjectState::new(None), + } + } +} + +impl PciDevice for TestDevice { + fn dynid(&self) -> PciDeviceID { + PciDeviceID::dummpy() + } + + fn vendor(&self) -> u16 { + return 0xffff; + } + + fn device_id(&self) -> u16 { + return 0xffff; + } + + fn subsystem_vendor(&self) -> u16 { + return 0xffff; + } + + fn subsystem_device(&self) -> u16 { + return 0xffff; + } +} + +impl Device for TestDevice { + fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { + Some(&[&HelloAttr]) + } + + fn bus(&self) -> Option> { + self.device_data.read().bus.clone() + } + + fn class(&self) -> Option> { + let mut guard = self.device_data.write(); + let r = guard.class.clone()?.upgrade(); + if r.is_none() { + guard.class = None; + } + + return r; + } + + fn driver(&self) -> Option> { + self.device_data.read().driver.clone()?.upgrade() + } + + fn dev_type(&self) -> DeviceType { + DeviceType::Pci + } + + fn id_table(&self) -> IdTable { + IdTable::new("testPci".to_string(), None) + } + + fn can_match(&self) -> bool { + true + } + + fn is_dead(&self) -> bool { + false + } + + fn set_bus(&self, bus: Option>) { + self.device_data.write().bus = bus + } + + fn set_can_match(&self, _can_match: bool) { + //todo + } + + fn set_class(&self, class: Option>) { + self.device_data.write().class = class + } + + fn set_driver(&self, driver: Option>) { + self.device_data.write().driver = driver + } + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for TestDevice { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.kobj_data.write().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.kobj_data.read().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.kobj_data.read().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.kobj_data.write().parent = parent; + } + + fn kset(&self) -> Option> { + self.kobj_data.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.kobj_data.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.kobj_data.read().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.kobj_data.write().kobj_type = ktype; + } + + fn name(&self) -> String { + "PciTest".to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + 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)] +pub struct HelloAttr; + +impl AttributeGroup for HelloAttr { + fn name(&self) -> Option<&str> { + return Some("TestAttr"); + } + + fn attrs(&self) -> &[&'static dyn Attribute] { + &[&Hello] + } + + fn is_visible( + &self, + _kobj: Arc, + attr: &'static dyn Attribute, + ) -> Option { + return Some(attr.mode()); + } +} +#[derive(Debug)] +pub struct Hello; + +impl Attribute for Hello { + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn name(&self) -> &str { + "Hello" + } + + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + return sysfs_emit_str(_buf, "Hello Pci"); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + todo!() + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } +} diff --git a/kernel/src/driver/pci/test/pt_driver.rs b/kernel/src/driver/pci/test/pt_driver.rs new file mode 100644 index 000000000..65affee28 --- /dev/null +++ b/kernel/src/driver/pci/test/pt_driver.rs @@ -0,0 +1,171 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, + vec::Vec, +}; + +use crate::{ + driver::{ + base::{ + device::{ + bus::Bus, + driver::{Driver, DriverCommonData}, + Device, IdTable, + }, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + pci::{dev_id::PciDeviceID, device::PciDevice, driver::PciDriver}, + }, + filesystem::kernfs::KernFSInode, + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; +#[derive(Debug)] +#[cast_to([sync] PciDriver)] +pub struct TestDriver { + driver_data: RwLock, + kobj_data: RwLock, + kobj_state: LockedKObjectState, + pub locked_dynid_list: RwLock>>, +} + +/// # 结构功能 +/// 本结构体是测试用的驱动,目前暂时保留,否则将出现大量dead code +/// 在编写了实际的pci驱动后,可将该驱动删除 +impl TestDriver { + pub fn new() -> Self { + Self { + driver_data: RwLock::new(DriverCommonData::default()), + kobj_data: RwLock::new(KObjectCommonData::default()), + kobj_state: LockedKObjectState::new(None), + locked_dynid_list: RwLock::new(vec![]), + } + } +} + +impl PciDriver for TestDriver { + fn add_dynid(&mut self, id: PciDeviceID) -> Result<(), system_error::SystemError> { + let id = Arc::new(id); + self.locked_dynid_list.write().push(id); + Ok(()) + } + + fn locked_dynid_list(&self) -> Option>> { + Some(self.locked_dynid_list.read().clone()) + } + + fn probe( + &self, + _device: &Arc, + _id: &PciDeviceID, + ) -> Result<(), system_error::SystemError> { + Ok(()) + } + + fn remove(&self, _device: &Arc) -> Result<(), system_error::SystemError> { + Ok(()) + } + + fn resume(&self, _device: &Arc) -> Result<(), system_error::SystemError> { + Ok(()) + } + + fn shutdown(&self, _device: &Arc) -> Result<(), system_error::SystemError> { + Ok(()) + } + + fn suspend(&self, _device: &Arc) -> Result<(), system_error::SystemError> { + Ok(()) + } +} + +impl Driver for TestDriver { + fn id_table(&self) -> Option { + Some(IdTable::new("PciTestDriver".to_string(), None)) + } + + fn devices(&self) -> Vec> { + self.driver_data.read().devices.clone() + } + + fn add_device(&self, device: Arc) { + let mut guard = self.driver_data.write(); + // check if the device is already in the list + if guard.devices.iter().any(|dev| Arc::ptr_eq(dev, &device)) { + return; + } + + guard.devices.push(device); + } + + fn delete_device(&self, device: &Arc) { + let mut guard = self.driver_data.write(); + guard.devices.retain(|dev| !Arc::ptr_eq(dev, device)); + } + + fn set_bus(&self, bus: Option>) { + self.driver_data.write().bus = bus; + } + + fn bus(&self) -> Option> { + self.driver_data.read().bus.clone() + } +} + +impl KObject for TestDriver { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.kobj_data.write().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.kobj_data.read().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.kobj_data.read().parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.kobj_data.write().parent = parent; + } + + fn kset(&self) -> Option> { + self.kobj_data.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.kobj_data.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.kobj_data.read().kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.kobj_data.write().kobj_type = ktype; + } + + fn name(&self) -> String { + "PciTestDriver".to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + 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; + } +}