Skip to content

Commit

Permalink
feat(driver/pci): add pci bus into sysfs (#792)
Browse files Browse the repository at this point in the history
把pci设备加入sysfs
  • Loading branch information
ZZJJWarth authored May 13, 2024
1 parent 1df85da commit 1f4877a
Show file tree
Hide file tree
Showing 12 changed files with 1,429 additions and 3 deletions.
3 changes: 2 additions & 1 deletion kernel/src/driver/base/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() }
}

Expand Down Expand Up @@ -287,6 +287,7 @@ pub enum DeviceType {
Intc,
PlatformDev,
Char,
Pci,
}

/// @brief: 设备标识符类型
Expand Down
159 changes: 159 additions & 0 deletions kernel/src/driver/pci/attr.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 109 additions & 0 deletions kernel/src/driver/pci/dev_id.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Loading

0 comments on commit 1f4877a

Please sign in to comment.