设备驱动模型:完善platform bus相关内容。并注册串口到sysfs (#403)

* 完成初始化platform bus
* 删除旧的sysfs
* 把uart驱动移动到tty/serial文件夹下
* 完成将串口挂载到sysfs
* 修复vfs系统调用未能follow symlink的问题
* 修复shell未能正确获取pwd的问题
This commit is contained in:
LoGin 2023-10-20 22:11:33 +08:00 committed by GitHub
parent 06d5e24726
commit a03c4f9dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 2904 additions and 1325 deletions

View File

@ -180,6 +180,7 @@
"rust-analyzer.cargo.target": "x86_64-unknown-none",
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.linkedProjects": [
"./kernel/Cargo.toml"
"./kernel/Cargo.toml",
"./kernel/src/libs/ida/Cargo.toml"
],
}

View File

@ -34,6 +34,7 @@ raw-cpuid = "11.0.1"
acpi = "5.0.0"
intertrait = { path = "src/libs/intertrait" }
linkme = "0.2"
ida = { path = "src/libs/ida" }
# 构建时依赖项
[build-dependencies]

9
kernel/src/arch/io.rs Normal file
View File

@ -0,0 +1,9 @@
/// 每个架构都需要实现的IO接口
pub trait PortIOArch {
unsafe fn in8(port: u16) -> u8;
unsafe fn in16(port: u16) -> u16;
unsafe fn in32(port: u16) -> u32;
unsafe fn out8(port: u16, data: u8);
unsafe fn out16(port: u16, data: u16);
unsafe fn out32(port: u16, data: u32);
}

View File

