mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 17:26:31 +00:00
设备驱动模型:完善platform bus相关内容。并注册串口到sysfs (#403)
* 完成初始化platform bus * 删除旧的sysfs * 把uart驱动移动到tty/serial文件夹下 * 完成将串口挂载到sysfs * 修复vfs系统调用未能follow symlink的问题 * 修复shell未能正确获取pwd的问题
This commit is contained in:
@ -74,8 +74,6 @@ pub fn platform_bus_init() -> Result<(), SystemError> {
|
||||
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
||||
DevicePrivateData::new(
|
||||
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
||||
None,
|
||||
CompatibleTable::new(vec!["platform"]),
|
||||
BusState::NotInitialized.into(),
|
||||
),
|
||||
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
||||
|
@ -2,31 +2,64 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use ida::IdAllocator;
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
device::{
|
||||
bus::{Bus, BusState},
|
||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
driver::base::{
|
||||
device::{
|
||||
bus::{Bus, BusState},
|
||||
device_manager,
|
||||
driver::Driver,
|
||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
Driver,
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{super::device::DeviceState, CompatibleTable};
|
||||
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
|
||||
|
||||
/// 平台设备id分配器
|
||||
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(i32::MAX as usize);
|
||||
|
||||
#[inline(always)]
|
||||
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
|
||||
&PlatformDeviceManager
|
||||
}
|
||||
|
||||
/// 没有平台设备id
|
||||
pub const PLATFORM_DEVID_NONE: i32 = -1;
|
||||
/// 请求自动分配这个平台设备id
|
||||
pub const PLATFORM_DEVID_AUTO: i32 = -2;
|
||||
|
||||
/// @brief: 实现该trait的设备实例应挂载在platform总线上,
|
||||
/// 同时应该实现Device trait
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||
pub trait PlatformDevice: Device {
|
||||
fn pdev_name(&self) -> &str;
|
||||
/// 返回平台设备id,以及这个id是否是自动生成的
|
||||
///
|
||||
/// 请注意,如果当前设备还没有id,应该返回
|
||||
/// (PLATFORM_DEVID_NONE, false)
|
||||
fn pdev_id(&self) -> (i32, bool) {
|
||||
(PLATFORM_DEVID_NONE, false)
|
||||
}
|
||||
|
||||
/// 设置平台设备id
|
||||
fn set_pdev_id(&self, id: i32);
|
||||
/// 设置id是否为自动分配
|
||||
fn set_pdev_id_auto(&self, id_auto: bool);
|
||||
|
||||
fn compatible_table(&self) -> CompatibleTable;
|
||||
/// @brief: 判断设备是否初始化
|
||||
/// @parameter: None
|
||||
@ -39,6 +72,54 @@ pub trait PlatformDevice: Device {
|
||||
fn set_state(&self, set_state: DeviceState);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformDeviceManager;
|
||||
|
||||
impl PlatformDeviceManager {
|
||||
/// platform_device_add - add a platform device to device hierarchy
|
||||
pub fn device_add(&self, pdev: Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
if pdev.parent().is_none() {
|
||||
pdev.set_parent(Some(Arc::downgrade(
|
||||
&(platform_bus_device() as Arc<dyn KObject>),
|
||||
)));
|
||||
}
|
||||
|
||||
pdev.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
|
||||
let id = pdev.pdev_id().0;
|
||||
match id {
|
||||
PLATFORM_DEVID_NONE => {
|
||||
pdev.set_name(format!("{}", pdev.pdev_name()));
|
||||
}
|
||||
PLATFORM_DEVID_AUTO => {
|
||||
let id = PLATFORM_DEVID_IDA.alloc().ok_or(SystemError::EOVERFLOW)?;
|
||||
pdev.set_pdev_id(id as i32);
|
||||
pdev.set_pdev_id_auto(true);
|
||||
pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0));
|
||||
}
|
||||
_ => {
|
||||
pdev.set_name(format!("{}.{}", pdev.pdev_name(), id));
|
||||
}
|
||||
}
|
||||
|
||||
// todo: 插入资源: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=platform_device_add#691
|
||||
let r = device_manager().add_device(pdev.clone() as Arc<dyn Device>);
|
||||
if r.is_ok() {
|
||||
pdev.set_state(DeviceState::Initialized);
|
||||
return Ok(()); // success
|
||||
} else {
|
||||
// failed
|
||||
let pdevid = pdev.pdev_id();
|
||||
if pdevid.1 {
|
||||
PLATFORM_DEVID_IDA.free(pdevid.0 as usize);
|
||||
pdev.set_pdev_id(PLATFORM_DEVID_AUTO);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct PlatformBusDevice {
|
||||
@ -56,7 +137,7 @@ impl PlatformBusDevice {
|
||||
) -> Arc<PlatformBusDevice> {
|
||||
return Arc::new(PlatformBusDevice {
|
||||
inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)),
|
||||
kobj_state: LockedKObjectState::new(KObjectState::empty()),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
});
|
||||
}
|
||||
|
||||
@ -101,18 +182,8 @@ impl PlatformBusDevice {
|
||||
let state = self.inner.lock().state;
|
||||
return state;
|
||||
}
|
||||
|
||||
// /// @brief:
|
||||
// /// @parameter: None
|
||||
// /// @return: 总线状态
|
||||
// #[inline]
|
||||
// #[allow(dead_code)]
|
||||
// fn set_driver(&self, driver: Option<Arc<LockedPlatformBusDriver>>) {
|
||||
// self.0.lock().driver = driver;
|
||||
// }
|
||||
}
|
||||
|
||||
/// @brief: platform总线
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InnerPlatformBusDevice {
|
||||
@ -125,14 +196,10 @@ pub struct InnerPlatformBusDevice {
|
||||
/// 当前设备挂载到的总线
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
/// 当前设备已经匹配的驱动
|
||||
driver: Option<Arc<dyn Driver>>,
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
}
|
||||
|
||||
/// @brief: platform方法集
|
||||
impl InnerPlatformBusDevice {
|
||||
/// @brief: 创建一个platform总线实例
|
||||
/// @parameter: None
|
||||
/// @return: platform总线实例
|
||||
pub fn new(data: DevicePrivateData, parent: Option<Weak<dyn KObject>>) -> Self {
|
||||
Self {
|
||||
data,
|
||||
@ -167,6 +234,10 @@ impl KObject for PlatformBusDevice {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!("platform_bus_device::set_kobj_type")
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
None
|
||||
}
|
||||
@ -218,8 +289,12 @@ impl Device for PlatformBusDevice {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
self.inner.lock().driver.clone()
|
||||
self.inner.lock().driver.clone()?.upgrade()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -227,7 +302,19 @@ impl Device for PlatformBusDevice {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_driver(&self, driver: Option<Arc<dyn Driver>>) {
|
||||
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||
self.inner.lock().driver = driver;
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,54 @@
|
||||
use crate::driver::{base::device::DevicePrivateData, Driver};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use super::{super::device::driver::DriverError, CompatibleTable};
|
||||
use crate::{
|
||||
driver::base::device::{
|
||||
bus::Bus,
|
||||
driver::{driver_manager, Driver},
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{platform_bus, platform_device::PlatformDevice};
|
||||
|
||||
lazy_static! {
|
||||
static ref PLATFORM_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["platform"]);
|
||||
}
|
||||
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上,
|
||||
/// 同时应该实现Driver trait
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||
pub trait PlatformDriver: Driver {
|
||||
fn compatible_table(&self) -> CompatibleTable;
|
||||
/// @brief 探测设备
|
||||
/// @param data 设备初始拥有的基本信息
|
||||
fn probe(&self, data: DevicePrivateData) -> Result<(), DriverError> {
|
||||
if data.compatible_table().matches(&PLATFORM_COMPAT_TABLE) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(DriverError::UnsupportedOperation);
|
||||
}
|
||||
/// 检测设备是否能绑定到这个驱动
|
||||
///
|
||||
/// 如果能,则把设备的driver指向这个驱动。
|
||||
/// 请注意,这个函数不应该把driver加入驱动的devices列表,相关工作会在外部的函数里面处理。
|
||||
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn remove(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn shutdown(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn suspend(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn resume(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn platform_driver_manager() -> &'static PlatformDriverManager {
|
||||
&PlatformDriverManager
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformDriverManager;
|
||||
|
||||
impl PlatformDriverManager {
|
||||
/// 注册平台设备驱动
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=__platform_driver_register#861
|
||||
pub fn register(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), SystemError> {
|
||||
driver.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
return driver_manager().register(driver as Arc<dyn Driver>);
|
||||
}
|
||||
|
||||
/// 卸载平台设备驱动
|
||||
#[allow(dead_code)]
|
||||
pub fn unregister(&self, driver: &Arc<dyn PlatformDriver>) {
|
||||
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,26 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use intertrait::cast::CastArc;
|
||||
|
||||
use crate::{
|
||||
driver::base::{device::bus::Bus, kobject::KObject, subsys::SubSysPrivate},
|
||||
driver::{
|
||||
acpi::acpi_manager,
|
||||
base::{
|
||||
device::{bus::Bus, driver::Driver, Device},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
},
|
||||
filesystem::{
|
||||
sysfs::{Attribute, AttributeGroup},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{platform_device::PlatformDevice, platform_driver::PlatformDriver};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformBus {
|
||||
private: SubSysPrivate,
|
||||
@ -44,6 +55,92 @@ impl Bus for PlatformBus {
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.private;
|
||||
}
|
||||
|
||||
fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let drv = device.driver().ok_or(SystemError::EINVAL)?;
|
||||
let pdrv = drv.cast::<dyn PlatformDriver>().map_err(|_|{
|
||||
kerror!("PlatformBus::probe() failed: device.driver() is not a PlatformDriver. Device: '{:?}'", device.name());
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
let pdev = device.clone().cast::<dyn PlatformDevice>().map_err(|_| {
|
||||
kerror!(
|
||||
"PlatformBus::probe() failed: device is not a PlatformDevice. Device: '{:?}'",
|
||||
device.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
return pdrv.probe(&pdev);
|
||||
}
|
||||
|
||||
fn remove(&self, _device: &Arc<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!()
|
||||
}
|
||||
|
||||
///
|
||||
/// match platform device to platform driver.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// * `device` - platform device
|
||||
/// * `driver` - platform driver
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - `Ok(true)` - 匹配成功
|
||||
/// - `Ok(false)` - 匹配失败
|
||||
/// - `Err(_)` - 由于内部错误导致匹配失败
|
||||
///
|
||||
/// Platform device IDs are assumed to be encoded like this:
|
||||
/// "<name><instance>", where <name> is a short description of the type of
|
||||
/// device, like "pci" or "floppy", and <instance> is the enumerated
|
||||
/// instance of the device, like '0' or '42'. Driver IDs are simply
|
||||
/// "<name>". So, extract the <name> from the platform_device structure,
|
||||
/// and compare it against the name of the driver. Return whether they match
|
||||
/// or not.
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c#1331
|
||||
///
|
||||
///
|
||||
fn match_device(
|
||||
&self,
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError> {
|
||||
// 尝试从 ACPI 中匹配
|
||||
if let Ok(x) = acpi_manager().driver_match_device(driver, device) {
|
||||
if x {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从 ID table 中匹配
|
||||
if let Some(drv_id_table) = driver.id_table() {
|
||||
let pdev = device
|
||||
.clone()
|
||||
.cast::<dyn PlatformDevice>()
|
||||
.map_err(|_| SystemError::EINVAL)?;
|
||||
if drv_id_table.name().eq(&pdev.name()) {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试根据设备名称匹配
|
||||
return Ok(device.name().eq(&driver.name()));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
Reference in New Issue
Block a user