新增设备驱动模型,为设备和驱动提供高层视图 (#227)

* 添加base mod

* 添加设备驱动模型相关文件

* 删除单独的mod文件,使用mod.rs,修改一些格式上的问题

* 移动驱动错误类型到该文件

* 修改一些格式上的问题
This commit is contained in:
TingHuang
2023-04-05 13:02:05 +08:00
committed by GitHub
parent 5d00b18528
commit 2a7d773d3d
8 changed files with 678 additions and 0 deletions

View File

@ -0,0 +1,156 @@
use alloc::{
collections::BTreeMap,
sync::Arc
};
use lazy_static::lazy_static;
use core::fmt::Debug;
use crate::libs::spinlock::SpinLock;
use super::{
driver::Driver,
DeviceState,
IdTable,
Device
};
/// @brief: 总线状态
#[derive(Debug, Copy, Clone)]
pub enum BusState {
NotInitialized = 0, // 未初始化
Initialized = 1, // 已初始化
UnDefined = 2, // 未定义的
}
/// @brief: 将u32类型转换为总线状态类型
impl From<u32> for BusState {
fn from(state: u32) -> Self {
match state {
0 => BusState::NotInitialized,
1 => BusState::Initialized,
_ => BusState::UnDefined,
}
}
}
/// @brief: 将总线状态类型转换为u32类型
impl From<DeviceState> for BusState {
fn from(state: DeviceState) -> Self {
match state {
DeviceState::Initialized => BusState::Initialized,
DeviceState::NotInitialized => BusState::NotInitialized,
DeviceState::UnDefined => BusState::UnDefined,
}
}
}
/// @brief: 将总线状态类型转换为设备状态类型
impl From<BusState> for DeviceState {
fn from(state: BusState) -> Self {
match state {
BusState::Initialized => DeviceState::Initialized,
BusState::NotInitialized => DeviceState::NotInitialized,
BusState::UnDefined => DeviceState::UnDefined,
}
}
}
/// @brief: 总线驱动trait所有总线驱动都应实现该trait
pub trait BusDriver: Driver {
/// @brief: 判断总线是否为空
/// @parameter: None
/// @return: 如果总线上设备和驱动的数量都为0则返回true否则返回false
fn is_empty(&self) -> bool;
}
/// @brief: 总线设备trait所有总线都应实现该trait
pub trait Bus: Device {}
/// @brief: 总线管理结构体
#[derive(Debug, Clone)]
pub struct BusManager {
buses: BTreeMap<IdTable, Arc<dyn Bus>>, // 总线设备表
bus_drvs: BTreeMap<IdTable, Arc<dyn BusDriver>>, // 总线驱动表
}
/// @brief: 总线管理结构体加锁
pub struct BusManagerLock(SpinLock<BusManager>);
/// @brief: 总线管理方法集
impl BusManagerLock {
/// @brief: 创建总线管理实例
/// @parameter: None
/// @return: 总线管理实例
#[inline]
#[allow(dead_code)]
pub fn new() -> Self {
BusManagerLock(SpinLock::new(BusManager {
buses: BTreeMap::new(),
bus_drvs: BTreeMap::new(),
}))
}
/// @brief: 添加总线
/// @parameter id_table: 总线标识符,用于唯一标识该总线
/// @parameter bus_dev: 总线实例
/// @return: None
#[inline]
#[allow(dead_code)]
pub fn add_bus(&self, id_table: IdTable, bus_dev: Arc<dyn Bus>) {
let mut bus_manager = self.0.lock();
bus_manager.buses.insert(id_table, bus_dev);
}
/// @brief: 添加总线驱动
/// @parameter id_table: 总线驱动标识符,用于唯一标识该总线驱动
/// @parameter bus_dev: 总线驱动实例
/// @return: None
#[inline]
#[allow(dead_code)]
pub fn add_bus_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: 卸载总线
/// @parameter id_table: 总线标识符,用于唯一标识该总线
/// @return: None
#[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: 卸载总线驱动
/// @parameter id_table: 总线驱动标识符,用于唯一标识该总线驱动
/// @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_bus_driver(&self, id_table: &IdTable) -> Option<Arc<dyn BusDriver>> {
let bus_manager = self.0.lock();
return bus_manager.bus_drvs.get(id_table).cloned();
}
}
lazy_static! {
pub static ref BUS_MANAGER: Arc<BusManagerLock> = Arc::new(BusManagerLock::new());
}

View File

