mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
363 lines
11 KiB
Rust
363 lines
11 KiB
Rust
use super::{
|
||
bus::{bus_manager, Bus},
|
||
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
||
};
|
||
use crate::{
|
||
driver::base::{
|
||
device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager},
|
||
kobject::KObject,
|
||
},
|
||
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
||
};
|
||
use alloc::{
|
||
string::ToString,
|
||
sync::{Arc, Weak},
|
||
vec::Vec,
|
||
};
|
||
use core::fmt::Debug;
|
||
use log::error;
|
||
use system_error::SystemError;
|
||
|
||
/// @brief: Driver error
|
||
#[allow(dead_code)]
|
||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||
pub enum DriverError {
|
||
ProbeError, // 探测设备失败(该驱动不能初始化这个设备)
|
||
RegisterError, // 设备注册失败
|
||
AllocateResourceError, // 获取设备所需资源失败
|
||
UnsupportedOperation, // 不支持的操作
|
||
UnInitialized, // 未初始化
|
||
}
|
||
|
||
impl From<DriverError> for SystemError {
|
||
fn from(value: DriverError) -> Self {
|
||
match value {
|
||
DriverError::ProbeError => SystemError::ENODEV,
|
||
DriverError::RegisterError => SystemError::ENODEV,
|
||
DriverError::AllocateResourceError => SystemError::EIO,
|
||
DriverError::UnsupportedOperation => SystemError::EIO,
|
||
DriverError::UnInitialized => SystemError::ENODEV,
|
||
}
|
||
}
|
||
}
|
||
|
||
#[inline(always)]
|
||
pub fn driver_manager() -> &'static DriverManager {
|
||
&DriverManager
|
||
}
|
||
|
||
/// 驱动程序应当实现的trait
|
||
///
|
||
/// ## 注意
|
||
///
|
||
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Driver>,
|
||
/// 因此,所有的实现了 Driver trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Driver)]`,
|
||
/// 否则在运行时会报错
|
||
pub trait Driver: Sync + Send + Debug + KObject {
|
||
fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||
Err(SystemError::ENOSYS)
|
||
}
|
||
|
||
/// @brief: 获取驱动标识符
|
||
/// @parameter: None
|
||
/// @return: 该驱动驱动唯一标识符
|
||
fn id_table(&self) -> Option<IdTable>;
|
||
|
||
fn devices(&self) -> Vec<Arc<dyn Device>>;
|
||
|
||
/// 把设备加入当前驱动管理的列表中
|
||
fn add_device(&self, device: Arc<dyn Device>);
|
||
|
||
/// 从当前驱动管理的列表中删除设备
|
||
fn delete_device(&self, device: &Arc<dyn Device>);
|
||
|
||
/// 根据设备名称查找绑定到驱动的设备
|
||
///
|
||
/// 该方法是一个快速查找方法,要求驱动开发者自行实现。
|
||
///
|
||
/// 如果开发者没有实现该方法,则应当返回None
|
||
///
|
||
/// ## 注意
|
||
///
|
||
/// 这是一个内部方法,不应当被外部调用,若要查找设备,请使用`find_device_by_name()`
|
||
fn __find_device_by_name_fast(&self, _name: &str) -> Option<Arc<dyn Device>> {
|
||
None
|
||
}
|
||
|
||
/// 是否禁用sysfs的bind/unbind属性
|
||
///
|
||
/// ## 返回
|
||
///
|
||
/// - true: 禁用
|
||
/// - false: 不禁用(默认)
|
||
fn suppress_bind_attrs(&self) -> bool {
|
||
false
|
||
}
|
||
|
||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||
None
|
||
}
|
||
|
||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>);
|
||
|
||
fn groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||
&[]
|
||
}
|
||
|
||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||
&[]
|
||
}
|
||
|
||
/// 使用什么样的策略来探测设备
|
||
fn probe_type(&self) -> DriverProbeType {
|
||
DriverProbeType::DefaultStrategy
|
||
}
|
||
}
|
||
|
||
#[derive(Debug, Default)]
|
||
pub struct DriverCommonData {
|
||
pub devices: Vec<Arc<dyn Device>>,
|
||
pub bus: Option<Weak<dyn Bus>>,
|
||
}
|
||
|
||
impl DriverCommonData {
|
||
pub fn push_device(&mut self, device: Arc<dyn Device>) {
|
||
if !self.devices.iter().any(|d| Arc::ptr_eq(d, &device)) {
|
||
self.devices.push(device);
|
||
}
|
||
}
|
||
|
||
pub fn delete_device(&mut self, device: &Arc<dyn Device>) {
|
||
self.devices.retain(|d| !Arc::ptr_eq(d, device));
|
||
}
|
||
}
|
||
|
||
impl dyn Driver {
|
||
pub fn allows_async_probing(&self) -> bool {
|
||
match self.probe_type() {
|
||
DriverProbeType::PreferAsync => true,
|
||
DriverProbeType::ForceSync => false,
|
||
DriverProbeType::DefaultStrategy => {
|
||
// todo: 判断是否请求异步探测,如果是的话,就返回true
|
||
|
||
// 由于目前还没有支持异步探测,因此这里暂时返回false
|
||
false
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 根据条件寻找一个绑定到这个驱动的设备(低效实现)
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `matcher` - 匹配器
|
||
/// - `data` - 传给匹配器的数据
|
||
///
|
||
/// ## 注意
|
||
///
|
||
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
|
||
fn find_device_slow<T: Copy>(
|
||
&self,
|
||
matcher: &dyn DeviceMatcher<T>,
|
||
data: T,
|
||
) -> Option<Arc<dyn Device>> {
|
||
self.devices()
|
||
.into_iter()
|
||
.find(|dev| matcher.match_device(dev, data))
|
||
}
|
||
|
||
/// 根据设备名称查找绑定到驱动的设备
|
||
///
|
||
/// ## 注意
|
||
///
|
||
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
|
||
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
|
||
if let Some(r) = self.__find_device_by_name_fast(name) {
|
||
return Some(r);
|
||
}
|
||
|
||
return self.find_device_slow(&DeviceMatchName, name);
|
||
}
|
||
}
|
||
|
||
/// @brief: 驱动管理器
|
||
#[derive(Debug, Clone)]
|
||
pub struct DriverManager;
|
||
|
||
impl DriverManager {
|
||
/// 注册设备驱动。该设备驱动应当已经设置好其bus字段
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - driver: 驱动
|
||
///
|
||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/driver.c#222
|
||
pub fn register(&self, driver: Arc<dyn Driver>) -> Result<(), SystemError> {
|
||
let bus = driver.bus().and_then(|bus| bus.upgrade()).ok_or_else(|| {
|
||
error!(
|
||
"DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
|
||
driver.name()
|
||
);
|
||
SystemError::EINVAL
|
||
})?;
|
||
|
||
let drv_name = driver.name();
|
||
let other = bus.find_driver_by_name(&drv_name);
|
||
if other.is_some() {
|
||
error!(
|
||
"DriverManager::register() failed: driver '{}' already registered",
|
||
drv_name
|
||
);
|
||
return Err(SystemError::EBUSY);
|
||
}
|
||
|
||
bus_manager().add_driver(&driver)?;
|
||
|
||
self.add_groups(&driver, driver.groups()).map_err(|e| {
|
||
bus_manager().remove_driver(&driver);
|
||
e
|
||
})?;
|
||
|
||
// todo: 发送uevent
|
||
|
||
return Ok(());
|
||
}
|
||
|
||
/// 从系统中删除一个驱动程序
|
||
#[allow(dead_code)]
|
||
pub fn unregister(&self, driver: &Arc<dyn Driver>) {
|
||
self.remove_groups(driver, driver.groups());
|
||
bus_manager().remove_driver(driver);
|
||
}
|
||
|
||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#434
|
||
pub fn driver_sysfs_add(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||
if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
|
||
bus.subsystem()
|
||
.bus_notifier()
|
||
.call_chain(BusNotifyEvent::BindDriver, Some(dev), None);
|
||
}
|
||
let driver_kobj = dev.driver().unwrap() as Arc<dyn KObject>;
|
||
let device_kobj = dev.clone() as Arc<dyn KObject>;
|
||
|
||
let err_remove_device = |e| {
|
||
sysfs_instance().remove_link(&driver_kobj, dev.name());
|
||
Err(e)
|
||
};
|
||
|
||
let err_remove_driver = |e| {
|
||
sysfs_instance().remove_link(&device_kobj, "driver".to_string());
|
||
err_remove_device(e)
|
||
};
|
||
|
||
sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device_kobj.name())?;
|
||
|
||
if let Err(e) =
|
||
sysfs_instance().create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
|
||
{
|
||
return err_remove_device(e);
|
||
}
|
||
|
||
if let Err(e) = device_manager().create_file(dev, &DeviceAttrCoredump) {
|
||
return err_remove_driver(e);
|
||
}
|
||
|
||
return Ok(());
|
||
}
|
||
|
||
pub fn add_groups(
|
||
&self,
|
||
driver: &Arc<dyn Driver>,
|
||
groups: &'static [&dyn AttributeGroup],
|
||
) -> Result<(), SystemError> {
|
||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||
return sysfs_instance().create_groups(&kobj, groups);
|
||
}
|
||
|
||
pub fn remove_groups(&self, driver: &Arc<dyn Driver>, groups: &'static [&dyn AttributeGroup]) {
|
||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||
sysfs_instance().remove_groups(&kobj, groups);
|
||
}
|
||
|
||
/// 为指定的驱动创建一个属性文件
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `driver` 要创建属性文件的驱动
|
||
/// - `attr` 属性
|
||
pub fn create_attr_file(
|
||
&self,
|
||
driver: &Arc<dyn Driver>,
|
||
attr: &'static dyn Attribute,
|
||
) -> Result<(), SystemError> {
|
||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||
return sysfs_instance().create_file(&kobj, attr);
|
||
}
|
||
|
||
/// 为指定的驱动删除一个属性文件
|
||
///
|
||
/// 如果属性不存在,也不会报错
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `driver` 要删除属性文件的驱动
|
||
/// - `attr` 属性
|
||
pub fn remove_attr_file(&self, driver: &Arc<dyn Driver>, attr: &'static dyn Attribute) {
|
||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||
sysfs_instance().remove_file(&kobj, attr);
|
||
}
|
||
}
|
||
|
||
/// 驱动匹配器
|
||
///
|
||
/// 用于匹配驱动是否符合某个条件
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `T` - 匹配器的数据类型
|
||
/// - `data` - 匹配器的数据
|
||
pub trait DriverMatcher<T>: Debug {
|
||
fn match_driver(&self, driver: &Arc<dyn Driver>, data: T) -> bool;
|
||
}
|
||
|
||
/// 根据名称匹配驱动
|
||
#[derive(Debug)]
|
||
pub struct DriverMatchName;
|
||
|
||
impl DriverMatcher<&str> for DriverMatchName {
|
||
#[inline(always)]
|
||
fn match_driver(&self, driver: &Arc<dyn Driver>, data: &str) -> bool {
|
||
driver.name() == data
|
||
}
|
||
}
|
||
|
||
/// enum probe_type - device driver probe type to try
|
||
/// Device drivers may opt in for special handling of their
|
||
/// respective probe routines. This tells the core what to
|
||
/// expect and prefer.
|
||
///
|
||
/// Note that the end goal is to switch the kernel to use asynchronous
|
||
/// probing by default, so annotating drivers with
|
||
/// %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
|
||
/// to speed up boot process while we are validating the rest of the
|
||
/// drivers.
|
||
#[allow(dead_code)]
|
||
#[derive(Debug, Default)]
|
||
pub enum DriverProbeType {
|
||
/// Drivers for "slow" devices which
|
||
/// probing order is not essential for booting the system may
|
||
/// opt into executing their probes asynchronously.
|
||
PreferAsync,
|
||
|
||
/// Use this to annotate drivers that need
|
||
/// their probe routines to run synchronously with driver and
|
||
/// device registration (with the exception of -EPROBE_DEFER
|
||
/// handling - re-probing always ends up being done asynchronously).
|
||
ForceSync,
|
||
|
||
#[default]
|
||
/// Used by drivers that work equally well
|
||
/// whether probed synchronously or asynchronously.
|
||
DefaultStrategy,
|
||
}
|