feat(driver/pci): add pci bus into sysfs (#792)

把pci设备加入sysfs
This commit is contained in:
曾俊 2024-05-13 15:27:08 +08:00 committed by GitHub
parent 1df85daf8f
commit 1f4877a4c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1429 additions and 3 deletions

View File

@ -75,7 +75,7 @@ static mut DEVICES_VIRTUAL_KSET_INSTANCE: Option<Arc<KSet>> = None;
/// 获取`/sys/devices`的kset实例
#[inline(always)]
pub(super) fn sys_devices_kset() -> Arc<KSet> {
pub fn sys_devices_kset() -> Arc<KSet> {
unsafe { DEVICES_KSET_INSTANCE.as_ref().unwrap().clone() }
}
@ -287,6 +287,7 @@ pub enum DeviceType {
Intc,
PlatformDev,
Char,
Pci,
}
/// @brief: 设备标识符类型

View File

@ -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<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<ModeType> {
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<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = _kobj
.cast::<dyn PciDevice>()
.map_err(|e: Arc<dyn KObject>| {
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<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
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<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = _kobj
.cast::<dyn PciDevice>()
.map_err(|e: Arc<dyn KObject>| {
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<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
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<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = _kobj
.cast::<dyn PciDevice>()
.map_err(|e: Arc<dyn KObject>| {
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<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
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<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = _kobj
.cast::<dyn PciDevice>()
.map_err(|e: Arc<dyn KObject>| {
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<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
todo!()
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
}

View File

@ -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<PciSpecifiedData>,
}
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<dyn PciDevice>) -> 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<Self>) -> bool {
if let Some(data) = data {
return *self == data;
} else {
return false;
}
}
}

View File

@ -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<dyn PciDevice>) -> 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<dyn KObject>),
)));
}
// 设置设备的总线
pci_dev.set_bus(Some(Arc::downgrade(&(pci_bus() as Arc<dyn Bus>))));
// 对设备进行默认的初始化
device_manager().device_default_initialize(&(pci_dev.clone() as Arc<dyn Device>));
// 使用设备管理器注册设备,当设备被注册后,会根据它的总线字段,在对应的总线上扫描驱动,并尝试进行匹配
let r = device_manager().add_device(pci_dev.clone() as Arc<dyn Device>);
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;
/// # 函数的功能
/// 返回本设备的供应商vendorID
///
/// ## 返回值
/// - 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<InnerPciBusDevice>,
device_data: SpinLock<DeviceCommonData>,
kobj_data: SpinLock<KObjectCommonData>,
kobj_state: LockedKObjectState,
name: String,
}
impl PciBusDevice {
pub fn new(parent: Option<Weak<dyn KObject>>) -> Arc<Self> {
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<alloc::sync::Weak<dyn KObject>> {
self.kobj_data.lock().parent.clone()
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.kobj_data.lock().kern_inode.clone()
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
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<Arc<KSet>> {
self.kobj_data.lock().kset.clone()
}
fn kobj_state(
&self,
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
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<Arc<KSet>>) {
self.kobj_data.lock().kset = kset;
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
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<Weak<dyn Bus>> {
self.device_data.lock().bus.clone()
}
fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn Bus>>) {
self.device_data.lock().bus = bus
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
self.device_data.lock().driver.clone()?.upgrade()
}
fn is_dead(&self) -> bool {
false
}
fn set_driver(&self, driver: Option<alloc::sync::Weak<dyn Driver>>) {
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<alloc::sync::Weak<dyn crate::driver::base::class::Class>>) {
todo!()
}
fn state_synced(&self) -> bool {
todo!()
}
}

View File

@ -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<dyn PciDevice>, id: &PciDeviceID) -> Result<(), SystemError>;
fn remove(&self, device: &Arc<dyn PciDevice>) -> Result<(), SystemError>;
fn shutdown(&self, device: &Arc<dyn PciDevice>) -> Result<(), SystemError>;
fn suspend(&self, device: &Arc<dyn PciDevice>) -> Result<(), SystemError>;
fn resume(&self, device: &Arc<dyn PciDevice>) -> 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<Vec<Arc<PciDeviceID>>>;
/// # 函数的功能
/// 检测当前驱动是否支持目标设备
///
/// ## 参数:
/// - 'dev' :要检测的设备
///
/// ## 返回值:
/// - 'Some(Arc<PciDeviceID>)': 如果支持则返回支持的ID
/// - 'None': 不支持的设备
fn match_dev(&self, dev: &Arc<dyn PciDevice>) -> Option<Arc<PciDeviceID>> {
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<dyn PciDriver>) -> Result<(), SystemError> {
driver.set_bus(Some(Arc::downgrade(&(pci_bus() as Arc<dyn Bus>))));
return driver_manager().register(driver as Arc<dyn Driver>);
}
#[allow(dead_code)]
pub fn unregister(&self, driver: &Arc<dyn PciDriver>) {
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
}
}

View File

@ -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;

View File

@ -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<u8, PciError> {
#[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<BusDeviceFunction> 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 {

View File

@ -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<DeviceCommonData>,
kobj_data: RwLock<KObjectCommonData>,
name: RwLock<Option<String>>,
kobj_state: LockedKObjectState,
dev_id: PciDeviceID,
header: Arc<PciDeviceStructureGeneralDevice>,
}
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<Weak<dyn Bus>> {
self.device_data.read().bus.clone()
}
fn class(&self) -> Option<Arc<dyn Class>> {
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<Arc<dyn Driver>> {
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<Weak<dyn Bus>>) {
self.device_data.write().bus = bus;
}
fn set_can_match(&self, _can_match: bool) {}
fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.device_data.write().class = class;
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
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<Arc<KernFSInode>>) {
self.kobj_data.write().kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.kobj_data.read().kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.kobj_data.read().parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.kobj_data.write().parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.kobj_data.read().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
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<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}

