mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
完善设备驱动模型,基于kset、kobj来维护对象之间的关系 (#401)
* 使用kobj和kset管理/sys文件夹下的对象 * 修改notifier,把action从u64换为泛型。 * 完善设备驱动模型,基于kset、kobj来维护对象之间的关系
This commit is contained in:
parent
6abb8bd7c0
commit
06d5e24726
8
kernel/src/driver/acpi/glue.rs
Normal file
8
kernel/src/driver/acpi/glue.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
|
use crate::driver::base::device::Device;
|
||||||
|
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/glue.c#352
|
||||||
|
pub fn acpi_device_notify(_dev: &Arc<dyn Device>) {
|
||||||
|
return;
|
||||||
|
}
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
mod c_adapter;
|
mod c_adapter;
|
||||||
|
pub mod glue;
|
||||||
pub mod old;
|
pub mod old;
|
||||||
|
|
||||||
extern crate acpi;
|
extern crate acpi;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/// 引入Module
|
/// 引入Module
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::{
|
driver::base::{
|
||||||
device::{mkdev, Device, DeviceNumber, IdTable, BLOCKDEVS, DEVICE_MANAGER},
|
device::{mkdev, Device, DeviceError, DeviceNumber, IdTable, BLOCKDEVS},
|
||||||
map::{
|
map::{
|
||||||
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
||||||
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
||||||
@ -475,11 +475,12 @@ impl BlockDeviceOps {
|
|||||||
/// range: 次设备号范围
|
/// range: 次设备号范围
|
||||||
/// @return: none
|
/// @return: none
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn bdev_add(bdev: Arc<dyn BlockDevice>, id_table: IdTable) {
|
pub fn bdev_add(_bdev: Arc<dyn BlockDevice>, id_table: IdTable) -> Result<(), DeviceError> {
|
||||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||||
kerror!("Device number can't be 0!\n");
|
kerror!("Device number can't be 0!\n");
|
||||||
}
|
}
|
||||||
DEVICE_MANAGER.add_device(id_table, bdev.device())
|
todo!("bdev_add")
|
||||||
|
// return device_manager().add_device(bdev.id_table(), bdev.device());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: block设备注销
|
/// @brief: block设备注销
|
||||||
|
10
kernel/src/driver/base/c_adapter.rs
Normal file
10
kernel/src/driver/base/c_adapter.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use super::init::driver_init;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn rs_driver_init() -> i32 {
|
||||||
|
let result = driver_init()
|
||||||
|
.map(|_| 0)
|
||||||
|
.unwrap_or_else(|e| e.to_posix_errno());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -3,7 +3,7 @@ use alloc::sync::Arc;
|
|||||||
use crate::{kerror, syscall::SystemError};
|
use crate::{kerror, syscall::SystemError};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
device::{mkdev, Device, DeviceNumber, IdTable, CHARDEVS, DEVICE_MANAGER, DEVMAP},
|
device::{device_manager, mkdev, Device, DeviceNumber, IdTable, CHARDEVS, DEVMAP},
|
||||||
map::{
|
map::{
|
||||||
kobj_map, kobj_unmap, DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END,
|
kobj_map, kobj_unmap, DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END,
|
||||||
DEV_MAJOR_DYN_EXT_START, DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
DEV_MAJOR_DYN_EXT_START, DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
||||||
@ -189,17 +189,23 @@ impl CharDevOps {
|
|||||||
/// range: 次设备号范围
|
/// range: 次设备号范围
|
||||||
/// @return: none
|
/// @return: none
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn cdev_add(cdev: Arc<dyn CharDevice>, id_table: IdTable, range: usize) {
|
pub fn cdev_add(
|
||||||
|
cdev: Arc<dyn CharDevice>,
|
||||||
|
id_table: IdTable,
|
||||||
|
range: usize,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||||
kerror!("Device number can't be 0!\n");
|
kerror!("Device number can't be 0!\n");
|
||||||
}
|
}
|
||||||
DEVICE_MANAGER.add_device(id_table.clone(), cdev.clone());
|
device_manager().add_device(cdev.clone())?;
|
||||||
kobj_map(
|
kobj_map(
|
||||||
DEVMAP.clone(),
|
DEVMAP.clone(),
|
||||||
id_table.device_number(),
|
id_table.device_number(),
|
||||||
range,
|
range,
|
||||||
cdev.clone(),
|
cdev.clone(),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 字符设备注销
|
/// @brief: 字符设备注销
|
||||||
@ -208,7 +214,7 @@ impl CharDevOps {
|
|||||||
/// @return: none
|
/// @return: none
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn cdev_del(id_table: IdTable, range: usize) {
|
pub fn cdev_del(id_table: IdTable, range: usize) {
|
||||||
DEVICE_MANAGER.remove_device(&id_table);
|
device_manager().remove_device(&id_table);
|
||||||
kobj_unmap(DEVMAP.clone(), id_table.device_number(), range);
|
kobj_unmap(DEVMAP.clone(), id_table.device_number(), range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
kernel/src/driver/base/class.rs
Normal file
26
kernel/src/driver/base/class.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
|
use crate::syscall::SystemError;
|
||||||
|
|
||||||
|
use super::kset::KSet;
|
||||||
|
|
||||||
|
/// `/sys/class`的kset
|
||||||
|
static mut CLASS_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn sys_class_kset() -> Arc<KSet> {
|
||||||
|
unsafe { CLASS_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 初始化`/sys/class`的kset
|
||||||
|
pub(super) fn classes_init() -> Result<(), SystemError> {
|
||||||
|
let class_kset = KSet::new("class".to_string());
|
||||||
|
class_kset
|
||||||
|
.register(None)
|
||||||
|
.expect("register class kset failed");
|
||||||
|
unsafe {
|
||||||
|
CLASS_KSET_INSTANCE = Some(class_kset);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
@ -1,25 +1,41 @@
|
|||||||
use super::{
|
use super::{sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState};
|
||||||
device_register, device_unregister,
|
|
||||||
driver::{driver_register, driver_unregister, DriverError},
|
|
||||||
Device, DeviceError, DeviceState, IdTable,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::Driver,
|
driver::base::{device::device_manager, kobject::KObject, kset::KSet, subsys::SubSysPrivate},
|
||||||
filesystem::{
|
filesystem::{
|
||||||
sysfs::{
|
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOpsSupport},
|
||||||
bus::{sys_bus_init, sys_bus_register},
|
vfs::syscall::ModeType,
|
||||||
SYS_BUS_INODE,
|
|
||||||
},
|
|
||||||
vfs::IndexNode,
|
|
||||||
},
|
},
|
||||||
libs::spinlock::SpinLock,
|
libs::rwlock::RwLock,
|
||||||
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
use alloc::{collections::BTreeMap, sync::Arc};
|
use alloc::{
|
||||||
use core::fmt::Debug;
|
string::{String, ToString},
|
||||||
use lazy_static::lazy_static;
|
sync::Arc,
|
||||||
|
};
|
||||||
|
use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
lazy_static! {
|
/// `/sys/bus`的kset
|
||||||
pub static ref BUS_MANAGER: Arc<LockedBusManager> = Arc::new(LockedBusManager::new());
|
static mut BUS_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
/// `/sys/devices/system`的kset
|
||||||
|
static mut DEVICES_SYSTEM_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
|
static mut BUS_MANAGER_INSTANCE: Option<BusManager> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sys_bus_kset() -> Arc<KSet> {
|
||||||
|
unsafe { BUS_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn sys_devices_system_kset() -> Arc<KSet> {
|
||||||
|
unsafe { DEVICES_SYSTEM_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn bus_manager() -> &'static BusManager {
|
||||||
|
unsafe { BUS_MANAGER_INSTANCE.as_ref().unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线状态
|
/// @brief: 总线状态
|
||||||
@ -63,151 +79,431 @@ impl From<BusState> for DeviceState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线驱动trait,所有总线驱动都应实现该trait
|
/// 总线子系统的trait,所有总线都应实现该trait
|
||||||
pub trait BusDriver: Driver {
|
///
|
||||||
/// @brief: 判断总线是否为空
|
/// 请注意,这个trait是用于实现总线子系统的,而不是总线驱动/总线设备。
|
||||||
/// @parameter: None
|
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device/bus.h#84
|
||||||
/// @return: 如果总线上设备和驱动的数量都为0,则返回true,否则,返回false
|
pub trait Bus: Debug + Send + Sync {
|
||||||
fn is_empty(&self) -> bool;
|
fn name(&self) -> String;
|
||||||
|
fn dev_name(&self) -> String;
|
||||||
|
fn root_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 总线上的设备的默认属性组
|
||||||
|
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 总线的默认属性组
|
||||||
|
fn bus_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 总线上的驱动的默认属性组
|
||||||
|
fn drv_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subsystem(&self) -> &SubSysPrivate;
|
||||||
|
|
||||||
|
/// 对当前总线操作的时候需要获取父级总线的锁
|
||||||
|
fn need_parent_lock(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线设备trait,所有总线都应实现该trait
|
impl dyn Bus {
|
||||||
pub trait Bus: Device {}
|
/// 在bus上,根据条件寻找一个特定的设备
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `matcher` - 匹配器
|
||||||
|
/// - `data` - 传给匹配器的数据
|
||||||
|
pub fn find_device<T: Copy>(
|
||||||
|
&self,
|
||||||
|
matcher: &dyn DeviceMatcher<T>,
|
||||||
|
data: T,
|
||||||
|
) -> Option<Arc<dyn Device>> {
|
||||||
|
let subsys = self.subsystem();
|
||||||
|
let guard = subsys.devices().read();
|
||||||
|
for dev in guard.iter() {
|
||||||
|
let dev = dev.upgrade();
|
||||||
|
if let Some(dev) = dev {
|
||||||
|
if matcher.match_device(&dev, data) {
|
||||||
|
return Some(dev.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 根据名称匹配设备
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - name 设备名称
|
||||||
|
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
|
||||||
|
return self.find_device(&DeviceMatchName, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief: 总线管理结构体
|
/// @brief: 总线管理结构体
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct BusManager {
|
pub struct BusManager {
|
||||||
buses: BTreeMap<IdTable, Arc<dyn Bus>>, // 总线设备表
|
/// 存储总线bus的kset结构体与bus实例的映射(用于在sysfs callback的时候,根据kset找到bus实例)
|
||||||
bus_drvs: BTreeMap<IdTable, Arc<dyn BusDriver>>, // 总线驱动表
|
kset_bus_map: RwLock<HashMap<Arc<KSet>, Arc<dyn Bus>>>,
|
||||||
sys_info: Option<Arc<dyn IndexNode>>, // 总线inode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: bus管理(锁)
|
impl BusManager {
|
||||||
pub struct LockedBusManager(SpinLock<BusManager>);
|
|
||||||
|
|
||||||
/// @brief: 总线管理方法集
|
|
||||||
impl LockedBusManager {
|
|
||||||
/// @brief: 创建总线管理实例
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: 总线管理实例
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
LockedBusManager(SpinLock::new(BusManager {
|
return Self {
|
||||||
buses: BTreeMap::new(),
|
kset_bus_map: RwLock::new(HashMap::new()),
|
||||||
bus_drvs: BTreeMap::new(),
|
};
|
||||||
sys_info: Some(SYS_BUS_INODE()),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 添加总线
|
///
|
||||||
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
/// bus_register - register a driver-core subsystem
|
||||||
/// @parameter bus_dev: 总线实例
|
///
|
||||||
/// @return: None
|
/// ## 参数
|
||||||
#[inline]
|
/// - `bus` - bus to register
|
||||||
#[allow(dead_code)]
|
///
|
||||||
pub fn add_bus(&self, id_table: IdTable, bus_dev: Arc<dyn Bus>) {
|
/// Once we have that, we register the bus with the kobject
|
||||||
let mut bus_manager = self.0.lock();
|
/// infrastructure, then register the children subsystems it has:
|
||||||
bus_manager.buses.insert(id_table, bus_dev);
|
/// the devices and drivers that belong to the subsystem.
|
||||||
|
///
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_register#783
|
||||||
|
///
|
||||||
|
/// todo: 增加错误处理逻辑
|
||||||
|
pub fn register(&self, bus: Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
|
bus.subsystem().set_bus(Arc::downgrade(&bus));
|
||||||
|
|
||||||
|
let subsys_kset = bus.subsystem().subsys();
|
||||||
|
subsys_kset.set_name(bus.name());
|
||||||
|
bus.subsystem().set_drivers_autoprobe(true);
|
||||||
|
|
||||||
|
subsys_kset.register(Some(sys_bus_kset()))?;
|
||||||
|
|
||||||
|
let devices_kset =
|
||||||
|
KSet::new_and_add("devices".to_string(), None, Some(subsys_kset.clone()))?;
|
||||||
|
bus.subsystem().set_devices_kset(devices_kset);
|
||||||
|
let drivers_kset =
|
||||||
|
KSet::new_and_add("drivers".to_string(), None, Some(subsys_kset.clone()))?;
|
||||||
|
bus.subsystem().set_drivers_kset(drivers_kset);
|
||||||
|
|
||||||
|
self.add_probe_files(&bus)?;
|
||||||
|
let bus_groups = bus.bus_groups();
|
||||||
|
self.add_groups(&bus, bus_groups)?;
|
||||||
|
// 把bus实例添加到总线管理器中(方便在sysfs callback的时候,根据kset找到bus实例)
|
||||||
|
self.kset_bus_map.write().insert(subsys_kset, bus.clone());
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 添加总线驱动
|
pub fn unregister(&self, _bus: Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
/// @parameter id_table: 总线驱动标识符,用于唯一标识该总线驱动
|
todo!("bus_unregister")
|
||||||
/// @parameter bus_dev: 总线驱动实例
|
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn add_driver(&self, id_table: IdTable, bus_drv: Arc<dyn BusDriver>) {
|
|
||||||
let mut bus_manager = self.0.lock();
|
|
||||||
bus_manager.bus_drvs.insert(id_table, bus_drv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 卸载总线
|
fn add_probe_files(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
self.create_file(bus, &BusAttrDriversProbe)?;
|
||||||
/// @return: None
|
let r = self.create_file(bus, &BusAttrDriversAutoprobe);
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn remove_bus(&self, id_table: &IdTable) {
|
|
||||||
let mut bus_manager = self.0.lock();
|
|
||||||
bus_manager.buses.remove(id_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 卸载总线驱动
|
if r.is_err() {
|
||||||
/// @parameter id_table: 总线驱动标识符,用于唯一标识该总线驱动
|
self.remove_file(bus, &BusAttrDriversProbe);
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn remove_bus_driver(&self, id_table: &IdTable) {
|
|
||||||
let mut bus_manager = self.0.lock();
|
|
||||||
bus_manager.bus_drvs.remove(id_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取总线设备
|
|
||||||
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
|
||||||
/// @return: 总线设备实例
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn get_bus(&self, id_table: &IdTable) -> Option<Arc<dyn Bus>> {
|
|
||||||
let bus_manager = self.0.lock();
|
|
||||||
bus_manager.buses.get(id_table).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取总线驱动
|
|
||||||
/// @parameter id_table: 总线驱动标识符,用于唯一标识该总线驱动
|
|
||||||
/// @return: 总线驱动实例
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn get_driver(&self, id_table: &IdTable) -> Option<Arc<dyn BusDriver>> {
|
|
||||||
let bus_manager = self.0.lock();
|
|
||||||
return bus_manager.bus_drvs.get(id_table).cloned();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取总线管理器的sys information
|
|
||||||
/// @parameter None
|
|
||||||
/// @return: sys inode
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 总线注册,将总线加入全局总线管理器中,并根据id table在sys/bus和sys/devices下生成文件夹
|
|
||||||
/// @parameter bus: Bus设备实体
|
|
||||||
/// @return: 成功:() 失败:DeviceError
|
|
||||||
pub fn bus_register<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
|
|
||||||
BUS_MANAGER.add_bus(bus.id_table(), bus.clone());
|
|
||||||
match sys_bus_register(&bus.id_table().name()) {
|
|
||||||
Ok(inode) => {
|
|
||||||
let _ = sys_bus_init(&inode);
|
|
||||||
return device_register(bus);
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(DeviceError::RegisterError),
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn remove_probe_files(&self, bus: &Arc<dyn Bus>) {
|
||||||
|
self.remove_file(bus, &BusAttrDriversAutoprobe);
|
||||||
|
self.remove_file(bus, &BusAttrDriversProbe);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_file(
|
||||||
|
&self,
|
||||||
|
bus: &Arc<dyn Bus>,
|
||||||
|
attr: &'static dyn Attribute,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let bus_kobj = bus.subsystem().subsys() as Arc<dyn KObject>;
|
||||||
|
return sysfs_instance().create_file(&bus_kobj, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_file(&self, bus: &Arc<dyn Bus>, attr: &'static dyn Attribute) {
|
||||||
|
let bus_kobj = bus.subsystem().subsys() as Arc<dyn KObject>;
|
||||||
|
sysfs_instance().remove_file(&bus_kobj, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add_groups(
|
||||||
|
&self,
|
||||||
|
bus: &Arc<dyn Bus>,
|
||||||
|
groups: &[&'static dyn AttributeGroup],
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let bus_kobj = bus.subsystem().subsys() as Arc<dyn KObject>;
|
||||||
|
return sysfs_instance().create_groups(&bus_kobj, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 根据bus的kset找到bus实例
|
||||||
|
fn get_bus_by_kset(&self, kset: &Arc<KSet>) -> Option<Arc<dyn Bus>> {
|
||||||
|
return self.kset_bus_map.read().get(kset).map(|bus| bus.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 为bus上的设备选择可能的驱动程序
|
||||||
|
///
|
||||||
|
/// 这个函数会扫描总线上的所有没有驱动的设备,然后为它们选择可能的驱动程序。
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `bus` - bus实例
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn rescan_devices(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
|
for dev in bus.subsystem().devices().read().iter() {
|
||||||
|
let dev = dev.upgrade();
|
||||||
|
if let Some(dev) = dev {
|
||||||
|
rescan_devices_helper(dev)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 为新设备探测驱动
|
||||||
|
///
|
||||||
|
/// Automatically probe for a driver if the bus allows it.
|
||||||
|
pub fn probe_device(&self, dev: &Arc<dyn Device>) {
|
||||||
|
let bus = dev.bus();
|
||||||
|
if bus.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let bus = bus.unwrap();
|
||||||
|
if bus.subsystem().drivers_autoprobe() {
|
||||||
|
device_manager().device_initial_probe(dev).ok();
|
||||||
|
}
|
||||||
|
for interface in bus.subsystem().interfaces() {
|
||||||
|
interface.add_device(dev).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在bus上,根据条件寻找一个特定的设备
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `matcher` - 匹配器
|
||||||
|
/// - `data` - 传给匹配器的数据
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn find_device<T: Copy>(
|
||||||
|
&self,
|
||||||
|
bus: &Arc<dyn Bus>,
|
||||||
|
matcher: &dyn DeviceMatcher<T>,
|
||||||
|
data: T,
|
||||||
|
) -> Option<Arc<dyn Device>> {
|
||||||
|
return bus.find_device(matcher, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线注销,将总线从全局总线管理器中删除,并在sys/bus和sys/devices下删除文件夹
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#684
|
||||||
|
fn rescan_devices_helper(dev: Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
if dev.driver().is_none() {
|
||||||
|
let need_parent_lock = dev.bus().map(|bus| bus.need_parent_lock()).unwrap_or(false);
|
||||||
|
if unlikely(need_parent_lock) {
|
||||||
|
// todo: lock device parent
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
device_manager().device_attach(&dev)?;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// bus_register - register a driver-core subsystem
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
/// - `bus` - bus to register
|
||||||
|
///
|
||||||
|
/// Once we have that, we register the bus with the kobject
|
||||||
|
/// infrastructure, then register the children subsystems it has:
|
||||||
|
/// the devices and drivers that belong to the subsystem.
|
||||||
|
pub fn bus_register(bus: Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
|
return bus_manager().register(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 总线注销,并在sys/bus和sys/devices下删除文件夹
|
||||||
/// @parameter bus: Bus设备实体
|
/// @parameter bus: Bus设备实体
|
||||||
/// @return: 成功:() 失败:DeviceError
|
/// @return: 成功:() 失败:SystemError
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn bus_unregister<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
|
pub fn bus_unregister(bus: Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||||
BUS_MANAGER.remove_bus(&bus.id_table());
|
return bus_manager().unregister(bus);
|
||||||
return device_unregister(bus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线驱动注册,将总线驱动加入全局总线管理器中
|
pub fn buses_init() -> Result<(), SystemError> {
|
||||||
/// @parameter bus: Bus设备驱动实体
|
let bus_kset = KSet::new("bus".to_string());
|
||||||
/// @return: 成功:() 失败:DeviceError
|
bus_kset.register(None).expect("bus kset register failed");
|
||||||
pub fn bus_driver_register(bus_driver: Arc<dyn BusDriver>) -> Result<(), DriverError> {
|
unsafe {
|
||||||
BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone());
|
BUS_KSET_INSTANCE = Some(bus_kset);
|
||||||
return driver_register(bus_driver);
|
}
|
||||||
|
|
||||||
|
// 初始化 /sys/devices/system
|
||||||
|
{
|
||||||
|
let devices_system_kset = KSet::new("system".to_string());
|
||||||
|
let parent = sys_devices_kset() as Arc<dyn KObject>;
|
||||||
|
devices_system_kset.set_parent(Some(Arc::downgrade(&parent)));
|
||||||
|
devices_system_kset
|
||||||
|
.register(Some(sys_devices_kset()))
|
||||||
|
.expect("devices system kset register failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化总线管理器
|
||||||
|
{
|
||||||
|
let bus_manager = BusManager::new();
|
||||||
|
unsafe {
|
||||||
|
BUS_MANAGER_INSTANCE = Some(bus_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 总线驱动注销,将总线从全局总线管理器中删除
|
/// 把一个设备添加到总线上
|
||||||
/// @parameter bus: Bus设备驱动实体
|
///
|
||||||
/// @return: 成功:() 失败:DeviceError
|
/// ## 描述
|
||||||
#[allow(dead_code)]
|
///
|
||||||
pub fn bus_driver_unregister(bus_driver: Arc<dyn BusDriver>) -> Result<(), DriverError> {
|
/// - 添加一个设备的与bus相关的属性
|
||||||
BUS_MANAGER.remove_bus_driver(&bus_driver.id_table());
|
/// - 在bus和设备文件夹下,创建软链接
|
||||||
return driver_unregister(bus_driver);
|
/// - 把设备添加到它的总线的设备列表中
|
||||||
|
///
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_device#441
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev` - 要被添加的设备
|
||||||
|
pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
let bus = dev.bus();
|
||||||
|
if let Some(bus) = bus {
|
||||||
|
device_manager().add_groups(dev, bus.dev_groups())?;
|
||||||
|
// todo: 增加符号链接
|
||||||
|
todo!("bus_add_device")
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 自动为设备在总线上寻找可用的驱动程序
|
||||||
|
///
|
||||||
|
/// Automatically probe for a driver if the bus allows it.
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev` - 要被添加的设备
|
||||||
|
///
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_probe_device#478
|
||||||
|
pub fn bus_probe_device(dev: &Arc<dyn Device>) {
|
||||||
|
bus_manager().probe_device(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BusAttrDriversProbe;
|
||||||
|
|
||||||
|
impl Attribute for BusAttrDriversProbe {
|
||||||
|
fn mode(&self) -> ModeType {
|
||||||
|
return ModeType::S_IWUSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
return "drivers_probe";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn support(&self) -> SysFSOpsSupport {
|
||||||
|
return SysFSOpsSupport::STORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#241
|
||||||
|
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
|
||||||
|
let kset: Arc<KSet> = kobj.arc_any().downcast().map_err(|_| SystemError::EINVAL)?;
|
||||||
|
let bus = bus_manager()
|
||||||
|
.get_bus_by_kset(&kset)
|
||||||
|
.ok_or(SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
let name = CStr::from_bytes_with_nul(buf)
|
||||||
|
.map_err(|_| SystemError::EINVAL)?
|
||||||
|
.to_str()
|
||||||
|
.map_err(|_| SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
let device = bus.find_device_by_name(name).ok_or(SystemError::ENODEV)?;
|
||||||
|
|
||||||
|
if rescan_devices_helper(device).is_ok() {
|
||||||
|
return Ok(buf.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BusAttrDriversAutoprobe;
|
||||||
|
|
||||||
|
impl Attribute for BusAttrDriversAutoprobe {
|
||||||
|
fn mode(&self) -> ModeType {
|
||||||
|
return ModeType::from_bits_truncate(0o644);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
return "drivers_autoprobe";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn support(&self) -> SysFSOpsSupport {
|
||||||
|
return SysFSOpsSupport::STORE | SysFSOpsSupport::SHOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#231
|
||||||
|
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
|
||||||
|
if buf.len() == 0 {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let kset: Arc<KSet> = kobj.arc_any().downcast().map_err(|_| SystemError::EINVAL)?;
|
||||||
|
let bus = bus_manager()
|
||||||
|
.get_bus_by_kset(&kset)
|
||||||
|
.ok_or(SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
if buf[0] == '0' as u8 {
|
||||||
|
bus.subsystem().set_drivers_autoprobe(false);
|
||||||
|
} else {
|
||||||
|
bus.subsystem().set_drivers_autoprobe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(buf.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#226
|
||||||
|
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||||
|
let kset: Arc<KSet> = kobj.arc_any().downcast().map_err(|_| SystemError::EINVAL)?;
|
||||||
|
let bus = bus_manager()
|
||||||
|
.get_bus_by_kset(&kset)
|
||||||
|
.ok_or(SystemError::EINVAL)?;
|
||||||
|
let val = if bus.subsystem().drivers_autoprobe() {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
return sysfs_emit_str(buf, format!("{val}\n").as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum BusNotifyEvent {
|
||||||
|
/// 一个设备被添加到总线上
|
||||||
|
AddDevice,
|
||||||
|
/// 一个设备将要被移除
|
||||||
|
DelDevice,
|
||||||
|
/// 一个设备已经被移除
|
||||||
|
RemovedDevice,
|
||||||
|
/// 一个驱动将要被绑定
|
||||||
|
BindDriver,
|
||||||
|
/// 一个驱动已经被绑定
|
||||||
|
BoundDriver,
|
||||||
|
/// 一个驱动将要被解绑
|
||||||
|
UnbindDriver,
|
||||||
|
/// 一个驱动已经被解绑
|
||||||
|
UnboundDriver,
|
||||||
|
/// 驱动绑定失败
|
||||||
|
DriverNotBound,
|
||||||
}
|
}
|
||||||
|
210
kernel/src/driver/base/device/dd.rs
Normal file
210
kernel/src/driver/base/device/dd.rs
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
use core::intrinsics::unlikely;
|
||||||
|
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
|
use crate::{driver::Driver, syscall::SystemError};
|
||||||
|
|
||||||
|
use super::{bus::BusNotifyEvent, driver::driver_manager, Device, DeviceManager};
|
||||||
|
|
||||||
|
impl DeviceManager {
|
||||||
|
/// 尝试把一个设备与一个驱动匹配
|
||||||
|
///
|
||||||
|
/// 当前函数会遍历整个bus的驱动列表,并且尝试把设备与每一个驱动进行匹配。
|
||||||
|
/// 一旦有一个驱动匹配成功,就会返回。
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// - Ok(true): 匹配成功
|
||||||
|
/// - Ok(false): 没有匹配成功
|
||||||
|
/// - Err(SystemError::ENODEV): 设备还没被注册
|
||||||
|
///
|
||||||
|
/// ## 参考
|
||||||
|
///
|
||||||
|
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#1049
|
||||||
|
pub fn device_attach(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
|
||||||
|
return self.do_device_attach(dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn device_initial_probe(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
|
||||||
|
return self.do_device_attach(dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#978
|
||||||
|
fn do_device_attach(
|
||||||
|
&self,
|
||||||
|
dev: &Arc<dyn Device>,
|
||||||
|
allow_async: bool,
|
||||||
|
) -> Result<bool, SystemError> {
|
||||||
|
if unlikely(allow_async) {
|
||||||
|
todo!("do_device_attach: allow_async")
|
||||||
|
}
|
||||||
|
if dev.is_dead() {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut do_async = false;
|
||||||
|
let mut r = Ok(false);
|
||||||
|
|
||||||
|
if dev.driver().is_some() {
|
||||||
|
if self.device_is_bound(dev) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.device_bind_driver(dev).is_ok() {
|
||||||
|
return Ok(true);
|
||||||
|
} else {
|
||||||
|
dev.set_driver(None);
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
|
||||||
|
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
|
||||||
|
let mut flag = true;
|
||||||
|
for driver in bus.subsystem().drivers().read().iter() {
|
||||||
|
if let Some(driver) = driver.upgrade() {
|
||||||
|
let r = self.do_device_attach_driver(&driver, &mut data);
|
||||||
|
if unlikely(r.is_err()) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag {
|
||||||
|
r = Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !flag && allow_async && data.have_async {
|
||||||
|
// If we could not find appropriate driver
|
||||||
|
// synchronously and we are allowed to do
|
||||||
|
// async probes and there are drivers that
|
||||||
|
// want to probe asynchronously, we'll
|
||||||
|
// try them.
|
||||||
|
|
||||||
|
do_async = true;
|
||||||
|
kdebug!(
|
||||||
|
"do_device_attach: try scheduling asynchronous probe for device: {}",
|
||||||
|
dev.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if do_async {
|
||||||
|
todo!("do_device_attach: do_async")
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#899
|
||||||
|
fn do_device_attach_driver(
|
||||||
|
&self,
|
||||||
|
_driver: &Arc<dyn Driver>,
|
||||||
|
_data: &mut DeviceAttachData,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
todo!("do_device_attach_driver")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查设备是否绑定到驱动程序
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
|
||||||
|
pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
|
||||||
|
if dev.driver().is_some() {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 把一个驱动绑定到设备上
|
||||||
|
///
|
||||||
|
/// 允许手动绑定驱动到设备上。调用者需要设置好dev.driver(),保证其不为None
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
///
|
||||||
|
/// ## 建议
|
||||||
|
///
|
||||||
|
/// 使用device_manager().driver_attach()会更好
|
||||||
|
///
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#496
|
||||||
|
pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
let r = driver_manager().driver_sysfs_add(dev);
|
||||||
|
if let Err(e) = r {
|
||||||
|
self.device_links_force_bind(dev);
|
||||||
|
self.driver_bound(dev);
|
||||||
|
return Err(e);
|
||||||
|
} else {
|
||||||
|
if let Some(bus) = dev.bus() {
|
||||||
|
bus.subsystem().bus_notifier().call_chain(
|
||||||
|
BusNotifyEvent::DriverNotBound,
|
||||||
|
Some(dev),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
|
||||||
|
fn driver_bound(&self, _dev: &Arc<dyn Device>) {
|
||||||
|
todo!("driver_bound")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#866
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct DeviceAttachData {
|
||||||
|
dev: Arc<dyn Device>,
|
||||||
|
|
||||||
|
/// Indicates whether we are considering asynchronous probing or
|
||||||
|
/// not. Only initial binding after device or driver registration
|
||||||
|
/// (including deferral processing) may be done asynchronously, the
|
||||||
|
/// rest is always synchronous, as we expect it is being done by
|
||||||
|
/// request from userspace.
|
||||||
|
check_async: bool,
|
||||||
|
|
||||||
|
/// Indicates if we are binding synchronous or asynchronous drivers.
|
||||||
|
/// When asynchronous probing is enabled we'll execute 2 passes
|
||||||
|
/// over drivers: first pass doing synchronous probing and second
|
||||||
|
/// doing asynchronous probing (if synchronous did not succeed -
|
||||||
|
/// most likely because there was no driver requiring synchronous
|
||||||
|
/// probing - and we found asynchronous driver during first pass).
|
||||||
|
/// The 2 passes are done because we can't shoot asynchronous
|
||||||
|
/// probe for given device and driver from bus_for_each_drv() since
|
||||||
|
/// driver pointer is not guaranteed to stay valid once
|
||||||
|
/// bus_for_each_drv() iterates to the next driver on the bus.
|
||||||
|
want_async: bool,
|
||||||
|
|
||||||
|
/// We'll set have_async to 'true' if, while scanning for matching
|
||||||
|
/// driver, we'll encounter one that requests asynchronous probing.
|
||||||
|
have_async: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceAttachData {
|
||||||
|
pub fn new(dev: Arc<dyn Device>, check_async: bool, want_async: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
dev,
|
||||||
|
check_async,
|
||||||
|
want_async,
|
||||||
|
have_async: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
|
fn set_have_async(&mut self) {
|
||||||
|
self.have_async = true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,8 @@
|
|||||||
use super::IdTable;
|
use super::Device;
|
||||||
use crate::{
|
use crate::syscall::SystemError;
|
||||||
driver::Driver, filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError,
|
use alloc::sync::Arc;
|
||||||
};
|
|
||||||
use alloc::{collections::BTreeMap, sync::Arc};
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref DRIVER_MANAGER: Arc<LockedDriverManager> = Arc::new(LockedDriverManager::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: Driver error
|
/// @brief: Driver error
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
@ -32,93 +26,18 @@ impl Into<SystemError> for DriverError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 驱动管理器(锁)
|
#[inline(always)]
|
||||||
#[derive(Debug)]
|
pub fn driver_manager() -> &'static DriverManager {
|
||||||
pub struct LockedDriverManager(SpinLock<DriverManager>);
|
&DriverManager
|
||||||
|
|
||||||
impl LockedDriverManager {
|
|
||||||
/// @brief: 创建一个新的驱动管理器(锁)
|
|
||||||
/// @parameter None
|
|
||||||
/// @return: LockedDriverManager实体
|
|
||||||
#[inline]
|
|
||||||
fn new() -> LockedDriverManager {
|
|
||||||
LockedDriverManager(SpinLock::new(DriverManager::new()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 添加驱动
|
|
||||||
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
|
|
||||||
/// @parameter drv: 驱动实例
|
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn add_driver(&self, id_table: IdTable, drv: Arc<dyn Driver>) {
|
|
||||||
let mut driver_manager = self.0.lock();
|
|
||||||
driver_manager.drivers.insert(id_table, drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 卸载驱动
|
|
||||||
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
|
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn remove_driver(&self, id_table: &IdTable) {
|
|
||||||
let mut driver_manager = self.0.lock();
|
|
||||||
driver_manager.drivers.remove(id_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取驱动
|
|
||||||
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
|
|
||||||
/// @return: 驱动实例
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn get_driver(&self, id_table: &IdTable) -> Option<Arc<dyn Driver>> {
|
|
||||||
let driver_manager = self.0.lock();
|
|
||||||
driver_manager.drivers.get(id_table).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取驱动管理器的sys information
|
|
||||||
/// @parameter id_table: 设备标识符,用于唯一标识该驱动
|
|
||||||
/// @return: 驱动实例
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 驱动管理器
|
/// @brief: 驱动管理器
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DriverManager {
|
pub struct DriverManager;
|
||||||
drivers: BTreeMap<IdTable, Arc<dyn Driver>>, // 所有驱动
|
|
||||||
sys_info: Option<Arc<dyn IndexNode>>, // sys information
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DriverManager {
|
impl DriverManager {
|
||||||
/// @brief: 创建一个新的设备管理器
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#434
|
||||||
/// @parameter: None
|
pub fn driver_sysfs_add(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
/// @return: Manager实体
|
todo!("DriverManager::driver_sysfs_add()");
|
||||||
#[inline]
|
|
||||||
fn new() -> DriverManager {
|
|
||||||
DriverManager {
|
|
||||||
drivers: BTreeMap::new(),
|
|
||||||
sys_info: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 驱动注册
|
|
||||||
/// @parameter: name: 驱动名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
pub fn driver_register(driver: Arc<dyn Driver>) -> Result<(), DriverError> {
|
|
||||||
DRIVER_MANAGER.add_driver(driver.id_table(), driver);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 驱动卸载
|
|
||||||
/// @parameter: name: 驱动名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn driver_unregister(driver: Arc<dyn Driver>) -> Result<(), DriverError> {
|
|
||||||
DRIVER_MANAGER.remove_driver(&driver.id_table());
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
@ -1,16 +1,78 @@
|
|||||||
use crate::{driver::uart::uart_device::uart_init, kinfo, syscall::SystemError};
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
#[no_mangle]
|
use crate::{
|
||||||
pub extern "C" fn rs_device_init() -> i32 {
|
driver::{
|
||||||
let result = device_init()
|
base::{
|
||||||
.map(|_| 0)
|
device::{
|
||||||
.unwrap_or_else(|e| e.to_posix_errno());
|
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER,
|
||||||
|
DEV_KSET_INSTANCE,
|
||||||
return result;
|
},
|
||||||
}
|
kobject::KObject,
|
||||||
|
kset::KSet,
|
||||||
|
},
|
||||||
|
uart::uart_device::uart_init,
|
||||||
|
},
|
||||||
|
kdebug, kinfo,
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn device_init() -> Result<(), SystemError> {
|
pub fn device_init() -> Result<(), SystemError> {
|
||||||
uart_init()?;
|
uart_init()?;
|
||||||
kinfo!("device init success");
|
kinfo!("device init success");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn devices_init() -> Result<(), SystemError> {
|
||||||
|
// 创建 `/sys/devices` 目录
|
||||||
|
{
|
||||||
|
let devices_kset = KSet::new("devices".to_string());
|
||||||
|
devices_kset
|
||||||
|
.register(None)
|
||||||
|
.expect("register devices kset failed");
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
DEVICES_KSET_INSTANCE = Some(devices_kset);
|
||||||
|
// 初始化全局设备管理器
|
||||||
|
DEVICE_MANAGER = Some(DeviceManager::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 `/sys/dev` 目录
|
||||||
|
{
|
||||||
|
let dev_kset = KSet::new("dev".to_string());
|
||||||
|
dev_kset.register(None).expect("register dev kset failed");
|
||||||
|
unsafe {
|
||||||
|
DEV_KSET_INSTANCE = Some(dev_kset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 `/sys/dev/block` 目录
|
||||||
|
{
|
||||||
|
kdebug!("create /sys/dev/block");
|
||||||
|
let dev_kset = sys_dev_kset();
|
||||||
|
let dev_block_kset = KSet::new("block".to_string());
|
||||||
|
let parent = dev_kset.clone() as Arc<dyn KObject>;
|
||||||
|
dev_block_kset.set_parent(Some(Arc::downgrade(&parent)));
|
||||||
|
|
||||||
|
dev_block_kset
|
||||||
|
.register(Some(dev_kset))
|
||||||
|
.expect("register dev block kset failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 `/sys/dev/char` 目录
|
||||||
|
{
|
||||||
|
kdebug!("create /sys/dev/char");
|
||||||
|
let dev_kset = sys_dev_kset();
|
||||||
|
let dev_char_kset = KSet::new("char".to_string());
|
||||||
|
let parent = dev_kset.clone() as Arc<dyn KObject>;
|
||||||
|
dev_char_kset.set_parent(Some(Arc::downgrade(&parent)));
|
||||||
|
|
||||||
|
dev_char_kset
|
||||||
|
.register(Some(dev_kset))
|
||||||
|
.expect("register dev char kset failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
kinfo!("devices init success");
|
||||||
|
device_init()?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
@ -1,32 +1,45 @@
|
|||||||
use alloc::{
|
use alloc::{
|
||||||
collections::BTreeMap,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
use intertrait::cast::CastArc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::map::{LockedDevsMap, LockedKObjMap},
|
driver::{
|
||||||
filesystem::{
|
acpi::glue::acpi_device_notify,
|
||||||
sysfs::{
|
base::map::{LockedDevsMap, LockedKObjMap},
|
||||||
devices::{sys_device_register, sys_device_unregister},
|
Driver,
|
||||||
SYS_DEVICES_INODE,
|
},
|
||||||
},
|
filesystem::{
|
||||||
vfs::IndexNode,
|
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
|
||||||
|
vfs::syscall::ModeType,
|
||||||
},
|
},
|
||||||
libs::spinlock::SpinLock,
|
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
use core::{any::Any, fmt::Debug};
|
use core::fmt::Debug;
|
||||||
|
use core::intrinsics::unlikely;
|
||||||
|
|
||||||
use super::platform::CompatibleTable;
|
use self::bus::{bus_add_device, bus_probe_device, Bus};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
kobject::{KObjType, KObject, KObjectManager},
|
||||||
|
kset::KSet,
|
||||||
|
platform::CompatibleTable,
|
||||||
|
swnode::software_node_notify,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod bus;
|
pub mod bus;
|
||||||
|
pub mod dd;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
|
|
||||||
lazy_static! {
|
static mut DEVICE_MANAGER: Option<DeviceManager> = None;
|
||||||
pub static ref DEVICE_MANAGER: Arc<LockedDeviceManager> = Arc::new(LockedDeviceManager::new());
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn device_manager() -> &'static DeviceManager {
|
||||||
|
unsafe { DEVICE_MANAGER.as_ref().unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// 全局字符设备号管理实例
|
// 全局字符设备号管理实例
|
||||||
pub static ref CHARDEVS: Arc<LockedDevsMap> = Arc::new(LockedDevsMap::default());
|
pub static ref CHARDEVS: Arc<LockedDevsMap> = Arc::new(LockedDevsMap::default());
|
||||||
@ -39,12 +52,47 @@ lazy_static! {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait KObject: Any + Send + Sync + Debug {}
|
/// `/sys/devices` 的 kset 实例
|
||||||
/// @brief 设备应该实现的操作
|
static mut DEVICES_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
/// @usage Device::read_at()
|
/// `/sys/dev` 的 kset 实例
|
||||||
|
static mut DEV_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
/// `/sys/dev/block` 的 kset 实例
|
||||||
|
static mut DEV_BLOCK_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
/// `/sys/dev/char` 的 kset 实例
|
||||||
|
static mut DEV_CHAR_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) fn sys_devices_kset() -> Arc<KSet> {
|
||||||
|
unsafe { DEVICES_KSET_INSTANCE.as_ref().unwrap().clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) fn sys_dev_kset() -> Arc<KSet> {
|
||||||
|
unsafe { DEV_KSET_INSTANCE.as_ref().unwrap().clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(super) fn sys_dev_block_kset() -> Arc<KSet> {
|
||||||
|
unsafe { DEV_BLOCK_KSET_INSTANCE.as_ref().unwrap().clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(self) fn sys_dev_char_kset() -> Arc<KSet> {
|
||||||
|
unsafe { DEV_CHAR_KSET_INSTANCE.as_ref().unwrap().clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 设备应该实现的操作
|
||||||
|
///
|
||||||
|
/// ## 注意
|
||||||
|
///
|
||||||
|
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Device>,
|
||||||
|
/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[[sync] Device]`,
|
||||||
|
///
|
||||||
|
/// 否则在释放设备资源的时候,会由于无法转换为Arc<dyn Device>而导致资源泄露,并且release回调函数也不会被调用。
|
||||||
pub trait Device: KObject {
|
pub trait Device: KObject {
|
||||||
// TODO: 待实现 open, close
|
// TODO: 待实现 open, close
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any;
|
|
||||||
/// @brief: 获取设备类型
|
/// @brief: 获取设备类型
|
||||||
/// @parameter: None
|
/// @parameter: None
|
||||||
/// @return: 实现该trait的设备所属类型
|
/// @return: 实现该trait的设备所属类型
|
||||||
@ -55,15 +103,27 @@ pub trait Device: KObject {
|
|||||||
/// @return: 该设备唯一标识
|
/// @return: 该设备唯一标识
|
||||||
fn id_table(&self) -> IdTable;
|
fn id_table(&self) -> IdTable;
|
||||||
|
|
||||||
/// @brief: 设置sysfs info
|
/// 设备释放时的回调函数
|
||||||
/// @parameter: None
|
fn release(&self) {
|
||||||
/// @return: 该设备唯一标识
|
let name = self.name();
|
||||||
fn set_sys_info(&self, _sys_info: Option<Arc<dyn IndexNode>>);
|
kwarn!(
|
||||||
|
"device {} does not have a release() function, it is broken and must be fixed.",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief: 获取设备的sys information
|
/// 获取当前设备所属的总线
|
||||||
/// @parameter id_table: 设备标识符,用于唯一标识该设备
|
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||||
/// @return: 设备实例
|
return None;
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>>;
|
}
|
||||||
|
|
||||||
|
/// 返回已经与当前设备匹配好的驱动程序
|
||||||
|
fn driver(&self) -> Option<Arc<dyn Driver>>;
|
||||||
|
|
||||||
|
fn set_driver(&self, driver: Option<Arc<dyn Driver>>);
|
||||||
|
|
||||||
|
/// 当前设备是否已经挂掉了
|
||||||
|
fn is_dead(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
|
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
|
||||||
@ -155,14 +215,14 @@ impl DeviceNumber {
|
|||||||
/// @parameter: none
|
/// @parameter: none
|
||||||
/// @return: 主设备号
|
/// @return: 主设备号
|
||||||
pub fn major(&self) -> usize {
|
pub fn major(&self) -> usize {
|
||||||
(self.0 >> 20) & 0xfff
|
(self.0 >> 8) & 0xffffff
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 获取次设备号
|
/// @brief: 获取次设备号
|
||||||
/// @parameter: none
|
/// @parameter: none
|
||||||
/// @return: 次设备号
|
/// @return: 次设备号
|
||||||
pub fn minor(&self) -> usize {
|
pub fn minor(&self) -> usize {
|
||||||
self.0 & 0xfffff
|
self.0 & 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
||||||
@ -211,7 +271,7 @@ impl IdTable {
|
|||||||
/// @parameter None
|
/// @parameter None
|
||||||
/// @return: 设备名
|
/// @return: 设备名
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
return format!("{}:{:?}", self.0, self.1 .0);
|
return format!("{}:{}", self.0, self.1 .0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_number(&self) -> DeviceNumber {
|
pub fn device_number(&self) -> DeviceNumber {
|
||||||
@ -285,24 +345,115 @@ impl From<DeviceState> for u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Device管理器(锁)
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LockedDeviceManager(SpinLock<DeviceManager>);
|
pub struct DeviceKObjType;
|
||||||
|
|
||||||
impl LockedDeviceManager {
|
impl KObjType for DeviceKObjType {
|
||||||
fn new() -> LockedDeviceManager {
|
// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#2307
|
||||||
LockedDeviceManager(SpinLock::new(DeviceManager::new()))
|
fn release(&self, kobj: Arc<dyn KObject>) {
|
||||||
|
let dev = kobj.cast::<dyn Device>().unwrap();
|
||||||
|
/*
|
||||||
|
* Some platform devices are driven without driver attached
|
||||||
|
* and managed resources may have been acquired. Make sure
|
||||||
|
* all resources are released.
|
||||||
|
*
|
||||||
|
* Drivers still can add resources into device after device
|
||||||
|
* is deleted but alive, so release devres here to avoid
|
||||||
|
* possible memory leak.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// todo: 在引入devres之后再实现
|
||||||
|
// devres_release_all(kobj);
|
||||||
|
dev.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
|
||||||
|
Some(&DeviceSysFSOps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct DeviceSysFSOps;
|
||||||
|
|
||||||
|
impl SysFSOps for DeviceSysFSOps {
|
||||||
|
fn store(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return attr.store(kobj, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return attr.show(kobj, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Device管理器
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DeviceManager;
|
||||||
|
|
||||||
|
impl DeviceManager {
|
||||||
|
/// @brief: 创建一个新的设备管理器
|
||||||
|
/// @parameter: None
|
||||||
|
/// @return: DeviceManager实体
|
||||||
|
#[inline]
|
||||||
|
const fn new() -> DeviceManager {
|
||||||
|
return Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 添加设备
|
/// @brief: 添加设备
|
||||||
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
||||||
/// @parameter dev: 设备实例
|
/// @parameter dev: 设备实例
|
||||||
/// @return: None
|
/// @return: None
|
||||||
|
///
|
||||||
|
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#3398
|
||||||
|
///
|
||||||
|
/// todo: 完善错误处理逻辑:如果添加失败,需要将之前添加的内容全部回滚
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn add_device(&self, id_table: IdTable, dev: Arc<dyn Device>) {
|
pub fn add_device(&self, device: Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
let mut device_manager = self.0.lock();
|
// todo: 引入class后,在这里处理与parent相关的逻辑
|
||||||
device_manager.devices.insert(id_table, dev);
|
|
||||||
|
KObjectManager::add_kobj(device.clone() as Arc<dyn KObject>, None).map_err(|e| {
|
||||||
|
kerror!("add device '{:?}' failed: {:?}", device.name(), e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.device_platform_notify(&device);
|
||||||
|
|
||||||
|
self.add_class_symlinks(&device)?;
|
||||||
|
|
||||||
|
self.add_attrs(&device)?;
|
||||||
|
|
||||||
|
bus_add_device(&device)?;
|
||||||
|
|
||||||
|
if device.id_table().device_number().major() != 0 {
|
||||||
|
self.create_file(&device, &DeviceAttrDev)?;
|
||||||
|
|
||||||
|
self.create_sys_dev_entry(&device)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: Notify clients of device addition.This call must come
|
||||||
|
// after dpm_sysfs_add() and before kobject_uevent().
|
||||||
|
// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#3491
|
||||||
|
|
||||||
|
// todo: 发送uevent
|
||||||
|
|
||||||
|
// probe drivers for a new device
|
||||||
|
bus_probe_device(&device);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 卸载设备
|
/// @brief: 卸载设备
|
||||||
@ -310,9 +461,8 @@ impl LockedDeviceManager {
|
|||||||
/// @return: None
|
/// @return: None
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn remove_device(&self, id_table: &IdTable) {
|
pub fn remove_device(&self, _id_table: &IdTable) {
|
||||||
let mut device_manager = self.0.lock();
|
todo!()
|
||||||
device_manager.devices.remove(id_table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 获取设备
|
/// @brief: 获取设备
|
||||||
@ -320,65 +470,205 @@ impl LockedDeviceManager {
|
|||||||
/// @return: 设备实例
|
/// @return: 设备实例
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_device(&self, id_table: &IdTable) -> Option<Arc<dyn Device>> {
|
pub fn find_device_by_idtable(&self, _id_table: &IdTable) -> Option<Arc<dyn Device>> {
|
||||||
let device_manager = self.0.lock();
|
todo!("find_device_by_idtable")
|
||||||
device_manager.devices.get(id_table).cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 获取设备管理器的sys information
|
fn device_platform_notify(&self, dev: &Arc<dyn Device>) {
|
||||||
/// @parameter id_table: 设备标识符,用于唯一标识该设备
|
acpi_device_notify(dev);
|
||||||
/// @return: 设备实例
|
software_node_notify(dev);
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Device管理器
|
fn add_class_symlinks(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
#[derive(Debug, Clone)]
|
// todo: 引入class后,在这里处理与class相关的逻辑
|
||||||
pub struct DeviceManager {
|
// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c#3224
|
||||||
devices: BTreeMap<IdTable, Arc<dyn Device>>, // 所有设备
|
|
||||||
sys_info: Option<Arc<dyn IndexNode>>, // sys information
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DeviceManager {
|
return Ok(());
|
||||||
/// @brief: 创建一个新的设备管理器
|
}
|
||||||
/// @parameter: None
|
|
||||||
/// @return: DeviceManager实体
|
/// 在sysfs中,为指定的设备创建属性文件
|
||||||
#[inline]
|
///
|
||||||
fn new() -> DeviceManager {
|
/// ## 参数
|
||||||
DeviceManager {
|
///
|
||||||
devices: BTreeMap::new(),
|
/// - `dev`: 设备
|
||||||
sys_info: Some(SYS_DEVICES_INODE()),
|
fn add_attrs(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
let kobj_type = dev.kobj_type();
|
||||||
|
if kobj_type.is_none() {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let kobj_type = kobj_type.unwrap();
|
||||||
|
|
||||||
|
let attr_groups = kobj_type.attribute_groups();
|
||||||
|
|
||||||
|
if attr_groups.is_none() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.add_groups(dev, attr_groups.unwrap())?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在sysfs中,为指定的设备创建属性组,以及属性组中的属性文件
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
/// - `attr_groups`: 属性组
|
||||||
|
pub fn add_groups(
|
||||||
|
&self,
|
||||||
|
dev: &Arc<dyn Device>,
|
||||||
|
attr_groups: &'static [&dyn AttributeGroup],
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let dev = dev.clone();
|
||||||
|
let binding = dev.arc_any();
|
||||||
|
let kobj: &Arc<dyn KObject> = binding.downcast_ref().unwrap();
|
||||||
|
return sysfs_instance().create_groups(kobj, attr_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 为设备在sysfs中创建属性文件
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
/// - `attr`: 属性
|
||||||
|
pub fn create_file(
|
||||||
|
&self,
|
||||||
|
dev: &Arc<dyn Device>,
|
||||||
|
attr: &'static dyn Attribute,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
if unlikely(
|
||||||
|
attr.mode().contains(ModeType::S_IRUGO)
|
||||||
|
&& (!attr.support().contains(SysFSOpsSupport::SHOW)),
|
||||||
|
) {
|
||||||
|
kwarn!(
|
||||||
|
"Attribute '{}': read permission without 'show'",
|
||||||
|
attr.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if unlikely(
|
||||||
|
attr.mode().contains(ModeType::S_IWUGO)
|
||||||
|
&& (!attr.support().contains(SysFSOpsSupport::STORE)),
|
||||||
|
) {
|
||||||
|
kwarn!(
|
||||||
|
"Attribute '{}': write permission without 'store'",
|
||||||
|
attr.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let kobj = dev.clone() as Arc<dyn KObject>;
|
||||||
|
|
||||||
|
return sysfs_instance().create_file(&kobj, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在/sys/dev下,或者设备所属的class下,为指定的设备创建链接
|
||||||
|
fn create_sys_dev_entry(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
let target_kobj = self.device_to_dev_kobj(dev);
|
||||||
|
let name = dev.id_table().name();
|
||||||
|
let current_kobj = dev.clone() as Arc<dyn KObject>;
|
||||||
|
return sysfs_instance().create_link(¤t_kobj, &target_kobj, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete symlink for device in `/sys/dev` or `/sys/class/<class_name>`
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn remove_sys_dev_entry(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
let kobj = self.device_to_dev_kobj(dev);
|
||||||
|
let name = dev.id_table().name();
|
||||||
|
return sysfs_instance().remove_link(&kobj, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// device_to_dev_kobj - select a /sys/dev/ directory for the device
|
||||||
|
///
|
||||||
|
/// By default we select char/ for new entries.
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `dev`: 设备
|
||||||
|
fn device_to_dev_kobj(&self, _dev: &Arc<dyn Device>) -> Arc<dyn KObject> {
|
||||||
|
// todo: 处理class的逻辑
|
||||||
|
let kobj = sys_dev_char_kset().as_kobject();
|
||||||
|
return kobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_links_force_bind#1226
|
||||||
|
pub fn device_links_force_bind(&self, _dev: &Arc<dyn Device>) {
|
||||||
|
todo!("device_links_force_bind")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 设备注册
|
/// @brief: 设备注册
|
||||||
/// @parameter: name: 设备名
|
/// @parameter: name: 设备名
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||||
pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
|
pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), SystemError> {
|
||||||
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
|
return device_manager().add_device(device);
|
||||||
match sys_device_register(&device.id_table().name()) {
|
|
||||||
Ok(sys_info) => {
|
|
||||||
device.set_sys_info(Some(sys_info));
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
Err(_) => Err(DeviceError::RegisterError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: 设备卸载
|
/// @brief: 设备卸载
|
||||||
/// @parameter: name: 设备名
|
/// @parameter: name: 设备名
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||||
pub fn device_unregister<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
|
pub fn device_unregister<T: Device>(_device: Arc<T>) {
|
||||||
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
|
// DEVICE_MANAGER.add_device(device.id_table(), device.clone());
|
||||||
match sys_device_unregister(&device.id_table().name()) {
|
// match sys_device_unregister(&device.id_table().name()) {
|
||||||
Ok(_) => {
|
// Ok(_) => {
|
||||||
device.set_sys_info(None);
|
// device.set_inode(None);
|
||||||
return Ok(());
|
// return Ok(());
|
||||||
}
|
// }
|
||||||
Err(_) => Err(DeviceError::RegisterError),
|
// Err(_) => Err(DeviceError::RegisterError),
|
||||||
|
// }
|
||||||
|
todo!("device_unregister")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 设备文件夹下的`dev`文件的属性
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct DeviceAttrDev;
|
||||||
|
|
||||||
|
impl Attribute for DeviceAttrDev {
|
||||||
|
fn mode(&self) -> ModeType {
|
||||||
|
// 0o444
|
||||||
|
return ModeType::S_IRUGO;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(&self, kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||||
|
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
|
||||||
|
kerror!(
|
||||||
|
"Intertrait casting not implemented for kobj: {}",
|
||||||
|
kobj.name()
|
||||||
|
);
|
||||||
|
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(dev.id_table().device_number().into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn support(&self) -> SysFSOpsSupport {
|
||||||
|
SysFSOpsSupport::SHOW
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 设备匹配器
|
||||||
|
///
|
||||||
|
/// 用于匹配设备是否符合某个条件
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `T` - 匹配器的数据类型
|
||||||
|
/// - `data` - 匹配器的数据
|
||||||
|
pub trait DeviceMatcher<T>: Debug {
|
||||||
|
fn match_device(&self, device: &Arc<dyn Device>, data: T) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 用于根据名称匹配设备的匹配器
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DeviceMatchName;
|
||||||
|
|
||||||
|
impl DeviceMatcher<&str> for DeviceMatchName {
|
||||||
|
#[inline]
|
||||||
|
fn match_device(&self, device: &Arc<dyn Device>, data: &str) -> bool {
|
||||||
|
return device.name() == data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
kernel/src/driver/base/firmware.rs
Normal file
26
kernel/src/driver/base/firmware.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
|
use crate::syscall::SystemError;
|
||||||
|
|
||||||
|
use super::kset::KSet;
|
||||||
|
|
||||||
|
/// `/sys/firmware`的kset
|
||||||
|
static mut FIRMWARE_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn sys_firmware_kset() -> Arc<KSet> {
|
||||||
|
unsafe { FIRMWARE_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 初始化`/sys/firmware`的kset
|
||||||
|
pub(super) fn firmware_init() -> Result<(), SystemError> {
|
||||||
|
let firmware_kset = KSet::new("firmware".to_string());
|
||||||
|
firmware_kset
|
||||||
|
.register(None)
|
||||||
|
.expect("register firmware kset failed");
|
||||||
|
unsafe {
|
||||||
|
FIRMWARE_KSET_INSTANCE = Some(firmware_kset);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
26
kernel/src/driver/base/hypervisor.rs
Normal file
26
kernel/src/driver/base/hypervisor.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
|
use crate::syscall::SystemError;
|
||||||
|
|
||||||
|
use super::kset::KSet;
|
||||||
|
|
||||||
|
/// `/sys/hypervisor`的kset
|
||||||
|
static mut HYPERVISOR_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn sys_hypervisor_kset() -> Arc<KSet> {
|
||||||
|
unsafe { HYPERVISOR_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 初始化`/sys/hypervisor`的kset
|
||||||
|
pub(super) fn hypervisor_init() -> Result<(), SystemError> {
|
||||||
|
let hypervisor_kset = KSet::new("hypervisor".to_string());
|
||||||
|
hypervisor_kset
|
||||||
|
.register(None)
|
||||||
|
.expect("register hypervisor kset failed");
|
||||||
|
unsafe {
|
||||||
|
HYPERVISOR_KSET_INSTANCE = Some(hypervisor_kset);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
19
kernel/src/driver/base/init.rs
Normal file
19
kernel/src/driver/base/init.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use crate::syscall::SystemError;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
class::classes_init,
|
||||||
|
device::{bus::buses_init, init::devices_init},
|
||||||
|
firmware::firmware_init,
|
||||||
|
hypervisor::hypervisor_init,
|
||||||
|
platform::platform_bus_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(super) fn driver_init() -> Result<(), SystemError> {
|
||||||
|
devices_init()?;
|
||||||
|
buses_init()?;
|
||||||
|
classes_init()?;
|
||||||
|
firmware_init()?;
|
||||||
|
hypervisor_init()?;
|
||||||
|
platform_bus_init()?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
211
kernel/src/driver/base/kobject.rs
Normal file
211
kernel/src/driver/base/kobject.rs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref};
|
||||||
|
|
||||||
|
use alloc::{
|
||||||
|
string::String,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
use intertrait::CastFromSync;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
filesystem::{
|
||||||
|
kernfs::KernFSInode,
|
||||||
|
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
|
||||||
|
},
|
||||||
|
kerror,
|
||||||
|
libs::{
|
||||||
|
casting::DowncastArc,
|
||||||
|
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
},
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::kset::KSet;
|
||||||
|
|
||||||
|
pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any;
|
||||||
|
|
||||||
|
/// 设置当前kobject对应的sysfs inode(类型为KernFSInode)
|
||||||
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>);
|
||||||
|
|
||||||
|
/// 获取当前kobject对应的sysfs inode(类型为KernFSInode)
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>>;
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>>;
|
||||||
|
|
||||||
|
/// 设置当前kobject的parent kobject(不一定与kset相同)
|
||||||
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>);
|
||||||
|
|
||||||
|
/// 当前kobject属于哪个kset
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>>;
|
||||||
|
|
||||||
|
/// 设置当前kobject所属的kset
|
||||||
|
fn set_kset(&self, kset: Option<Arc<KSet>>);
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
|
||||||
|
|
||||||
|
fn name(&self) -> String;
|
||||||
|
|
||||||
|
fn set_name(&self, name: String);
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState>;
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>;
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, state: KObjectState);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dyn KObject {
|
||||||
|
/// 更新kobject的状态
|
||||||
|
pub fn update_kobj_state(&self, insert: Option<KObjectState>, remove: Option<KObjectState>) {
|
||||||
|
let insert = insert.unwrap_or(KObjectState::empty());
|
||||||
|
let remove = remove.unwrap_or(KObjectState::empty());
|
||||||
|
let mut state = self.kobj_state_mut();
|
||||||
|
*state = (*state | insert) & !remove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DowncastArc for dyn KObject {
|
||||||
|
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait KObjType: Debug {
|
||||||
|
fn release(&self, _kobj: Arc<dyn KObject>) {}
|
||||||
|
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
|
||||||
|
|
||||||
|
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct KObjectState: u32 {
|
||||||
|
const IN_SYSFS = 1 << 0;
|
||||||
|
const ADD_UEVENT_SENT = 1 << 1;
|
||||||
|
const REMOVE_UEVENT_SENT = 1 << 2;
|
||||||
|
const INITIALIZED = 1 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LockedKObjectState(RwLock<KObjectState>);
|
||||||
|
|
||||||
|
impl LockedKObjectState {
|
||||||
|
pub const fn new(state: KObjectState) -> LockedKObjectState {
|
||||||
|
LockedKObjectState(RwLock::new(state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for LockedKObjectState {
|
||||||
|
type Target = RwLock<KObjectState>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait KObjectAttribute: Attribute {
|
||||||
|
fn support(&self) -> SysFSOpsSupport;
|
||||||
|
|
||||||
|
fn show(&self, kobj: &dyn KObject, buf: &mut [u8]) -> Result<usize, SystemError>;
|
||||||
|
fn store(&self, kobj: &dyn KObject, buf: &[u8]) -> Result<usize, SystemError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KObjectSysFSOps;
|
||||||
|
|
||||||
|
impl SysFSOps for KObjectSysFSOps {
|
||||||
|
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
|
||||||
|
return attr.support();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
let r = attr.show(kobj, buf).map_err(|e| {
|
||||||
|
if e == SystemError::EOPNOTSUPP_OR_ENOTSUP {
|
||||||
|
SystemError::EIO
|
||||||
|
} else {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
let r = attr.store(kobj, buf).map_err(|e| {
|
||||||
|
if e == SystemError::EOPNOTSUPP_OR_ENOTSUP {
|
||||||
|
SystemError::EIO
|
||||||
|
} else {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KObjectManager;
|
||||||
|
|
||||||
|
impl KObjectManager {
|
||||||
|
pub fn add_kobj(
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
join_kset: Option<Arc<KSet>>,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
if join_kset.is_some() {
|
||||||
|
let kset = join_kset.unwrap();
|
||||||
|
kset.join(&kobj);
|
||||||
|
// 如果kobject没有parent,那么就将这个kset作为parent
|
||||||
|
if kobj.parent().is_none() {
|
||||||
|
kobj.set_parent(Some(Arc::downgrade(&(kset as Arc<dyn KObject>))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = Self::create_dir(kobj.clone());
|
||||||
|
|
||||||
|
if let Err(e) = r {
|
||||||
|
// https://opengrok.ringotek.cn/xref/linux-6.1.9/lib/kobject.c?r=&mo=10426&fi=394#224
|
||||||
|
if let Some(kset) = kobj.kset() {
|
||||||
|
kset.leave(&kobj);
|
||||||
|
}
|
||||||
|
kobj.set_parent(None);
|
||||||
|
if e == SystemError::EEXIST {
|
||||||
|
kerror!("KObjectManager::add_kobj() failed with error: {e:?}, kobj:{kobj:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
kobj.update_kobj_state(Some(KObjectState::IN_SYSFS), None);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_dir(kobj: Arc<dyn KObject>) -> Result<(), SystemError> {
|
||||||
|
// create dir in sysfs
|
||||||
|
sysfs_instance().create_dir(kobj.clone())?;
|
||||||
|
|
||||||
|
// create default attributes in sysfs
|
||||||
|
if let Some(ktype) = kobj.kobj_type() {
|
||||||
|
let groups = ktype.attribute_groups();
|
||||||
|
if let Some(groups) = groups {
|
||||||
|
let r = sysfs_instance().create_groups(&kobj, groups);
|
||||||
|
if let Err(e) = r {
|
||||||
|
sysfs_instance().remove_dir(&kobj);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
229
kernel/src/driver/base/kset.rs
Normal file
229
kernel/src/driver/base/kset.rs
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
use alloc::{
|
||||||
|
string::String,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
use core::hash::Hash;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
filesystem::{
|
||||||
|
kernfs::KernFSInode,
|
||||||
|
sysfs::{AttributeGroup, SysFSOps},
|
||||||
|
},
|
||||||
|
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::kobject::{
|
||||||
|
KObjType, KObject, KObjectManager, KObjectState, KObjectSysFSOps, LockedKObjectState,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KSet {
|
||||||
|
/// 属于当前kset的kobject
|
||||||
|
kobjects: RwLock<Vec<Weak<dyn KObject>>>,
|
||||||
|
/// 节点的一些信息
|
||||||
|
inner: RwLock<InnerKSet>,
|
||||||
|
/// kobject的状态
|
||||||
|
kobj_state: LockedKObjectState,
|
||||||
|
/// 与父节点有关的一些信息
|
||||||
|
parent_data: RwLock<KSetParentData>,
|
||||||
|
self_ref: Weak<KSet>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for KSet {
|
||||||
|
fn hash<H: ~const core::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.self_ref.as_ptr().hash(state);
|
||||||
|
self.inner.read().name.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::cmp::Eq for KSet {}
|
||||||
|
|
||||||
|
impl core::cmp::PartialEq for KSet {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.self_ref.as_ptr() == other.self_ref.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KSet {
|
||||||
|
pub fn new(name: String) -> Arc<Self> {
|
||||||
|
let r = Self {
|
||||||
|
kobjects: RwLock::new(Vec::new()),
|
||||||
|
inner: RwLock::new(InnerKSet::new(name)),
|
||||||
|
kobj_state: LockedKObjectState::new(KObjectState::empty()),
|
||||||
|
parent_data: RwLock::new(KSetParentData::new(None, None)),
|
||||||
|
self_ref: Weak::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let r = Arc::new(r);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let p = r.as_ref() as *const Self as *mut Self;
|
||||||
|
(*p).self_ref = Arc::downgrade(&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建一个kset,并且设置它的父亲为parent_kobj。然后把这个kset注册到sysfs
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - name: kset的名字
|
||||||
|
/// - parent_kobj: 父亲kobject
|
||||||
|
/// - join_kset: 如果不为None,那么这个kset会加入到join_kset中
|
||||||
|
pub fn new_and_add(
|
||||||
|
name: String,
|
||||||
|
parent_kobj: Option<Arc<dyn KObject>>,
|
||||||
|
join_kset: Option<Arc<KSet>>,
|
||||||
|
) -> Result<Arc<Self>, SystemError> {
|
||||||
|
let kset = KSet::new(name);
|
||||||
|
if let Some(parent_kobj) = parent_kobj {
|
||||||
|
kset.set_parent(Some(Arc::downgrade(&parent_kobj)));
|
||||||
|
}
|
||||||
|
kset.register(join_kset)?;
|
||||||
|
return Ok(kset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register(&self, join_kset: Option<Arc<KSet>>) -> Result<(), SystemError> {
|
||||||
|
return KObjectManager::add_kobj(self.self_ref.upgrade().unwrap(), join_kset);
|
||||||
|
// todo: 引入uevent之后,发送uevent
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 把一个kobject加入到当前kset中。
|
||||||
|
///
|
||||||
|
/// 该函数不会修改kobj的parent,需要调用者自己视情况修改。
|
||||||
|
///
|
||||||
|
/// ## Panic
|
||||||
|
///
|
||||||
|
/// 这个kobject的kset必须是None,否则会panic
|
||||||
|
pub fn join(&self, kobj: &Arc<dyn KObject>) {
|
||||||
|
assert!(kobj.kset().is_none());
|
||||||
|
kobj.set_kset(self.self_ref.upgrade());
|
||||||
|
self.kobjects.write().push(Arc::downgrade(&kobj));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 把一个kobject从当前kset中移除。
|
||||||
|
pub fn leave(&self, kobj: &Arc<dyn KObject>) {
|
||||||
|
let mut kobjects = self.kobjects.write();
|
||||||
|
let index = kobjects.iter().position(|x| {
|
||||||
|
if let Some(x) = x.upgrade() {
|
||||||
|
return Arc::ptr_eq(&x, kobj);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if let Some(index) = index {
|
||||||
|
let x = kobjects.remove(index);
|
||||||
|
let x = x.upgrade().unwrap();
|
||||||
|
drop(kobjects);
|
||||||
|
x.set_kset(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 清除所有已经被释放的kobject
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn cleanup_weak(&self) {
|
||||||
|
let mut kobjects = self.kobjects.write();
|
||||||
|
kobjects.drain_filter(|x| x.upgrade().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_kobject(&self) -> Arc<dyn KObject> {
|
||||||
|
return self.self_ref.upgrade().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KObject for KSet {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
self.inner.read().kern_inode.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||||
|
self.inner.write().kern_inode = inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
self.parent_data.read().parent.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||||
|
self.parent_data.write().parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
self.kobj_state.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
self.kobj_state.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
Some(&KSetKObjType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
self.parent_data.read().kset.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||||
|
self.parent_data.write().kset = kset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
return self.inner.read().name.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, name: String) {
|
||||||
|
self.inner.write().name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, state: KObjectState) {
|
||||||
|
*self.kobj_state.write() = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct KSetParentData {
|
||||||
|
parent: Option<Weak<dyn KObject>>,
|
||||||
|
kset: Option<Arc<KSet>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KSetParentData {
|
||||||
|
fn new(parent: Option<Weak<dyn KObject>>, kset: Option<Arc<KSet>>) -> Self {
|
||||||
|
Self { parent, kset }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InnerKSet {
|
||||||
|
kern_inode: Option<Arc<KernFSInode>>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InnerKSet {
|
||||||
|
fn new(name: String) -> Self {
|
||||||
|
Self {
|
||||||
|
kern_inode: None,
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KSetKObjType;
|
||||||
|
|
||||||
|
impl KObjType for KSetKObjType {
|
||||||
|
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
|
||||||
|
Some(&KObjectSysFSOps)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use super::device::{mkdev, DeviceNumber, KObject};
|
use super::{
|
||||||
|
device::{mkdev, DeviceNumber},
|
||||||
|
kobject::KObject,
|
||||||
|
};
|
||||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||||
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
|
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
|
||||||
|
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod c_adapter;
|
||||||
pub mod char;
|
pub mod char;
|
||||||
|
pub mod class;
|
||||||
pub mod device;
|
pub mod device;
|
||||||
|
pub mod firmware;
|
||||||
|
pub mod hypervisor;
|
||||||
|
pub mod init;
|
||||||
|
pub mod kobject;
|
||||||
|
pub mod kset;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod platform;
|
pub mod platform;
|
||||||
|
pub mod subsys;
|
||||||
|
pub mod swnode;
|
||||||
|
@ -1,24 +1,34 @@
|
|||||||
use super::device::{
|
use self::{platform_device::PlatformBusDevice, subsys::PlatformBus};
|
||||||
bus::{bus_driver_register, bus_register, Bus, BusDriver, BusState},
|
|
||||||
driver::DriverError,
|
use super::{
|
||||||
Device, DeviceError, DeviceNumber, DevicePrivateData, DeviceResource, DeviceType, IdTable,
|
device::{
|
||||||
KObject,
|
bus::{bus_register, Bus, BusState},
|
||||||
};
|
device_unregister, sys_devices_kset, DeviceNumber, DevicePrivateData, IdTable,
|
||||||
use crate::{
|
},
|
||||||
driver::Driver, filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError,
|
kobject::KObject,
|
||||||
};
|
|
||||||
use alloc::{
|
|
||||||
collections::{BTreeMap, BTreeSet},
|
|
||||||
string::ToString,
|
|
||||||
sync::Arc,
|
|
||||||
vec::Vec,
|
|
||||||
};
|
};
|
||||||
|
use crate::{driver::base::device::device_register, syscall::SystemError};
|
||||||
|
use alloc::{collections::BTreeSet, string::ToString, sync::Arc, vec::Vec};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use platform_device::PlatformDevice;
|
|
||||||
use platform_driver::PlatformDriver;
|
|
||||||
|
|
||||||
pub mod platform_device;
|
pub mod platform_device;
|
||||||
pub mod platform_driver;
|
pub mod platform_driver;
|
||||||
|
pub mod subsys;
|
||||||
|
|
||||||
|
static mut PLATFORM_BUS_DEVICE: Option<Arc<PlatformBusDevice>> = None;
|
||||||
|
static mut PLATFORM_BUS: Option<Arc<PlatformBus>> = None;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn platform_bus_device() -> Arc<PlatformBusDevice> {
|
||||||
|
unsafe { PLATFORM_BUS_DEVICE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn platform_bus() -> Arc<PlatformBus> {
|
||||||
|
unsafe { PLATFORM_BUS.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief: platform总线匹配表
|
/// @brief: platform总线匹配表
|
||||||
/// 总线上的设备和驱动都存在一份匹配表
|
/// 总线上的设备和驱动都存在一份匹配表
|
||||||
@ -55,317 +65,34 @@ impl CompatibleTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct LockedPlatformBusDriver(SpinLock<PlatformBusDriver>);
|
|
||||||
|
|
||||||
impl LockedPlatformBusDriver {
|
|
||||||
/// @brief: 创建一个platform总线加锁驱动,该驱动用于匹配plaform总线
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platfor总线驱动
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new() -> LockedPlatformBusDriver {
|
|
||||||
LockedPlatformBusDriver(SpinLock::new(PlatformBusDriver::new()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取该驱动的匹配表
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: 驱动的匹配表
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_compatible_table(&self) -> CompatibleTable {
|
|
||||||
CompatibleTable::new(vec!["platform"])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 根据设备标识符获取platform总线上的设备
|
|
||||||
/// @parameter id_table: 设备标识符
|
|
||||||
/// @return: 总线上的设备
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_device(&self, id_table: &IdTable) -> Option<Arc<dyn PlatformDevice>> {
|
|
||||||
let device_map = &self.0.lock().devices;
|
|
||||||
return device_map.get(id_table).cloned();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 根据设备驱动标识符获取platform总线上的驱动
|
|
||||||
/// @parameter id_table: 设备驱动标识符
|
|
||||||
/// @return: 总线上的驱动
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_driver(&self, id_table: &IdTable) -> Option<Arc<dyn PlatformDriver>> {
|
|
||||||
let driver_map = &self.0.lock().drivers;
|
|
||||||
return driver_map.get(id_table).cloned();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注册platform类型驱动
|
|
||||||
/// @parameter driver: platform类型驱动,该驱动需要实现PlatformDriver trait
|
|
||||||
/// @return: 注册成功,返回Ok(()),,注册失败,返回BusError类型
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn register_platform_driver(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), DeviceError> {
|
|
||||||
let id_table = driver.id_table();
|
|
||||||
|
|
||||||
let drivers = &mut self.0.lock().drivers;
|
|
||||||
// 如果存在同类型的驱动,返回错误
|
|
||||||
if drivers.contains_key(&id_table) {
|
|
||||||
return Err(DeviceError::DriverExists);
|
|
||||||
} else {
|
|
||||||
drivers.insert(id_table.clone(), driver.clone());
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 卸载platform类型驱动
|
|
||||||
/// @parameter driver: platform类型驱动,该驱动需挂载在plaform总线之上
|
|
||||||
/// @return: None
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline]
|
|
||||||
fn unregister_platform_driver(
|
|
||||||
&mut self,
|
|
||||||
driver: Arc<dyn PlatformDriver>,
|
|
||||||
) -> Result<(), DeviceError> {
|
|
||||||
let id_table = driver.id_table();
|
|
||||||
self.0.lock().drivers.remove(&id_table);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注册platform类型设备
|
|
||||||
/// @parameter driver: platform类型设备,该驱动需要实现PlatformDevice trait
|
|
||||||
/// @return: 注册成功,返回Ok(()),,注册失败,返回BusError类型
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn register_platform_device(
|
|
||||||
&mut self,
|
|
||||||
device: Arc<dyn PlatformDevice>,
|
|
||||||
) -> Result<(), DeviceError> {
|
|
||||||
let id_table = device.id_table();
|
|
||||||
|
|
||||||
let devices = &mut self.0.lock().devices;
|
|
||||||
if devices.contains_key(&id_table) {
|
|
||||||
return Err(DeviceError::DeviceExists);
|
|
||||||
} else {
|
|
||||||
devices.insert(id_table.clone(), device.clone());
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 卸载platform类型设备
|
|
||||||
/// @parameter device: platform类型设备,该驱设备需挂载在plaform总线之上
|
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn unregister_platform_device(&mut self, device: Arc<dyn PlatformDevice>) {
|
|
||||||
let id_table = device.id_table();
|
|
||||||
self.0.lock().devices.remove(&id_table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: platform总线驱动
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct PlatformBusDriver {
|
|
||||||
drivers: BTreeMap<IdTable, Arc<dyn PlatformDriver>>, // 总线上所有驱动
|
|
||||||
devices: BTreeMap<IdTable, Arc<dyn PlatformDevice>>, // 总线上所有设备
|
|
||||||
sys_info: Option<Arc<dyn IndexNode>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PlatformBusDriver {
|
|
||||||
/// @brief: 创建一个platform总线驱动,该驱动用于匹配plaform总线
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platfor总线驱动
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
drivers: BTreeMap::new(),
|
|
||||||
devices: BTreeMap::new(),
|
|
||||||
sys_info: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 为PlatformBusDriver实现Driver trait
|
|
||||||
impl Driver for LockedPlatformBusDriver {
|
|
||||||
#[inline]
|
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn id_table(&self) -> IdTable {
|
|
||||||
return IdTable::new("PlatformBusDriver".to_string(), DeviceNumber::new(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>) {
|
|
||||||
self.0.lock().sys_info = sys_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load(
|
|
||||||
&self,
|
|
||||||
_data: DevicePrivateData,
|
|
||||||
_resource: Option<DeviceResource>,
|
|
||||||
) -> Result<Arc<dyn Device>, DriverError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 为PlatformBusDriver实现BusDriver trait
|
|
||||||
impl BusDriver for LockedPlatformBusDriver {
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
if self.0.lock().devices.is_empty() && self.0.lock().drivers.is_empty() {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KObject for LockedPlatformBusDriver {}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct LockedPlatform(SpinLock<Platform>);
|
|
||||||
|
|
||||||
impl LockedPlatform {
|
|
||||||
/// @brief: 创建一个加锁的platform总线实例
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platform总线实例
|
|
||||||
pub fn new(data: DevicePrivateData) -> LockedPlatform {
|
|
||||||
LockedPlatform(SpinLock::new(Platform::new(data)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取总线的匹配表
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platform总线匹配表
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn compatible_table(&self) -> CompatibleTable {
|
|
||||||
CompatibleTable::new(vec!["platform"])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 判断总线是否初始化
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: 已初始化,返回true,否则,返回false
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn is_initialized(&self) -> bool {
|
|
||||||
let state = self.0.lock().state;
|
|
||||||
match state {
|
|
||||||
BusState::Initialized => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 设置总线状态
|
|
||||||
/// @parameter set_state: 总线状态BusState
|
|
||||||
/// @return: None
|
|
||||||
#[inline]
|
|
||||||
fn set_state(&self, set_state: BusState) {
|
|
||||||
let state = &mut self.0.lock().state;
|
|
||||||
*state = set_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 获取总线状态
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: 总线状态
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn get_state(&self) -> BusState {
|
|
||||||
let state = self.0.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总线
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Platform {
|
|
||||||
_data: DevicePrivateData,
|
|
||||||
state: BusState, // 总线状态
|
|
||||||
sys_info: Option<Arc<dyn IndexNode>>, // 总线sys information
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: platform方法集
|
|
||||||
impl Platform {
|
|
||||||
/// @brief: 创建一个platform总线实例
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platform总线实例
|
|
||||||
pub fn new(_data: DevicePrivateData) -> Self {
|
|
||||||
Self {
|
|
||||||
_data,
|
|
||||||
state: BusState::NotInitialized,
|
|
||||||
sys_info: Option::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 为Platform实现Device trait,platform总线也是一种设备,属于总线设备类型
|
|
||||||
impl Device for LockedPlatform {
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn dev_type(&self) -> DeviceType {
|
|
||||||
return DeviceType::Bus;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn id_table(&self) -> IdTable {
|
|
||||||
IdTable::new("platform".to_string(), DeviceNumber::new(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>) {
|
|
||||||
self.0.lock().sys_info = sys_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 为Platform实现Bus trait,platform总线是一种总线设备
|
|
||||||
impl Bus for LockedPlatform {}
|
|
||||||
|
|
||||||
impl KObject for LockedPlatform {}
|
|
||||||
|
|
||||||
/// @brief: 初始化platform总线
|
/// @brief: 初始化platform总线
|
||||||
/// @parameter: None
|
/// @parameter: None
|
||||||
/// @return: None
|
/// @return: None
|
||||||
|
///
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=platform_bus_init#1511
|
||||||
pub fn platform_bus_init() -> Result<(), SystemError> {
|
pub fn platform_bus_init() -> Result<(), SystemError> {
|
||||||
let platform_driver: Arc<LockedPlatformBusDriver> = Arc::new(LockedPlatformBusDriver::new());
|
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
||||||
let platform_device: Arc<LockedPlatform> =
|
DevicePrivateData::new(
|
||||||
Arc::new(LockedPlatform::new(DevicePrivateData::new(
|
|
||||||
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
||||||
None,
|
None,
|
||||||
CompatibleTable::new(vec!["platform"]),
|
CompatibleTable::new(vec!["platform"]),
|
||||||
BusState::NotInitialized.into(),
|
BusState::NotInitialized.into(),
|
||||||
)));
|
),
|
||||||
bus_register(platform_device.clone()).map_err(|e| e.into())?;
|
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
||||||
platform_device.set_state(BusState::Initialized);
|
);
|
||||||
//platform_device.set_driver(Some(platform_driver.clone()));
|
unsafe { PLATFORM_BUS_DEVICE = Some(platform_device.clone()) };
|
||||||
bus_driver_register(platform_driver.clone()).map_err(|e| e.into())?;
|
// 注册到/sys/devices下
|
||||||
|
device_register(platform_device.clone())?;
|
||||||
|
|
||||||
return Ok(());
|
let paltform_bus = PlatformBus::new();
|
||||||
|
// 注册到/sys/bus下
|
||||||
|
let r = bus_register(paltform_bus.clone() as Arc<dyn Bus>);
|
||||||
|
if r.is_err() {
|
||||||
|
device_unregister(platform_device.clone());
|
||||||
|
unsafe { PLATFORM_BUS_DEVICE = None };
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
unsafe { PLATFORM_BUS = Some(paltform_bus) };
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,26 @@
|
|||||||
use crate::driver::base::device::Device;
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
driver::{
|
||||||
|
base::{
|
||||||
|
device::{
|
||||||
|
bus::{Bus, BusState},
|
||||||
|
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||||
|
},
|
||||||
|
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||||
|
kset::KSet,
|
||||||
|
},
|
||||||
|
Driver,
|
||||||
|
},
|
||||||
|
filesystem::kernfs::KernFSInode,
|
||||||
|
libs::{
|
||||||
|
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
spinlock::SpinLock,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{super::device::DeviceState, CompatibleTable};
|
use super::{super::device::DeviceState, CompatibleTable};
|
||||||
|
|
||||||
@ -16,3 +38,196 @@ pub trait PlatformDevice: Device {
|
|||||||
/// @return: None
|
/// @return: None
|
||||||
fn set_state(&self, set_state: DeviceState);
|
fn set_state(&self, set_state: DeviceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cast_to([sync] Device)]
|
||||||
|
pub struct PlatformBusDevice {
|
||||||
|
inner: SpinLock<InnerPlatformBusDevice>,
|
||||||
|
kobj_state: LockedKObjectState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlatformBusDevice {
|
||||||
|
/// @brief: 创建一个加锁的platform总线实例
|
||||||
|
/// @parameter: None
|
||||||
|
/// @return: platform总线实例
|
||||||
|
pub fn new(
|
||||||
|
data: DevicePrivateData,
|
||||||
|
parent: Option<Weak<dyn KObject>>,
|
||||||
|
) -> Arc<PlatformBusDevice> {
|
||||||
|
return Arc::new(PlatformBusDevice {
|
||||||
|
inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)),
|
||||||
|
kobj_state: LockedKObjectState::new(KObjectState::empty()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 获取总线的匹配表
|
||||||
|
/// @parameter: None
|
||||||
|
/// @return: platform总线匹配表
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn compatible_table(&self) -> CompatibleTable {
|
||||||
|
CompatibleTable::new(vec!["platform"])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 判断总线是否初始化
|
||||||
|
/// @parameter: None
|
||||||
|
/// @return: 已初始化,返回true,否则,返回false
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn is_initialized(&self) -> bool {
|
||||||
|
let state = self.inner.lock().state;
|
||||||
|
match state {
|
||||||
|
BusState::Initialized => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 设置总线状态
|
||||||
|
/// @parameter set_state: 总线状态BusState
|
||||||
|
/// @return: None
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn set_state(&self, set_state: BusState) {
|
||||||
|
let state = &mut self.inner.lock().state;
|
||||||
|
*state = set_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 获取总线状态
|
||||||
|
/// @parameter: None
|
||||||
|
/// @return: 总线状态
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn get_state(&self) -> BusState {
|
||||||
|
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 {
|
||||||
|
name: String,
|
||||||
|
data: DevicePrivateData,
|
||||||
|
state: BusState, // 总线状态
|
||||||
|
parent: Option<Weak<dyn KObject>>, // 总线的父对象
|
||||||
|
|
||||||
|
kernfs_inode: Option<Arc<KernFSInode>>,
|
||||||
|
/// 当前设备挂载到的总线
|
||||||
|
bus: Option<Arc<dyn Bus>>,
|
||||||
|
/// 当前设备已经匹配的驱动
|
||||||
|
driver: Option<Arc<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,
|
||||||
|
name: "platform".to_string(),
|
||||||
|
state: BusState::NotInitialized,
|
||||||
|
parent,
|
||||||
|
kernfs_inode: None,
|
||||||
|
bus: None,
|
||||||
|
driver: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KObject for PlatformBusDevice {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
self.inner.lock().parent.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
self.inner.lock().kernfs_inode.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||||
|
self.inner.lock().kernfs_inode = inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.inner.lock().name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, name: String) {
|
||||||
|
self.inner.lock().name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||||
|
self.inner.lock().parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief: 为Platform实现Device trait,platform总线也是一种设备,属于总线设备类型
|
||||||
|
impl Device for PlatformBusDevice {
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn dev_type(&self) -> DeviceType {
|
||||||
|
return DeviceType::Bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn id_table(&self) -> IdTable {
|
||||||
|
IdTable::new("platform".to_string(), DeviceNumber::new(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||||
|
self.inner.lock().bus.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
|
self.inner.lock().driver.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_dead(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_driver(&self, driver: Option<Arc<dyn Driver>>) {
|
||||||
|
self.inner.lock().driver = driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
65
kernel/src/driver/base/platform/subsys.rs
Normal file
65
kernel/src/driver/base/platform/subsys.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
driver::base::{device::bus::Bus, kobject::KObject, subsys::SubSysPrivate},
|
||||||
|
filesystem::{
|
||||||
|
sysfs::{Attribute, AttributeGroup},
|
||||||
|
vfs::syscall::ModeType,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PlatformBus {
|
||||||
|
private: SubSysPrivate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlatformBus {
|
||||||
|
pub fn new() -> Arc<Self> {
|
||||||
|
let w: Weak<Self> = Weak::new();
|
||||||
|
let private = SubSysPrivate::new("platform".to_string(), w, &[]);
|
||||||
|
let bus = Arc::new(Self { private });
|
||||||
|
bus.subsystem()
|
||||||
|
.set_bus(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>)));
|
||||||
|
|
||||||
|
return bus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bus for PlatformBus {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
return "platform".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_name(&self) -> String {
|
||||||
|
return self.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||||
|
return &[&PlatformDeviceAttrGroup];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subsystem(&self) -> &SubSysPrivate {
|
||||||
|
return &self.private;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PlatformDeviceAttrGroup;
|
||||||
|
|
||||||
|
impl AttributeGroup for PlatformDeviceAttrGroup {
|
||||||
|
fn name(&self) -> Option<&str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs(&self) -> &[&'static dyn Attribute] {
|
||||||
|
// todo: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?r=&mo=38425&fi=1511#1311
|
||||||
|
return &[];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_visible(&self, _kobj: Arc<dyn KObject>, attr: &dyn Attribute) -> Option<ModeType> {
|
||||||
|
return Some(attr.mode());
|
||||||
|
}
|
||||||
|
}
|
150
kernel/src/driver/base/subsys.rs
Normal file
150
kernel/src/driver/base/subsys.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use core::{
|
||||||
|
fmt::Debug,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
|
use alloc::{
|
||||||
|
string::String,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
driver::Driver,
|
||||||
|
libs::{notifier::AtomicNotifierChain, rwlock::RwLock, spinlock::SpinLock},
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
device::{
|
||||||
|
bus::{Bus, BusNotifyEvent},
|
||||||
|
Device,
|
||||||
|
},
|
||||||
|
kset::KSet,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 一个用于存储bus/class的驱动核心部分的信息的结构体
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SubSysPrivate {
|
||||||
|
/// 用于定义这个子系统的kset
|
||||||
|
subsys: Arc<KSet>,
|
||||||
|
ksets: RwLock<SubSysKSets>,
|
||||||
|
/// 指向拥有当前结构体的`dyn bus`对象的弱引用
|
||||||
|
bus: SpinLock<Weak<dyn Bus>>,
|
||||||
|
drivers_autoprobe: AtomicBool,
|
||||||
|
/// 当前总线上的所有设备
|
||||||
|
devices: RwLock<Vec<Weak<dyn Device>>>,
|
||||||
|
/// 当前总线上的所有驱动
|
||||||
|
drivers: RwLock<Vec<Weak<dyn Driver>>>,
|
||||||
|
interfaces: &'static [&'static dyn SubSysInterface],
|
||||||
|
bus_notifier: AtomicNotifierChain<BusNotifyEvent, Arc<dyn Device>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SubSysKSets {
|
||||||
|
/// 子系统的`devices`目录
|
||||||
|
devices_kset: Option<Arc<KSet>>,
|
||||||
|
/// 子系统的`drivers`目录
|
||||||
|
drivers_kset: Option<Arc<KSet>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubSysKSets {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
return Self {
|
||||||
|
devices_kset: None,
|
||||||
|
drivers_kset: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubSysPrivate {
|
||||||
|
pub fn new(
|
||||||
|
name: String,
|
||||||
|
bus: Weak<dyn Bus>,
|
||||||
|
interfaces: &'static [&'static dyn SubSysInterface],
|
||||||
|
) -> Self {
|
||||||
|
let subsys = KSet::new(name);
|
||||||
|
return Self {
|
||||||
|
subsys,
|
||||||
|
ksets: RwLock::new(SubSysKSets::new()),
|
||||||
|
drivers_autoprobe: AtomicBool::new(false),
|
||||||
|
bus: SpinLock::new(bus),
|
||||||
|
devices: RwLock::new(Vec::new()),
|
||||||
|
drivers: RwLock::new(Vec::new()),
|
||||||
|
interfaces,
|
||||||
|
bus_notifier: AtomicNotifierChain::new(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subsys(&self) -> Arc<KSet> {
|
||||||
|
return self.subsys.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn bus(&self) -> Weak<dyn Bus> {
|
||||||
|
return self.bus.lock().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_bus(&self, bus: Weak<dyn Bus>) {
|
||||||
|
*self.bus.lock() = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn devices(&self) -> &RwLock<Vec<Weak<dyn Device>>> {
|
||||||
|
return &self.devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drivers(&self) -> &RwLock<Vec<Weak<dyn Driver>>> {
|
||||||
|
return &self.drivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drivers_autoprobe(&self) -> bool {
|
||||||
|
return self.drivers_autoprobe.load(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_drivers_autoprobe(&self, drivers_autoprobe: bool) {
|
||||||
|
self.drivers_autoprobe
|
||||||
|
.store(drivers_autoprobe, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline]
|
||||||
|
pub fn devices_kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
return self.ksets.read().devices_kset.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline]
|
||||||
|
pub fn set_devices_kset(&self, devices_kset: Arc<KSet>) {
|
||||||
|
self.ksets.write().devices_kset = Some(devices_kset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline]
|
||||||
|
pub fn drivers_kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
return self.ksets.read().drivers_kset.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_drivers_kset(&self, drivers_kset: Arc<KSet>) {
|
||||||
|
self.ksets.write().drivers_kset = Some(drivers_kset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bus_notifier(&self) -> &AtomicNotifierChain<BusNotifyEvent, Arc<dyn Device>> {
|
||||||
|
return &self.bus_notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] {
|
||||||
|
return self.interfaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device.h#63
|
||||||
|
pub trait SubSysInterface: Debug + Send + Sync {
|
||||||
|
fn name(&self) -> &str;
|
||||||
|
fn bus(&self) -> Option<Weak<dyn Bus>>;
|
||||||
|
fn set_bus(&self, bus: Option<Weak<dyn Bus>>);
|
||||||
|
fn add_device(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
fn remove_device(&self, device: &Arc<dyn Device>);
|
||||||
|
}
|
8
kernel/src/driver/base/swnode.rs
Normal file
8
kernel/src/driver/base/swnode.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
|
use super::device::Device;
|
||||||
|
|
||||||
|
pub fn software_node_notify(_dev: &Arc<dyn Device>) {
|
||||||
|
// todo: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/swnode.c?fi=software_node_notify#1120
|
||||||
|
return;
|
||||||
|
}
|
@ -2,12 +2,18 @@ use super::{_port, hba::HbaCmdTable, virt_2_phys};
|
|||||||
use crate::driver::base::block::block_device::{BlockDevice, BlockId};
|
use crate::driver::base::block::block_device::{BlockDevice, BlockId};
|
||||||
use crate::driver::base::block::disk_info::Partition;
|
use crate::driver::base::block::disk_info::Partition;
|
||||||
use crate::driver::base::block::SeekFrom;
|
use crate::driver::base::block::SeekFrom;
|
||||||
use crate::driver::base::device::{Device, DeviceType, KObject};
|
use crate::driver::base::device::bus::Bus;
|
||||||
|
use crate::driver::base::device::{Device, DeviceType, IdTable};
|
||||||
|
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
||||||
|
use crate::driver::base::kset::KSet;
|
||||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||||
|
use crate::driver::Driver;
|
||||||
|
use crate::filesystem::kernfs::KernFSInode;
|
||||||
use crate::filesystem::mbr::MbrDiskPartionTable;
|
use crate::filesystem::mbr::MbrDiskPartionTable;
|
||||||
use crate::include::bindings::bindings::verify_area;
|
use crate::include::bindings::bindings::verify_area;
|
||||||
|
|
||||||
use crate::kdebug;
|
use crate::kdebug;
|
||||||
|
use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
|
||||||
use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
|
use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
|
||||||
use crate::mm::phys_2_virt;
|
use crate::mm::phys_2_virt;
|
||||||
use crate::syscall::SystemError;
|
use crate::syscall::SystemError;
|
||||||
@ -431,27 +437,83 @@ impl LockedAhciDisk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KObject for LockedAhciDisk {}
|
impl KObject for LockedAhciDisk {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, _state: KObjectState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> alloc::string::String {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: alloc::string::String) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Device for LockedAhciDisk {
|
impl Device for LockedAhciDisk {
|
||||||
fn dev_type(&self) -> DeviceType {
|
fn dev_type(&self) -> DeviceType {
|
||||||
return DeviceType::Block;
|
return DeviceType::Block;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
fn id_table(&self) -> IdTable {
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id_table(&self) -> crate::driver::base::device::IdTable {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sys_info(&self, _sys_info: Option<Arc<dyn crate::filesystem::vfs::IndexNode>>) {
|
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||||
todo!()
|
todo!("LockedAhciDisk::bus()")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn crate::filesystem::vfs::IndexNode>> {
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
todo!()
|
todo!("LockedAhciDisk::driver()")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_dead(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
|
||||||
|
todo!("LockedAhciDisk::set_driver()")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,20 +14,16 @@ use core::fmt::Debug;
|
|||||||
|
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
use crate::filesystem::vfs::IndexNode;
|
|
||||||
|
|
||||||
use self::base::{
|
use self::base::{
|
||||||
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||||
|
kobject::KObject,
|
||||||
platform::CompatibleTable,
|
platform::CompatibleTable,
|
||||||
};
|
};
|
||||||
pub trait Driver: Sync + Send + Debug {
|
pub trait Driver: Sync + Send + Debug + KObject {
|
||||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
|
|
||||||
|
|
||||||
//对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表
|
|
||||||
|
|
||||||
/// @brief: 获取驱动匹配表
|
/// @brief: 获取驱动匹配表
|
||||||
/// @parameter: None
|
/// @parameter: None
|
||||||
/// @return: 驱动匹配表
|
/// @return: 驱动匹配表
|
||||||
|
/// 对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表
|
||||||
fn compatible_table(&self) -> CompatibleTable {
|
fn compatible_table(&self) -> CompatibleTable {
|
||||||
//TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除
|
//TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除
|
||||||
return CompatibleTable::new(vec!["unknown"]);
|
return CompatibleTable::new(vec!["unknown"]);
|
||||||
@ -56,15 +52,4 @@ pub trait Driver: Sync + Send + Debug {
|
|||||||
/// @parameter: None
|
/// @parameter: None
|
||||||
/// @return: 该驱动驱动唯一标识符
|
/// @return: 该驱动驱动唯一标识符
|
||||||
fn id_table(&self) -> IdTable;
|
fn id_table(&self) -> IdTable;
|
||||||
|
|
||||||
// 考虑到很多驱动并不需要存储在系统中,只需要当工具人就可以了,因此 SysINode 是可选的
|
|
||||||
/// @brief: 设置驱动的sys information
|
|
||||||
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
|
|
||||||
/// @return: 驱动实例
|
|
||||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>);
|
|
||||||
|
|
||||||
/// @brief: 获取驱动的sys information
|
|
||||||
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
|
|
||||||
/// @return: 驱动实例
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>>;
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
base::device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
base::{
|
||||||
|
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||||
|
kobject::KObject,
|
||||||
|
},
|
||||||
virtio::virtio_impl::HalImpl,
|
virtio::virtio_impl::HalImpl,
|
||||||
Driver,
|
Driver,
|
||||||
},
|
},
|
||||||
@ -231,20 +234,17 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
|
|||||||
let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
||||||
let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
|
let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
|
||||||
let iface = VirtioInterface::new(driver);
|
let iface = VirtioInterface::new(driver);
|
||||||
|
let name = iface.name.clone();
|
||||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||||
NET_DRIVERS.write().insert(iface.nic_id(), iface.clone());
|
NET_DRIVERS.write().insert(iface.nic_id(), iface.clone());
|
||||||
kinfo!(
|
kinfo!(
|
||||||
"Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
|
"Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
|
||||||
iface.name(),
|
name,
|
||||||
mac
|
mac
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> Driver for VirtioInterface<T> {
|
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
||||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -260,17 +260,9 @@ impl<T: Transport> Driver for VirtioInterface<T> {
|
|||||||
fn id_table(&self) -> IdTable {
|
fn id_table(&self) -> IdTable {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sys_info(&self, _sys_info: Option<Arc<dyn crate::filesystem::vfs::IndexNode>>) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn crate::filesystem::vfs::IndexNode>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> NetDriver for VirtioInterface<T> {
|
impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
||||||
fn mac(&self) -> smoltcp::wire::EthernetAddress {
|
fn mac(&self) -> smoltcp::wire::EthernetAddress {
|
||||||
let mac: [u8; 6] = self.driver.inner.lock().mac_address();
|
let mac: [u8; 6] = self.driver.inner.lock().mac_address();
|
||||||
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
||||||
@ -327,6 +319,64 @@ impl<T: Transport> NetDriver for VirtioInterface<T> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Transport + 'static> KObject for VirtioInterface<T> {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: String) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(
|
||||||
|
&self,
|
||||||
|
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(
|
||||||
|
&self,
|
||||||
|
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 向编译器保证,VirtioNICDriver在线程之间是安全的.
|
// 向编译器保证,VirtioNICDriver在线程之间是安全的.
|
||||||
// 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
|
// 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
|
||||||
// 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
|
// 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
|
||||||
|
@ -3,9 +3,11 @@ use crate::{
|
|||||||
base::{
|
base::{
|
||||||
char::CharDevice,
|
char::CharDevice,
|
||||||
device::{
|
device::{
|
||||||
driver::DriverError, Device, DeviceError, DeviceNumber, DevicePrivateData,
|
bus::Bus, driver::DriverError, Device, DeviceError, DeviceNumber,
|
||||||
DeviceResource, DeviceState, DeviceType, IdTable, KObject, DEVICE_MANAGER,
|
DevicePrivateData, DeviceResource, DeviceState, DeviceType, IdTable,
|
||||||
},
|
},
|
||||||
|
kobject::{KObjType, KObject, KObjectState},
|
||||||
|
kset::KSet,
|
||||||
platform::{
|
platform::{
|
||||||
platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
|
platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
|
||||||
},
|
},
|
||||||
@ -14,7 +16,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
filesystem::{
|
filesystem::{
|
||||||
devfs::{devfs_register, DevFS, DeviceINode},
|
devfs::{devfs_register, DevFS, DeviceINode},
|
||||||
sysfs::bus::{bus_device_register, bus_driver_register},
|
kernfs::KernFSInode,
|
||||||
vfs::{
|
vfs::{
|
||||||
syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
|
syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
|
||||||
PollStatus,
|
PollStatus,
|
||||||
@ -22,7 +24,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
include::bindings::bindings::{io_in8, io_out8},
|
include::bindings::bindings::{io_in8, io_out8},
|
||||||
kinfo,
|
kinfo,
|
||||||
libs::spinlock::SpinLock,
|
libs::{
|
||||||
|
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
spinlock::SpinLock,
|
||||||
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
@ -120,8 +125,7 @@ struct UartRegister {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Uart {
|
pub struct Uart {
|
||||||
private_data: DevicePrivateData, // 设备状态
|
private_data: DevicePrivateData, // 设备状态
|
||||||
sys_info: Option<Arc<dyn IndexNode>>,
|
fs: Weak<DevFS>, // 文件系统
|
||||||
fs: Weak<DevFS>, // 文件系统
|
|
||||||
port: UartPort,
|
port: UartPort,
|
||||||
baud_rate: u32,
|
baud_rate: u32,
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
@ -142,7 +146,6 @@ impl Default for Uart {
|
|||||||
CompatibleTable::new(vec!["uart"]),
|
CompatibleTable::new(vec!["uart"]),
|
||||||
DeviceState::NotInitialized,
|
DeviceState::NotInitialized,
|
||||||
),
|
),
|
||||||
sys_info: None,
|
|
||||||
fs: Weak::default(),
|
fs: Weak::default(),
|
||||||
port: UartPort::COM1,
|
port: UartPort::COM1,
|
||||||
baud_rate: 115200,
|
baud_rate: 115200,
|
||||||
@ -161,7 +164,59 @@ impl Default for LockedUart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KObject for LockedUart {}
|
impl KObject for LockedUart {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, _state: KObjectState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> alloc::string::String {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: alloc::string::String) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PlatformDevice for LockedUart {
|
impl PlatformDevice for LockedUart {
|
||||||
fn is_initialized(&self) -> bool {
|
fn is_initialized(&self) -> bool {
|
||||||
@ -189,20 +244,24 @@ impl Device for LockedUart {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>) {
|
|
||||||
self.0.lock().sys_info = sys_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
self.0.lock().sys_info.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dev_type(&self) -> DeviceType {
|
fn dev_type(&self) -> DeviceType {
|
||||||
DeviceType::Serial
|
DeviceType::Serial
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_ref(&self) -> &dyn Any {
|
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||||
self
|
todo!("LockedUart::bus()")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
|
todo!("LockedUart::driver()")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_dead(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
|
||||||
|
todo!("LockedUart::set_driver()")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,25 +592,65 @@ impl Default for LockedUartDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KObject for LockedUartDriver {}
|
impl KObject for LockedUartDriver {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
impl Driver for LockedUartDriver {
|
|
||||||
fn as_any_ref(&self) -> &dyn Any {
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, _state: KObjectState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> alloc::string::String {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: alloc::string::String) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Driver for LockedUartDriver {
|
||||||
fn id_table(&self) -> IdTable {
|
fn id_table(&self) -> IdTable {
|
||||||
return IdTable::new("uart_driver".to_string(), DeviceNumber::new(0));
|
return IdTable::new("uart_driver".to_string(), DeviceNumber::new(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>) {
|
|
||||||
self.0.lock().sys_info = sys_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
|
|
||||||
return self.0.lock().sys_info.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
|
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||||
let table = data.compatible_table();
|
let table = data.compatible_table();
|
||||||
if table.matches(&CompatibleTable::new(vec!["uart"])) {
|
if table.matches(&CompatibleTable::new(vec!["uart"])) {
|
||||||
@ -693,14 +792,14 @@ pub fn uart_init() -> Result<(), SystemError> {
|
|||||||
let dev = UART_DEV.0.lock();
|
let dev = UART_DEV.0.lock();
|
||||||
LockedUart::uart_init(&dev.port, dev.baud_rate).map_err(|_| SystemError::ENODEV)?;
|
LockedUart::uart_init(&dev.port, dev.baud_rate).map_err(|_| SystemError::ENODEV)?;
|
||||||
drop(dev);
|
drop(dev);
|
||||||
let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().name())
|
// let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().name())
|
||||||
.expect("uart device register error");
|
// .expect("uart device register error");
|
||||||
UART_DEV.set_sys_info(Some(device_inode));
|
// UART_DEV.set_sys_info(Some(device_inode));
|
||||||
let driver_inode = bus_driver_register("platform:0", &UART_DRV.id_table().name())
|
// let driver_inode = bus_driver_register("platform:0", &UART_DRV.id_table().name())
|
||||||
.expect("uart driver register error");
|
// .expect("uart driver register error");
|
||||||
UART_DRV.set_sys_info(Some(driver_inode));
|
// UART_DRV.set_sys_info(Some(driver_inode));
|
||||||
UART_DEV.set_state(DeviceState::Initialized);
|
UART_DEV.set_state(DeviceState::Initialized);
|
||||||
devfs_register(&UART_DEV.id_table().name(), UART_DEV.clone())?;
|
devfs_register(&UART_DEV.id_table().name(), UART_DEV.clone())?;
|
||||||
DEVICE_MANAGER.add_device(UART_DEV.id_table().clone(), UART_DEV.clone());
|
// DEVICE_MANAGER.add_device(UART_DEV.id_table().clone(), UART_DEV.clone());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
use crate::driver::base::char::CharDevOps;
|
use crate::driver::base::char::CharDevOps;
|
||||||
use crate::driver::base::device::{Device, DeviceResource, DEVICE_MANAGER};
|
use crate::driver::base::device::{device_manager, Device, DeviceResource};
|
||||||
|
use crate::driver::base::kobject::KObject;
|
||||||
use crate::driver::base::platform::CompatibleTable;
|
use crate::driver::base::platform::CompatibleTable;
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
@ -32,7 +33,63 @@ impl Default for UartDriver {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl KObject for UartDriver {
|
||||||
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> alloc::string::String {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: alloc::string::String) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(
|
||||||
|
&self,
|
||||||
|
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(
|
||||||
|
&self,
|
||||||
|
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Driver for UartDriver {
|
impl Driver for UartDriver {
|
||||||
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
|
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||||
let compatible_table = data.compatible_table();
|
let compatible_table = data.compatible_table();
|
||||||
@ -48,34 +105,25 @@ impl Driver for UartDriver {
|
|||||||
data: DevicePrivateData,
|
data: DevicePrivateData,
|
||||||
_resource: Option<DeviceResource>,
|
_resource: Option<DeviceResource>,
|
||||||
) -> Result<Arc<dyn Device>, DriverError> {
|
) -> Result<Arc<dyn Device>, DriverError> {
|
||||||
if let Some(device) = DEVICE_MANAGER.get_device(data.id_table()) {
|
if let Some(device) = device_manager().find_device_by_idtable(data.id_table()) {
|
||||||
return Ok(device.clone());
|
return Ok(device.clone());
|
||||||
}
|
}
|
||||||
let compatible_table = data.compatible_table();
|
let compatible_table = data.compatible_table();
|
||||||
if compatible_table.matches(&UART_COMPAT_TABLE) {
|
if compatible_table.matches(&UART_COMPAT_TABLE) {
|
||||||
let device = LockedUart::default();
|
let device = LockedUart::default();
|
||||||
let arc_device = Arc::new(device);
|
let arc_device = Arc::new(device);
|
||||||
DEVICE_MANAGER.add_device(data.id_table().clone(), arc_device.clone());
|
device_manager()
|
||||||
CharDevOps::cdev_add(arc_device.clone(), data.id_table().clone(), 1);
|
.add_device(arc_device.clone())
|
||||||
|
.map_err(|_| DriverError::RegisterError)?;
|
||||||
|
CharDevOps::cdev_add(arc_device.clone(), data.id_table().clone(), 1)
|
||||||
|
.map_err(|_| DriverError::RegisterError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(DriverError::ProbeError);
|
return Err(DriverError::RegisterError);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_table(&self) -> IdTable {
|
fn id_table(&self) -> IdTable {
|
||||||
let driver = self.0.lock();
|
let driver = self.0.lock();
|
||||||
return driver.id_table.clone();
|
return driver.id_table.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_sys_info(&self, _sys_info: Option<Arc<dyn crate::filesystem::vfs::IndexNode>>) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sys_info(&self) -> Option<Arc<dyn crate::filesystem::vfs::IndexNode>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,22 @@ impl<'a> KernCallbackData<'a> {
|
|||||||
pub fn private_data_mut(&mut self) -> &mut Option<KernInodePrivateData> {
|
pub fn private_data_mut(&mut self) -> &mut Option<KernInodePrivateData> {
|
||||||
return &mut self.private_data;
|
return &mut self.private_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
|
let private_data = self.private_data();
|
||||||
|
if let Some(private_data) = private_data {
|
||||||
|
return private_data.callback_read(buf, offset);
|
||||||
|
}
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
|
let private_data = self.private_data();
|
||||||
|
if let Some(private_data) = private_data {
|
||||||
|
return private_data.callback_write(buf, offset);
|
||||||
|
}
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -71,3 +87,23 @@ impl<'a> KernCallbackData<'a> {
|
|||||||
pub enum KernInodePrivateData {
|
pub enum KernInodePrivateData {
|
||||||
SysFS(SysFSKernPrivateData),
|
SysFS(SysFSKernPrivateData),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl KernInodePrivateData {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
|
match self {
|
||||||
|
KernInodePrivateData::SysFS(private_data) => {
|
||||||
|
return private_data.callback_read(buf, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
|
match self {
|
||||||
|
KernInodePrivateData::SysFS(private_data) => {
|
||||||
|
return private_data.callback_write(buf, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,7 +8,11 @@ use alloc::{
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
libs::{
|
||||||
|
casting::DowncastArc,
|
||||||
|
rwlock::RwLock,
|
||||||
|
spinlock::{SpinLock, SpinLockGuard},
|
||||||
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
time::TimeSpec,
|
time::TimeSpec,
|
||||||
};
|
};
|
||||||
@ -83,6 +87,7 @@ impl KernFS {
|
|||||||
raw_dev: 0,
|
raw_dev: 0,
|
||||||
};
|
};
|
||||||
let root_inode = Arc::new(KernFSInode {
|
let root_inode = Arc::new(KernFSInode {
|
||||||
|
name: String::from(""),
|
||||||
inner: SpinLock::new(InnerKernFSInode {
|
inner: SpinLock::new(InnerKernFSInode {
|
||||||
parent: Weak::new(),
|
parent: Weak::new(),
|
||||||
metadata,
|
metadata,
|
||||||
@ -114,6 +119,8 @@ pub struct KernFSInode {
|
|||||||
children: SpinLock<HashMap<String, Arc<KernFSInode>>>,
|
children: SpinLock<HashMap<String, Arc<KernFSInode>>>,
|
||||||
/// Inode类型
|
/// Inode类型
|
||||||
inode_type: KernInodeType,
|
inode_type: KernInodeType,
|
||||||
|
/// Inode名称
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -199,13 +206,29 @@ impl IndexNode for KernFSInode {
|
|||||||
if unlikely(self.inode_type != KernInodeType::Dir) {
|
if unlikely(self.inode_type != KernInodeType::Dir) {
|
||||||
return Err(SystemError::ENOTDIR);
|
return Err(SystemError::ENOTDIR);
|
||||||
}
|
}
|
||||||
let x: Arc<KernFSInode> = self
|
match name {
|
||||||
.children
|
"" | "." => {
|
||||||
.lock()
|
return Ok(self.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
|
||||||
.get(name)
|
}
|
||||||
.cloned()
|
|
||||||
.ok_or(SystemError::ENOENT)?;
|
".." => {
|
||||||
return Ok(x);
|
return Ok(self
|
||||||
|
.inner
|
||||||
|
.lock()
|
||||||
|
.parent
|
||||||
|
.upgrade()
|
||||||
|
.ok_or(SystemError::ENOENT)?);
|
||||||
|
}
|
||||||
|
name => {
|
||||||
|
// 在子目录项中查找
|
||||||
|
return Ok(self
|
||||||
|
.children
|
||||||
|
.lock()
|
||||||
|
.get(name)
|
||||||
|
.ok_or(SystemError::ENOENT)?
|
||||||
|
.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
|
fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
|
||||||
@ -248,11 +271,21 @@ impl IndexNode for KernFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn list(&self) -> Result<Vec<String>, SystemError> {
|
fn list(&self) -> Result<Vec<String>, SystemError> {
|
||||||
let mut list = Vec::new();
|
let info = self.metadata()?;
|
||||||
for (name, _) in self.children.lock().iter() {
|
if info.file_type != FileType::Dir {
|
||||||
list.push(name.clone());
|
return Err(SystemError::ENOTDIR);
|
||||||
}
|
}
|
||||||
return Ok(list);
|
|
||||||
|
let mut keys: Vec<String> = Vec::new();
|
||||||
|
keys.push(String::from("."));
|
||||||
|
keys.push(String::from(".."));
|
||||||
|
self.children
|
||||||
|
.lock()
|
||||||
|
.keys()
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|x| keys.push(x.clone()));
|
||||||
|
|
||||||
|
return Ok(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self) -> Result<PollStatus, SystemError> {
|
fn poll(&self) -> Result<PollStatus, SystemError> {
|
||||||
@ -272,6 +305,7 @@ impl IndexNode for KernFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.callback.is_none() {
|
if self.callback.is_none() {
|
||||||
|
kwarn!("kernfs: callback is none");
|
||||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,8 +410,14 @@ impl KernFSInode {
|
|||||||
private_data: Option<KernInodePrivateData>,
|
private_data: Option<KernInodePrivateData>,
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
callback: Option<&'static dyn KernFSCallback>,
|
||||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
|
let size = if file_type == KernInodeType::File {
|
||||||
|
4096
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let metadata = Metadata {
|
let metadata = Metadata {
|
||||||
size: 0,
|
size,
|
||||||
mode,
|
mode,
|
||||||
uid: 0,
|
uid: 0,
|
||||||
gid: 0,
|
gid: 0,
|
||||||
@ -394,9 +434,10 @@ impl KernFSInode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let new_inode: Arc<KernFSInode> = Self::new(
|
let new_inode: Arc<KernFSInode> = Self::new(
|
||||||
self.self_ref.upgrade().unwrap(),
|
Some(self.self_ref.upgrade().unwrap()),
|
||||||
|
name.clone(),
|
||||||
metadata,
|
metadata,
|
||||||
KernInodeType::Dir,
|
file_type,
|
||||||
private_data,
|
private_data,
|
||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
@ -434,16 +475,21 @@ impl KernFSInode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(self) fn new(
|
pub fn new(
|
||||||
parent: Arc<KernFSInode>,
|
parent: Option<Arc<KernFSInode>>,
|
||||||
metadata: Metadata,
|
name: String,
|
||||||
|
mut metadata: Metadata,
|
||||||
inode_type: KernInodeType,
|
inode_type: KernInodeType,
|
||||||
private_data: Option<KernInodePrivateData>,
|
private_data: Option<KernInodePrivateData>,
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
callback: Option<&'static dyn KernFSCallback>,
|
||||||
) -> Arc<KernFSInode> {
|
) -> Arc<KernFSInode> {
|
||||||
|
metadata.file_type = inode_type.into();
|
||||||
|
let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
|
||||||
|
|
||||||
let inode = Arc::new(KernFSInode {
|
let inode = Arc::new(KernFSInode {
|
||||||
|
name,
|
||||||
inner: SpinLock::new(InnerKernFSInode {
|
inner: SpinLock::new(InnerKernFSInode {
|
||||||
parent: Arc::downgrade(&parent),
|
parent: parent.clone(),
|
||||||
metadata,
|
metadata,
|
||||||
}),
|
}),
|
||||||
self_ref: Weak::new(),
|
self_ref: Weak::new(),
|
||||||
@ -460,18 +506,50 @@ impl KernFSInode {
|
|||||||
(*ptr).self_ref = Arc::downgrade(&inode);
|
(*ptr).self_ref = Arc::downgrade(&inode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*inode.fs.write() = Arc::downgrade(
|
if parent.strong_count() > 0 {
|
||||||
parent
|
let kernfs = parent
|
||||||
|
.upgrade()
|
||||||
|
.unwrap()
|
||||||
.fs()
|
.fs()
|
||||||
.as_any_ref()
|
.downcast_arc::<KernFS>()
|
||||||
.downcast_ref()
|
.expect("KernFSInode::new: parent is not a KernFS instance");
|
||||||
.expect("KernFSInode::new: parent is not a KernFS instance"),
|
*inode.fs.write() = Arc::downgrade(&kernfs);
|
||||||
);
|
}
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
return &self.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
return self.inner.lock().parent.upgrade();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
|
||||||
|
return self.private_data.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// remove a kernfs_node recursively
|
||||||
|
pub fn remove_recursive(&self) {
|
||||||
|
let mut children = self.children.lock().drain().collect::<Vec<_>>();
|
||||||
|
while let Some((_, child)) = children.pop() {
|
||||||
|
children.append(&mut child.children.lock().drain().collect::<Vec<_>>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除当前的inode(包括其自身、子目录和子文件)
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn remove_inode_include_self(&self) {
|
||||||
|
let parent = self.parent();
|
||||||
|
if let Some(parent) = parent {
|
||||||
|
parent.children.lock().remove(self.name());
|
||||||
|
}
|
||||||
|
self.remove_recursive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub(self) enum KernInodeType {
|
pub enum KernInodeType {
|
||||||
Dir,
|
Dir,
|
||||||
File,
|
File,
|
||||||
}
|
}
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
use super::{LockedSysFSInode, SYS_BUS_INODE};
|
|
||||||
use crate::{filesystem::vfs::IndexNode, kdebug, syscall::SystemError};
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
/// @brief: 注册bus,在sys/bus下生成文件夹
|
|
||||||
/// @parameter bus_name: 总线文件夹名
|
|
||||||
/// @return: 操作成功,返回inode,操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_bus_register(bus_name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_BUS_INODE();
|
|
||||||
kdebug!("Before bus_register: ls /sys/bus/: {:?}", binding.list());
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(bus_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注销bus,在sys/bus删除文件夹
|
|
||||||
/// @parameter bus_name: 总线文件夹名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_bus_unregister(bus_name: &str) -> Result<(), SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_BUS_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.remove(bus_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 在相应总线文件夹下生成devices和drivers文件夹
|
|
||||||
/// @parameter inode: 总线文件夹inode
|
|
||||||
/// @return: 操作成功,返回devices inode和drivers inode,操作失败,返回错误码
|
|
||||||
pub fn sys_bus_init(
|
|
||||||
inode: &Arc<dyn IndexNode>,
|
|
||||||
) -> Result<(Arc<dyn IndexNode>, Arc<dyn IndexNode>), SystemError> {
|
|
||||||
match inode.as_any_ref().downcast_ref::<LockedSysFSInode>() {
|
|
||||||
Some(lock_bus) => match lock_bus.add_dir("devices") {
|
|
||||||
Ok(devices) => match lock_bus.add_dir("drivers") {
|
|
||||||
Ok(drivers) => Ok((devices, drivers)),
|
|
||||||
Err(err) => Err(err),
|
|
||||||
},
|
|
||||||
Err(err) => Err(err),
|
|
||||||
},
|
|
||||||
None => Err(SystemError::E2BIG),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 在相应总线的device下生成设备文件夹
|
|
||||||
/// @parameter bus_name: 总线名
|
|
||||||
/// name: 设备名
|
|
||||||
/// @return: 操作成功,返回device inode,操作失败,返回错误码
|
|
||||||
pub fn bus_driver_register(bus_name: &str, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
match SYS_BUS_INODE().find(bus_name) {
|
|
||||||
Ok(platform) => match platform.find("drivers") {
|
|
||||||
Ok(device) => device
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(name),
|
|
||||||
Err(_) => return Err(SystemError::EXDEV),
|
|
||||||
},
|
|
||||||
Err(_) => return Err(SystemError::EXDEV),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 在相应总线的driver下生成驱动文件夹
|
|
||||||
/// @parameter bus_name: 总线名
|
|
||||||
/// name: 驱动名
|
|
||||||
/// @return: 操作成功,返回drivers inode,操作失败,返回错误码
|
|
||||||
pub fn bus_device_register(bus_name: &str, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
match SYS_BUS_INODE().find(bus_name) {
|
|
||||||
Ok(platform) => match platform.find("devices") {
|
|
||||||
Ok(device) => device
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(name),
|
|
||||||
Err(_) => return Err(SystemError::EXDEV),
|
|
||||||
},
|
|
||||||
Err(_) => return Err(SystemError::EXDEV),
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
use super::{LockedSysFSInode, SYS_CLASS_INODE};
|
|
||||||
use crate::{filesystem::vfs::IndexNode, syscall::SystemError};
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
/// @brief: 注册class,在sys/class下生成文件夹
|
|
||||||
/// @parameter class_name: 类文件夹名
|
|
||||||
/// @return: 操作成功,返回inode,操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_class_register(class_name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_CLASS_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(class_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注销class,在sys/class删除文件夹
|
|
||||||
/// @parameter class_name: 总线文件夹名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_class_unregister(class_name: &str) -> Result<(), SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_CLASS_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.remove(class_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注册device,在对应类下操作设备文件夹
|
|
||||||
/// @parameter class: 类文件夹inode
|
|
||||||
/// @parameter device_name: 设备文件夹名
|
|
||||||
/// @return: 操作成功,返回inode,操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn class_device_register(
|
|
||||||
class: Arc<dyn IndexNode>,
|
|
||||||
device_name: &str,
|
|
||||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
class
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(device_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 操作device,在对应类下删除设备文件夹
|
|
||||||
/// @parameter class: 类文件夹inode
|
|
||||||
/// @parameter device_name: 设备文件夹名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn class_device_unregister(
|
|
||||||
class: Arc<dyn IndexNode>,
|
|
||||||
device_name: &str,
|
|
||||||
) -> Result<(), SystemError> {
|
|
||||||
class
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.remove(device_name)
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
use super::{LockedSysFSInode, SYS_DEVICES_INODE};
|
|
||||||
use crate::{filesystem::vfs::IndexNode, syscall::SystemError};
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
/// @brief: 注册device,在sys/devices下生成文件夹
|
|
||||||
/// @parameter device_name: 类文件夹名
|
|
||||||
/// @return: 操作成功,返回inode,操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_device_register(device_name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_DEVICES_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(device_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 操作bus,在sys/devices删除文件夹
|
|
||||||
/// @parameter device_name: 总线文件夹名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn sys_device_unregister(device_name: &str) -> Result<(), SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_DEVICES_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.remove(device_name)
|
|
||||||
}
|
|
@ -1,32 +1,127 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use alloc::sync::Arc;
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::driver::base::device::KObject;
|
use crate::{
|
||||||
|
driver::base::kobject::KObject,
|
||||||
|
filesystem::{
|
||||||
|
kernfs::{callback::KernInodePrivateData, KernFSInode},
|
||||||
|
vfs::syscall::ModeType,
|
||||||
|
},
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
use super::AttributeGroup;
|
use super::{SysFS, SysFSKernPrivateData};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SysKernDirPriv {
|
pub struct SysKernDirPriv {
|
||||||
kobj: Arc<dyn KObject>,
|
/// 该目录对应的kobject
|
||||||
attribute_group: Option<&'static dyn AttributeGroup>,
|
/// use weak reference to avoid cyclic reference
|
||||||
|
kobj: Weak<dyn KObject>,
|
||||||
|
// attribute_group: Option<&'static dyn AttributeGroup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysKernDirPriv {
|
impl SysKernDirPriv {
|
||||||
pub fn new(
|
pub fn new(kobj: Arc<dyn KObject>) -> Self {
|
||||||
kobj: Arc<dyn KObject>,
|
// let attribute_group = kobj.kobj_type().map(|kobj_type| kobj_type.attribute_groups()).flatten();
|
||||||
attribute_group: Option<&'static dyn AttributeGroup>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
kobj,
|
kobj: Arc::downgrade(&kobj),
|
||||||
attribute_group,
|
// attribute_group,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kobj(&self) -> Arc<dyn KObject> {
|
pub fn kobj(&self) -> Option<Arc<dyn KObject>> {
|
||||||
self.kobj.clone()
|
self.kobj.upgrade()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute_group(&self) -> Option<&'static dyn AttributeGroup> {
|
// pub fn attribute_group(&self) -> Option<&'static dyn AttributeGroup> {
|
||||||
self.attribute_group
|
// self.attribute_group
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysFS {
|
||||||
|
/// 在sysfs中创建一个目录
|
||||||
|
///
|
||||||
|
/// 如果kobj的parent为None,则会在根目录下创建一个目录。
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj`: 要创建的目录对应的kobject
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 返回创建的目录对应的inode
|
||||||
|
pub fn create_dir(&self, kobj: Arc<dyn KObject>) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
|
// 如果kobj的parent为None,则会在/sys目录下创建一个目录。
|
||||||
|
let parent = kobj
|
||||||
|
.parent()
|
||||||
|
.map(|p| p.upgrade().unwrap().inode())
|
||||||
|
.unwrap_or_else(|| Some(self.root_inode.clone()))
|
||||||
|
.ok_or(SystemError::ENOENT)?;
|
||||||
|
|
||||||
|
let sysfs_dir_priv = SysFSKernPrivateData::Dir(SysKernDirPriv::new(kobj.clone()));
|
||||||
|
// 在kernfs里面创建一个目录
|
||||||
|
let dir: Arc<KernFSInode> = parent.add_dir(
|
||||||
|
kobj.name(),
|
||||||
|
ModeType::from_bits_truncate(0o755),
|
||||||
|
Some(KernInodePrivateData::SysFS(sysfs_dir_priv)),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
kobj.set_inode(Some(dir.clone()));
|
||||||
|
|
||||||
|
return Ok(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取指定的kernfs inode在sysfs中的路径(不包含`/sys`)
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `parent`: inode的父目录
|
||||||
|
/// - `name`: inode的名称
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 返回inode在sysfs中的路径
|
||||||
|
pub(super) fn kernfs_path(&self, parent: &Arc<KernFSInode>) -> String {
|
||||||
|
let mut p = parent.clone();
|
||||||
|
let mut parts = Vec::new();
|
||||||
|
let sys_root_inode = self.root_inode();
|
||||||
|
let mut not_reach_sys_root = false;
|
||||||
|
while !Arc::ptr_eq(&p, sys_root_inode) {
|
||||||
|
parts.push(p.name().to_string());
|
||||||
|
if let Some(parent) = p.parent() {
|
||||||
|
p = parent;
|
||||||
|
} else {
|
||||||
|
not_reach_sys_root = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut path = String::new();
|
||||||
|
if not_reach_sys_root {
|
||||||
|
path.push_str("(null)");
|
||||||
|
};
|
||||||
|
|
||||||
|
for part in parts.iter().rev() {
|
||||||
|
path.push('/');
|
||||||
|
path.push_str(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从sysfs中删除一个kobject对应的目录(包括目录自身以及目录下的所有文件、文件夹)
|
||||||
|
pub fn remove_dir(&self, kobj: &Arc<dyn KObject>) {
|
||||||
|
let kobj_inode = kobj.inode();
|
||||||
|
kobj.set_inode(None);
|
||||||
|
|
||||||
|
if let Some(inode) = kobj_inode {
|
||||||
|
let parent = inode.parent().unwrap();
|
||||||
|
parent.remove_recursive()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,298 @@
|
|||||||
#![allow(dead_code)]
|
use core::{intrinsics::unlikely, ops::BitAnd};
|
||||||
use super::Attribute;
|
|
||||||
|
use alloc::{
|
||||||
|
string::ToString,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
driver::base::kobject::KObject,
|
||||||
|
filesystem::{
|
||||||
|
kernfs::{
|
||||||
|
callback::{KernCallbackData, KernFSCallback, KernInodePrivateData},
|
||||||
|
KernFSInode,
|
||||||
|
},
|
||||||
|
sysfs::{SysFSOps, SysFSOpsSupport},
|
||||||
|
vfs::{syscall::ModeType, PollStatus},
|
||||||
|
},
|
||||||
|
kwarn,
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{Attribute, SysFS, SysFSKernPrivateData};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SysKernFilePriv {
|
pub struct SysKernFilePriv {
|
||||||
attribute: Option<&'static dyn Attribute>,
|
attribute: Option<&'static dyn Attribute>,
|
||||||
|
/// 当前文件对应的kobject
|
||||||
|
kobj: Weak<dyn KObject>,
|
||||||
// todo: 增加bin attribute,它和attribute二选一,只能有一个为Some
|
// todo: 增加bin attribute,它和attribute二选一,只能有一个为Some
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysKernFilePriv {
|
impl SysKernFilePriv {
|
||||||
pub fn new(attribute: Option<&'static dyn Attribute>) -> Self {
|
pub fn new(kobj: &Arc<dyn KObject>, attribute: Option<&'static dyn Attribute>) -> Self {
|
||||||
if attribute.is_none() {
|
if attribute.is_none() {
|
||||||
panic!("attribute can't be None");
|
panic!("attribute can't be None");
|
||||||
}
|
}
|
||||||
return Self { attribute };
|
let kobj = Arc::downgrade(kobj);
|
||||||
|
return Self { kobj, attribute };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline]
|
||||||
pub fn attribute(&self) -> Option<&'static dyn Attribute> {
|
pub fn attribute(&self) -> Option<&'static dyn Attribute> {
|
||||||
self.attribute
|
self.attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn callback_read(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||||
|
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
|
||||||
|
// 当前文件所指向的kobject已经被释放
|
||||||
|
let kobj = self.kobj.upgrade().expect("kobj is None");
|
||||||
|
return attribute.show(kobj, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn callback_write(&self, buf: &[u8]) -> Result<usize, SystemError> {
|
||||||
|
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
|
||||||
|
// 当前文件所指向的kobject已经被释放
|
||||||
|
let kobj = self.kobj.upgrade().expect("kobj is None");
|
||||||
|
return attribute.store(kobj, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysFS {
|
||||||
|
/// 为指定的kobject创建一个属性文件
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj` 要创建属性文件的kobject
|
||||||
|
/// - `attr` 属性
|
||||||
|
pub fn create_file(
|
||||||
|
&self,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
attr: &'static dyn Attribute,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let inode = kobj.inode().ok_or(SystemError::EINVAL)?;
|
||||||
|
return self.add_file_with_mode(&inode, attr, attr.mode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c?fi=sysfs_add_file_mode_ns#271
|
||||||
|
pub(super) fn add_file_with_mode(
|
||||||
|
&self,
|
||||||
|
parent: &Arc<KernFSInode>,
|
||||||
|
attr: &'static dyn Attribute,
|
||||||
|
mode: ModeType,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let x = parent.private_data_mut();
|
||||||
|
let kobj: Arc<dyn KObject>;
|
||||||
|
if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() {
|
||||||
|
kobj = dt.kobj().unwrap();
|
||||||
|
} else {
|
||||||
|
drop(x);
|
||||||
|
let path = self.kernfs_path(parent);
|
||||||
|
panic!("parent '{path}' is not a dir");
|
||||||
|
}
|
||||||
|
drop(x);
|
||||||
|
|
||||||
|
let sysfs_ops: &dyn SysFSOps = kobj.kobj_type().unwrap().sysfs_ops().ok_or_else(|| {
|
||||||
|
kwarn!("missing sysfs attribute operations for kobject: {kobj:?}");
|
||||||
|
SystemError::EINVAL
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// assume that all sysfs ops are preallocated.
|
||||||
|
|
||||||
|
let sys_support = sysfs_ops.support(attr);
|
||||||
|
|
||||||
|
let kern_callback: &'static dyn KernFSCallback;
|
||||||
|
if sys_support.contains(SysFSOpsSupport::SHOW)
|
||||||
|
&& sys_support.contains(SysFSOpsSupport::STORE)
|
||||||
|
{
|
||||||
|
kern_callback = &PreallocKFOpsRW;
|
||||||
|
} else if sys_support.contains(SysFSOpsSupport::SHOW) {
|
||||||
|
kern_callback = &PreallocKFOpsReadOnly;
|
||||||
|
} else if sys_support.contains(SysFSOpsSupport::STORE) {
|
||||||
|
kern_callback = &PreallocKFOpsWriteOnly;
|
||||||
|
} else {
|
||||||
|
kern_callback = &PreallocKFOpsEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr)));
|
||||||
|
let r = parent.add_file(
|
||||||
|
attr.name().to_string(),
|
||||||
|
mode.bitand(ModeType::from_bits_truncate(0o777)),
|
||||||
|
Some(KernInodePrivateData::SysFS(sys_priv)),
|
||||||
|
Some(kern_callback),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = r {
|
||||||
|
if e == SystemError::EEXIST {
|
||||||
|
self.warn_duplicate(parent, attr.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在sysfs中删除某个kobject的属性文件
|
||||||
|
///
|
||||||
|
/// 如果属性文件不存在,则发出一个警告
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj` 要删除属性文件的kobject
|
||||||
|
/// - `attr` 属性
|
||||||
|
pub fn remove_file(&self, kobj: &Arc<dyn KObject>, attr: &'static dyn Attribute) {
|
||||||
|
let parent = kobj.inode();
|
||||||
|
|
||||||
|
if let Some(parent) = parent {
|
||||||
|
let r = parent.remove(attr.name());
|
||||||
|
if unlikely(r.is_err()) {
|
||||||
|
kwarn!(
|
||||||
|
"failed to remove file '{}' from '{}'",
|
||||||
|
attr.name(),
|
||||||
|
kobj.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PreallocKFOpsRW;
|
||||||
|
|
||||||
|
impl KernFSCallback for PreallocKFOpsRW {
|
||||||
|
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(
|
||||||
|
&self,
|
||||||
|
data: KernCallbackData,
|
||||||
|
buf: &mut [u8],
|
||||||
|
offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return data.callback_read(buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&self,
|
||||||
|
data: KernCallbackData,
|
||||||
|
buf: &[u8],
|
||||||
|
offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return data.callback_write(buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
|
||||||
|
return Ok(PollStatus::READ | PollStatus::WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PreallocKFOpsReadOnly;
|
||||||
|
|
||||||
|
impl KernFSCallback for PreallocKFOpsReadOnly {
|
||||||
|
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(
|
||||||
|
&self,
|
||||||
|
data: KernCallbackData,
|
||||||
|
buf: &mut [u8],
|
||||||
|
offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return data.callback_read(buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&self,
|
||||||
|
_data: KernCallbackData,
|
||||||
|
_buf: &[u8],
|
||||||
|
_offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
|
||||||
|
return Ok(PollStatus::READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PreallocKFOpsWriteOnly;
|
||||||
|
|
||||||
|
impl KernFSCallback for PreallocKFOpsWriteOnly {
|
||||||
|
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(
|
||||||
|
&self,
|
||||||
|
_data: KernCallbackData,
|
||||||
|
_buf: &mut [u8],
|
||||||
|
_offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&self,
|
||||||
|
data: KernCallbackData,
|
||||||
|
buf: &[u8],
|
||||||
|
offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return data.callback_write(buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
|
||||||
|
return Ok(PollStatus::WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PreallocKFOpsEmpty;
|
||||||
|
|
||||||
|
impl KernFSCallback for PreallocKFOpsEmpty {
|
||||||
|
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(
|
||||||
|
&self,
|
||||||
|
_data: KernCallbackData,
|
||||||
|
_buf: &mut [u8],
|
||||||
|
_offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&self,
|
||||||
|
_data: KernCallbackData,
|
||||||
|
_buf: &[u8],
|
||||||
|
_offset: usize,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
|
||||||
|
return Ok(PollStatus::empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sysfs_emit_str(buf: &mut [u8], s: &str) -> Result<usize, SystemError> {
|
||||||
|
let len;
|
||||||
|
if buf.len() > s.len() {
|
||||||
|
len = s.len();
|
||||||
|
} else {
|
||||||
|
len = buf.len() - 1;
|
||||||
|
}
|
||||||
|
buf[..len].copy_from_slice(&s.as_bytes()[..len]);
|
||||||
|
buf[len] = b'\0';
|
||||||
|
return Ok(len);
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
use super::{LockedSysFSInode, SYS_FS_INODE};
|
|
||||||
use crate::{filesystem::vfs::IndexNode, syscall::SystemError};
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
/// @brief: 注册fs,在sys/fs下是生成文件夹
|
|
||||||
/// @parameter fs_name: 类文件夹名
|
|
||||||
/// @return: 操作成功,返回inode,操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn fs_register(fs_name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_FS_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.add_dir(fs_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief: 注销fs,在sys/fs删除文件夹
|
|
||||||
/// @parameter fs_name: 总线文件夹名
|
|
||||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn fs_unregister(fs_name: &str) -> Result<(), SystemError> {
|
|
||||||
let binding: Arc<dyn IndexNode> = SYS_FS_INODE();
|
|
||||||
binding
|
|
||||||
.as_any_ref()
|
|
||||||
.downcast_ref::<LockedSysFSInode>()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap()
|
|
||||||
.remove(fs_name)
|
|
||||||
}
|
|
200
kernel/src/filesystem/sysfs/group.rs
Normal file
200
kernel/src/filesystem/sysfs/group.rs
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
use core::intrinsics::unlikely;
|
||||||
|
|
||||||
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
driver::base::kobject::KObject,
|
||||||
|
filesystem::{
|
||||||
|
kernfs::{callback::KernInodePrivateData, KernFSInode},
|
||||||
|
sysfs::{dir::SysKernDirPriv, sysfs_instance, SysFSKernPrivateData},
|
||||||
|
vfs::{syscall::ModeType, IndexNode},
|
||||||
|
},
|
||||||
|
kwarn,
|
||||||
|
libs::casting::DowncastArc,
|
||||||
|
syscall::SystemError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{AttributeGroup, SysFS};
|
||||||
|
|
||||||
|
impl SysFS {
|
||||||
|
/// 在sysfs中,为指定的kobject的属性组创建文件夹
|
||||||
|
pub fn create_groups(
|
||||||
|
&self,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
groups: &[&'static dyn AttributeGroup],
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
return self.do_create_groups(kobj, groups, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_create_groups(
|
||||||
|
&self,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
groups: &[&'static dyn AttributeGroup],
|
||||||
|
update: bool,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
for i in 0..groups.len() {
|
||||||
|
let group = groups[i];
|
||||||
|
if let Err(e) = self.do_create_group(kobj, group, update) {
|
||||||
|
for j in (0..=i).rev() {
|
||||||
|
self.remove_group(kobj, groups[j]).ok();
|
||||||
|
}
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_create_group(
|
||||||
|
&self,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
group: &'static dyn AttributeGroup,
|
||||||
|
update: bool,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
// kobj的inode必须存在
|
||||||
|
let kobj_inode = kobj.inode().ok_or(SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
if group.attrs().is_empty() {
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_inode: Arc<KernFSInode>;
|
||||||
|
if group.name().is_some() {
|
||||||
|
if update {
|
||||||
|
// 如果是更新,那么group的name必须存在
|
||||||
|
parent_inode = kobj_inode
|
||||||
|
.find(group.name().unwrap())
|
||||||
|
.map_err(|_| SystemError::EINVAL)?
|
||||||
|
.downcast_arc()
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
let private_data = KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(
|
||||||
|
SysKernDirPriv::new(kobj.clone()),
|
||||||
|
));
|
||||||
|
parent_inode = kobj_inode
|
||||||
|
.add_dir(
|
||||||
|
group.name().unwrap().to_string(),
|
||||||
|
ModeType::S_IRWXU | ModeType::S_IRUGO | ModeType::S_IXUGO,
|
||||||
|
Some(private_data),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
if e == SystemError::EEXIST {
|
||||||
|
self.warn_duplicate(&kobj_inode, group.name().unwrap());
|
||||||
|
}
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parent_inode = kobj_inode.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = self.group_create_files(parent_inode.clone(), kobj, group, update) {
|
||||||
|
if group.name().is_some() {
|
||||||
|
parent_inode.remove_recursive();
|
||||||
|
}
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从一个kobject中移除一个group
|
||||||
|
///
|
||||||
|
/// This function removes a group of attributes from a kobject. The attributes
|
||||||
|
/// previously have to have been created for this group, otherwise it will fail.
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj` - 要移除group的kobject
|
||||||
|
/// - `group` - 要移除的group
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub fn remove_group(
|
||||||
|
&self,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
group: &'static dyn AttributeGroup,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let inode = kobj.inode().unwrap();
|
||||||
|
let parent_inode: Arc<KernFSInode>;
|
||||||
|
if let Some(name) = group.name() {
|
||||||
|
parent_inode = inode
|
||||||
|
.find(name)
|
||||||
|
.map_err(|e| {
|
||||||
|
kwarn!("sysfs group '{name}' not found for kobject {kobj:?}");
|
||||||
|
e
|
||||||
|
})?
|
||||||
|
.downcast_arc()
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
parent_inode = inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.group_remove_files(&parent_inode, group);
|
||||||
|
|
||||||
|
if group.name().is_some() {
|
||||||
|
parent_inode.remove_recursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建属性组的文件
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `parent` - 属性组的父文件夹
|
||||||
|
/// - `kobj` - 属性组所属的kobject
|
||||||
|
/// - `group` - 属性组
|
||||||
|
/// - `update` - 当前是否正在更新属性
|
||||||
|
///
|
||||||
|
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/group.c#34
|
||||||
|
fn group_create_files(
|
||||||
|
&self,
|
||||||
|
parent: Arc<KernFSInode>,
|
||||||
|
kobj: &Arc<dyn KObject>,
|
||||||
|
group: &'static dyn AttributeGroup,
|
||||||
|
update: bool,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let mut e = Ok(());
|
||||||
|
for attr in group.attrs() {
|
||||||
|
let mut mode = attr.mode();
|
||||||
|
|
||||||
|
// 由于我们在更新的时候,可能会更改visibility和permissions,所以需要先删除再创建
|
||||||
|
if update {
|
||||||
|
parent.remove(attr.name()).ok();
|
||||||
|
}
|
||||||
|
if let Some(mt) = group.is_visible(kobj.clone(), *attr) {
|
||||||
|
mode = mt;
|
||||||
|
// 当前属性不可见,跳过
|
||||||
|
if mode.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if unlikely((mode.bits() & (!0o644)) != 0) {
|
||||||
|
kwarn!(
|
||||||
|
"Attribute '{name}' has invalid mode 0{mode:o}",
|
||||||
|
name = attr.name(),
|
||||||
|
mode = mode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = ModeType::from_bits_truncate(mode.bits() & 0o644);
|
||||||
|
e = sysfs_instance().add_file_with_mode(&parent, *attr, mode);
|
||||||
|
if e.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = e {
|
||||||
|
self.group_remove_files(&parent, group);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup) {
|
||||||
|
todo!("group_remove_files")
|
||||||
|
}
|
||||||
|
}
|
@ -2,479 +2,31 @@ use core::fmt::Debug;
|
|||||||
|
|
||||||
use self::{dir::SysKernDirPriv, file::SysKernFilePriv};
|
use self::{dir::SysKernDirPriv, file::SysKernFilePriv};
|
||||||
|
|
||||||
use super::vfs::{
|
use super::{
|
||||||
core::generate_inode_id, file::FileMode, syscall::ModeType, FileSystem, FileType, FsInfo,
|
kernfs::{KernFS, KernFSInode},
|
||||||
IndexNode, Metadata, PollStatus,
|
vfs::{syscall::ModeType, FileSystem},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::{device::KObject, platform::platform_bus_init},
|
driver::base::kobject::KObject,
|
||||||
filesystem::{sysfs::bus::sys_bus_init, vfs::ROOT_INODE},
|
filesystem::vfs::ROOT_INODE,
|
||||||
kdebug, kinfo,
|
kinfo, kwarn,
|
||||||
libs::{
|
libs::{casting::DowncastArc, once::Once},
|
||||||
once::Once,
|
|
||||||
spinlock::{SpinLock, SpinLockGuard},
|
|
||||||
},
|
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
time::TimeSpec,
|
|
||||||
};
|
|
||||||
use alloc::{
|
|
||||||
collections::BTreeMap,
|
|
||||||
string::{String, ToString},
|
|
||||||
sync::{Arc, Weak},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
};
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
pub mod bus;
|
pub mod dir;
|
||||||
pub mod class;
|
pub mod file;
|
||||||
pub mod devices;
|
pub mod group;
|
||||||
mod dir;
|
pub mod symlink;
|
||||||
mod file;
|
|
||||||
pub mod fs;
|
|
||||||
|
|
||||||
const SYSFS_MAX_NAMELEN: usize = 64;
|
/// 全局的sysfs实例
|
||||||
|
pub(self) static mut SYSFS_INSTANCE: Option<SysFS> = None;
|
||||||
|
|
||||||
static mut __SYS_DEVICES_INODE: Option<Arc<dyn IndexNode>> = None;
|
|
||||||
static mut __SYS_BUS_INODE: Option<Arc<dyn IndexNode>> = None;
|
|
||||||
static mut __SYS_CLASS_INODE: Option<Arc<dyn IndexNode>> = None;
|
|
||||||
static mut __SYS_FS_INODE: Option<Arc<dyn IndexNode>> = None;
|
|
||||||
|
|
||||||
/// @brief 获取全局的sys/devices节点
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(non_snake_case)]
|
pub fn sysfs_instance() -> &'static SysFS {
|
||||||
pub fn SYS_DEVICES_INODE() -> Arc<dyn IndexNode> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
return __SYS_DEVICES_INODE.as_ref().unwrap().clone();
|
return &SYSFS_INSTANCE.as_ref().unwrap();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 获取全局的sys/bus节点
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn SYS_BUS_INODE() -> Arc<dyn IndexNode> {
|
|
||||||
unsafe {
|
|
||||||
return __SYS_BUS_INODE.as_ref().unwrap().clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 获取全局的sys/class节点
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn SYS_CLASS_INODE() -> Arc<dyn IndexNode> {
|
|
||||||
unsafe {
|
|
||||||
return __SYS_CLASS_INODE.as_ref().unwrap().clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 获取全局的sys/fs节点
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn SYS_FS_INODE() -> Arc<dyn IndexNode> {
|
|
||||||
unsafe {
|
|
||||||
return __SYS_FS_INODE.as_ref().unwrap().clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief dev文件系统
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SysFS {
|
|
||||||
// 文件系统根节点
|
|
||||||
root_inode: Arc<LockedSysFSInode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileSystem for SysFS {
|
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
|
|
||||||
return self.root_inode.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn info(&self) -> super::vfs::FsInfo {
|
|
||||||
return FsInfo {
|
|
||||||
blk_dev_id: 0,
|
|
||||||
max_name_len: SYSFS_MAX_NAMELEN,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SysFS {
|
|
||||||
pub fn new() -> Arc<Self> {
|
|
||||||
// 初始化root inode
|
|
||||||
let root: Arc<LockedSysFSInode> = Arc::new(LockedSysFSInode(SpinLock::new(
|
|
||||||
// /sys 的权限设置为 读+执行,root 可以读写
|
|
||||||
// root 的 parent 是空指针
|
|
||||||
SysFSInode::new(FileType::Dir, ModeType::from_bits_truncate(0o755), 0),
|
|
||||||
)));
|
|
||||||
|
|
||||||
let sysfs: Arc<SysFS> = Arc::new(SysFS { root_inode: root });
|
|
||||||
|
|
||||||
// 对root inode加锁,并继续完成初始化工作
|
|
||||||
let mut root_guard: SpinLockGuard<SysFSInode> = sysfs.root_inode.0.lock();
|
|
||||||
root_guard.parent = Arc::downgrade(&sysfs.root_inode);
|
|
||||||
root_guard.self_ref = Arc::downgrade(&sysfs.root_inode);
|
|
||||||
root_guard.fs = Arc::downgrade(&sysfs);
|
|
||||||
// 释放锁
|
|
||||||
drop(root_guard);
|
|
||||||
|
|
||||||
// 创建文件夹
|
|
||||||
let root: &Arc<LockedSysFSInode> = &sysfs.root_inode;
|
|
||||||
match root.add_dir("devices") {
|
|
||||||
Ok(devices) => unsafe {
|
|
||||||
__SYS_DEVICES_INODE = Some(devices);
|
|
||||||
},
|
|
||||||
Err(_) => panic!("SysFS: Failed to create /sys/devices"),
|
|
||||||
}
|
|
||||||
|
|
||||||
match root.add_dir("bus") {
|
|
||||||
Ok(bus) => unsafe {
|
|
||||||
__SYS_BUS_INODE = Some(bus);
|
|
||||||
},
|
|
||||||
Err(_) => panic!("SysFS: Failed to create /sys/bus"),
|
|
||||||
}
|
|
||||||
|
|
||||||
match root.add_dir("class") {
|
|
||||||
Ok(class) => unsafe {
|
|
||||||
__SYS_CLASS_INODE = Some(class);
|
|
||||||
},
|
|
||||||
Err(_) => panic!("SysFS: Failed to create /sys/class"),
|
|
||||||
}
|
|
||||||
|
|
||||||
match root.add_dir("fs") {
|
|
||||||
Ok(fs) => unsafe {
|
|
||||||
__SYS_FS_INODE = Some(fs);
|
|
||||||
},
|
|
||||||
Err(_) => panic!("SysFS: Failed to create /sys/fs"),
|
|
||||||
}
|
|
||||||
|
|
||||||
return sysfs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief sys文件i节点(锁)
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct LockedSysFSInode(SpinLock<SysFSInode>);
|
|
||||||
|
|
||||||
impl IndexNode for LockedSysFSInode {
|
|
||||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&self, _len: usize) -> Result<(), SystemError> {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn truncate(&self, _len: usize) -> Result<(), SystemError> {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open(
|
|
||||||
&self,
|
|
||||||
_data: &mut super::vfs::FilePrivateData,
|
|
||||||
_mode: &FileMode,
|
|
||||||
) -> Result<(), SystemError> {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), SystemError> {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_at(
|
|
||||||
&self,
|
|
||||||
_offset: usize,
|
|
||||||
_len: usize,
|
|
||||||
_buf: &mut [u8],
|
|
||||||
_data: &mut super::vfs::FilePrivateData,
|
|
||||||
) -> Result<usize, SystemError> {
|
|
||||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_at(
|
|
||||||
&self,
|
|
||||||
_offset: usize,
|
|
||||||
_len: usize,
|
|
||||||
_buf: &[u8],
|
|
||||||
_data: &mut super::vfs::FilePrivateData,
|
|
||||||
) -> Result<usize, SystemError> {
|
|
||||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll(&self) -> Result<super::vfs::PollStatus, SystemError> {
|
|
||||||
// 加锁
|
|
||||||
let inode: SpinLockGuard<SysFSInode> = self.0.lock();
|
|
||||||
|
|
||||||
// 检查当前inode是否为一个文件夹,如果是的话,就返回错误
|
|
||||||
if inode.metadata.file_type == FileType::Dir {
|
|
||||||
return Err(SystemError::EISDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(PollStatus::READ | PollStatus::WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
|
||||||
return Ok(self.0.lock().metadata.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
|
||||||
return self.0.lock().fs.upgrade().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, SystemError> {
|
|
||||||
let inode: SpinLockGuard<SysFSInode> = self.0.lock();
|
|
||||||
if inode.metadata.file_type != FileType::Dir {
|
|
||||||
return Err(SystemError::ENOTDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
match ino.into() {
|
|
||||||
0 => {
|
|
||||||
return Ok(String::from("."));
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
return Ok(String::from(".."));
|
|
||||||
}
|
|
||||||
ino => {
|
|
||||||
// 暴力遍历所有的children,判断inode id是否相同
|
|
||||||
// TODO: 优化这里,这个地方性能很差!
|
|
||||||
let mut key: Vec<String> = inode
|
|
||||||
.children
|
|
||||||
.keys()
|
|
||||||
.filter(|k| {
|
|
||||||
inode
|
|
||||||
.children
|
|
||||||
.get(*k)
|
|
||||||
.unwrap()
|
|
||||||
.metadata()
|
|
||||||
.unwrap()
|
|
||||||
.inode_id
|
|
||||||
.into()
|
|
||||||
== ino
|
|
||||||
})
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
match key.len() {
|
|
||||||
0=>{return Err(SystemError::ENOENT);}
|
|
||||||
1=>{return Ok(key.remove(0));}
|
|
||||||
_ => panic!("Sysfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id:?}, to find={to_find:?}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let inode = self.0.lock();
|
|
||||||
|
|
||||||
if inode.metadata.file_type != FileType::Dir {
|
|
||||||
return Err(SystemError::ENOTDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
match name {
|
|
||||||
"" | "." => {
|
|
||||||
return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
|
|
||||||
}
|
|
||||||
".." => {
|
|
||||||
return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
|
|
||||||
}
|
|
||||||
name => {
|
|
||||||
// 在子目录项中查找
|
|
||||||
// match inode.children.get(name) {
|
|
||||||
// Some(_) => {}
|
|
||||||
// None => kdebug!("Sysfs find {} error", name),
|
|
||||||
// }
|
|
||||||
return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
|
|
||||||
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn list(&self) -> Result<Vec<String>, SystemError> {
|
|
||||||
let info = self.metadata()?;
|
|
||||||
if info.file_type != FileType::Dir {
|
|
||||||
return Err(SystemError::ENOTDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut keys: Vec<String> = Vec::new();
|
|
||||||
keys.push(String::from("."));
|
|
||||||
keys.push(String::from(".."));
|
|
||||||
keys.append(&mut self.0.lock().children.keys().cloned().collect());
|
|
||||||
|
|
||||||
return Ok(keys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LockedSysFSInode {
|
|
||||||
fn do_create_with_data(
|
|
||||||
&self,
|
|
||||||
mut guard: SpinLockGuard<SysFSInode>,
|
|
||||||
name: &str,
|
|
||||||
file_type: FileType,
|
|
||||||
mode: ModeType,
|
|
||||||
data: usize,
|
|
||||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
if guard.metadata.file_type != FileType::Dir {
|
|
||||||
return Err(SystemError::ENOTDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有重名的,则返回
|
|
||||||
if guard.children.contains_key(name) {
|
|
||||||
return Err(SystemError::EEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建inode
|
|
||||||
let result: Arc<LockedSysFSInode> = Arc::new(LockedSysFSInode(SpinLock::new(SysFSInode {
|
|
||||||
parent: guard.self_ref.clone(),
|
|
||||||
self_ref: Weak::default(),
|
|
||||||
children: BTreeMap::new(),
|
|
||||||
metadata: Metadata {
|
|
||||||
dev_id: 0,
|
|
||||||
inode_id: generate_inode_id(),
|
|
||||||
size: 0,
|
|
||||||
blk_size: 0,
|
|
||||||
blocks: 0,
|
|
||||||
atime: TimeSpec::default(),
|
|
||||||
mtime: TimeSpec::default(),
|
|
||||||
ctime: TimeSpec::default(),
|
|
||||||
file_type,
|
|
||||||
mode,
|
|
||||||
nlinks: 1,
|
|
||||||
uid: 0,
|
|
||||||
gid: 0,
|
|
||||||
raw_dev: data,
|
|
||||||
},
|
|
||||||
fs: guard.fs.clone(),
|
|
||||||
})));
|
|
||||||
|
|
||||||
// 初始化inode的自引用的weak指针
|
|
||||||
result.0.lock().self_ref = Arc::downgrade(&result);
|
|
||||||
|
|
||||||
// 将子inode插入父inode的B树中
|
|
||||||
guard.children.insert(String::from(name), result.clone());
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 在当前目录下,创建一个目录
|
|
||||||
/// @param name: 目录名
|
|
||||||
/// @return 成功返回目录inode, 失败返回Err(错误码)
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn add_dir(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
||||||
let guard: SpinLockGuard<SysFSInode> = self.0.lock();
|
|
||||||
|
|
||||||
if guard.children.contains_key(name) {
|
|
||||||
return Err(SystemError::EEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.do_create_with_data(
|
|
||||||
guard,
|
|
||||||
name,
|
|
||||||
FileType::Dir,
|
|
||||||
ModeType::from_bits_truncate(0o755),
|
|
||||||
0,
|
|
||||||
) {
|
|
||||||
Ok(inode) => return Ok(inode),
|
|
||||||
Err(err) => {
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 在当前目录下,创建一个二进制文件
|
|
||||||
/// @param name: 文件名
|
|
||||||
/// @return 成功返回Ok(()), 失败返回Err(错误码)
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn add_file(&self, name: &str, file: Arc<dyn IndexNode>) -> Result<(), SystemError> {
|
|
||||||
let mut this = self.0.lock();
|
|
||||||
|
|
||||||
if this.children.contains_key(name) {
|
|
||||||
return Err(SystemError::EEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.children.insert(name.to_string(), file);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 为该inode创建硬链接
|
|
||||||
/// @param None
|
|
||||||
/// @return 当前inode强引用
|
|
||||||
#[inline]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn link(&self) -> Arc<dyn IndexNode> {
|
|
||||||
return self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.self_ref
|
|
||||||
.clone()
|
|
||||||
.upgrade()
|
|
||||||
.ok_or(SystemError::E2BIG)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(&self, name: &str) -> Result<(), SystemError> {
|
|
||||||
let x = self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.children
|
|
||||||
.remove(name)
|
|
||||||
.ok_or(SystemError::ENOENT)?;
|
|
||||||
|
|
||||||
drop(x);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief sys文件i节点(无锁)
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SysFSInode {
|
|
||||||
/// 指向父Inode的弱引用
|
|
||||||
parent: Weak<LockedSysFSInode>,
|
|
||||||
/// 指向自身的弱引用
|
|
||||||
self_ref: Weak<LockedSysFSInode>,
|
|
||||||
/// 子Inode的B树
|
|
||||||
children: BTreeMap<String, Arc<dyn IndexNode>>,
|
|
||||||
/// 指向inode所在的文件系统对象的指针
|
|
||||||
fs: Weak<SysFS>,
|
|
||||||
/// INode 元数据
|
|
||||||
metadata: Metadata,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SysFSInode {
|
|
||||||
pub fn new(file_type: FileType, mode: ModeType, data_: usize) -> Self {
|
|
||||||
return Self::new_with_parent(Weak::default(), file_type, mode, data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_with_parent(
|
|
||||||
parent: Weak<LockedSysFSInode>,
|
|
||||||
file_type: FileType,
|
|
||||||
mode: ModeType,
|
|
||||||
data_: usize,
|
|
||||||
) -> Self {
|
|
||||||
return SysFSInode {
|
|
||||||
parent: parent,
|
|
||||||
self_ref: Weak::default(),
|
|
||||||
children: BTreeMap::new(),
|
|
||||||
metadata: Metadata {
|
|
||||||
dev_id: 1,
|
|
||||||
inode_id: generate_inode_id(),
|
|
||||||
size: 0,
|
|
||||||
blk_size: 0,
|
|
||||||
blocks: 0,
|
|
||||||
atime: TimeSpec::default(),
|
|
||||||
mtime: TimeSpec::default(),
|
|
||||||
ctime: TimeSpec::default(),
|
|
||||||
file_type,
|
|
||||||
mode,
|
|
||||||
nlinks: 1,
|
|
||||||
uid: 0,
|
|
||||||
gid: 0,
|
|
||||||
raw_dev: data_,
|
|
||||||
},
|
|
||||||
fs: Weak::default(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,25 +35,21 @@ pub fn sysfs_init() -> Result<(), SystemError> {
|
|||||||
let mut result = None;
|
let mut result = None;
|
||||||
INIT.call_once(|| {
|
INIT.call_once(|| {
|
||||||
kinfo!("Initializing SysFS...");
|
kinfo!("Initializing SysFS...");
|
||||||
|
|
||||||
// 创建 sysfs 实例
|
// 创建 sysfs 实例
|
||||||
let sysfs: Arc<SysFS> = SysFS::new();
|
// let sysfs: Arc<OldSysFS> = OldSysFS::new();
|
||||||
|
let sysfs = SysFS::new();
|
||||||
|
unsafe { SYSFS_INSTANCE = Some(sysfs) };
|
||||||
|
|
||||||
// sysfs 挂载
|
// sysfs 挂载
|
||||||
let _t = ROOT_INODE()
|
let _t = ROOT_INODE()
|
||||||
.find("sys")
|
.find("sys")
|
||||||
.expect("Cannot find /sys")
|
.expect("Cannot find /sys")
|
||||||
.mount(sysfs)
|
.mount(sysfs_instance().fs().clone())
|
||||||
.expect("Failed to mount sysfs");
|
.expect("Failed to mount sysfs");
|
||||||
kinfo!("SysFS mounted.");
|
kinfo!("SysFS mounted.");
|
||||||
|
|
||||||
// 初始化platform总线
|
// kdebug!("sys_bus_init result: {:?}", SYS_BUS_INODE().list());
|
||||||
platform_bus_init().expect("platform bus init failed");
|
|
||||||
|
|
||||||
sys_bus_init(&SYS_BUS_INODE()).unwrap_or_else(|err| {
|
|
||||||
panic!("sys_bus_init failed: {:?}", err);
|
|
||||||
});
|
|
||||||
|
|
||||||
kdebug!("sys_bus_init result: {:?}", SYS_BUS_INODE().list());
|
|
||||||
result = Some(Ok(()));
|
result = Some(Ok(()));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -516,15 +64,131 @@ pub enum SysFSKernPrivateData {
|
|||||||
File(SysKernFilePriv),
|
File(SysKernFilePriv),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SysFSKernPrivateData {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
|
match self {
|
||||||
|
SysFSKernPrivateData::File(file) => {
|
||||||
|
let len = file.callback_read(buf)?;
|
||||||
|
if offset > 0 {
|
||||||
|
if len <= offset {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
let len = len - offset;
|
||||||
|
buf.copy_within(offset..offset + len, 0);
|
||||||
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
return Ok(len);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn callback_write(&self, buf: &[u8], _offset: usize) -> Result<usize, SystemError> {
|
||||||
|
match self {
|
||||||
|
SysFSKernPrivateData::File(file) => {
|
||||||
|
return file.callback_write(buf);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// sysfs文件目录的属性组
|
/// sysfs文件目录的属性组
|
||||||
pub trait AttributeGroup: Debug + Send + Sync {
|
pub trait AttributeGroup: Debug + Send + Sync {
|
||||||
fn name(&self) -> &str;
|
/// 属性组的名称
|
||||||
|
///
|
||||||
|
/// 如果属性组的名称为None,则所有的属性都会被添加到父目录下,而不是创建一个新的目录
|
||||||
|
fn name(&self) -> Option<&str>;
|
||||||
|
/// 属性组的属性列表
|
||||||
fn attrs(&self) -> &[&'static dyn Attribute];
|
fn attrs(&self) -> &[&'static dyn Attribute];
|
||||||
fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &dyn Attribute) -> bool;
|
|
||||||
|
/// 属性在当前属性组内的权限(该方法可选)
|
||||||
|
///
|
||||||
|
/// 如果返回None,则使用Attribute的mode()方法返回的权限
|
||||||
|
///
|
||||||
|
/// 如果返回Some,则使用返回的权限。
|
||||||
|
/// 如果要标识属性不可见,则返回Some(ModeType::empty())
|
||||||
|
fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &dyn Attribute) -> Option<ModeType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sysfs文件的属性
|
/// sysfs文件的属性
|
||||||
pub trait Attribute: Debug + Send + Sync {
|
pub trait Attribute: Debug + Send + Sync {
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
fn mode(&self) -> ModeType;
|
fn mode(&self) -> ModeType;
|
||||||
|
|
||||||
|
fn support(&self) -> SysFSOpsSupport;
|
||||||
|
|
||||||
|
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||||
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SysFSOps: Debug {
|
||||||
|
/// 获取当前文件的支持的操作
|
||||||
|
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
|
||||||
|
return attr.support();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, SystemError>;
|
||||||
|
|
||||||
|
fn store(
|
||||||
|
&self,
|
||||||
|
kobj: Arc<dyn KObject>,
|
||||||
|
attr: &dyn Attribute,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<usize, SystemError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct SysFSOpsSupport: u8{
|
||||||
|
const SHOW = 1 << 0;
|
||||||
|
const STORE = 1 << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SysFS {
|
||||||
|
root_inode: Arc<KernFSInode>,
|
||||||
|
kernfs: Arc<KernFS>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysFS {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let kernfs: Arc<KernFS> = KernFS::new();
|
||||||
|
|
||||||
|
let root_inode: Arc<KernFSInode> = kernfs.root_inode().downcast_arc().unwrap();
|
||||||
|
|
||||||
|
let sysfs = SysFS { root_inode, kernfs };
|
||||||
|
|
||||||
|
return sysfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root_inode(&self) -> &Arc<KernFSInode> {
|
||||||
|
return &self.root_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fs(&self) -> &Arc<KernFS> {
|
||||||
|
return &self.kernfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 警告:重复的sysfs entry
|
||||||
|
pub(self) fn warn_duplicate(&self, parent: &Arc<KernFSInode>, name: &str) {
|
||||||
|
let path = self.kernfs_path(parent);
|
||||||
|
kwarn!("duplicate sysfs entry: {path}/{name}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
38
kernel/src/filesystem/sysfs/symlink.rs
Normal file
38
kernel/src/filesystem/sysfs/symlink.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use alloc::{string::String, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{driver::base::kobject::KObject, syscall::SystemError};
|
||||||
|
|
||||||
|
use super::SysFS;
|
||||||
|
|
||||||
|
impl SysFS {
|
||||||
|
/// 在sysfs中创建一个符号链接
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj`: 要创建符号链接的kobject
|
||||||
|
/// - `target`: 符号链接的目标(在目标目录下创建)
|
||||||
|
/// - `name`: 符号链接的名称
|
||||||
|
///
|
||||||
|
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
|
||||||
|
pub fn create_link(
|
||||||
|
&self,
|
||||||
|
_kobj: &Arc<dyn KObject>,
|
||||||
|
_target: &Arc<dyn KObject>,
|
||||||
|
_name: String,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
todo!("sysfs create link")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 在sysfs中删除一个符号链接
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `kobj`: 要删除符号链接的kobject(符号链接所在目录)
|
||||||
|
/// - `name`: 符号链接的名称
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143
|
||||||
|
pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) -> Result<(), SystemError> {
|
||||||
|
todo!("sysfs remove link")
|
||||||
|
}
|
||||||
|
}
|
@ -280,7 +280,9 @@ impl File {
|
|||||||
let sub_inode: Arc<dyn IndexNode> = match inode.find(&name) {
|
let sub_inode: Arc<dyn IndexNode> = match inode.find(&name) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
kerror!("Readdir error: Failed to find sub inode, file={self:?}");
|
kerror!(
|
||||||
|
"Readdir error: Failed to find sub inode:{name:?}, file={self:?}, error={e:?}"
|
||||||
|
);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -559,6 +559,12 @@ pub trait FileSystem: Any + Sync + Send + Debug {
|
|||||||
fn as_any_ref(&self) -> &dyn Any;
|
fn as_any_ref(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DowncastArc for dyn FileSystem {
|
||||||
|
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FsInfo {
|
pub struct FsInfo {
|
||||||
/// 文件系统所在的块设备的id
|
/// 文件系统所在的块设备的id
|
||||||
|
@ -64,6 +64,19 @@ bitflags! {
|
|||||||
const S_IROTH = 0o0004;
|
const S_IROTH = 0o0004;
|
||||||
const S_IWOTH = 0o0002;
|
const S_IWOTH = 0o0002;
|
||||||
const S_IXOTH = 0o0001;
|
const S_IXOTH = 0o0001;
|
||||||
|
|
||||||
|
/// 0o777
|
||||||
|
const S_IRWXUGO = Self::S_IRWXU.bits | Self::S_IRWXG.bits | Self::S_IRWXO.bits;
|
||||||
|
/// 0o7777
|
||||||
|
const S_IALLUGO = Self::S_ISUID.bits | Self::S_ISGID.bits | Self::S_ISVTX.bits| Self::S_IRWXUGO.bits;
|
||||||
|
/// 0o444
|
||||||
|
const S_IRUGO = Self::S_IRUSR.bits | Self::S_IRGRP.bits | Self::S_IROTH.bits;
|
||||||
|
/// 0o222
|
||||||
|
const S_IWUGO = Self::S_IWUSR.bits | Self::S_IWGRP.bits | Self::S_IWOTH.bits;
|
||||||
|
/// 0o111
|
||||||
|
const S_IXUGO = Self::S_IXUSR.bits | Self::S_IXGRP.bits | Self::S_IXOTH.bits;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#![feature(arbitrary_self_types)]
|
#![feature(arbitrary_self_types)]
|
||||||
#![feature(asm_const)]
|
#![feature(asm_const)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(c_void_variant)]
|
#![feature(c_void_variant)]
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
kwarn,
|
kwarn,
|
||||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||||
@ -7,18 +9,19 @@ use crate::{
|
|||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
|
|
||||||
/// @brief 通知链节点
|
/// @brief 通知链节点
|
||||||
pub trait NotifierBlock<T> {
|
pub trait NotifierBlock<V: Clone + Copy, T>: Debug + Send + Sync {
|
||||||
/// @brief 通知链中注册的回调函数类型
|
/// @brief 通知链中注册的回调函数类型
|
||||||
fn notifier_call(&self, action: u64, data: Option<&T>) -> i32;
|
fn notifier_call(&self, action: V, data: Option<&T>) -> i32;
|
||||||
/// @brief 通知链节点的优先级
|
/// @brief 通知链节点的优先级
|
||||||
fn priority(&self) -> i32;
|
fn priority(&self) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 通知链
|
/// @brief 通知链
|
||||||
// TODO: 考虑使用红黑树封装
|
// TODO: 考虑使用红黑树封装
|
||||||
struct NotifierChain<T>(Vec<Arc<dyn NotifierBlock<T>>>);
|
#[derive(Debug)]
|
||||||
|
struct NotifierChain<V: Clone + Copy, T>(Vec<Arc<dyn NotifierBlock<V, T>>>);
|
||||||
|
|
||||||
impl<T> NotifierChain<T> {
|
impl<V: Clone + Copy, T> NotifierChain<V, T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(vec![])
|
Self(vec![])
|
||||||
}
|
}
|
||||||
@ -27,7 +30,7 @@ impl<T> NotifierChain<T> {
|
|||||||
/// @param unique_priority 检查通知链中优先级的唯一性
|
/// @param unique_priority 检查通知链中优先级的唯一性
|
||||||
pub fn register(
|
pub fn register(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: Arc<dyn NotifierBlock<T>>,
|
block: Arc<dyn NotifierBlock<V, T>>,
|
||||||
unique_priority: bool,
|
unique_priority: bool,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
let mut index: usize = 0;
|
let mut index: usize = 0;
|
||||||
@ -61,7 +64,7 @@ impl<T> NotifierChain<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 在通知链中取消注册节点
|
/// @brief 在通知链中取消注册节点
|
||||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
let remove = self
|
let remove = self
|
||||||
.0
|
.0
|
||||||
.drain_filter(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
|
.drain_filter(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
|
||||||
@ -71,13 +74,20 @@ impl<T> NotifierChain<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 通知链进行事件通知
|
/// 通知链进行事件通知
|
||||||
/// @param nr_to_call 回调函数次数
|
///
|
||||||
/// @return (最后一次回调函数的返回值,回调次数)
|
/// ## 参数
|
||||||
// TODO: 增加 NOTIFIER_STOP_MASK 相关功能
|
///
|
||||||
|
/// - nr_to_call 最大调用回调函数的数量,如果为None,则不限制次数
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// (最后一次回调函数的返回值,回调次数)
|
||||||
|
///
|
||||||
|
/// TODO: 增加 NOTIFIER_STOP_MASK 相关功能
|
||||||
pub fn call_chain(
|
pub fn call_chain(
|
||||||
&self,
|
&self,
|
||||||
action: u64,
|
action: V,
|
||||||
data: Option<&T>,
|
data: Option<&T>,
|
||||||
nr_to_call: Option<usize>,
|
nr_to_call: Option<usize>,
|
||||||
) -> (i32, usize) {
|
) -> (i32, usize) {
|
||||||
@ -96,34 +106,35 @@ impl<T> NotifierChain<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 原子的通知链,使用 SpinLock 进行同步
|
/// @brief 原子的通知链,使用 SpinLock 进行同步
|
||||||
pub struct AtomicNotifierChain<T>(SpinLock<NotifierChain<T>>);
|
#[derive(Debug)]
|
||||||
|
pub struct AtomicNotifierChain<V: Clone + Copy, T>(SpinLock<NotifierChain<V, T>>);
|
||||||
|
|
||||||
impl<T> AtomicNotifierChain<T> {
|
impl<V: Clone + Copy, T> AtomicNotifierChain<V, T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(SpinLock::new(NotifierChain::<T>::new()))
|
Self(SpinLock::new(NotifierChain::<V, T>::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.lock();
|
let mut notifier_chain_guard = self.0.lock();
|
||||||
return notifier_chain_guard.register(block, false);
|
return notifier_chain_guard.register(block, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_unique_prio(
|
pub fn register_unique_prio(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: Arc<dyn NotifierBlock<T>>,
|
block: Arc<dyn NotifierBlock<V, T>>,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.lock();
|
let mut notifier_chain_guard = self.0.lock();
|
||||||
return notifier_chain_guard.register(block, true);
|
return notifier_chain_guard.register(block, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.lock();
|
let mut notifier_chain_guard = self.0.lock();
|
||||||
return notifier_chain_guard.unregister(block);
|
return notifier_chain_guard.unregister(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_chain(
|
pub fn call_chain(
|
||||||
&self,
|
&self,
|
||||||
action: u64,
|
action: V,
|
||||||
data: Option<&T>,
|
data: Option<&T>,
|
||||||
nr_to_call: Option<usize>,
|
nr_to_call: Option<usize>,
|
||||||
) -> (i32, usize) {
|
) -> (i32, usize) {
|
||||||
@ -134,34 +145,35 @@ impl<T> AtomicNotifierChain<T> {
|
|||||||
|
|
||||||
/// @brief 可阻塞的通知链,使用 RwLock 进行同步
|
/// @brief 可阻塞的通知链,使用 RwLock 进行同步
|
||||||
// TODO: 使用 semaphore 封装
|
// TODO: 使用 semaphore 封装
|
||||||
pub struct BlockingNotifierChain<T>(RwLock<NotifierChain<T>>);
|
#[derive(Debug)]
|
||||||
|
pub struct BlockingNotifierChain<V: Clone + Copy, T>(RwLock<NotifierChain<V, T>>);
|
||||||
|
|
||||||
impl<T> BlockingNotifierChain<T> {
|
impl<V: Clone + Copy, T> BlockingNotifierChain<V, T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(RwLock::new(NotifierChain::<T>::new()))
|
Self(RwLock::new(NotifierChain::<V, T>::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.write();
|
let mut notifier_chain_guard = self.0.write();
|
||||||
return notifier_chain_guard.register(block, false);
|
return notifier_chain_guard.register(block, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_unique_prio(
|
pub fn register_unique_prio(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: Arc<dyn NotifierBlock<T>>,
|
block: Arc<dyn NotifierBlock<V, T>>,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.write();
|
let mut notifier_chain_guard = self.0.write();
|
||||||
return notifier_chain_guard.register(block, true);
|
return notifier_chain_guard.register(block, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
let mut notifier_chain_guard = self.0.write();
|
let mut notifier_chain_guard = self.0.write();
|
||||||
return notifier_chain_guard.unregister(block);
|
return notifier_chain_guard.unregister(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_chain(
|
pub fn call_chain(
|
||||||
&self,
|
&self,
|
||||||
action: u64,
|
action: V,
|
||||||
data: Option<&T>,
|
data: Option<&T>,
|
||||||
nr_to_call: Option<usize>,
|
nr_to_call: Option<usize>,
|
||||||
) -> (i32, usize) {
|
) -> (i32, usize) {
|
||||||
@ -171,24 +183,24 @@ impl<T> BlockingNotifierChain<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 原始的通知链,由调用者自行考虑同步
|
/// @brief 原始的通知链,由调用者自行考虑同步
|
||||||
pub struct RawNotifierChain<T>(NotifierChain<T>);
|
pub struct RawNotifierChain<V: Clone + Copy, T>(NotifierChain<V, T>);
|
||||||
|
|
||||||
impl<T> RawNotifierChain<T> {
|
impl<V: Clone + Copy, T> RawNotifierChain<V, T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(NotifierChain::<T>::new())
|
Self(NotifierChain::<V, T>::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
return self.0.register(block, false);
|
return self.0.register(block, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||||
return self.0.unregister(block);
|
return self.0.unregister(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_chain(
|
pub fn call_chain(
|
||||||
&self,
|
&self,
|
||||||
action: u64,
|
action: V,
|
||||||
data: Option<&T>,
|
data: Option<&T>,
|
||||||
nr_to_call: Option<usize>,
|
nr_to_call: Option<usize>,
|
||||||
) -> (i32, usize) {
|
) -> (i32, usize) {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include <driver/interrupt/apic/apic_timer.h>
|
#include <driver/interrupt/apic/apic_timer.h>
|
||||||
|
|
||||||
extern int rs_device_init();
|
extern int rs_driver_init();
|
||||||
extern int rs_tty_init();
|
extern int rs_tty_init();
|
||||||
extern void rs_softirq_init();
|
extern void rs_softirq_init();
|
||||||
extern void rs_mm_init();
|
extern void rs_mm_init();
|
||||||
@ -129,7 +129,8 @@ void system_initialize()
|
|||||||
rs_jiffies_init();
|
rs_jiffies_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
vfs_init();
|
vfs_init();
|
||||||
rs_device_init();
|
|
||||||
|
rs_driver_init();
|
||||||
rs_tty_init();
|
rs_tty_init();
|
||||||
|
|
||||||
rs_kthread_init();
|
rs_kthread_init();
|
||||||
|
@ -339,9 +339,11 @@ int shell_cmd_cat(int argc, char **argv)
|
|||||||
int l = read(fd, buf, 511);
|
int l = read(fd, buf, 511);
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
{
|
{
|
||||||
printf("ERROR: Cannot read file: %s\n", file_path);
|
printf("ERROR: Cannot read file: %s, errno = %d\n", file_path, errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (l == 0)
|
||||||
|
break;
|
||||||
buf[l] = '\0';
|
buf[l] = '\0';
|
||||||
|
|
||||||
file_size -= l;
|
file_size -= l;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user