注册串口设备,创建字符设备框架(#290)

* 按照rust规范修改两个函数名称

* 修改一些函数句柄以符合rust规范

* 添加字符设备相关

* 添加字符设备相关文件

* 添加字符设备驱动框架代码

* 将串口注册

* 规范代码
This commit is contained in:
TingHuang
2023-07-12 12:49:45 +08:00
committed by GitHub
parent cc36cf4a18
commit 0663027b11
12 changed files with 751 additions and 45 deletions

View File

@ -0,0 +1,285 @@
use super::{
device::{mkdev, DeviceNumber, KObject},
map::{kobj_map, kobj_unmap, LockedKObjMap},
};
use crate::{filesystem::vfs::IndexNode, kerror, libs::spinlock::SpinLock, syscall::SystemError};
use alloc::{sync::Arc, vec::Vec};
use core::cmp::Ordering;
const CHARDEV_MAJOR_HASH_SIZE: usize = 255;
const CHARDEV_MAJOR_MAX: usize = 512;
const MINOR_BITS: usize = 20;
const MINOR_MASK: usize = 1 << MINOR_BITS - 1;
/* Marks the bottom of the first segment of free char majors */
const CHARDEV_MAJOR_DYN_END: usize = 234;
/* Marks the top and bottom of the second segment of free char majors */
const CHARDEV_MAJOR_DYN_EXT_START: usize = 511;
const CHARDEV_MAJOR_DYN_EXT_END: usize = 384;
lazy_static! {
// 全局字符设备号管理实例
pub static ref CHARDEVS: Arc<LockedChrDevs> = Arc::new(LockedChrDevs::default());
// 全局字符设备管理实例
pub static ref CDEVMAP: Arc<LockedKObjMap> = Arc::new(LockedKObjMap::default());
}
pub trait CharDevice: KObject {
/// @brief: 打开设备
/// @parameter: file: devfs inode
/// @return: 打开成功返回OK(()),失败,返回错误代码
fn open(&self, file: Arc<dyn IndexNode>) -> Result<(), SystemError>;
/// @brief: 关闭设备
/// @parameter: file: devfs inode
/// @return: 关闭成功返回OK(()),失败,返回错误代码
fn close(&self, file: Arc<dyn IndexNode>) -> Result<(), SystemError>;
}
// 管理字符设备号的map(加锁)
pub struct LockedChrDevs(SpinLock<ChrDevs>);
impl Default for LockedChrDevs {
fn default() -> Self {
LockedChrDevs(SpinLock::new(ChrDevs::default()))
}
}
// 管理字符设备号的map
#[derive(Debug)]
struct ChrDevs(Vec<Vec<CharDeviceStruct>>);
impl Default for ChrDevs {
fn default() -> Self {
ChrDevs(vec![Vec::new(); CHARDEV_MAJOR_HASH_SIZE])
}
}
// 字符设备在系统中的实例devfs通过该结构与实际字符设备进行联系
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CharDeviceStruct {
dev_t: DeviceNumber, //起始设备号
minorct: usize, // 次设备号数量
name: &'static str, //字符设备名
}
impl CharDeviceStruct {
/// @brief: 创建实例
/// @parameter: dev_t: 设备号
/// minorct: 次设备号数量
/// name: 字符设备名
/// char: 字符设备实例
/// @return: 实例
///
#[allow(dead_code)]
pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self {
Self {
dev_t,
minorct,
name,
}
}
/// @brief: 获取起始次设备号
/// @parameter: None
/// @return: 起始设备号
///
#[allow(dead_code)]
pub fn device_number(&self) -> DeviceNumber {
self.dev_t
}
/// @brief: 获取起始次设备号
/// @parameter: None
/// @return: 起始设备号
///
#[allow(dead_code)]
pub fn base_minor(&self) -> usize {
self.dev_t.minor()
}
/// @brief: 获取次设备号数量
/// @parameter: None
/// @return: 次设备号数量
#[allow(dead_code)]
pub fn minorct(&self) -> usize {
self.minorct
}
}
/// @brief 字符设备框架函数集
pub struct CharDevOps;
impl CharDevOps {
/// @brief: 主设备号转下标
/// @parameter: major: 主设备号
/// @return: 返回下标
#[allow(dead_code)]
fn major_to_index(major: usize) -> usize {
return major % CHARDEV_MAJOR_HASH_SIZE;
}
/// @brief: 动态获取主设备号
/// @parameter: None
/// @return: 如果成功,返回主设备号,否则,返回错误码
#[allow(dead_code)]
fn find_dynamic_major() -> Result<usize, SystemError> {
let chardevs = CHARDEVS.0.lock();
// 寻找主设备号为234255的设备
for index in (CHARDEV_MAJOR_DYN_END..CHARDEV_MAJOR_HASH_SIZE).rev() {
if let Some(item) = chardevs.0.get(index) {
if item.is_empty() {
return Ok(index); // 返回可用的主设备号
}
}
}
// 寻找主设备号在384511的设备
for index in (CHARDEV_MAJOR_DYN_EXT_END + 1..CHARDEV_MAJOR_DYN_EXT_START + 1).rev() {
if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) {
let mut flag = true;
for item in chardevss {
if item.device_number().major() == index {
flag = false;
break;
}
}
if flag {
// 如果数组中不存在主设备号等于index的设备
return Ok(index); // 返回可用的主设备号
}
}
}
return Err(SystemError::EBUSY);
}
/// @brief: 注册设备号,该函数需要指定主设备号
/// @parameter: from: 主设备号
/// count: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功,返回设备号,否则,返回错误码
#[allow(dead_code)]
pub fn register_chardev_region(
from: DeviceNumber,
count: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
Self::__register_chardev_region(from, count, name)
}
/// @brief: 注册设备号,该函数自动分配主设备号
/// @parameter: baseminor: 主设备号
/// count: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功返回否则返回false
#[allow(dead_code)]
pub fn alloc_chardev_region(
baseminor: usize,
count: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
Self::__register_chardev_region(mkdev(0, baseminor), count, name)
}
/// @brief: 注册设备号
/// @parameter: device_number: 设备号主设备号如果为0则动态分配
/// minorct: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功,返回设备号,否则,返回错误码
fn __register_chardev_region(
device_number: DeviceNumber,
minorct: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
let mut major = device_number.major();
let baseminor = device_number.minor();
if major >= CHARDEV_MAJOR_MAX {
kerror!(
"CHARDEV {} major requested {} is greater than the maximum {}\n",
name,
major,
CHARDEV_MAJOR_MAX - 1
);
}
if minorct > MINOR_MASK + 1 - baseminor {
kerror!("CHARDEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
}
let chardev = CharDeviceStruct::new(mkdev(major, baseminor), minorct, name);
if major == 0 {
// 如果主设备号为0,则自动分配主设备号
major = Self::find_dynamic_major().expect("Find synamic major error.\n");
}
if let Some(items) = CHARDEVS.0.lock().0.get_mut(Self::major_to_index(major)) {
let mut insert_index: usize = 0;
for (index, item) in items.iter().enumerate() {
insert_index = index;
match item.device_number().major().cmp(&major) {
Ordering::Less => continue,
Ordering::Greater => {
break; // 大于则向后插入
}
Ordering::Equal => {
if item.device_number().minor() + item.minorct() <= baseminor {
continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
}
if item.base_minor() >= baseminor + minorct {
break; // 在此处插入
}
return Err(SystemError::EBUSY); // 存在重合的次设备号
}
}
}
items.insert(insert_index, chardev);
}
return Ok(mkdev(major, baseminor));
}
/// @brief: 注销设备号
/// @parameter: major: 主设备号如果为0动态分配
/// baseminor: 起始次设备号
/// minorct: 次设备号数量
/// @return: 如果注销成功,返回(),否则,返回错误码
fn __unregister_chardev_region(
device_number: DeviceNumber,
minorct: usize,
) -> Result<(), SystemError> {
if let Some(items) = CHARDEVS
.0
.lock()
.0
.get_mut(Self::major_to_index(device_number.major()))
{
for (index, item) in items.iter().enumerate() {
if item.device_number() == device_number && item.minorct() == minorct {
// 设备号和数量都相等
items.remove(index);
return Ok(());
}
}
}
return Err(SystemError::EBUSY);
}
/// @brief: 字符设备注册
/// @parameter: cdev: 字符设备实例
/// dev_t: 字符设备号
/// range: 次设备号范围
/// @return: none
#[allow(dead_code)]
pub fn cdev_add(cdev: Arc<dyn CharDevice>, dev_t: DeviceNumber, range: usize) {
if Into::<usize>::into(dev_t) == 0 {
kerror!("Device number can't be 0!\n");
}
kobj_map(CDEVMAP.clone(), dev_t, range, cdev);
}
/// @brief: 字符设备注销
/// @parameter: dev_t: 字符设备号
/// range: 次设备号范围
/// @return: none
#[allow(dead_code)]
pub fn cdev_del(dev_t: DeviceNumber, range: usize) {
kobj_unmap(CDEVMAP.clone(), dev_t, range);
}
}

View File

@ -175,8 +175,8 @@ impl LockedBusManager {
/// @parameter bus: Bus设备实体
/// @return: 成功:() 失败:DeviceError
pub fn bus_register<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone());
match sys_bus_register(&bus.get_id_table().to_name()) {
BUS_MANAGER.add_bus(bus.id_table(), bus.clone());
match sys_bus_register(&bus.id_table().to_name()) {
Ok(inode) => {
let _ = sys_bus_init(&inode);
return device_register(bus);
@ -190,7 +190,7 @@ pub fn bus_register<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
/// @return: 成功:() 失败:DeviceError
#[allow(dead_code)]
pub fn bus_unregister<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone());
BUS_MANAGER.add_bus(bus.id_table(), bus.clone());
return device_unregister(bus);
}
@ -198,7 +198,7 @@ pub fn bus_unregister<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
/// @parameter bus: Bus设备驱动实体
/// @return: 成功:() 失败:DeviceError
pub fn bus_driver_register<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone());
BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone());
return driver_register(bus_driver);
}
@ -207,6 +207,6 @@ pub fn bus_driver_register<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), Drive
/// @return: 成功:() 失败:DeviceError
#[allow(dead_code)]
pub fn bus_driver_unregister<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone());
BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone());
return driver_unregister(bus_driver);
}

