mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
完善设备驱动模型&调试串口驱动 (#379)
* 完成了基本架构重构,正在进行兼容 * 重构了所有 Device Driver ,还没有接上具体设备 * 基本把 Uart 接上了,还没有测试 * 初步完成系统设备初始化 * 初步重构 BlockDevice ,使其兼容新的 Device 结构 * 修改文件系统内的部分函数调用以满足重构后的接口 * 测试完 Uart 设备的功能 * 移除了自动添加的文件 * 修复了 warning 和部分格式 * 解决warning,并且修正sysfs初始化的位置 * Patch fix * 删除了 sysinfo 的默认实现 * 删除了字符设备读写的 offset 参数 * 修复了 warning 和一些小逻辑错误 --------- Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
parent
9029414af2
commit
b087521e07
@ -5,7 +5,7 @@ use hashbrown::HashSet;
|
||||
use x86::time::rdtsc;
|
||||
use x86_64::registers::model_specific::EferFlags;
|
||||
|
||||
use crate::driver::uart::uart::c_uart_send_str;
|
||||
use crate::driver::uart::uart_device::c_uart_send_str;
|
||||
use crate::include::bindings::bindings::{
|
||||
multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
/// 引入Module
|
||||
use crate::syscall::SystemError;
|
||||
use crate::{driver::base::device::Device, syscall::SystemError};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Debug};
|
||||
use core::any::Any;
|
||||
|
||||
use super::disk_info::Partition;
|
||||
|
||||
@ -17,172 +17,10 @@ use super::disk_info::Partition;
|
||||
pub type BlockId = usize;
|
||||
|
||||
/// 定义常量
|
||||
const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12.
|
||||
pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12.
|
||||
/// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA)
|
||||
pub const LBA_SIZE: usize = 512;
|
||||
|
||||
/// @brief 设备应该实现的操作
|
||||
/// @usage Device::read_at()
|
||||
pub trait Device: Any + Send + Sync + Debug {
|
||||
/// Notice buffer对应设备按字节划分,使用u8类型
|
||||
/// Notice offset应该从0开始计数
|
||||
|
||||
/// @brief: 从设备的第offset个字节开始,读取len个byte,存放到buf中
|
||||
/// @parameter offset: 起始字节偏移量
|
||||
/// @parameter len: 读取字节的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
|
||||
fn read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中
|
||||
/// @parameter offset: 起始字节偏移量
|
||||
/// @parameter len: 读取字节的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
|
||||
fn write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
|
||||
// TODO: 待实现 open, close
|
||||
}
|
||||
|
||||
/// @brief 块设备应该实现的操作
|
||||
pub trait BlockDevice: Any + Send + Sync + Debug {
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
|
||||
///
|
||||
/// @parameter lba_id_start: 起始块
|
||||
/// @parameter count: 读取块的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中
|
||||
/// @parameter lba_id_start: 起始块
|
||||
/// @parameter count: 写入块的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
|
||||
/// @brief: 每个块设备都必须固定自己块大小,而且该块大小必须是2的幂次
|
||||
/// @return: 返回一个固定量,硬编码(编程的时候固定的常量).
|
||||
fn blk_size_log2(&self) -> u8;
|
||||
|
||||
// TODO: 待实现 open, close
|
||||
|
||||
/// @brief 本函数用于实现动态转换。
|
||||
/// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
|
||||
/// @brief 本函数用于将BlockDevice转换为Device。
|
||||
/// 由于实现了BlockDevice的结构体,本身也实现了Device Trait, 因此转换是可能的。
|
||||
/// 思路:在BlockDevice的结构体中新增一个self_ref变量,返回self_ref.upgrade()即可。
|
||||
fn device(&self) -> Arc<dyn Device>;
|
||||
|
||||
/// @brief 返回块设备的块大小(单位:字节)
|
||||
fn block_size(&self) -> usize;
|
||||
|
||||
/// @brief 返回当前磁盘上的所有分区的Arc指针数组
|
||||
fn partitions(&self) -> Vec<Arc<Partition>>;
|
||||
}
|
||||
|
||||
/// 对于所有<块设备>自动实现 Device Trait 的 read_at 和 write_at 函数
|
||||
impl<T: BlockDevice> Device for T {
|
||||
// 读取设备操作,读取设备内部 [offset, offset + buf.len) 区间内的字符,存放到 buf 中
|
||||
fn read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
|
||||
let multi = iter.multiblock;
|
||||
|
||||
// 枚举每一个range
|
||||
for range in iter {
|
||||
let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
|
||||
let buf_end = range.origin_end() - offset;
|
||||
let buf_slice = &mut buf[buf_begin..buf_end];
|
||||
let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
|
||||
let full = multi && range.is_multi() || !multi && range.is_full();
|
||||
|
||||
if full {
|
||||
// 调用 BlockDevice::read_at() 直接把引用传进去,不是把整个数组move进去
|
||||
BlockDevice::read_at(self, range.lba_start, count, buf_slice)?;
|
||||
} else {
|
||||
// 判断块的长度不能超过最大值
|
||||
if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let mut temp = Vec::new();
|
||||
temp.resize(1usize << self.blk_size_log2(), 0);
|
||||
BlockDevice::read_at(self, range.lba_start, 1, &mut temp[..])?;
|
||||
// 把数据从临时buffer复制到目标buffer
|
||||
buf_slice.copy_from_slice(&temp[range.begin..range.end]);
|
||||
}
|
||||
}
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
/// 写入设备操作,把 buf 的数据写入到设备内部 [offset, offset + len) 区间内
|
||||
fn write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
// assert!(len <= buf.len());
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
|
||||
let multi = iter.multiblock;
|
||||
|
||||
for range in iter {
|
||||
let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
|
||||
let buf_end = range.origin_end() - offset;
|
||||
let buf_slice = &buf[buf_begin..buf_end];
|
||||
let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
|
||||
let full = multi && range.is_multi() || !multi && range.is_full();
|
||||
|
||||
if full {
|
||||
BlockDevice::write_at(self, range.lba_start, count, buf_slice)?;
|
||||
} else {
|
||||
if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let mut temp = Vec::new();
|
||||
temp.resize(1usize << self.blk_size_log2(), 0);
|
||||
// 由于块设备每次读写都是整块的,在不完整写入之前,必须把不完整的地方补全
|
||||
BlockDevice::read_at(self, range.lba_start, 1, &mut temp[..])?;
|
||||
// 把数据从临时buffer复制到目标buffer
|
||||
temp[range.begin..range.end].copy_from_slice(&buf_slice);
|
||||
BlockDevice::write_at(self, range.lba_start, 1, &temp[..])?;
|
||||
}
|
||||
}
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
/// 数据同步
|
||||
fn sync(&self) -> Result<(), SystemError> {
|
||||
BlockDevice::sync(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 块设备的迭代器
|
||||
/// @usage 某次操作读/写块设备的[L,R]范围内的字节,
|
||||
/// 那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange
|
||||
@ -331,3 +169,141 @@ pub fn __bytes_to_lba(addr: usize, blk_size: usize) -> BlockId {
|
||||
pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
|
||||
return lba_id * blk_size;
|
||||
}
|
||||
|
||||
/// @brief 块设备应该实现的操作
|
||||
pub trait BlockDevice: Device {
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
|
||||
///
|
||||
/// @parameter lba_id_start: 起始块
|
||||
/// @parameter count: 读取块的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中
|
||||
/// @parameter lba_id_start: 起始块
|
||||
/// @parameter count: 写入块的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
|
||||
/// @brief: 每个块设备都必须固定自己块大小,而且该块大小必须是2的幂次
|
||||
/// @return: 返回一个固定量,硬编码(编程的时候固定的常量).
|
||||
fn blk_size_log2(&self) -> u8;
|
||||
|
||||
// TODO: 待实现 open, close
|
||||
|
||||
/// @brief 本函数用于实现动态转换。
|
||||
/// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
|
||||
/// @brief 本函数用于将BlockDevice转换为Device。
|
||||
/// 由于实现了BlockDevice的结构体,本身也实现了Device Trait, 因此转换是可能的。
|
||||
/// 思路:在BlockDevice的结构体中新增一个self_ref变量,返回self_ref.upgrade()即可。
|
||||
fn device(&self) -> Arc<dyn Device>;
|
||||
|
||||
/// @brief 返回块设备的块大小(单位:字节)
|
||||
fn block_size(&self) -> usize;
|
||||
|
||||
/// @brief 返回当前磁盘上的所有分区的Arc指针数组
|
||||
fn partitions(&self) -> Vec<Arc<Partition>>;
|
||||
|
||||
fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
// assert!(len <= buf.len());
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
|
||||
let multi = iter.multiblock;
|
||||
|
||||
for range in iter {
|
||||
let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
|
||||
let buf_end = range.origin_end() - offset;
|
||||
let buf_slice = &buf[buf_begin..buf_end];
|
||||
let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
|
||||
let full = multi && range.is_multi() || !multi && range.is_full();
|
||||
|
||||
if full {
|
||||
self.write_at(range.lba_start, count, buf_slice)?;
|
||||
} else {
|
||||
if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let mut temp = Vec::new();
|
||||
temp.resize(1usize << self.blk_size_log2(), 0);
|
||||
// 由于块设备每次读写都是整块的,在不完整写入之前,必须把不完整的地方补全
|
||||
self.write_at(range.lba_start, 1, &mut temp[..])?;
|
||||
// 把数据从临时buffer复制到目标buffer
|
||||
temp[range.begin..range.end].copy_from_slice(&buf_slice);
|
||||
self.write_at(range.lba_start, 1, &temp[..])?;
|
||||
}
|
||||
}
|
||||
return Ok(len);
|
||||
//self.0.lock().write_at(lba_id_start, count, buf)
|
||||
}
|
||||
|
||||
fn read_at_bytes(
|
||||
&self,
|
||||
offset: usize,
|
||||
len: usize,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
|
||||
let multi = iter.multiblock;
|
||||
|
||||
// 枚举每一个range
|
||||
for range in iter {
|
||||
let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
|
||||
let buf_end = range.origin_end() - offset;
|
||||
let buf_slice = &mut buf[buf_begin..buf_end];
|
||||
let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
|
||||
let full = multi && range.is_multi() || !multi && range.is_full();
|
||||
|
||||
if full {
|
||||
// 调用 BlockDevice::read_at() 直接把引用传进去,不是把整个数组move进去
|
||||
self.read_at(range.lba_start, count, buf)?;
|
||||
} else {
|
||||
// 判断块的长度不能超过最大值
|
||||
if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
|
||||
let mut temp = Vec::new();
|
||||
temp.resize(1usize << self.blk_size_log2(), 0);
|
||||
self.read_at(range.lba_start, 1, &mut temp[..])?;
|
||||
|
||||
// 把数据从临时buffer复制到目标buffer
|
||||
buf_slice.copy_from_slice(&temp[range.begin..range.end]);
|
||||
}
|
||||
}
|
||||
return Ok(len);
|
||||
|
||||
// kdebug!(
|
||||
// "ahci read at {lba_id_start}, count={count}, lock={:?}",
|
||||
// self.0
|
||||
// );
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
#![allow(dead_code)]
|
||||
use super::device::BlockDevice;
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
|
||||
use super::block_device::BlockDevice;
|
||||
|
||||
pub type SectorT = u64;
|
||||
|
||||
pub const BLK_TYPE_AHCI: u64 = 0;
|
@ -1,5 +1,4 @@
|
||||
pub mod block;
|
||||
pub mod device;
|
||||
pub mod block_device;
|
||||
pub mod disk_info;
|
||||
|
||||
#[derive(Debug)]
|
@ -1,285 +1,25 @@
|
||||
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;
|
||||
use crate::syscall::SystemError;
|
||||
|
||||
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;
|
||||
use super::device::Device;
|
||||
|
||||
lazy_static! {
|
||||
// 全局字符设备号管理实例
|
||||
pub static ref CHARDEVS: Arc<LockedChrDevs> = Arc::new(LockedChrDevs::default());
|
||||
pub trait CharDevice: Device {
|
||||
/// Notice buffer对应设备按字节划分,使用u8类型
|
||||
/// Notice offset应该从0开始计数
|
||||
|
||||
// 全局字符设备管理实例
|
||||
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();
|
||||
// 寻找主设备号为234~255的设备
|
||||
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); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
// 寻找主设备号在384~511的设备
|
||||
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);
|
||||
}
|
||||
/// @brief: 从设备的第offset个字节开始,读取len个byte,存放到buf中
|
||||
/// @parameter offset: 起始字节偏移量
|
||||
/// @parameter len: 读取字节的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
|
||||
fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中
|
||||
/// @parameter offset: 起始字节偏移量
|
||||
/// @parameter len: 读取字节的数量
|
||||
/// @parameter buf: 目标数组
|
||||
/// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
|
||||
fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use super::{
|
||||
device_register, device_unregister,
|
||||
driver::{driver_register, driver_unregister, Driver, DriverError},
|
||||
driver::{driver_register, driver_unregister, DriverError},
|
||||
Device, DeviceError, DeviceState, IdTable,
|
||||
};
|
||||
use crate::{
|
||||
driver::Driver,
|
||||
filesystem::{
|
||||
sysfs::{
|
||||
bus::{sys_bus_init, sys_bus_register},
|
||||
@ -176,7 +177,7 @@ impl LockedBusManager {
|
||||
/// @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().to_name()) {
|
||||
match sys_bus_register(&bus.id_table().name()) {
|
||||
Ok(inode) => {
|
||||
let _ = sys_bus_init(&inode);
|
||||
return device_register(bus);
|
||||
@ -197,7 +198,7 @@ pub fn bus_unregister<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
|
||||
/// @brief: 总线驱动注册,将总线驱动加入全局总线管理器中
|
||||
/// @parameter bus: Bus设备驱动实体
|
||||
/// @return: 成功:() 失败:DeviceError
|
||||
pub fn bus_driver_register<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
|
||||
pub fn bus_driver_register(bus_driver: Arc<dyn BusDriver>) -> Result<(), DriverError> {
|
||||
BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone());
|
||||
return driver_register(bus_driver);
|
||||
}
|
||||
@ -206,7 +207,7 @@ pub fn bus_driver_register<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), Drive
|
||||
/// @parameter bus: Bus设备驱动实体
|
||||
/// @return: 成功:() 失败:DeviceError
|
||||
#[allow(dead_code)]
|
||||
pub fn bus_driver_unregister<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
|
||||
pub fn bus_driver_unregister(bus_driver: Arc<dyn BusDriver>) -> Result<(), DriverError> {
|
||||
BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone());
|
||||
return driver_unregister(bus_driver);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
use super::{IdTable, KObject};
|
||||
use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError};
|
||||
use super::IdTable;
|
||||
use crate::{
|
||||
driver::Driver, filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError,
|
||||
};
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
use core::fmt::Debug;
|
||||
|
||||
@ -11,42 +13,25 @@ lazy_static! {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum DriverError {
|
||||
ProbeError,
|
||||
RegisterError,
|
||||
ProbeError, // 探测设备失败(该驱动不能初始化这个设备)
|
||||
RegisterError, // 设备注册失败
|
||||
AllocateResourceError, // 获取设备所需资源失败
|
||||
UnsupportedOperation, // 不支持的操作
|
||||
UnInitialized, // 未初始化
|
||||
}
|
||||
|
||||
impl Into<SystemError> for DriverError {
|
||||
fn into(self) -> SystemError {
|
||||
match self {
|
||||
DriverError::ProbeError => SystemError::EIO,
|
||||
DriverError::RegisterError => SystemError::EIO,
|
||||
DriverError::ProbeError => SystemError::ENODEV,
|
||||
DriverError::RegisterError => SystemError::ENODEV,
|
||||
DriverError::AllocateResourceError => SystemError::EIO,
|
||||
DriverError::UnsupportedOperation => SystemError::EIO,
|
||||
DriverError::UnInitialized => SystemError::ENODEV,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 所有驱动驱动都应该实现该trait
|
||||
pub trait Driver: KObject {
|
||||
/// @brief: 本函数用于实现动态转换
|
||||
/// @parameter: None
|
||||
/// @return: any
|
||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
|
||||
|
||||
/// @brief: 获取驱动驱动标识符
|
||||
/// @parameter: None
|
||||
/// @return: 该驱动驱动唯一标识符
|
||||
fn id_table(&self) -> IdTable;
|
||||
|
||||
/// @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>>;
|
||||
}
|
||||
|
||||
/// @brief: 驱动管理器(锁)
|
||||
#[derive(Debug)]
|
||||
pub struct LockedDriverManager(SpinLock<DriverManager>);
|
||||
@ -111,7 +96,7 @@ pub struct DriverManager {
|
||||
impl DriverManager {
|
||||
/// @brief: 创建一个新的设备管理器
|
||||
/// @parameter: None
|
||||
/// @return: DeviceManager实体
|
||||
/// @return: Manager实体
|
||||
#[inline]
|
||||
fn new() -> DriverManager {
|
||||
DriverManager {
|
||||
@ -124,7 +109,7 @@ impl DriverManager {
|
||||
/// @brief: 驱动注册
|
||||
/// @parameter: name: 驱动名
|
||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||
pub fn driver_register<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
|
||||
pub fn driver_register(driver: Arc<dyn Driver>) -> Result<(), DriverError> {
|
||||
DRIVER_MANAGER.add_driver(driver.id_table(), driver);
|
||||
return Ok(());
|
||||
}
|
||||
@ -133,7 +118,7 @@ pub fn driver_register<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
|
||||
/// @parameter: name: 驱动名
|
||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||
#[allow(dead_code)]
|
||||
pub fn driver_unregister<T: Driver>(driver: Arc<T>) -> Result<(), DriverError> {
|
||||
pub fn driver_unregister(driver: Arc<dyn Driver>) -> Result<(), DriverError> {
|
||||
DRIVER_MANAGER.add_driver(driver.id_table(), driver);
|
||||
return Ok(());
|
||||
}
|
||||
|
16
kernel/src/driver/base/device/init.rs
Normal file
16
kernel/src/driver/base/device/init.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::{driver::uart::uart_device::uart_init, kinfo, syscall::SystemError};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_device_init() -> i32 {
|
||||
let result = device_init()
|
||||
.map(|_| 0)
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn device_init() -> Result<(), SystemError> {
|
||||
uart_init()?;
|
||||
kinfo!("device init success");
|
||||
return Ok(());
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
use alloc::{collections::BTreeMap, string::String, sync::Arc};
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::base::map::{LockedDevsMap, LockedKObjMap},
|
||||
filesystem::{
|
||||
sysfs::{
|
||||
devices::{sys_device_register, sys_device_unregister},
|
||||
@ -13,18 +18,113 @@ use crate::{
|
||||
};
|
||||
use core::{any::Any, fmt::Debug};
|
||||
|
||||
use super::platform::CompatibleTable;
|
||||
|
||||
pub mod bus;
|
||||
pub mod driver;
|
||||
pub mod init;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref DEVICE_MANAGER: Arc<LockedDeviceManager> = Arc::new(LockedDeviceManager::new());
|
||||
}
|
||||
lazy_static! {
|
||||
// 全局字符设备号管理实例
|
||||
pub static ref CHARDEVS: Arc<LockedDevsMap> = Arc::new(LockedDevsMap::default());
|
||||
|
||||
// 全局块设备管理实例
|
||||
pub static ref BLOCKDEVS: Arc<LockedDevsMap> = Arc::new(LockedDevsMap::default());
|
||||
|
||||
// 全局设备管理实例
|
||||
pub static ref DEVMAP: Arc<LockedKObjMap> = Arc::new(LockedKObjMap::default());
|
||||
|
||||
}
|
||||
|
||||
pub trait KObject: Any + Send + Sync + Debug {}
|
||||
/// @brief 设备应该实现的操作
|
||||
/// @usage Device::read_at()
|
||||
pub trait Device: KObject {
|
||||
// TODO: 待实现 open, close
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any;
|
||||
/// @brief: 获取设备类型
|
||||
/// @parameter: None
|
||||
/// @return: 实现该trait的设备所属类型
|
||||
fn dev_type(&self) -> DeviceType;
|
||||
|
||||
/// @brief: 设备号实例
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct DeviceNumber(usize);
|
||||
/// @brief: 获取设备标识
|
||||
/// @parameter: None
|
||||
/// @return: 该设备唯一标识
|
||||
fn id_table(&self) -> IdTable;
|
||||
|
||||
/// @brief: 设置sysfs info
|
||||
/// @parameter: None
|
||||
/// @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>>;
|
||||
}
|
||||
|
||||
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DevicePrivateData {
|
||||
id_table: IdTable,
|
||||
resource: Option<DeviceResource>,
|
||||
compatible_table: CompatibleTable,
|
||||
state: DeviceState,
|
||||
}
|
||||
|
||||
impl DevicePrivateData {
|
||||
pub fn new(
|
||||
id_table: IdTable,
|
||||
resource: Option<DeviceResource>,
|
||||
compatible_table: CompatibleTable,
|
||||
state: DeviceState,
|
||||
) -> Self {
|
||||
Self {
|
||||
id_table,
|
||||
resource,
|
||||
compatible_table,
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_table(&self) -> &IdTable {
|
||||
&self.id_table
|
||||
}
|
||||
|
||||
pub fn state(&self) -> DeviceState {
|
||||
self.state
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn resource(&self) -> Option<&DeviceResource> {
|
||||
self.resource.as_ref()
|
||||
}
|
||||
|
||||
pub fn compatible_table(&self) -> &CompatibleTable {
|
||||
&self.compatible_table
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, state: DeviceState) {
|
||||
self.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceResource {
|
||||
//可能会用来保存例如 IRQ PWM 内存地址等需要申请的资源,将来由资源管理器+Framework框架进行管理。
|
||||
}
|
||||
|
||||
impl Default for DeviceResource {
|
||||
fn default() -> Self {
|
||||
return Self {};
|
||||
}
|
||||
}
|
||||
|
||||
int_like!(DeviceNumber, usize);
|
||||
|
||||
impl Default for DeviceNumber {
|
||||
fn default() -> Self {
|
||||
@ -44,6 +144,12 @@ impl Into<usize> for DeviceNumber {
|
||||
}
|
||||
}
|
||||
|
||||
impl core::hash::Hash for DeviceNumber {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceNumber {
|
||||
/// @brief: 设备号创建
|
||||
/// @parameter: dev_t: 设备号
|
||||
@ -65,6 +171,10 @@ impl DeviceNumber {
|
||||
pub fn minor(&self) -> usize {
|
||||
self.0 & 0xfffff
|
||||
}
|
||||
|
||||
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
||||
((major & 0xffffff) << 8) | (minor & 0xff)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 根据主次设备号创建设备号实例
|
||||
@ -92,7 +202,7 @@ pub enum DeviceType {
|
||||
|
||||
/// @brief: 设备标识符类型
|
||||
#[derive(Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)]
|
||||
pub struct IdTable(&'static str, u32);
|
||||
pub struct IdTable(String, DeviceNumber);
|
||||
|
||||
/// @brief: 设备标识符操作方法集
|
||||
impl IdTable {
|
||||
@ -100,18 +210,29 @@ impl IdTable {
|
||||
/// @parameter name: 设备名
|
||||
/// @parameter id: 设备id
|
||||
/// @return: 设备标识符
|
||||
pub fn new(name: &'static str, id: u32) -> IdTable {
|
||||
pub fn new(name: String, id: DeviceNumber) -> IdTable {
|
||||
Self(name, id)
|
||||
}
|
||||
|
||||
/// @brief: 将设备标识符转换成name
|
||||
/// @parameter None
|
||||
/// @return: 设备名
|
||||
pub fn to_name(&self) -> String {
|
||||
return format!("{}:{}", self.0, self.1);
|
||||
pub fn name(&self) -> String {
|
||||
return format!("{}:{:?}", self.0, self.1 .0);
|
||||
}
|
||||
|
||||
pub fn device_number(&self) -> DeviceNumber {
|
||||
return self.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IdTable {
|
||||
fn default() -> Self {
|
||||
IdTable("unknown".to_string(), DeviceNumber::new(0))
|
||||
}
|
||||
}
|
||||
|
||||
// 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉
|
||||
/// @brief: 设备当前状态
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum DeviceState {
|
||||
@ -121,14 +242,17 @@ pub enum DeviceState {
|
||||
}
|
||||
|
||||
/// @brief: 设备错误类型
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum DeviceError {
|
||||
DriverExists, // 设备已存在
|
||||
DeviceExists, // 驱动已存在
|
||||
InitializeFailed, // 初始化错误
|
||||
NoDeviceForDriver, // 没有合适的设备匹配驱动
|
||||
NoDriverForDevice, // 没有合适的驱动匹配设备
|
||||
RegisterError, // 注册失败
|
||||
DriverExists, // 设备已存在
|
||||
DeviceExists, // 驱动已存在
|
||||
InitializeFailed, // 初始化错误
|
||||
NotInitialized, // 未初始化的设备
|
||||
NoDeviceForDriver, // 没有合适的设备匹配驱动
|
||||
NoDriverForDevice, // 没有合适的驱动匹配设备
|
||||
RegisterError, // 注册失败
|
||||
UnsupportedOperation, // 不支持的操作
|
||||
}
|
||||
|
||||
impl Into<SystemError> for DeviceError {
|
||||
@ -137,9 +261,11 @@ impl Into<SystemError> for DeviceError {
|
||||
DeviceError::DriverExists => SystemError::EEXIST,
|
||||
DeviceError::DeviceExists => SystemError::EEXIST,
|
||||
DeviceError::InitializeFailed => SystemError::EIO,
|
||||
DeviceError::NotInitialized => SystemError::ENODEV,
|
||||
DeviceError::NoDeviceForDriver => SystemError::ENODEV,
|
||||
DeviceError::NoDriverForDevice => SystemError::ENODEV,
|
||||
DeviceError::RegisterError => SystemError::EIO,
|
||||
DeviceError::UnsupportedOperation => SystemError::EIO,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,34 +292,6 @@ impl From<DeviceState> for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 所有设备都应该实现该trait
|
||||
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 dev_type(&self) -> DeviceType;
|
||||
|
||||
/// @brief: 获取设备标识
|
||||
/// @parameter: None
|
||||
/// @return: 该设备唯一标识
|
||||
fn id_table(&self) -> IdTable;
|
||||
|
||||
/// @brief: 设置sysfs info
|
||||
/// @parameter: None
|
||||
/// @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>>;
|
||||
}
|
||||
|
||||
/// @brief Device管理器(锁)
|
||||
#[derive(Debug)]
|
||||
pub struct LockedDeviceManager(SpinLock<DeviceManager>);
|
||||
@ -269,7 +367,7 @@ impl DeviceManager {
|
||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||
pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
|
||||
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
|
||||
match sys_device_register(&device.id_table().to_name()) {
|
||||
match sys_device_register(&device.id_table().name()) {
|
||||
Ok(sys_info) => {
|
||||
device.set_sys_info(Some(sys_info));
|
||||
return Ok(());
|
||||
@ -283,7 +381,7 @@ pub fn device_register<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
|
||||
/// @return: 操作成功,返回(),操作失败,返回错误码
|
||||
pub fn device_unregister<T: Device>(device: Arc<T>) -> Result<(), DeviceError> {
|
||||
DEVICE_MANAGER.add_device(device.id_table(), device.clone());
|
||||
match sys_device_unregister(&device.id_table().to_name()) {
|
||||
match sys_device_unregister(&device.id_table().name()) {
|
||||
Ok(_) => {
|
||||
device.set_sys_info(None);
|
||||
return Ok(());
|
||||
|
@ -1,8 +1,23 @@
|
||||
use super::device::{mkdev, DeviceNumber, KObject};
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use core::cmp::Ordering;
|
||||
|
||||
use super::{
|
||||
block::block_device::BlockDevice,
|
||||
char::CharDevice,
|
||||
device::{mkdev, DeviceNumber, IdTable, KObject, BLOCKDEVS, CHARDEVS, DEVICE_MANAGER, DEVMAP},
|
||||
};
|
||||
use crate::{kerror, libs::spinlock::SpinLock, syscall::SystemError};
|
||||
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
|
||||
|
||||
const KOBJMAP_HASH_SIZE: usize = 255;
|
||||
const DEV_MAJOR_HASH_SIZE: usize = 255;
|
||||
const DEV_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 DEV_MAJOR_DYN_END: usize = 234;
|
||||
/* Marks the top and bottom of the second segment of free char majors */
|
||||
const DEV_MAJOR_DYN_EXT_START: usize = 511;
|
||||
const DEV_MAJOR_DYN_EXT_END: usize = 384;
|
||||
|
||||
/// @brief: 字符设备与块设备管理结构体
|
||||
#[derive(Debug, Clone)]
|
||||
@ -96,3 +111,435 @@ pub fn kobj_lookup(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber) -> Option<Ar
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// 管理字符设备号的map(加锁)
|
||||
pub struct LockedDevsMap(SpinLock<DevsMap>);
|
||||
|
||||
impl Default for LockedDevsMap {
|
||||
fn default() -> Self {
|
||||
LockedDevsMap(SpinLock::new(DevsMap::default()))
|
||||
}
|
||||
}
|
||||
|
||||
// 管理字符设备号的map
|
||||
#[derive(Debug)]
|
||||
struct DevsMap(Vec<Vec<DeviceStruct>>);
|
||||
|
||||
impl Default for DevsMap {
|
||||
fn default() -> Self {
|
||||
DevsMap(vec![Vec::new(); DEV_MAJOR_HASH_SIZE])
|
||||
}
|
||||
}
|
||||
|
||||
// 字符设备在系统中的实例,devfs通过该结构与实际字符设备进行联系
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceStruct {
|
||||
dev_t: DeviceNumber, //起始设备号
|
||||
minorct: usize, // 次设备号数量
|
||||
name: &'static str, //字符设备名
|
||||
}
|
||||
|
||||
impl DeviceStruct {
|
||||
/// @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 BlockDeviceOps;
|
||||
|
||||
impl BlockDeviceOps {
|
||||
/// @brief: 主设备号转下标
|
||||
/// @parameter: major: 主设备号
|
||||
/// @return: 返回下标
|
||||
#[allow(dead_code)]
|
||||
fn major_to_index(major: usize) -> usize {
|
||||
return major % DEV_MAJOR_HASH_SIZE;
|
||||
}
|
||||
|
||||
/// @brief: 动态获取主设备号
|
||||
/// @parameter: None
|
||||
/// @return: 如果成功,返回主设备号,否则,返回错误码
|
||||
#[allow(dead_code)]
|
||||
fn find_dynamic_major() -> Result<usize, SystemError> {
|
||||
let blockdevs = BLOCKDEVS.0.lock();
|
||||
// 寻找主设备号为234~255的设备
|
||||
for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = blockdevs.0.get(index) {
|
||||
if item.is_empty() {
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
// 寻找主设备号在384~511的设备
|
||||
for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() {
|
||||
if let Some(blockdevss) = blockdevs.0.get(Self::major_to_index(index)) {
|
||||
let mut flag = true;
|
||||
for item in blockdevss {
|
||||
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_blockdev_region(
|
||||
from: DeviceNumber,
|
||||
count: usize,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_blockdev_region(from, count, name)
|
||||
}
|
||||
|
||||
/// @brief: 注册设备号,该函数自动分配主设备号
|
||||
/// @parameter: baseminor: 主设备号
|
||||
/// count: 次设备号数量
|
||||
/// name: 字符设备名
|
||||
/// @return: 如果注册成功,返回,否则,返回false
|
||||
#[allow(dead_code)]
|
||||
pub fn alloc_blockdev_region(
|
||||
baseminor: usize,
|
||||
count: usize,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_blockdev_region(mkdev(0, baseminor), count, name)
|
||||
}
|
||||
|
||||
/// @brief: 注册设备号
|
||||
/// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
|
||||
/// minorct: 次设备号数量
|
||||
/// name: 字符设备名
|
||||
/// @return: 如果注册成功,返回设备号,否则,返回错误码
|
||||
fn __register_blockdev_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 >= DEV_MAJOR_MAX {
|
||||
kerror!(
|
||||
"DEV {} major requested {} is greater than the maximum {}\n",
|
||||
name,
|
||||
major,
|
||||
DEV_MAJOR_MAX - 1
|
||||
);
|
||||
}
|
||||
if minorct > MINOR_MASK + 1 - baseminor {
|
||||
kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
|
||||
name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
|
||||
}
|
||||
let blockdev = DeviceStruct::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) = BLOCKDEVS.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, blockdev);
|
||||
}
|
||||
return Ok(mkdev(major, baseminor));
|
||||
}
|
||||
|
||||
/// @brief: 注销设备号
|
||||
/// @parameter: major: 主设备号,如果为0,动态分配
|
||||
/// baseminor: 起始次设备号
|
||||
/// minorct: 次设备号数量
|
||||
/// @return: 如果注销成功,返回(),否则,返回错误码
|
||||
fn __unregister_blockdev_region(
|
||||
device_number: DeviceNumber,
|
||||
minorct: usize,
|
||||
) -> Result<(), SystemError> {
|
||||
if let Some(items) = BLOCKDEVS
|
||||
.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 bdev_add(bdev: Arc<dyn BlockDevice>, id_table: IdTable) {
|
||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||
kerror!("Device number can't be 0!\n");
|
||||
}
|
||||
DEVICE_MANAGER.add_device(id_table, bdev.device())
|
||||
}
|
||||
|
||||
/// @brief: block设备注销
|
||||
/// @parameter: dev_t: 字符设备号
|
||||
/// range: 次设备号范围
|
||||
/// @return: none
|
||||
#[allow(dead_code)]
|
||||
pub fn bdev_del(_devnum: DeviceNumber, _range: usize) {}
|
||||
}
|
||||
|
||||
/// @brief 字符设备框架函数集
|
||||
pub struct CharDevOps;
|
||||
|
||||
impl CharDevOps {
|
||||
/// @brief: 主设备号转下标
|
||||
/// @parameter: major: 主设备号
|
||||
/// @return: 返回下标
|
||||
#[allow(dead_code)]
|
||||
fn major_to_index(major: usize) -> usize {
|
||||
return major % DEV_MAJOR_HASH_SIZE;
|
||||
}
|
||||
|
||||
/// @brief: 动态获取主设备号
|
||||
/// @parameter: None
|
||||
/// @return: 如果成功,返回主设备号,否则,返回错误码
|
||||
#[allow(dead_code)]
|
||||
fn find_dynamic_major() -> Result<usize, SystemError> {
|
||||
let chardevs = CHARDEVS.0.lock();
|
||||
// 寻找主设备号为234~255的设备
|
||||
for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = chardevs.0.get(index) {
|
||||
if item.is_empty() {
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
// 寻找主设备号在384~511的设备
|
||||
for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_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 >= DEV_MAJOR_MAX {
|
||||
kerror!(
|
||||
"DEV {} major requested {} is greater than the maximum {}\n",
|
||||
name,
|
||||
major,
|
||||
DEV_MAJOR_MAX - 1
|
||||
);
|
||||
}
|
||||
if minorct > MINOR_MASK + 1 - baseminor {
|
||||
kerror!("DEV {} 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 = DeviceStruct::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>, id_table: IdTable, range: usize) {
|
||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||
kerror!("Device number can't be 0!\n");
|
||||
}
|
||||
DEVICE_MANAGER.add_device(id_table.clone(), cdev.clone());
|
||||
kobj_map(
|
||||
DEVMAP.clone(),
|
||||
id_table.device_number(),
|
||||
range,
|
||||
cdev.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
/// @brief: 字符设备注销
|
||||
/// @parameter: dev_t: 字符设备号
|
||||
/// range: 次设备号范围
|
||||
/// @return: none
|
||||
#[allow(dead_code)]
|
||||
pub fn cdev_del(id_table: IdTable, range: usize) {
|
||||
DEVICE_MANAGER.remove_device(&id_table);
|
||||
kobj_unmap(DEVMAP.clone(), id_table.device_number(), range);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod block;
|
||||
pub mod char;
|
||||
pub mod device;
|
||||
pub mod map;
|
||||
|
@ -1,11 +1,15 @@
|
||||
use super::device::{
|
||||
bus::{bus_driver_register, bus_register, Bus, BusDriver, BusState},
|
||||
driver::Driver,
|
||||
Device, DeviceError, DeviceState, DeviceType, IdTable, KObject,
|
||||
driver::DriverError,
|
||||
Device, DeviceError, DeviceNumber, DevicePrivateData, DeviceResource, DeviceType, IdTable,
|
||||
KObject,
|
||||
};
|
||||
use crate::{
|
||||
driver::Driver, filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError,
|
||||
};
|
||||
use crate::{filesystem::vfs::IndexNode, libs::spinlock::SpinLock, syscall::SystemError};
|
||||
use alloc::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
string::ToString,
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
@ -19,7 +23,7 @@ pub mod platform_driver;
|
||||
/// @brief: platform总线匹配表
|
||||
/// 总线上的设备和驱动都存在一份匹配表
|
||||
/// 根据匹配表条目是否匹配来辨识设备和驱动能否进行匹配
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CompatibleTable(BTreeSet<&'static str>);
|
||||
|
||||
/// @brief: 匹配表操作方法集
|
||||
@ -38,12 +42,16 @@ impl CompatibleTable {
|
||||
/// @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;
|
||||
}
|
||||
self.0.intersection(&other.0).next().is_some()
|
||||
}
|
||||
|
||||
/// @brief: 添加一组匹配条目
|
||||
/// @param:
|
||||
#[allow(dead_code)]
|
||||
pub fn add_device(&mut self, devices: Vec<&'static str>) {
|
||||
for str in devices {
|
||||
self.0.insert(str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,9 +119,13 @@ impl LockedPlatformBusDriver {
|
||||
/// @return: None
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn unregister_platform_driver(&mut self, driver: Arc<dyn PlatformDriver>) {
|
||||
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类型设备
|
||||
@ -144,63 +156,6 @@ impl LockedPlatformBusDriver {
|
||||
let id_table = device.id_table();
|
||||
self.0.lock().devices.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.0.lock().devices;
|
||||
|
||||
for (_dev_id_table, device) in devices.iter() {
|
||||
if device
|
||||
.compatible_table()
|
||||
.matches(&driver.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 = &mut self.0.lock().drivers;
|
||||
for (_drv_id_table, driver) in drivers.into_iter() {
|
||||
if driver
|
||||
.compatible_table()
|
||||
.matches(&device.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: platform总线驱动
|
||||
@ -235,7 +190,7 @@ impl Driver for LockedPlatformBusDriver {
|
||||
|
||||
#[inline]
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new("PlatformBusDriver", 0)
|
||||
return IdTable::new("PlatformBusDriver".to_string(), DeviceNumber::new(0));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -249,6 +204,18 @@ impl Driver for LockedPlatformBusDriver {
|
||||
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
|
||||
@ -271,8 +238,8 @@ impl LockedPlatform {
|
||||
/// @brief: 创建一个加锁的platform总线实例
|
||||
/// @parameter: None
|
||||
/// @return: platform总线实例
|
||||
pub fn new() -> LockedPlatform {
|
||||
LockedPlatform(SpinLock::new(Platform::new()))
|
||||
pub fn new(data: DevicePrivateData) -> LockedPlatform {
|
||||
LockedPlatform(SpinLock::new(Platform::new(data)))
|
||||
}
|
||||
|
||||
/// @brief: 获取总线的匹配表
|
||||
@ -316,22 +283,22 @@ impl LockedPlatform {
|
||||
return state;
|
||||
}
|
||||
|
||||
/// @brief:
|
||||
/// @parameter: None
|
||||
/// @return: 总线状态
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
fn set_driver(&self, driver: Option<Arc<LockedPlatformBusDriver>>) {
|
||||
self.0.lock().driver = driver;
|
||||
}
|
||||
// /// @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 {
|
||||
state: BusState, // 总线状态
|
||||
driver: Option<Arc<LockedPlatformBusDriver>>, // 总线驱动
|
||||
sys_info: Option<Arc<dyn IndexNode>>, // 总线sys information
|
||||
_data: DevicePrivateData,
|
||||
state: BusState, // 总线状态
|
||||
sys_info: Option<Arc<dyn IndexNode>>, // 总线sys information
|
||||
}
|
||||
|
||||
/// @brief: platform方法集
|
||||
@ -339,10 +306,10 @@ impl Platform {
|
||||
/// @brief: 创建一个platform总线实例
|
||||
/// @parameter: None
|
||||
/// @return: platform总线实例
|
||||
pub fn new() -> Self {
|
||||
pub fn new(_data: DevicePrivateData) -> Self {
|
||||
Self {
|
||||
_data,
|
||||
state: BusState::NotInitialized,
|
||||
driver: Option::None,
|
||||
sys_info: Option::None,
|
||||
}
|
||||
}
|
||||
@ -359,7 +326,7 @@ impl Device for LockedPlatform {
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new("platform", 0)
|
||||
IdTable::new("platform".to_string(), DeviceNumber::new(0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -373,7 +340,7 @@ impl Device for LockedPlatform {
|
||||
return self.0.lock().sys_info.clone();
|
||||
}
|
||||
|
||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -388,10 +355,16 @@ impl KObject for LockedPlatform {}
|
||||
/// @return: None
|
||||
pub fn platform_bus_init() -> Result<(), SystemError> {
|
||||
let platform_driver: Arc<LockedPlatformBusDriver> = Arc::new(LockedPlatformBusDriver::new());
|
||||
let platform_device: Arc<LockedPlatform> = Arc::new(LockedPlatform::new());
|
||||
let platform_device: Arc<LockedPlatform> =
|
||||
Arc::new(LockedPlatform::new(DevicePrivateData::new(
|
||||
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
||||
None,
|
||||
CompatibleTable::new(vec!["platform"]),
|
||||
BusState::NotInitialized.into(),
|
||||
)));
|
||||
bus_register(platform_device.clone()).map_err(|e| e.into())?;
|
||||
platform_device.set_state(BusState::Initialized);
|
||||
platform_device.set_driver(Some(platform_driver.clone()));
|
||||
//platform_device.set_driver(Some(platform_driver.clone()));
|
||||
bus_driver_register(platform_driver.clone()).map_err(|e| e.into())?;
|
||||
|
||||
return Ok(());
|
||||
|
@ -1,18 +1,11 @@
|
||||
use super::{
|
||||
super::device::{Device, DeviceState},
|
||||
platform_driver::PlatformDriver,
|
||||
CompatibleTable,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use crate::driver::base::device::Device;
|
||||
|
||||
use super::{super::device::DeviceState, CompatibleTable};
|
||||
|
||||
/// @brief: 实现该trait的设备实例应挂载在platform总线上,
|
||||
/// 同时应该实现Device trait
|
||||
pub trait PlatformDevice: Device {
|
||||
/// @brief: 获取设备匹配表
|
||||
/// @parameter: None
|
||||
/// @return: 设备匹配表
|
||||
fn compatible_table(&self) -> CompatibleTable;
|
||||
|
||||
/// @brief: 判断设备是否初始化
|
||||
/// @parameter: None
|
||||
/// @return: 如果已经初始化,返回true,否则,返回false
|
||||
@ -22,9 +15,4 @@ pub trait PlatformDevice: Device {
|
||||
/// @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>>);
|
||||
}
|
||||
|
@ -1,20 +1,21 @@
|
||||
use super::{
|
||||
super::device::driver::{Driver, DriverError},
|
||||
platform_device::PlatformDevice,
|
||||
CompatibleTable,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use crate::driver::{base::device::DevicePrivateData, Driver};
|
||||
|
||||
use super::{super::device::driver::DriverError, CompatibleTable};
|
||||
|
||||
lazy_static! {
|
||||
static ref PLATFORM_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["platform"]);
|
||||
}
|
||||
/// @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 compatible_table(&self) -> CompatibleTable;
|
||||
/// @brief 探测设备
|
||||
/// @param data 设备初始拥有的基本信息
|
||||
fn probe(&self, data: DevicePrivateData) -> Result<(), DriverError> {
|
||||
if data.compatible_table().matches(&PLATFORM_COMPAT_TABLE) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(DriverError::UnsupportedOperation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::driver::base::block::block_device::BlockDevice;
|
||||
use crate::filesystem::devfs::{DevFS, DeviceINode};
|
||||
use crate::filesystem::vfs::file::FileMode;
|
||||
use crate::filesystem::vfs::io::device::BlockDevice;
|
||||
use crate::filesystem::vfs::{
|
||||
core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||
Metadata, PollStatus,
|
||||
@ -124,7 +124,7 @@ impl IndexNode for LockedAhciInode {
|
||||
}
|
||||
|
||||
if let FilePrivateData::Unused = data {
|
||||
return self.0.lock().disk.read_at(offset, len, buf);
|
||||
return self.0.lock().disk.read_at_bytes(offset, len, buf);
|
||||
}
|
||||
|
||||
return Err(SystemError::EINVAL);
|
||||
@ -143,7 +143,7 @@ impl IndexNode for LockedAhciInode {
|
||||
}
|
||||
|
||||
if let FilePrivateData::Unused = data {
|
||||
return self.0.lock().disk.write_at(offset, len, buf);
|
||||
return self.0.lock().disk.write_at_bytes(offset, len, buf);
|
||||
}
|
||||
|
||||
return Err(SystemError::EINVAL);
|
||||
|
@ -1,9 +1,13 @@
|
||||
use super::{_port, hba::HbaCmdTable, virt_2_phys};
|
||||
use crate::driver::base::block::block_device::{BlockDevice, BlockId};
|
||||
use crate::driver::base::block::disk_info::Partition;
|
||||
use crate::driver::base::block::SeekFrom;
|
||||
use crate::driver::base::device::{Device, DeviceType, KObject};
|
||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||
use crate::filesystem::mbr::MbrDiskPartionTable;
|
||||
use crate::filesystem::vfs::io::{device::BlockDevice, disk_info::Partition, SeekFrom};
|
||||
use crate::include::bindings::bindings::verify_area;
|
||||
|
||||
use crate::kdebug;
|
||||
use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
|
||||
use crate::mm::phys_2_virt;
|
||||
use crate::syscall::SystemError;
|
||||
@ -52,8 +56,8 @@ impl Debug for AhciDisk {
|
||||
impl AhciDisk {
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: crate::filesystem::vfs::io::device::BlockId, // 起始lba编号
|
||||
count: usize, // 读取lba的数量
|
||||
lba_id_start: BlockId, // 起始lba编号
|
||||
count: usize, // 读取lba的数量
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
@ -211,7 +215,7 @@ impl AhciDisk {
|
||||
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: crate::filesystem::vfs::io::device::BlockId,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
@ -392,7 +396,6 @@ impl LockedAhciDisk {
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
result.0.lock().partitions = part_s;
|
||||
result.0.lock().self_ref = weak_this;
|
||||
return Ok(result);
|
||||
@ -406,14 +409,13 @@ impl LockedAhciDisk {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
buf.resize(size_of::<MbrDiskPartionTable>(), 0);
|
||||
|
||||
self.read_at(0, 1, &mut buf)?;
|
||||
|
||||
BlockDevice::read_at(self, 0, 1, &mut buf)?;
|
||||
// 创建 Cursor 用于按字节读取
|
||||
let mut cursor = VecCursor::new(buf);
|
||||
cursor.seek(SeekFrom::SeekCurrent(446))?;
|
||||
|
||||
for i in 0..4 {
|
||||
// kdebug!("infomation of partition {}:\n", i);
|
||||
kdebug!("infomation of partition {}:\n", i);
|
||||
|
||||
table.dpte[i].flags = cursor.read_u8()?;
|
||||
table.dpte[i].starting_head = cursor.read_u8()?;
|
||||
@ -424,7 +426,7 @@ impl LockedAhciDisk {
|
||||
table.dpte[i].starting_lba = cursor.read_u32()?;
|
||||
table.dpte[i].total_sectors = cursor.read_u32()?;
|
||||
|
||||
// kdebug!("dpte[i] = {:?}", table.dpte[i]);
|
||||
kdebug!("dpte[i] = {:?}", table.dpte[i]);
|
||||
}
|
||||
table.bs_trailsig = cursor.read_u16()?;
|
||||
// kdebug!("bs_trailsig = {}", unsafe {
|
||||
@ -435,6 +437,30 @@ impl LockedAhciDisk {
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for LockedAhciDisk {}
|
||||
|
||||
impl Device for LockedAhciDisk {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
return DeviceType::Block;
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
return self;
|
||||
}
|
||||
|
||||
fn id_table(&self) -> crate::driver::base::device::IdTable {
|
||||
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 BlockDevice for LockedAhciDisk {
|
||||
#[inline]
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
@ -446,36 +472,12 @@ impl BlockDevice for LockedAhciDisk {
|
||||
9
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: crate::filesystem::vfs::io::device::BlockId,
|
||||
count: usize,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
// kdebug!(
|
||||
// "ahci read at {lba_id_start}, count={count}, lock={:?}",
|
||||
// self.0
|
||||
// );
|
||||
return self.0.lock().read_at(lba_id_start, count, buf);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: crate::filesystem::vfs::io::device::BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
self.0.lock().write_at(lba_id_start, count, buf)
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<(), SystemError> {
|
||||
return self.0.lock().sync();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn device(&self) -> Arc<dyn crate::filesystem::vfs::io::device::Device> {
|
||||
fn device(&self) -> Arc<dyn Device> {
|
||||
return self.0.lock().self_ref.upgrade().unwrap();
|
||||
}
|
||||
|
||||
@ -486,4 +488,24 @@ impl BlockDevice for LockedAhciDisk {
|
||||
fn partitions(&self) -> Vec<Arc<Partition>> {
|
||||
return self.0.lock().partitions.clone();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: BlockId, // 起始lba编号
|
||||
count: usize, // 读取lba的数量
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
self.0.lock().read_at(lba_id_start, count, buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
self.0.lock().write_at(lba_id_start, count, buf)
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,13 @@ pub mod ahci_inode;
|
||||
pub mod ahcidisk;
|
||||
pub mod hba;
|
||||
|
||||
use crate::filesystem::vfs::io::device::BlockDevice;
|
||||
use crate::driver::base::block::block_device::BlockDevice;
|
||||
use crate::driver::base::block::disk_info::BLK_GF_AHCI;
|
||||
// 依赖的rust工具包
|
||||
use crate::driver::pci::pci::{
|
||||
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
|
||||
};
|
||||
use crate::filesystem::devfs::devfs_register;
|
||||
use crate::filesystem::vfs::io::disk_info::BLK_GF_AHCI;
|
||||
use crate::kerror;
|
||||
use crate::libs::rwlock::RwLockWriteGuard;
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
|
@ -1,81 +0,0 @@
|
||||
#include "ata.h"
|
||||
#include <common/kprint.h>
|
||||
#include <driver/interrupt/apic/apic.h>
|
||||
|
||||
struct apic_IO_APIC_RTE_entry entry;
|
||||
|
||||
/**
|
||||
* @brief 硬盘中断上半部处理程序
|
||||
*
|
||||
* @param irq_num
|
||||
* @param param
|
||||
* @param regs
|
||||
*/
|
||||
void ata_disk_handler(ul irq_num, ul param, struct pt_regs *regs)
|
||||
{
|
||||
struct ata_identify_device_data info;
|
||||
|
||||
kdebug("irq_num=%ld", irq_num);
|
||||
|
||||
// 从端口读入磁盘配置信息
|
||||
io_insw(PORT_DISK0_DATA, &info, 256);
|
||||
kdebug("General_Config=%#018lx", info.General_Config);
|
||||
printk("Serial number:");
|
||||
unsigned char buf[64];
|
||||
int js=0;
|
||||
//printk("%d", info.Serial_Number);
|
||||
|
||||
for(int i = 0;i<10;i++)
|
||||
{
|
||||
buf[js++]=(info.Serial_Number[i] & 0xff);
|
||||
}
|
||||
buf[js] = '\0';
|
||||
printk("%s", buf);
|
||||
printk("\n");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
hardware_intr_controller ata_disk_intr_controller =
|
||||
{
|
||||
.enable = apic_ioapic_enable,
|
||||
.disable = apic_ioapic_disable,
|
||||
.install = apic_ioapic_install,
|
||||
.uninstall = apic_ioapic_uninstall,
|
||||
.ack = apic_ioapic_edge_ack,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化ATA磁盘驱动程序
|
||||
*
|
||||
*/
|
||||
void ata_init()
|
||||
{
|
||||
entry.vector = 0x2e;
|
||||
entry.deliver_mode = IO_APIC_FIXED;
|
||||
entry.dest_mode = DEST_PHYSICAL;
|
||||
entry.deliver_status = IDLE;
|
||||
entry.polarity = POLARITY_HIGH;
|
||||
entry.remote_IRR = IRR_RESET;
|
||||
entry.trigger_mode = EDGE_TRIGGER;
|
||||
entry.mask = MASKED;
|
||||
entry.reserved = 0;
|
||||
|
||||
entry.destination.physical.reserved1 = 0;
|
||||
entry.destination.physical.reserved2 = 0;
|
||||
entry.destination.physical.phy_dest = 0; // 投递至BSP
|
||||
|
||||
irq_register(entry.vector, &entry, &ata_disk_handler, 0, &ata_disk_intr_controller, "ATA Disk 1");
|
||||
|
||||
io_out8(PORT_DISK0_STATUS_CTRL_REG, 0); // 使能中断请求
|
||||
|
||||
io_out8(PORT_DISK0_ERR_STATUS, 0);
|
||||
io_out8(PORT_DISK0_SECTOR_CNT, 0);
|
||||
io_out8(PORT_DISK0_LBA_7_0, 0);
|
||||
io_out8(PORT_DISK0_LBA_15_8, 0);
|
||||
io_out8(PORT_DISK0_LBA_23_16, 0);
|
||||
io_out8(PORT_DISK0_DEVICE_CONFIGURE_REG, 0);
|
||||
|
||||
io_out8(PORT_DISK0_CONTROLLER_STATUS_CMD, 0xec); // 获取硬件设备识别信息
|
||||
}
|
@ -11,6 +11,60 @@ pub mod video;
|
||||
pub mod virtio;
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::filesystem::vfs::IndexNode;
|
||||
|
||||
use self::base::{
|
||||
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||
platform::CompatibleTable,
|
||||
};
|
||||
pub trait Driver: Sync + Send + Debug {
|
||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
|
||||
|
||||
//对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表
|
||||
|
||||
/// @brief: 获取驱动匹配表
|
||||
/// @parameter: None
|
||||
/// @return: 驱动匹配表
|
||||
fn compatible_table(&self) -> CompatibleTable {
|
||||
//TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除
|
||||
return CompatibleTable::new(vec!["unknown"]);
|
||||
}
|
||||
|
||||
/// @brief 添加可支持的设备
|
||||
/// @parameter: device 新增的匹配项
|
||||
fn append_compatible_table(&self, _device: &CompatibleTable) -> Result<(), DriverError> {
|
||||
Err(DriverError::UnsupportedOperation)
|
||||
}
|
||||
|
||||
/// @brief 探测设备
|
||||
/// @param data 设备初始拥有的基本信息
|
||||
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError>;
|
||||
|
||||
/// @brief 加载设备,包括检查资源可用性,和注册到相应的管理器中。
|
||||
/// @param data 设备初始拥有的信息
|
||||
/// @param resource 设备可能申请的资源(或者像伪设备不需要就为None)
|
||||
fn load(
|
||||
&self,
|
||||
data: DevicePrivateData,
|
||||
resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError>;
|
||||
|
||||
/// @brief: 获取驱动标识符
|
||||
/// @parameter: None
|
||||
/// @return: 该驱动驱动唯一标识符
|
||||
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>>;
|
||||
}
|
||||
|
@ -9,7 +9,11 @@ use smoltcp::{phy, wire};
|
||||
use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
||||
|
||||
use crate::{
|
||||
driver::{virtio::virtio_impl::HalImpl, Driver},
|
||||
driver::{
|
||||
base::device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||
virtio::virtio_impl::HalImpl,
|
||||
Driver,
|
||||
},
|
||||
kerror, kinfo,
|
||||
libs::spinlock::SpinLock,
|
||||
net::{generate_iface_id, NET_DRIVERS},
|
||||
@ -240,6 +244,30 @@ impl<T: Transport> Driver for VirtioInterface<T> {
|
||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
_data: DevicePrivateData,
|
||||
_resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
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> {
|
||||
|
@ -1 +1,2 @@
|
||||
pub mod uart;
|
||||
pub mod uart_device;
|
||||
pub mod uart_driver;
|
||||
|
@ -1,22 +1,38 @@
|
||||
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,
|
||||
driver::{
|
||||
base::{
|
||||
char::CharDevice,
|
||||
device::{
|
||||
driver::DriverError, Device, DeviceError, DeviceNumber, DevicePrivateData,
|
||||
DeviceResource, DeviceState, DeviceType, IdTable, KObject, DEVICE_MANAGER,
|
||||
},
|
||||
platform::{
|
||||
platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
|
||||
},
|
||||
},
|
||||
Driver,
|
||||
},
|
||||
filesystem::{
|
||||
devfs::{devfs_register, DevFS, DeviceINode},
|
||||
sysfs::bus::{bus_device_register, bus_driver_register},
|
||||
vfs::IndexNode,
|
||||
vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus},
|
||||
},
|
||||
include::bindings::bindings::{io_in8, io_out8},
|
||||
kinfo,
|
||||
libs::spinlock::SpinLock,
|
||||
syscall::SystemError,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use core::{char, intrinsics::offset, str};
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{
|
||||
any::Any,
|
||||
char,
|
||||
intrinsics::offset,
|
||||
str::{self, from_utf8},
|
||||
};
|
||||
|
||||
const UART_SUCCESS: i32 = 0;
|
||||
const E_UART_BITS_RATE_ERROR: i32 = 1;
|
||||
@ -100,17 +116,34 @@ struct UartRegister {
|
||||
// @brief 串口设备结构体
|
||||
#[derive(Debug)]
|
||||
pub struct Uart {
|
||||
state: DeviceState, // 设备状态
|
||||
private_data: DevicePrivateData, // 设备状态
|
||||
sys_info: Option<Arc<dyn IndexNode>>,
|
||||
driver: Option<Arc<dyn PlatformDriver>>,
|
||||
fs: Weak<DevFS>, // 文件系统
|
||||
port: UartPort,
|
||||
baud_rate: u32,
|
||||
metadata: Metadata,
|
||||
}
|
||||
|
||||
impl Default for Uart {
|
||||
fn default() -> Self {
|
||||
let mut metadata = Metadata::default();
|
||||
metadata.file_type = FileType::CharDevice;
|
||||
c_uart_init(UartPort::COM1.to_u16(), 115200);
|
||||
Self {
|
||||
state: DeviceState::NotInitialized,
|
||||
private_data: DevicePrivateData::new(
|
||||
IdTable::new(
|
||||
"uart".to_string(),
|
||||
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
|
||||
),
|
||||
None,
|
||||
CompatibleTable::new(vec!["uart"]),
|
||||
DeviceState::NotInitialized,
|
||||
),
|
||||
sys_info: None,
|
||||
driver: None,
|
||||
fs: Weak::default(),
|
||||
port: UartPort::COM1,
|
||||
baud_rate: 115200,
|
||||
metadata,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,12 +161,8 @@ impl Default for LockedUart {
|
||||
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;
|
||||
let state = self.0.lock().private_data.state();
|
||||
match state {
|
||||
DeviceState::Initialized => true,
|
||||
_ => false,
|
||||
@ -141,18 +170,20 @@ impl PlatformDevice for LockedUart {
|
||||
}
|
||||
|
||||
fn set_state(&self, set_state: DeviceState) {
|
||||
let state = &mut self.0.lock().state;
|
||||
*state = set_state;
|
||||
self.0.lock().private_data.set_state(set_state);
|
||||
}
|
||||
|
||||
fn set_driver(&self, driver: Option<Arc<dyn PlatformDriver>>) {
|
||||
self.0.lock().driver = driver;
|
||||
fn compatible_table(&self) -> CompatibleTable {
|
||||
return self.0.lock().private_data.compatible_table().clone();
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for LockedUart {
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new("uart", 0)
|
||||
return IdTable::new(
|
||||
"uart".to_string(),
|
||||
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
|
||||
);
|
||||
}
|
||||
|
||||
fn set_sys_info(&self, sys_info: Option<Arc<dyn IndexNode>>) {
|
||||
@ -167,121 +198,222 @@ impl Device for LockedUart {
|
||||
DeviceType::Serial
|
||||
}
|
||||
|
||||
fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
||||
fn as_any_ref(&self) -> &dyn 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 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
port: UartPort::COM1,
|
||||
baud_rate: 115200,
|
||||
sys_info: None,
|
||||
impl CharDevice for LockedUart {
|
||||
fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let device = self.0.lock();
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
kinfo!("------len: {:?}", len);
|
||||
for i in 0..len {
|
||||
buf[i] = Self::uart_read_byte(&device.port) as u8;
|
||||
kinfo!("------buf[{:?}] = {:?}", i, buf[i]);
|
||||
}
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
let device = self.0.lock();
|
||||
if len > buf.len() {
|
||||
return Err(SystemError::E2BIG);
|
||||
}
|
||||
Self::uart_send(
|
||||
&device.port,
|
||||
from_utf8(&buf[0..len]).map_err(|_| SystemError::EIO)?,
|
||||
);
|
||||
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// @brief 串口驱动结构体(加锁)
|
||||
#[derive(Debug)]
|
||||
pub struct LockedUartDriver(SpinLock<UartDriver>);
|
||||
// impl TtyDevice for LockedUart {
|
||||
// fn ioctl(&self, cmd: String) -> Result<(), DeviceError> {
|
||||
// //TODO 补充详细信息
|
||||
// Err(DeviceError::UnsupportedOperation)
|
||||
// }
|
||||
// fn state(&self) -> Result<TtyState, TtyError> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
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(
|
||||
impl IndexNode for LockedUart {
|
||||
fn read_at(
|
||||
&self,
|
||||
_device: Arc<dyn PlatformDevice>,
|
||||
) -> Result<(), crate::driver::base::device::driver::DriverError> {
|
||||
_offset: usize,
|
||||
len: usize,
|
||||
buf: &mut [u8],
|
||||
_data: &mut FilePrivateData,
|
||||
) -> Result<usize, SystemError> {
|
||||
CharDevice::read(self, len, buf)
|
||||
}
|
||||
|
||||
fn write_at(
|
||||
&self,
|
||||
_offset: usize,
|
||||
len: usize,
|
||||
buf: &[u8],
|
||||
_data: &mut FilePrivateData,
|
||||
) -> Result<usize, SystemError> {
|
||||
CharDevice::write(self, len, buf)
|
||||
}
|
||||
|
||||
fn poll(&self) -> Result<PollStatus, SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
return self
|
||||
.0
|
||||
.lock()
|
||||
.fs
|
||||
.clone()
|
||||
.upgrade()
|
||||
.expect("DevFS is not initialized inside Uart Device");
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn Any {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<Vec<String>, SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||
return Ok(self.0.lock().metadata.clone());
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
_data: &mut FilePrivateData,
|
||||
_mode: &crate::filesystem::vfs::file::FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn compatible_table(&self) -> platform::CompatibleTable {
|
||||
return CompatibleTable::new(vec!["uart"]);
|
||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Ok(self.0.lock().metadata = _metadata.clone());
|
||||
}
|
||||
fn create(
|
||||
&self,
|
||||
name: &str,
|
||||
file_type: FileType,
|
||||
mode: u32,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
// 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值
|
||||
return self.create_with_data(name, file_type, mode, 0);
|
||||
}
|
||||
|
||||
fn create_with_data(
|
||||
&self,
|
||||
_name: &str,
|
||||
_file_type: FileType,
|
||||
_mode: u32,
|
||||
_data: usize,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn unlink(&self, _name: &str) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn rmdir(&self, _name: &str) -> Result<(), SystemError> {
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn move_(
|
||||
&self,
|
||||
_old_name: &str,
|
||||
_target: &Arc<dyn IndexNode>,
|
||||
_new_name: &str,
|
||||
) -> Result<(), SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn find(&self, _name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn get_entry_name(&self, _ino: crate::filesystem::vfs::InodeId) -> Result<String, SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn get_entry_name_and_metadata(
|
||||
&self,
|
||||
ino: crate::filesystem::vfs::InodeId,
|
||||
) -> Result<(String, Metadata), SystemError> {
|
||||
// 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
|
||||
let name = self.get_entry_name(ino)?;
|
||||
let entry = self.find(&name)?;
|
||||
return Ok((name, entry.metadata()?));
|
||||
}
|
||||
|
||||
fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
|
||||
// 若文件系统没有实现此方法,则返回“不支持”
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn mount(
|
||||
&self,
|
||||
_fs: Arc<dyn FileSystem>,
|
||||
) -> Result<Arc<crate::filesystem::vfs::MountFS>, SystemError> {
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn truncate(&self, _len: usize) -> Result<(), SystemError> {
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
impl DeviceINode for LockedUart {
|
||||
fn set_fs(&self, fs: Weak<DevFS>) {
|
||||
self.0.lock().fs = fs;
|
||||
}
|
||||
}
|
||||
|
||||
impl LockedUart {
|
||||
/// @brief 串口初始化
|
||||
/// @param uart_port 端口号
|
||||
/// @param baud_rate 波特率
|
||||
/// @return 初始化成功,返回0,失败,返回错误信息
|
||||
#[allow(dead_code)]
|
||||
pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<i32, &'static str> {
|
||||
pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<(), DeviceError> {
|
||||
let message: &'static str = "uart init.";
|
||||
let port = uart_port.to_u16();
|
||||
// 错误的比特率
|
||||
if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
|
||||
return Err("uart init error.");
|
||||
return Err(DeviceError::InitializeFailed);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@ -300,15 +432,15 @@ impl UartDriver {
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if io_in8(port + 0) != 0xAE {
|
||||
return Err("uart faulty");
|
||||
return Err(DeviceError::InitializeFailed);
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
io_out8(port + 4, 0x08);
|
||||
}
|
||||
UartDriver::uart_send(uart_port, message);
|
||||
Ok(0)
|
||||
Self::uart_send(uart_port, message);
|
||||
Ok(())
|
||||
/*
|
||||
Notice that the initialization code above writes to [PORT + 1]
|
||||
twice with different values. This is once to write to the Divisor
|
||||
@ -342,13 +474,12 @@ impl UartDriver {
|
||||
#[allow(dead_code)]
|
||||
fn uart_send(uart_port: &UartPort, s: &str) {
|
||||
let port = uart_port.to_u16();
|
||||
while UartDriver::is_transmit_empty(port) == false {
|
||||
for c in s.bytes() {
|
||||
unsafe {
|
||||
io_out8(port, c);
|
||||
}
|
||||
while Self::is_transmit_empty(port) == false {} //TODO:pause
|
||||
for c in s.bytes() {
|
||||
unsafe {
|
||||
io_out8(port, c);
|
||||
}
|
||||
} //TODO:pause
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 串口接收一个字节
|
||||
@ -357,8 +488,8 @@ impl UartDriver {
|
||||
#[allow(dead_code)]
|
||||
fn uart_read_byte(uart_port: &UartPort) -> char {
|
||||
let port = uart_port.to_u16();
|
||||
while UartDriver::serial_received(port) == false {} //TODO:pause
|
||||
unsafe { io_in8(port) as char }
|
||||
while Self::serial_received(port) == false {} //TODO:pause
|
||||
return unsafe { io_in8(port) as char };
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -367,12 +498,112 @@ impl UartDriver {
|
||||
}
|
||||
}
|
||||
|
||||
// @brief 串口驱动结构体
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct UartDriver {
|
||||
id_table: IdTable,
|
||||
|
||||
sys_info: Option<Arc<dyn IndexNode>>,
|
||||
}
|
||||
|
||||
impl Default for UartDriver {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id_table: IdTable::new(
|
||||
"ttyS".to_string(),
|
||||
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
|
||||
),
|
||||
|
||||
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(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
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> {
|
||||
let table = data.compatible_table();
|
||||
if table.matches(&CompatibleTable::new(vec!["uart"])) {
|
||||
return Ok(());
|
||||
}
|
||||
return Err(DriverError::ProbeError);
|
||||
}
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
_data: DevicePrivateData,
|
||||
_resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError> {
|
||||
return Err(DriverError::UnsupportedOperation);
|
||||
}
|
||||
}
|
||||
|
||||
impl LockedUartDriver {
|
||||
/// @brief 创建串口驱动
|
||||
/// @param sys_info: sys文件系统inode
|
||||
/// @return
|
||||
#[allow(dead_code)]
|
||||
pub fn new(sys_info: Option<Arc<dyn IndexNode>>) -> Self {
|
||||
Self(SpinLock::new(UartDriver::new(sys_info)))
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformDriver for LockedUartDriver {
|
||||
fn compatible_table(&self) -> CompatibleTable {
|
||||
return CompatibleTable::new(vec!["uart"]);
|
||||
}
|
||||
}
|
||||
|
||||
impl UartDriver {
|
||||
/// @brief 创建串口驱动
|
||||
/// @param sys_info: sys文件系统inode
|
||||
/// @return 返回串口驱动
|
||||
#[allow(dead_code)]
|
||||
pub fn new(sys_info: Option<Arc<dyn IndexNode>>) -> Self {
|
||||
Self {
|
||||
id_table: IdTable::new(
|
||||
"ttyS".to_string(),
|
||||
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
|
||||
),
|
||||
sys_info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///@brief 发送数据
|
||||
///@param port 端口号
|
||||
///@param c 要发送的数据
|
||||
#[no_mangle]
|
||||
pub extern "C" fn c_uart_send(port: u16, c: u8) {
|
||||
while UartDriver::is_transmit_empty(port) == false {} //TODO:pause
|
||||
while LockedUart::is_transmit_empty(port) == false {} //TODO:pause
|
||||
unsafe {
|
||||
io_out8(port, c);
|
||||
}
|
||||
@ -383,7 +614,7 @@ pub extern "C" fn c_uart_send(port: u16, c: u8) {
|
||||
///@return u8 接收到的数据
|
||||
#[no_mangle]
|
||||
pub extern "C" fn c_uart_read(port: u16) -> u8 {
|
||||
while UartDriver::serial_received(port) == false {} //TODO:pause
|
||||
while LockedUart::serial_received(port) == false {} //TODO:pause
|
||||
unsafe { io_in8(port) }
|
||||
}
|
||||
|
||||
@ -455,13 +686,18 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
|
||||
/// @param none
|
||||
/// @return 初始化成功,返回(),失败,返回错误码
|
||||
pub fn uart_init() -> Result<(), SystemError> {
|
||||
let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().to_name())
|
||||
// 以后设备管理初始化完善后不应该出现这种代码,应该在 Driver load 一个设备,即返回设备实例之前就完成设备的 init ,不应该用 lazy_init 在设备上
|
||||
let dev = UART_DEV.0.lock();
|
||||
LockedUart::uart_init(&dev.port, dev.baud_rate).map_err(|_| SystemError::ENODEV)?;
|
||||
drop(dev);
|
||||
let device_inode = bus_device_register("platform:0", &UART_DEV.id_table().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())
|
||||
let driver_inode = bus_driver_register("platform:0", &UART_DRV.id_table().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);
|
||||
devfs_register(&UART_DEV.id_table().name(), UART_DEV.clone())?;
|
||||
DEVICE_MANAGER.add_device(UART_DEV.id_table().clone(), UART_DEV.clone());
|
||||
return Ok(());
|
||||
}
|
81
kernel/src/driver/uart/uart_driver.rs
Normal file
81
kernel/src/driver/uart/uart_driver.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::driver::base::device::{Device, DeviceResource, DEVICE_MANAGER};
|
||||
use crate::driver::base::map::CharDevOps;
|
||||
use crate::driver::base::platform::CompatibleTable;
|
||||
use crate::{
|
||||
driver::{
|
||||
base::device::{driver::DriverError, DevicePrivateData, IdTable},
|
||||
Driver,
|
||||
},
|
||||
libs::spinlock::SpinLock,
|
||||
};
|
||||
|
||||
use super::uart_device::LockedUart;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref UART_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["uart"]);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InnerUartDriver {
|
||||
id_table: IdTable,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UartDriver(SpinLock<InnerUartDriver>);
|
||||
|
||||
impl Default for UartDriver {
|
||||
fn default() -> Self {
|
||||
Self(SpinLock::new(InnerUartDriver {
|
||||
id_table: IdTable::default(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for UartDriver {
|
||||
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||
let compatible_table = data.compatible_table();
|
||||
if compatible_table.matches(&UART_COMPAT_TABLE) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(DriverError::ProbeError);
|
||||
}
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
data: DevicePrivateData,
|
||||
_resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError> {
|
||||
if let Some(device) = DEVICE_MANAGER.get_device(data.id_table()) {
|
||||
return Ok(device.clone());
|
||||
}
|
||||
let compatible_table = data.compatible_table();
|
||||
if compatible_table.matches(&UART_COMPAT_TABLE) {
|
||||
let device = LockedUart::default();
|
||||
let arc_device = Arc::new(device);
|
||||
DEVICE_MANAGER.add_device(data.id_table().clone(), arc_device.clone());
|
||||
CharDevOps::cdev_add(arc_device.clone(), data.id_table().clone(), 1);
|
||||
}
|
||||
|
||||
return Err(DriverError::ProbeError);
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
let driver = self.0.lock();
|
||||
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!()
|
||||
}
|
||||
}
|
@ -8,8 +8,11 @@ use super::vfs::{
|
||||
FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus,
|
||||
};
|
||||
use crate::{
|
||||
kerror,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
kerror, kinfo,
|
||||
libs::{
|
||||
once::Once,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -529,3 +532,23 @@ pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(),
|
||||
pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), SystemError> {
|
||||
return devfs_exact_ref!().unregister_device(name, device);
|
||||
}
|
||||
|
||||
pub fn devfs_init() -> Result<(), SystemError> {
|
||||
static INIT: Once = Once::new();
|
||||
let mut result = None;
|
||||
INIT.call_once(|| {
|
||||
kinfo!("Initializing ProcFS...");
|
||||
// 创建 devfs 实例
|
||||
let devfs: Arc<DevFS> = DevFS::new();
|
||||
// devfs 挂载
|
||||
let _t = ROOT_INODE()
|
||||
.find("dev")
|
||||
.expect("Cannot find /dev")
|
||||
.mount(devfs)
|
||||
.expect("Failed to mount devfs");
|
||||
kinfo!("DevFS mounted.");
|
||||
result = Some(Ok(()));
|
||||
});
|
||||
|
||||
return result.unwrap();
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
filesystem::vfs::io::{device::LBA_SIZE, disk_info::Partition, SeekFrom},
|
||||
driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom},
|
||||
kerror,
|
||||
libs::vec_cursor::VecCursor,
|
||||
syscall::SystemError,
|
||||
|
@ -2,7 +2,7 @@
|
||||
use core::{cmp::min, intrinsics::unlikely};
|
||||
|
||||
use crate::{
|
||||
filesystem::vfs::io::{device::LBA_SIZE, SeekFrom},
|
||||
driver::base::block::{block_device::LBA_SIZE, SeekFrom},
|
||||
kwarn,
|
||||
libs::vec_cursor::VecCursor,
|
||||
syscall::SystemError,
|
||||
@ -130,7 +130,7 @@ impl FATFile {
|
||||
|
||||
// 从磁盘上读取数据
|
||||
let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_offset;
|
||||
let r = fs.partition.disk().device().read_at(
|
||||
let r = fs.partition.disk().read_at_bytes(
|
||||
offset as usize,
|
||||
end_len,
|
||||
&mut buf[start..start + end_len],
|
||||
@ -198,7 +198,7 @@ impl FATFile {
|
||||
// 计算本次写入位置在磁盘上的偏移量
|
||||
let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_bytes_offset;
|
||||
// 写入磁盘
|
||||
let w: usize = fs.partition.disk().device().write_at(
|
||||
let w: usize = fs.partition.disk().write_at(
|
||||
offset as usize,
|
||||
end_len,
|
||||
&buf[start..start + end_len],
|
||||
@ -326,11 +326,9 @@ impl FATFile {
|
||||
}
|
||||
|
||||
let zeroes: Vec<u8> = vec![0u8; (range_end - range_start) as usize];
|
||||
fs.partition.disk().device().write_at(
|
||||
range_start as usize,
|
||||
zeroes.len(),
|
||||
zeroes.as_slice(),
|
||||
)?;
|
||||
fs.partition
|
||||
.disk()
|
||||
.write_at(range_start as usize, zeroes.len(), zeroes.as_slice())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -612,11 +610,10 @@ impl FATDir {
|
||||
LongDirEntry::validate_long_name(name)?;
|
||||
// 目标目录项
|
||||
let mut short_entry = ShortDirEntry::default();
|
||||
// kdebug!("to allocate cluster");
|
||||
|
||||
let first_cluster: Cluster = fs.allocate_cluster(None)?;
|
||||
short_entry.set_first_cluster(first_cluster);
|
||||
|
||||
// kdebug!("to create dot");
|
||||
// === 接下来在子目录中创建'.'目录项和'..'目录项
|
||||
let mut offset = 0;
|
||||
// '.'目录项
|
||||
@ -632,7 +629,6 @@ impl FATDir {
|
||||
// 偏移量加上一个目录项的长度
|
||||
offset += FATRawDirEntry::DIR_ENTRY_LEN;
|
||||
|
||||
// kdebug!("to create dot dot");
|
||||
// '..'目录项
|
||||
let mut dot_dot_entry = ShortDirEntry::default();
|
||||
dot_dot_entry.name = ShortNameGenerator::new("..").generate().unwrap();
|
||||
|
@ -9,7 +9,7 @@ use alloc::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
filesystem::vfs::io::{device::LBA_SIZE, disk_info::Partition, SeekFrom},
|
||||
driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom},
|
||||
filesystem::vfs::{
|
||||
core::generate_inode_id,
|
||||
file::{FileMode, FilePrivateData},
|
||||
@ -1174,8 +1174,7 @@ impl FATFileSystem {
|
||||
let offset: usize = self.cluster_bytes_offset(cluster) as usize;
|
||||
self.partition
|
||||
.disk()
|
||||
.device()
|
||||
.write_at(offset, zeros.len(), zeros.as_slice())?;
|
||||
.write_at_bytes(offset, zeros.len(), zeros.as_slice())?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -1425,7 +1424,6 @@ impl IndexNode for LockedFATInode {
|
||||
_mode: u32,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
// 由于FAT32不支持文件权限的功能,因此忽略mode参数
|
||||
|
||||
let mut guard: SpinLockGuard<FATInode> = self.0.lock();
|
||||
let fs: &Arc<FATFileSystem> = &guard.fs.upgrade().unwrap();
|
||||
|
||||
|
@ -16,8 +16,11 @@ use crate::{
|
||||
FileType,
|
||||
},
|
||||
include::bindings::bindings::{pid_t, process_find_pcb_by_pid},
|
||||
kerror,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
kerror, kinfo,
|
||||
libs::{
|
||||
once::Once,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -704,3 +707,24 @@ pub fn procfs_unregister_pid(pid: pid_t) -> Result<(), SystemError> {
|
||||
// 调用解除注册函数
|
||||
return procfs.unregister_pid(pid);
|
||||
}
|
||||
|
||||
pub fn procfs_init() -> Result<(), SystemError> {
|
||||
static INIT: Once = Once::new();
|
||||
let mut result = None;
|
||||
INIT.call_once(|| {
|
||||
kinfo!("Initializing ProcFS...");
|
||||
// 创建 sysfs 实例
|
||||
let procfs: Arc<ProcFS> = ProcFS::new();
|
||||
|
||||
// sysfs 挂载
|
||||
let _t = ROOT_INODE()
|
||||
.find("proc")
|
||||
.expect("Cannot find /proc")
|
||||
.mount(procfs)
|
||||
.expect("Failed to mount proc");
|
||||
kinfo!("ProcFS mounted.");
|
||||
result = Some(Ok(()));
|
||||
});
|
||||
|
||||
return result.unwrap();
|
||||
}
|
||||
|
@ -3,7 +3,13 @@ use super::vfs::{
|
||||
PollStatus,
|
||||
};
|
||||
use crate::{
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
driver::base::platform::platform_bus_init,
|
||||
filesystem::{sysfs::bus::sys_bus_init, vfs::ROOT_INODE},
|
||||
kdebug, kinfo,
|
||||
libs::{
|
||||
once::Once,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -136,10 +142,7 @@ impl SysFS {
|
||||
},
|
||||
Err(_) => panic!("SysFS: Failed to create /sys/fs"),
|
||||
}
|
||||
// 初始化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;
|
||||
}
|
||||
}
|
||||
@ -446,3 +449,33 @@ impl SysFSInode {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sysfs_init() -> Result<(), SystemError> {
|
||||
static INIT: Once = Once::new();
|
||||
let mut result = None;
|
||||
INIT.call_once(|| {
|
||||
kinfo!("Initializing SysFS...");
|
||||
// 创建 sysfs 实例
|
||||
let sysfs: Arc<SysFS> = SysFS::new();
|
||||
|
||||
// sysfs 挂载
|
||||
let _t = ROOT_INODE()
|
||||
.find("sys")
|
||||
.expect("Cannot find /sys")
|
||||
.mount(sysfs)
|
||||
.expect("Failed to mount sysfs");
|
||||
kinfo!("SysFS mounted.");
|
||||
|
||||
// 初始化platform总线
|
||||
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(()));
|
||||
});
|
||||
|
||||
return result.unwrap();
|
||||
}
|
||||
|
@ -7,17 +7,20 @@ use core::{
|
||||
use alloc::{boxed::Box, format, string::ToString, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::disk::ahci::{self},
|
||||
driver::{
|
||||
base::block::disk_info::Partition,
|
||||
disk::ahci::{self},
|
||||
},
|
||||
filesystem::{
|
||||
devfs::DevFS,
|
||||
devfs::devfs_init,
|
||||
fat::fs::FATFileSystem,
|
||||
procfs::ProcFS,
|
||||
procfs::procfs_init,
|
||||
ramfs::RamFS,
|
||||
sysfs::SysFS,
|
||||
sysfs::sysfs_init,
|
||||
vfs::{mount::MountFS, FileSystem, FileType},
|
||||
},
|
||||
include::bindings::bindings::PAGE_4K_SIZE,
|
||||
kerror, kinfo,
|
||||
kdebug, kerror, kinfo,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -65,37 +68,13 @@ pub extern "C" fn vfs_init() -> i32 {
|
||||
root_inode
|
||||
.create("sys", FileType::Dir, 0o777)
|
||||
.expect("Failed to create /sys");
|
||||
kdebug!("dir in root:{:?}", root_inode.list());
|
||||
|
||||
// // 创建procfs实例
|
||||
let procfs: Arc<ProcFS> = ProcFS::new();
|
||||
procfs_init().expect("Failed to initialize procfs");
|
||||
|
||||
// procfs挂载
|
||||
let _t = root_inode
|
||||
.find("proc")
|
||||
.expect("Cannot find /proc")
|
||||
.mount(procfs)
|
||||
.expect("Failed to mount procfs.");
|
||||
kinfo!("ProcFS mounted.");
|
||||
devfs_init().expect("Failed to initialize devfs");
|
||||
|
||||
// 创建 devfs 实例
|
||||
let devfs: Arc<DevFS> = DevFS::new();
|
||||
// devfs 挂载
|
||||
let _t = root_inode
|
||||
.find("dev")
|
||||
.expect("Cannot find /dev")
|
||||
.mount(devfs)
|
||||
.expect("Failed to mount devfs");
|
||||
kinfo!("DevFS mounted.");
|
||||
|
||||
// 创建 sysfs 实例
|
||||
let sysfs: Arc<SysFS> = SysFS::new();
|
||||
// sysfs 挂载
|
||||
let _t = root_inode
|
||||
.find("sys")
|
||||
.expect("Cannot find /sys")
|
||||
.mount(sysfs)
|
||||
.expect("Failed to mount sysfs");
|
||||
kinfo!("SysFS mounted.");
|
||||
sysfs_init().expect("Failed to initialize sysfs");
|
||||
|
||||
let root_inode = ROOT_INODE().list().expect("VFS init failed");
|
||||
if root_inode.len() > 0 {
|
||||
@ -117,14 +96,14 @@ fn do_migrate(
|
||||
let mountpoint = if r.is_err() {
|
||||
new_root_inode
|
||||
.create(mountpoint_name, FileType::Dir, 0o777)
|
||||
.expect(format!("Failed to create '/{mountpoint_name}'").as_str())
|
||||
.expect(format!("Failed to create '/{mountpoint_name}' in migrating").as_str())
|
||||
} else {
|
||||
r.unwrap()
|
||||
};
|
||||
// 迁移挂载点
|
||||
mountpoint
|
||||
.mount(fs.inner_filesystem())
|
||||
.expect(format!("Failed to migrate {mountpoint_name}").as_str());
|
||||
.expect(format!("Failed to migrate {mountpoint_name} ").as_str());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -168,13 +147,12 @@ fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemE
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mount_root_fs() -> i32 {
|
||||
kinfo!("Try to mount FAT32 as root fs...");
|
||||
let partiton: Arc<crate::filesystem::vfs::io::disk_info::Partition> =
|
||||
ahci::get_disks_by_name("ahci_disk_0".to_string())
|
||||
.unwrap()
|
||||
.0
|
||||
.lock()
|
||||
.partitions[0]
|
||||
.clone();
|
||||
let partiton: Arc<Partition> = ahci::get_disks_by_name("ahci_disk_0".to_string())
|
||||
.unwrap()
|
||||
.0
|
||||
.lock()
|
||||
.partitions[0]
|
||||
.clone();
|
||||
|
||||
let fatfs: Result<Arc<FATFileSystem>, SystemError> = FATFileSystem::new(partiton);
|
||||
if fatfs.is_err() {
|
||||
|
@ -3,9 +3,15 @@ use core::mem::MaybeUninit;
|
||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb, driver::tty::TtyFilePrivateData,
|
||||
filesystem::procfs::ProcfsFilePrivateData, filesystem::vfs::io::SeekFrom,
|
||||
include::bindings::bindings::process_control_block, kerror, syscall::SystemError,
|
||||
arch::asm::current::current_pcb,
|
||||
driver::{
|
||||
base::{block::SeekFrom, device::DevicePrivateData},
|
||||
tty::TtyFilePrivateData,
|
||||
},
|
||||
filesystem::procfs::ProcfsFilePrivateData,
|
||||
include::bindings::bindings::process_control_block,
|
||||
kerror,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{Dirent, FileType, IndexNode, Metadata};
|
||||
@ -15,7 +21,9 @@ use super::{Dirent, FileType, IndexNode, Metadata};
|
||||
pub enum FilePrivateData {
|
||||
/// procfs文件私有信息
|
||||
Procfs(ProcfsFilePrivateData),
|
||||
/// Tty设备的私有信息
|
||||
/// 设备文件的私有信息
|
||||
DevFS(DevicePrivateData),
|
||||
/// tty设备文件的私有信息
|
||||
Tty(TtyFilePrivateData),
|
||||
/// 不需要文件私有信息
|
||||
Unused,
|
||||
|
@ -3,7 +3,6 @@
|
||||
pub mod core;
|
||||
pub mod fcntl;
|
||||
pub mod file;
|
||||
pub mod io;
|
||||
pub mod mount;
|
||||
pub mod syscall;
|
||||
mod utils;
|
||||
|
@ -2,8 +2,8 @@ use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
driver::base::block::SeekFrom,
|
||||
filesystem::vfs::file::FileDescriptorVec,
|
||||
filesystem::vfs::io::SeekFrom,
|
||||
include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM},
|
||||
kerror,
|
||||
syscall::{Syscall, SystemError},
|
||||
|
@ -10,7 +10,7 @@ use elf::{endian::AnyEndian, file::FileHeader, segment::ProgramHeader};
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
current_pcb,
|
||||
filesystem::vfs::io::SeekFrom,
|
||||
driver::base::block::SeekFrom,
|
||||
kerror,
|
||||
libs::align::page_align_up,
|
||||
mm::{
|
||||
|
@ -7,7 +7,7 @@ use core::{
|
||||
use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::uart::uart::{c_uart_send_str, UartPort},
|
||||
driver::uart::uart_device::{c_uart_send_str, UartPort},
|
||||
include::bindings::bindings::{
|
||||
scm_buffer_info_t, video_frame_buffer_info, video_reinitialize, video_set_refresh_target,
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
driver::uart::uart::{c_uart_send, c_uart_send_str, UartPort},
|
||||
driver::uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
|
||||
include::bindings::bindings::video_frame_buffer_info,
|
||||
kinfo,
|
||||
libs::{lib_ui::font::FONT_8x16, spinlock::SpinLock},
|
||||
|
@ -4,7 +4,7 @@ use core::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::uart::uart::{c_uart_send, UartPort},
|
||||
driver::uart::uart_device::{c_uart_send, UartPort},
|
||||
include::bindings::bindings::video_frame_buffer_info,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ use core::mem::size_of;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{filesystem::vfs::io::SeekFrom, syscall::SystemError};
|
||||
use crate::{driver::base::block::SeekFrom, syscall::SystemError};
|
||||
|
||||
/// @brief 本模块用于为数组提供游标的功能,以简化其操作。
|
||||
#[derive(Debug)]
|
||||
|
@ -34,7 +34,8 @@
|
||||
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
|
||||
extern int rs_tty_init();
|
||||
extern int rs_device_init();
|
||||
extern int rs_tty_init();
|
||||
extern void rs_softirq_init();
|
||||
extern void rs_mm_init();
|
||||
|
||||
@ -141,10 +142,9 @@ void system_initialize()
|
||||
io_mfence();
|
||||
|
||||
rs_jiffies_init();
|
||||
io_mfence();
|
||||
|
||||
io_mfence();
|
||||
vfs_init();
|
||||
rs_device_init();
|
||||
rs_tty_init();
|
||||
io_mfence();
|
||||
// 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块
|
||||
|
@ -3,7 +3,7 @@ use core::{fmt::Debug, ptr::null};
|
||||
use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
filesystem::vfs::io::SeekFrom,
|
||||
driver::base::block::SeekFrom,
|
||||
filesystem::vfs::{
|
||||
file::{File, FileMode},
|
||||
ROOT_INODE,
|
||||
|
@ -7,7 +7,7 @@ use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
arch::{cpu::cpu_reset, MMArch},
|
||||
filesystem::vfs::io::SeekFrom,
|
||||
driver::base::block::SeekFrom,
|
||||
filesystem::vfs::{
|
||||
fcntl::FcntlCommand,
|
||||
file::FileMode,
|
||||
|
25
user/apps/test_uart/Makefile
Normal file
25
user/apps/test_uart/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
CC=$(DragonOS_GCC)/x86_64-elf-gcc
|
||||
LD=ld
|
||||
OBJCOPY=objcopy
|
||||
# 修改这里,把它改为你的relibc的sysroot路径
|
||||
RELIBC_OPT=$(DADK_BUILD_CACHE_DIR_RELIBC_0_1_0)
|
||||
CFLAGS=-I $(RELIBC_OPT)/include -D__dragonos__
|
||||
|
||||
tmp_output_dir=$(ROOT_PATH)/bin/tmp/user
|
||||
output_dir=$(DADK_BUILD_CACHE_DIR_TEST_UART_0_1_0)
|
||||
|
||||
LIBC_OBJS:=$(shell find $(RELIBC_OPT)/lib -name "*.o" | sort )
|
||||
LIBC_OBJS+=$(RELIBC_OPT)/lib/libc.a
|
||||
|
||||
all: main.o
|
||||
mkdir -p $(tmp_output_dir)
|
||||
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_uart $(shell find . -name "*.o") $(LIBC_OBJS) -T link.lds
|
||||
|
||||
$(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_uart $(output_dir)/test_uart.elf
|
||||
mv $(output_dir)/test_uart.elf $(output_dir)/test_uart
|
||||
main.o: main.c
|
||||
$(CC) $(CFLAGS) -c main.c -o main.o
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
239
user/apps/test_uart/link.lds
Normal file
239
user/apps/test_uart/link.lds
Normal file
@ -0,0 +1,239 @@
|
||||
/* Script for -z combreloc */
|
||||
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||
Copying and distribution of this script, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. */
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||
"elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.dyn :
|
||||
{
|
||||
*(.rela.init)
|
||||
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||
*(.rela.fini)
|
||||
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||
*(.rela.ctors)
|
||||
*(.rela.dtors)
|
||||
*(.rela.got)
|
||||
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||
*(.rela.ifunc)
|
||||
}
|
||||
.rela.plt :
|
||||
{
|
||||
*(.rela.plt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
}
|
||||
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}
|
||||
.plt : { *(.plt) *(.iplt) }
|
||||
.plt.got : { *(.plt.got) }
|
||||
.plt.sec : { *(.plt.sec) }
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf.em. */
|
||||
*(.gnu.warning)
|
||||
}
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.got : { *(.got) *(.igot) }
|
||||
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||
.data :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
.lbss :
|
||||
{
|
||||
*(.dynlbss)
|
||||
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||
*(LARGE_COMMON)
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||
}
|
||||
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
_end = .; PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3 */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
/* DWARF Extension. */
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
}
|
32
user/apps/test_uart/main.c
Normal file
32
user/apps/test_uart/main.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
// 打开设备文件
|
||||
int fd = open("/dev/char/uart:1088", O_WRONLY | O_NONBLOCK);
|
||||
char buf[1] = {0};
|
||||
int n;
|
||||
memset(buf, 0, 1);
|
||||
while (1) {
|
||||
n = read(fd, buf, 1);
|
||||
close(fd);
|
||||
fd = open("/dev/char/uart:1088", O_WRONLY | O_NONBLOCK);
|
||||
if (n != 0) { // 添加字符串结束符
|
||||
printf("Received: %s\n", buf); // 打印接收到的数据
|
||||
if (buf[0] == 'g') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("fd: %ld", fd);
|
||||
// 写入字符串
|
||||
char *str = "------fuck-----";
|
||||
int len = write(fd, str, strlen(str));
|
||||
printf("len: %ld", len);
|
||||
// 关闭文件
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
28
user/dadk/config/test_uart-0.1.0.dadk
Normal file
28
user/dadk/config/test_uart-0.1.0.dadk
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "test_uart",
|
||||
"version": "0.1.0",
|
||||
"description": "一个用来测试串口设备能够正常运行的app",
|
||||
"task_type": {
|
||||
"BuildFromSource": {
|
||||
"Local": {
|
||||
"path": "apps/test_uart"
|
||||
}
|
||||
}
|
||||
},
|
||||
"depends": [
|
||||
{
|
||||
"name": "relibc",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"build_command": "make"
|
||||
},
|
||||
"install": {
|
||||
"in_dragonos_path": "/bin"
|
||||
},
|
||||
"clean": {
|
||||
"clean_command": "make clean"
|
||||
},
|
||||
"envs": []
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user