@ -7,6 +7,8 @@ use crate::{
mm::PhysAddr,
};
pub mod io;
/// TraitPciArch Pci架构相关函数任何架构都应独立实现trait里的函数
pub trait TraitPciArch {
/// @brief 读取寄存器值x86_64架构通过读取两个特定io端口实现

View File

@ -1,2 +1,3 @@
pub mod bitops;
pub mod irqflags;
pub mod pio;

View File

@ -0,0 +1,35 @@
use crate::arch::io::PortIOArch;
pub struct X86_64PortIOArch;
impl PortIOArch for X86_64PortIOArch {
#[inline(always)]
unsafe fn in8(port: u16) -> u8 {
x86::io::inb(port)
}
#[inline(always)]
unsafe fn in16(port: u16) -> u16 {
x86::io::inw(port)
}
#[inline(always)]
unsafe fn in32(port: u16) -> u32 {
x86::io::inl(port)
}
#[inline(always)]
unsafe fn out8(port: u16, data: u8) {
x86::io::outb(port, data)
}
#[inline(always)]
unsafe fn out16(port: u16, data: u16) {
x86::io::outw(port, data)
}
#[inline(always)]
unsafe fn out32(port: u16, data: u32) {
x86::io::outl(port, data)
}
}

View File

@ -5,7 +5,7 @@ use hashbrown::HashSet;
use x86::time::rdtsc;
use x86_64::registers::model_specific::EferFlags;
use crate::driver::uart::uart_device::c_uart_send_str;
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
use crate::include::bindings::bindings::{
multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
};
@ -148,7 +148,7 @@ impl MemoryManagementArch for X86_64MMArch {
// 初始化物理内存区域(从multiboot2中获取)
let areas_count =
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
c_uart_send_str(0x3f8, "x86 64 init end\n\0".as_ptr());
send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes());
return &PHYS_MEMORY_AREAS[0..areas_count];
}
@ -229,7 +229,7 @@ impl X86_64MMArch {
unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
// 这个数组用来存放内存区域的信息从C获取
let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed();
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 begin\n\0".as_ptr());
send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes());
let mut mb2_count: u32 = 0;
multiboot2_iter(
@ -237,7 +237,7 @@ impl X86_64MMArch {
&mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void,
&mut mb2_count,
);
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 2\n\0".as_ptr());
send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes());
let mb2_count = mb2_count as usize;
let mut areas_count = 0usize;
@ -255,7 +255,7 @@ impl X86_64MMArch {
areas_count += 1;
}
}
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 end\n\0".as_ptr());
send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes());
kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
return Ok(areas_count);
@ -291,7 +291,7 @@ impl VirtAddr {
/// @brief 初始化内存管理模块
pub fn mm_init() {
c_uart_send_str(0x3f8, "mm_init\n\0".as_ptr());
send_to_default_serial8250_port("mm_init\n\0".as_bytes());
PrintkWriter
.write_fmt(format_args!("mm_init() called\n"))
.unwrap();
@ -301,7 +301,7 @@ pub fn mm_init() {
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{
c_uart_send_str(0x3f8, "mm_init err\n\0".as_ptr());
send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
panic!("mm_init() can only be called once");
}

View File

@ -20,3 +20,5 @@ pub use self::pci::pci::X86_64PciArch as PciArch;
pub use self::mm::X86_64MMArch as MMArch;
pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;

View File

@ -0,0 +1,23 @@
use alloc::sync::Arc;
use crate::{
driver::base::device::{driver::Driver, Device},
syscall::SystemError,
};
use super::AcpiManager;
impl AcpiManager {
/// 通过acpi来匹配驱动
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#949
pub fn driver_match_device(
&self,
_driver: &Arc<dyn Driver>,
_device: &Arc<dyn Device>,
) -> Result<bool, SystemError> {
// todo:
return Ok(false);
}
}

View File

@ -14,6 +14,7 @@ use crate::{
},
};
pub mod bus;
mod c_adapter;
pub mod glue;
pub mod old;
@ -22,6 +23,11 @@ extern crate acpi;
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
#[inline(always)]
pub fn acpi_manager() -> &'static AcpiManager {
&AcpiManager
}
#[derive(Debug)]
pub struct AcpiManager;

View File

@ -1,8 +1,19 @@
use super::{sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState};
use super::{
driver::{Driver, DriverMatchName, DriverMatcher},
sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState,
};
use crate::{
driver::base::{device::device_manager, kobject::KObject, kset::KSet, subsys::SubSysPrivate},
driver::base::{
device::{device_manager, driver::driver_manager},
kobject::{KObjType, KObject, KObjectManager},
kset::KSet,
subsys::SubSysPrivate,
},
filesystem::{
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOpsSupport},
sysfs::{
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
SysFSOpsSupport,
},
vfs::syscall::ModeType,
},
libs::rwlock::RwLock,
@ -14,6 +25,7 @@ use alloc::{
};
use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely};
use hashbrown::HashMap;
use intertrait::cast::CastArc;
/// `/sys/bus`的kset
static mut BUS_KSET_INSTANCE: Option<Arc<KSet>> = None;
@ -105,6 +117,46 @@ pub trait Bus: Debug + Send + Sync {
&[]
}
/// 检查设备是否可以被总线绑定,如果可以,就绑定它们。
/// 绑定之后,device的driver字段会被设置为驱动实例。
///
/// ## 参数
///
/// - `device` - 设备实例
///
/// ## 默认实现
///
/// 如果总线不支持该操作,返回`SystemError::EOPNOTSUPP_OR_ENOTSUP`
fn probe(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError>;
fn sync_state(&self, _device: &Arc<dyn Device>) {}
fn shutdown(&self, _device: &Arc<dyn Device>);
fn suspend(&self, _device: &Arc<dyn Device>) {
// todo: implement suspend
}
fn resume(&self, device: &Arc<dyn Device>) -> Result<(), SystemError>;
/// match platform device to platform driver.
///
/// ## 参数
///
/// * `device` - platform device
/// * `driver` - platform driver
///
/// ## 返回
///
/// - `Ok(true)` - 匹配成功
/// - `Ok(false)` - 匹配失败
/// - `Err(_)` - 由于内部错误导致匹配失败
fn match_device(
&self,
device: &Arc<dyn Device>,
driver: &Arc<dyn Driver>,
) -> Result<bool, SystemError>;
fn subsystem(&self) -> &SubSysPrivate;
/// 对当前总线操作的时候需要获取父级总线的锁
@ -126,7 +178,7 @@ impl dyn Bus {
data: T,
) -> Option<Arc<dyn Device>> {
let subsys = self.subsystem();
let guard = subsys.devices().read();
let guard = subsys.devices();
for dev in guard.iter() {
let dev = dev.upgrade();
if let Some(dev) = dev {
@ -146,6 +198,35 @@ impl dyn Bus {
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
return self.find_device(&DeviceMatchName, name);
}
/// 在bus上,根据条件寻找一个特定的驱动
///
/// ## 参数
///
/// - `matcher` - 匹配器
/// - `data` - 传给匹配器的数据
pub fn find_driver<T: Copy>(
&self,
matcher: &dyn DriverMatcher<T>,
data: T,
) -> Option<Arc<dyn Driver>> {
let subsys = self.subsystem();
let guard = subsys.drivers();
for drv in guard.iter() {
let drv = drv.upgrade();
if let Some(drv) = drv {
if matcher.match_driver(&drv, data) {
return Some(drv.clone());
}
}
}
return None;
}
/// 根据名称在bus上匹配驱动
pub fn find_driver_by_name(&self, name: &str) -> Option<Arc<dyn Driver>> {
return self.find_driver(&DriverMatchName, name);
}
}
/// @brief: 总线管理结构体
@ -162,6 +243,94 @@ impl BusManager {
};
}
/// 把一个设备添加到总线上
///
/// ## 描述
///
/// - 添加一个设备的与bus相关的属性
/// - 在bus和设备文件夹下创建软链接
/// - 把设备添加到它的总线的设备列表中
///
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_device#441
///
/// ## 参数
///
/// - `dev` - 要被添加的设备
pub fn add_device(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
let bus = dev.bus();
if let Some(bus) = bus {
device_manager().add_groups(dev, bus.dev_groups())?;
// 增加符号链接
let bus_devices_kset = bus
.subsystem()
.devices_kset()
.expect("bus devices kset is none, maybe bus is not registered");
let dev_kobj = dev.clone() as Arc<dyn KObject>;
sysfs_instance().create_link(
Some(&bus_devices_kset.as_kobject()),
&dev_kobj,
dev.name(),
)?;
sysfs_instance().create_link(
Some(&dev_kobj),
&(&bus.subsystem().subsys().as_kobject()),
"subsystem".to_string(),
)?;
bus.subsystem().add_device_to_vec(dev)?;
}
return Ok(());
}
/// 在总线上添加一个驱动
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_driver#590
pub fn add_driver(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
kdebug!("bus '{}' add driver '{}'", bus.name(), driver.name());
driver.set_kobj_type(Some(&BusDriverKType));
let kobj = driver.clone() as Arc<dyn KObject>;
KObjectManager::add_kobj(kobj, bus.subsystem().drivers_kset())?;
bus.subsystem().add_driver_to_vec(driver)?;
if bus.subsystem().drivers_autoprobe() {
let r = driver_manager().driver_attach(driver);
if let Err(e) = r {
bus.subsystem().remove_driver_from_vec(driver);
return Err(e);
}
}
driver_manager()
.add_groups(driver, bus.drv_groups())
.or_else(|e| {
kerror!(
"BusManager::add_driver: driver '{:?}' add_groups failed, err: '{:?}",
driver.name(),
e
);
Err(e)
})
.ok();
if !driver.suppress_bind_attrs() {
self.add_bind_files(driver)
.or_else(|e| {
kerror!(
"BusManager::add_driver: driver '{:?}' add_bind_files failed, err: '{:?}",
driver.name(),
e
);
Err(e)
})
.ok();
}
return Ok(());
}
///
/// bus_register - register a driver-core subsystem
///
@ -257,7 +426,7 @@ impl BusManager {
/// - `bus` - bus实例
#[allow(dead_code)]
pub fn rescan_devices(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
for dev in bus.subsystem().devices().read().iter() {
for dev in bus.subsystem().devices().iter() {
let dev = dev.upgrade();
if let Some(dev) = dev {
rescan_devices_helper(dev)?;
@ -283,21 +452,32 @@ impl BusManager {
}
}
/// 在bus上,根据条件寻找一个特定的设备
/// 从总线上移除一个驱动
///
/// Detach the driver from the devices it controls, and remove
/// it from its bus's list of drivers. Finally, we drop the reference
/// to the bus.
///
/// ## 参数
///
/// - `matcher` - 匹配器
/// - `data` - 传给匹配器的数据
#[inline]
#[allow(dead_code)]
pub fn find_device<T: Copy>(
&self,
bus: &Arc<dyn Bus>,
matcher: &dyn DeviceMatcher<T>,
data: T,
) -> Option<Arc<dyn Device>> {
return bus.find_device(matcher, data);
/// - `driver` - 驱动实例
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_remove_driver#666
pub fn remove_driver(&self, _driver: &Arc<dyn Driver>) {
todo!("BusManager::remove_driver")
}
fn add_bind_files(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
driver_manager().create_attr_file(driver, &DriverAttrUnbind)?;
driver_manager()
.create_attr_file(driver, &DriverAttrBind)
.map_err(|e| {
driver_manager().remove_attr_file(driver, &DriverAttrUnbind);
e
})?;
return Ok(());
}
}
@ -376,13 +556,7 @@ pub fn buses_init() -> Result<(), SystemError> {
///
/// - `dev` - 要被添加的设备
pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
let bus = dev.bus();
if let Some(bus) = bus {
device_manager().add_groups(dev, bus.dev_groups())?;
// todo: 增加符号链接
todo!("bus_add_device")
}
return Ok(());
return bus_manager().add_device(dev);
}
/// 自动为设备在总线上寻找可用的驱动程序
@ -507,3 +681,129 @@ pub enum BusNotifyEvent {
/// 驱动绑定失败
DriverNotBound,
}
#[derive(Debug)]
struct BusDriverKType;
impl KObjType for BusDriverKType {
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
Some(&BusDriverSysFSOps)
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
None
}
}
#[derive(Debug)]
struct BusDriverSysFSOps;
impl SysFSOps for BusDriverSysFSOps {
#[inline]
fn show(
&self,
kobj: Arc<dyn KObject>,
attr: &dyn Attribute,
buf: &mut [u8],
) -> Result<usize, SystemError> {
attr.show(kobj, buf)
}
#[inline]
fn store(
&self,
kobj: Arc<dyn KObject>,
attr: &dyn Attribute,
buf: &[u8],
) -> Result<usize, SystemError> {
attr.store(kobj, buf)
}
}
#[derive(Debug)]
struct DriverAttrUnbind;
impl Attribute for DriverAttrUnbind {
fn mode(&self) -> ModeType {
ModeType::from_bits_truncate(0o200)
}
fn name(&self) -> &str {
"unbind"
}
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
let driver = kobj.cast::<dyn Driver>().map_err(|kobj| {
kerror!(
"Intertrait casting not implemented for kobj: {}",
kobj.name()
);
SystemError::EOPNOTSUPP_OR_ENOTSUP
})?;
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
let s = CStr::from_bytes_with_nul(buf)
.map_err(|_| SystemError::EINVAL)?
.to_str()
.map_err(|_| SystemError::EINVAL)?;
let dev = bus.find_device_by_name(s).ok_or(SystemError::ENODEV)?;
let p = dev.driver().ok_or(SystemError::ENODEV)?;
if Arc::ptr_eq(&p, &driver) {
device_manager().device_driver_detach(&dev);
return Ok(buf.len());
}
return Err(SystemError::ENODEV);
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::STORE
}
}
#[derive(Debug)]
struct DriverAttrBind;
impl Attribute for DriverAttrBind {
fn name(&self) -> &str {
"bind"
}
fn mode(&self) -> ModeType {
ModeType::from_bits_truncate(0o200)
}
/*
* Manually attach a device to a driver.
* Note: the driver must want to bind to the device,
* it is not possible to override the driver's id table.
*/
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
let driver = kobj.cast::<dyn Driver>().map_err(|kobj| {
kerror!(
"Intertrait casting not implemented for kobj: {}",
kobj.name()
);
SystemError::EOPNOTSUPP_OR_ENOTSUP
})?;
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
let device = bus
.find_device_by_name(
CStr::from_bytes_with_nul(buf)
.map_err(|_| SystemError::EINVAL)?
.to_str()
.map_err(|_| SystemError::EINVAL)?,
)
.ok_or(SystemError::ENODEV)?;
if driver_manager().match_device(&driver, &device)? {
device_manager().device_driver_attach(&driver, &device)?;
return Ok(buf.len());
}
return Err(SystemError::ENODEV);
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::STORE
}
}

View File

@ -1,10 +1,26 @@
use core::intrinsics::unlikely;
use alloc::sync::Arc;
use alloc::{string::ToString, sync::Arc};
use intertrait::cast::CastArc;
use crate::{driver::Driver, syscall::SystemError};
use crate::{
driver::base::kobject::KObject,
filesystem::{
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport},
vfs::syscall::ModeType,
},
libs::wait_queue::WaitQueue,
syscall::SystemError,
};
use super::{bus::BusNotifyEvent, driver::driver_manager, Device, DeviceManager};
use super::{
bus::BusNotifyEvent,
device_manager,
driver::{driver_manager, Driver, DriverManager},
Device, DeviceManager,
};
static PROBE_WAIT_QUEUE: WaitQueue = WaitQueue::INIT;
impl DeviceManager {
/// 尝试把一个设备与一个驱动匹配
@ -40,7 +56,8 @@ impl DeviceManager {
allow_async: bool,
) -> Result<bool, SystemError> {
if unlikely(allow_async) {
todo!("do_device_attach: allow_async")
// todo!("do_device_attach: allow_async")
kwarn!("do_device_attach: allow_async is true, but currently not supported");
}
if dev.is_dead() {
return Ok(false);
@ -64,7 +81,7 @@ impl DeviceManager {
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
let mut flag = true;
for driver in bus.subsystem().drivers().read().iter() {
for driver in bus.subsystem().drivers().iter() {
if let Some(driver) = driver.upgrade() {
let r = self.do_device_attach_driver(&driver, &mut data);
if unlikely(r.is_err()) {
@ -142,7 +159,7 @@ impl DeviceManager {
let r = driver_manager().driver_sysfs_add(dev);
if let Err(e) = r {
self.device_links_force_bind(dev);
self.driver_bound(dev);
driver_manager().driver_bound(dev);
return Err(e);
} else {
if let Some(bus) = dev.bus() {
@ -156,9 +173,10 @@ impl DeviceManager {
return r;
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
fn driver_bound(&self, _dev: &Arc<dyn Device>) {
todo!("driver_bound")
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528
fn unbind_cleanup(&self, dev: &Arc<dyn Device>) {
dev.set_driver(None);
// todo: 添加更多操作,清理数据
}
}
@ -208,3 +226,368 @@ impl DeviceAttachData {
self.have_async = true;
}
}
impl DriverManager {
/// 尝试把驱动绑定到现有的设备上
///
/// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。
/// 一旦有一个设备匹配成功就会返回并且设备的driver字段会被设置。
pub fn driver_attach(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
for dev in bus.subsystem().devices().iter() {
if let Some(dev) = dev.upgrade() {
if self.do_driver_attach(&dev, &driver) {
// 匹配成功
return Ok(());
}
}
}
return Ok(());
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#1134
fn do_driver_attach(&self, device: &Arc<dyn Device>, driver: &Arc<dyn Driver>) -> bool {
let r = self.match_device(driver, device).unwrap_or(false);
if r == false {
// 不匹配
return false;
}
if driver.allows_async_probing() {
unimplemented!(
"do_driver_attach: probe driver '{}' asynchronously",
driver.name()
);
}
if self.probe_device(driver, device).is_err() {
return false;
}
return true;
}
#[inline(always)]
pub fn match_device(
&self,
driver: &Arc<dyn Driver>,
device: &Arc<dyn Device>,
) -> Result<bool, SystemError> {
return driver.bus().unwrap().match_device(device, driver);
}
/// 尝试把设备和驱动绑定在一起
///
///
/// ## 返回
///
/// - Ok(): 绑定成功
/// - Err(ENODEV): 设备未注册
/// - Err(EBUSY): 设备已经绑定到驱动上
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#802
fn probe_device(
&self,
driver: &Arc<dyn Driver>,
device: &Arc<dyn Device>,
) -> Result<(), SystemError> {
let r = self.do_probe_device(driver, device);
PROBE_WAIT_QUEUE.wakeup_all(None);
return r;
}
fn do_probe_device(
&self,
driver: &Arc<dyn Driver>,
device: &Arc<dyn Device>,
) -> Result<(), SystemError> {
if device.is_dead() || (!device.is_registered()) {
return Err(SystemError::ENODEV);
}
if device.driver().is_some() {
return Err(SystemError::EBUSY);
}
device.set_can_match(true);
self.really_probe(driver, device)?;
return Ok(());
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#584
fn really_probe(
&self,
driver: &Arc<dyn Driver>,
device: &Arc<dyn Device>,
) -> Result<(), SystemError> {
let bind_failed = || {
device_manager().unbind_cleanup(device);
};
let sysfs_failed = || {
if let Some(bus) = device.bus() {
bus.subsystem().bus_notifier().call_chain(
BusNotifyEvent::DriverNotBound,
Some(device),
None,
);
}
};
let probe_failed = || {
self.remove_from_sysfs(device);
};
let dev_groups_failed = || {
device_manager().remove(device);
};
device.set_driver(Some(Arc::downgrade(driver)));
self.add_to_sysfs(device).map_err(|e| {
kerror!(
"really_probe: add_to_sysfs failed, dev: '{}', err: {:?}",
device.name(),
e
);
sysfs_failed();
bind_failed();
e
})?;
self.call_driver_probe(device, driver).map_err(|e| {
kerror!(
"really_probe: call_driver_probe failed, dev: '{}', err: {:?}",
device.name(),
e
);
probe_failed();
sysfs_failed();
bind_failed();
e
})?;
device_manager()
.add_groups(device, driver.dev_groups())
.map_err(|e| {
kerror!(
"really_probe: add_groups failed, dev: '{}', err: {:?}",
device.name(),
e
);
dev_groups_failed();
probe_failed();
sysfs_failed();
bind_failed();
e
})?;
// 我们假设所有的设备都有sync_state这个属性。如果没有的话也创建属性文件。
device_manager()
.create_file(device, &DeviceAttrStateSynced)
.map_err(|e| {
kerror!(
"really_probe: create_file failed, dev: '{}', err: {:?}",
device.name(),
e
);
dev_groups_failed();
probe_failed();
sysfs_failed();
bind_failed();
e
})?;
self.driver_bound(device);
return Ok(());
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#434
fn add_to_sysfs(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
let driver = device.driver().ok_or(SystemError::EINVAL)?;
if let Some(bus) = device.bus() {
bus.subsystem().bus_notifier().call_chain(
BusNotifyEvent::BindDriver,
Some(&device),
None,
);
}
let driver_kobj = driver.clone() as Arc<dyn KObject>;
let device_kobj = device.clone() as Arc<dyn KObject>;
sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device.name())?;
let fail_rm_dev_link = || {
sysfs_instance().remove_link(&driver_kobj, device.name());
};
sysfs_instance()
.create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
.map_err(|e| {
fail_rm_dev_link();
e
})?;
device_manager()
.create_file(device, &DeviceAttrCoredump)
.map_err(|e| {
sysfs_instance().remove_link(&device_kobj, "driver".to_string());
fail_rm_dev_link();
e
})?;
return Ok(());
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#469
fn remove_from_sysfs(&self, _device: &Arc<dyn Device>) {
todo!("remove_from_sysfs")
}
fn call_driver_probe(
&self,
device: &Arc<dyn Device>,
driver: &Arc<dyn Driver>,
) -> Result<(), SystemError> {
let bus = device.bus().ok_or(SystemError::EINVAL)?;
let r = bus.probe(device);
if r == Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) {
kerror!(
"call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}",
device.name(),
r
);
return r;
}
if r.is_ok() {
return Ok(());
}
let err = r.unwrap_err();
match err {
SystemError::ENODEV | SystemError::ENXIO => {
kdebug!(
"driver'{}': probe of {} rejects match {:?}",
driver.name(),
device.name(),
err
);
}
_ => {
kwarn!(
"driver'{}': probe of {} failed with error {:?}",
driver.name(),
device.name(),
err
);
}
}
return Err(err);
}
/// 当设备被成功探测,进行了'设备->驱动'绑定后,调用这个函数,完成'驱动->设备'的绑定
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
fn driver_bound(&self, device: &Arc<dyn Device>) {
if self.driver_is_bound(device) {
kwarn!("driver_bound: device '{}' is already bound.", device.name());
return;
}
let driver = device.driver().unwrap();
driver.add_device(device.clone());
if let Some(bus) = device.bus() {
bus.subsystem().bus_notifier().call_chain(
BusNotifyEvent::BoundDriver,
Some(device),
None,
);
}
// todo: 发送kobj bind的uevent
}
fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {
if let Some(driver) = device.driver() {
if driver.find_device_by_name(&device.name()).is_some() {
return true;
}
}
return false;
}
}
/// 设备文件夹下的`dev`文件的属性
#[derive(Debug, Clone, Copy)]
pub struct DeviceAttrStateSynced;
impl Attribute for DeviceAttrStateSynced {
fn mode(&self) -> ModeType {
// 0o444
return ModeType::S_IRUGO;
}
fn name(&self) -> &str {
"state_synced"
}
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
kerror!(
"Intertrait casting not implemented for kobj: {}",
kobj.name()
);
SystemError::EOPNOTSUPP_OR_ENOTSUP
})?;
let val = dev.state_synced();
let val = if val { 1 } else { 0 };
return sysfs_emit_str(buf, format!("{}\n", val).as_str());
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::SHOW
}
}
#[derive(Debug)]
struct DeviceAttrCoredump;
impl Attribute for DeviceAttrCoredump {
fn name(&self) -> &str {
"coredump"
}
fn mode(&self) -> ModeType {
ModeType::from_bits_truncate(0o200)
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::STORE
}
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
kerror!(
"Intertrait casting not implemented for kobj: {}",
kobj.name()
);
SystemError::EOPNOTSUPP_OR_ENOTSUP
})?;
let drv = dev.driver().ok_or(SystemError::EINVAL)?;
drv.coredump(&dev)?;
return Ok(buf.len());
}
}

View File

@ -1,6 +1,13 @@
use super::Device;
use crate::syscall::SystemError;
use alloc::sync::Arc;
use super::{
bus::{bus_manager, Bus},
Device, DeviceMatchName, DeviceMatcher, IdTable,
};
use crate::{
driver::base::kobject::KObject,
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
syscall::SystemError,
};
use alloc::{sync::Arc, vec::Vec};
use core::fmt::Debug;
/// @brief: Driver error
@ -31,13 +38,278 @@ pub fn driver_manager() -> &'static DriverManager {
&DriverManager
}
/// 驱动程序应当实现的trait
///
/// ## 注意
///
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Driver>
/// 因此,所有的实现了 Driver trait的结构体都应该在结构体上方标注`#[cast_to([sync] Driver)]`
/// 否则在运行时会报错
pub trait Driver: Sync + Send + Debug + KObject {
fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
}
/// @brief: 获取驱动标识符
/// @parameter: None
/// @return: 该驱动驱动唯一标识符
fn id_table(&self) -> Option<IdTable>;
fn devices(&self) -> Vec<Arc<dyn Device>>;
/// 把设备加入当前驱动管理的列表中
fn add_device(&self, device: Arc<dyn Device>);
/// 从当前驱动管理的列表中删除设备
fn delete_device(&self, device: &Arc<dyn Device>);
/// 根据设备名称查找绑定到驱动的设备
///
/// 该方法是一个快速查找方法,要求驱动开发者自行实现。
///
/// 如果开发者没有实现该方法则应当返回None
///
/// ## 注意
///
/// 这是一个内部方法,不应当被外部调用,若要查找设备,请使用`find_device_by_name()`
fn __find_device_by_name_fast(&self, _name: &str) -> Option<Arc<dyn Device>> {
None
}
/// 是否禁用sysfs的bind/unbind属性
///
/// ## 返回
///
/// - true: 禁用
/// - false: 不禁用(默认)
fn suppress_bind_attrs(&self) -> bool {
false
}
fn bus(&self) -> Option<Arc<dyn Bus>> {
None
}
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
fn groups(&self) -> &'static [&'static dyn AttributeGroup] {
&[]
}
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
&[]
}
/// 使用什么样的策略来探测设备
fn probe_type(&self) -> DriverProbeType {
DriverProbeType::DefaultStrategy
}
}
impl dyn Driver {
pub fn allows_async_probing(&self) -> bool {
match self.probe_type() {
DriverProbeType::PreferAsync => true,
DriverProbeType::ForceSync => false,
DriverProbeType::DefaultStrategy => {
// todo: 判断是否请求异步探测如果是的话就返回true
// 由于目前还没有支持异步探测因此这里暂时返回false
false
}
}
}
/// 根据条件寻找一个绑定到这个驱动的设备(低效实现)
///
/// ## 参数
///
/// - `matcher` - 匹配器
/// - `data` - 传给匹配器的数据
///
/// ## 注意
///
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
fn find_device_slow<T: Copy>(
&self,
matcher: &dyn DeviceMatcher<T>,
data: T,
) -> Option<Arc<dyn Device>> {
for dev in self.devices() {
if matcher.match_device(&dev, data) {
return Some(dev);
}
}
return None;
}
/// 根据设备名称查找绑定到驱动的设备
///
/// ## 注意
///
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
if let Some(r) = self.__find_device_by_name_fast(name) {
return Some(r);
}
return self.find_device_slow(&DeviceMatchName, name);
}
}
/// @brief: 驱动管理器
#[derive(Debug, Clone)]
pub struct DriverManager;
impl DriverManager {
/// 注册设备驱动。该设备驱动应当已经设置好其bus字段
///
/// ## 参数
///
/// - driver: 驱动
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/driver.c#222
pub fn register(&self, driver: Arc<dyn Driver>) -> Result<(), SystemError> {
let bus = driver.bus().ok_or_else(|| {
kerror!(
"DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
driver.name()
);
SystemError::EINVAL
})?;
let drv_name = driver.name();
let other = bus.find_driver_by_name(&drv_name);
if other.is_some() {
kerror!(
"DriverManager::register() failed: driver '{}' already registered",
drv_name
);
return Err(SystemError::EBUSY);
}
bus_manager().add_driver(&driver)?;
self.add_groups(&driver, driver.groups()).map_err(|e| {
bus_manager().remove_driver(&driver);
e
})?;
// todo: 发送uevent
return Ok(());
}
/// 从系统中删除一个驱动程序
#[allow(dead_code)]
pub fn unregister(&self, driver: &Arc<dyn Driver>) {
self.remove_groups(driver, driver.groups());
bus_manager().remove_driver(driver);
}
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#434
pub fn driver_sysfs_add(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!("DriverManager::driver_sysfs_add()");
}
pub fn add_groups(
&self,
driver: &Arc<dyn Driver>,
groups: &'static [&dyn AttributeGroup],
) -> Result<(), SystemError> {
let kobj = driver.clone() as Arc<dyn KObject>;
return sysfs_instance().create_groups(&kobj, groups);
}
pub fn remove_groups(&self, driver: &Arc<dyn Driver>, groups: &'static [&dyn AttributeGroup]) {
let kobj = driver.clone() as Arc<dyn KObject>;
sysfs_instance().remove_groups(&kobj, groups);
}
/// 为指定的驱动创建一个属性文件
///
/// ## 参数
///
/// - `driver` 要创建属性文件的驱动
/// - `attr` 属性
pub fn create_attr_file(
&self,
driver: &Arc<dyn Driver>,
attr: &'static dyn Attribute,
) -> Result<(), SystemError> {
let kobj = driver.clone() as Arc<dyn KObject>;
return sysfs_instance().create_file(&kobj, attr);
}
/// 为指定的驱动删除一个属性文件
///
/// 如果属性不存在,也不会报错
///
/// ## 参数
///
/// - `driver` 要删除属性文件的驱动
/// - `attr` 属性
pub fn remove_attr_file(&self, driver: &Arc<dyn Driver>, attr: &'static dyn Attribute) {
let kobj = driver.clone() as Arc<dyn KObject>;
sysfs_instance().remove_file(&kobj, attr);
}
}
/// 驱动匹配器
///
/// 用于匹配驱动是否符合某个条件
///
/// ## 参数
///
/// - `T` - 匹配器的数据类型
/// - `data` - 匹配器的数据
pub trait DriverMatcher<T>: Debug {
fn match_driver(&self, driver: &Arc<dyn Driver>, data: T) -> bool;
}
/// 根据名称匹配驱动
#[derive(Debug)]
pub struct DriverMatchName;
impl DriverMatcher<&str> for DriverMatchName {
#[inline(always)]
fn match_driver(&self, driver: &Arc<dyn Driver>, data: &str) -> bool {
driver.name() == data
}
}
/// enum probe_type - device driver probe type to try
/// Device drivers may opt in for special handling of their
/// respective probe routines. This tells the core what to
/// expect and prefer.
///
/// Note that the end goal is to switch the kernel to use asynchronous
/// probing by default, so annotating drivers with
/// %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
/// to speed up boot process while we are validating the rest of the
/// drivers.
#[allow(dead_code)]
#[derive(Debug)]
pub enum DriverProbeType {
/// Used by drivers that work equally well
/// whether probed synchronously or asynchronously.
DefaultStrategy,
/// Drivers for "slow" devices which
/// probing order is not essential for booting the system may
/// opt into executing their probes asynchronously.
PreferAsync,
/// Use this to annotate drivers that need
/// their probe routines to run synchronously with driver and
/// device registration (with the exception of -EPROBE_DEFER
/// handling - re-probing always ends up being done asynchronously).
ForceSync,
}
impl Default for DriverProbeType {
fn default() -> Self {
DriverProbeType::DefaultStrategy
}
}

View File

@ -1,27 +1,17 @@
use alloc::{string::ToString, sync::Arc};
use crate::{
driver::{
base::{
device::{
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER,
DEV_KSET_INSTANCE,
},
kobject::KObject,
kset::KSet,
driver::base::{
device::{
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, DEV_KSET_INSTANCE,
},
uart::uart_device::uart_init,
kobject::KObject,
kset::KSet,
},
kdebug, kinfo,
syscall::SystemError,
};
pub fn device_init() -> Result<(), SystemError> {
uart_init()?;
kinfo!("device init success");
return Ok(());
}
pub fn devices_init() -> Result<(), SystemError> {
// 创建 `/sys/devices` 目录
{
@ -73,6 +63,6 @@ pub fn devices_init() -> Result<(), SystemError> {
}
kinfo!("devices init success");
device_init()?;
return Ok(());
}

View File

@ -1,6 +1,6 @@
use alloc::{
string::{String, ToString},
sync::Arc,
sync::{Arc, Weak},
};
use intertrait::cast::CastArc;
@ -8,10 +8,12 @@ use crate::{
driver::{
acpi::glue::acpi_device_notify,
base::map::{LockedDevsMap, LockedKObjMap},
Driver,
},
filesystem::{
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
sysfs::{
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
SysFSOpsSupport,
},
vfs::syscall::ModeType,
},
syscall::SystemError,
@ -19,12 +21,14 @@ use crate::{
use core::fmt::Debug;
use core::intrinsics::unlikely;
use self::bus::{bus_add_device, bus_probe_device, Bus};
use self::{
bus::{bus_add_device, bus_probe_device, Bus},
driver::Driver,
};
use super::{
kobject::{KObjType, KObject, KObjectManager},
kobject::{KObjType, KObject, KObjectManager, KObjectState},
kset::KSet,
platform::CompatibleTable,
swnode::software_node_notify,
};
@ -87,7 +91,7 @@ pub(self) fn sys_dev_char_kset() -> Arc<KSet> {
/// ## 注意
///
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Device>
/// 因此所有的实现了Device trait的结构体都应该在结构体上方标注`#[[sync] Device]`
/// 因此所有的实现了Device trait的结构体都应该在结构体上方标注`#[cast_to([sync] Device)]`
///
/// 否则在释放设备资源的时候会由于无法转换为Arc<dyn Device>而导致资源泄露并且release回调函数也不会被调用。
pub trait Device: KObject {
@ -117,13 +121,39 @@ pub trait Device: KObject {
return None;
}
/// 设置当前设备所属的总线
///
/// 一定要传入Arc因为bus的subsysprivate里面存储的是Device的Weak指针
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
/// 返回已经与当前设备匹配好的驱动程序
fn driver(&self) -> Option<Arc<dyn Driver>>;
fn set_driver(&self, driver: Option<Arc<dyn Driver>>);
fn set_driver(&self, driver: Option<Weak<dyn Driver>>);
/// 当前设备是否已经挂掉了
fn is_dead(&self) -> bool;
/// 当前设备是否处于可以被匹配的状态
///
/// The device has matched with a driver at least once or it is in
/// a bus (like AMBA) which can't check for matching drivers until
/// other devices probe successfully.
fn can_match(&self) -> bool;
fn set_can_match(&self, can_match: bool);
/// The hardware state of this device has been synced to match
/// the software state of this device by calling the driver/bus
/// sync_state() callback.
fn state_synced(&self) -> bool;
}
impl dyn Device {
#[inline(always)]
pub fn is_registered(&self) -> bool {
self.kobj_state().contains(KObjectState::IN_SYSFS)
}
}
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
@ -131,24 +161,13 @@ pub trait Device: KObject {
#[derive(Debug, Clone)]
pub struct DevicePrivateData {
id_table: IdTable,
resource: Option<DeviceResource>,
compatible_table: CompatibleTable,
state: DeviceState,
}
#[allow(dead_code)]
impl DevicePrivateData {
pub fn new(
id_table: IdTable,
resource: Option<DeviceResource>,
compatible_table: CompatibleTable,
state: DeviceState,
) -> Self {
Self {
id_table,
resource,
compatible_table,
state,
}
pub fn new(id_table: IdTable, state: DeviceState) -> Self {
Self { id_table, state }
}
pub fn id_table(&self) -> &IdTable {
@ -159,31 +178,11 @@ impl DevicePrivateData {
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 {
@ -225,6 +224,8 @@ impl DeviceNumber {
self.0 & 0xff
}
#[inline]
#[allow(dead_code)]
pub fn from_major_minor(major: usize, minor: usize) -> usize {
((major & 0xffffff) << 8) | (minor & 0xff)
}
@ -287,7 +288,7 @@ impl Default for IdTable {
// 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉
/// @brief: 设备当前状态
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum DeviceState {
NotInitialized = 0,
Initialized = 1,
@ -465,6 +466,11 @@ impl DeviceManager {
todo!()
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#542
fn remove(&self, _dev: &Arc<dyn Device>) {
todo!("DeviceManager::remove")
}
/// @brief: 获取设备
/// @parameter id_table: 设备标识符,用于唯一标识该设备
/// @return: 设备实例
@ -521,10 +527,8 @@ impl DeviceManager {
dev: &Arc<dyn Device>,
attr_groups: &'static [&dyn AttributeGroup],
) -> Result<(), SystemError> {
let dev = dev.clone();
let binding = dev.arc_any();
let kobj: &Arc<dyn KObject> = binding.downcast_ref().unwrap();
return sysfs_instance().create_groups(kobj, attr_groups);
let kobj = dev.clone() as Arc<dyn KObject>;
return sysfs_instance().create_groups(&kobj, attr_groups);
}
/// 为设备在sysfs中创建属性文件
@ -567,15 +571,15 @@ impl DeviceManager {
let target_kobj = self.device_to_dev_kobj(dev);
let name = dev.id_table().name();
let current_kobj = dev.clone() as Arc<dyn KObject>;
return sysfs_instance().create_link(&current_kobj, &target_kobj, name);
return sysfs_instance().create_link(Some(&current_kobj), &target_kobj, name);
}
/// Delete symlink for device in `/sys/dev` or `/sys/class/<class_name>`
#[allow(dead_code)]
fn remove_sys_dev_entry(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
fn remove_sys_dev_entry(&self, dev: &Arc<dyn Device>) {
let kobj = self.device_to_dev_kobj(dev);
let name = dev.id_table().name();
return sysfs_instance().remove_link(&kobj, name);
sysfs_instance().remove_link(&kobj, name);
}
/// device_to_dev_kobj - select a /sys/dev/ directory for the device
@ -595,6 +599,28 @@ impl DeviceManager {
pub fn device_links_force_bind(&self, _dev: &Arc<dyn Device>) {
todo!("device_links_force_bind")
}
/// 把device对象的一些结构进行默认初始化
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_initialize#2976
pub fn device_default_initialize(&self, dev: &Arc<dyn Device>) {
dev.set_kset(Some(sys_devices_kset()));
return;
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=29885&fi=1100#1100
pub fn device_driver_attach(
&self,
_driver: &Arc<dyn Driver>,
_dev: &Arc<dyn Device>,
) -> Result<(), SystemError> {
todo!("device_driver_attach")
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=35401&fi=1313#1313
pub fn device_driver_detach(&self, _dev: &Arc<dyn Device>) {
todo!("device_driver_detach")
}
}
/// @brief: 设备注册
@ -633,7 +659,7 @@ impl Attribute for DeviceAttrDev {
"dev"
}
fn show(&self, kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
kerror!(
"Intertrait casting not implemented for kobj: {}",
@ -642,7 +668,10 @@ impl Attribute for DeviceAttrDev {
SystemError::EOPNOTSUPP_OR_ENOTSUP
})?;
return Ok(dev.id_table().device_number().into());
let device_number = dev.id_table().device_number();
let s = format!("{}:{}\n", device_number.major(), device_number.minor());
return sysfs_emit_str(buf, &s);
}
fn support(&self) -> SysFSOpsSupport {

View File

@ -1,4 +1,4 @@
use crate::syscall::SystemError;
use crate::{driver::tty::tty_device::tty_init, syscall::SystemError};
use super::{
class::classes_init,
@ -15,5 +15,15 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
firmware_init()?;
hypervisor_init()?;
platform_bus_init()?;
// 至此,已完成设备驱动模型的初始化
// 接下来,初始化设备
actual_device_init()?;
return Ok(());
}
fn actual_device_init() -> Result<(), SystemError> {
tty_init()?;
return Ok(());
}

View File

@ -43,6 +43,8 @@ pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>);
fn name(&self) -> String;
fn set_name(&self, name: String);
@ -70,7 +72,7 @@ impl DowncastArc for dyn KObject {
}
}
pub trait KObjType: Debug {
pub trait KObjType: Debug + Send + Sync {
fn release(&self, _kobj: Arc<dyn KObject>) {}
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
@ -91,7 +93,8 @@ bitflags! {
pub struct LockedKObjectState(RwLock<KObjectState>);
impl LockedKObjectState {
pub const fn new(state: KObjectState) -> LockedKObjectState {
pub fn new(state: Option<KObjectState>) -> LockedKObjectState {
let state = state.unwrap_or(KObjectState::empty());
LockedKObjectState(RwLock::new(state))
}
}

View File

@ -52,7 +52,7 @@ impl KSet {
let r = Self {
kobjects: RwLock::new(Vec::new()),
inner: RwLock::new(InnerKSet::new(name)),
kobj_state: LockedKObjectState::new(KObjectState::empty()),
kobj_state: LockedKObjectState::new(None),
parent_data: RwLock::new(KSetParentData::new(None, None)),
self_ref: Weak::default(),
};
@ -167,6 +167,10 @@ impl KObject for KSet {
Some(&KSetKObjType)
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!("KSet::set_kobj_type")
}
fn kset(&self) -> Option<Arc<KSet>> {
self.parent_data.read().kset.clone()
}

View File

@ -74,8 +74,6 @@ pub fn platform_bus_init() -> Result<(), SystemError> {
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
DevicePrivateData::new(
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
None,
CompatibleTable::new(vec!["platform"]),
BusState::NotInitialized.into(),
),
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),

View File

@ -2,31 +2,64 @@ use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
};
use ida::IdAllocator;
use crate::{
driver::{
base::{
device::{
bus::{Bus, BusState},
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
driver::base::{
device::{
bus::{Bus, BusState},
device_manager,
driver::Driver,
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
},
Driver,
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
},
filesystem::kernfs::KernFSInode,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::SpinLock,
},
syscall::SystemError,
};
use super::{super::device::DeviceState, CompatibleTable};
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
/// 平台设备id分配器
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(i32::MAX as usize);
#[inline(always)]
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
&PlatformDeviceManager
}
/// 没有平台设备id
pub const PLATFORM_DEVID_NONE: i32 = -1;
/// 请求自动分配这个平台设备id
pub const PLATFORM_DEVID_AUTO: i32 = -2;
/// @brief: 实现该trait的设备实例应挂载在platform总线上
/// 同时应该实现Device trait
///
/// ## 注意
///
/// 应当在所有实现这个trait的结构体上方添加 `#[cast_to([sync] PlatformDriver)]`
/// 否则运行时将报错“该对象不是PlatformDriver”
pub trait PlatformDevice: Device {
fn pdev_name(&self) -> &str;
/// 返回平台设备id以及这个id是否是自动生成的
///
/// 请注意如果当前设备还没有id应该返回
/// (PLATFORM_DEVID_NONE, false)
fn pdev_id(&self) -> (i32, bool) {
(PLATFORM_DEVID_NONE, false)
}
/// 设置平台设备id
fn set_pdev_id(&self, id: i32);
/// 设置id是否为自动分配
fn set_pdev_id_auto(&self, id_auto: bool);
fn compatible_table(&self) -> CompatibleTable;
/// @brief: 判断设备是否初始化
/// @parameter: None
@ -39,6 +72,54 @@ pub trait PlatformDevice: Device {
fn set_state(&self, set_state: DeviceState);
}
#[derive(Debug)]
pub struct PlatformDeviceManager;
impl PlatformDeviceManager {
/// platform_device_add - add a platform device to device hierarchy
pub fn device_add(&self, pdev: Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
if pdev.parent().is_none() {
pdev.set_parent(Some(Arc::downgrade(
&(platform_bus_device() as Arc<dyn KObject>),
)));
}
pdev.set_bus(Some(platform_bus() as Arc<dyn Bus>));
let id = pdev.pdev_id().0;
match id {
PLATFORM_DEVID_NONE => {
pdev.set_name(format!("{}", pdev.pdev_name()));
}
PLATFORM_DEVID_AUTO => {
let id = PLATFORM_DEVID_IDA.alloc().ok_or(SystemError::EOVERFLOW)?;
pdev.set_pdev_id(id as i32);
pdev.set_pdev_id_auto(true);
pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0));
}
_ => {
pdev.set_name(format!("{}.{}", pdev.pdev_name(), id));
}
}
// todo: 插入资源: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=platform_device_add#691
let r = device_manager().add_device(pdev.clone() as Arc<dyn Device>);
if r.is_ok() {
pdev.set_state(DeviceState::Initialized);
return Ok(()); // success
} else {
// failed
let pdevid = pdev.pdev_id();
if pdevid.1 {
PLATFORM_DEVID_IDA.free(pdevid.0 as usize);
pdev.set_pdev_id(PLATFORM_DEVID_AUTO);
}
return r;
}
}
}
#[derive(Debug)]
#[cast_to([sync] Device)]
pub struct PlatformBusDevice {
@ -56,7 +137,7 @@ impl PlatformBusDevice {
) -> Arc<PlatformBusDevice> {
return Arc::new(PlatformBusDevice {
inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)),
kobj_state: LockedKObjectState::new(KObjectState::empty()),
kobj_state: LockedKObjectState::new(None),
});
}
@ -101,18 +182,8 @@ impl PlatformBusDevice {
let state = self.inner.lock().state;
return state;
}
// /// @brief:
// /// @parameter: None
// /// @return: 总线状态
// #[inline]
// #[allow(dead_code)]
// fn set_driver(&self, driver: Option<Arc<LockedPlatformBusDriver>>) {
// self.0.lock().driver = driver;
// }
}
/// @brief: platform总线
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct InnerPlatformBusDevice {
@ -125,14 +196,10 @@ pub struct InnerPlatformBusDevice {
/// 当前设备挂载到的总线
bus: Option<Arc<dyn Bus>>,
/// 当前设备已经匹配的驱动
driver: Option<Arc<dyn Driver>>,
driver: Option<Weak<dyn Driver>>,
}
/// @brief: platform方法集
impl InnerPlatformBusDevice {
/// @brief: 创建一个platform总线实例
/// @parameter: None
/// @return: platform总线实例
pub fn new(data: DevicePrivateData, parent: Option<Weak<dyn KObject>>) -> Self {
Self {
data,
@ -167,6 +234,10 @@ impl KObject for PlatformBusDevice {
None
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!("platform_bus_device::set_kobj_type")
}
fn kset(&self) -> Option<Arc<KSet>> {
None
}
@ -218,8 +289,12 @@ impl Device for PlatformBusDevice {
self.inner.lock().bus.clone()
}
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
self.inner.lock().bus = bus;
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
self.inner.lock().driver.clone()
self.inner.lock().driver.clone()?.upgrade()
}
#[inline]
@ -227,7 +302,19 @@ impl Device for PlatformBusDevice {
false
}
fn set_driver(&self, driver: Option<Arc<dyn Driver>>) {
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner.lock().driver = driver;
}
fn can_match(&self) -> bool {
todo!()
}
fn set_can_match(&self, _can_match: bool) {
todo!()
}
fn state_synced(&self) -> bool {
todo!()
}
}

View File

@ -1,21 +1,54 @@
use crate::driver::{base::device::DevicePrivateData, Driver};
use alloc::sync::Arc;
use super::{super::device::driver::DriverError, CompatibleTable};
use crate::{
driver::base::device::{
bus::Bus,
driver::{driver_manager, Driver},
},
syscall::SystemError,
};
use super::{platform_bus, platform_device::PlatformDevice};
lazy_static! {
static ref PLATFORM_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["platform"]);
}
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上
/// 同时应该实现Driver trait
///
/// ## 注意
///
/// 应当在所有实现这个trait的结构体上方添加 `#[cast_to([sync] PlatformDriver)]`
/// 否则运行时将报错“该对象不是PlatformDriver”
pub trait PlatformDriver: Driver {
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);
}
/// 检测设备是否能绑定到这个驱动
///
/// 如果能则把设备的driver指向这个驱动。
/// 请注意这个函数不应该把driver加入驱动的devices列表相关工作会在外部的函数里面处理。
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
fn remove(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
fn shutdown(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
fn suspend(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
fn resume(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
}
#[inline(always)]
pub fn platform_driver_manager() -> &'static PlatformDriverManager {
&PlatformDriverManager
}
#[derive(Debug)]
pub struct PlatformDriverManager;
impl PlatformDriverManager {
/// 注册平台设备驱动
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=__platform_driver_register#861
pub fn register(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), SystemError> {
driver.set_bus(Some(platform_bus() as Arc<dyn Bus>));
return driver_manager().register(driver as Arc<dyn Driver>);
}
/// 卸载平台设备驱动
#[allow(dead_code)]
pub fn unregister(&self, driver: &Arc<dyn PlatformDriver>) {
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
}
}

View File

@ -2,15 +2,26 @@ use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
};
use intertrait::cast::CastArc;
use crate::{
driver::base::{device::bus::Bus, kobject::KObject, subsys::SubSysPrivate},
driver::{
acpi::acpi_manager,
base::{
device::{bus::Bus, driver::Driver, Device},
kobject::KObject,
subsys::SubSysPrivate,
},
},
filesystem::{
sysfs::{Attribute, AttributeGroup},
vfs::syscall::ModeType,
},
syscall::SystemError,
};
use super::{platform_device::PlatformDevice, platform_driver::PlatformDriver};
#[derive(Debug)]
pub struct PlatformBus {
private: SubSysPrivate,
@ -44,6 +55,92 @@ impl Bus for PlatformBus {
fn subsystem(&self) -> &SubSysPrivate {
return &self.private;
}
fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
let drv = device.driver().ok_or(SystemError::EINVAL)?;
let pdrv = drv.cast::<dyn PlatformDriver>().map_err(|_|{
kerror!("PlatformBus::probe() failed: device.driver() is not a PlatformDriver. Device: '{:?}'", device.name());
SystemError::EINVAL
})?;
let pdev = device.clone().cast::<dyn PlatformDevice>().map_err(|_| {
kerror!(
"PlatformBus::probe() failed: device is not a PlatformDevice. Device: '{:?}'",
device.name()
);
SystemError::EINVAL
})?;
return pdrv.probe(&pdev);
}
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!()
}
fn sync_state(&self, _device: &Arc<dyn Device>) {
todo!()
}
fn shutdown(&self, _device: &Arc<dyn Device>) {
todo!()
}
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!()
}
///
/// match platform device to platform driver.
///
/// ## 参数
///
/// * `device` - platform device
/// * `driver` - platform driver
///
/// ## 返回
///
/// - `Ok(true)` - 匹配成功
/// - `Ok(false)` - 匹配失败
/// - `Err(_)` - 由于内部错误导致匹配失败
///
/// Platform device IDs are assumed to be encoded like this:
/// "<name><instance>", where <name> is a short description of the type of
/// device, like "pci" or "floppy", and <instance> is the enumerated
/// instance of the device, like '0' or '42'. Driver IDs are simply
/// "<name>". So, extract the <name> from the platform_device structure,
/// and compare it against the name of the driver. Return whether they match
/// or not.
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c#1331
///
///
fn match_device(
&self,
device: &Arc<dyn Device>,
driver: &Arc<dyn Driver>,
) -> Result<bool, SystemError> {
// 尝试从 ACPI 中匹配
if let Ok(x) = acpi_manager().driver_match_device(driver, device) {
if x {
return Ok(true);
}
}
// 尝试从 ID table 中匹配
if let Some(drv_id_table) = driver.id_table() {
let pdev = device
.clone()
.cast::<dyn PlatformDevice>()
.map_err(|_| SystemError::EINVAL)?;
if drv_id_table.name().eq(&pdev.name()) {
return Ok(true);
}
}
// 尝试根据设备名称匹配
return Ok(device.name().eq(&driver.name()));
}
}
#[derive(Debug)]

View File

@ -10,14 +10,18 @@ use alloc::{
};
use crate::{
driver::Driver,
libs::{notifier::AtomicNotifierChain, rwlock::RwLock, spinlock::SpinLock},
libs::{
notifier::AtomicNotifierChain,
rwlock::{RwLock, RwLockReadGuard},
spinlock::SpinLock,
},
syscall::SystemError,
};
use super::{
device::{
bus::{Bus, BusNotifyEvent},
driver::Driver,
Device,
},
kset::KSet,
@ -90,12 +94,12 @@ impl SubSysPrivate {
*self.bus.lock() = bus;
}
pub fn devices(&self) -> &RwLock<Vec<Weak<dyn Device>>> {
return &self.devices;
pub fn devices(&self) -> RwLockReadGuard<Vec<Weak<dyn Device>>> {
return self.devices.read();
}
pub fn drivers(&self) -> &RwLock<Vec<Weak<dyn Driver>>> {
return &self.drivers;
pub fn drivers(&self) -> RwLockReadGuard<Vec<Weak<dyn Driver>>> {
return self.drivers.read();
}
pub fn drivers_autoprobe(&self) -> bool {
@ -136,6 +140,45 @@ impl SubSysPrivate {
pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] {
return self.interfaces;
}
pub fn add_driver_to_vec(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
let mut drivers = self.drivers.write();
let driver_weak = Arc::downgrade(driver);
if drivers.iter().any(|d| d.ptr_eq(&driver_weak)) {
return Err(SystemError::EEXIST);
}
drivers.push(driver_weak);
return Ok(());
}
pub fn remove_driver_from_vec(&self, driver: &Arc<dyn Driver>) {
let mut drivers = self.drivers.write();
let driver_weak = Arc::downgrade(driver);
let index = drivers.iter().position(|d| d.ptr_eq(&driver_weak));
if let Some(index) = index {
drivers.remove(index);
}
}
pub fn add_device_to_vec(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
let mut devices = self.devices.write();
let device_weak = Arc::downgrade(device);
if devices.iter().any(|d| d.ptr_eq(&device_weak)) {
return Err(SystemError::EEXIST);
}
devices.push(device_weak);
return Ok(());
}
#[allow(dead_code)]
pub fn remove_device_from_vec(&self, device: &Arc<dyn Device>) {
let mut devices = self.devices.write();
let device_weak = Arc::downgrade(device);
let index = devices.iter().position(|d| d.ptr_eq(&device_weak));
if let Some(index) = index {
devices.remove(index);
}
}
}
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device.h#63

View File

@ -3,11 +3,12 @@ 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::bus::Bus;
use crate::driver::base::device::driver::Driver;
use crate::driver::base::device::{Device, DeviceType, IdTable};
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
use crate::driver::base::kset::KSet;
use crate::driver::disk::ahci::HBA_PxIS_TFES;
use crate::driver::Driver;
use crate::filesystem::kernfs::KernFSInode;
use crate::filesystem::mbr::MbrDiskPartionTable;
use crate::include::bindings::bindings::verify_area;
@ -489,6 +490,10 @@ impl KObject for LockedAhciDisk {
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
todo!()
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!()
}
}
impl Device for LockedAhciDisk {
@ -504,6 +509,10 @@ impl Device for LockedAhciDisk {
todo!("LockedAhciDisk::bus()")
}
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
todo!("LockedAhciDisk::set_bus()")
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
todo!("LockedAhciDisk::driver()")
}
@ -512,9 +521,21 @@ impl Device for LockedAhciDisk {
false
}
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
todo!("LockedAhciDisk::set_driver()")
}
fn can_match(&self) -> bool {
todo!()
}
fn set_can_match(&self, _can_match: bool) {
todo!()
}
fn state_synced(&self) -> bool {
todo!()
}
}
impl BlockDevice for LockedAhciDisk {

View File

@ -6,7 +6,6 @@
#include <common/printk.h>
#include <driver/acpi/acpi.h>
#include <exception/gate.h>
#include <driver/uart/uart.h>
#include <exception/softirq.h>
#include <process/process.h>
#include <sched/sched.h>

View File

@ -6,50 +6,5 @@ pub mod net;
pub mod pci;
pub mod timers;
pub mod tty;
pub mod uart;
pub mod video;
pub mod virtio;
use core::fmt::Debug;
use alloc::sync::Arc;
use self::base::{
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
kobject::KObject,
platform::CompatibleTable,
};
pub trait Driver: Sync + Send + Debug + KObject {
/// @brief: 获取驱动匹配表
/// @parameter: None
/// @return: 驱动匹配表
/// 对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表
fn compatible_table(&self) -> CompatibleTable {
//TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除
return CompatibleTable::new(vec!["unknown"]);
}
/// @brief 添加可支持的设备
/// @parameter: device 新增的匹配项
fn append_compatible_table(&self, _device: &CompatibleTable) -> Result<(), DriverError> {
Err(DriverError::UnsupportedOperation)
}
/// @brief 探测设备
/// @param data 设备初始拥有的基本信息
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError>;
/// @brief 加载设备,包括检查资源可用性,和注册到相应的管理器中。
/// @param data 设备初始拥有的信息
/// @param resource 设备可能申请的资源(或者像伪设备不需要就为None)
fn load(
&self,
data: DevicePrivateData,
resource: Option<DeviceResource>,
) -> Result<Arc<dyn Device>, DriverError>;
/// @brief: 获取驱动标识符
/// @parameter: None
/// @return: 该驱动驱动唯一标识符
fn id_table(&self) -> IdTable;
}

View File

@ -6,7 +6,7 @@ use smoltcp::{
use crate::{libs::spinlock::SpinLock, syscall::SystemError};
use super::Driver;
use super::base::device::driver::Driver;
pub mod virtio_net;

View File

@ -11,11 +11,10 @@ use virtio_drivers::{device::net::VirtIONet, transport::Transport};
use crate::{
driver::{
base::{
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
kobject::KObject,
device::{bus::Bus, driver::Driver, Device, IdTable},
kobject::{KObjType, KObject, KObjectState},
},
virtio::virtio_impl::HalImpl,
Driver,
},
kerror, kinfo,
libs::spinlock::SpinLock,
@ -245,19 +244,27 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
}
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
fn id_table(&self) -> Option<IdTable> {
todo!()
}
fn load(
&self,
_data: DevicePrivateData,
_resource: Option<DeviceResource>,
) -> Result<Arc<dyn Device>, DriverError> {
fn add_device(&self, _device: Arc<dyn Device>) {
todo!()
}
fn id_table(&self) -> IdTable {
fn delete_device(&self, _device: &Arc<dyn Device>) {
todo!()
}
fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
todo!()
}
fn bus(&self) -> Option<Arc<dyn Bus>> {
todo!()
}
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
todo!()
}
}
@ -372,7 +379,11 @@ impl<T: Transport + 'static> KObject for VirtioInterface<T> {
todo!()
}
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
fn set_kobj_state(&self, _state: KObjectState) {
todo!()
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!()
}
}

View File

@ -0,0 +1,8 @@
use crate::syscall::SystemError;
use super::serial::serial_early_init;
pub fn tty_early_init() -> Result<(), SystemError> {
serial_early_init()?;
return Ok(());
}

View File

@ -9,7 +9,10 @@ use thingbuf::mpsc::{
use crate::libs::rwlock::RwLock;
pub mod init;
pub mod serial;
pub mod tty_device;
pub mod tty_driver;
bitflags! {
pub struct TtyCoreState: u32{

View File

@ -0,0 +1,71 @@
use core::{fmt::Debug, sync::atomic::AtomicU32};
use alloc::sync::Arc;
use crate::{driver::base::device::DeviceNumber, mm::VirtAddr, syscall::SystemError};
use self::serial8250::serial8250_manager;
use super::tty_driver::TtyDriver;
pub mod serial8250;
pub trait UartDriver: Debug + Send + Sync + TtyDriver {
fn device_number(&self) -> DeviceNumber;
/// 获取最大的设备数量
fn max_devs_num(&self) -> i32;
// todo: 获取指向console的指针在我们系统里面将来可能是改进后的Textui Window
}
/// 串口端口应当实现的trait
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/serial_core.h#428
pub trait UartPort {
fn iobase(&self) -> Option<usize> {
None
}
fn membase(&self) -> Option<VirtAddr> {
None
}
fn serial_in(&self, offset: u32) -> u32;
fn serial_out(&self, offset: u32, value: u32);
fn divisor(&self, baud: BaudRate) -> (u32, DivisorFraction);
fn set_divisor(&self, baud: BaudRate) -> Result<(), SystemError>;
fn baud_rate(&self) -> Option<BaudRate>;
fn startup(&self) -> Result<(), SystemError>;
fn shutdown(&self);
fn handle_irq(&self) -> Result<(), SystemError>;
}
int_like!(BaudRate, AtomicBaudRate, u32, AtomicU32);
int_like!(DivisorFraction, u32);
#[inline(always)]
#[allow(dead_code)]
pub(super) fn uart_manager() -> &'static UartManager {
&UartManager
}
#[derive(Debug)]
pub(super) struct UartManager;
impl UartManager {
/// todo: 把uart设备注册到tty层
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720
pub fn register_driver(&self, _driver: &Arc<dyn UartDriver>) -> Result<(), SystemError> {
return Ok(());
}
}
pub fn serial_early_init() -> Result<(), SystemError> {
serial8250_manager().early_init()?;
return Ok(());
}
pub(super) fn serial_init() -> Result<(), SystemError> {
serial8250_manager().init()?;
return Ok(());
}

View File

@ -0,0 +1,543 @@
use core::{
any::Any,
sync::atomic::{AtomicBool, AtomicI32, Ordering},
};
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};
use crate::{
driver::{
base::{
device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceKObjType, DeviceNumber,
DeviceState, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
platform::{
platform_device::{platform_device_manager, PlatformDevice},
platform_driver::{platform_driver_manager, PlatformDriver},
},
},
tty::{
tty_device::TtyDevice,
tty_driver::{TtyDriver, TtyDriverMetadata, TtyDriverOperations},
},
},
filesystem::kernfs::KernFSInode,
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
syscall::SystemError,
};
use self::serial8250_pio::{send_to_serial8250_pio_com1, serial8250_pio_port_early_init};
use super::{uart_manager, UartDriver, UartPort};
mod serial8250_pio;
static mut SERIAL8250_ISA_DEVICES: Option<Arc<Serial8250ISADevices>> = None;
static mut SERIAL8250_ISA_DRIVER: Option<Arc<Serial8250ISADriver>> = None;
#[inline(always)]
#[allow(dead_code)]
fn serial8250_isa_devices() -> &'static Arc<Serial8250ISADevices> {
unsafe { SERIAL8250_ISA_DEVICES.as_ref().unwrap() }
}
#[inline(always)]
#[allow(dead_code)]
fn serial8250_isa_driver() -> &'static Arc<Serial8250ISADriver> {
unsafe { SERIAL8250_ISA_DRIVER.as_ref().unwrap() }
}
#[inline(always)]
pub(super) fn serial8250_manager() -> &'static Serial8250Manager {
&Serial8250Manager
}
#[derive(Debug)]
pub(super) struct Serial8250Manager;
impl Serial8250Manager {
/// 初始化串口设备(在内存管理初始化之前)
pub fn early_init(&self) -> Result<(), SystemError> {
serial8250_pio_port_early_init()?;
return Ok(());
}
/// 初始化serial8250设备、驱动
///
/// 应当在设备驱动模型初始化之后调用这里
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#1169
pub fn init(&self) -> Result<(), SystemError> {
// 初始化serial8250 isa设备
let serial8250_isa_dev = Serial8250ISADevices::new();
unsafe {
SERIAL8250_ISA_DEVICES = Some(serial8250_isa_dev.clone());
}
let serial8250_isa_driver = Serial8250ISADriver::new();
unsafe {
SERIAL8250_ISA_DRIVER = Some(serial8250_isa_driver.clone());
}
// todo: 把端口绑定到isa_dev、 isa_driver上
self.register_ports(&serial8250_isa_driver, &serial8250_isa_dev);
// todo: 把驱动注册到uart层、tty层
uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc<dyn UartDriver>))?;
// 注册isa设备到platform总线
platform_device_manager()
.device_add(serial8250_isa_dev.clone() as Arc<dyn PlatformDevice>)
.map_err(|e| {
unsafe {
SERIAL8250_ISA_DEVICES = None;
}
return e;
})?;
// todo: 把驱动注册到platform总线
platform_driver_manager()
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
return Ok(());
}
/// 把uart端口与uart driver、uart device绑定
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#553
fn register_ports(
&self,
uart_driver: &Arc<Serial8250ISADriver>,
devs: &Arc<Serial8250ISADevices>,
) {
self.bind_pio_ports(uart_driver, devs);
}
/// 把uart端口与uart driver绑定
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_add_one_port#3048
pub(self) fn uart_add_one_port(
&self,
_uart_driver: &Arc<Serial8250ISADriver>,
_port: &dyn UartPort,
) -> Result<(), SystemError> {
return Ok(());
// todo!("Serial8250Manager::uart_add_one_port")
}
}
/// 所有的8250串口设备都应该实现的trait
trait Serial8250Port: UartPort {
fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
None
}
fn set_device(&self, device: Option<&Arc<Serial8250ISADevices>>);
}
#[derive(Debug)]
#[cast_to([sync] Device, PlatformDevice)]
struct Serial8250ISADevices {
/// 设备id是否自动分配
id_auto: AtomicBool,
/// 平台设备id
id: AtomicI32,
inner: RwLock<InnerSerial8250ISADevices>,
name: &'static str,
kobj_state: LockedKObjectState,
}
impl Serial8250ISADevices {
pub fn new() -> Arc<Self> {
let r = Arc::new(Self {
id_auto: AtomicBool::new(false),
id: AtomicI32::new(Serial8250PlatformDeviceID::Legacy as i32),
inner: RwLock::new(InnerSerial8250ISADevices::new()),
name: "serial8250",
kobj_state: LockedKObjectState::new(None),
});
device_manager().device_default_initialize(&(r.clone() as Arc<dyn Device>));
return r;
}
}
impl PlatformDevice for Serial8250ISADevices {
fn compatible_table(&self) -> crate::driver::base::platform::CompatibleTable {
unimplemented!()
}
fn pdev_id(&self) -> (i32, bool) {
return (
self.id.load(Ordering::SeqCst),
self.id_auto.load(Ordering::SeqCst),
);
}
fn set_pdev_id(&self, id: i32) {
self.id.store(id, Ordering::SeqCst);
}
fn set_pdev_id_auto(&self, id_auto: bool) {
self.id_auto.store(id_auto, Ordering::SeqCst);
}
fn pdev_name(&self) -> &str {
return self.name;
}
fn is_initialized(&self) -> bool {
return self.inner.read().device_state == DeviceState::Initialized;
}
fn set_state(&self, set_state: DeviceState) {
self.inner.write().device_state = set_state;
}
}
impl Device for Serial8250ISADevices {
fn is_dead(&self) -> bool {
false
}
fn bus(&self) -> Option<Arc<dyn Bus>> {
self.inner.read().bus.clone()
}
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
self.inner.write().bus = bus;
}
fn dev_type(&self) -> DeviceType {
DeviceType::Serial
}
fn id_table(&self) -> IdTable {
return IdTable::new(self.name.to_string(), DeviceNumber::new(0));
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
self.inner.read().driver.clone()?.upgrade()
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner.write().driver = driver;
}
fn can_match(&self) -> bool {
self.inner.read().can_match
}
fn set_can_match(&self, can_match: bool) {
self.inner.write().can_match = can_match;
}
fn state_synced(&self) -> bool {
true
}
}
impl KObject for Serial8250ISADevices {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner.write().inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner.read().inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner.read().parent_kobj.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner.write().parent_kobj = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner.read().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner.write().kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
Some(&DeviceKObjType)
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!()
}
fn name(&self) -> String {
self.name.to_string()
}
fn set_name(&self, _name: String) {}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}
#[derive(Debug)]
struct InnerSerial8250ISADevices {
/// 当前设备所述的kset
kset: Option<Arc<KSet>>,
parent_kobj: Option<Weak<dyn KObject>>,
/// 当前设备所述的总线
bus: Option<Arc<dyn Bus>>,
inode: Option<Arc<KernFSInode>>,
driver: Option<Weak<dyn Driver>>,
device_state: DeviceState,
can_match: bool,
}
impl InnerSerial8250ISADevices {
fn new() -> Self {
Self {
kset: None,
parent_kobj: None,
bus: None,
inode: None,
driver: None,
device_state: DeviceState::NotInitialized,
can_match: false,
}
}
}
/// Serial 8250平台设备的id
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/serial_8250.h?fi=PLAT8250_DEV_LEGACY#49
#[derive(Debug)]
#[repr(i32)]
enum Serial8250PlatformDeviceID {
Legacy = -1,
}
#[derive(Debug)]
struct InnerSerial8250ISADriver {
bus: Option<Arc<dyn Bus>>,
kobj_type: Option<&'static dyn KObjType>,
kset: Option<Arc<KSet>>,
parent_kobj: Option<Weak<dyn KObject>>,
kern_inode: Option<Arc<KernFSInode>>,
devices: Vec<Arc<dyn Device>>,
}
impl InnerSerial8250ISADriver {
fn new() -> Self {
Self {
bus: None,
kobj_type: None,
kset: None,
parent_kobj: None,
kern_inode: None,
devices: Vec::new(),
}
}
}
#[derive(Debug)]
#[cast_to([sync] Driver, PlatformDriver)]
struct Serial8250ISADriver {
inner: RwLock<InnerSerial8250ISADriver>,
name: &'static str,
kobj_state: LockedKObjectState,
self_ref: Weak<Self>,
}
impl Serial8250ISADriver {
pub fn new() -> Arc<Self> {
let r = Arc::new(Self {
inner: RwLock::new(InnerSerial8250ISADriver::new()),
name: "serial8250",
kobj_state: LockedKObjectState::new(None),
self_ref: Weak::default(),
});
unsafe {
let p = r.as_ref() as *const Self as *mut Self;
(*p).self_ref = Arc::downgrade(&r);
}
return r;
}
}
impl TtyDriver for Serial8250ISADriver {
fn driver_name(&self) -> &str {
self.name
}
fn dev_name(&self) -> &str {
todo!()
}
fn metadata(&self) -> &TtyDriverMetadata {
todo!()
}
fn other(&self) -> Option<&Arc<dyn TtyDriver>> {
todo!()
}
fn ttys(&self) -> &[Arc<TtyDevice>] {
todo!()
}
fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> {
None
}
}
impl UartDriver for Serial8250ISADriver {
fn device_number(&self) -> DeviceNumber {
todo!()
}
fn max_devs_num(&self) -> i32 {
todo!()
}
}
impl PlatformDriver for Serial8250ISADriver {
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
let isa_dev = device
.clone()
.arc_any()
.downcast::<Serial8250ISADevices>()
.map_err(|_| {
kerror!("Serial8250ISADriver::probe: device is not a Serial8250ISADevices");
SystemError::EINVAL
})?;
isa_dev.set_driver(Some(self.self_ref.clone()));
return Ok(());
}
fn remove(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!()
}
fn shutdown(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!()
}
fn suspend(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!()
}
fn resume(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!()
}
}
impl Driver for Serial8250ISADriver {
fn id_table(&self) -> Option<IdTable> {
None
}
fn devices(&self) -> Vec<Arc<dyn Device>> {
self.inner.read().devices.clone()
}
fn add_device(&self, device: Arc<dyn Device>) {
self.inner.write().devices.push(device);
}
fn delete_device(&self, device: &Arc<dyn Device>) {
let mut inner = self.inner.write();
inner.devices.drain_filter(|d| Arc::ptr_eq(d, device));
}
fn bus(&self) -> Option<Arc<dyn Bus>> {
self.inner.read().bus.clone()
}
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
self.inner.write().bus = bus;
}
}
impl KObject for Serial8250ISADriver {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner.write().kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner.read().kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner.read().parent_kobj.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner.write().parent_kobj = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner.read().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner.write().kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner.read().kobj_type.clone()
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner.write().kobj_type = ktype;
}
fn name(&self) -> String {
"serial8250".to_string()
}
fn set_name(&self, _name: String) {}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}
/// 临时函数,用于向默认的串口发送数据
pub fn send_to_default_serial8250_port(s: &[u8]) {
send_to_serial8250_pio_com1(s);
}

View File

@ -0,0 +1,297 @@
//! PIO的串口驱动
use core::{
hint::spin_loop,
sync::atomic::{AtomicBool, Ordering},
};
use alloc::sync::{Arc, Weak};
use crate::{
arch::{io::PortIOArch, CurrentPortIOArch},
driver::tty::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
libs::rwlock::RwLock,
syscall::SystemError,
};
use super::{Serial8250ISADevices, Serial8250ISADriver, Serial8250Manager, Serial8250Port};
static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] =
[None, None, None, None, None, None, None, None];
impl Serial8250Manager {
pub(super) fn bind_pio_ports(
&self,
uart_driver: &Arc<Serial8250ISADriver>,
devs: &Arc<Serial8250ISADevices>,
) {
for i in 0..8 {
if let Some(port) = unsafe { PIO_PORTS[i].as_ref() } {
port.set_device(Some(devs));
self.uart_add_one_port(uart_driver, port).ok();
}
}
}
}
macro_rules! init_port {
($port_num:expr, $baudrate:expr) => {
unsafe {
let port = Serial8250PIOPort::new(
match $port_num {
1 => Serial8250PortBase::COM1,
2 => Serial8250PortBase::COM2,
3 => Serial8250PortBase::COM3,
4 => Serial8250PortBase::COM4,
5 => Serial8250PortBase::COM5,
6 => Serial8250PortBase::COM6,
7 => Serial8250PortBase::COM7,
8 => Serial8250PortBase::COM8,
_ => panic!("invalid port number"),
},
BaudRate::new($baudrate),
);
if let Ok(port) = port {
if port.init().is_ok() {
PIO_PORTS[$port_num - 1] = Some(port);
}
}
}
};
}
/// 在内存管理初始化之前,初始化串口设备
pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> {
for i in 1..=8 {
init_port!(i, 115200);
}
return Ok(());
}
#[derive(Debug)]
pub struct Serial8250PIOPort {
iobase: Serial8250PortBase,
baudrate: AtomicBaudRate,
initialized: AtomicBool,
inner: RwLock<Serial8250PIOPortInner>,
}
impl Serial8250PIOPort {
const SERIAL8250PIO_MAX_BAUD_RATE: BaudRate = BaudRate::new(115200);
pub fn new(iobase: Serial8250PortBase, baudrate: BaudRate) -> Result<Self, SystemError> {
let r = Self {
iobase,
baudrate: AtomicBaudRate::new(baudrate),
initialized: AtomicBool::new(false),
inner: RwLock::new(Serial8250PIOPortInner::new()),
};
if let Err(e) = r.check_baudrate(&baudrate) {
return Err(e);
}
return Ok(r);
}
pub fn init(&self) -> Result<(), SystemError> {
let r = self
.initialized
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
if r.is_err() {
// 已经初始化
return Ok(());
}
let port = self.iobase as u16;
unsafe {
CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts
self.set_divisor(self.baudrate.load(Ordering::SeqCst))
.unwrap(); // Set baud rate
CurrentPortIOArch::out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
CurrentPortIOArch::out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control因此不需要置位RTS/DSR)
CurrentPortIOArch::out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
CurrentPortIOArch::out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if CurrentPortIOArch::in8(port + 0) != 0xAE {
self.initialized.store(false, Ordering::SeqCst);
return Err(SystemError::ENODEV);
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
CurrentPortIOArch::out8(port + 4, 0x08);
}
return Ok(());
/*
Notice that the initialization code above writes to [PORT + 1]
twice with different values. This is once to write to the Divisor
register along with [PORT + 0] and once to write to the Interrupt
register as detailed in the previous section.
The second write to the Line Control register [PORT + 3]
clears the DLAB again as well as setting various other bits.
*/
}
const fn check_baudrate(&self, baudrate: &BaudRate) -> Result<(), SystemError> {
// 错误的比特率
if baudrate.data() > Self::SERIAL8250PIO_MAX_BAUD_RATE.data()
|| Self::SERIAL8250PIO_MAX_BAUD_RATE.data() % baudrate.data() != 0
{
return Err(SystemError::EINVAL);
}
return Ok(());
}
#[allow(dead_code)]
fn serial_received(&self) -> bool {
if self.serial_in(5) & 1 != 0 {
true
} else {
false
}
}
fn is_transmit_empty(&self) -> bool {
if self.serial_in(5) & 0x20 != 0 {
true
} else {
false
}
}
/// 发送字节
///
/// ## 参数
///
/// - `s`:待发送的字节
fn send_bytes(&self, s: &[u8]) {
while self.is_transmit_empty() == false {
spin_loop();
}
for c in s {
self.serial_out(0, (*c).into());
}
}
/// 读取一个字节
#[allow(dead_code)]
fn read_one_byte(&self) -> u8 {
while self.serial_received() == false {
spin_loop();
}
return self.serial_in(0) as u8;
}
}
impl Serial8250Port for Serial8250PIOPort {
fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
self.inner.read().device()
}
fn set_device(&self, device: Option<&Arc<Serial8250ISADevices>>) {
self.inner.write().set_device(device);
}
}
impl UartPort for Serial8250PIOPort {
fn serial_in(&self, offset: u32) -> u32 {
unsafe { CurrentPortIOArch::in8(self.iobase as u16 + offset as u16).into() }
}
fn serial_out(&self, offset: u32, value: u32) {
// warning: pio的串口只能写入8位因此这里丢弃高24位
unsafe { CurrentPortIOArch::out8(self.iobase as u16 + offset as u16, value as u8) }
}
fn divisor(&self, baud: BaudRate) -> (u32, DivisorFraction) {
let divisor = Self::SERIAL8250PIO_MAX_BAUD_RATE.data() / baud.data();
return (divisor, DivisorFraction::new(0));
}
fn set_divisor(&self, baud: BaudRate) -> Result<(), SystemError> {
self.check_baudrate(&baud)?;
let port = self.iobase as u16;
unsafe {
CurrentPortIOArch::out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
let divisor = self.divisor(baud).0;
CurrentPortIOArch::out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte)
CurrentPortIOArch::out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
CurrentPortIOArch::out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
}
self.baudrate.store(baud, Ordering::SeqCst);
return Ok(());
}
fn startup(&self) -> Result<(), SystemError> {
todo!("serial8250_pio::startup")
}
fn shutdown(&self) {
todo!("serial8250_pio::shutdown")
}
fn baud_rate(&self) -> Option<BaudRate> {
Some(self.baudrate.load(Ordering::SeqCst))
}
fn handle_irq(&self) -> Result<(), SystemError> {
todo!("serial8250_pio::handle_irq")
}
}
#[derive(Debug)]
struct Serial8250PIOPortInner {
/// 当前端口绑定的设备
///
/// ps: 存储weak以避免循环引用
device: Option<Weak<Serial8250ISADevices>>,
}
impl Serial8250PIOPortInner {
pub const fn new() -> Self {
Self { device: None }
}
pub fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
if let Some(device) = self.device.as_ref() {
return device.upgrade();
}
return None;
}
fn set_device(&mut self, device: Option<&Arc<Serial8250ISADevices>>) {
self.device = device.map(|d| Arc::downgrade(d));
}
}
#[allow(dead_code)]
#[repr(u16)]
#[derive(Clone, Debug, Copy)]
pub enum Serial8250PortBase {
COM1 = 0x3f8,
COM2 = 0x2f8,
COM3 = 0x3e8,
COM4 = 0x2e8,
COM5 = 0x5f8,
COM6 = 0x4f8,
COM7 = 0x5e8,
COM8 = 0x4e8,
}
/// 临时函数用于向COM1发送数据
pub fn send_to_serial8250_pio_com1(s: &[u8]) {
if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } {
port.send_bytes(s);
}
}

View File

@ -20,7 +20,7 @@ use crate::{
syscall::SystemError,
};
use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
lazy_static! {
/// 所有TTY设备的B树。用于根据名字找到Arc<TtyDevice>
@ -283,17 +283,6 @@ impl TtyDevicePrivateData {
}
}
/// @brief 导出到C的tty初始化函数
#[no_mangle]
pub extern "C" fn rs_tty_init() -> i32 {
let r = tty_init();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 初始化TTY设备
pub fn tty_init() -> Result<(), SystemError> {
let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
@ -322,5 +311,6 @@ pub fn tty_init() -> Result<(), SystemError> {
return Err(devfs_root_inode.unwrap_err());
}
serial_init()?;
return Ok(());
}

View File

@ -0,0 +1,61 @@
use core::fmt::Debug;
use alloc::sync::Arc;
use crate::driver::base::device::driver::Driver;
use super::tty_device::TtyDevice;
/// TTY 驱动
///
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#434
pub trait TtyDriver: Debug + Send + Sync + Driver {
fn driver_name(&self) -> &str;
fn dev_name(&self) -> &str;
fn metadata(&self) -> &TtyDriverMetadata;
fn other(&self) -> Option<&Arc<dyn TtyDriver>>;
fn ttys(&self) -> &[Arc<TtyDevice>];
fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> {
None
}
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub struct TtyDriverMetadata {
/// name of the driver used in /proc/tty
driver_name: &'static str,
/// used for constructing /dev node name
dev_name: &'static str,
/// used as a number base for constructing /dev node name
name_base: i32,
/// major /dev device number (zero for autoassignment)
major: i32,
/// the first minor /dev device number
minor_start: i32,
drv_type: TtyDriverType,
subtype: TtyDriverSubtype,
}
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#411
#[derive(Debug, Clone, Copy)]
pub enum TtyDriverType {}
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#412
#[derive(Debug, Clone, Copy)]
pub enum TtyDriverSubtype {}
bitflags! {
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h?fi=SERIAL_TYPE_NORMAL#492
pub struct TtyDriverFlags: u64 {
}
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/tty_driver.h#350
pub trait TtyDriverOperations {}

View File

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

View File

@ -1,17 +0,0 @@
#include <common/glib.h>
//driver/uart/uart.rs --rust function
enum uart_port_io_addr
{
COM1 = 0x3f8,
COM2 = 0x2f8,
COM3 = 0x3e8,
COM4 = 0x2e8,
COM5 = 0x5f8,
COM6 = 0x4f8,
COM7 = 0x5e8,
COM8 = 0x4E8,
};
extern int c_uart_init(uint16_t port, uint32_t baud_rate);
extern void c_uart_send(uint16_t port, char c);
extern void c_uart_send_str(uint16_t port, const char *str);

View File

@ -1,805 +0,0 @@
use crate::{
driver::{
base::{
char::CharDevice,
device::{
bus::Bus, driver::DriverError, Device, DeviceError, DeviceNumber,
DevicePrivateData, DeviceResource, DeviceState, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectState},
kset::KSet,
platform::{
platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
},
},
Driver,
},
filesystem::{
devfs::{devfs_register, DevFS, DeviceINode},
kernfs::KernFSInode,
vfs::{
syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
PollStatus,
},
},
include::bindings::bindings::{io_in8, io_out8},
kinfo,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::SpinLock,
},
syscall::SystemError,
};
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;
const E_UART_SERIAL_FAULT: i32 = 2;
const UART_MAX_BITS_RATE: u32 = 115200;
lazy_static! {
// 串口设备
pub static ref UART_DEV: Arc<LockedUart> = Arc::new(LockedUart::default());
// 串口驱动
pub static ref UART_DRV: Arc<LockedUartDriver> = Arc::new(LockedUartDriver::default());
}
// @brief 串口端口
#[allow(dead_code)]
#[repr(u16)]
#[derive(Clone, Debug)]
pub enum UartPort {
COM1 = 0x3f8,
COM2 = 0x2f8,
COM3 = 0x3e8,
COM4 = 0x2e8,
COM5 = 0x5f8,
COM6 = 0x4f8,
COM7 = 0x5e8,
COM8 = 0x4e8,
}
impl UartPort {
///@brief 将u16转换为UartPort枚举类型
///@param val 要转换的u16类型
///@return 输入的端口地址正确返回UartPort类型错误返回错误信息
#[allow(dead_code)]
pub fn from_u16(val: u16) -> Result<Self, &'static str> {
match val {
0x3f8 => Ok(Self::COM1),
0x2f8 => Ok(Self::COM2),
0x3e8 => Ok(Self::COM3),
0x2e8 => Ok(Self::COM4),
0x5f8 => Ok(Self::COM5),
0x4f8 => Ok(Self::COM6),
0x5e8 => Ok(Self::COM7),
0x4e8 => Ok(Self::COM8),
_ => Err("port error!"),
}
}
///@brief 将UartPort枚举类型转换为u16类型
///@param self 要转换的UartPort
///@return 转换的u16值
#[allow(dead_code)]
pub fn to_u16(self: &Self) -> u16 {
match self {
Self::COM1 => 0x3f8,
Self::COM2 => 0x2f8,
Self::COM3 => 0x3e8,
Self::COM4 => 0x2e8,
Self::COM5 => 0x5f8,
Self::COM6 => 0x4f8,
Self::COM7 => 0x5e8,
Self::COM8 => 0x4e8,
}
}
}
// @brief 串口寄存器
#[allow(dead_code)]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct UartRegister {
reg_data: u8,
reg_interrupt_enable: u8,
reg_ii_fifo: u8, // Interrupt Identification and FIFO control registers
reg_line_config: u8,
reg_modem_config: u8,
reg_line_status: u8,
reg_modem_statue: u8,
reg_scartch: u8,
}
// @brief 串口设备结构体
#[derive(Debug)]
pub struct Uart {
private_data: DevicePrivateData, // 设备状态
fs: Weak<DevFS>, // 文件系统
port: UartPort,
baud_rate: u32,
metadata: Metadata,
}
impl Default for Uart {
fn default() -> Self {
let mut metadata = Metadata::default();
metadata.file_type = FileType::CharDevice;
c_uart_init(UartPort::COM1.to_u16(), 115200);
Self {
private_data: DevicePrivateData::new(
IdTable::new(
"uart".to_string(),
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
),
None,
CompatibleTable::new(vec!["uart"]),
DeviceState::NotInitialized,
),
fs: Weak::default(),
port: UartPort::COM1,
baud_rate: 115200,
metadata,
}
}
}
// @brief 串口设备结构体(加锁)
#[derive(Debug)]
pub struct LockedUart(SpinLock<Uart>);
impl Default for LockedUart {
fn default() -> Self {
Self(SpinLock::new(Uart::default()))
}
}
impl KObject for LockedUart {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
todo!()
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
todo!()
}
fn kset(&self) -> Option<Arc<KSet>> {
todo!()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
todo!()
}
fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
todo!()
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
todo!()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
todo!()
}
fn set_kobj_state(&self, _state: KObjectState) {
todo!()
}
fn name(&self) -> alloc::string::String {
todo!()
}
fn set_name(&self, _name: alloc::string::String) {
todo!()
}
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
todo!()
}
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
todo!()
}
}
impl PlatformDevice for LockedUart {
fn is_initialized(&self) -> bool {
let state = self.0.lock().private_data.state();
match state {
DeviceState::Initialized => true,
_ => false,
}
}
fn set_state(&self, set_state: DeviceState) {
self.0.lock().private_data.set_state(set_state);
}
fn compatible_table(&self) -> CompatibleTable {
return self.0.lock().private_data.compatible_table().clone();
}
}
impl Device for LockedUart {
fn id_table(&self) -> IdTable {
return IdTable::new(
"uart".to_string(),
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
);
}
fn dev_type(&self) -> DeviceType {
DeviceType::Serial
}
fn bus(&self) -> Option<Arc<dyn Bus>> {
todo!("LockedUart::bus()")
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
todo!("LockedUart::driver()")
}
fn is_dead(&self) -> bool {
false
}
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
todo!("LockedUart::set_driver()")
}
}
impl CharDevice for LockedUart {
fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
let device = self.0.lock();
if len > buf.len() {
return Err(SystemError::E2BIG);
}
kinfo!("------len: {:?}", len);
for i in 0..len {
buf[i] = Self::uart_read_byte(&device.port) as u8;
kinfo!("------buf[{:?}] = {:?}", i, buf[i]);
}
return Ok(len);
}
fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
let device = self.0.lock();
if len > buf.len() {
return Err(SystemError::E2BIG);
}
Self::uart_send(
&device.port,
from_utf8(&buf[0..len]).map_err(|_| SystemError::EIO)?,
);
return Ok(len);
}
fn sync(&self) -> Result<(), SystemError> {
todo!()
}
}
// impl TtyDevice for LockedUart {
// fn ioctl(&self, cmd: String) -> Result<(), DeviceError> {
// //TODO 补充详细信息
// Err(DeviceError::UnsupportedOperation)
// }
// fn state(&self) -> Result<TtyState, TtyError> {
// todo!()
// }
// }
impl IndexNode for LockedUart {
fn read_at(
&self,
_offset: usize,
len: usize,
buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
CharDevice::read(self, len, buf)
}
fn write_at(
&self,
_offset: usize,
len: usize,
buf: &[u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
CharDevice::write(self, len, buf)
}
fn poll(&self) -> Result<PollStatus, SystemError> {
todo!()
}
fn fs(&self) -> Arc<dyn FileSystem> {
return self
.0
.lock()
.fs
.clone()
.upgrade()
.expect("DevFS is not initialized inside Uart Device");
}
fn as_any_ref(&self) -> &dyn Any {
todo!()
}
fn list(&self) -> Result<Vec<String>, SystemError> {
todo!()
}
fn metadata(&self) -> Result<Metadata, SystemError> {
return Ok(self.0.lock().metadata.clone());
}
fn open(
&self,
_data: &mut FilePrivateData,
_mode: &crate::filesystem::vfs::file::FileMode,
) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Ok(());
}
fn 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: ModeType,
) -> Result<Arc<dyn IndexNode>, SystemError> {
// 若文件系统没有实现此方法则默认调用其create_with_data方法。如果仍未实现则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值
return self.create_with_data(name, file_type, mode, 0);
}
fn create_with_data(
&self,
_name: &str,
_file_type: FileType,
_mode: ModeType,
_data: usize,
) -> Result<Arc<dyn IndexNode>, SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn unlink(&self, _name: &str) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn rmdir(&self, _name: &str) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn move_(
&self,
_old_name: &str,
_target: &Arc<dyn IndexNode>,
_new_name: &str,
) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn find(&self, _name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn get_entry_name(&self, _ino: crate::filesystem::vfs::InodeId) -> Result<String, SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn get_entry_name_and_metadata(
&self,
ino: crate::filesystem::vfs::InodeId,
) -> Result<(String, Metadata), SystemError> {
// 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
let name = self.get_entry_name(ino)?;
let entry = self.find(&name)?;
return Ok((name, entry.metadata()?));
}
fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn mount(
&self,
_fs: Arc<dyn FileSystem>,
) -> Result<Arc<crate::filesystem::vfs::MountFS>, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn truncate(&self, _len: usize) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn sync(&self) -> Result<(), SystemError> {
return Ok(());
}
}
impl DeviceINode for LockedUart {
fn set_fs(&self, fs: Weak<DevFS>) {
self.0.lock().fs = fs;
}
}
impl LockedUart {
/// @brief 串口初始化
/// @param uart_port 端口号
/// @param baud_rate 波特率
/// @return 初始化成功返回0,失败,返回错误信息
#[allow(dead_code)]
pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<(), 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(DeviceError::InitializeFailed);
}
unsafe {
io_out8(port + 1, 0x00); // Disable all interrupts
io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
let divisor = UART_MAX_BITS_RATE / baud_rate;
io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte)
io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control因此不需要置位RTS/DSR)
io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if io_in8(port + 0) != 0xAE {
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);
}
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
register along with [PORT + 0] and once to write to the Interrupt
register as detailed in the previous section.
The second write to the Line Control register [PORT + 3]
clears the DLAB again as well as setting various other bits.
*/
}
fn serial_received(offset: u16) -> bool {
if unsafe { io_in8(offset + 5) } & 1 != 0 {
true
} else {
false
}
}
fn is_transmit_empty(offset: u16) -> bool {
if unsafe { io_in8(offset + 5) } & 0x20 != 0 {
true
} else {
false
}
}
/// @brief 串口发送
/// @param uart_port 端口号
/// @param str 发送字符切片
/// @return None
#[allow(dead_code)]
fn uart_send(uart_port: &UartPort, s: &str) {
let port = uart_port.to_u16();
while Self::is_transmit_empty(port) == false {} //TODO:pause
for c in s.bytes() {
unsafe {
io_out8(port, c);
}
}
}
/// @brief 串口接收一个字节
/// @param uart_port 端口号
/// @return 接收的字节
#[allow(dead_code)]
fn uart_read_byte(uart_port: &UartPort) -> char {
let port = uart_port.to_u16();
while Self::serial_received(port) == false {} //TODO:pause
return unsafe { io_in8(port) as char };
}
#[allow(dead_code)]
fn port() -> u16 {
UartPort::COM1.to_u16()
}
}
// @brief 串口驱动结构体
#[repr(C)]
#[derive(Debug)]
pub struct UartDriver {
id_table: IdTable,
sys_info: Option<Arc<dyn IndexNode>>,
}
impl Default for UartDriver {
fn default() -> Self {
Self {
id_table: IdTable::new(
"ttyS".to_string(),
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
),
sys_info: None,
}
}
}
// @brief 串口驱动结构体(加锁)
#[derive(Debug)]
pub struct LockedUartDriver(SpinLock<UartDriver>);
impl Default for LockedUartDriver {
fn default() -> Self {
Self(SpinLock::new(UartDriver::default()))
}
}
impl KObject for LockedUartDriver {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
todo!()
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
todo!()
}
fn kset(&self) -> Option<Arc<KSet>> {
todo!()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
todo!()
}
fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
todo!()
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
todo!()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
todo!()
}
fn set_kobj_state(&self, _state: KObjectState) {
todo!()
}
fn name(&self) -> alloc::string::String {
todo!()
}
fn set_name(&self, _name: alloc::string::String) {
todo!()
}
fn set_kset(&self, _kset: Option<Arc<KSet>>) {
todo!()
}
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
todo!()
}
}
impl Driver for LockedUartDriver {
fn id_table(&self) -> IdTable {
return IdTable::new("uart_driver".to_string(), DeviceNumber::new(0));
}
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
let table = data.compatible_table();
if table.matches(&CompatibleTable::new(vec!["uart"])) {
return Ok(());
}
return Err(DriverError::ProbeError);
}
fn load(
&self,
_data: DevicePrivateData,
_resource: Option<DeviceResource>,
) -> Result<Arc<dyn Device>, DriverError> {
return Err(DriverError::UnsupportedOperation);
}
}
impl LockedUartDriver {
/// @brief 创建串口驱动
/// @param sys_info: sys文件系统inode
/// @return
#[allow(dead_code)]
pub fn new(sys_info: Option<Arc<dyn IndexNode>>) -> Self {
Self(SpinLock::new(UartDriver::new(sys_info)))
}
}
impl PlatformDriver for LockedUartDriver {
fn compatible_table(&self) -> CompatibleTable {
return CompatibleTable::new(vec!["uart"]);
}
}
impl UartDriver {
/// @brief 创建串口驱动
/// @param sys_info: sys文件系统inode
/// @return 返回串口驱动
#[allow(dead_code)]
pub fn new(sys_info: Option<Arc<dyn IndexNode>>) -> Self {
Self {
id_table: IdTable::new(
"ttyS".to_string(),
DeviceNumber::new(DeviceNumber::from_major_minor(4, 64)),
),
sys_info,
}
}
}
///@brief 发送数据
///@param port 端口号
///@param c 要发送的数据
#[no_mangle]
pub extern "C" fn c_uart_send(port: u16, c: u8) {
while LockedUart::is_transmit_empty(port) == false {} //TODO:pause
unsafe {
io_out8(port, c);
}
}
///@brief 从uart接收数据
///@param port 端口号
///@return u8 接收到的数据
#[no_mangle]
pub extern "C" fn c_uart_read(port: u16) -> u8 {
while LockedUart::serial_received(port) == false {} //TODO:pause
unsafe { io_in8(port) }
}
///@brief 通过串口发送整个字符串
///@param port 串口端口
///@param str 字符串S
#[no_mangle]
pub extern "C" fn c_uart_send_str(port: u16, s: *const u8) {
unsafe {
let mut i = 0isize;
while *offset(s, i) != '\0' as u8 {
c_uart_send(port, *offset(s, i));
i = i + 1;
}
}
}
/// @brief 串口初始化
/// @param u16 端口号
/// @param baud_rate 波特率
/// @return 初始化成功返回0,失败,返回错误码
#[no_mangle]
pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
let message: &'static str = "uart init\n";
// 错误的比特率
if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
return -E_UART_BITS_RATE_ERROR;
}
unsafe {
io_out8(port + 1, 0x00); // Disable all interrupts
io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
let divisor = UART_MAX_BITS_RATE / baud_rate;
io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte)
io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // CompatibleTable(hi byte)
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control因此不需要置位RTS/DSR)
io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if io_in8(port + 0) != 0xAE {
return -E_UART_SERIAL_FAULT;
}
// 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);
let bytes = message.as_bytes();
for c in bytes {
c_uart_send(port, *c);
}
}
return UART_SUCCESS;
/*
Notice that the initialization code above writes to [PORT + 1]
twice with different values. This is once to write to the Divisor
register along with [PORT + 0] and once to write to the Interrupt
register as detailed in the previous section.
The second write to the Line Control register [PORT + 3]
clears the DLAB again as well as setting various other bits.
*/
}
/// @brief 串口初始化,注册串口
/// @param none
/// @return 初始化成功,返回(),失败,返回错误码
pub fn uart_init() -> Result<(), SystemError> {
// 以后设备管理初始化完善后不应该出现这种代码,应该在 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().name())
// .expect("uart driver register error");
// UART_DRV.set_sys_info(Some(driver_inode));
UART_DEV.set_state(DeviceState::Initialized);
devfs_register(&UART_DEV.id_table().name(), UART_DEV.clone())?;
// DEVICE_MANAGER.add_device(UART_DEV.id_table().clone(), UART_DEV.clone());
return Ok(());
}

