mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
parent
1df85daf8f
commit
1f4877a4c5
@ -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: 设备标识符类型
|
||||
|
159
kernel/src/driver/pci/attr.rs
Normal file
159
kernel/src/driver/pci/attr.rs
Normal 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
|
||||
}
|
||||
}
|
109
kernel/src/driver/pci/dev_id.rs
Normal file
109
kernel/src/driver/pci/dev_id.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
219
kernel/src/driver/pci/device.rs
Normal file
219
kernel/src/driver/pci/device.rs
Normal 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;
|
||||
|
||||
/// # 函数的功能
|
||||
/// 返回本设备的供应商(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<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!()
|
||||
}
|
||||
}
|
83
kernel/src/driver/pci/driver.rs
Normal file
83
kernel/src/driver/pci/driver.rs
Normal 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>));
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
194
kernel/src/driver/pci/raw_device.rs
Normal file
194
kernel/src/driver/pci/raw_device.rs
Normal 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;
|
||||
}
|
||||
}
|
190
kernel/src/driver/pci/subsys.rs
Normal file
190
kernel/src/driver/pci/subsys.rs
Normal 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;
|
||||
}
|
30
kernel/src/driver/pci/test/mod.rs
Normal file
30
kernel/src/driver/pci/test/mod.rs
Normal 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(())
|
||||
}
|
236
kernel/src/driver/pci/test/pt_device.rs
Normal file
236
kernel/src/driver/pci/test/pt_device.rs
Normal 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
|
||||
}
|
||||
}
|
171
kernel/src/driver/pci/test/pt_driver.rs
Normal file
171
kernel/src/driver/pci/test/pt_driver.rs
Normal 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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user