View File

@ -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<Arc<PciBusDevice>> = None;
static mut PCI_BUS: Option<Arc<PciBus>> = None;
pub(super) fn set_pci_bus_device(device: Arc<PciBusDevice>) {
unsafe {
PCI_BUS_DEVICE = Some(device);
}
}
pub(super) fn set_pci_bus(bus: Arc<PciBus>) {
unsafe {
PCI_BUS = Some(bus);
}
}
pub fn pci_bus_device() -> Arc<PciBusDevice> {
unsafe {
return PCI_BUS_DEVICE.clone().unwrap();
}
}
pub fn pci_bus() -> Arc<PciBus> {
unsafe {
return PCI_BUS.clone().unwrap();
}
}
/// # 结构功能
/// 该结构为Pci总线由于总线也属于设备故设此结构
/// 此结构对应/sys/bus/pci
#[derive(Debug)]
pub struct PciBus {
private: SubSysPrivate,
}
impl PciBus {
pub fn new() -> Arc<Self> {
let w: Weak<Self> = 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<dyn Device>) -> Result<(), SystemError> {
let drv = device.driver().ok_or(SystemError::EINVAL)?;
let pci_drv = drv.cast::<dyn PciDriver>().map_err(|_| {
kerror!(
"PciBus::probe() failed: device.driver() is not a PciDriver. Device: '{:?}'",
device.name()
);
SystemError::EINVAL
})?;
let pci_dev = device.clone().cast::<dyn PciDevice>().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<dyn Device>) -> Result<(), SystemError> {
todo!()
}
fn sync_state(&self, _device: &Arc<dyn Device>) {
todo!()
}
fn shutdown(&self, _device: &Arc<dyn Device>) {
todo!()
}
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!()
}
fn match_device(
&self,
device: &Arc<dyn Device>,
driver: &Arc<dyn Driver>,
) -> Result<bool, SystemError> {
//首先将设备和驱动映射为pci设备和pci驱动
let pci_driver = driver.clone().cast::<dyn PciDriver>().map_err(|_| {
return SystemError::EINVAL;
})?;
let pci_dev = device.clone().cast::<dyn PciDevice>().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<dyn crate::driver::base::kobject::KObject>,
attr: &'static dyn crate::filesystem::sysfs::Attribute,
) -> Option<crate::filesystem::vfs::syscall::ModeType> {
return Some(attr.mode());
}
}
pub(super) fn pci_bus_subsys_init() -> Result<(), SystemError> {
let pci_bus_device: Arc<PciBusDevice> = PciBusDevice::new(Some(Arc::downgrade(
&(sys_devices_kset() as Arc<dyn KObject>),
)));
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<dyn Bus>);
pt_init()?;
return r;
}

View File

@ -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<Arc<TestDriver>> = None;
static mut TEST_DEVICE: Option<Arc<TestDevice>> = 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(())
}

View File

@ -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<DeviceCommonData>,
kobj_data: RwLock<KObjectCommonData>,
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<Weak<dyn Bus>> {
self.device_data.read().bus.clone()
}
fn class(&self) -> Option<Arc<dyn Class>> {
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<Arc<dyn Driver>> {
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<Weak<dyn Bus>>) {
self.device_data.write().bus = bus
}
fn set_can_match(&self, _can_match: bool) {
//todo
}
fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.device_data.write().class = class
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
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<Arc<KernFSInode>>) {
self.kobj_data.write().kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.kobj_data.read().kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.kobj_data.read().parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.kobj_data.write().parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.kobj_data.read().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
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<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
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<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<ModeType> {
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<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
return sysfs_emit_str(_buf, "Hello Pci");
}
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
todo!()
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
}

View File

@ -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<DriverCommonData>,
kobj_data: RwLock<KObjectCommonData>,
kobj_state: LockedKObjectState,
pub locked_dynid_list: RwLock<Vec<Arc<PciDeviceID>>>,
}
/// # 结构功能
/// 本结构体是测试用的驱动目前暂时保留否则将出现大量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<Vec<Arc<PciDeviceID>>> {
Some(self.locked_dynid_list.read().clone())
}
fn probe(
&self,
_device: &Arc<dyn PciDevice>,
_id: &PciDeviceID,
) -> Result<(), system_error::SystemError> {
Ok(())
}
fn remove(&self, _device: &Arc<dyn PciDevice>) -> Result<(), system_error::SystemError> {
Ok(())
}
fn resume(&self, _device: &Arc<dyn PciDevice>) -> Result<(), system_error::SystemError> {
Ok(())
}
fn shutdown(&self, _device: &Arc<dyn PciDevice>) -> Result<(), system_error::SystemError> {
Ok(())
}
fn suspend(&self, _device: &Arc<dyn PciDevice>) -> Result<(), system_error::SystemError> {
Ok(())
}
}
impl Driver for TestDriver {
fn id_table(&self) -> Option<IdTable> {
Some(IdTable::new("PciTestDriver".to_string(), None))
}
fn devices(&self) -> Vec<Arc<dyn Device>> {
self.driver_data.read().devices.clone()
}
fn add_device(&self, device: Arc<dyn Device>) {
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<dyn Device>) {
let mut guard = self.driver_data.write();
guard.devices.retain(|dev| !Arc::ptr_eq(dev, device));
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.driver_data.write().bus = bus;
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
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<Arc<KernFSInode>>) {
self.kobj_data.write().kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.kobj_data.read().kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.kobj_data.read().parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.kobj_data.write().parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.kobj_data.read().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
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<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}