mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
设备驱动模型:完善platform bus相关内容。并注册串口到sysfs (#403)
* 完成初始化platform bus * 删除旧的sysfs * 把uart驱动移动到tty/serial文件夹下 * 完成将串口挂载到sysfs * 修复vfs系统调用未能follow symlink的问题 * 修复shell未能正确获取pwd的问题
This commit is contained in:
parent
06d5e24726
commit
a03c4f9dee
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -180,6 +180,7 @@
|
|||||||
"rust-analyzer.cargo.target": "x86_64-unknown-none",
|
"rust-analyzer.cargo.target": "x86_64-unknown-none",
|
||||||
"rust-analyzer.checkOnSave.allTargets": false,
|
"rust-analyzer.checkOnSave.allTargets": false,
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
"./kernel/Cargo.toml"
|
"./kernel/Cargo.toml",
|
||||||
|
"./kernel/src/libs/ida/Cargo.toml"
|
||||||
],
|
],
|
||||||
}
|
}
|
@ -34,6 +34,7 @@ raw-cpuid = "11.0.1"
|
|||||||
acpi = "5.0.0"
|
acpi = "5.0.0"
|
||||||
intertrait = { path = "src/libs/intertrait" }
|
intertrait = { path = "src/libs/intertrait" }
|
||||||
linkme = "0.2"
|
linkme = "0.2"
|
||||||
|
ida = { path = "src/libs/ida" }
|
||||||
|
|
||||||
# 构建时依赖项
|
# 构建时依赖项
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
9
kernel/src/arch/io.rs
Normal file
9
kernel/src/arch/io.rs
Normal 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);
|
||||||
|
}
|
@ -7,6 +7,8 @@ use crate::{
|
|||||||
mm::PhysAddr,
|
mm::PhysAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod io;
|
||||||
|
|
||||||
/// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数
|
/// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数
|
||||||
pub trait TraitPciArch {
|
pub trait TraitPciArch {
|
||||||
/// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现
|
/// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod bitops;
|
pub mod bitops;
|
||||||
pub mod irqflags;
|
pub mod irqflags;
|
||||||
|
pub mod pio;
|
||||||
|
35
kernel/src/arch/x86_64/asm/pio.rs
Normal file
35
kernel/src/arch/x86_64/asm/pio.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ use hashbrown::HashSet;
|
|||||||
use x86::time::rdtsc;
|
use x86::time::rdtsc;
|
||||||
use x86_64::registers::model_specific::EferFlags;
|
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::{
|
use crate::include::bindings::bindings::{
|
||||||
multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
||||||
};
|
};
|
||||||
@ -148,7 +148,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
|||||||
// 初始化物理内存区域(从multiboot2中获取)
|
// 初始化物理内存区域(从multiboot2中获取)
|
||||||
let areas_count =
|
let areas_count =
|
||||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
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];
|
return &PHYS_MEMORY_AREAS[0..areas_count];
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ impl X86_64MMArch {
|
|||||||
unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
|
unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
|
||||||
// 这个数组用来存放内存区域的信息(从C获取)
|
// 这个数组用来存放内存区域的信息(从C获取)
|
||||||
let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed();
|
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;
|
let mut mb2_count: u32 = 0;
|
||||||
multiboot2_iter(
|
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_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void,
|
||||||
&mut mb2_count,
|
&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 mb2_count = mb2_count as usize;
|
||||||
let mut areas_count = 0usize;
|
let mut areas_count = 0usize;
|
||||||
@ -255,7 +255,7 @@ impl X86_64MMArch {
|
|||||||
areas_count += 1;
|
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);
|
kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
|
||||||
|
|
||||||
return Ok(areas_count);
|
return Ok(areas_count);
|
||||||
@ -291,7 +291,7 @@ impl VirtAddr {
|
|||||||
|
|
||||||
/// @brief 初始化内存管理模块
|
/// @brief 初始化内存管理模块
|
||||||
pub fn mm_init() {
|
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
|
PrintkWriter
|
||||||
.write_fmt(format_args!("mm_init() called\n"))
|
.write_fmt(format_args!("mm_init() called\n"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -301,7 +301,7 @@ pub fn mm_init() {
|
|||||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||||
.is_err()
|
.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");
|
panic!("mm_init() can only be called once");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,3 +20,5 @@ pub use self::pci::pci::X86_64PciArch as PciArch;
|
|||||||
pub use self::mm::X86_64MMArch as MMArch;
|
pub use self::mm::X86_64MMArch as MMArch;
|
||||||
|
|
||||||
pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
|
pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
|
||||||
|
|
||||||
|
pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;
|
||||||
|
23
kernel/src/driver/acpi/bus.rs
Normal file
23
kernel/src/driver/acpi/bus.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod bus;
|
||||||
mod c_adapter;
|
mod c_adapter;
|
||||||
pub mod glue;
|
pub mod glue;
|
||||||
pub mod old;
|
pub mod old;
|
||||||
@ -22,6 +23,11 @@ extern crate acpi;
|
|||||||
|
|
||||||
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn acpi_manager() -> &'static AcpiManager {
|
||||||
|
&AcpiManager
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AcpiManager;
|
pub struct AcpiManager;
|
||||||
|
|
||||||
|
@ -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::{
|
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::{
|
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,
|
vfs::syscall::ModeType,
|
||||||
},
|
},
|
||||||
libs::rwlock::RwLock,
|
libs::rwlock::RwLock,
|
||||||
@ -14,6 +25,7 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely};
|
use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use intertrait::cast::CastArc;
|
||||||
|
|
||||||
/// `/sys/bus`的kset
|
/// `/sys/bus`的kset
|
||||||
static mut BUS_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
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;
|
fn subsystem(&self) -> &SubSysPrivate;
|
||||||
|
|
||||||
/// 对当前总线操作的时候需要获取父级总线的锁
|
/// 对当前总线操作的时候需要获取父级总线的锁
|
||||||
@ -126,7 +178,7 @@ impl dyn Bus {
|
|||||||
data: T,
|
data: T,
|
||||||
) -> Option<Arc<dyn Device>> {
|
) -> Option<Arc<dyn Device>> {
|
||||||
let subsys = self.subsystem();
|
let subsys = self.subsystem();
|
||||||
let guard = subsys.devices().read();
|
let guard = subsys.devices();
|
||||||
for dev in guard.iter() {
|
for dev in guard.iter() {
|
||||||
let dev = dev.upgrade();
|
let dev = dev.upgrade();
|
||||||
if let Some(dev) = dev {
|
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>> {
|
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
|
||||||
return self.find_device(&DeviceMatchName, name);
|
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: 总线管理结构体
|
/// @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
|
/// bus_register - register a driver-core subsystem
|
||||||
///
|
///
|
||||||
@ -257,7 +426,7 @@ impl BusManager {
|
|||||||
/// - `bus` - bus实例
|
/// - `bus` - bus实例
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn rescan_devices(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
|
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();
|
let dev = dev.upgrade();
|
||||||
if let Some(dev) = dev {
|
if let Some(dev) = dev {
|
||||||
rescan_devices_helper(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` - 匹配器
|
/// - `driver` - 驱动实例
|
||||||
/// - `data` - 传给匹配器的数据
|
///
|
||||||
#[inline]
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_remove_driver#666
|
||||||
#[allow(dead_code)]
|
pub fn remove_driver(&self, _driver: &Arc<dyn Driver>) {
|
||||||
pub fn find_device<T: Copy>(
|
todo!("BusManager::remove_driver")
|
||||||
&self,
|
}
|
||||||
bus: &Arc<dyn Bus>,
|
|
||||||
matcher: &dyn DeviceMatcher<T>,
|
fn add_bind_files(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||||
data: T,
|
driver_manager().create_attr_file(driver, &DriverAttrUnbind)?;
|
||||||
) -> Option<Arc<dyn Device>> {
|
|
||||||
return bus.find_device(matcher, data);
|
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` - 要被添加的设备
|
/// - `dev` - 要被添加的设备
|
||||||
pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
let bus = dev.bus();
|
return bus_manager().add_device(dev);
|
||||||
if let Some(bus) = bus {
|
|
||||||
device_manager().add_groups(dev, bus.dev_groups())?;
|
|
||||||
// todo: 增加符号链接
|
|
||||||
todo!("bus_add_device")
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 自动为设备在总线上寻找可用的驱动程序
|
/// 自动为设备在总线上寻找可用的驱动程序
|
||||||
@ -507,3 +681,129 @@ pub enum BusNotifyEvent {
|
|||||||
/// 驱动绑定失败
|
/// 驱动绑定失败
|
||||||
DriverNotBound,
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,26 @@
|
|||||||
use core::intrinsics::unlikely;
|
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 {
|
impl DeviceManager {
|
||||||
/// 尝试把一个设备与一个驱动匹配
|
/// 尝试把一个设备与一个驱动匹配
|
||||||
@ -40,7 +56,8 @@ impl DeviceManager {
|
|||||||
allow_async: bool,
|
allow_async: bool,
|
||||||
) -> Result<bool, SystemError> {
|
) -> Result<bool, SystemError> {
|
||||||
if unlikely(allow_async) {
|
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() {
|
if dev.is_dead() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -64,7 +81,7 @@ impl DeviceManager {
|
|||||||
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
|
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
|
||||||
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
|
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
|
||||||
let mut flag = true;
|
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() {
|
if let Some(driver) = driver.upgrade() {
|
||||||
let r = self.do_device_attach_driver(&driver, &mut data);
|
let r = self.do_device_attach_driver(&driver, &mut data);
|
||||||
if unlikely(r.is_err()) {
|
if unlikely(r.is_err()) {
|
||||||
@ -142,7 +159,7 @@ impl DeviceManager {
|
|||||||
let r = driver_manager().driver_sysfs_add(dev);
|
let r = driver_manager().driver_sysfs_add(dev);
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
self.device_links_force_bind(dev);
|
self.device_links_force_bind(dev);
|
||||||
self.driver_bound(dev);
|
driver_manager().driver_bound(dev);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
} else {
|
} else {
|
||||||
if let Some(bus) = dev.bus() {
|
if let Some(bus) = dev.bus() {
|
||||||
@ -156,9 +173,10 @@ impl DeviceManager {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
|
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528
|
||||||
fn driver_bound(&self, _dev: &Arc<dyn Device>) {
|
fn unbind_cleanup(&self, dev: &Arc<dyn Device>) {
|
||||||
todo!("driver_bound")
|
dev.set_driver(None);
|
||||||
|
// todo: 添加更多操作,清理数据
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,3 +226,368 @@ impl DeviceAttachData {
|
|||||||
self.have_async = true;
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
use super::Device;
|
use super::{
|
||||||
use crate::syscall::SystemError;
|
bus::{bus_manager, Bus},
|
||||||
use alloc::sync::Arc;
|
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;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
/// @brief: Driver error
|
/// @brief: Driver error
|
||||||
@ -31,13 +38,278 @@ pub fn driver_manager() -> &'static DriverManager {
|
|||||||
&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: 驱动管理器
|
/// @brief: 驱动管理器
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DriverManager;
|
pub struct DriverManager;
|
||||||
|
|
||||||
impl 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
|
/// 参考: 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> {
|
pub fn driver_sysfs_add(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
todo!("DriverManager::driver_sysfs_add()");
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,17 @@
|
|||||||
use alloc::{string::ToString, sync::Arc};
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::base::{
|
||||||
base::{
|
|
||||||
device::{
|
device::{
|
||||||
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER,
|
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, DEV_KSET_INSTANCE,
|
||||||
DEV_KSET_INSTANCE,
|
|
||||||
},
|
},
|
||||||
kobject::KObject,
|
kobject::KObject,
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
},
|
},
|
||||||
uart::uart_device::uart_init,
|
|
||||||
},
|
|
||||||
kdebug, kinfo,
|
kdebug, kinfo,
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn device_init() -> Result<(), SystemError> {
|
|
||||||
uart_init()?;
|
|
||||||
kinfo!("device init success");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn devices_init() -> Result<(), SystemError> {
|
pub fn devices_init() -> Result<(), SystemError> {
|
||||||
// 创建 `/sys/devices` 目录
|
// 创建 `/sys/devices` 目录
|
||||||
{
|
{
|
||||||
@ -73,6 +63,6 @@ pub fn devices_init() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kinfo!("devices init success");
|
kinfo!("devices init success");
|
||||||
device_init()?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use alloc::{
|
use alloc::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
use intertrait::cast::CastArc;
|
use intertrait::cast::CastArc;
|
||||||
|
|
||||||
@ -8,10 +8,12 @@ use crate::{
|
|||||||
driver::{
|
driver::{
|
||||||
acpi::glue::acpi_device_notify,
|
acpi::glue::acpi_device_notify,
|
||||||
base::map::{LockedDevsMap, LockedKObjMap},
|
base::map::{LockedDevsMap, LockedKObjMap},
|
||||||
Driver,
|
|
||||||
},
|
},
|
||||||
filesystem::{
|
filesystem::{
|
||||||
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
|
sysfs::{
|
||||||
|
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
|
||||||
|
SysFSOpsSupport,
|
||||||
|
},
|
||||||
vfs::syscall::ModeType,
|
vfs::syscall::ModeType,
|
||||||
},
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
@ -19,12 +21,14 @@ use crate::{
|
|||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::intrinsics::unlikely;
|
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::{
|
use super::{
|
||||||
kobject::{KObjType, KObject, KObjectManager},
|
kobject::{KObjType, KObject, KObjectManager, KObjectState},
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
platform::CompatibleTable,
|
|
||||||
swnode::software_node_notify,
|
swnode::software_node_notify,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +91,7 @@ pub(self) fn sys_dev_char_kset() -> Arc<KSet> {
|
|||||||
/// ## 注意
|
/// ## 注意
|
||||||
///
|
///
|
||||||
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Device>,
|
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Device>,
|
||||||
/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[[sync] Device]`,
|
/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Device)]`,
|
||||||
///
|
///
|
||||||
/// 否则在释放设备资源的时候,会由于无法转换为Arc<dyn Device>而导致资源泄露,并且release回调函数也不会被调用。
|
/// 否则在释放设备资源的时候,会由于无法转换为Arc<dyn Device>而导致资源泄露,并且release回调函数也不会被调用。
|
||||||
pub trait Device: KObject {
|
pub trait Device: KObject {
|
||||||
@ -117,13 +121,39 @@ pub trait Device: KObject {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 设置当前设备所属的总线
|
||||||
|
///
|
||||||
|
/// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Weak指针)
|
||||||
|
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
|
||||||
|
|
||||||
/// 返回已经与当前设备匹配好的驱动程序
|
/// 返回已经与当前设备匹配好的驱动程序
|
||||||
fn driver(&self) -> Option<Arc<dyn Driver>>;
|
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;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DevicePrivateData {
|
pub struct DevicePrivateData {
|
||||||
id_table: IdTable,
|
id_table: IdTable,
|
||||||
resource: Option<DeviceResource>,
|
|
||||||
compatible_table: CompatibleTable,
|
|
||||||
state: DeviceState,
|
state: DeviceState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl DevicePrivateData {
|
impl DevicePrivateData {
|
||||||
pub fn new(
|
pub fn new(id_table: IdTable, state: DeviceState) -> Self {
|
||||||
id_table: IdTable,
|
Self { id_table, state }
|
||||||
resource: Option<DeviceResource>,
|
|
||||||
compatible_table: CompatibleTable,
|
|
||||||
state: DeviceState,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
id_table,
|
|
||||||
resource,
|
|
||||||
compatible_table,
|
|
||||||
state,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_table(&self) -> &IdTable {
|
pub fn id_table(&self) -> &IdTable {
|
||||||
@ -159,31 +178,11 @@ impl DevicePrivateData {
|
|||||||
self.state
|
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) {
|
pub fn set_state(&mut self, state: DeviceState) {
|
||||||
self.state = state;
|
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);
|
int_like!(DeviceNumber, usize);
|
||||||
|
|
||||||
impl Default for DeviceNumber {
|
impl Default for DeviceNumber {
|
||||||
@ -225,6 +224,8 @@ impl DeviceNumber {
|
|||||||
self.0 & 0xff
|
self.0 & 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
||||||
((major & 0xffffff) << 8) | (minor & 0xff)
|
((major & 0xffffff) << 8) | (minor & 0xff)
|
||||||
}
|
}
|
||||||
@ -287,7 +288,7 @@ impl Default for IdTable {
|
|||||||
|
|
||||||
// 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉
|
// 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉
|
||||||
/// @brief: 设备当前状态
|
/// @brief: 设备当前状态
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum DeviceState {
|
pub enum DeviceState {
|
||||||
NotInitialized = 0,
|
NotInitialized = 0,
|
||||||
Initialized = 1,
|
Initialized = 1,
|
||||||
@ -465,6 +466,11 @@ impl DeviceManager {
|
|||||||
todo!()
|
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: 获取设备
|
/// @brief: 获取设备
|
||||||
/// @parameter id_table: 设备标识符,用于唯一标识该设备
|
/// @parameter id_table: 设备标识符,用于唯一标识该设备
|
||||||
/// @return: 设备实例
|
/// @return: 设备实例
|
||||||
@ -521,10 +527,8 @@ impl DeviceManager {
|
|||||||
dev: &Arc<dyn Device>,
|
dev: &Arc<dyn Device>,
|
||||||
attr_groups: &'static [&dyn AttributeGroup],
|
attr_groups: &'static [&dyn AttributeGroup],
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
let dev = dev.clone();
|
let kobj = dev.clone() as Arc<dyn KObject>;
|
||||||
let binding = dev.arc_any();
|
return sysfs_instance().create_groups(&kobj, attr_groups);
|
||||||
let kobj: &Arc<dyn KObject> = binding.downcast_ref().unwrap();
|
|
||||||
return sysfs_instance().create_groups(kobj, attr_groups);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 为设备在sysfs中创建属性文件
|
/// 为设备在sysfs中创建属性文件
|
||||||
@ -567,15 +571,15 @@ impl DeviceManager {
|
|||||||
let target_kobj = self.device_to_dev_kobj(dev);
|
let target_kobj = self.device_to_dev_kobj(dev);
|
||||||
let name = dev.id_table().name();
|
let name = dev.id_table().name();
|
||||||
let current_kobj = dev.clone() as Arc<dyn KObject>;
|
let current_kobj = dev.clone() as Arc<dyn KObject>;
|
||||||
return sysfs_instance().create_link(¤t_kobj, &target_kobj, name);
|
return sysfs_instance().create_link(Some(¤t_kobj), &target_kobj, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete symlink for device in `/sys/dev` or `/sys/class/<class_name>`
|
/// Delete symlink for device in `/sys/dev` or `/sys/class/<class_name>`
|
||||||
#[allow(dead_code)]
|
#[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 kobj = self.device_to_dev_kobj(dev);
|
||||||
let name = dev.id_table().name();
|
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
|
/// 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>) {
|
pub fn device_links_force_bind(&self, _dev: &Arc<dyn Device>) {
|
||||||
todo!("device_links_force_bind")
|
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: 设备注册
|
/// @brief: 设备注册
|
||||||
@ -633,7 +659,7 @@ impl Attribute for DeviceAttrDev {
|
|||||||
"dev"
|
"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| {
|
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
|
||||||
kerror!(
|
kerror!(
|
||||||
"Intertrait casting not implemented for kobj: {}",
|
"Intertrait casting not implemented for kobj: {}",
|
||||||
@ -642,7 +668,10 @@ impl Attribute for DeviceAttrDev {
|
|||||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
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 {
|
fn support(&self) -> SysFSOpsSupport {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::syscall::SystemError;
|
use crate::{driver::tty::tty_device::tty_init, syscall::SystemError};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
class::classes_init,
|
class::classes_init,
|
||||||
@ -15,5 +15,15 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
|
|||||||
firmware_init()?;
|
firmware_init()?;
|
||||||
hypervisor_init()?;
|
hypervisor_init()?;
|
||||||
platform_bus_init()?;
|
platform_bus_init()?;
|
||||||
|
|
||||||
|
// 至此,已完成设备驱动模型的初始化
|
||||||
|
// 接下来,初始化设备
|
||||||
|
actual_device_init()?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn actual_device_init() -> Result<(), SystemError> {
|
||||||
|
tty_init()?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
|
|||||||
|
|
||||||
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
|
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>);
|
||||||
|
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
|
||||||
fn set_name(&self, name: 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 release(&self, _kobj: Arc<dyn KObject>) {}
|
||||||
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
|
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
|
||||||
|
|
||||||
@ -91,7 +93,8 @@ bitflags! {
|
|||||||
pub struct LockedKObjectState(RwLock<KObjectState>);
|
pub struct LockedKObjectState(RwLock<KObjectState>);
|
||||||
|
|
||||||
impl LockedKObjectState {
|
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))
|
LockedKObjectState(RwLock::new(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ impl KSet {
|
|||||||
let r = Self {
|
let r = Self {
|
||||||
kobjects: RwLock::new(Vec::new()),
|
kobjects: RwLock::new(Vec::new()),
|
||||||
inner: RwLock::new(InnerKSet::new(name)),
|
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)),
|
parent_data: RwLock::new(KSetParentData::new(None, None)),
|
||||||
self_ref: Weak::default(),
|
self_ref: Weak::default(),
|
||||||
};
|
};
|
||||||
@ -167,6 +167,10 @@ impl KObject for KSet {
|
|||||||
Some(&KSetKObjType)
|
Some(&KSetKObjType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||||
|
todo!("KSet::set_kobj_type")
|
||||||
|
}
|
||||||
|
|
||||||
fn kset(&self) -> Option<Arc<KSet>> {
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
self.parent_data.read().kset.clone()
|
self.parent_data.read().kset.clone()
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,6 @@ pub fn platform_bus_init() -> Result<(), SystemError> {
|
|||||||
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
||||||
DevicePrivateData::new(
|
DevicePrivateData::new(
|
||||||
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
||||||
None,
|
|
||||||
CompatibleTable::new(vec!["platform"]),
|
|
||||||
BusState::NotInitialized.into(),
|
BusState::NotInitialized.into(),
|
||||||
),
|
),
|
||||||
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
||||||
|
@ -2,31 +2,64 @@ use alloc::{
|
|||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
use ida::IdAllocator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::base::{
|
||||||
base::{
|
|
||||||
device::{
|
device::{
|
||||||
bus::{Bus, BusState},
|
bus::{Bus, BusState},
|
||||||
|
device_manager,
|
||||||
|
driver::Driver,
|
||||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||||
},
|
},
|
||||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
},
|
},
|
||||||
Driver,
|
|
||||||
},
|
|
||||||
filesystem::kernfs::KernFSInode,
|
filesystem::kernfs::KernFSInode,
|
||||||
libs::{
|
libs::{
|
||||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||||
spinlock::SpinLock,
|
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总线上,
|
/// @brief: 实现该trait的设备实例应挂载在platform总线上,
|
||||||
/// 同时应该实现Device trait
|
/// 同时应该实现Device trait
|
||||||
|
///
|
||||||
|
/// ## 注意
|
||||||
|
///
|
||||||
|
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||||
|
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||||
pub trait PlatformDevice: Device {
|
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;
|
fn compatible_table(&self) -> CompatibleTable;
|
||||||
/// @brief: 判断设备是否初始化
|
/// @brief: 判断设备是否初始化
|
||||||
/// @parameter: None
|
/// @parameter: None
|
||||||
@ -39,6 +72,54 @@ pub trait PlatformDevice: Device {
|
|||||||
fn set_state(&self, set_state: DeviceState);
|
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)]
|
#[derive(Debug)]
|
||||||
#[cast_to([sync] Device)]
|
#[cast_to([sync] Device)]
|
||||||
pub struct PlatformBusDevice {
|
pub struct PlatformBusDevice {
|
||||||
@ -56,7 +137,7 @@ impl PlatformBusDevice {
|
|||||||
) -> Arc<PlatformBusDevice> {
|
) -> Arc<PlatformBusDevice> {
|
||||||
return Arc::new(PlatformBusDevice {
|
return Arc::new(PlatformBusDevice {
|
||||||
inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)),
|
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;
|
let state = self.inner.lock().state;
|
||||||
return 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)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InnerPlatformBusDevice {
|
pub struct InnerPlatformBusDevice {
|
||||||
@ -125,14 +196,10 @@ pub struct InnerPlatformBusDevice {
|
|||||||
/// 当前设备挂载到的总线
|
/// 当前设备挂载到的总线
|
||||||
bus: Option<Arc<dyn Bus>>,
|
bus: Option<Arc<dyn Bus>>,
|
||||||
/// 当前设备已经匹配的驱动
|
/// 当前设备已经匹配的驱动
|
||||||
driver: Option<Arc<dyn Driver>>,
|
driver: Option<Weak<dyn Driver>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief: platform方法集
|
|
||||||
impl InnerPlatformBusDevice {
|
impl InnerPlatformBusDevice {
|
||||||
/// @brief: 创建一个platform总线实例
|
|
||||||
/// @parameter: None
|
|
||||||
/// @return: platform总线实例
|
|
||||||
pub fn new(data: DevicePrivateData, parent: Option<Weak<dyn KObject>>) -> Self {
|
pub fn new(data: DevicePrivateData, parent: Option<Weak<dyn KObject>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data,
|
data,
|
||||||
@ -167,6 +234,10 @@ impl KObject for PlatformBusDevice {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||||
|
todo!("platform_bus_device::set_kobj_type")
|
||||||
|
}
|
||||||
|
|
||||||
fn kset(&self) -> Option<Arc<KSet>> {
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -218,8 +289,12 @@ impl Device for PlatformBusDevice {
|
|||||||
self.inner.lock().bus.clone()
|
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>> {
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
self.inner.lock().driver.clone()
|
self.inner.lock().driver.clone()?.upgrade()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -227,7 +302,19 @@ impl Device for PlatformBusDevice {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_driver(&self, driver: Option<Arc<dyn Driver>>) {
|
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||||
self.inner.lock().driver = 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!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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总线上,
|
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上,
|
||||||
/// 同时应该实现Driver trait
|
/// 同时应该实现Driver trait
|
||||||
|
///
|
||||||
|
/// ## 注意
|
||||||
|
///
|
||||||
|
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||||
|
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||||
pub trait PlatformDriver: Driver {
|
pub trait PlatformDriver: Driver {
|
||||||
fn compatible_table(&self) -> CompatibleTable;
|
/// 检测设备是否能绑定到这个驱动
|
||||||
/// @brief 探测设备
|
///
|
||||||
/// @param data 设备初始拥有的基本信息
|
/// 如果能,则把设备的driver指向这个驱动。
|
||||||
fn probe(&self, data: DevicePrivateData) -> Result<(), DriverError> {
|
/// 请注意,这个函数不应该把driver加入驱动的devices列表,相关工作会在外部的函数里面处理。
|
||||||
if data.compatible_table().matches(&PLATFORM_COMPAT_TABLE) {
|
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||||
return Ok(());
|
fn remove(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||||
} else {
|
fn shutdown(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||||
return Err(DriverError::UnsupportedOperation);
|
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>));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,26 @@ use alloc::{
|
|||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
use intertrait::cast::CastArc;
|
||||||
|
|
||||||
use crate::{
|
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::{
|
filesystem::{
|
||||||
sysfs::{Attribute, AttributeGroup},
|
sysfs::{Attribute, AttributeGroup},
|
||||||
vfs::syscall::ModeType,
|
vfs::syscall::ModeType,
|
||||||
},
|
},
|
||||||
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::{platform_device::PlatformDevice, platform_driver::PlatformDriver};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PlatformBus {
|
pub struct PlatformBus {
|
||||||
private: SubSysPrivate,
|
private: SubSysPrivate,
|
||||||
@ -44,6 +55,92 @@ impl Bus for PlatformBus {
|
|||||||
fn subsystem(&self) -> &SubSysPrivate {
|
fn subsystem(&self) -> &SubSysPrivate {
|
||||||
return &self.private;
|
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)]
|
#[derive(Debug)]
|
||||||
|
@ -10,14 +10,18 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::Driver,
|
libs::{
|
||||||
libs::{notifier::AtomicNotifierChain, rwlock::RwLock, spinlock::SpinLock},
|
notifier::AtomicNotifierChain,
|
||||||
|
rwlock::{RwLock, RwLockReadGuard},
|
||||||
|
spinlock::SpinLock,
|
||||||
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
device::{
|
device::{
|
||||||
bus::{Bus, BusNotifyEvent},
|
bus::{Bus, BusNotifyEvent},
|
||||||
|
driver::Driver,
|
||||||
Device,
|
Device,
|
||||||
},
|
},
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
@ -90,12 +94,12 @@ impl SubSysPrivate {
|
|||||||
*self.bus.lock() = bus;
|
*self.bus.lock() = bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn devices(&self) -> &RwLock<Vec<Weak<dyn Device>>> {
|
pub fn devices(&self) -> RwLockReadGuard<Vec<Weak<dyn Device>>> {
|
||||||
return &self.devices;
|
return self.devices.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drivers(&self) -> &RwLock<Vec<Weak<dyn Driver>>> {
|
pub fn drivers(&self) -> RwLockReadGuard<Vec<Weak<dyn Driver>>> {
|
||||||
return &self.drivers;
|
return self.drivers.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drivers_autoprobe(&self) -> bool {
|
pub fn drivers_autoprobe(&self) -> bool {
|
||||||
@ -136,6 +140,45 @@ impl SubSysPrivate {
|
|||||||
pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] {
|
pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] {
|
||||||
return self.interfaces;
|
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
|
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device.h#63
|
||||||
|
@ -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::disk_info::Partition;
|
||||||
use crate::driver::base::block::SeekFrom;
|
use crate::driver::base::block::SeekFrom;
|
||||||
use crate::driver::base::device::bus::Bus;
|
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::device::{Device, DeviceType, IdTable};
|
||||||
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
||||||
use crate::driver::base::kset::KSet;
|
use crate::driver::base::kset::KSet;
|
||||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||||
use crate::driver::Driver;
|
|
||||||
use crate::filesystem::kernfs::KernFSInode;
|
use crate::filesystem::kernfs::KernFSInode;
|
||||||
use crate::filesystem::mbr::MbrDiskPartionTable;
|
use crate::filesystem::mbr::MbrDiskPartionTable;
|
||||||
use crate::include::bindings::bindings::verify_area;
|
use crate::include::bindings::bindings::verify_area;
|
||||||
@ -489,6 +490,10 @@ impl KObject for LockedAhciDisk {
|
|||||||
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device for LockedAhciDisk {
|
impl Device for LockedAhciDisk {
|
||||||
@ -504,6 +509,10 @@ impl Device for LockedAhciDisk {
|
|||||||
todo!("LockedAhciDisk::bus()")
|
todo!("LockedAhciDisk::bus()")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||||
|
todo!("LockedAhciDisk::set_bus()")
|
||||||
|
}
|
||||||
|
|
||||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
todo!("LockedAhciDisk::driver()")
|
todo!("LockedAhciDisk::driver()")
|
||||||
}
|
}
|
||||||
@ -512,9 +521,21 @@ impl Device for LockedAhciDisk {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
|
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
|
||||||
todo!("LockedAhciDisk::set_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 {
|
impl BlockDevice for LockedAhciDisk {
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <common/printk.h>
|
#include <common/printk.h>
|
||||||
#include <driver/acpi/acpi.h>
|
#include <driver/acpi/acpi.h>
|
||||||
#include <exception/gate.h>
|
#include <exception/gate.h>
|
||||||
#include <driver/uart/uart.h>
|
|
||||||
#include <exception/softirq.h>
|
#include <exception/softirq.h>
|
||||||
#include <process/process.h>
|
#include <process/process.h>
|
||||||
#include <sched/sched.h>
|
#include <sched/sched.h>
|
||||||
|
@ -6,50 +6,5 @@ pub mod net;
|
|||||||
pub mod pci;
|
pub mod pci;
|
||||||
pub mod timers;
|
pub mod timers;
|
||||||
pub mod tty;
|
pub mod tty;
|
||||||
pub mod uart;
|
|
||||||
pub mod video;
|
pub mod video;
|
||||||
pub mod virtio;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,7 @@ use smoltcp::{
|
|||||||
|
|
||||||
use crate::{libs::spinlock::SpinLock, syscall::SystemError};
|
use crate::{libs::spinlock::SpinLock, syscall::SystemError};
|
||||||
|
|
||||||
use super::Driver;
|
use super::base::device::driver::Driver;
|
||||||
|
|
||||||
pub mod virtio_net;
|
pub mod virtio_net;
|
||||||
|
|
||||||
|
@ -11,11 +11,10 @@ use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
|||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
base::{
|
base::{
|
||||||
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
device::{bus::Bus, driver::Driver, Device, IdTable},
|
||||||
kobject::KObject,
|
kobject::{KObjType, KObject, KObjectState},
|
||||||
},
|
},
|
||||||
virtio::virtio_impl::HalImpl,
|
virtio::virtio_impl::HalImpl,
|
||||||
Driver,
|
|
||||||
},
|
},
|
||||||
kerror, kinfo,
|
kerror, kinfo,
|
||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
@ -245,19 +244,27 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
||||||
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
fn id_table(&self) -> Option<IdTable> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(
|
fn add_device(&self, _device: Arc<dyn Device>) {
|
||||||
&self,
|
|
||||||
_data: DevicePrivateData,
|
|
||||||
_resource: Option<DeviceResource>,
|
|
||||||
) -> Result<Arc<dyn Device>, DriverError> {
|
|
||||||
todo!()
|
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!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +379,11 @@ impl<T: Transport + 'static> KObject for VirtioInterface<T> {
|
|||||||
todo!()
|
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!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
kernel/src/driver/tty/init.rs
Normal file
8
kernel/src/driver/tty/init.rs
Normal 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(());
|
||||||
|
}
|
@ -9,7 +9,10 @@ use thingbuf::mpsc::{
|
|||||||
|
|
||||||
use crate::libs::rwlock::RwLock;
|
use crate::libs::rwlock::RwLock;
|
||||||
|
|
||||||
|
pub mod init;
|
||||||
|
pub mod serial;
|
||||||
pub mod tty_device;
|
pub mod tty_device;
|
||||||
|
pub mod tty_driver;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct TtyCoreState: u32{
|
pub struct TtyCoreState: u32{
|
||||||
|
71
kernel/src/driver/tty/serial/mod.rs
Normal file
71
kernel/src/driver/tty/serial/mod.rs
Normal 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(());
|
||||||
|
}
|
543
kernel/src/driver/tty/serial/serial8250/mod.rs
Normal file
543
kernel/src/driver/tty/serial/serial8250/mod.rs
Normal 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);
|
||||||
|
}
|
297
kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs
Normal file
297
kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
|
use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice>
|
/// 所有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设备
|
/// @brief 初始化TTY设备
|
||||||
pub fn tty_init() -> Result<(), SystemError> {
|
pub fn tty_init() -> Result<(), SystemError> {
|
||||||
let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
|
let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
|
||||||
@ -322,5 +311,6 @@ pub fn tty_init() -> Result<(), SystemError> {
|
|||||||
return Err(devfs_root_inode.unwrap_err());
|
return Err(devfs_root_inode.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serial_init()?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
61
kernel/src/driver/tty/tty_driver.rs
Normal file
61
kernel/src/driver/tty/tty_driver.rs
Normal 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 {}
|
@ -1,2 +0,0 @@
|
|||||||
pub mod uart_device;
|
|
||||||
pub mod uart_driver;
|
|
@ -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);
|
|
@ -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(());
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,8 +8,7 @@ use alloc::{boxed::Box, sync::Arc};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::MMArch,
|
arch::MMArch,
|
||||||
driver::uart::uart_device::c_uart_send_str,
|
driver::tty::serial::serial8250::send_to_default_serial8250_port,
|
||||||
driver::uart::uart_device::UartPort::COM1,
|
|
||||||
include::bindings::bindings::{
|
include::bindings::bindings::{
|
||||||
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
||||||
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
|
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
|
||||||
@ -226,7 +225,7 @@ impl VideoRefreshManager {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let init_text = "Video driver to map.\n\0";
|
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);
|
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||||
@ -245,7 +244,7 @@ impl VideoRefreshManager {
|
|||||||
__MAMAGER = Some(result);
|
__MAMAGER = Some(result);
|
||||||
|
|
||||||
let init_text = "Video driver initialized.\n\0";
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::{fmt::Debug, intrinsics::unlikely};
|
use core::{cmp::min, fmt::Debug, intrinsics::unlikely};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
string::String,
|
string::String,
|
||||||
@ -64,7 +64,7 @@ impl KernFS {
|
|||||||
(*ptr).self_ref = Arc::downgrade(&root_inode);
|
(*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);
|
*root_inode.fs.write() = Arc::downgrade(&fs);
|
||||||
return fs;
|
return fs;
|
||||||
}
|
}
|
||||||
@ -88,9 +88,11 @@ impl KernFS {
|
|||||||
};
|
};
|
||||||
let root_inode = Arc::new(KernFSInode {
|
let root_inode = Arc::new(KernFSInode {
|
||||||
name: String::from(""),
|
name: String::from(""),
|
||||||
inner: SpinLock::new(InnerKernFSInode {
|
inner: RwLock::new(InnerKernFSInode {
|
||||||
parent: Weak::new(),
|
parent: Weak::new(),
|
||||||
metadata,
|
metadata,
|
||||||
|
symlink_target: None,
|
||||||
|
symlink_target_absolute_path: None,
|
||||||
}),
|
}),
|
||||||
self_ref: Weak::new(),
|
self_ref: Weak::new(),
|
||||||
fs: RwLock::new(Weak::new()),
|
fs: RwLock::new(Weak::new()),
|
||||||
@ -106,7 +108,7 @@ impl KernFS {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KernFSInode {
|
pub struct KernFSInode {
|
||||||
inner: SpinLock<InnerKernFSInode>,
|
inner: RwLock<InnerKernFSInode>,
|
||||||
/// 指向当前Inode所属的文件系统的弱引用
|
/// 指向当前Inode所属的文件系统的弱引用
|
||||||
fs: RwLock<Weak<KernFS>>,
|
fs: RwLock<Weak<KernFS>>,
|
||||||
/// 指向自身的弱引用
|
/// 指向自身的弱引用
|
||||||
@ -129,6 +131,9 @@ pub struct InnerKernFSInode {
|
|||||||
|
|
||||||
/// 当前inode的元数据
|
/// 当前inode的元数据
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
|
/// 符号链接指向的inode(仅当inode_type为SymLink时有效)
|
||||||
|
symlink_target: Option<Weak<KernFSInode>>,
|
||||||
|
symlink_target_absolute_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexNode for KernFSInode {
|
impl IndexNode for KernFSInode {
|
||||||
@ -151,7 +156,7 @@ impl IndexNode for KernFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
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> {
|
fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
|
||||||
@ -214,7 +219,7 @@ impl IndexNode for KernFSInode {
|
|||||||
".." => {
|
".." => {
|
||||||
return Ok(self
|
return Ok(self
|
||||||
.inner
|
.inner
|
||||||
.lock()
|
.read()
|
||||||
.parent
|
.parent
|
||||||
.upgrade()
|
.upgrade()
|
||||||
.ok_or(SystemError::ENOENT)?);
|
.ok_or(SystemError::ENOENT)?);
|
||||||
@ -300,6 +305,25 @@ impl IndexNode for KernFSInode {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
_data: &mut FilePrivateData,
|
_data: &mut FilePrivateData,
|
||||||
) -> Result<usize, SystemError> {
|
) -> 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 {
|
if self.inode_type != KernInodeType::File {
|
||||||
return Err(SystemError::EISDIR);
|
return Err(SystemError::EISDIR);
|
||||||
}
|
}
|
||||||
@ -344,6 +368,51 @@ impl IndexNode for KernFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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下增加子目录
|
/// 在当前inode下增加子目录
|
||||||
///
|
///
|
||||||
/// ## 参数
|
/// ## 参数
|
||||||
@ -410,11 +479,15 @@ impl KernFSInode {
|
|||||||
private_data: Option<KernInodePrivateData>,
|
private_data: Option<KernInodePrivateData>,
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
callback: Option<&'static dyn KernFSCallback>,
|
||||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
let size = if file_type == KernInodeType::File {
|
let size;
|
||||||
4096
|
match file_type {
|
||||||
} else {
|
KernInodeType::Dir | KernInodeType::SymLink => {
|
||||||
0
|
size = 0;
|
||||||
};
|
}
|
||||||
|
KernInodeType::File => {
|
||||||
|
size = 4096;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let metadata = Metadata {
|
let metadata = Metadata {
|
||||||
size,
|
size,
|
||||||
@ -475,47 +548,35 @@ impl KernFSInode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
/// add_link - create a symlink in kernfs
|
||||||
parent: Option<Arc<KernFSInode>>,
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `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,
|
name: String,
|
||||||
mut metadata: Metadata,
|
target: &Arc<KernFSInode>,
|
||||||
inode_type: KernInodeType,
|
target_absolute_path: String,
|
||||||
private_data: Option<KernInodePrivateData>,
|
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
// kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
|
||||||
) -> Arc<KernFSInode> {
|
let inode = self.inner_create(
|
||||||
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,
|
name,
|
||||||
inner: SpinLock::new(InnerKernFSInode {
|
KernInodeType::SymLink,
|
||||||
parent: parent.clone(),
|
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
|
||||||
metadata,
|
None,
|
||||||
}),
|
None,
|
||||||
self_ref: Weak::new(),
|
)?;
|
||||||
fs: RwLock::new(Weak::new()),
|
|
||||||
private_data: SpinLock::new(private_data),
|
|
||||||
callback,
|
|
||||||
children: SpinLock::new(HashMap::new()),
|
|
||||||
inode_type,
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
inode.inner.write().symlink_target = Some(Arc::downgrade(target));
|
||||||
let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
|
inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
|
||||||
unsafe {
|
return Ok(inode);
|
||||||
(*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
@ -523,13 +584,18 @@ impl KernFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent(&self) -> Option<Arc<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>> {
|
pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
|
||||||
return self.private_data.lock();
|
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
|
/// remove a kernfs_node recursively
|
||||||
pub fn remove_recursive(&self) {
|
pub fn remove_recursive(&self) {
|
||||||
let mut children = self.children.lock().drain().collect::<Vec<_>>();
|
let mut children = self.children.lock().drain().collect::<Vec<_>>();
|
||||||
@ -552,6 +618,7 @@ impl KernFSInode {
|
|||||||
pub enum KernInodeType {
|
pub enum KernInodeType {
|
||||||
Dir,
|
Dir,
|
||||||
File,
|
File,
|
||||||
|
SymLink,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<FileType> for KernInodeType {
|
impl Into<FileType> for KernInodeType {
|
||||||
@ -559,6 +626,7 @@ impl Into<FileType> for KernInodeType {
|
|||||||
match self {
|
match self {
|
||||||
KernInodeType::Dir => FileType::Dir,
|
KernInodeType::Dir => FileType::Dir,
|
||||||
KernInodeType::File => FileType::File,
|
KernInodeType::File => FileType::File,
|
||||||
|
KernInodeType::SymLink => FileType::SymLink,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,14 @@ impl SysFS {
|
|||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
for i in 0..groups.len() {
|
for i in 0..groups.len() {
|
||||||
let group = groups[i];
|
let group = groups[i];
|
||||||
|
if group.attrs().is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Err(e) = self.do_create_group(kobj, group, update) {
|
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() {
|
for j in (0..=i).rev() {
|
||||||
self.remove_group(kobj, groups[j]).ok();
|
self.remove_group(kobj, groups[j]).ok();
|
||||||
}
|
}
|
||||||
@ -98,6 +105,16 @@ impl SysFS {
|
|||||||
return Ok(());
|
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
|
/// 从一个kobject中移除一个group
|
||||||
///
|
///
|
||||||
/// This function removes a group of attributes from a kobject. The attributes
|
/// This function removes a group of attributes from a kobject. The attributes
|
||||||
@ -187,6 +204,10 @@ impl SysFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = e {
|
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);
|
self.group_remove_files(&parent, group);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
use super::SysFS;
|
||||||
|
|
||||||
@ -9,18 +15,19 @@ impl SysFS {
|
|||||||
///
|
///
|
||||||
/// ## 参数
|
/// ## 参数
|
||||||
///
|
///
|
||||||
/// - `kobj`: 要创建符号链接的kobject
|
/// - `kobj`: object whose directory we're creating the link in. (符号链接所在目录)
|
||||||
/// - `target`: 符号链接的目标(在目标目录下创建)
|
/// 如果为None,则创建在sysfs的根目录下
|
||||||
|
/// - `target`: object we're pointing to.
|
||||||
/// - `name`: 符号链接的名称
|
/// - `name`: 符号链接的名称
|
||||||
///
|
///
|
||||||
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
|
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
|
||||||
pub fn create_link(
|
pub fn create_link(
|
||||||
&self,
|
&self,
|
||||||
_kobj: &Arc<dyn KObject>,
|
kobj: Option<&Arc<dyn KObject>>,
|
||||||
_target: &Arc<dyn KObject>,
|
target: &Arc<dyn KObject>,
|
||||||
_name: String,
|
name: String,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
todo!("sysfs create link")
|
return self.do_create_link(kobj, target, name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 在sysfs中删除一个符号链接
|
/// 在sysfs中删除一个符号链接
|
||||||
@ -32,7 +39,67 @@ impl SysFS {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143
|
/// 参考: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")
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,9 @@ pub const DT_SOCK: u16 = 12;
|
|||||||
pub const DT_WHT: u16 = 14;
|
pub const DT_WHT: u16 = 14;
|
||||||
pub const DT_MAX: u16 = 16;
|
pub const DT_MAX: u16 = 16;
|
||||||
|
|
||||||
|
/// vfs容许的最大的符号链接跳转次数
|
||||||
|
pub const VFS_MAX_FOLLOW_SYMLINK_TIMES: usize = 8;
|
||||||
|
|
||||||
impl FileType {
|
impl FileType {
|
||||||
pub fn get_file_type_num(&self) -> u16 {
|
pub fn get_file_type_num(&self) -> u16 {
|
||||||
return match self {
|
return match self {
|
||||||
|
@ -23,7 +23,7 @@ use super::{
|
|||||||
fcntl::{FcntlCommand, FD_CLOEXEC},
|
fcntl::{FcntlCommand, FD_CLOEXEC},
|
||||||
file::{File, FileMode},
|
file::{File, FileMode},
|
||||||
utils::rsplit_path,
|
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;
|
pub const SEEK_SET: u32 = 0;
|
||||||
@ -156,7 +156,8 @@ impl Syscall {
|
|||||||
return Err(SystemError::ENAMETOOLONG);
|
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 inode: Arc<dyn IndexNode> = if inode.is_err() {
|
||||||
let errno = inode.unwrap_err();
|
let errno = inode.unwrap_err();
|
||||||
@ -344,7 +345,8 @@ impl Syscall {
|
|||||||
new_path = String::from("/");
|
new_path = String::from("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let inode = match ROOT_INODE().lookup(&new_path) {
|
let inode =
|
||||||
|
match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
kerror!("Change Directory Failed, Error = {:?}", e);
|
kerror!("Change Directory Failed, Error = {:?}", e);
|
||||||
return Err(SystemError::ENOENT);
|
return Err(SystemError::ENOENT);
|
||||||
@ -730,7 +732,8 @@ impl Syscall {
|
|||||||
return Err(SystemError::ENAMETOOLONG);
|
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() {
|
if inode.is_ok() {
|
||||||
return Err(SystemError::EEXIST);
|
return Err(SystemError::EEXIST);
|
||||||
@ -739,7 +742,8 @@ impl Syscall {
|
|||||||
let (filename, parent_path) = rsplit_path(path);
|
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
|
// 创建nod
|
||||||
parent_inode.mknod(filename, mode, dev_t)?;
|
parent_inode.mknod(filename, mode, dev_t)?;
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
use super::init_intertrait;
|
use super::{init_before_mem_init, init_intertrait};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn rs_init_intertrait() {
|
unsafe extern "C" fn rs_init_intertrait() {
|
||||||
init_intertrait();
|
init_intertrait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn rs_init_before_mem_init() {
|
||||||
|
init_before_mem_init();
|
||||||
|
}
|
||||||
|
@ -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;
|
pub mod c_adapter;
|
||||||
|
|
||||||
fn init_intertrait() {
|
fn init_intertrait() {
|
||||||
intertrait::init_caster_map();
|
intertrait::init_caster_map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 在内存管理初始化之前,执行的初始化
|
||||||
|
fn init_before_mem_init() {
|
||||||
|
tty_early_init().expect("tty early init failed");
|
||||||
|
unsafe { VideoRefreshManager::video_init().ok() };
|
||||||
|
scm_init();
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#![feature(asm_const)]
|
#![feature(asm_const)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(const_refs_to_cell)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(c_void_variant)]
|
#![feature(c_void_variant)]
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
|
9
kernel/src/libs/ida/Cargo.toml
Normal file
9
kernel/src/libs/ida/Cargo.toml
Normal 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]
|
50
kernel/src/libs/ida/src/lib.rs
Normal file
50
kernel/src/libs/ida/src/lib.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,11 @@ macro_rules! int_like {
|
|||||||
pub const fn new(x: $backing_type) -> Self {
|
pub const fn new(x: $backing_type) -> Self {
|
||||||
Self::from(x)
|
Self::from(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const fn data(&self) -> $backing_type {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化屏幕管理模块
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
extern void scm_init();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 当内存管理单元被初始化之后,重新处理帧缓冲区问题
|
* @brief 当内存管理单元被初始化之后,重新处理帧缓冲区问题
|
||||||
*
|
*
|
||||||
|
@ -8,8 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
uart::uart_device::{c_uart_send_str, UartPort},
|
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||||
video::video_refresh_manager,
|
|
||||||
},
|
},
|
||||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||||
mm::VirtAddr,
|
mm::VirtAddr,
|
||||||
@ -275,13 +274,12 @@ pub trait ScmUiFramework: Sync + Send + Debug {
|
|||||||
/// ## 调用时机
|
/// ## 调用时机
|
||||||
///
|
///
|
||||||
/// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
|
/// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
|
||||||
#[no_mangle]
|
pub fn scm_init() {
|
||||||
pub extern "C" fn scm_init() {
|
|
||||||
SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
|
SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
|
||||||
|
|
||||||
textui_init_no_alloc();
|
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框架,将它的帧缓冲区渲染到屏幕上
|
/// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上
|
||||||
@ -381,10 +379,7 @@ pub fn scm_enable_put_to_window() {
|
|||||||
.enable()
|
.enable()
|
||||||
.unwrap_or_else(|e| e.to_posix_errno());
|
.unwrap_or_else(|e| e.to_posix_errno());
|
||||||
if r.is_negative() {
|
if r.is_negative() {
|
||||||
c_uart_send_str(
|
send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
|
||||||
UartPort::COM1.to_u16(),
|
|
||||||
"scm_enable_put_to_window() failed.\n\0".as_ptr(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,10 +397,7 @@ pub fn scm_disable_put_to_window() {
|
|||||||
.disable()
|
.disable()
|
||||||
.unwrap_or_else(|e| e.to_posix_errno());
|
.unwrap_or_else(|e| e.to_posix_errno());
|
||||||
if r.is_negative() {
|
if r.is_negative() {
|
||||||
c_uart_send_str(
|
send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
|
||||||
UartPort::COM1.to_u16(),
|
|
||||||
"scm_disable_put_to_window() failed.\n\0".as_ptr(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,7 +406,7 @@ pub fn scm_disable_put_to_window() {
|
|||||||
pub extern "C" fn scm_reinit() -> i32 {
|
pub extern "C" fn scm_reinit() -> i32 {
|
||||||
let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno());
|
let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno());
|
||||||
if r.is_negative() {
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
|
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||||
video::video_refresh_manager,
|
|
||||||
},
|
},
|
||||||
kdebug, kinfo,
|
kdebug, kinfo,
|
||||||
libs::{
|
libs::{
|
||||||
@ -86,10 +85,7 @@ pub unsafe fn textui_framwork_init() {
|
|||||||
scm_register(textui_framework()).expect("register textui framework failed");
|
scm_register(textui_framework()).expect("register textui framework failed");
|
||||||
kdebug!("textui framework init success");
|
kdebug!("textui framework init success");
|
||||||
|
|
||||||
c_uart_send_str(
|
send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes());
|
||||||
UartPort::COM1.to_u16(),
|
|
||||||
"\ntext ui initialized\n\0".as_ptr(),
|
|
||||||
);
|
|
||||||
unsafe { TEXTUI_IS_INIT = true };
|
unsafe { TEXTUI_IS_INIT = true };
|
||||||
} else {
|
} else {
|
||||||
panic!("Try to init TEXTUI_FRAMEWORK twice!");
|
panic!("Try to init TEXTUI_FRAMEWORK twice!");
|
||||||
@ -756,7 +752,7 @@ impl TextuiWindow {
|
|||||||
//进行换行操作
|
//进行换行操作
|
||||||
if character == '\n' {
|
if character == '\n' {
|
||||||
// 换行时还需要输出\r
|
// 换行时还需要输出\r
|
||||||
c_uart_send(UartPort::COM1.to_u16(), b'\r');
|
send_to_default_serial8250_port(&[b'\r']);
|
||||||
if is_enable_window == true {
|
if is_enable_window == true {
|
||||||
self.textui_new_line()?;
|
self.textui_new_line()?;
|
||||||
}
|
}
|
||||||
@ -837,7 +833,7 @@ impl TextuiWindow {
|
|||||||
} else {
|
} 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 is_enable_window == true {
|
||||||
if let TextuiVline::Chromatic(vline) =
|
if let TextuiVline::Chromatic(vline) =
|
||||||
@ -902,10 +898,7 @@ impl TextUiFramework {
|
|||||||
impl ScmUiFramework for TextUiFramework {
|
impl ScmUiFramework for TextUiFramework {
|
||||||
// 安装ui框架的回调函数
|
// 安装ui框架的回调函数
|
||||||
fn install(&self) -> Result<i32, SystemError> {
|
fn install(&self) -> Result<i32, SystemError> {
|
||||||
c_uart_send_str(
|
send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes());
|
||||||
UartPort::COM1.to_u16(),
|
|
||||||
"\ntextui_install_handler\n\0".as_ptr(),
|
|
||||||
);
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
// 卸载ui框架的回调函数
|
// 卸载ui框架的回调函数
|
||||||
@ -1015,7 +1008,7 @@ pub fn textui_putchar(
|
|||||||
pub extern "C" fn rs_textui_init() -> i32 {
|
pub extern "C" fn rs_textui_init() -> i32 {
|
||||||
let r = textui_init().unwrap_or_else(|e| e.to_posix_errno());
|
let r = textui_init().unwrap_or_else(|e| e.to_posix_errno());
|
||||||
if r.is_negative() {
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ use core::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::{
|
driver::{
|
||||||
uart::uart_device::{c_uart_send, UartPort},
|
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||||
video::video_refresh_manager,
|
|
||||||
},
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
@ -43,13 +42,12 @@ pub fn no_init_textui_putchar_window(
|
|||||||
if unlikely(character == '\0') {
|
if unlikely(character == '\0') {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
send_to_default_serial8250_port(&[character as u8]);
|
||||||
c_uart_send(UartPort::COM1.to_u16(), character as u8);
|
|
||||||
|
|
||||||
// 进行换行操作
|
// 进行换行操作
|
||||||
if unlikely(character == '\n') {
|
if unlikely(character == '\n') {
|
||||||
// 换行时还需要输出\r
|
// 换行时还需要输出\r
|
||||||
c_uart_send(UartPort::COM1.to_u16(), b'\r');
|
send_to_default_serial8250_port(&[b'\r']);
|
||||||
if is_put_to_window == true {
|
if is_put_to_window == true {
|
||||||
NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
|
NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
|
||||||
NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
|
NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
|
||||||
|
@ -201,16 +201,25 @@ impl WaitQueue {
|
|||||||
let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
|
let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
|
||||||
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
|
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
|
||||||
while let Some(to_wakeup) = guard.wait_list.pop_front() {
|
while let Some(to_wakeup) = guard.wait_list.pop_front() {
|
||||||
|
let mut wake = false;
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
if to_wakeup.sched_info().state() == state {
|
if to_wakeup.sched_info().state() == state {
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if wake {
|
||||||
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
|
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
|
||||||
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
|
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
to_push_back.push(to_wakeup);
|
to_push_back.push(to_wakeup);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for to_wakeup in to_push_back {
|
for to_wakeup in to_push_back {
|
||||||
guard.wait_list.push_back(to_wakeup);
|
guard.wait_list.push_back(to_wakeup);
|
||||||
}
|
}
|
||||||
|
@ -27,18 +27,16 @@
|
|||||||
#include "driver/mouse/ps2_mouse.h"
|
#include "driver/mouse/ps2_mouse.h"
|
||||||
#include "driver/multiboot2/multiboot2.h"
|
#include "driver/multiboot2/multiboot2.h"
|
||||||
#include <driver/timers/HPET/HPET.h>
|
#include <driver/timers/HPET/HPET.h>
|
||||||
#include <driver/uart/uart.h>
|
|
||||||
#include <time/timer.h>
|
#include <time/timer.h>
|
||||||
|
|
||||||
#include <driver/interrupt/apic/apic_timer.h>
|
#include <driver/interrupt/apic/apic_timer.h>
|
||||||
|
|
||||||
extern int rs_driver_init();
|
extern int rs_driver_init();
|
||||||
extern int rs_tty_init();
|
|
||||||
extern void rs_softirq_init();
|
extern void rs_softirq_init();
|
||||||
extern void rs_mm_init();
|
extern void rs_mm_init();
|
||||||
extern int rs_video_init();
|
|
||||||
extern void rs_kthread_init();
|
extern void rs_kthread_init();
|
||||||
extern void rs_init_intertrait();
|
extern void rs_init_intertrait();
|
||||||
|
extern void rs_init_before_mem_init();
|
||||||
|
|
||||||
ul bsp_idt_size, bsp_gdt_size;
|
ul bsp_idt_size, bsp_gdt_size;
|
||||||
|
|
||||||
@ -72,10 +70,8 @@ void reload_idt()
|
|||||||
// 初始化系统各模块
|
// 初始化系统各模块
|
||||||
void system_initialize()
|
void system_initialize()
|
||||||
{
|
{
|
||||||
c_uart_init(COM1, 115200);
|
rs_init_before_mem_init();
|
||||||
|
|
||||||
rs_video_init();
|
|
||||||
scm_init();
|
|
||||||
// 重新加载gdt和idt
|
// 重新加载gdt和idt
|
||||||
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
||||||
|
|
||||||
@ -131,7 +127,6 @@ void system_initialize()
|
|||||||
vfs_init();
|
vfs_init();
|
||||||
|
|
||||||
rs_driver_init();
|
rs_driver_init();
|
||||||
rs_tty_init();
|
|
||||||
|
|
||||||
rs_kthread_init();
|
rs_kthread_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define MAX_PATH_LEN 4096
|
||||||
|
|
||||||
// 当前工作目录(在main_loop中初始化)
|
// 当前工作目录(在main_loop中初始化)
|
||||||
char *shell_current_path = NULL;
|
char *shell_current_path = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief shell 内建函数的主命令与处理函数的映射表
|
* @brief shell 内建函数的主命令与处理函数的映射表
|
||||||
*
|
*
|
||||||
@ -181,16 +184,18 @@ int shell_cmd_cd(int argc, char **argv)
|
|||||||
if (ec == 0)
|
if (ec == 0)
|
||||||
{
|
{
|
||||||
// 获取新的路径字符串
|
// 获取新的路径字符串
|
||||||
char *new_path = (char *)malloc(dest_len + 2);
|
char *new_path = (char *)malloc(MAX_PATH_LEN);
|
||||||
memset(new_path, 0, dest_len + 2);
|
if (new_path==NULL) {
|
||||||
strncpy(new_path, argv[1], dest_len);
|
goto fail;
|
||||||
|
}
|
||||||
|
memset(new_path, 0, MAX_PATH_LEN);
|
||||||
|
getcwd(new_path, MAX_PATH_LEN);
|
||||||
|
|
||||||
// 释放原有的路径字符串的内存空间
|
// 释放原有的路径字符串的内存空间
|
||||||
free(shell_current_path);
|
free(shell_current_path);
|
||||||
|
|
||||||
shell_current_path = new_path;
|
shell_current_path = new_path;
|
||||||
|
|
||||||
shell_current_path[dest_len] = '\0';
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -216,7 +221,7 @@ int shell_cmd_cd(int argc, char **argv)
|
|||||||
|
|
||||||
// 拼接出新的字符串
|
// 拼接出新的字符串
|
||||||
char *new_path = (char *)malloc(new_len + 2);
|
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);
|
strncpy(new_path, shell_current_path, current_dir_len);
|
||||||
|
|
||||||
if (current_dir_len > 1)
|
if (current_dir_len > 1)
|
||||||
@ -225,10 +230,16 @@ int shell_cmd_cd(int argc, char **argv)
|
|||||||
int x = chdir(new_path);
|
int x = chdir(new_path);
|
||||||
if (x == 0) // 成功切换目录
|
if (x == 0) // 成功切换目录
|
||||||
{
|
{
|
||||||
|
free(new_path);
|
||||||
free(shell_current_path);
|
free(shell_current_path);
|
||||||
// printf("new_path=%s, newlen= %d\n", new_path, new_len);
|
|
||||||
new_path[new_len + 1] = '\0';
|
char * pwd = malloc(MAX_PATH_LEN);
|
||||||
shell_current_path = new_path;
|
if (pwd==NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
memset(pwd, 0, MAX_PATH_LEN);
|
||||||
|
getcwd(pwd, MAX_PATH_LEN);
|
||||||
|
shell_current_path = pwd;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -131,6 +131,7 @@ pid_t getpid(void);
|
|||||||
int dup(int fd);
|
int dup(int fd);
|
||||||
|
|
||||||
int dup2(int ofd, int nfd);
|
int dup2(int ofd, int nfd);
|
||||||
|
char *getcwd(char* buf, size_t size);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -236,3 +236,8 @@ int dup2(int ofd, int nfd)
|
|||||||
{
|
{
|
||||||
return syscall_invoke(SYS_DUP2, ofd, nfd, 0, 0, 0, 0, 0, 0);
|
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);
|
||||||
|
}
|
@ -50,6 +50,8 @@
|
|||||||
#define SYS_GETSOCKNAME 41 // 获取socket的名字
|
#define SYS_GETSOCKNAME 41 // 获取socket的名字
|
||||||
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
|
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
|
||||||
|
|
||||||
|
#define SYS_GETCWD 48
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 用户态系统调用函数
|
* @brief 用户态系统调用函数
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user