完善设备驱动模型&调试串口驱动 (#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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1930 additions and 981 deletions

View File

@ -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,
};

View File

@ -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
// );
}
}

View File

@ -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;

View File

@ -1,5 +1,4 @@
pub mod block;
pub mod device;
pub mod block_device;
pub mod disk_info;
#[derive(Debug)]

View File

@ -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();
// 寻找主设备号为234255的设备
for index in (CHARDEV_MAJOR_DYN_END..CHARDEV_MAJOR_HASH_SIZE).rev() {
if let Some(item) = chardevs.0.get(index) {
if item.is_empty() {
return Ok(index); // 返回可用的主设备号
}
}
}
// 寻找主设备号在384511的设备
for index in (CHARDEV_MAJOR_DYN_EXT_END + 1..CHARDEV_MAJOR_DYN_EXT_START + 1).rev() {
if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) {
let mut flag = true;
for item in chardevss {
if item.device_number().major() == index {
flag = false;
break;
}
}
if flag {
// 如果数组中不存在主设备号等于index的设备
return Ok(index); // 返回可用的主设备号
}
}
}
return Err(SystemError::EBUSY);
}
/// @brief: 注册设备号,该函数需要指定主设备号
/// @parameter: from: 主设备号
/// count: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功,返回设备号,否则,返回错误码
#[allow(dead_code)]
pub fn register_chardev_region(
from: DeviceNumber,
count: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
Self::__register_chardev_region(from, count, name)
}
/// @brief: 注册设备号,该函数自动分配主设备号
/// @parameter: baseminor: 主设备号
/// count: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功返回否则返回false
#[allow(dead_code)]
pub fn alloc_chardev_region(
baseminor: usize,
count: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
Self::__register_chardev_region(mkdev(0, baseminor), count, name)
}
/// @brief: 注册设备号
/// @parameter: device_number: 设备号主设备号如果为0则动态分配
/// minorct: 次设备号数量
/// name: 字符设备名
/// @return: 如果注册成功,返回设备号,否则,返回错误码
fn __register_chardev_region(
device_number: DeviceNumber,
minorct: usize,
name: &'static str,
) -> Result<DeviceNumber, SystemError> {
let mut major = device_number.major();
let baseminor = device_number.minor();
if major >= CHARDEV_MAJOR_MAX {
kerror!(
"CHARDEV {} major requested {} is greater than the maximum {}\n",
name,
major,
CHARDEV_MAJOR_MAX - 1
);
}
if minorct > MINOR_MASK + 1 - baseminor {
kerror!("CHARDEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
}
let chardev = CharDeviceStruct::new(mkdev(major, baseminor), minorct, name);
if major == 0 {
// 如果主设备号为0,则自动分配主设备号
major = Self::find_dynamic_major().expect("Find synamic major error.\n");
}
if let Some(items) = CHARDEVS.0.lock().0.get_mut(Self::major_to_index(major)) {
let mut insert_index: usize = 0;
for (index, item) in items.iter().enumerate() {
insert_index = index;
match item.device_number().major().cmp(&major) {
Ordering::Less => continue,
Ordering::Greater => {
break; // 大于则向后插入
}
Ordering::Equal => {
if item.device_number().minor() + item.minorct() <= baseminor {
continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
}
if item.base_minor() >= baseminor + minorct {
break; // 在此处插入
}
return Err(SystemError::EBUSY); // 存在重合的次设备号
}
}
}
items.insert(insert_index, chardev);
}
return Ok(mkdev(major, baseminor));
}
/// @brief: 注销设备号
/// @parameter: major: 主设备号如果为0动态分配
/// baseminor: 起始次设备号
/// minorct: 次设备号数量
/// @return: 如果注销成功,返回(),否则,返回错误码
fn __unregister_chardev_region(
device_number: DeviceNumber,
minorct: usize,
) -> Result<(), SystemError> {
if let Some(items) = CHARDEVS
.0
.lock()
.0
.get_mut(Self::major_to_index(device_number.major()))
{
for (index, item) in items.iter().enumerate() {
if item.device_number() == device_number && item.minorct() == minorct {
// 设备号和数量都相等
items.remove(index);
return Ok(());
}
}
}
return Err(SystemError::EBUSY);
}
/// @brief: 字符设备注册
/// @parameter: cdev: 字符设备实例
/// dev_t: 字符设备号
/// range: 次设备号范围
/// @return: none
#[allow(dead_code)]
pub fn cdev_add(cdev: Arc<dyn CharDevice>, dev_t: DeviceNumber, range: usize) {
if Into::<usize>::into(dev_t) == 0 {
kerror!("Device number can't be 0!\n");
}
kobj_map(CDEVMAP.clone(), dev_t, range, cdev);
}
/// @brief: 字符设备注销
/// @parameter: dev_t: 字符设备号
/// range: 次设备号范围
/// @return: none
#[allow(dead_code)]
pub fn cdev_del(dev_t: DeviceNumber, range: usize) {
kobj_unmap(CDEVMAP.clone(), dev_t, range);
}
/// @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>;
}

View File

@ -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);
}

View File

@ -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(());
}

View 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(());
}

View File

@ -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(());

View File

@ -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();
// 寻找主设备号为234255的设备
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); // 返回可用的主设备号
}
}
}
// 寻找主设备号在384511的设备
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();
// 寻找主设备号为234255的设备
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); // 返回可用的主设备号
}
}
}
// 寻找主设备号在384511的设备
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);
}
}

View File

@ -1,3 +1,4 @@
pub mod block;
pub mod char;
pub mod device;
pub mod map;

View File

@ -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(());

View File

@ -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>>);
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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)
}
}

View File

@ -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};

View File

@ -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); // 获取硬件设备识别信息
}

View File

@ -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>>;
}

View File

@ -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> {

View File

@ -1 +1,2 @@
pub mod uart;
pub mod uart_device;
pub mod uart_driver;

View File

@ -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(());
}

View 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!()
}
}

View File

@ -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();
}

View File

@ -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,

View File

@ -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();

View File

@ -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();

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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() {

View File

@ -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,

View File

@ -3,7 +3,6 @@
pub mod core;
pub mod fcntl;
pub mod file;
pub mod io;
pub mod mount;
pub mod syscall;
mod utils;

View File

@ -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},

View File

@ -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::{

View File

@ -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,
},

View File

@ -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},

View File

@ -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,
};

View File

@ -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)]

View File

@ -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();
// 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块

View File

@ -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,

View File

@ -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,

View 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

View 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_*) }
}

View 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;
}

View 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": []
}