View File

@ -1,129 +0,0 @@
use alloc::sync::Arc;
use crate::driver::base::char::CharDevOps;
use crate::driver::base::device::{device_manager, Device, DeviceResource};
use crate::driver::base::kobject::KObject;
use crate::driver::base::platform::CompatibleTable;
use crate::{
driver::{
base::device::{driver::DriverError, DevicePrivateData, IdTable},
Driver,
},
libs::spinlock::SpinLock,
};
use super::uart_device::LockedUart;
lazy_static! {
pub static ref UART_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["uart"]);
}
#[derive(Debug)]
pub struct InnerUartDriver {
id_table: IdTable,
}
#[derive(Debug)]
pub struct UartDriver(SpinLock<InnerUartDriver>);
impl Default for UartDriver {
fn default() -> Self {
Self(SpinLock::new(InnerUartDriver {
id_table: IdTable::default(),
}))
}
}
impl KObject for UartDriver {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
todo!()
}
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
todo!()
}
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
todo!()
}
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
todo!()
}
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
todo!()
}
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
todo!()
}
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
todo!()
}
fn name(&self) -> alloc::string::String {
todo!()
}
fn set_name(&self, _name: alloc::string::String) {
todo!()
}
fn kobj_state(
&self,
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn kobj_state_mut(
&self,
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
todo!()
}
}
impl Driver for UartDriver {
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError> {
let compatible_table = data.compatible_table();
if compatible_table.matches(&UART_COMPAT_TABLE) {
return Ok(());
}
return Err(DriverError::ProbeError);
}
fn load(
&self,
data: DevicePrivateData,
_resource: Option<DeviceResource>,
) -> Result<Arc<dyn Device>, DriverError> {
if let Some(device) = device_manager().find_device_by_idtable(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(arc_device.clone())
.map_err(|_| DriverError::RegisterError)?;
CharDevOps::cdev_add(arc_device.clone(), data.id_table().clone(), 1)
.map_err(|_| DriverError::RegisterError)?;
}
return Err(DriverError::RegisterError);
}
fn id_table(&self) -> IdTable {
let driver = self.0.lock();
return driver.id_table.clone();
}
}

