完善设备驱动模型&调试串口驱动 (#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:
Chiichen
2023-09-13 18:01:52 +08:00
committed by GitHub
parent 9029414af2
commit b087521e07
45 changed files with 1930 additions and 981 deletions

View File

@ -0,0 +1,309 @@
/// 引入Module
use crate::{driver::base::device::Device, syscall::SystemError};
use alloc::{sync::Arc, vec::Vec};
use core::any::Any;
use super::disk_info::Partition;
/// 该文件定义了 Device 和 BlockDevice 的接口
/// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示而不是自己定义错误enum
// 使用方法:
// 假设 blk_dev 是块设备
// <blk_dev as Device>::read_at() 调用的是Device的函数
// <blk_dev as BlockDevice>::read_at() 调用的是BlockDevice的函数
/// 定义类型
pub type BlockId = usize;
/// 定义常量
pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12.
/// 在DragonOS中我们认为磁盘的每个LBA大小均为512字节。注意文件系统的1个扇区可能事实上是多个LBA
pub const LBA_SIZE: usize = 512;
/// @brief 块设备的迭代器
/// @usage 某次操作读/写块设备的[L,R]范围内的字节,
/// 那么可以使用此结构体进行迭代遍历每次调用next()返回一个BlockRange
pub struct BlockIter {
pub begin: usize, // 迭代器的起始位置 -> 块设备的地址 (单位是字节)
pub end: usize,
pub blk_size_log2: u8,
pub multiblock: bool, // 是否启用连续整块同时遍历
}
/// @brief Range搭配迭代器BlockIter使用[L,R]区间被分割成多个小的Range
/// Range要么是整块要么是一块的某一部分
/// 细节: range = [begin, end) 左闭右开
pub struct BlockRange {
pub lba_start: usize, // 起始块的lba_id
pub lba_end: usize, // 终止块的lba_id
pub begin: usize, // 起始位置在块内的偏移量, 如果BlockIter启用Multiblock则是多个块的偏移量
pub end: usize, // 结束位置在块内的偏移量,单位是字节
pub blk_size_log2: u8,
}
impl BlockIter {
#[allow(dead_code)]
pub fn new(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
return BlockIter {
begin: start_addr,
end: end_addr,
blk_size_log2: blk_size_log2,
multiblock: false,
};
}
pub fn new_multiblock(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
return BlockIter {
begin: start_addr,
end: end_addr,
blk_size_log2: blk_size_log2,
multiblock: true,
};
}
/// 获取下一个整块或者不完整的块
pub fn next_block(&mut self) -> BlockRange {
let blk_size_log2 = self.blk_size_log2;
let blk_size = 1usize << self.blk_size_log2;
let lba_id = self.begin / blk_size;
let begin = self.begin % blk_size;
let end = if lba_id == self.end / blk_size {
self.end % blk_size
} else {
blk_size
};
self.begin += end - begin;
return BlockRange {
lba_start: lba_id,
lba_end: lba_id + 1,
begin: begin,
end: end,
blk_size_log2: blk_size_log2,
};
}
/// 如果能返回多个连续的整块则返回否则调用next_block()返回不完整的块
pub fn next_multiblock(&mut self) -> BlockRange {
let blk_size_log2 = self.blk_size_log2;
let blk_size = 1usize << self.blk_size_log2;
let lba_start = self.begin / blk_size;
let lba_end = self.end / blk_size;
// 如果不是整块,先返回非整块的小部分
if __bytes_to_lba(self.begin, blk_size)
!= __bytes_to_lba(self.begin + blk_size - 1, blk_size)
|| lba_start == lba_end
{
return self.next_block();
}
let begin = self.begin % blk_size; // 因为是多个整块这里必然是0
let end = __lba_to_bytes(lba_end, blk_size) - self.begin;
self.begin += end - begin;
return BlockRange {
lba_start: lba_start,
lba_end: lba_end,
begin: begin,
end: end,
blk_size_log2: blk_size_log2,
};
}
}
/// BlockIter 函数实现
impl Iterator for BlockIter {
type Item = BlockRange;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if self.begin >= self.end {
return None;
}
if self.multiblock {
return Some(self.next_multiblock());
} else {
return Some(self.next_block());
}
}
}
/// BlockRange 函数实现
impl BlockRange {
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
return self.end == self.begin;
}
pub fn len(&self) -> usize {
return self.end - self.begin;
}
/// 判断是不是整块
pub fn is_full(&self) -> bool {
return self.len() == (1usize << self.blk_size_log2);
}
/// 判断是不是多个整块连在一起
pub fn is_multi(&self) -> bool {
return self.len() >= (1usize << self.blk_size_log2)
&& (self.len() % (1usize << self.blk_size_log2) == 0);
}
/// 获取 BlockRange 在块设备内部的起始位置 (单位是字节)
pub fn origin_begin(&self) -> usize {
return (self.lba_start << self.blk_size_log2) + self.begin;
}
/// 获取 BlockRange 在块设备内部的结尾位置 (单位是字节)
pub fn origin_end(&self) -> usize {
return (self.lba_start << self.blk_size_log2) + self.end;
}
}
/// 从字节地址转换到lba id
#[inline]
pub fn __bytes_to_lba(addr: usize, blk_size: usize) -> BlockId {
return addr / blk_size;
}
/// 从lba id转换到字节地址 返回lba_id的最左侧字节
#[inline]
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
// );
}
}