View File

@ -1,7 +1,7 @@
use super::IdTable;
use super::{IdTable, KObject};
use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError};
use alloc::{collections::BTreeMap, sync::Arc};
use core::{any::Any, fmt::Debug};
use core::fmt::Debug;
lazy_static! {
pub static ref DRIVER_MANAGER: Arc<LockedDriverManager> = Arc::new(LockedDriverManager::new());
@ -25,16 +25,16 @@ impl Into<SystemError> for DriverError {
}
/// @brief: 所有驱动驱动都应该实现该trait
pub trait Driver: Any + Send + Sync + Debug {
pub trait Driver: KObject {
/// @brief: 本函数用于实现动态转换
/// @parameter: None
/// @return: 该驱动驱动唯一标识符
/// @return: any
fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
/// @brief: 获取驱动驱动标识符
/// @parameter: None
/// @return: 该驱动驱动唯一标识符
fn get_id_table(&self) -> IdTable;
fn id_table(&self) -> IdTable;
/// @brief: 设置驱动的sys information
/// @parameter id_table: 驱动标识符,用于唯一标识该驱动
@ -125,7 +125,7 @@ impl DriverManager {
/// @parameter: name: 驱动名
/// @return: 操作成功,返回(),操作失败,返回错误码
pub fn driver_register<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
DRIVER_MANAGER.add_driver(driver.get_id_table(), driver);
DRIVER_MANAGER.add_driver(driver.id_table(), driver);
return Ok(());
}
@ -134,6 +134,6 @@ pub fn driver_register<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
/// @return: 操作成功,返回(),操作失败,返回错误码
#[allow(dead_code)]
pub fn driver_unregister<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
DRIVER_MANAGER.add_driver(driver.get_id_table(), driver);
DRIVER_MANAGER.add_driver(driver.id_table(), driver);
return Ok(());
}

View File

@ -1,5 +1,3 @@
use alloc::{collections::BTreeMap, string::String, sync::Arc};
use crate::{
filesystem::{
sysfs::{
@ -11,6 +9,7 @@ use crate::{
libs::spinlock::SpinLock,
syscall::SystemError,
};
use alloc::{collections::BTreeMap, string::String, sync::Arc};
use core::{any::Any, fmt::Debug};
pub mod bus;
@ -20,6 +19,61 @@ lazy_static! {
pub static ref DEVICE_MANAGER: Arc<LockedDeviceManager> = Arc::new(LockedDeviceManager::new());
}
pub trait KObject: Any + Send + Sync + Debug {}
/// @brief: 设备号实例
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub struct DeviceNumber(usize);
impl Default for DeviceNumber {
fn default() -> Self {
DeviceNumber(0)
}
}
impl From<usize> for DeviceNumber {
fn from(dev_t: usize) -> Self {
DeviceNumber(dev_t)
}
}
impl Into<usize> for DeviceNumber {
fn into(self) -> usize {
self.0
}
}
impl DeviceNumber {
/// @brief: 设备号创建
/// @parameter: dev_t: 设备号
/// @return: 设备号实例
pub fn new(dev_t: usize) -> DeviceNumber {
Self(dev_t)
}
/// @brief: 获取主设备号
/// @parameter: none
/// @return: 主设备号
pub fn major(&self) -> usize {
(self.0 >> 20) & 0xfff
}
/// @brief: 获取次设备号
/// @parameter: none
/// @return: 次设备号
pub fn minor(&self) -> usize {
self.0 & 0xfffff
}
}
/// @brief: 根据主次设备号创建设备号实例
/// @parameter: major: 主设备号
/// minor: 次设备号
/// @return: 设备号实例
pub fn mkdev(major: usize, minor: usize) -> DeviceNumber {
DeviceNumber(((major & 0xfff) << 20) | (minor & 0xfffff))
}
/// @brief: 设备类型
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
@ -112,16 +166,21 @@ impl From<DeviceState> for u32 {
}
/// @brief: 所有设备都应该实现该trait
pub trait Device: Any + Send + Sync + Debug {
pub trait Device: KObject {
/// @brief: 本函数用于实现动态转换
/// @parameter: None
/// @return: any
fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
/// @brief: 获取设备类型
/// @parameter: None
/// @return: 实现该trait的设备所属类型
fn get_type(&self) -> DeviceType;
fn dev_type(&self) -> DeviceType;
/// @brief: 获取设备标识
/// @parameter: None
/// @return: 该设备唯一标识
fn get_id_table(&self) -> IdTable;
fn id_table(&self) -> IdTable;
/// @brief: 设置sysfs info
/// @parameter: None
@ -208,8 +267,8 @@ impl DeviceManager {
/// @parameter: name: 设备名
/// @return: 操作成功,返回(),操作失败,返回错误码
pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
DEVICE_MANAGER.add_device(device.get_id_table(), device.clone());
match sys_device_register(&device.get_id_table().to_name()) {
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
match sys_device_register(&device.id_table().to_name()) {
Ok(sys_info) => {
device.set_sys_info(Some(sys_info));
return Ok(());
@ -222,8 +281,8 @@ pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
/// @parameter: name: 设备名
/// @return: 操作成功,返回(),操作失败,返回错误码
pub fn device_unregister<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
DEVICE_MANAGER.add_device(device.get_id_table(), device.clone());
match sys_device_unregister(&device.get_id_table().to_name()) {
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
match sys_device_unregister(&device.id_table().to_name()) {
Ok(_) => {
device.set_sys_info(None);
return Ok(());

View File

@ -0,0 +1,98 @@
use super::device::{mkdev, DeviceNumber, KObject};
use crate::libs::spinlock::SpinLock;
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
const KOBJMAP_HASH_SIZE: usize = 255;
/// @brief: 字符设备与块设备管理结构体
#[derive(Debug, Clone)]
struct Probe(Arc<dyn KObject>);
impl Probe {
/// @brief: 新建probe实例
/// @parameter: data: probe实例
/// @return: probe实例
pub fn new(data: Arc<dyn KObject>) -> Self {
Self(data)
}
}
/// @brief: 字符设备和块设备管理实例(锁)
#[derive(Debug)]
pub struct LockedKObjMap(SpinLock<KObjMap>);
impl Default for LockedKObjMap {
fn default() -> Self {
Self(SpinLock::new(KObjMap::default()))
}
}
/// @brief: 字符设备和块设备管理实例
#[derive(Debug, Clone)]
struct KObjMap(Vec<BTreeMap<DeviceNumber, Probe>>);
impl Default for KObjMap {
fn default() -> Self {
Self(vec![BTreeMap::new(); KOBJMAP_HASH_SIZE])
}
}
/// @brief: obj设备注册
/// @parameter: domain: 管理实例
/// dev_t: 设备号
/// range: 次设备号范围
/// data: 设备实例
/// @return: none
pub fn kobj_map(
domain: Arc<LockedKObjMap>,
dev_t: DeviceNumber,
range: usize,
data: Arc<dyn KObject>,
) {
if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
for i in 0..range {
map.insert(
mkdev(dev_t.major(), dev_t.minor() + i),
Probe::new(data.clone()),
);
}
}
}
/// @brief: obj设备注销
/// @parameter: domain: 管理实例
/// dev_t: 设备号
/// range: 次设备号范围
/// @return: none
pub fn kobj_unmap(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber, range: usize) {
if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
for i in 0..range {
let rm_dev_t = &DeviceNumber::new(Into::<usize>::into(dev_t) + i);
match map.get(rm_dev_t) {
Some(_) => {
map.remove(rm_dev_t);
}
None => {}
}
}
}
}
/// @brief: 设备查找
/// @parameter: domain: 管理实例
/// dev_t: 设备号
/// @return: 查找成功返回设备实例否则返回None
#[allow(dead_code)]
pub fn kobj_lookup(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber) -> Option<Arc<dyn KObject>> {
if let Some(map) = domain.0.lock().0.get(dev_t.major() % 255) {
match map.get(&dev_t) {
Some(value) => {
return Some(value.0.clone());
}
None => {
return None;
}
}
}
return None;
}

View File

@ -1,2 +1,4 @@
pub mod char;
pub mod device;
pub mod map;
pub mod platform;

View File

@ -1,7 +1,7 @@
use super::device::{
bus::{bus_driver_register, bus_register, Bus, BusDriver, BusState},
driver::Driver,
Device, DeviceError, DeviceState, DeviceType, IdTable,
Device, DeviceError, DeviceState, DeviceType, IdTable, KObject,
};
use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError};
use alloc::{
@ -94,7 +94,7 @@ impl LockedPlatformBusDriver {
/// @return: 注册成功返回Ok(()),注册失败返回BusError类型
#[allow(dead_code)]
fn register_platform_driver(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), DeviceError> {
let id_table = driver.get_id_table();
let id_table = driver.id_table();
let drivers = &mut self.0.lock().drivers;
// 如果存在同类型的驱动,返回错误
@ -112,7 +112,7 @@ impl LockedPlatformBusDriver {
#[allow(dead_code)]
#[inline]
fn unregister_platform_driver(&mut self, driver: Arc<dyn PlatformDriver>) {
let id_table = driver.get_id_table();
let id_table = driver.id_table();
self.0.lock().drivers.remove(&id_table);
}
@ -124,7 +124,7 @@ impl LockedPlatformBusDriver {
&mut self,
device: Arc<dyn PlatformDevice>,
) -> Result<(), DeviceError> {
let id_table = device.get_id_table();
let id_table = device.id_table();
let devices = &mut self.0.lock().devices;
if devices.contains_key(&id_table) {
@ -141,7 +141,7 @@ impl LockedPlatformBusDriver {
#[inline]
#[allow(dead_code)]
fn unregister_platform_device(&mut self, device: Arc<dyn PlatformDevice>) {
let id_table = device.get_id_table();
let id_table = device.id_table();
self.0.lock().devices.remove(&id_table);
}
@ -155,8 +155,8 @@ impl LockedPlatformBusDriver {
for (_dev_id_table, device) in devices.iter() {
if device
.get_compatible_table()
.matches(&driver.get_compatible_table())
.compatible_table()
.matches(&driver.compatible_table())
{
if !device.is_initialized() {
// 设备未初始化调用驱动probe函数
@ -186,8 +186,8 @@ impl LockedPlatformBusDriver {
let drivers = &mut self.0.lock().drivers;
for (_drv_id_table, driver) in drivers.into_iter() {
if driver
.get_compatible_table()
.matches(&device.get_compatible_table())
.compatible_table()
.matches(&device.compatible_table())
{
match driver.probe(device.clone()) {
Ok(_driver) => {
@ -234,7 +234,7 @@ impl Driver for LockedPlatformBusDriver {
}
#[inline]
fn get_id_table(&self) -> IdTable {
fn id_table(&self) -> IdTable {
IdTable::new("PlatformBusDriver", 0)
}
@ -262,6 +262,8 @@ impl BusDriver for LockedPlatformBusDriver {
}
}
impl KObject for LockedPlatformBusDriver {}
#[derive(Debug)]
pub struct LockedPlatform(SpinLock<Platform>);
@ -278,7 +280,7 @@ impl LockedPlatform {
/// @return: platform总线匹配表
#[inline]
#[allow(dead_code)]
fn get_compatible_table(&self) -> CompatibleTable {
fn compatible_table(&self) -> CompatibleTable {
CompatibleTable::new(vec!["platform"])
}
@ -350,13 +352,13 @@ impl Platform {
impl Device for LockedPlatform {
#[inline]
#[allow(dead_code)]
fn get_type(&self) -> DeviceType {
fn dev_type(&self) -> DeviceType {
return DeviceType::Bus;
}
#[inline]
#[allow(dead_code)]
fn get_id_table(&self) -> IdTable {
fn id_table(&self) -> IdTable {
IdTable::new("platform", 0)
}
@ -370,11 +372,17 @@ impl Device for LockedPlatform {
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
return self.0.lock().sys_info.clone();
}
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
self
}
}
/// @brief: 为Platform实现Bus traitplatform总线是一种总线设备
impl Bus for LockedPlatform {}
impl KObject for LockedPlatform {}
/// @brief: 初始化platform总线
/// @parameter: None
/// @return: None

View File

@ -1,5 +1,5 @@
use super::{
super::device::{Device, DeviceState, DeviceType},
super::device::{Device, DeviceState},
platform_driver::PlatformDriver,
CompatibleTable,
};
@ -8,14 +8,10 @@ use alloc::sync::Arc;
/// @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;
fn compatible_table(&self) -> CompatibleTable;
/// @brief: 判断设备是否初始化
/// @parameter: None

View File

@ -16,5 +16,5 @@ pub trait PlatformDriver: Driver {
/// @brief: 获取驱动匹配表
/// @parameter: None
/// @return: 驱动匹配表
fn get_compatible_table(&self) -> CompatibleTable;
fn compatible_table(&self) -> CompatibleTable;
}

View File

@ -1,4 +1,21 @@
use crate::include::bindings::bindings::{io_in8, io_out8};
use super::super::base::device::Device;
use crate::{
driver::base::{
char::CharDevice,
device::{driver::Driver, DeviceState, DeviceType, IdTable, KObject},
platform::{
self, platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
},
},
filesystem::{
sysfs::bus::{bus_device_register, bus_driver_register},
vfs::IndexNode,
},
include::bindings::bindings::{io_in8, io_out8},
libs::spinlock::SpinLock,
syscall::SystemError,
};
use alloc::sync::Arc;
use core::{char, intrinsics::offset, str};
const UART_SUCCESS: i32 = 0;
@ -6,9 +23,17 @@ const E_UART_BITS_RATE_ERROR: i32 = 1;
const E_UART_SERIAL_FAULT: i32 = 2;
const UART_MAX_BITS_RATE: u32 = 115200;
lazy_static! {
// 串口设备
pub static ref UART_DEV: Arc<LockedUart> = Arc::new(LockedUart::default());
// 串口驱动
pub static ref UART_DRV: Arc<LockedUartDriver> = Arc::new(LockedUartDriver::default());
}
// @brief 串口端口
#[allow(dead_code)]
#[repr(u16)]
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum UartPort {
COM1 = 0x3f8,
COM2 = 0x2f8,
@ -57,6 +82,7 @@ impl UartPort {
}
}
// @brief 串口寄存器
#[allow(dead_code)]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@ -71,10 +97,88 @@ struct UartRegister {
reg_scartch: u8,
}
// @brief 串口设备结构体
#[derive(Debug)]
pub struct Uart {
state: DeviceState, // 设备状态
sys_info: Option<Arc<dyn IndexNode>>,
driver: Option<Arc<dyn PlatformDriver>>,
}
impl Default for Uart {
fn default() -> Self {
Self {
state: DeviceState::NotInitialized,
sys_info: None,
driver: None,
}
}
}
// @brief 串口设备结构体(加锁)
#[derive(Debug)]
pub struct LockedUart(SpinLock<Uart>);
impl Default for LockedUart {
fn default() -> Self {
Self(SpinLock::new(Uart::default()))
}
}
impl KObject for LockedUart {}
impl PlatformDevice for LockedUart {
fn compatible_table(&self) -> platform::CompatibleTable {
platform::CompatibleTable::new(vec!["uart"])
}
fn is_initialized(&self) -> bool {
let state = self.0.lock().state;
match state {
DeviceState::Initialized => true,
_ => false,
}
}
fn set_state(&self, set_state: DeviceState) {
let state = &mut self.0.lock().state;
*state = set_state;
}
fn set_driver(&self, driver: Option<Arc<dyn PlatformDriver>>) {
self.0.lock().driver = driver;
}
}
impl Device for LockedUart {
fn id_table(&self) -> IdTable {
IdTable::new("uart", 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>> {
self.0.lock().sys_info.clone()
}
fn dev_type(&self) -> DeviceType {
DeviceType::Serial
}
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
self
}
}
// @brief 串口驱动结构体
#[repr(C)]
#[derive(Debug)]
pub struct UartDriver {
port: UartPort,
baud_rate: u32,
sys_info: Option<Arc<dyn IndexNode>>,
}
impl Default for UartDriver {
@ -82,11 +186,91 @@ impl Default for UartDriver {
Self {
port: UartPort::COM1,
baud_rate: 115200,
sys_info: None,
}
}
}
// @brief 串口驱动结构体(加锁)
#[derive(Debug)]
pub struct LockedUartDriver(SpinLock<UartDriver>);
impl Default for LockedUartDriver {
fn default() -> Self {
Self(SpinLock::new(UartDriver::default()))
}
}
impl KObject for LockedUartDriver {}
impl Driver for LockedUartDriver {
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
self
}
fn id_table(&self) -> IdTable {
return IdTable::new("uart_driver", 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();
}
}
impl CharDevice for LockedUartDriver {
fn open(&self, _file: Arc<dyn IndexNode>) -> Result<(), crate::syscall::SystemError> {
return Ok(());
}
fn close(&self, _file: Arc<dyn IndexNode>) -> Result<(), crate::syscall::SystemError> {
return Ok(());
}
}
impl LockedUartDriver {
/// @brief 创建串口驱动
/// @param port 端口号
/// baud_rate 波特率
/// sys_info: sys文件系统inode
/// @return
#[allow(dead_code)]
pub fn new(port: UartPort, baud_rate: u32, sys_info: Option<Arc<dyn IndexNode>>) -> Self {
Self(SpinLock::new(UartDriver::new(port, baud_rate, sys_info)))
}
}
impl PlatformDriver for LockedUartDriver {
fn probe(
&self,
_device: Arc<dyn PlatformDevice>,
) -> Result<(), crate::driver::base::device::driver::DriverError> {
return Ok(());
}
fn compatible_table(&self) -> platform::CompatibleTable {
return CompatibleTable::new(vec!["uart"]);
}
}
impl UartDriver {
/// @brief 创建串口驱动
/// @param port 端口号
/// baud_rate 波特率
/// sys_info: sys文件系统inode
/// @return 返回串口驱动
#[allow(dead_code)]
pub fn new(port: UartPort, baud_rate: u32, sys_info: Option<Arc<dyn IndexNode>>) -> Self {
Self {
port,
baud_rate,
sys_info,
}
}
/// @brief 串口初始化
/// @param uart_port 端口号
/// @param baud_rate 波特率
@ -176,6 +360,11 @@ impl UartDriver {
while UartDriver::serial_received(port) == false {} //TODO:pause
unsafe { io_in8(port) as char }
}
#[allow(dead_code)]
fn port() -> u16 {
UartPort::COM1.to_u16()
}
}
///@brief 发送数据
@ -231,7 +420,7 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
let divisor = UART_MAX_BITS_RATE / baud_rate;
io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte)
io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // CompatibleTable(hi byte)
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control因此不需要置位RTS/DSR)
@ -261,3 +450,18 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
clears the DLAB again as well as setting various other bits.
*/
}
/// @brief 串口初始化,注册串口
/// @param none
/// @return 初始化成功,返回(),失败,返回错误码
pub fn uart_init() -> Result<(), SystemError> {
let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().to_name())
.expect("uart device register error");
UART_DEV.set_sys_info(Some(device_inode));
let driver_inode = bus_driver_register("platform:0", &UART_DRV.id_table().to_name())
.expect("uart driver register error");
UART_DRV.set_sys_info(Some(driver_inode));
UART_DEV.set_driver(Some(UART_DRV.clone()));
UART_DEV.set_state(DeviceState::Initialized);
return Ok(());
}

View File

@ -1,5 +1,9 @@
use super::{LockedSysFSInode, SYS_BUS_INODE};
use crate::{filesystem::vfs::IndexNode, kdebug, syscall::SystemError};
use crate::{
filesystem::vfs::IndexNode,
kdebug,
syscall::SystemError,
};
use alloc::sync::Arc;
/// @brief: 注册bus在sys/bus下生成文件夹
@ -49,3 +53,51 @@ pub fn sys_bus_init(
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),
}
}

View File

@ -138,6 +138,8 @@ impl SysFS {
}
// 初始化platform总线
crate::driver::base::platform::platform_bus_init().expect("platform bus init failed");
// 初始化串口
crate::driver::uart::uart::uart_init().expect("initilize uart error");
return sysfs;
}
}