View File

@ -8,8 +8,7 @@ use alloc::{boxed::Box, sync::Arc};
use crate::{
arch::MMArch,
driver::uart::uart_device::c_uart_send_str,
driver::uart::uart_device::UartPort::COM1,
driver::tty::serial::serial8250::send_to_default_serial8250_port,
include::bindings::bindings::{
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
@ -226,7 +225,7 @@ impl VideoRefreshManager {
.unwrap();
let init_text = "Video driver to map.\n\0";
c_uart_send_str(COM1 as u16, init_text.as_ptr());
send_to_default_serial8250_port(init_text.as_bytes());
//地址映射
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
@ -245,7 +244,7 @@ impl VideoRefreshManager {
__MAMAGER = Some(result);
let init_text = "Video driver initialized.\n\0";
c_uart_send_str(COM1 as u16, init_text.as_ptr());
send_to_default_serial8250_port(init_text.as_bytes());
return Ok(());
}
}

View File

@ -1,4 +1,4 @@
use core::{fmt::Debug, intrinsics::unlikely};
use core::{cmp::min, fmt::Debug, intrinsics::unlikely};
use alloc::{
string::String,
@ -64,7 +64,7 @@ impl KernFS {
(*ptr).self_ref = Arc::downgrade(&root_inode);
}
}
root_inode.inner.lock().parent = Arc::downgrade(&root_inode);
root_inode.inner.write().parent = Arc::downgrade(&root_inode);
*root_inode.fs.write() = Arc::downgrade(&fs);
return fs;
}
@ -88,9 +88,11 @@ impl KernFS {
};
let root_inode = Arc::new(KernFSInode {
name: String::from(""),
inner: SpinLock::new(InnerKernFSInode {
inner: RwLock::new(InnerKernFSInode {
parent: Weak::new(),
metadata,
symlink_target: None,
symlink_target_absolute_path: None,
}),
self_ref: Weak::new(),
fs: RwLock::new(Weak::new()),
@ -106,7 +108,7 @@ impl KernFS {
#[derive(Debug)]
pub struct KernFSInode {
inner: SpinLock<InnerKernFSInode>,
inner: RwLock<InnerKernFSInode>,
/// 指向当前Inode所属的文件系统的弱引用
fs: RwLock<Weak<KernFS>>,
/// 指向自身的弱引用
@ -129,6 +131,9 @@ pub struct InnerKernFSInode {
/// 当前inode的元数据
metadata: Metadata,
/// 符号链接指向的inode仅当inode_type为SymLink时有效
symlink_target: Option<Weak<KernFSInode>>,
symlink_target_absolute_path: Option<String>,
}
impl IndexNode for KernFSInode {
@ -151,7 +156,7 @@ impl IndexNode for KernFSInode {
}
fn metadata(&self) -> Result<Metadata, SystemError> {
return Ok(self.inner.lock().metadata.clone());
return Ok(self.inner.read().metadata.clone());
}
fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
@ -214,7 +219,7 @@ impl IndexNode for KernFSInode {
".." => {
return Ok(self
.inner
.lock()
.read()
.parent
.upgrade()
.ok_or(SystemError::ENOENT)?);
@ -300,6 +305,25 @@ impl IndexNode for KernFSInode {
buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
if self.inode_type == KernInodeType::SymLink {
let inner = self.inner.read();
if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() {
return Ok(0);
}
let len = min(len, buf.len());
let len = min(
len,
inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset,
);
buf[0..len].copy_from_slice(
&inner
.symlink_target_absolute_path
.as_ref()
.unwrap()
.as_bytes()[offset..offset + len],
);
return Ok(len);
}
if self.inode_type != KernInodeType::File {
return Err(SystemError::EISDIR);
}
@ -344,6 +368,51 @@ impl IndexNode for KernFSInode {
}
impl KernFSInode {
pub fn new(
parent: Option<Arc<KernFSInode>>,
name: String,
mut metadata: Metadata,
inode_type: KernInodeType,
private_data: Option<KernInodePrivateData>,
callback: Option<&'static dyn KernFSCallback>,
) -> Arc<KernFSInode> {
metadata.file_type = inode_type.into();
let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
let inode = Arc::new(KernFSInode {
name,
inner: RwLock::new(InnerKernFSInode {
parent: parent.clone(),
metadata,
symlink_target: None,
symlink_target_absolute_path: None,
}),
self_ref: Weak::new(),
fs: RwLock::new(Weak::new()),
private_data: SpinLock::new(private_data),
callback,
children: SpinLock::new(HashMap::new()),
inode_type,
});
{
let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
unsafe {
(*ptr).self_ref = Arc::downgrade(&inode);
}
}
if parent.strong_count() > 0 {
let kernfs = parent
.upgrade()
.unwrap()
.fs()
.downcast_arc::<KernFS>()
.expect("KernFSInode::new: parent is not a KernFS instance");
*inode.fs.write() = Arc::downgrade(&kernfs);
}
return inode;
}
/// 在当前inode下增加子目录
///
/// ## 参数
@ -410,11 +479,15 @@ impl KernFSInode {
private_data: Option<KernInodePrivateData>,
callback: Option<&'static dyn KernFSCallback>,
) -> Result<Arc<KernFSInode>, SystemError> {
let size = if file_type == KernInodeType::File {
4096
} else {
0
};
let size;
match file_type {
KernInodeType::Dir | KernInodeType::SymLink => {
size = 0;
}
KernInodeType::File => {
size = 4096;
}
}
let metadata = Metadata {
size,
@ -475,47 +548,35 @@ impl KernFSInode {
}
}
pub fn new(
parent: Option<Arc<KernFSInode>>,
/// add_link - create a symlink in kernfs
///
/// ## 参数
///
/// - `parent`: directory to create the symlink in
/// - `name`: name of the symlink
/// - `target`: target node for the symlink to point to
///
/// Returns the created node on success
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
pub fn add_link(
&self,
name: String,
mut metadata: Metadata,
inode_type: KernInodeType,
private_data: Option<KernInodePrivateData>,
callback: Option<&'static dyn KernFSCallback>,
) -> Arc<KernFSInode> {
metadata.file_type = inode_type.into();
let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
let inode = Arc::new(KernFSInode {
target: &Arc<KernFSInode>,
target_absolute_path: String,
) -> Result<Arc<KernFSInode>, SystemError> {
// kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
let inode = self.inner_create(
name,
inner: SpinLock::new(InnerKernFSInode {
parent: parent.clone(),
metadata,
}),
self_ref: Weak::new(),
fs: RwLock::new(Weak::new()),
private_data: SpinLock::new(private_data),
callback,
children: SpinLock::new(HashMap::new()),
inode_type,
});
KernInodeType::SymLink,
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
None,
None,
)?;
{
let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
unsafe {
(*ptr).self_ref = Arc::downgrade(&inode);
}
}
if parent.strong_count() > 0 {
let kernfs = parent
.upgrade()
.unwrap()
.fs()
.downcast_arc::<KernFS>()
.expect("KernFSInode::new: parent is not a KernFS instance");
*inode.fs.write() = Arc::downgrade(&kernfs);
}
return inode;
inode.inner.write().symlink_target = Some(Arc::downgrade(target));
inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
return Ok(inode);
}
pub fn name(&self) -> &str {
@ -523,13 +584,18 @@ impl KernFSInode {
}
pub fn parent(&self) -> Option<Arc<KernFSInode>> {
return self.inner.lock().parent.upgrade();
return self.inner.read().parent.upgrade();
}
pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
return self.private_data.lock();
}
#[allow(dead_code)]
pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
return self.inner.read().symlink_target.as_ref()?.upgrade();
}
/// remove a kernfs_node recursively
pub fn remove_recursive(&self) {
let mut children = self.children.lock().drain().collect::<Vec<_>>();
@ -552,6 +618,7 @@ impl KernFSInode {
pub enum KernInodeType {
Dir,
File,
SymLink,
}
impl Into<FileType> for KernInodeType {
@ -559,6 +626,7 @@ impl Into<FileType> for KernInodeType {
match self {
KernInodeType::Dir => FileType::Dir,
KernInodeType::File => FileType::File,
KernInodeType::SymLink => FileType::SymLink,
}
}
}

View File

@ -34,7 +34,14 @@ impl SysFS {
) -> Result<(), SystemError> {
for i in 0..groups.len() {
let group = groups[i];
if group.attrs().is_empty() {
continue;
}
if let Err(e) = self.do_create_group(kobj, group, update) {
kerror!(
"Failed to create group '{}', err={e:?}",
group.name().unwrap_or("")
);
for j in (0..=i).rev() {
self.remove_group(kobj, groups[j]).ok();
}
@ -98,6 +105,16 @@ impl SysFS {
return Ok(());
}
pub fn remove_groups(
&self,
kobj: &Arc<dyn KObject>,
groups: &'static [&'static dyn AttributeGroup],
) {
for group in groups.iter() {
self.remove_group(kobj, *group).ok();
}
}
/// 从一个kobject中移除一个group
///
/// This function removes a group of attributes from a kobject. The attributes
@ -187,6 +204,10 @@ impl SysFS {
}
if let Err(e) = e {
kerror!(
"Failed to create sysfs files for group '{}', err={e:?}",
group.name().unwrap_or("")
);
self.group_remove_files(&parent, group);
return Err(e);
}

View File

@ -1,6 +1,12 @@
use alloc::{string::String, sync::Arc};
use alloc::{
borrow::ToOwned,
string::{String, ToString},
sync::Arc,
};
use crate::{driver::base::kobject::KObject, syscall::SystemError};
use crate::{
driver::base::kobject::KObject, filesystem::kernfs::KernFSInode, syscall::SystemError,
};
use super::SysFS;
@ -9,18 +15,19 @@ impl SysFS {
///
/// ## 参数
///
/// - `kobj`: 要创建符号链接的kobject
/// - `target`: 符号链接的目标(在目标目录下创建)
/// - `kobj`: object whose directory we're creating the link in. (符号链接所在目录)
/// 如果为None则创建在sysfs的根目录下
/// - `target`: object we're pointing to.
/// - `name`: 符号链接的名称
///
/// 参考https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
pub fn create_link(
&self,
_kobj: &Arc<dyn KObject>,
_target: &Arc<dyn KObject>,
_name: String,
kobj: Option<&Arc<dyn KObject>>,
target: &Arc<dyn KObject>,
name: String,
) -> Result<(), SystemError> {
todo!("sysfs create link")
return self.do_create_link(kobj, target, name, true);
}
/// 在sysfs中删除一个符号链接
@ -32,7 +39,67 @@ impl SysFS {
///
///
/// 参考https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143
pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) -> Result<(), SystemError> {
pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) {
todo!("sysfs remove link")
}
fn do_create_link(
&self,
kobj: Option<&Arc<dyn KObject>>,
target: &Arc<dyn KObject>,
name: String,
warn: bool,
) -> Result<(), SystemError> {
let parent = if let Some(kobj) = kobj {
kobj.inode()
} else {
Some(self.root_inode().clone())
};
// 没有parent返回错误
let parent = parent.ok_or(SystemError::EFAULT)?;
return self.do_create_link_sd(&parent, target, name, warn);
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#20
fn do_create_link_sd(
&self,
inode: &Arc<KernFSInode>,
target: &Arc<dyn KObject>,
name: String,
warn: bool,
) -> Result<(), SystemError> {
let target_inode = target.inode().ok_or(SystemError::ENOENT)?;
let target_abs_path = "/sys".to_string() + &self.kernfs_path(&target_inode).to_owned();
// let current_path = self.kernfs_path(inode);
// kdebug!("sysfs: create link {} to {}", current_path, target_abs_path);
let kn = inode.add_link(name.clone(), &target_inode, target_abs_path);
if kn.is_ok() {
return Ok(());
}
let err = kn.unwrap_err();
if warn && err == SystemError::EEXIST {
self.warn_duplicate(inode, &name);
}
return Err(err);
}
/// sysfs_create_link_sd - create symlink to a given object.
///
/// ## 参数
///
/// - `inode`: 目录inode在这个目录下创建符号链接
/// - `target`: object we're pointing to.
/// - `name`: 符号链接的名称
#[allow(dead_code)]
pub(super) fn create_link_sd(
&self,
inode: &Arc<KernFSInode>,
target: &Arc<dyn KObject>,
name: String,
) -> Result<(), SystemError> {
return self.do_create_link_sd(inode, target, name, true);
}
}

View File

@ -78,6 +78,9 @@ pub const DT_SOCK: u16 = 12;
pub const DT_WHT: u16 = 14;
pub const DT_MAX: u16 = 16;
/// vfs容许的最大的符号链接跳转次数
pub const VFS_MAX_FOLLOW_SYMLINK_TIMES: usize = 8;
impl FileType {
pub fn get_file_type_num(&self) -> u16 {
return match self {

View File

@ -23,7 +23,7 @@ use super::{
fcntl::{FcntlCommand, FD_CLOEXEC},
file::{File, FileMode},
utils::rsplit_path,
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE,
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
};
pub const SEEK_SET: u32 = 0;
@ -156,7 +156,8 @@ impl Syscall {
return Err(SystemError::ENAMETOOLONG);
}
let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
let inode: Result<Arc<dyn IndexNode>, SystemError> =
ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
let inode: Arc<dyn IndexNode> = if inode.is_err() {
let errno = inode.unwrap_err();
@ -344,13 +345,14 @@ impl Syscall {
new_path = String::from("/");
}
}
let inode = match ROOT_INODE().lookup(&new_path) {
Err(e) => {
kerror!("Change Directory Failed, Error = {:?}", e);
return Err(SystemError::ENOENT);
}
Ok(i) => i,
};
let inode =
match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) {
Err(e) => {
kerror!("Change Directory Failed, Error = {:?}", e);
return Err(SystemError::ENOENT);
}
Ok(i) => i,
};
let metadata = inode.metadata()?;
if metadata.file_type == FileType::Dir {
proc.basic_mut().set_cwd(String::from(new_path));
@ -730,7 +732,8 @@ impl Syscall {
return Err(SystemError::ENAMETOOLONG);
}
let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
let inode: Result<Arc<dyn IndexNode>, SystemError> =
ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
if inode.is_ok() {
return Err(SystemError::EEXIST);
@ -739,7 +742,8 @@ impl Syscall {
let (filename, parent_path) = rsplit_path(path);
// 查找父目录
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE()
.lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
// 创建nod
parent_inode.mknod(filename, mode, dev_t)?;

View File

@ -1,6 +1,11 @@
use super::init_intertrait;
use super::{init_before_mem_init, init_intertrait};
#[no_mangle]
unsafe extern "C" fn rs_init_intertrait() {
init_intertrait();
}
#[no_mangle]
unsafe extern "C" fn rs_init_before_mem_init() {
init_before_mem_init();
}

View File

@ -1,5 +1,17 @@
use crate::{
driver::{tty::init::tty_early_init, video::VideoRefreshManager},
libs::lib_ui::screen_manager::scm_init,
};
pub mod c_adapter;
fn init_intertrait() {
intertrait::init_caster_map();
}
/// 在内存管理初始化之前,执行的初始化
fn init_before_mem_init() {
tty_early_init().expect("tty early init failed");
unsafe { VideoRefreshManager::video_init().ok() };
scm_init();
}

View File

@ -5,6 +5,7 @@
#![feature(asm_const)]
#![feature(const_mut_refs)]
#![feature(const_trait_impl)]
#![feature(const_refs_to_cell)]
#![feature(core_intrinsics)]
#![feature(c_void_variant)]
#![feature(drain_filter)]

View File

@ -0,0 +1,9 @@
[package]
name = "ida"
version = "0.1.0"
edition = "2021"
authors = ["longjin <longjin@dragonos.org>"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1,50 @@
#![no_std]
#![feature(core_intrinsics)]
use core::intrinsics::unlikely;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
/// id分配器
///
/// TODO: 当前只是为了简单实现功能将来这里应使用类似linux的ida的方式去实现
#[derive(Debug)]
pub struct IdAllocator {
current_id: AtomicUsize,
max_id: usize,
dead: AtomicBool,
}
impl IdAllocator {
/// 创建一个新的id分配器
pub const fn new(max_id: usize) -> Self {
Self {
current_id: AtomicUsize::new(0),
max_id,
dead: AtomicBool::new(false),
}
}
/// 分配一个新的id
///
/// ## 返回
///
/// 如果分配成功返回Some(id)否则返回None
pub fn alloc(&self) -> Option<usize> {
if unlikely(self.dead.load(Ordering::SeqCst)) {
return None;
}
let ret = self.current_id.fetch_add(1, Ordering::SeqCst);
// 如果id溢出panic
if ret == self.max_id {
self.dead.store(true, Ordering::SeqCst);
return None;
}
return Some(ret);
}
pub fn free(&self, _id: usize) {
// todo: free
}
}

View File

@ -44,6 +44,11 @@ macro_rules! int_like {
pub const fn new(x: $backing_type) -> Self {
Self::from(x)
}
#[allow(dead_code)]
pub const fn data(&self) -> $backing_type {
self.0
}
}
};

View File

@ -1,11 +1,5 @@
#pragma once
/**
* @brief
*
*/
extern void scm_init();
/**
* @brief
*

View File

@ -8,8 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
use crate::{
driver::{
uart::uart_device::{c_uart_send_str, UartPort},
video::video_refresh_manager,
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
},
libs::{rwlock::RwLock, spinlock::SpinLock},
mm::VirtAddr,
@ -275,13 +274,12 @@ pub trait ScmUiFramework: Sync + Send + Debug {
/// ## 调用时机
///
/// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
#[no_mangle]
pub extern "C" fn scm_init() {
pub fn scm_init() {
SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
textui_init_no_alloc();
c_uart_send_str(UartPort::COM1.to_u16(), "\nfinish_scm_init\n\0".as_ptr());
send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes());
}
/// 启用某个ui框架将它的帧缓冲区渲染到屏幕上
@ -381,10 +379,7 @@ pub fn scm_enable_put_to_window() {
.enable()
.unwrap_or_else(|e| e.to_posix_errno());
if r.is_negative() {
c_uart_send_str(
UartPort::COM1.to_u16(),
"scm_enable_put_to_window() failed.\n\0".as_ptr(),
);
send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
}
}
}
@ -402,10 +397,7 @@ pub fn scm_disable_put_to_window() {
.disable()
.unwrap_or_else(|e| e.to_posix_errno());
if r.is_negative() {
c_uart_send_str(
UartPort::COM1.to_u16(),
"scm_disable_put_to_window() failed.\n\0".as_ptr(),
);
send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
}
}
}
@ -414,7 +406,7 @@ pub fn scm_disable_put_to_window() {
pub extern "C" fn scm_reinit() -> i32 {
let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno());
if r.is_negative() {
c_uart_send_str(UartPort::COM1.to_u16(), "scm reinit failed.\n\0".as_ptr());
send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes());
}
return r;
}

View File

@ -1,7 +1,6 @@
use crate::{
driver::{
uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
video::video_refresh_manager,
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
},
kdebug, kinfo,
libs::{
@ -86,10 +85,7 @@ pub unsafe fn textui_framwork_init() {
scm_register(textui_framework()).expect("register textui framework failed");
kdebug!("textui framework init success");
c_uart_send_str(
UartPort::COM1.to_u16(),
"\ntext ui initialized\n\0".as_ptr(),
);
send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes());
unsafe { TEXTUI_IS_INIT = true };
} else {
panic!("Try to init TEXTUI_FRAMEWORK twice!");
@ -756,7 +752,7 @@ impl TextuiWindow {
//进行换行操作
if character == '\n' {
// 换行时还需要输出\r
c_uart_send(UartPort::COM1.to_u16(), b'\r');
send_to_default_serial8250_port(&[b'\r']);
if is_enable_window == true {
self.textui_new_line()?;
}
@ -837,7 +833,7 @@ impl TextuiWindow {
} else {
// 输出其他字符
c_uart_send(UartPort::COM1.to_u16(), character as u8);
send_to_default_serial8250_port(&[character as u8]);
if is_enable_window == true {
if let TextuiVline::Chromatic(vline) =
@ -902,10 +898,7 @@ impl TextUiFramework {
impl ScmUiFramework for TextUiFramework {
// 安装ui框架的回调函数
fn install(&self) -> Result<i32, SystemError> {
c_uart_send_str(
UartPort::COM1.to_u16(),
"\ntextui_install_handler\n\0".as_ptr(),
);
send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes());
return Ok(0);
}
// 卸载ui框架的回调函数
@ -1015,7 +1008,7 @@ pub fn textui_putchar(
pub extern "C" fn rs_textui_init() -> i32 {
let r = textui_init().unwrap_or_else(|e| e.to_posix_errno());
if r.is_negative() {
c_uart_send_str(UartPort::COM1.to_u16(), "textui init failed.\n\0".as_ptr());
send_to_default_serial8250_port("textui init failed.\n\0".as_bytes());
}
return r;
}

View File

@ -5,8 +5,7 @@ use core::{
use crate::{
driver::{
uart::uart_device::{c_uart_send, UartPort},
video::video_refresh_manager,
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
},
syscall::SystemError,
};
@ -43,13 +42,12 @@ pub fn no_init_textui_putchar_window(
if unlikely(character == '\0') {
return Ok(());
}
c_uart_send(UartPort::COM1.to_u16(), character as u8);
send_to_default_serial8250_port(&[character as u8]);
// 进行换行操作
if unlikely(character == '\n') {
// 换行时还需要输出\r
c_uart_send(UartPort::COM1.to_u16(), b'\r');
send_to_default_serial8250_port(&[b'\r']);
if is_put_to_window == true {
NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);

View File

@ -201,16 +201,25 @@ impl WaitQueue {
let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
// 如果队列头部的pcb的state与给定的state相与结果不为0则唤醒
while let Some(to_wakeup) = guard.wait_list.pop_front() {
let mut wake = false;
if let Some(state) = state {
if to_wakeup.sched_info().state() == state {
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
});
continue;
wake = true;
}
} else {
wake = true;
}
if wake {
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
});
continue;
} else {
to_push_back.push(to_wakeup);
}
to_push_back.push(to_wakeup);
}
for to_wakeup in to_push_back {
guard.wait_list.push_back(to_wakeup);
}

View File

@ -27,18 +27,16 @@
#include "driver/mouse/ps2_mouse.h"
#include "driver/multiboot2/multiboot2.h"
#include <driver/timers/HPET/HPET.h>
#include <driver/uart/uart.h>
#include <time/timer.h>
#include <driver/interrupt/apic/apic_timer.h>
extern int rs_driver_init();
extern int rs_tty_init();
extern void rs_softirq_init();
extern void rs_mm_init();
extern int rs_video_init();
extern void rs_kthread_init();
extern void rs_init_intertrait();
extern void rs_init_before_mem_init();
ul bsp_idt_size, bsp_gdt_size;
@ -72,10 +70,8 @@ void reload_idt()
// 初始化系统各模块
void system_initialize()
{
c_uart_init(COM1, 115200);
rs_init_before_mem_init();
rs_video_init();
scm_init();
// 重新加载gdt和idt
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
@ -131,7 +127,6 @@ void system_initialize()
vfs_init();
rs_driver_init();
rs_tty_init();
rs_kthread_init();
io_mfence();

View File

@ -14,8 +14,11 @@
#include <sys/wait.h>
#include <unistd.h>
#define MAX_PATH_LEN 4096
// 当前工作目录在main_loop中初始化
char *shell_current_path = NULL;
/**
* @brief shell
*
@ -181,16 +184,18 @@ int shell_cmd_cd(int argc, char **argv)
if (ec == 0)
{
// 获取新的路径字符串
char *new_path = (char *)malloc(dest_len + 2);
memset(new_path, 0, dest_len + 2);
strncpy(new_path, argv[1], dest_len);
char *new_path = (char *)malloc(MAX_PATH_LEN);
if (new_path==NULL) {
goto fail;
}
memset(new_path, 0, MAX_PATH_LEN);
getcwd(new_path, MAX_PATH_LEN);
// 释放原有的路径字符串的内存空间
free(shell_current_path);
shell_current_path = new_path;
shell_current_path[dest_len] = '\0';
return 0;
}
else
@ -216,7 +221,7 @@ int shell_cmd_cd(int argc, char **argv)
// 拼接出新的字符串
char *new_path = (char *)malloc(new_len + 2);
memset(new_path, 0, sizeof(new_path));
memset(new_path, 0, new_len);
strncpy(new_path, shell_current_path, current_dir_len);
if (current_dir_len > 1)
@ -225,10 +230,16 @@ int shell_cmd_cd(int argc, char **argv)
int x = chdir(new_path);
if (x == 0) // 成功切换目录
{
free(new_path);
free(shell_current_path);
// printf("new_path=%s, newlen= %d\n", new_path, new_len);
new_path[new_len + 1] = '\0';
shell_current_path = new_path;
char * pwd = malloc(MAX_PATH_LEN);
if (pwd==NULL) {
goto fail;
}
memset(pwd, 0, MAX_PATH_LEN);
getcwd(pwd, MAX_PATH_LEN);
shell_current_path = pwd;
goto done;
}
else

View File

@ -131,6 +131,7 @@ pid_t getpid(void);
int dup(int fd);
int dup2(int ofd, int nfd);
char *getcwd(char* buf, size_t size);
#if defined(__cplusplus)
} /* extern "C" */

View File

@ -235,4 +235,9 @@ int dup(int fd)
int dup2(int ofd, int nfd)
{
return syscall_invoke(SYS_DUP2, ofd, nfd, 0, 0, 0, 0, 0, 0);
}
char *getcwd(char* buf, size_t size)
{
return syscall_invoke(SYS_GETCWD, buf, size, 0, 0, 0, 0, 0, 0);
}

View File

@ -50,6 +50,8 @@
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_GETCWD 48
/**
* @brief
*