From b087521e07f601b30e3d48df788fcc2f09f19566 Mon Sep 17 00:00:00 2001 From: Chiichen <39649411+Chiichen@users.noreply.github.com> Date: Wed, 13 Sep 2023 18:01:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AE=BE=E5=A4=87=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E6=A8=A1=E5=9E=8B&=E8=B0=83=E8=AF=95=E4=B8=B2?= =?UTF-8?q?=E5=8F=A3=E9=A9=B1=E5=8A=A8=20(#379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 完成了基本架构重构,正在进行兼容 * 重构了所有 Device Driver ,还没有接上具体设备 * 基本把 Uart 接上了,还没有测试 * 初步完成系统设备初始化 * 初步重构 BlockDevice ,使其兼容新的 Device 结构 * 修改文件系统内的部分函数调用以满足重构后的接口 * 测试完 Uart 设备的功能 * 移除了自动添加的文件 * 修复了 warning 和部分格式 * 解决warning,并且修正sysfs初始化的位置 * Patch fix * 删除了 sysinfo 的默认实现 * 删除了字符设备读写的 offset 参数 * 修复了 warning 和一些小逻辑错误 --------- Co-authored-by: longjin --- kernel/src/arch/x86_64/mm/mod.rs | 2 +- .../base/block/block_device.rs} | 306 +++++------ .../vfs/io => driver/base/block}/disk_info.rs | 4 +- .../vfs/io => driver/base/block}/mod.rs | 3 +- kernel/src/driver/base/char/mod.rs | 302 +---------- kernel/src/driver/base/device/bus.rs | 9 +- kernel/src/driver/base/device/driver.rs | 49 +- kernel/src/driver/base/device/init.rs | 16 + kernel/src/driver/base/device/mod.rs | 186 +++++-- kernel/src/driver/base/map/mod.rs | 451 +++++++++++++++- kernel/src/driver/base/mod.rs | 1 + kernel/src/driver/base/platform/mod.rs | 147 +++--- .../driver/base/platform/platform_device.rs | 18 +- .../driver/base/platform/platform_driver.rs | 29 +- kernel/src/driver/disk/ahci/ahci_inode.rs | 6 +- kernel/src/driver/disk/ahci/ahcidisk.rs | 90 ++-- kernel/src/driver/disk/ahci/mod.rs | 4 +- kernel/src/driver/disk/ata.c | 81 --- kernel/src/driver/mod.rs | 54 ++ kernel/src/driver/net/virtio_net.rs | 30 +- kernel/src/driver/uart/mod.rs | 3 +- .../driver/uart/{uart.rs => uart_device.rs} | 490 +++++++++++++----- kernel/src/driver/uart/uart_driver.rs | 81 +++ kernel/src/filesystem/devfs/mod.rs | 27 +- kernel/src/filesystem/fat/bpb.rs | 2 +- kernel/src/filesystem/fat/entry.rs | 18 +- kernel/src/filesystem/fat/fs.rs | 6 +- kernel/src/filesystem/procfs/mod.rs | 28 +- kernel/src/filesystem/sysfs/mod.rs | 43 +- kernel/src/filesystem/vfs/core.rs | 62 +-- kernel/src/filesystem/vfs/file.rs | 16 +- kernel/src/filesystem/vfs/mod.rs | 1 - kernel/src/filesystem/vfs/syscall.rs | 2 +- kernel/src/libs/elf.rs | 2 +- kernel/src/libs/lib_ui/screen_manager.rs | 2 +- kernel/src/libs/lib_ui/textui.rs | 2 +- kernel/src/libs/lib_ui/textui_no_alloc.rs | 2 +- kernel/src/libs/vec_cursor.rs | 2 +- kernel/src/main.c | 6 +- kernel/src/process/exec.rs | 2 +- kernel/src/syscall/mod.rs | 2 +- user/apps/test_uart/Makefile | 25 + user/apps/test_uart/link.lds | 239 +++++++++ user/apps/test_uart/main.c | 32 ++ user/dadk/config/test_uart-0.1.0.dadk | 28 + 45 files changed, 1930 insertions(+), 981 deletions(-) rename kernel/src/{filesystem/vfs/io/device.rs => driver/base/block/block_device.rs} (80%) rename kernel/src/{filesystem/vfs/io => driver/base/block}/disk_info.rs (97%) rename kernel/src/{filesystem/vfs/io => driver/base/block}/mod.rs (82%) create mode 100644 kernel/src/driver/base/device/init.rs delete mode 100644 kernel/src/driver/disk/ata.c rename kernel/src/driver/uart/{uart.rs => uart_device.rs} (53%) create mode 100644 kernel/src/driver/uart/uart_driver.rs create mode 100644 user/apps/test_uart/Makefile create mode 100644 user/apps/test_uart/link.lds create mode 100644 user/apps/test_uart/main.c create mode 100644 user/dadk/config/test_uart-0.1.0.dadk diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 66952ba5..21e239b4 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -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, }; diff --git a/kernel/src/filesystem/vfs/io/device.rs b/kernel/src/driver/base/block/block_device.rs similarity index 80% rename from kernel/src/filesystem/vfs/io/device.rs rename to kernel/src/driver/base/block/block_device.rs index 96d2f12f..bf71c39f 100644 --- a/kernel/src/filesystem/vfs/io/device.rs +++ b/kernel/src/driver/base/block/block_device.rs @@ -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; - - /// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中 - /// @parameter offset: 起始字节偏移量 - /// @parameter len: 读取字节的数量 - /// @parameter buf: 目标数组 - /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度 - fn write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result; - - /// @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; - - /// @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; - - /// @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; - - /// @brief 返回块设备的块大小(单位:字节) - fn block_size(&self) -> usize; - - /// @brief 返回当前磁盘上的所有分区的Arc指针数组 - fn partitions(&self) -> Vec>; -} - -/// 对于所有<块设备>自动实现 Device Trait 的 read_at 和 write_at 函数 -impl Device for T { - // 读取设备操作,读取设备内部 [offset, offset + buf.len) 区间内的字符,存放到 buf 中 - fn read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result { - 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 { - // 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; + + /// @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; + + /// @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; + + /// @brief 返回块设备的块大小(单位:字节) + fn block_size(&self) -> usize; + + /// @brief 返回当前磁盘上的所有分区的Arc指针数组 + fn partitions(&self) -> Vec>; + + fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result { + // 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 { + 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 + // ); + } +} diff --git a/kernel/src/filesystem/vfs/io/disk_info.rs b/kernel/src/driver/base/block/disk_info.rs similarity index 97% rename from kernel/src/filesystem/vfs/io/disk_info.rs rename to kernel/src/driver/base/block/disk_info.rs index 6301f744..e9d7b8ec 100644 --- a/kernel/src/filesystem/vfs/io/disk_info.rs +++ b/kernel/src/driver/base/block/disk_info.rs @@ -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; diff --git a/kernel/src/filesystem/vfs/io/mod.rs b/kernel/src/driver/base/block/mod.rs similarity index 82% rename from kernel/src/filesystem/vfs/io/mod.rs rename to kernel/src/driver/base/block/mod.rs index 003fb3a6..5a092a0b 100644 --- a/kernel/src/filesystem/vfs/io/mod.rs +++ b/kernel/src/driver/base/block/mod.rs @@ -1,5 +1,4 @@ -pub mod block; -pub mod device; +pub mod block_device; pub mod disk_info; #[derive(Debug)] diff --git a/kernel/src/driver/base/char/mod.rs b/kernel/src/driver/base/char/mod.rs index 2b81d8ea..3cdf9345 100644 --- a/kernel/src/driver/base/char/mod.rs +++ b/kernel/src/driver/base/char/mod.rs @@ -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 = Arc::new(LockedChrDevs::default()); +pub trait CharDevice: Device { + /// Notice buffer对应设备按字节划分,使用u8类型 + /// Notice offset应该从0开始计数 - // 全局字符设备管理实例 - pub static ref CDEVMAP: Arc = Arc::new(LockedKObjMap::default()); -} - -pub trait CharDevice: KObject { - /// @brief: 打开设备 - /// @parameter: file: devfs inode - /// @return: 打开成功,返回OK(()),失败,返回错误代码 - fn open(&self, file: Arc) -> Result<(), SystemError>; - - /// @brief: 关闭设备 - /// @parameter: file: devfs inode - /// @return: 关闭成功,返回OK(()),失败,返回错误代码 - fn close(&self, file: Arc) -> Result<(), SystemError>; -} - -// 管理字符设备号的map(加锁) -pub struct LockedChrDevs(SpinLock); - -impl Default for LockedChrDevs { - fn default() -> Self { - LockedChrDevs(SpinLock::new(ChrDevs::default())) - } -} - -// 管理字符设备号的map -#[derive(Debug)] -struct ChrDevs(Vec>); - -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 { - let chardevs = CHARDEVS.0.lock(); - // 寻找主设备号为234~255的设备 - for index in (CHARDEV_MAJOR_DYN_END..CHARDEV_MAJOR_HASH_SIZE).rev() { - if let Some(item) = chardevs.0.get(index) { - if item.is_empty() { - return Ok(index); // 返回可用的主设备号 - } - } - } - // 寻找主设备号在384~511的设备 - for index in (CHARDEV_MAJOR_DYN_EXT_END + 1..CHARDEV_MAJOR_DYN_EXT_START + 1).rev() { - if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) { - let mut flag = true; - for item in chardevss { - if item.device_number().major() == index { - flag = false; - break; - } - } - if flag { - // 如果数组中不存在主设备号等于index的设备 - return Ok(index); // 返回可用的主设备号 - } - } - } - return Err(SystemError::EBUSY); - } - - /// @brief: 注册设备号,该函数需要指定主设备号 - /// @parameter: from: 主设备号 - /// count: 次设备号数量 - /// name: 字符设备名 - /// @return: 如果注册成功,返回设备号,否则,返回错误码 - #[allow(dead_code)] - pub fn register_chardev_region( - from: DeviceNumber, - count: usize, - name: &'static str, - ) -> Result { - 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 { - 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 { - 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, dev_t: DeviceNumber, range: usize) { - if Into::::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; + + /// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中 + /// @parameter offset: 起始字节偏移量 + /// @parameter len: 读取字节的数量 + /// @parameter buf: 目标数组 + /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度 + fn write(&self, len: usize, buf: &[u8]) -> Result; + + /// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现 + fn sync(&self) -> Result<(), SystemError>; } diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index 48617577..3aa30ae0 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -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(bus: Arc) -> 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(bus: Arc) -> Result<(), DeviceError> { /// @brief: 总线驱动注册,将总线驱动加入全局总线管理器中 /// @parameter bus: Bus设备驱动实体 /// @return: 成功:() 失败:DeviceError -pub fn bus_driver_register(bus_driver: Arc) -> Result<(), DriverError> { +pub fn bus_driver_register(bus_driver: Arc) -> 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(bus_driver: Arc) -> Result<(), Drive /// @parameter bus: Bus设备驱动实体 /// @return: 成功:() 失败:DeviceError #[allow(dead_code)] -pub fn bus_driver_unregister(bus_driver: Arc) -> Result<(), DriverError> { +pub fn bus_driver_unregister(bus_driver: Arc) -> Result<(), DriverError> { BUS_MANAGER.add_driver(bus_driver.id_table(), bus_driver.clone()); return driver_unregister(bus_driver); } diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index 79d3daff..d0117fd0 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -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 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>); - - /// @brief: 获取驱动的sys information - /// @parameter id_table: 驱动标识符,用于唯一标识该驱动 - /// @return: 驱动实例 - fn sys_info(&self) -> Option>; -} - /// @brief: 驱动管理器(锁) #[derive(Debug)] pub struct LockedDriverManager(SpinLock); @@ -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(driver: Arc) -> Result<(), DriverError> { +pub fn driver_register(driver: Arc) -> Result<(), DriverError> { DRIVER_MANAGER.add_driver(driver.id_table(), driver); return Ok(()); } @@ -133,7 +118,7 @@ pub fn driver_register(driver: Arc) -> Result<(), DriverError> { /// @parameter: name: 驱动名 /// @return: 操作成功,返回(),操作失败,返回错误码 #[allow(dead_code)] -pub fn driver_unregister(driver: Arc) -> Result<(), DriverError> { +pub fn driver_unregister(driver: Arc) -> Result<(), DriverError> { DRIVER_MANAGER.add_driver(driver.id_table(), driver); return Ok(()); } diff --git a/kernel/src/driver/base/device/init.rs b/kernel/src/driver/base/device/init.rs new file mode 100644 index 00000000..09395250 --- /dev/null +++ b/kernel/src/driver/base/device/init.rs @@ -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(()); +} diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 2baa5197..8d8f4261 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -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 = Arc::new(LockedDeviceManager::new()); } +lazy_static! { + // 全局字符设备号管理实例 + pub static ref CHARDEVS: Arc = Arc::new(LockedDevsMap::default()); + + // 全局块设备管理实例 + pub static ref BLOCKDEVS: Arc = Arc::new(LockedDevsMap::default()); + + // 全局设备管理实例 + pub static ref DEVMAP: Arc = 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>); + + /// @brief: 获取设备的sys information + /// @parameter id_table: 设备标识符,用于唯一标识该设备 + /// @return: 设备实例 + fn sys_info(&self) -> Option>; +} + +// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息 +#[allow(dead_code)] +#[derive(Debug, Clone)] +pub struct DevicePrivateData { + id_table: IdTable, + resource: Option, + compatible_table: CompatibleTable, + state: DeviceState, +} + +impl DevicePrivateData { + pub fn new( + id_table: IdTable, + resource: Option, + 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 for DeviceNumber { } } +impl core::hash::Hash for DeviceNumber { + fn hash(&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 for DeviceError { @@ -137,9 +261,11 @@ impl Into 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 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>); - - /// @brief: 获取设备的sys information - /// @parameter id_table: 设备标识符,用于唯一标识该设备 - /// @return: 设备实例 - fn sys_info(&self) -> Option>; -} - /// @brief Device管理器(锁) #[derive(Debug)] pub struct LockedDeviceManager(SpinLock); @@ -269,7 +367,7 @@ impl DeviceManager { /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_register(device: Arc) -> 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(device: Arc) -> Result<(), DeviceError> { /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_unregister(device: Arc) -> 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(()); diff --git a/kernel/src/driver/base/map/mod.rs b/kernel/src/driver/base/map/mod.rs index 2b2e0359..bc9ab666 100644 --- a/kernel/src/driver/base/map/mod.rs +++ b/kernel/src/driver/base/map/mod.rs @@ -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, dev_t: DeviceNumber) -> Option); + +impl Default for LockedDevsMap { + fn default() -> Self { + LockedDevsMap(SpinLock::new(DevsMap::default())) + } +} + +// 管理字符设备号的map +#[derive(Debug)] +struct DevsMap(Vec>); + +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 { + let blockdevs = BLOCKDEVS.0.lock(); + // 寻找主设备号为234~255的设备 + for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() { + if let Some(item) = blockdevs.0.get(index) { + if item.is_empty() { + return Ok(index); // 返回可用的主设备号 + } + } + } + // 寻找主设备号在384~511的设备 + for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() { + if let Some(blockdevss) = blockdevs.0.get(Self::major_to_index(index)) { + let mut flag = true; + for item in blockdevss { + if item.device_number().major() == index { + flag = false; + break; + } + } + if flag { + // 如果数组中不存在主设备号等于index的设备 + return Ok(index); // 返回可用的主设备号 + } + } + } + return Err(SystemError::EBUSY); + } + + /// @brief: 注册设备号,该函数需要指定主设备号 + /// @parameter: from: 主设备号 + /// count: 次设备号数量 + /// name: 字符设备名 + /// @return: 如果注册成功,返回设备号,否则,返回错误码 + #[allow(dead_code)] + pub fn register_blockdev_region( + from: DeviceNumber, + count: usize, + name: &'static str, + ) -> Result { + 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 { + 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 { + 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, id_table: IdTable) { + if Into::::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 { + let chardevs = CHARDEVS.0.lock(); + // 寻找主设备号为234~255的设备 + for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() { + if let Some(item) = chardevs.0.get(index) { + if item.is_empty() { + return Ok(index); // 返回可用的主设备号 + } + } + } + // 寻找主设备号在384~511的设备 + for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() { + if let Some(chardevss) = chardevs.0.get(Self::major_to_index(index)) { + let mut flag = true; + for item in chardevss { + if item.device_number().major() == index { + flag = false; + break; + } + } + if flag { + // 如果数组中不存在主设备号等于index的设备 + return Ok(index); // 返回可用的主设备号 + } + } + } + return Err(SystemError::EBUSY); + } + + /// @brief: 注册设备号,该函数需要指定主设备号 + /// @parameter: from: 主设备号 + /// count: 次设备号数量 + /// name: 字符设备名 + /// @return: 如果注册成功,返回设备号,否则,返回错误码 + #[allow(dead_code)] + pub fn register_chardev_region( + from: DeviceNumber, + count: usize, + name: &'static str, + ) -> Result { + 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 { + 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 { + 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, id_table: IdTable, range: usize) { + if Into::::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); + } +} diff --git a/kernel/src/driver/base/mod.rs b/kernel/src/driver/base/mod.rs index d6880d08..e1efc6c1 100644 --- a/kernel/src/driver/base/mod.rs +++ b/kernel/src/driver/base/mod.rs @@ -1,3 +1,4 @@ +pub mod block; pub mod char; pub mod device; pub mod map; diff --git a/kernel/src/driver/base/platform/mod.rs b/kernel/src/driver/base/platform/mod.rs index 3aac0a8d..3643d320 100644 --- a/kernel/src/driver/base/platform/mod.rs +++ b/kernel/src/driver/base/platform/mod.rs @@ -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) { + fn unregister_platform_driver( + &mut self, + driver: Arc, + ) -> 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) -> Result { - 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) -> 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>) { self.0.lock().sys_info = sys_info; } + + fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> { + todo!() + } + + fn load( + &self, + _data: DevicePrivateData, + _resource: Option, + ) -> Result, 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>) { - self.0.lock().driver = driver; - } + // /// @brief: + // /// @parameter: None + // /// @return: 总线状态 + // #[inline] + // #[allow(dead_code)] + // fn set_driver(&self, driver: Option>) { + // self.0.lock().driver = driver; + // } } /// @brief: platform总线 #[derive(Debug, Clone)] pub struct Platform { - state: BusState, // 总线状态 - driver: Option>, // 总线驱动 - sys_info: Option>, // 总线sys information + _data: DevicePrivateData, + state: BusState, // 总线状态 + sys_info: Option>, // 总线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 = Arc::new(LockedPlatformBusDriver::new()); - let platform_device: Arc = Arc::new(LockedPlatform::new()); + let platform_device: Arc = + 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(()); diff --git a/kernel/src/driver/base/platform/platform_device.rs b/kernel/src/driver/base/platform/platform_device.rs index 6fc2657f..4f21de89 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -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>); } diff --git a/kernel/src/driver/base/platform/platform_driver.rs b/kernel/src/driver/base/platform/platform_driver.rs index fd5110e4..403c0e3c 100644 --- a/kernel/src/driver/base/platform/platform_driver.rs +++ b/kernel/src/driver/base/platform/platform_driver.rs @@ -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) -> 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); + } + } } diff --git a/kernel/src/driver/disk/ahci/ahci_inode.rs b/kernel/src/driver/disk/ahci/ahci_inode.rs index adbe7f00..6c6fc138 100644 --- a/kernel/src/driver/disk/ahci/ahci_inode.rs +++ b/kernel/src/driver/disk/ahci/ahci_inode.rs @@ -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); diff --git a/kernel/src/driver/disk/ahci/ahcidisk.rs b/kernel/src/driver/disk/ahci/ahcidisk.rs index f952e265..90d010ce 100644 --- a/kernel/src/driver/disk/ahci/ahcidisk.rs +++ b/kernel/src/driver/disk/ahci/ahcidisk.rs @@ -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 { 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 { @@ -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 = Vec::new(); buf.resize(size_of::(), 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>) { + todo!() + } + + fn sys_info(&self) -> Option> { + 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 { - // 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 { - 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 { + fn device(&self) -> Arc { return self.0.lock().self_ref.upgrade().unwrap(); } @@ -486,4 +488,24 @@ impl BlockDevice for LockedAhciDisk { fn partitions(&self) -> Vec> { return self.0.lock().partitions.clone(); } + + #[inline] + fn read_at( + &self, + lba_id_start: BlockId, // 起始lba编号 + count: usize, // 读取lba的数量 + buf: &mut [u8], + ) -> Result { + self.0.lock().read_at(lba_id_start, count, buf) + } + + #[inline] + fn write_at( + &self, + lba_id_start: BlockId, + count: usize, + buf: &[u8], + ) -> Result { + self.0.lock().write_at(lba_id_start, count, buf) + } } diff --git a/kernel/src/driver/disk/ahci/mod.rs b/kernel/src/driver/disk/ahci/mod.rs index 15255821..ae5373ad 100644 --- a/kernel/src/driver/disk/ahci/mod.rs +++ b/kernel/src/driver/disk/ahci/mod.rs @@ -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}; diff --git a/kernel/src/driver/disk/ata.c b/kernel/src/driver/disk/ata.c deleted file mode 100644 index de1f6d13..00000000 --- a/kernel/src/driver/disk/ata.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "ata.h" -#include -#include - -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); // 获取硬件设备识别信息 -} \ No newline at end of file diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index 9984bb3c..688ea0d7 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -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, + ) -> Result, 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>); + + /// @brief: 获取驱动的sys information + /// @parameter id_table: 驱动标识符,用于唯一标识该驱动 + /// @return: 驱动实例 + fn sys_info(&self) -> Option>; } diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 417e60da..15461d36 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -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 Driver for VirtioInterface { 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, + ) -> Result, DriverError> { + todo!() + } + + fn id_table(&self) -> IdTable { + todo!() + } + + fn set_sys_info(&self, _sys_info: Option>) { + todo!() + } + + fn sys_info(&self) -> Option> { + todo!() + } } impl NetDriver for VirtioInterface { diff --git a/kernel/src/driver/uart/mod.rs b/kernel/src/driver/uart/mod.rs index 8c203607..59f95bb5 100644 --- a/kernel/src/driver/uart/mod.rs +++ b/kernel/src/driver/uart/mod.rs @@ -1 +1,2 @@ -pub mod uart; +pub mod uart_device; +pub mod uart_driver; diff --git a/kernel/src/driver/uart/uart.rs b/kernel/src/driver/uart/uart_device.rs similarity index 53% rename from kernel/src/driver/uart/uart.rs rename to kernel/src/driver/uart/uart_device.rs index 101f4944..f16d5442 100644 --- a/kernel/src/driver/uart/uart.rs +++ b/kernel/src/driver/uart/uart_device.rs @@ -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>, - driver: Option>, + fs: Weak, // 文件系统 + 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>) { - 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>) { @@ -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>, -} - -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 { + 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 { + 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); +// impl TtyDevice for LockedUart { +// fn ioctl(&self, cmd: String) -> Result<(), DeviceError> { +// //TODO 补充详细信息 +// Err(DeviceError::UnsupportedOperation) +// } +// fn state(&self) -> Result { +// 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>) { - self.0.lock().sys_info = sys_info; - } - - fn sys_info(&self) -> Option> { - return self.0.lock().sys_info.clone(); - } -} - -impl CharDevice for LockedUartDriver { - fn open(&self, _file: Arc) -> Result<(), crate::syscall::SystemError> { - return Ok(()); - } - - fn close(&self, _file: Arc) -> 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>) -> 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, - ) -> Result<(), crate::driver::base::device::driver::DriverError> { + _offset: usize, + len: usize, + buf: &mut [u8], + _data: &mut FilePrivateData, + ) -> Result { + CharDevice::read(self, len, buf) + } + + fn write_at( + &self, + _offset: usize, + len: usize, + buf: &[u8], + _data: &mut FilePrivateData, + ) -> Result { + CharDevice::write(self, len, buf) + } + + fn poll(&self) -> Result { + todo!() + } + + fn fs(&self) -> Arc { + 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, SystemError> { + todo!() + } + + fn metadata(&self) -> Result { + 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, 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, SystemError> { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn link(&self, _name: &str, _other: &Arc) -> 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, + _new_name: &str, + ) -> Result<(), SystemError> { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn find(&self, _name: &str) -> Result, SystemError> { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn get_entry_name(&self, _ino: crate::filesystem::vfs::InodeId) -> Result { + // 若文件系统没有实现此方法,则返回“不支持” + 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 { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn mount( + &self, + _fs: Arc, + ) -> Result, 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>) -> Self { - Self { - port, - baud_rate, - sys_info, - } +impl DeviceINode for LockedUart { + fn set_fs(&self, fs: Weak) { + 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 { + 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>, +} + +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); + +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>) { + self.0.lock().sys_info = sys_info; + } + + fn sys_info(&self) -> Option> { + 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, + ) -> Result, DriverError> { + return Err(DriverError::UnsupportedOperation); + } +} + +impl LockedUartDriver { + /// @brief 创建串口驱动 + /// @param sys_info: sys文件系统inode + /// @return + #[allow(dead_code)] + pub fn new(sys_info: Option>) -> 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>) -> 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(()); } diff --git a/kernel/src/driver/uart/uart_driver.rs b/kernel/src/driver/uart/uart_driver.rs new file mode 100644 index 00000000..4bea7281 --- /dev/null +++ b/kernel/src/driver/uart/uart_driver.rs @@ -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); + +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, + ) -> Result, 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>) { + todo!() + } + + fn sys_info(&self) -> Option> { + todo!() + } +} diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index cb68b590..36edc061 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -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(name: &str, device: Arc) -> Result<(), pub fn devfs_unregister(name: &str, device: Arc) -> 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::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(); +} diff --git a/kernel/src/filesystem/fat/bpb.rs b/kernel/src/filesystem/fat/bpb.rs index 9f5c8573..1fbad7c9 100644 --- a/kernel/src/filesystem/fat/bpb.rs +++ b/kernel/src/filesystem/fat/bpb.rs @@ -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, diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index af7af5d1..021c9c5e 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -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 = 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(); diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index cf59a043..1277afaa 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -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, SystemError> { // 由于FAT32不支持文件权限的功能,因此忽略mode参数 - let mut guard: SpinLockGuard = self.0.lock(); let fs: &Arc = &guard.fs.upgrade().unwrap(); diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index c1146cfb..cddd517f 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -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::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(); +} diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index bc0093e9..c94ff982 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -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::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(); +} diff --git a/kernel/src/filesystem/vfs/core.rs b/kernel/src/filesystem/vfs/core.rs index 1a7b8eb4..8026f3f8 100644 --- a/kernel/src/filesystem/vfs/core.rs +++ b/kernel/src/filesystem/vfs/core.rs @@ -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::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::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::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) -> Result<(), SystemE #[no_mangle] pub extern "C" fn mount_root_fs() -> i32 { kinfo!("Try to mount FAT32 as root fs..."); - let partiton: Arc = - ahci::get_disks_by_name("ahci_disk_0".to_string()) - .unwrap() - .0 - .lock() - .partitions[0] - .clone(); + let partiton: Arc = ahci::get_disks_by_name("ahci_disk_0".to_string()) + .unwrap() + .0 + .lock() + .partitions[0] + .clone(); let fatfs: Result, SystemError> = FATFileSystem::new(partiton); if fatfs.is_err() { diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 2520c0d6..cf41224f 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -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, diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index d4232d79..d037e068 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -3,7 +3,6 @@ pub mod core; pub mod fcntl; pub mod file; -pub mod io; pub mod mount; pub mod syscall; mod utils; diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 3a5e90c7..c439f558 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -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}, diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index 7fd9d348..d6ca7818 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -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::{ diff --git a/kernel/src/libs/lib_ui/screen_manager.rs b/kernel/src/libs/lib_ui/screen_manager.rs index 5689329c..35a19dc0 100644 --- a/kernel/src/libs/lib_ui/screen_manager.rs +++ b/kernel/src/libs/lib_ui/screen_manager.rs @@ -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, }, diff --git a/kernel/src/libs/lib_ui/textui.rs b/kernel/src/libs/lib_ui/textui.rs index 1c60bbd1..98362351 100644 --- a/kernel/src/libs/lib_ui/textui.rs +++ b/kernel/src/libs/lib_ui/textui.rs @@ -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}, diff --git a/kernel/src/libs/lib_ui/textui_no_alloc.rs b/kernel/src/libs/lib_ui/textui_no_alloc.rs index 82de0a36..6f7c26fe 100644 --- a/kernel/src/libs/lib_ui/textui_no_alloc.rs +++ b/kernel/src/libs/lib_ui/textui_no_alloc.rs @@ -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, }; diff --git a/kernel/src/libs/vec_cursor.rs b/kernel/src/libs/vec_cursor.rs index 74371297..983d7bae 100644 --- a/kernel/src/libs/vec_cursor.rs +++ b/kernel/src/libs/vec_cursor.rs @@ -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)] diff --git a/kernel/src/main.c b/kernel/src/main.c index 14635d67..a72c3bd8 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -34,7 +34,8 @@ #include -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(); // 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块 diff --git a/kernel/src/process/exec.rs b/kernel/src/process/exec.rs index be6e1601..9a169e91 100644 --- a/kernel/src/process/exec.rs +++ b/kernel/src/process/exec.rs @@ -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, diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index e6b0d128..d21a9fb0 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -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, diff --git a/user/apps/test_uart/Makefile b/user/apps/test_uart/Makefile new file mode 100644 index 00000000..bf1fa624 --- /dev/null +++ b/user/apps/test_uart/Makefile @@ -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 \ No newline at end of file diff --git a/user/apps/test_uart/link.lds b/user/apps/test_uart/link.lds new file mode 100644 index 00000000..1f2e57e4 --- /dev/null +++ b/user/apps/test_uart/link.lds @@ -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_*) } +} diff --git a/user/apps/test_uart/main.c b/user/apps/test_uart/main.c new file mode 100644 index 00000000..60afd411 --- /dev/null +++ b/user/apps/test_uart/main.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/user/dadk/config/test_uart-0.1.0.dadk b/user/dadk/config/test_uart-0.1.0.dadk new file mode 100644 index 00000000..c1b5ca37 --- /dev/null +++ b/user/dadk/config/test_uart-0.1.0.dadk @@ -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": [] +}