@ -0,0 +1,19 @@
use super::IdTable;
use core::{any::Any, fmt::Debug};
/// @brief: Driver error
#[allow(dead_code)]
#[derive(Debug)]
#[derive(PartialEq, Eq)]
#[derive(Clone, Copy)]
pub enum DriverError {
ProbeError,
}
/// @brief: 所有设备驱动都应该实现该trait
pub trait Driver: Any + Send + Sync + Debug {
/// @brief: 获取设备驱动标识符
/// @parameter: None
/// @return: 该设备驱动唯一标识符
fn get_id_table(&self) -> IdTable;
}

View File

@ -0,0 +1,92 @@
use core::{any::Any, fmt::Debug};
pub mod bus;
pub mod driver;
/// @brief: 设备类型
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
Bus,
Net,
Gpu,
Input,
Block,
Rtc,
Serial,
Intc,
PlatformDev,
}
/// @brief: 设备标识符类型
#[derive(Debug)]
#[derive(Clone)]
#[derive(Hash)]
#[derive(PartialOrd, PartialEq)]
#[derive(Ord, Eq)]
pub struct IdTable(&'static str, u32);
/// @brief: 设备标识符操作方法集
impl IdTable {
/// @brief: 创建一个新的设备标识符
/// @parameter name: 设备名
/// @parameter id: 设备id
/// @return: 设备标识符
pub fn new(name: &'static str, id: u32) -> IdTable {
Self(name, id)
}
}
/// @brief: 设备当前状态
#[derive(Debug)]
#[derive(Clone, Copy)]
pub enum DeviceState {
NotInitialized = 0,
Initialized = 1,
UnDefined = 2,
}
/// @brief: 设备错误类型
#[derive(Debug, Copy, Clone)]
pub enum DeviceError {
DriverExists, // 设备已存在
DeviceExists, // 驱动已存在
InitializeFailed, // 初始化错误
NoDeviceForDriver, // 没有合适的设备匹配驱动
NoDriverForDevice, // 没有合适的驱动匹配设备
}
/// @brief: 将u32类型转换为设备状态类型
impl From<u32> for DeviceState {
fn from(state: u32) -> Self {
match state {
0 => DeviceState::NotInitialized,
1 => DeviceState::Initialized,
_ => todo!(),
}
}
}
/// @brief: 将设备状态转换为u32类型
impl From<DeviceState> for u32 {
fn from(state: DeviceState) -> Self {
match state {
DeviceState::NotInitialized => 0,
DeviceState::Initialized => 1,
DeviceState::UnDefined => 2,
}
}
}
/// @brief: 所有设备都应该实现该trait
pub trait Device: Any + Send + Sync + Debug {
/// @brief: 获取设备类型
/// @parameter: None
/// @return: 实现该trait的设备所属类型
fn get_type(&self) -> DeviceType;
/// @brief: 获取设备标识
/// @parameter: None
/// @return: 该设备唯一标识
fn get_id_table(&self) -> IdTable;
}

View File

@ -0,0 +1,2 @@
pub mod platform;
pub mod device;

View File

@ -0,0 +1,347 @@
use alloc::{
collections::{BTreeSet, BTreeMap},
vec::Vec, sync::Arc
};
use lazy_static::lazy_static;
use core::fmt::Debug;
use super::device::{
bus::{
BusDriver,
BusState,
BUS_MANAGER,
Bus
},
driver::Driver,
IdTable,
DeviceError,
DeviceState,
DeviceType, Device
};
use crate::libs::{rwlock::RwLock, mutex::Mutex};
use platform_device::PlatformDevice;
use platform_driver::PlatformDriver;
pub mod platform_device;
pub mod platform_driver;
/// @brief: platform总线匹配表
/// 总线上的设备和驱动都存在一份匹配表
/// 根据匹配表条目是否匹配来辨识设备和驱动能否进行匹配
#[derive(Debug)]
pub struct CompatibleTable(BTreeSet<&'static str>);
/// @brief: 匹配表操作方法集
impl CompatibleTable {
/// @brief: 创建一个新的匹配表
/// @parameter id_vec: 匹配条目数组
/// @return: 匹配表
#[inline]
#[allow(dead_code)]
pub fn new(id_vec: Vec<&'static str>) -> CompatibleTable {
CompatibleTable(BTreeSet::from_iter(id_vec.iter().cloned()))
}
/// @brief: 判断两个匹配表是否能够匹配
/// @parameter other: 其他匹配表
/// @return: 如果匹配成功返回true否则返回false
#[allow(dead_code)]
pub fn matches(&self, other: &CompatibleTable) -> bool {
for id in &self.0 {
if other.0.contains(id) {
return true;
}
}
return false;
}
}
/// @brief: platform总线驱动
#[derive(Debug)]
pub struct PlatformBusDriver {
drivers: RwLock<BTreeMap<IdTable, Arc<dyn PlatformDriver>>>, // 总线上所有驱动
devices: RwLock<BTreeMap<IdTable, Arc<dyn PlatformDevice>>>, // 总线上所有设备
}
impl PlatformBusDriver {
/// @brief: 创建一个platform总线驱动该驱动用于匹配plaform总线
/// @parameter: None
/// @return: platfor总线驱动
#[inline]
#[allow(dead_code)]
pub fn new() -> Self {
Self {
drivers: RwLock::new(BTreeMap::new()),
devices: RwLock::new(BTreeMap::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.devices.read();
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.drivers.read();
return driver_map.get(id_table).cloned();
}
/// @brief: 注册platform类型驱动
/// @parameter driver: platform类型驱动该驱动需要实现PlatformDriver trait
/// @return: 注册成功返回Ok(()),注册失败返回BusError类型
#[allow(dead_code)]
fn register_platform_driver(&mut self, driver: Arc<dyn PlatformDriver>) -> Result<(), DeviceError> {
let id_table = driver.get_id_table();
let mut drivers = self.drivers.write();
// 如果存在同类型的驱动,返回错误
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>) {
let id_table = driver.get_id_table();
self.drivers.write().remove(&id_table);
}
/// @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.get_id_table();
let mut devices = self.devices.write();
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.get_id_table();
self.devices.write().remove(&id_table);
}
/// @brief: 匹配platform类型驱动
/// @parameter driver: platform类型驱动
/// @return: 如果匹配成功返回成功驱动的设备数否则返回BusError类型
#[allow(dead_code)]
fn driver_match_device(&self, driver: Arc<dyn PlatformDriver>) -> Result<i32, DeviceError> {
let mut num = 0;
let devices = self.devices.read();
for (_dev_id_table, device) in devices.iter() {
if device.get_compatible_table().matches(&driver.get_compatible_table()) {
if !device.is_initialized() {
// 设备未初始化调用驱动probe函数
match driver.probe(device.clone()) {
Ok(()) => {
num = num + 1;
device.set_state(DeviceState::Initialized)
},
// 可以驱动很多设备,一个设备初始化出错即返回
Err(_) => return Err(DeviceError::InitializeFailed),
}
}
}
}
if num == 0 {
return Err(DeviceError::NoDeviceForDriver);
} else {
return Ok(num);
}
}
/// @brief: 匹配platform上的设备
/// @parameter driver: platform类型设备
/// @return: 如果匹配成功返回Ok(())否则返回BusError类型
#[allow(dead_code)]
fn device_match_driver(&self, device: Arc<dyn PlatformDevice>) -> Result<(), DeviceError> {
let drivers = self.drivers.read();
for (_drv_id_table, driver) in &*drivers {
if driver.get_compatible_table().matches(&device.get_compatible_table()) {
match driver.probe(device.clone()) {
Ok(_driver) => {
// 将设备状态置为已初始化
device.set_state(DeviceState::Initialized);
return Ok(());
}
Err(_) => return Err(DeviceError::InitializeFailed),
}
}
}
return Err(DeviceError::NoDriverForDevice);
}
}
/// @brief: 为PlatformBusDriver实现Driver trait
impl Driver for PlatformBusDriver {
fn get_id_table(&self) -> IdTable {
IdTable::new("PlatformBusDriver", 0)
}
}
/// @brief: 为PlatformBusDriver实现BusDriver trait
impl BusDriver for PlatformBusDriver {
fn is_empty(&self) -> bool {
if self.devices.read().is_empty() && self.drivers.read().is_empty() {
return true;
} else {
return false;
}
}
}
/// @brief: platform总线
#[derive(Debug)]
#[derive(Clone)]
pub struct Platform {
state: Arc<Mutex<BusState>>, // 总线状态
driver: Option<Arc<PlatformBusDriver>>, // 总线驱动
}
/// @brief: platform方法集
impl Platform {
/// @brief: 创建一个platform总线实例
/// @parameter: None
/// @return: platform总线实例
pub fn new() -> Self {
Self {
state: Arc::new(Mutex::new(BusState::NotInitialized)),
driver: Option::None,
}
}
/// @brief: 获取总线的匹配表
/// @parameter: None
/// @return: platform总线匹配表
#[inline]
#[allow(dead_code)]
fn get_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.state.lock();
match *state {
BusState::Initialized => true,
_ => false,
}
}
/// @brief: 设置总线状态
/// @parameter set_state: 总线状态BusState
/// @return: None
#[inline]
fn set_state(&self, set_state: BusState) {
let mut state = self.state.lock();
*state = set_state;
}
/// @brief: 获取总线状态
/// @parameter: None
/// @return: 总线状态
#[inline]
#[allow(dead_code)]
fn get_state(&self) -> BusState {
let state = self.state.lock();
return *state;
}
/// @brief:
/// @parameter: None
/// @return: 总线状态
#[inline]
#[allow(dead_code)]
fn set_driver(&mut self, driver: Option<Arc<PlatformBusDriver>>) {
self.driver = driver;
}
}
/// @brief: 为Platform实现Device traitplatform总线也是一种设备属于总线设备类型
impl Device for Platform {
/// @brief: 获取platform设备类型
/// @parameter: None
/// @return: Bus类型
#[inline]
#[allow(dead_code)]
fn get_type(&self) -> DeviceType {
return DeviceType::Bus;
}
/// @brief: 获取platform设备标识符
/// @parameter: None
/// @return: platform总线设备标识符
#[inline]
#[allow(dead_code)]
fn get_id_table(&self) -> IdTable {
IdTable::new("platform", 0)
}
}
/// @brief: 为Platform实现Bus traitplatform总线是一种总线设备
impl Bus for Platform {}
lazy_static! {
pub static ref BUS_PLATFORM_DRIVER: Arc<PlatformBusDriver> = Arc::new(PlatformBusDriver::new());
pub static ref BUS_PLATFORM_DEVICE: Arc<Platform> = Arc::new(Platform::new());
}
/// @brief: 初始化platform总线
/// @parameter: None
/// @return: None
#[allow(dead_code)]
pub fn platform_bus_init() {
BUS_MANAGER.add_bus_driver(BUS_PLATFORM_DRIVER.get_id_table(), BUS_PLATFORM_DRIVER.clone());
BUS_MANAGER.add_bus(BUS_PLATFORM_DEVICE.get_id_table(), BUS_PLATFORM_DEVICE.clone());
BUS_PLATFORM_DEVICE.set_state(BusState::Initialized);
}
#[no_mangle]
extern "C" fn c_platform_bus_init() {
BUS_MANAGER.add_bus_driver(BUS_PLATFORM_DRIVER.get_id_table(), BUS_PLATFORM_DRIVER.clone());
BUS_MANAGER.add_bus(BUS_PLATFORM_DEVICE.get_id_table(), BUS_PLATFORM_DEVICE.clone());
BUS_PLATFORM_DEVICE.set_state(BusState::Initialized);
}

View File

@ -0,0 +1,38 @@
use alloc::sync::Arc;
use super::{
super::device::{
Device,
DeviceType,
DeviceState
},
CompatibleTable, platform_driver::PlatformDriver
};
/// @brief: 实现该trait的设备实例应挂载在platform总线上
/// 同时应该实现Device trait
pub trait PlatformDevice: Device {
fn get_type(&self) -> DeviceType {
DeviceType::PlatformDev
}
/// @brief: 获取设备匹配表
/// @parameter: None
/// @return: 设备匹配表
fn get_compatible_table(&self) -> CompatibleTable;
/// @brief: 判断设备是否初始化
/// @parameter: None
/// @return: 如果已经初始化返回true否则返回false
fn is_initialized(&self) -> bool;
/// @brief: 设置设备状态
/// @parameter set_state: 设备状态
/// @return: None
fn set_state(&self, set_state: DeviceState);
/// @brief: 设置platform设备驱动
/// @parameter driver: platform设备驱动
/// @return: None
fn set_driver(&self, driver: Option<Arc<dyn PlatformDriver>>);
}

View File

@ -0,0 +1,23 @@
use alloc::sync::Arc;
use super::{
super::device::driver::{
Driver,
DriverError
},
platform_device::PlatformDevice,
CompatibleTable,
};
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上
/// 同时应该实现Driver trait
pub trait PlatformDriver: Driver {
/// @brief: 设备驱动探测函数,此函数在设备和驱动匹配成功后调用
/// @parameter device: 匹配成功的设备实例
/// @return: 成功驱动设备返回Ok(())否则返回DriverError
fn probe(&self, device: Arc<dyn PlatformDevice>) -> Result<(), DriverError>;
/// @brief: 获取驱动匹配表
/// @parameter: None
/// @return: 驱动匹配表
fn get_compatible_table(&self) -> CompatibleTable;
}

View File

@ -6,3 +6,4 @@ pub mod tty;
pub mod uart; pub mod uart;
pub mod video; pub mod video;
pub mod virtio; pub mod virtio;
pub mod base;