mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16: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.checkOnSave.allTargets": false,
|
||||
"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"
|
||||
intertrait = { path = "src/libs/intertrait" }
|
||||
linkme = "0.2"
|
||||
ida = { path = "src/libs/ida" }
|
||||
|
||||
# 构建时依赖项
|
||||
[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,
|
||||
};
|
||||
|
||||
pub mod io;
|
||||
|
||||
/// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数
|
||||
pub trait TraitPciArch {
|
||||
/// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod bitops;
|
||||
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_64::registers::model_specific::EferFlags;
|
||||
|
||||
use crate::driver::uart::uart_device::c_uart_send_str;
|
||||
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
|
||||
use crate::include::bindings::bindings::{
|
||||
multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
||||
};
|
||||
@ -148,7 +148,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
// 初始化物理内存区域(从multiboot2中获取)
|
||||
let areas_count =
|
||||
Self::init_memory_area_from_multiboot2().expect("init memory area failed");
|
||||
c_uart_send_str(0x3f8, "x86 64 init end\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes());
|
||||
|
||||
return &PHYS_MEMORY_AREAS[0..areas_count];
|
||||
}
|
||||
@ -229,7 +229,7 @@ impl X86_64MMArch {
|
||||
unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
|
||||
// 这个数组用来存放内存区域的信息(从C获取)
|
||||
let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed();
|
||||
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 begin\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes());
|
||||
|
||||
let mut mb2_count: u32 = 0;
|
||||
multiboot2_iter(
|
||||
@ -237,7 +237,7 @@ impl X86_64MMArch {
|
||||
&mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void,
|
||||
&mut mb2_count,
|
||||
);
|
||||
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 2\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes());
|
||||
|
||||
let mb2_count = mb2_count as usize;
|
||||
let mut areas_count = 0usize;
|
||||
@ -255,7 +255,7 @@ impl X86_64MMArch {
|
||||
areas_count += 1;
|
||||
}
|
||||
}
|
||||
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 end\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes());
|
||||
kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
|
||||
|
||||
return Ok(areas_count);
|
||||
@ -291,7 +291,7 @@ impl VirtAddr {
|
||||
|
||||
/// @brief 初始化内存管理模块
|
||||
pub fn mm_init() {
|
||||
c_uart_send_str(0x3f8, "mm_init\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("mm_init\n\0".as_bytes());
|
||||
PrintkWriter
|
||||
.write_fmt(format_args!("mm_init() called\n"))
|
||||
.unwrap();
|
||||
@ -301,7 +301,7 @@ pub fn mm_init() {
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_err()
|
||||
{
|
||||
c_uart_send_str(0x3f8, "mm_init err\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("mm_init err\n\0".as_bytes());
|
||||
panic!("mm_init() can only be called once");
|
||||
}
|
||||
|
||||
|
@ -20,3 +20,5 @@ pub use self::pci::pci::X86_64PciArch as PciArch;
|
||||
pub use self::mm::X86_64MMArch as MMArch;
|
||||
|
||||
pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
|
||||
|
||||
pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;
|
||||
|
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;
|
||||
pub mod glue;
|
||||
pub mod old;
|
||||
@ -22,6 +23,11 @@ extern crate acpi;
|
||||
|
||||
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn acpi_manager() -> &'static AcpiManager {
|
||||
&AcpiManager
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AcpiManager;
|
||||
|
||||
|
@ -1,8 +1,19 @@
|
||||
use super::{sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState};
|
||||
use super::{
|
||||
driver::{Driver, DriverMatchName, DriverMatcher},
|
||||
sys_devices_kset, Device, DeviceMatchName, DeviceMatcher, DeviceState,
|
||||
};
|
||||
use crate::{
|
||||
driver::base::{device::device_manager, kobject::KObject, kset::KSet, subsys::SubSysPrivate},
|
||||
driver::base::{
|
||||
device::{device_manager, driver::driver_manager},
|
||||
kobject::{KObjType, KObject, KObjectManager},
|
||||
kset::KSet,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
filesystem::{
|
||||
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOpsSupport},
|
||||
sysfs::{
|
||||
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
|
||||
SysFSOpsSupport,
|
||||
},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
libs::rwlock::RwLock,
|
||||
@ -14,6 +25,7 @@ use alloc::{
|
||||
};
|
||||
use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely};
|
||||
use hashbrown::HashMap;
|
||||
use intertrait::cast::CastArc;
|
||||
|
||||
/// `/sys/bus`的kset
|
||||
static mut BUS_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||
@ -105,6 +117,46 @@ pub trait Bus: Debug + Send + Sync {
|
||||
&[]
|
||||
}
|
||||
|
||||
/// 检查设备是否可以被总线绑定,如果可以,就绑定它们。
|
||||
/// 绑定之后,device的driver字段会被设置为驱动实例。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `device` - 设备实例
|
||||
///
|
||||
/// ## 默认实现
|
||||
///
|
||||
/// 如果总线不支持该操作,返回`SystemError::EOPNOTSUPP_OR_ENOTSUP`
|
||||
fn probe(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError>;
|
||||
fn sync_state(&self, _device: &Arc<dyn Device>) {}
|
||||
fn shutdown(&self, _device: &Arc<dyn Device>);
|
||||
fn suspend(&self, _device: &Arc<dyn Device>) {
|
||||
// todo: implement suspend
|
||||
}
|
||||
|
||||
fn resume(&self, device: &Arc<dyn Device>) -> Result<(), SystemError>;
|
||||
|
||||
/// match platform device to platform driver.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// * `device` - platform device
|
||||
/// * `driver` - platform driver
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - `Ok(true)` - 匹配成功
|
||||
/// - `Ok(false)` - 匹配失败
|
||||
/// - `Err(_)` - 由于内部错误导致匹配失败
|
||||
fn match_device(
|
||||
&self,
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError>;
|
||||
|
||||
fn subsystem(&self) -> &SubSysPrivate;
|
||||
|
||||
/// 对当前总线操作的时候需要获取父级总线的锁
|
||||
@ -126,7 +178,7 @@ impl dyn Bus {
|
||||
data: T,
|
||||
) -> Option<Arc<dyn Device>> {
|
||||
let subsys = self.subsystem();
|
||||
let guard = subsys.devices().read();
|
||||
let guard = subsys.devices();
|
||||
for dev in guard.iter() {
|
||||
let dev = dev.upgrade();
|
||||
if let Some(dev) = dev {
|
||||
@ -146,6 +198,35 @@ impl dyn Bus {
|
||||
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
|
||||
return self.find_device(&DeviceMatchName, name);
|
||||
}
|
||||
|
||||
/// 在bus上,根据条件寻找一个特定的驱动
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `matcher` - 匹配器
|
||||
/// - `data` - 传给匹配器的数据
|
||||
pub fn find_driver<T: Copy>(
|
||||
&self,
|
||||
matcher: &dyn DriverMatcher<T>,
|
||||
data: T,
|
||||
) -> Option<Arc<dyn Driver>> {
|
||||
let subsys = self.subsystem();
|
||||
let guard = subsys.drivers();
|
||||
for drv in guard.iter() {
|
||||
let drv = drv.upgrade();
|
||||
if let Some(drv) = drv {
|
||||
if matcher.match_driver(&drv, data) {
|
||||
return Some(drv.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
/// 根据名称在bus上匹配驱动
|
||||
pub fn find_driver_by_name(&self, name: &str) -> Option<Arc<dyn Driver>> {
|
||||
return self.find_driver(&DriverMatchName, name);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 总线管理结构体
|
||||
@ -162,6 +243,94 @@ impl BusManager {
|
||||
};
|
||||
}
|
||||
|
||||
/// 把一个设备添加到总线上
|
||||
///
|
||||
/// ## 描述
|
||||
///
|
||||
/// - 添加一个设备的与bus相关的属性
|
||||
/// - 在bus和设备文件夹下,创建软链接
|
||||
/// - 把设备添加到它的总线的设备列表中
|
||||
///
|
||||
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_device#441
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `dev` - 要被添加的设备
|
||||
pub fn add_device(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let bus = dev.bus();
|
||||
if let Some(bus) = bus {
|
||||
device_manager().add_groups(dev, bus.dev_groups())?;
|
||||
|
||||
// 增加符号链接
|
||||
let bus_devices_kset = bus
|
||||
.subsystem()
|
||||
.devices_kset()
|
||||
.expect("bus devices kset is none, maybe bus is not registered");
|
||||
let dev_kobj = dev.clone() as Arc<dyn KObject>;
|
||||
|
||||
sysfs_instance().create_link(
|
||||
Some(&bus_devices_kset.as_kobject()),
|
||||
&dev_kobj,
|
||||
dev.name(),
|
||||
)?;
|
||||
sysfs_instance().create_link(
|
||||
Some(&dev_kobj),
|
||||
&(&bus.subsystem().subsys().as_kobject()),
|
||||
"subsystem".to_string(),
|
||||
)?;
|
||||
bus.subsystem().add_device_to_vec(dev)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 在总线上添加一个驱动
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_driver#590
|
||||
pub fn add_driver(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
|
||||
kdebug!("bus '{}' add driver '{}'", bus.name(), driver.name());
|
||||
|
||||
driver.set_kobj_type(Some(&BusDriverKType));
|
||||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||||
KObjectManager::add_kobj(kobj, bus.subsystem().drivers_kset())?;
|
||||
|
||||
bus.subsystem().add_driver_to_vec(driver)?;
|
||||
if bus.subsystem().drivers_autoprobe() {
|
||||
let r = driver_manager().driver_attach(driver);
|
||||
if let Err(e) = r {
|
||||
bus.subsystem().remove_driver_from_vec(driver);
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
|
||||
driver_manager()
|
||||
.add_groups(driver, bus.drv_groups())
|
||||
.or_else(|e| {
|
||||
kerror!(
|
||||
"BusManager::add_driver: driver '{:?}' add_groups failed, err: '{:?}",
|
||||
driver.name(),
|
||||
e
|
||||
);
|
||||
Err(e)
|
||||
})
|
||||
.ok();
|
||||
|
||||
if !driver.suppress_bind_attrs() {
|
||||
self.add_bind_files(driver)
|
||||
.or_else(|e| {
|
||||
kerror!(
|
||||
"BusManager::add_driver: driver '{:?}' add_bind_files failed, err: '{:?}",
|
||||
driver.name(),
|
||||
e
|
||||
);
|
||||
Err(e)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
///
|
||||
/// bus_register - register a driver-core subsystem
|
||||
///
|
||||
@ -257,7 +426,7 @@ impl BusManager {
|
||||
/// - `bus` - bus实例
|
||||
#[allow(dead_code)]
|
||||
pub fn rescan_devices(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||
for dev in bus.subsystem().devices().read().iter() {
|
||||
for dev in bus.subsystem().devices().iter() {
|
||||
let dev = dev.upgrade();
|
||||
if let Some(dev) = dev {
|
||||
rescan_devices_helper(dev)?;
|
||||
@ -283,21 +452,32 @@ impl BusManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// 在bus上,根据条件寻找一个特定的设备
|
||||
/// 从总线上移除一个驱动
|
||||
///
|
||||
/// Detach the driver from the devices it controls, and remove
|
||||
/// it from its bus's list of drivers. Finally, we drop the reference
|
||||
/// to the bus.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `matcher` - 匹配器
|
||||
/// - `data` - 传给匹配器的数据
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn find_device<T: Copy>(
|
||||
&self,
|
||||
bus: &Arc<dyn Bus>,
|
||||
matcher: &dyn DeviceMatcher<T>,
|
||||
data: T,
|
||||
) -> Option<Arc<dyn Device>> {
|
||||
return bus.find_device(matcher, data);
|
||||
/// - `driver` - 驱动实例
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_remove_driver#666
|
||||
pub fn remove_driver(&self, _driver: &Arc<dyn Driver>) {
|
||||
todo!("BusManager::remove_driver")
|
||||
}
|
||||
|
||||
fn add_bind_files(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
driver_manager().create_attr_file(driver, &DriverAttrUnbind)?;
|
||||
|
||||
driver_manager()
|
||||
.create_attr_file(driver, &DriverAttrBind)
|
||||
.map_err(|e| {
|
||||
driver_manager().remove_attr_file(driver, &DriverAttrUnbind);
|
||||
e
|
||||
})?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,13 +556,7 @@ pub fn buses_init() -> Result<(), SystemError> {
|
||||
///
|
||||
/// - `dev` - 要被添加的设备
|
||||
pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let bus = dev.bus();
|
||||
if let Some(bus) = bus {
|
||||
device_manager().add_groups(dev, bus.dev_groups())?;
|
||||
// todo: 增加符号链接
|
||||
todo!("bus_add_device")
|
||||
}
|
||||
return Ok(());
|
||||
return bus_manager().add_device(dev);
|
||||
}
|
||||
|
||||
/// 自动为设备在总线上寻找可用的驱动程序
|
||||
@ -507,3 +681,129 @@ pub enum BusNotifyEvent {
|
||||
/// 驱动绑定失败
|
||||
DriverNotBound,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BusDriverKType;
|
||||
|
||||
impl KObjType for BusDriverKType {
|
||||
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
|
||||
Some(&BusDriverSysFSOps)
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BusDriverSysFSOps;
|
||||
|
||||
impl SysFSOps for BusDriverSysFSOps {
|
||||
#[inline]
|
||||
fn show(
|
||||
&self,
|
||||
kobj: Arc<dyn KObject>,
|
||||
attr: &dyn Attribute,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
attr.show(kobj, buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn store(
|
||||
&self,
|
||||
kobj: Arc<dyn KObject>,
|
||||
attr: &dyn Attribute,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
attr.store(kobj, buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DriverAttrUnbind;
|
||||
|
||||
impl Attribute for DriverAttrUnbind {
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::from_bits_truncate(0o200)
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"unbind"
|
||||
}
|
||||
|
||||
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
let driver = kobj.cast::<dyn Driver>().map_err(|kobj| {
|
||||
kerror!(
|
||||
"Intertrait casting not implemented for kobj: {}",
|
||||
kobj.name()
|
||||
);
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
|
||||
|
||||
let s = CStr::from_bytes_with_nul(buf)
|
||||
.map_err(|_| SystemError::EINVAL)?
|
||||
.to_str()
|
||||
.map_err(|_| SystemError::EINVAL)?;
|
||||
let dev = bus.find_device_by_name(s).ok_or(SystemError::ENODEV)?;
|
||||
let p = dev.driver().ok_or(SystemError::ENODEV)?;
|
||||
if Arc::ptr_eq(&p, &driver) {
|
||||
device_manager().device_driver_detach(&dev);
|
||||
return Ok(buf.len());
|
||||
}
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::STORE
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DriverAttrBind;
|
||||
|
||||
impl Attribute for DriverAttrBind {
|
||||
fn name(&self) -> &str {
|
||||
"bind"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::from_bits_truncate(0o200)
|
||||
}
|
||||
|
||||
/*
|
||||
* Manually attach a device to a driver.
|
||||
* Note: the driver must want to bind to the device,
|
||||
* it is not possible to override the driver's id table.
|
||||
*/
|
||||
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
let driver = kobj.cast::<dyn Driver>().map_err(|kobj| {
|
||||
kerror!(
|
||||
"Intertrait casting not implemented for kobj: {}",
|
||||
kobj.name()
|
||||
);
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
|
||||
let device = bus
|
||||
.find_device_by_name(
|
||||
CStr::from_bytes_with_nul(buf)
|
||||
.map_err(|_| SystemError::EINVAL)?
|
||||
.to_str()
|
||||
.map_err(|_| SystemError::EINVAL)?,
|
||||
)
|
||||
.ok_or(SystemError::ENODEV)?;
|
||||
|
||||
if driver_manager().match_device(&driver, &device)? {
|
||||
device_manager().device_driver_attach(&driver, &device)?;
|
||||
return Ok(buf.len());
|
||||
}
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::STORE
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,26 @@
|
||||
use core::intrinsics::unlikely;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{string::ToString, sync::Arc};
|
||||
use intertrait::cast::CastArc;
|
||||
|
||||
use crate::{driver::Driver, syscall::SystemError};
|
||||
use crate::{
|
||||
driver::base::kobject::KObject,
|
||||
filesystem::{
|
||||
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
libs::wait_queue::WaitQueue,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{bus::BusNotifyEvent, driver::driver_manager, Device, DeviceManager};
|
||||
use super::{
|
||||
bus::BusNotifyEvent,
|
||||
device_manager,
|
||||
driver::{driver_manager, Driver, DriverManager},
|
||||
Device, DeviceManager,
|
||||
};
|
||||
|
||||
static PROBE_WAIT_QUEUE: WaitQueue = WaitQueue::INIT;
|
||||
|
||||
impl DeviceManager {
|
||||
/// 尝试把一个设备与一个驱动匹配
|
||||
@ -40,7 +56,8 @@ impl DeviceManager {
|
||||
allow_async: bool,
|
||||
) -> Result<bool, SystemError> {
|
||||
if unlikely(allow_async) {
|
||||
todo!("do_device_attach: allow_async")
|
||||
// todo!("do_device_attach: allow_async")
|
||||
kwarn!("do_device_attach: allow_async is true, but currently not supported");
|
||||
}
|
||||
if dev.is_dead() {
|
||||
return Ok(false);
|
||||
@ -64,7 +81,7 @@ impl DeviceManager {
|
||||
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
|
||||
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
|
||||
let mut flag = true;
|
||||
for driver in bus.subsystem().drivers().read().iter() {
|
||||
for driver in bus.subsystem().drivers().iter() {
|
||||
if let Some(driver) = driver.upgrade() {
|
||||
let r = self.do_device_attach_driver(&driver, &mut data);
|
||||
if unlikely(r.is_err()) {
|
||||
@ -142,7 +159,7 @@ impl DeviceManager {
|
||||
let r = driver_manager().driver_sysfs_add(dev);
|
||||
if let Err(e) = r {
|
||||
self.device_links_force_bind(dev);
|
||||
self.driver_bound(dev);
|
||||
driver_manager().driver_bound(dev);
|
||||
return Err(e);
|
||||
} else {
|
||||
if let Some(bus) = dev.bus() {
|
||||
@ -156,9 +173,10 @@ impl DeviceManager {
|
||||
return r;
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
|
||||
fn driver_bound(&self, _dev: &Arc<dyn Device>) {
|
||||
todo!("driver_bound")
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528
|
||||
fn unbind_cleanup(&self, dev: &Arc<dyn Device>) {
|
||||
dev.set_driver(None);
|
||||
// todo: 添加更多操作,清理数据
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,3 +226,368 @@ impl DeviceAttachData {
|
||||
self.have_async = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl DriverManager {
|
||||
/// 尝试把驱动绑定到现有的设备上
|
||||
///
|
||||
/// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。
|
||||
/// 一旦有一个设备匹配成功,就会返回,并且设备的driver字段会被设置。
|
||||
pub fn driver_attach(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
|
||||
for dev in bus.subsystem().devices().iter() {
|
||||
if let Some(dev) = dev.upgrade() {
|
||||
if self.do_driver_attach(&dev, &driver) {
|
||||
// 匹配成功
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#1134
|
||||
fn do_driver_attach(&self, device: &Arc<dyn Device>, driver: &Arc<dyn Driver>) -> bool {
|
||||
let r = self.match_device(driver, device).unwrap_or(false);
|
||||
if r == false {
|
||||
// 不匹配
|
||||
return false;
|
||||
}
|
||||
|
||||
if driver.allows_async_probing() {
|
||||
unimplemented!(
|
||||
"do_driver_attach: probe driver '{}' asynchronously",
|
||||
driver.name()
|
||||
);
|
||||
}
|
||||
|
||||
if self.probe_device(driver, device).is_err() {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn match_device(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
device: &Arc<dyn Device>,
|
||||
) -> Result<bool, SystemError> {
|
||||
return driver.bus().unwrap().match_device(device, driver);
|
||||
}
|
||||
|
||||
/// 尝试把设备和驱动绑定在一起
|
||||
///
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - Ok(): 绑定成功
|
||||
/// - Err(ENODEV): 设备未注册
|
||||
/// - Err(EBUSY): 设备已经绑定到驱动上
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#802
|
||||
fn probe_device(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
device: &Arc<dyn Device>,
|
||||
) -> Result<(), SystemError> {
|
||||
let r = self.do_probe_device(driver, device);
|
||||
PROBE_WAIT_QUEUE.wakeup_all(None);
|
||||
return r;
|
||||
}
|
||||
|
||||
fn do_probe_device(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
device: &Arc<dyn Device>,
|
||||
) -> Result<(), SystemError> {
|
||||
if device.is_dead() || (!device.is_registered()) {
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
if device.driver().is_some() {
|
||||
return Err(SystemError::EBUSY);
|
||||
}
|
||||
|
||||
device.set_can_match(true);
|
||||
|
||||
self.really_probe(driver, device)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#584
|
||||
fn really_probe(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
device: &Arc<dyn Device>,
|
||||
) -> Result<(), SystemError> {
|
||||
let bind_failed = || {
|
||||
device_manager().unbind_cleanup(device);
|
||||
};
|
||||
|
||||
let sysfs_failed = || {
|
||||
if let Some(bus) = device.bus() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::DriverNotBound,
|
||||
Some(device),
|
||||
None,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let probe_failed = || {
|
||||
self.remove_from_sysfs(device);
|
||||
};
|
||||
|
||||
let dev_groups_failed = || {
|
||||
device_manager().remove(device);
|
||||
};
|
||||
|
||||
device.set_driver(Some(Arc::downgrade(driver)));
|
||||
|
||||
self.add_to_sysfs(device).map_err(|e| {
|
||||
kerror!(
|
||||
"really_probe: add_to_sysfs failed, dev: '{}', err: {:?}",
|
||||
device.name(),
|
||||
e
|
||||
);
|
||||
sysfs_failed();
|
||||
bind_failed();
|
||||
e
|
||||
})?;
|
||||
|
||||
self.call_driver_probe(device, driver).map_err(|e| {
|
||||
kerror!(
|
||||
"really_probe: call_driver_probe failed, dev: '{}', err: {:?}",
|
||||
device.name(),
|
||||
e
|
||||
);
|
||||
|
||||
probe_failed();
|
||||
sysfs_failed();
|
||||
bind_failed();
|
||||
e
|
||||
})?;
|
||||
|
||||
device_manager()
|
||||
.add_groups(device, driver.dev_groups())
|
||||
.map_err(|e| {
|
||||
kerror!(
|
||||
"really_probe: add_groups failed, dev: '{}', err: {:?}",
|
||||
device.name(),
|
||||
e
|
||||
);
|
||||
dev_groups_failed();
|
||||
probe_failed();
|
||||
sysfs_failed();
|
||||
bind_failed();
|
||||
e
|
||||
})?;
|
||||
|
||||
// 我们假设所有的设备都有sync_state这个属性。如果没有的话,也创建属性文件。
|
||||
device_manager()
|
||||
.create_file(device, &DeviceAttrStateSynced)
|
||||
.map_err(|e| {
|
||||
kerror!(
|
||||
"really_probe: create_file failed, dev: '{}', err: {:?}",
|
||||
device.name(),
|
||||
e
|
||||
);
|
||||
dev_groups_failed();
|
||||
probe_failed();
|
||||
sysfs_failed();
|
||||
bind_failed();
|
||||
e
|
||||
})?;
|
||||
|
||||
self.driver_bound(device);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#434
|
||||
fn add_to_sysfs(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let driver = device.driver().ok_or(SystemError::EINVAL)?;
|
||||
|
||||
if let Some(bus) = device.bus() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::BindDriver,
|
||||
Some(&device),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
let driver_kobj = driver.clone() as Arc<dyn KObject>;
|
||||
let device_kobj = device.clone() as Arc<dyn KObject>;
|
||||
|
||||
sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device.name())?;
|
||||
|
||||
let fail_rm_dev_link = || {
|
||||
sysfs_instance().remove_link(&driver_kobj, device.name());
|
||||
};
|
||||
|
||||
sysfs_instance()
|
||||
.create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
|
||||
.map_err(|e| {
|
||||
fail_rm_dev_link();
|
||||
e
|
||||
})?;
|
||||
|
||||
device_manager()
|
||||
.create_file(device, &DeviceAttrCoredump)
|
||||
.map_err(|e| {
|
||||
sysfs_instance().remove_link(&device_kobj, "driver".to_string());
|
||||
fail_rm_dev_link();
|
||||
e
|
||||
})?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#469
|
||||
fn remove_from_sysfs(&self, _device: &Arc<dyn Device>) {
|
||||
todo!("remove_from_sysfs")
|
||||
}
|
||||
|
||||
fn call_driver_probe(
|
||||
&self,
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<(), SystemError> {
|
||||
let bus = device.bus().ok_or(SystemError::EINVAL)?;
|
||||
let r = bus.probe(device);
|
||||
if r == Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) {
|
||||
kerror!(
|
||||
"call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}",
|
||||
device.name(),
|
||||
r
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
if r.is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let err = r.unwrap_err();
|
||||
match err {
|
||||
SystemError::ENODEV | SystemError::ENXIO => {
|
||||
kdebug!(
|
||||
"driver'{}': probe of {} rejects match {:?}",
|
||||
driver.name(),
|
||||
device.name(),
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
_ => {
|
||||
kwarn!(
|
||||
"driver'{}': probe of {} failed with error {:?}",
|
||||
driver.name(),
|
||||
device.name(),
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
/// 当设备被成功探测,进行了'设备->驱动'绑定后,调用这个函数,完成'驱动->设备'的绑定
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#393
|
||||
fn driver_bound(&self, device: &Arc<dyn Device>) {
|
||||
if self.driver_is_bound(device) {
|
||||
kwarn!("driver_bound: device '{}' is already bound.", device.name());
|
||||
return;
|
||||
}
|
||||
|
||||
let driver = device.driver().unwrap();
|
||||
driver.add_device(device.clone());
|
||||
|
||||
if let Some(bus) = device.bus() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::BoundDriver,
|
||||
Some(device),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
// todo: 发送kobj bind的uevent
|
||||
}
|
||||
|
||||
fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {
|
||||
if let Some(driver) = device.driver() {
|
||||
if driver.find_device_by_name(&device.name()).is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 设备文件夹下的`dev`文件的属性
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct DeviceAttrStateSynced;
|
||||
|
||||
impl Attribute for DeviceAttrStateSynced {
|
||||
fn mode(&self) -> ModeType {
|
||||
// 0o444
|
||||
return ModeType::S_IRUGO;
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"state_synced"
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
|
||||
kerror!(
|
||||
"Intertrait casting not implemented for kobj: {}",
|
||||
kobj.name()
|
||||
);
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let val = dev.state_synced();
|
||||
let val = if val { 1 } else { 0 };
|
||||
return sysfs_emit_str(buf, format!("{}\n", val).as_str());
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DeviceAttrCoredump;
|
||||
|
||||
impl Attribute for DeviceAttrCoredump {
|
||||
fn name(&self) -> &str {
|
||||
"coredump"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::from_bits_truncate(0o200)
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
|
||||
kerror!(
|
||||
"Intertrait casting not implemented for kobj: {}",
|
||||
kobj.name()
|
||||
);
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let drv = dev.driver().ok_or(SystemError::EINVAL)?;
|
||||
drv.coredump(&dev)?;
|
||||
|
||||
return Ok(buf.len());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
use super::Device;
|
||||
use crate::syscall::SystemError;
|
||||
use alloc::sync::Arc;
|
||||
use super::{
|
||||
bus::{bus_manager, Bus},
|
||||
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
||||
};
|
||||
use crate::{
|
||||
driver::base::kobject::KObject,
|
||||
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
||||
syscall::SystemError,
|
||||
};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::fmt::Debug;
|
||||
|
||||
/// @brief: Driver error
|
||||
@ -31,13 +38,278 @@ pub fn driver_manager() -> &'static DriverManager {
|
||||
&DriverManager
|
||||
}
|
||||
|
||||
/// 驱动程序应当实现的trait
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Driver>,
|
||||
/// 因此,所有的实现了 Driver trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Driver)]`,
|
||||
/// 否则在运行时会报错
|
||||
pub trait Driver: Sync + Send + Debug + KObject {
|
||||
fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
|
||||
}
|
||||
|
||||
/// @brief: 获取驱动标识符
|
||||
/// @parameter: None
|
||||
/// @return: 该驱动驱动唯一标识符
|
||||
fn id_table(&self) -> Option<IdTable>;
|
||||
|
||||
fn devices(&self) -> Vec<Arc<dyn Device>>;
|
||||
|
||||
/// 把设备加入当前驱动管理的列表中
|
||||
fn add_device(&self, device: Arc<dyn Device>);
|
||||
|
||||
/// 从当前驱动管理的列表中删除设备
|
||||
fn delete_device(&self, device: &Arc<dyn Device>);
|
||||
|
||||
/// 根据设备名称查找绑定到驱动的设备
|
||||
///
|
||||
/// 该方法是一个快速查找方法,要求驱动开发者自行实现。
|
||||
///
|
||||
/// 如果开发者没有实现该方法,则应当返回None
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 这是一个内部方法,不应当被外部调用,若要查找设备,请使用`find_device_by_name()`
|
||||
fn __find_device_by_name_fast(&self, _name: &str) -> Option<Arc<dyn Device>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// 是否禁用sysfs的bind/unbind属性
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - true: 禁用
|
||||
/// - false: 不禁用(默认)
|
||||
fn suppress_bind_attrs(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
|
||||
|
||||
fn groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
&[]
|
||||
}
|
||||
|
||||
/// 使用什么样的策略来探测设备
|
||||
fn probe_type(&self) -> DriverProbeType {
|
||||
DriverProbeType::DefaultStrategy
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Driver {
|
||||
pub fn allows_async_probing(&self) -> bool {
|
||||
match self.probe_type() {
|
||||
DriverProbeType::PreferAsync => true,
|
||||
DriverProbeType::ForceSync => false,
|
||||
DriverProbeType::DefaultStrategy => {
|
||||
// todo: 判断是否请求异步探测,如果是的话,就返回true
|
||||
|
||||
// 由于目前还没有支持异步探测,因此这里暂时返回false
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据条件寻找一个绑定到这个驱动的设备(低效实现)
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `matcher` - 匹配器
|
||||
/// - `data` - 传给匹配器的数据
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
|
||||
fn find_device_slow<T: Copy>(
|
||||
&self,
|
||||
matcher: &dyn DeviceMatcher<T>,
|
||||
data: T,
|
||||
) -> Option<Arc<dyn Device>> {
|
||||
for dev in self.devices() {
|
||||
if matcher.match_device(&dev, data) {
|
||||
return Some(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
/// 根据设备名称查找绑定到驱动的设备
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 这里的默认实现很低效,请为特定的驱动自行实现高效的查询
|
||||
pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
|
||||
if let Some(r) = self.__find_device_by_name_fast(name) {
|
||||
return Some(r);
|
||||
}
|
||||
|
||||
return self.find_device_slow(&DeviceMatchName, name);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 驱动管理器
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DriverManager;
|
||||
|
||||
impl DriverManager {
|
||||
/// 注册设备驱动。该设备驱动应当已经设置好其bus字段
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - driver: 驱动
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/driver.c#222
|
||||
pub fn register(&self, driver: Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or_else(|| {
|
||||
kerror!(
|
||||
"DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
|
||||
driver.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
let drv_name = driver.name();
|
||||
let other = bus.find_driver_by_name(&drv_name);
|
||||
if other.is_some() {
|
||||
kerror!(
|
||||
"DriverManager::register() failed: driver '{}' already registered",
|
||||
drv_name
|
||||
);
|
||||
return Err(SystemError::EBUSY);
|
||||
}
|
||||
|
||||
bus_manager().add_driver(&driver)?;
|
||||
|
||||
self.add_groups(&driver, driver.groups()).map_err(|e| {
|
||||
bus_manager().remove_driver(&driver);
|
||||
e
|
||||
})?;
|
||||
|
||||
// todo: 发送uevent
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 从系统中删除一个驱动程序
|
||||
#[allow(dead_code)]
|
||||
pub fn unregister(&self, driver: &Arc<dyn Driver>) {
|
||||
self.remove_groups(driver, driver.groups());
|
||||
bus_manager().remove_driver(driver);
|
||||
}
|
||||
|
||||
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#434
|
||||
pub fn driver_sysfs_add(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!("DriverManager::driver_sysfs_add()");
|
||||
}
|
||||
|
||||
pub fn add_groups(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
groups: &'static [&dyn AttributeGroup],
|
||||
) -> Result<(), SystemError> {
|
||||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||||
return sysfs_instance().create_groups(&kobj, groups);
|
||||
}
|
||||
|
||||
pub fn remove_groups(&self, driver: &Arc<dyn Driver>, groups: &'static [&dyn AttributeGroup]) {
|
||||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||||
sysfs_instance().remove_groups(&kobj, groups);
|
||||
}
|
||||
|
||||
/// 为指定的驱动创建一个属性文件
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `driver` 要创建属性文件的驱动
|
||||
/// - `attr` 属性
|
||||
pub fn create_attr_file(
|
||||
&self,
|
||||
driver: &Arc<dyn Driver>,
|
||||
attr: &'static dyn Attribute,
|
||||
) -> Result<(), SystemError> {
|
||||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||||
return sysfs_instance().create_file(&kobj, attr);
|
||||
}
|
||||
|
||||
/// 为指定的驱动删除一个属性文件
|
||||
///
|
||||
/// 如果属性不存在,也不会报错
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `driver` 要删除属性文件的驱动
|
||||
/// - `attr` 属性
|
||||
pub fn remove_attr_file(&self, driver: &Arc<dyn Driver>, attr: &'static dyn Attribute) {
|
||||
let kobj = driver.clone() as Arc<dyn KObject>;
|
||||
sysfs_instance().remove_file(&kobj, attr);
|
||||
}
|
||||
}
|
||||
|
||||
/// 驱动匹配器
|
||||
///
|
||||
/// 用于匹配驱动是否符合某个条件
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `T` - 匹配器的数据类型
|
||||
/// - `data` - 匹配器的数据
|
||||
pub trait DriverMatcher<T>: Debug {
|
||||
fn match_driver(&self, driver: &Arc<dyn Driver>, data: T) -> bool;
|
||||
}
|
||||
|
||||
/// 根据名称匹配驱动
|
||||
#[derive(Debug)]
|
||||
pub struct DriverMatchName;
|
||||
|
||||
impl DriverMatcher<&str> for DriverMatchName {
|
||||
#[inline(always)]
|
||||
fn match_driver(&self, driver: &Arc<dyn Driver>, data: &str) -> bool {
|
||||
driver.name() == data
|
||||
}
|
||||
}
|
||||
|
||||
/// enum probe_type - device driver probe type to try
|
||||
/// Device drivers may opt in for special handling of their
|
||||
/// respective probe routines. This tells the core what to
|
||||
/// expect and prefer.
|
||||
///
|
||||
/// Note that the end goal is to switch the kernel to use asynchronous
|
||||
/// probing by default, so annotating drivers with
|
||||
/// %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
|
||||
/// to speed up boot process while we are validating the rest of the
|
||||
/// drivers.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum DriverProbeType {
|
||||
/// Used by drivers that work equally well
|
||||
/// whether probed synchronously or asynchronously.
|
||||
DefaultStrategy,
|
||||
|
||||
/// Drivers for "slow" devices which
|
||||
/// probing order is not essential for booting the system may
|
||||
/// opt into executing their probes asynchronously.
|
||||
PreferAsync,
|
||||
|
||||
/// Use this to annotate drivers that need
|
||||
/// their probe routines to run synchronously with driver and
|
||||
/// device registration (with the exception of -EPROBE_DEFER
|
||||
/// handling - re-probing always ends up being done asynchronously).
|
||||
ForceSync,
|
||||
}
|
||||
|
||||
impl Default for DriverProbeType {
|
||||
fn default() -> Self {
|
||||
DriverProbeType::DefaultStrategy
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,17 @@
|
||||
use alloc::{string::ToString, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
device::{
|
||||
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER,
|
||||
DEV_KSET_INSTANCE,
|
||||
},
|
||||
kobject::KObject,
|
||||
kset::KSet,
|
||||
driver::base::{
|
||||
device::{
|
||||
sys_dev_kset, DeviceManager, DEVICES_KSET_INSTANCE, DEVICE_MANAGER, DEV_KSET_INSTANCE,
|
||||
},
|
||||
uart::uart_device::uart_init,
|
||||
kobject::KObject,
|
||||
kset::KSet,
|
||||
},
|
||||
kdebug, kinfo,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
pub fn device_init() -> Result<(), SystemError> {
|
||||
uart_init()?;
|
||||
kinfo!("device init success");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn devices_init() -> Result<(), SystemError> {
|
||||
// 创建 `/sys/devices` 目录
|
||||
{
|
||||
@ -73,6 +63,6 @@ pub fn devices_init() -> Result<(), SystemError> {
|
||||
}
|
||||
|
||||
kinfo!("devices init success");
|
||||
device_init()?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use intertrait::cast::CastArc;
|
||||
|
||||
@ -8,10 +8,12 @@ use crate::{
|
||||
driver::{
|
||||
acpi::glue::acpi_device_notify,
|
||||
base::map::{LockedDevsMap, LockedKObjMap},
|
||||
Driver,
|
||||
},
|
||||
filesystem::{
|
||||
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
|
||||
sysfs::{
|
||||
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
|
||||
SysFSOpsSupport,
|
||||
},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
syscall::SystemError,
|
||||
@ -19,12 +21,14 @@ use crate::{
|
||||
use core::fmt::Debug;
|
||||
use core::intrinsics::unlikely;
|
||||
|
||||
use self::bus::{bus_add_device, bus_probe_device, Bus};
|
||||
use self::{
|
||||
bus::{bus_add_device, bus_probe_device, Bus},
|
||||
driver::Driver,
|
||||
};
|
||||
|
||||
use super::{
|
||||
kobject::{KObjType, KObject, KObjectManager},
|
||||
kobject::{KObjType, KObject, KObjectManager, KObjectState},
|
||||
kset::KSet,
|
||||
platform::CompatibleTable,
|
||||
swnode::software_node_notify,
|
||||
};
|
||||
|
||||
@ -87,7 +91,7 @@ pub(self) fn sys_dev_char_kset() -> Arc<KSet> {
|
||||
/// ## 注意
|
||||
///
|
||||
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Device>,
|
||||
/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[[sync] Device]`,
|
||||
/// 因此,所有的实现了Device trait的结构体,都应该在结构体上方标注`#[cast_to([sync] Device)]`,
|
||||
///
|
||||
/// 否则在释放设备资源的时候,会由于无法转换为Arc<dyn Device>而导致资源泄露,并且release回调函数也不会被调用。
|
||||
pub trait Device: KObject {
|
||||
@ -117,13 +121,39 @@ pub trait Device: KObject {
|
||||
return None;
|
||||
}
|
||||
|
||||
/// 设置当前设备所属的总线
|
||||
///
|
||||
/// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Weak指针)
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
|
||||
|
||||
/// 返回已经与当前设备匹配好的驱动程序
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>>;
|
||||
|
||||
fn set_driver(&self, driver: Option<Arc<dyn Driver>>);
|
||||
fn set_driver(&self, driver: Option<Weak<dyn Driver>>);
|
||||
|
||||
/// 当前设备是否已经挂掉了
|
||||
fn is_dead(&self) -> bool;
|
||||
|
||||
/// 当前设备是否处于可以被匹配的状态
|
||||
///
|
||||
/// The device has matched with a driver at least once or it is in
|
||||
/// a bus (like AMBA) which can't check for matching drivers until
|
||||
/// other devices probe successfully.
|
||||
fn can_match(&self) -> bool;
|
||||
|
||||
fn set_can_match(&self, can_match: bool);
|
||||
|
||||
/// The hardware state of this device has been synced to match
|
||||
/// the software state of this device by calling the driver/bus
|
||||
/// sync_state() callback.
|
||||
fn state_synced(&self) -> bool;
|
||||
}
|
||||
|
||||
impl dyn Device {
|
||||
#[inline(always)]
|
||||
pub fn is_registered(&self) -> bool {
|
||||
self.kobj_state().contains(KObjectState::IN_SYSFS)
|
||||
}
|
||||
}
|
||||
|
||||
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
|
||||
@ -131,24 +161,13 @@ pub trait Device: KObject {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DevicePrivateData {
|
||||
id_table: IdTable,
|
||||
resource: Option<DeviceResource>,
|
||||
compatible_table: CompatibleTable,
|
||||
state: DeviceState,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl DevicePrivateData {
|
||||
pub fn new(
|
||||
id_table: IdTable,
|
||||
resource: Option<DeviceResource>,
|
||||
compatible_table: CompatibleTable,
|
||||
state: DeviceState,
|
||||
) -> Self {
|
||||
Self {
|
||||
id_table,
|
||||
resource,
|
||||
compatible_table,
|
||||
state,
|
||||
}
|
||||
pub fn new(id_table: IdTable, state: DeviceState) -> Self {
|
||||
Self { id_table, state }
|
||||
}
|
||||
|
||||
pub fn id_table(&self) -> &IdTable {
|
||||
@ -159,31 +178,11 @@ impl DevicePrivateData {
|
||||
self.state
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn resource(&self) -> Option<&DeviceResource> {
|
||||
self.resource.as_ref()
|
||||
}
|
||||
|
||||
pub fn compatible_table(&self) -> &CompatibleTable {
|
||||
&self.compatible_table
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, state: DeviceState) {
|
||||
self.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceResource {
|
||||
//可能会用来保存例如 IRQ PWM 内存地址等需要申请的资源,将来由资源管理器+Framework框架进行管理。
|
||||
}
|
||||
|
||||
impl Default for DeviceResource {
|
||||
fn default() -> Self {
|
||||
return Self {};
|
||||
}
|
||||
}
|
||||
|
||||
int_like!(DeviceNumber, usize);
|
||||
|
||||
impl Default for DeviceNumber {
|
||||
@ -225,6 +224,8 @@ impl DeviceNumber {
|
||||
self.0 & 0xff
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
||||
((major & 0xffffff) << 8) | (minor & 0xff)
|
||||
}
|
||||
@ -287,7 +288,7 @@ impl Default for IdTable {
|
||||
|
||||
// 以现在的模型,设备在加载到系统中就是已经初始化的状态了,因此可以考虑把这个删掉
|
||||
/// @brief: 设备当前状态
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum DeviceState {
|
||||
NotInitialized = 0,
|
||||
Initialized = 1,
|
||||
@ -465,6 +466,11 @@ impl DeviceManager {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#542
|
||||
fn remove(&self, _dev: &Arc<dyn Device>) {
|
||||
todo!("DeviceManager::remove")
|
||||
}
|
||||
|
||||
/// @brief: 获取设备
|
||||
/// @parameter id_table: 设备标识符,用于唯一标识该设备
|
||||
/// @return: 设备实例
|
||||
@ -521,10 +527,8 @@ impl DeviceManager {
|
||||
dev: &Arc<dyn Device>,
|
||||
attr_groups: &'static [&dyn AttributeGroup],
|
||||
) -> Result<(), SystemError> {
|
||||
let dev = dev.clone();
|
||||
let binding = dev.arc_any();
|
||||
let kobj: &Arc<dyn KObject> = binding.downcast_ref().unwrap();
|
||||
return sysfs_instance().create_groups(kobj, attr_groups);
|
||||
let kobj = dev.clone() as Arc<dyn KObject>;
|
||||
return sysfs_instance().create_groups(&kobj, attr_groups);
|
||||
}
|
||||
|
||||
/// 为设备在sysfs中创建属性文件
|
||||
@ -567,15 +571,15 @@ impl DeviceManager {
|
||||
let target_kobj = self.device_to_dev_kobj(dev);
|
||||
let name = dev.id_table().name();
|
||||
let current_kobj = dev.clone() as Arc<dyn KObject>;
|
||||
return sysfs_instance().create_link(¤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>`
|
||||
#[allow(dead_code)]
|
||||
fn remove_sys_dev_entry(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
fn remove_sys_dev_entry(&self, dev: &Arc<dyn Device>) {
|
||||
let kobj = self.device_to_dev_kobj(dev);
|
||||
let name = dev.id_table().name();
|
||||
return sysfs_instance().remove_link(&kobj, name);
|
||||
sysfs_instance().remove_link(&kobj, name);
|
||||
}
|
||||
|
||||
/// device_to_dev_kobj - select a /sys/dev/ directory for the device
|
||||
@ -595,6 +599,28 @@ impl DeviceManager {
|
||||
pub fn device_links_force_bind(&self, _dev: &Arc<dyn Device>) {
|
||||
todo!("device_links_force_bind")
|
||||
}
|
||||
|
||||
/// 把device对象的一些结构进行默认初始化
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_initialize#2976
|
||||
pub fn device_default_initialize(&self, dev: &Arc<dyn Device>) {
|
||||
dev.set_kset(Some(sys_devices_kset()));
|
||||
return;
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=29885&fi=1100#1100
|
||||
pub fn device_driver_attach(
|
||||
&self,
|
||||
_driver: &Arc<dyn Driver>,
|
||||
_dev: &Arc<dyn Device>,
|
||||
) -> Result<(), SystemError> {
|
||||
todo!("device_driver_attach")
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c?r=&mo=35401&fi=1313#1313
|
||||
pub fn device_driver_detach(&self, _dev: &Arc<dyn Device>) {
|
||||
todo!("device_driver_detach")
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 设备注册
|
||||
@ -633,7 +659,7 @@ impl Attribute for DeviceAttrDev {
|
||||
"dev"
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
|
||||
kerror!(
|
||||
"Intertrait casting not implemented for kobj: {}",
|
||||
@ -642,7 +668,10 @@ impl Attribute for DeviceAttrDev {
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
return Ok(dev.id_table().device_number().into());
|
||||
let device_number = dev.id_table().device_number();
|
||||
let s = format!("{}:{}\n", device_number.major(), device_number.minor());
|
||||
|
||||
return sysfs_emit_str(buf, &s);
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::syscall::SystemError;
|
||||
use crate::{driver::tty::tty_device::tty_init, syscall::SystemError};
|
||||
|
||||
use super::{
|
||||
class::classes_init,
|
||||
@ -15,5 +15,15 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
|
||||
firmware_init()?;
|
||||
hypervisor_init()?;
|
||||
platform_bus_init()?;
|
||||
|
||||
// 至此,已完成设备驱动模型的初始化
|
||||
// 接下来,初始化设备
|
||||
actual_device_init()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn actual_device_init() -> Result<(), SystemError> {
|
||||
tty_init()?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
|
||||
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>);
|
||||
|
||||
fn name(&self) -> String;
|
||||
|
||||
fn set_name(&self, name: String);
|
||||
@ -70,7 +72,7 @@ impl DowncastArc for dyn KObject {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait KObjType: Debug {
|
||||
pub trait KObjType: Debug + Send + Sync {
|
||||
fn release(&self, _kobj: Arc<dyn KObject>) {}
|
||||
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
|
||||
|
||||
@ -91,7 +93,8 @@ bitflags! {
|
||||
pub struct LockedKObjectState(RwLock<KObjectState>);
|
||||
|
||||
impl LockedKObjectState {
|
||||
pub const fn new(state: KObjectState) -> LockedKObjectState {
|
||||
pub fn new(state: Option<KObjectState>) -> LockedKObjectState {
|
||||
let state = state.unwrap_or(KObjectState::empty());
|
||||
LockedKObjectState(RwLock::new(state))
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ impl KSet {
|
||||
let r = Self {
|
||||
kobjects: RwLock::new(Vec::new()),
|
||||
inner: RwLock::new(InnerKSet::new(name)),
|
||||
kobj_state: LockedKObjectState::new(KObjectState::empty()),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
parent_data: RwLock::new(KSetParentData::new(None, None)),
|
||||
self_ref: Weak::default(),
|
||||
};
|
||||
@ -167,6 +167,10 @@ impl KObject for KSet {
|
||||
Some(&KSetKObjType)
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!("KSet::set_kobj_type")
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.parent_data.read().kset.clone()
|
||||
}
|
||||
|
@ -74,8 +74,6 @@ pub fn platform_bus_init() -> Result<(), SystemError> {
|
||||
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
||||
DevicePrivateData::new(
|
||||
IdTable::new("platform".to_string(), DeviceNumber::new(0)),
|
||||
None,
|
||||
CompatibleTable::new(vec!["platform"]),
|
||||
BusState::NotInitialized.into(),
|
||||
),
|
||||
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
||||
|
@ -2,31 +2,64 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use ida::IdAllocator;
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
device::{
|
||||
bus::{Bus, BusState},
|
||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
driver::base::{
|
||||
device::{
|
||||
bus::{Bus, BusState},
|
||||
device_manager,
|
||||
driver::Driver,
|
||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
Driver,
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{super::device::DeviceState, CompatibleTable};
|
||||
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
|
||||
|
||||
/// 平台设备id分配器
|
||||
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(i32::MAX as usize);
|
||||
|
||||
#[inline(always)]
|
||||
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
|
||||
&PlatformDeviceManager
|
||||
}
|
||||
|
||||
/// 没有平台设备id
|
||||
pub const PLATFORM_DEVID_NONE: i32 = -1;
|
||||
/// 请求自动分配这个平台设备id
|
||||
pub const PLATFORM_DEVID_AUTO: i32 = -2;
|
||||
|
||||
/// @brief: 实现该trait的设备实例应挂载在platform总线上,
|
||||
/// 同时应该实现Device trait
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||
pub trait PlatformDevice: Device {
|
||||
fn pdev_name(&self) -> &str;
|
||||
/// 返回平台设备id,以及这个id是否是自动生成的
|
||||
///
|
||||
/// 请注意,如果当前设备还没有id,应该返回
|
||||
/// (PLATFORM_DEVID_NONE, false)
|
||||
fn pdev_id(&self) -> (i32, bool) {
|
||||
(PLATFORM_DEVID_NONE, false)
|
||||
}
|
||||
|
||||
/// 设置平台设备id
|
||||
fn set_pdev_id(&self, id: i32);
|
||||
/// 设置id是否为自动分配
|
||||
fn set_pdev_id_auto(&self, id_auto: bool);
|
||||
|
||||
fn compatible_table(&self) -> CompatibleTable;
|
||||
/// @brief: 判断设备是否初始化
|
||||
/// @parameter: None
|
||||
@ -39,6 +72,54 @@ pub trait PlatformDevice: Device {
|
||||
fn set_state(&self, set_state: DeviceState);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformDeviceManager;
|
||||
|
||||
impl PlatformDeviceManager {
|
||||
/// platform_device_add - add a platform device to device hierarchy
|
||||
pub fn device_add(&self, pdev: Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
if pdev.parent().is_none() {
|
||||
pdev.set_parent(Some(Arc::downgrade(
|
||||
&(platform_bus_device() as Arc<dyn KObject>),
|
||||
)));
|
||||
}
|
||||
|
||||
pdev.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
|
||||
let id = pdev.pdev_id().0;
|
||||
match id {
|
||||
PLATFORM_DEVID_NONE => {
|
||||
pdev.set_name(format!("{}", pdev.pdev_name()));
|
||||
}
|
||||
PLATFORM_DEVID_AUTO => {
|
||||
let id = PLATFORM_DEVID_IDA.alloc().ok_or(SystemError::EOVERFLOW)?;
|
||||
pdev.set_pdev_id(id as i32);
|
||||
pdev.set_pdev_id_auto(true);
|
||||
pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0));
|
||||
}
|
||||
_ => {
|
||||
pdev.set_name(format!("{}.{}", pdev.pdev_name(), id));
|
||||
}
|
||||
}
|
||||
|
||||
// todo: 插入资源: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=platform_device_add#691
|
||||
let r = device_manager().add_device(pdev.clone() as Arc<dyn Device>);
|
||||
if r.is_ok() {
|
||||
pdev.set_state(DeviceState::Initialized);
|
||||
return Ok(()); // success
|
||||
} else {
|
||||
// failed
|
||||
let pdevid = pdev.pdev_id();
|
||||
if pdevid.1 {
|
||||
PLATFORM_DEVID_IDA.free(pdevid.0 as usize);
|
||||
pdev.set_pdev_id(PLATFORM_DEVID_AUTO);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct PlatformBusDevice {
|
||||
@ -56,7 +137,7 @@ impl PlatformBusDevice {
|
||||
) -> Arc<PlatformBusDevice> {
|
||||
return Arc::new(PlatformBusDevice {
|
||||
inner: SpinLock::new(InnerPlatformBusDevice::new(data, parent)),
|
||||
kobj_state: LockedKObjectState::new(KObjectState::empty()),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
});
|
||||
}
|
||||
|
||||
@ -101,18 +182,8 @@ impl PlatformBusDevice {
|
||||
let state = self.inner.lock().state;
|
||||
return state;
|
||||
}
|
||||
|
||||
// /// @brief:
|
||||
// /// @parameter: None
|
||||
// /// @return: 总线状态
|
||||
// #[inline]
|
||||
// #[allow(dead_code)]
|
||||
// fn set_driver(&self, driver: Option<Arc<LockedPlatformBusDriver>>) {
|
||||
// self.0.lock().driver = driver;
|
||||
// }
|
||||
}
|
||||
|
||||
/// @brief: platform总线
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InnerPlatformBusDevice {
|
||||
@ -125,14 +196,10 @@ pub struct InnerPlatformBusDevice {
|
||||
/// 当前设备挂载到的总线
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
/// 当前设备已经匹配的驱动
|
||||
driver: Option<Arc<dyn Driver>>,
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
}
|
||||
|
||||
/// @brief: platform方法集
|
||||
impl InnerPlatformBusDevice {
|
||||
/// @brief: 创建一个platform总线实例
|
||||
/// @parameter: None
|
||||
/// @return: platform总线实例
|
||||
pub fn new(data: DevicePrivateData, parent: Option<Weak<dyn KObject>>) -> Self {
|
||||
Self {
|
||||
data,
|
||||
@ -167,6 +234,10 @@ impl KObject for PlatformBusDevice {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!("platform_bus_device::set_kobj_type")
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
None
|
||||
}
|
||||
@ -218,8 +289,12 @@ impl Device for PlatformBusDevice {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
self.inner.lock().driver.clone()
|
||||
self.inner.lock().driver.clone()?.upgrade()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -227,7 +302,19 @@ impl Device for PlatformBusDevice {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_driver(&self, driver: Option<Arc<dyn Driver>>) {
|
||||
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||
self.inner.lock().driver = driver;
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,54 @@
|
||||
use crate::driver::{base::device::DevicePrivateData, Driver};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use super::{super::device::driver::DriverError, CompatibleTable};
|
||||
use crate::{
|
||||
driver::base::device::{
|
||||
bus::Bus,
|
||||
driver::{driver_manager, Driver},
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{platform_bus, platform_device::PlatformDevice};
|
||||
|
||||
lazy_static! {
|
||||
static ref PLATFORM_COMPAT_TABLE: CompatibleTable = CompatibleTable::new(vec!["platform"]);
|
||||
}
|
||||
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上,
|
||||
/// 同时应该实现Driver trait
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||
pub trait PlatformDriver: Driver {
|
||||
fn compatible_table(&self) -> CompatibleTable;
|
||||
/// @brief 探测设备
|
||||
/// @param data 设备初始拥有的基本信息
|
||||
fn probe(&self, data: DevicePrivateData) -> Result<(), DriverError> {
|
||||
if data.compatible_table().matches(&PLATFORM_COMPAT_TABLE) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(DriverError::UnsupportedOperation);
|
||||
}
|
||||
/// 检测设备是否能绑定到这个驱动
|
||||
///
|
||||
/// 如果能,则把设备的driver指向这个驱动。
|
||||
/// 请注意,这个函数不应该把driver加入驱动的devices列表,相关工作会在外部的函数里面处理。
|
||||
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn remove(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn shutdown(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn suspend(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn resume(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn platform_driver_manager() -> &'static PlatformDriverManager {
|
||||
&PlatformDriverManager
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformDriverManager;
|
||||
|
||||
impl PlatformDriverManager {
|
||||
/// 注册平台设备驱动
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=__platform_driver_register#861
|
||||
pub fn register(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), SystemError> {
|
||||
driver.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
return driver_manager().register(driver as Arc<dyn Driver>);
|
||||
}
|
||||
|
||||
/// 卸载平台设备驱动
|
||||
#[allow(dead_code)]
|
||||
pub fn unregister(&self, driver: &Arc<dyn PlatformDriver>) {
|
||||
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,26 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use intertrait::cast::CastArc;
|
||||
|
||||
use crate::{
|
||||
driver::base::{device::bus::Bus, kobject::KObject, subsys::SubSysPrivate},
|
||||
driver::{
|
||||
acpi::acpi_manager,
|
||||
base::{
|
||||
device::{bus::Bus, driver::Driver, Device},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
},
|
||||
filesystem::{
|
||||
sysfs::{Attribute, AttributeGroup},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{platform_device::PlatformDevice, platform_driver::PlatformDriver};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformBus {
|
||||
private: SubSysPrivate,
|
||||
@ -44,6 +55,92 @@ impl Bus for PlatformBus {
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.private;
|
||||
}
|
||||
|
||||
fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let drv = device.driver().ok_or(SystemError::EINVAL)?;
|
||||
let pdrv = drv.cast::<dyn PlatformDriver>().map_err(|_|{
|
||||
kerror!("PlatformBus::probe() failed: device.driver() is not a PlatformDriver. Device: '{:?}'", device.name());
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
let pdev = device.clone().cast::<dyn PlatformDevice>().map_err(|_| {
|
||||
kerror!(
|
||||
"PlatformBus::probe() failed: device is not a PlatformDevice. Device: '{:?}'",
|
||||
device.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
return pdrv.probe(&pdev);
|
||||
}
|
||||
|
||||
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn sync_state(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn shutdown(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
///
|
||||
/// match platform device to platform driver.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// * `device` - platform device
|
||||
/// * `driver` - platform driver
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - `Ok(true)` - 匹配成功
|
||||
/// - `Ok(false)` - 匹配失败
|
||||
/// - `Err(_)` - 由于内部错误导致匹配失败
|
||||
///
|
||||
/// Platform device IDs are assumed to be encoded like this:
|
||||
/// "<name><instance>", where <name> is a short description of the type of
|
||||
/// device, like "pci" or "floppy", and <instance> is the enumerated
|
||||
/// instance of the device, like '0' or '42'. Driver IDs are simply
|
||||
/// "<name>". So, extract the <name> from the platform_device structure,
|
||||
/// and compare it against the name of the driver. Return whether they match
|
||||
/// or not.
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c#1331
|
||||
///
|
||||
///
|
||||
fn match_device(
|
||||
&self,
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError> {
|
||||
// 尝试从 ACPI 中匹配
|
||||
if let Ok(x) = acpi_manager().driver_match_device(driver, device) {
|
||||
if x {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从 ID table 中匹配
|
||||
if let Some(drv_id_table) = driver.id_table() {
|
||||
let pdev = device
|
||||
.clone()
|
||||
.cast::<dyn PlatformDevice>()
|
||||
.map_err(|_| SystemError::EINVAL)?;
|
||||
if drv_id_table.name().eq(&pdev.name()) {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试根据设备名称匹配
|
||||
return Ok(device.name().eq(&driver.name()));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -10,14 +10,18 @@ use alloc::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::Driver,
|
||||
libs::{notifier::AtomicNotifierChain, rwlock::RwLock, spinlock::SpinLock},
|
||||
libs::{
|
||||
notifier::AtomicNotifierChain,
|
||||
rwlock::{RwLock, RwLockReadGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::{
|
||||
device::{
|
||||
bus::{Bus, BusNotifyEvent},
|
||||
driver::Driver,
|
||||
Device,
|
||||
},
|
||||
kset::KSet,
|
||||
@ -90,12 +94,12 @@ impl SubSysPrivate {
|
||||
*self.bus.lock() = bus;
|
||||
}
|
||||
|
||||
pub fn devices(&self) -> &RwLock<Vec<Weak<dyn Device>>> {
|
||||
return &self.devices;
|
||||
pub fn devices(&self) -> RwLockReadGuard<Vec<Weak<dyn Device>>> {
|
||||
return self.devices.read();
|
||||
}
|
||||
|
||||
pub fn drivers(&self) -> &RwLock<Vec<Weak<dyn Driver>>> {
|
||||
return &self.drivers;
|
||||
pub fn drivers(&self) -> RwLockReadGuard<Vec<Weak<dyn Driver>>> {
|
||||
return self.drivers.read();
|
||||
}
|
||||
|
||||
pub fn drivers_autoprobe(&self) -> bool {
|
||||
@ -136,6 +140,45 @@ impl SubSysPrivate {
|
||||
pub fn interfaces(&self) -> &'static [&'static dyn SubSysInterface] {
|
||||
return self.interfaces;
|
||||
}
|
||||
|
||||
pub fn add_driver_to_vec(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let mut drivers = self.drivers.write();
|
||||
let driver_weak = Arc::downgrade(driver);
|
||||
if drivers.iter().any(|d| d.ptr_eq(&driver_weak)) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
drivers.push(driver_weak);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn remove_driver_from_vec(&self, driver: &Arc<dyn Driver>) {
|
||||
let mut drivers = self.drivers.write();
|
||||
let driver_weak = Arc::downgrade(driver);
|
||||
let index = drivers.iter().position(|d| d.ptr_eq(&driver_weak));
|
||||
if let Some(index) = index {
|
||||
drivers.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_device_to_vec(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let mut devices = self.devices.write();
|
||||
let device_weak = Arc::downgrade(device);
|
||||
if devices.iter().any(|d| d.ptr_eq(&device_weak)) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
devices.push(device_weak);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn remove_device_from_vec(&self, device: &Arc<dyn Device>) {
|
||||
let mut devices = self.devices.write();
|
||||
let device_weak = Arc::downgrade(device);
|
||||
let index = devices.iter().position(|d| d.ptr_eq(&device_weak));
|
||||
if let Some(index) = index {
|
||||
devices.remove(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device.h#63
|
||||
|
@ -3,11 +3,12 @@ use crate::driver::base::block::block_device::{BlockDevice, BlockId};
|
||||
use crate::driver::base::block::disk_info::Partition;
|
||||
use crate::driver::base::block::SeekFrom;
|
||||
use crate::driver::base::device::bus::Bus;
|
||||
use crate::driver::base::device::driver::Driver;
|
||||
use crate::driver::base::device::{Device, DeviceType, IdTable};
|
||||
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
||||
use crate::driver::base::kset::KSet;
|
||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||
use crate::driver::Driver;
|
||||
|
||||
use crate::filesystem::kernfs::KernFSInode;
|
||||
use crate::filesystem::mbr::MbrDiskPartionTable;
|
||||
use crate::include::bindings::bindings::verify_area;
|
||||
@ -489,6 +490,10 @@ impl KObject for LockedAhciDisk {
|
||||
fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for LockedAhciDisk {
|
||||
@ -504,6 +509,10 @@ impl Device for LockedAhciDisk {
|
||||
todo!("LockedAhciDisk::bus()")
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||
todo!("LockedAhciDisk::set_bus()")
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
todo!("LockedAhciDisk::driver()")
|
||||
}
|
||||
@ -512,9 +521,21 @@ impl Device for LockedAhciDisk {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_driver(&self, _driver: Option<Arc<dyn Driver>>) {
|
||||
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
|
||||
todo!("LockedAhciDisk::set_driver()")
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for LockedAhciDisk {
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <common/printk.h>
|
||||
#include <driver/acpi/acpi.h>
|
||||
#include <exception/gate.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <exception/softirq.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
|
@ -6,50 +6,5 @@ pub mod net;
|
||||
pub mod pci;
|
||||
pub mod timers;
|
||||
pub mod tty;
|
||||
pub mod uart;
|
||||
pub mod video;
|
||||
pub mod virtio;
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use self::base::{
|
||||
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||
kobject::KObject,
|
||||
platform::CompatibleTable,
|
||||
};
|
||||
pub trait Driver: Sync + Send + Debug + KObject {
|
||||
/// @brief: 获取驱动匹配表
|
||||
/// @parameter: None
|
||||
/// @return: 驱动匹配表
|
||||
/// 对于不需要匹配,在系统初始化的时候就生成的设备,例如 PlatformBus 就不需要匹配表
|
||||
fn compatible_table(&self) -> CompatibleTable {
|
||||
//TODO 要完善每个 CompatibleTable ,将来要把这个默认实现删除
|
||||
return CompatibleTable::new(vec!["unknown"]);
|
||||
}
|
||||
|
||||
/// @brief 添加可支持的设备
|
||||
/// @parameter: device 新增的匹配项
|
||||
fn append_compatible_table(&self, _device: &CompatibleTable) -> Result<(), DriverError> {
|
||||
Err(DriverError::UnsupportedOperation)
|
||||
}
|
||||
|
||||
/// @brief 探测设备
|
||||
/// @param data 设备初始拥有的基本信息
|
||||
fn probe(&self, data: &DevicePrivateData) -> Result<(), DriverError>;
|
||||
|
||||
/// @brief 加载设备,包括检查资源可用性,和注册到相应的管理器中。
|
||||
/// @param data 设备初始拥有的信息
|
||||
/// @param resource 设备可能申请的资源(或者像伪设备不需要就为None)
|
||||
fn load(
|
||||
&self,
|
||||
data: DevicePrivateData,
|
||||
resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError>;
|
||||
|
||||
/// @brief: 获取驱动标识符
|
||||
/// @parameter: None
|
||||
/// @return: 该驱动驱动唯一标识符
|
||||
fn id_table(&self) -> IdTable;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use smoltcp::{
|
||||
|
||||
use crate::{libs::spinlock::SpinLock, syscall::SystemError};
|
||||
|
||||
use super::Driver;
|
||||
use super::base::device::driver::Driver;
|
||||
|
||||
pub mod virtio_net;
|
||||
|
||||
|
@ -11,11 +11,10 @@ use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
||||
use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
|
||||
kobject::KObject,
|
||||
device::{bus::Bus, driver::Driver, Device, IdTable},
|
||||
kobject::{KObjType, KObject, KObjectState},
|
||||
},
|
||||
virtio::virtio_impl::HalImpl,
|
||||
Driver,
|
||||
},
|
||||
kerror, kinfo,
|
||||
libs::spinlock::SpinLock,
|
||||
@ -245,19 +244,27 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
|
||||
}
|
||||
|
||||
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
||||
fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
|
||||
fn id_table(&self) -> Option<IdTable> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
_data: DevicePrivateData,
|
||||
_resource: Option<DeviceResource>,
|
||||
) -> Result<Arc<dyn Device>, DriverError> {
|
||||
fn add_device(&self, _device: Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
fn delete_device(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -372,7 +379,11 @@ impl<T: Transport + 'static> KObject for VirtioInterface<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
|
||||
fn set_kobj_state(&self, _state: KObjectState) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
|
||||
pub mod init;
|
||||
pub mod serial;
|
||||
pub mod tty_device;
|
||||
pub mod tty_driver;
|
||||
|
||||
bitflags! {
|
||||
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,
|
||||
};
|
||||
|
||||
use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
|
||||
use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
|
||||
|
||||
lazy_static! {
|
||||
/// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice>
|
||||
@ -283,17 +283,6 @@ impl TtyDevicePrivateData {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 导出到C的tty初始化函数
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_tty_init() -> i32 {
|
||||
let r = tty_init();
|
||||
if r.is_ok() {
|
||||
return 0;
|
||||
} else {
|
||||
return r.unwrap_err().to_posix_errno();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 初始化TTY设备
|
||||
pub fn tty_init() -> Result<(), SystemError> {
|
||||
let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
|
||||
@ -322,5 +311,6 @@ pub fn tty_init() -> Result<(), SystemError> {
|
||||
return Err(devfs_root_inode.unwrap_err());
|
||||
}
|
||||
|
||||
serial_init()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
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::{
|
||||
arch::MMArch,
|
||||
driver::uart::uart_device::c_uart_send_str,
|
||||
driver::uart::uart_device::UartPort::COM1,
|
||||
driver::tty::serial::serial8250::send_to_default_serial8250_port,
|
||||
include::bindings::bindings::{
|
||||
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
||||
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
|
||||
@ -226,7 +225,7 @@ impl VideoRefreshManager {
|
||||
.unwrap();
|
||||
|
||||
let init_text = "Video driver to map.\n\0";
|
||||
c_uart_send_str(COM1 as u16, init_text.as_ptr());
|
||||
send_to_default_serial8250_port(init_text.as_bytes());
|
||||
|
||||
//地址映射
|
||||
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||
@ -245,7 +244,7 @@ impl VideoRefreshManager {
|
||||
__MAMAGER = Some(result);
|
||||
|
||||
let init_text = "Video driver initialized.\n\0";
|
||||
c_uart_send_str(COM1 as u16, init_text.as_ptr());
|
||||
send_to_default_serial8250_port(init_text.as_bytes());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use core::{fmt::Debug, intrinsics::unlikely};
|
||||
use core::{cmp::min, fmt::Debug, intrinsics::unlikely};
|
||||
|
||||
use alloc::{
|
||||
string::String,
|
||||
@ -64,7 +64,7 @@ impl KernFS {
|
||||
(*ptr).self_ref = Arc::downgrade(&root_inode);
|
||||
}
|
||||
}
|
||||
root_inode.inner.lock().parent = Arc::downgrade(&root_inode);
|
||||
root_inode.inner.write().parent = Arc::downgrade(&root_inode);
|
||||
*root_inode.fs.write() = Arc::downgrade(&fs);
|
||||
return fs;
|
||||
}
|
||||
@ -88,9 +88,11 @@ impl KernFS {
|
||||
};
|
||||
let root_inode = Arc::new(KernFSInode {
|
||||
name: String::from(""),
|
||||
inner: SpinLock::new(InnerKernFSInode {
|
||||
inner: RwLock::new(InnerKernFSInode {
|
||||
parent: Weak::new(),
|
||||
metadata,
|
||||
symlink_target: None,
|
||||
symlink_target_absolute_path: None,
|
||||
}),
|
||||
self_ref: Weak::new(),
|
||||
fs: RwLock::new(Weak::new()),
|
||||
@ -106,7 +108,7 @@ impl KernFS {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KernFSInode {
|
||||
inner: SpinLock<InnerKernFSInode>,
|
||||
inner: RwLock<InnerKernFSInode>,
|
||||
/// 指向当前Inode所属的文件系统的弱引用
|
||||
fs: RwLock<Weak<KernFS>>,
|
||||
/// 指向自身的弱引用
|
||||
@ -129,6 +131,9 @@ pub struct InnerKernFSInode {
|
||||
|
||||
/// 当前inode的元数据
|
||||
metadata: Metadata,
|
||||
/// 符号链接指向的inode(仅当inode_type为SymLink时有效)
|
||||
symlink_target: Option<Weak<KernFSInode>>,
|
||||
symlink_target_absolute_path: Option<String>,
|
||||
}
|
||||
|
||||
impl IndexNode for KernFSInode {
|
||||
@ -151,7 +156,7 @@ impl IndexNode for KernFSInode {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||
return Ok(self.inner.lock().metadata.clone());
|
||||
return Ok(self.inner.read().metadata.clone());
|
||||
}
|
||||
|
||||
fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
|
||||
@ -214,7 +219,7 @@ impl IndexNode for KernFSInode {
|
||||
".." => {
|
||||
return Ok(self
|
||||
.inner
|
||||
.lock()
|
||||
.read()
|
||||
.parent
|
||||
.upgrade()
|
||||
.ok_or(SystemError::ENOENT)?);
|
||||
@ -300,6 +305,25 @@ impl IndexNode for KernFSInode {
|
||||
buf: &mut [u8],
|
||||
_data: &mut FilePrivateData,
|
||||
) -> Result<usize, SystemError> {
|
||||
if self.inode_type == KernInodeType::SymLink {
|
||||
let inner = self.inner.read();
|
||||
if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() {
|
||||
return Ok(0);
|
||||
}
|
||||
let len = min(len, buf.len());
|
||||
let len = min(
|
||||
len,
|
||||
inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset,
|
||||
);
|
||||
buf[0..len].copy_from_slice(
|
||||
&inner
|
||||
.symlink_target_absolute_path
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_bytes()[offset..offset + len],
|
||||
);
|
||||
return Ok(len);
|
||||
}
|
||||
if self.inode_type != KernInodeType::File {
|
||||
return Err(SystemError::EISDIR);
|
||||
}
|
||||
@ -344,6 +368,51 @@ impl IndexNode for KernFSInode {
|
||||
}
|
||||
|
||||
impl KernFSInode {
|
||||
pub fn new(
|
||||
parent: Option<Arc<KernFSInode>>,
|
||||
name: String,
|
||||
mut metadata: Metadata,
|
||||
inode_type: KernInodeType,
|
||||
private_data: Option<KernInodePrivateData>,
|
||||
callback: Option<&'static dyn KernFSCallback>,
|
||||
) -> Arc<KernFSInode> {
|
||||
metadata.file_type = inode_type.into();
|
||||
let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
|
||||
|
||||
let inode = Arc::new(KernFSInode {
|
||||
name,
|
||||
inner: RwLock::new(InnerKernFSInode {
|
||||
parent: parent.clone(),
|
||||
metadata,
|
||||
symlink_target: None,
|
||||
symlink_target_absolute_path: None,
|
||||
}),
|
||||
self_ref: Weak::new(),
|
||||
fs: RwLock::new(Weak::new()),
|
||||
private_data: SpinLock::new(private_data),
|
||||
callback,
|
||||
children: SpinLock::new(HashMap::new()),
|
||||
inode_type,
|
||||
});
|
||||
|
||||
{
|
||||
let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
|
||||
unsafe {
|
||||
(*ptr).self_ref = Arc::downgrade(&inode);
|
||||
}
|
||||
}
|
||||
if parent.strong_count() > 0 {
|
||||
let kernfs = parent
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.fs()
|
||||
.downcast_arc::<KernFS>()
|
||||
.expect("KernFSInode::new: parent is not a KernFS instance");
|
||||
*inode.fs.write() = Arc::downgrade(&kernfs);
|
||||
}
|
||||
return inode;
|
||||
}
|
||||
|
||||
/// 在当前inode下增加子目录
|
||||
///
|
||||
/// ## 参数
|
||||
@ -410,11 +479,15 @@ impl KernFSInode {
|
||||
private_data: Option<KernInodePrivateData>,
|
||||
callback: Option<&'static dyn KernFSCallback>,
|
||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||
let size = if file_type == KernInodeType::File {
|
||||
4096
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let size;
|
||||
match file_type {
|
||||
KernInodeType::Dir | KernInodeType::SymLink => {
|
||||
size = 0;
|
||||
}
|
||||
KernInodeType::File => {
|
||||
size = 4096;
|
||||
}
|
||||
}
|
||||
|
||||
let metadata = Metadata {
|
||||
size,
|
||||
@ -475,47 +548,35 @@ impl KernFSInode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
parent: Option<Arc<KernFSInode>>,
|
||||
/// add_link - create a symlink in kernfs
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `parent`: directory to create the symlink in
|
||||
/// - `name`: name of the symlink
|
||||
/// - `target`: target node for the symlink to point to
|
||||
///
|
||||
/// Returns the created node on success
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
|
||||
pub fn add_link(
|
||||
&self,
|
||||
name: String,
|
||||
mut metadata: Metadata,
|
||||
inode_type: KernInodeType,
|
||||
private_data: Option<KernInodePrivateData>,
|
||||
callback: Option<&'static dyn KernFSCallback>,
|
||||
) -> Arc<KernFSInode> {
|
||||
metadata.file_type = inode_type.into();
|
||||
let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
|
||||
|
||||
let inode = Arc::new(KernFSInode {
|
||||
target: &Arc<KernFSInode>,
|
||||
target_absolute_path: String,
|
||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||
// kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
|
||||
let inode = self.inner_create(
|
||||
name,
|
||||
inner: SpinLock::new(InnerKernFSInode {
|
||||
parent: parent.clone(),
|
||||
metadata,
|
||||
}),
|
||||
self_ref: Weak::new(),
|
||||
fs: RwLock::new(Weak::new()),
|
||||
private_data: SpinLock::new(private_data),
|
||||
callback,
|
||||
children: SpinLock::new(HashMap::new()),
|
||||
inode_type,
|
||||
});
|
||||
KernInodeType::SymLink,
|
||||
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
|
||||
{
|
||||
let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
|
||||
unsafe {
|
||||
(*ptr).self_ref = Arc::downgrade(&inode);
|
||||
}
|
||||
}
|
||||
if parent.strong_count() > 0 {
|
||||
let kernfs = parent
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.fs()
|
||||
.downcast_arc::<KernFS>()
|
||||
.expect("KernFSInode::new: parent is not a KernFS instance");
|
||||
*inode.fs.write() = Arc::downgrade(&kernfs);
|
||||
}
|
||||
return inode;
|
||||
inode.inner.write().symlink_target = Some(Arc::downgrade(target));
|
||||
inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
|
||||
return Ok(inode);
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
@ -523,13 +584,18 @@ impl KernFSInode {
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<Arc<KernFSInode>> {
|
||||
return self.inner.lock().parent.upgrade();
|
||||
return self.inner.read().parent.upgrade();
|
||||
}
|
||||
|
||||
pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
|
||||
return self.private_data.lock();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
|
||||
return self.inner.read().symlink_target.as_ref()?.upgrade();
|
||||
}
|
||||
|
||||
/// remove a kernfs_node recursively
|
||||
pub fn remove_recursive(&self) {
|
||||
let mut children = self.children.lock().drain().collect::<Vec<_>>();
|
||||
@ -552,6 +618,7 @@ impl KernFSInode {
|
||||
pub enum KernInodeType {
|
||||
Dir,
|
||||
File,
|
||||
SymLink,
|
||||
}
|
||||
|
||||
impl Into<FileType> for KernInodeType {
|
||||
@ -559,6 +626,7 @@ impl Into<FileType> for KernInodeType {
|
||||
match self {
|
||||
KernInodeType::Dir => FileType::Dir,
|
||||
KernInodeType::File => FileType::File,
|
||||
KernInodeType::SymLink => FileType::SymLink,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,14 @@ impl SysFS {
|
||||
) -> Result<(), SystemError> {
|
||||
for i in 0..groups.len() {
|
||||
let group = groups[i];
|
||||
if group.attrs().is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = self.do_create_group(kobj, group, update) {
|
||||
kerror!(
|
||||
"Failed to create group '{}', err={e:?}",
|
||||
group.name().unwrap_or("")
|
||||
);
|
||||
for j in (0..=i).rev() {
|
||||
self.remove_group(kobj, groups[j]).ok();
|
||||
}
|
||||
@ -98,6 +105,16 @@ impl SysFS {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn remove_groups(
|
||||
&self,
|
||||
kobj: &Arc<dyn KObject>,
|
||||
groups: &'static [&'static dyn AttributeGroup],
|
||||
) {
|
||||
for group in groups.iter() {
|
||||
self.remove_group(kobj, *group).ok();
|
||||
}
|
||||
}
|
||||
|
||||
/// 从一个kobject中移除一个group
|
||||
///
|
||||
/// This function removes a group of attributes from a kobject. The attributes
|
||||
@ -187,6 +204,10 @@ impl SysFS {
|
||||
}
|
||||
|
||||
if let Err(e) = e {
|
||||
kerror!(
|
||||
"Failed to create sysfs files for group '{}', err={e:?}",
|
||||
group.name().unwrap_or("")
|
||||
);
|
||||
self.group_remove_files(&parent, group);
|
||||
return Err(e);
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use alloc::{
|
||||
borrow::ToOwned,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{driver::base::kobject::KObject, syscall::SystemError};
|
||||
use crate::{
|
||||
driver::base::kobject::KObject, filesystem::kernfs::KernFSInode, syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::SysFS;
|
||||
|
||||
@ -9,18 +15,19 @@ impl SysFS {
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `kobj`: 要创建符号链接的kobject
|
||||
/// - `target`: 符号链接的目标(在目标目录下创建)
|
||||
/// - `kobj`: object whose directory we're creating the link in. (符号链接所在目录)
|
||||
/// 如果为None,则创建在sysfs的根目录下
|
||||
/// - `target`: object we're pointing to.
|
||||
/// - `name`: 符号链接的名称
|
||||
///
|
||||
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
|
||||
pub fn create_link(
|
||||
&self,
|
||||
_kobj: &Arc<dyn KObject>,
|
||||
_target: &Arc<dyn KObject>,
|
||||
_name: String,
|
||||
kobj: Option<&Arc<dyn KObject>>,
|
||||
target: &Arc<dyn KObject>,
|
||||
name: String,
|
||||
) -> Result<(), SystemError> {
|
||||
todo!("sysfs create link")
|
||||
return self.do_create_link(kobj, target, name, true);
|
||||
}
|
||||
|
||||
/// 在sysfs中删除一个符号链接
|
||||
@ -32,7 +39,67 @@ impl SysFS {
|
||||
///
|
||||
///
|
||||
/// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143
|
||||
pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) -> Result<(), SystemError> {
|
||||
pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) {
|
||||
todo!("sysfs remove link")
|
||||
}
|
||||
|
||||
fn do_create_link(
|
||||
&self,
|
||||
kobj: Option<&Arc<dyn KObject>>,
|
||||
target: &Arc<dyn KObject>,
|
||||
name: String,
|
||||
warn: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
let parent = if let Some(kobj) = kobj {
|
||||
kobj.inode()
|
||||
} else {
|
||||
Some(self.root_inode().clone())
|
||||
};
|
||||
|
||||
// 没有parent,返回错误
|
||||
let parent = parent.ok_or(SystemError::EFAULT)?;
|
||||
return self.do_create_link_sd(&parent, target, name, warn);
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#20
|
||||
fn do_create_link_sd(
|
||||
&self,
|
||||
inode: &Arc<KernFSInode>,
|
||||
target: &Arc<dyn KObject>,
|
||||
name: String,
|
||||
warn: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
let target_inode = target.inode().ok_or(SystemError::ENOENT)?;
|
||||
|
||||
let target_abs_path = "/sys".to_string() + &self.kernfs_path(&target_inode).to_owned();
|
||||
// let current_path = self.kernfs_path(inode);
|
||||
// kdebug!("sysfs: create link {} to {}", current_path, target_abs_path);
|
||||
|
||||
let kn = inode.add_link(name.clone(), &target_inode, target_abs_path);
|
||||
if kn.is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
let err = kn.unwrap_err();
|
||||
if warn && err == SystemError::EEXIST {
|
||||
self.warn_duplicate(inode, &name);
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
/// sysfs_create_link_sd - create symlink to a given object.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `inode`: 目录inode,在这个目录下创建符号链接
|
||||
/// - `target`: object we're pointing to.
|
||||
/// - `name`: 符号链接的名称
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn create_link_sd(
|
||||
&self,
|
||||
inode: &Arc<KernFSInode>,
|
||||
target: &Arc<dyn KObject>,
|
||||
name: String,
|
||||
) -> Result<(), SystemError> {
|
||||
return self.do_create_link_sd(inode, target, name, true);
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,9 @@ pub const DT_SOCK: u16 = 12;
|
||||
pub const DT_WHT: u16 = 14;
|
||||
pub const DT_MAX: u16 = 16;
|
||||
|
||||
/// vfs容许的最大的符号链接跳转次数
|
||||
pub const VFS_MAX_FOLLOW_SYMLINK_TIMES: usize = 8;
|
||||
|
||||
impl FileType {
|
||||
pub fn get_file_type_num(&self) -> u16 {
|
||||
return match self {
|
||||
|
@ -23,7 +23,7 @@ use super::{
|
||||
fcntl::{FcntlCommand, FD_CLOEXEC},
|
||||
file::{File, FileMode},
|
||||
utils::rsplit_path,
|
||||
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE,
|
||||
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
|
||||
};
|
||||
|
||||
pub const SEEK_SET: u32 = 0;
|
||||
@ -156,7 +156,8 @@ impl Syscall {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
}
|
||||
|
||||
let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
|
||||
let inode: Result<Arc<dyn IndexNode>, SystemError> =
|
||||
ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
|
||||
|
||||
let inode: Arc<dyn IndexNode> = if inode.is_err() {
|
||||
let errno = inode.unwrap_err();
|
||||
@ -344,13 +345,14 @@ impl Syscall {
|
||||
new_path = String::from("/");
|
||||
}
|
||||
}
|
||||
let inode = match ROOT_INODE().lookup(&new_path) {
|
||||
Err(e) => {
|
||||
kerror!("Change Directory Failed, Error = {:?}", e);
|
||||
return Err(SystemError::ENOENT);
|
||||
}
|
||||
Ok(i) => i,
|
||||
};
|
||||
let inode =
|
||||
match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) {
|
||||
Err(e) => {
|
||||
kerror!("Change Directory Failed, Error = {:?}", e);
|
||||
return Err(SystemError::ENOENT);
|
||||
}
|
||||
Ok(i) => i,
|
||||
};
|
||||
let metadata = inode.metadata()?;
|
||||
if metadata.file_type == FileType::Dir {
|
||||
proc.basic_mut().set_cwd(String::from(new_path));
|
||||
@ -730,7 +732,8 @@ impl Syscall {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
}
|
||||
|
||||
let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
|
||||
let inode: Result<Arc<dyn IndexNode>, SystemError> =
|
||||
ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
|
||||
|
||||
if inode.is_ok() {
|
||||
return Err(SystemError::EEXIST);
|
||||
@ -739,7 +742,8 @@ impl Syscall {
|
||||
let (filename, parent_path) = rsplit_path(path);
|
||||
|
||||
// 查找父目录
|
||||
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
|
||||
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE()
|
||||
.lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
|
||||
// 创建nod
|
||||
parent_inode.mknod(filename, mode, dev_t)?;
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
use super::init_intertrait;
|
||||
use super::{init_before_mem_init, init_intertrait};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_init_intertrait() {
|
||||
init_intertrait();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_init_before_mem_init() {
|
||||
init_before_mem_init();
|
||||
}
|
||||
|
@ -1,5 +1,17 @@
|
||||
use crate::{
|
||||
driver::{tty::init::tty_early_init, video::VideoRefreshManager},
|
||||
libs::lib_ui::screen_manager::scm_init,
|
||||
};
|
||||
|
||||
pub mod c_adapter;
|
||||
|
||||
fn init_intertrait() {
|
||||
intertrait::init_caster_map();
|
||||
}
|
||||
|
||||
/// 在内存管理初始化之前,执行的初始化
|
||||
fn init_before_mem_init() {
|
||||
tty_early_init().expect("tty early init failed");
|
||||
unsafe { VideoRefreshManager::video_init().ok() };
|
||||
scm_init();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![feature(asm_const)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_refs_to_cell)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(c_void_variant)]
|
||||
#![feature(drain_filter)]
|
||||
|
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 {
|
||||
Self::from(x)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn data(&self) -> $backing_type {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief 初始化屏幕管理模块
|
||||
*
|
||||
*/
|
||||
extern void scm_init();
|
||||
|
||||
/**
|
||||
* @brief 当内存管理单元被初始化之后,重新处理帧缓冲区问题
|
||||
*
|
||||
|
@ -8,8 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send_str, UartPort},
|
||||
video::video_refresh_manager,
|
||||
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||
},
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
mm::VirtAddr,
|
||||
@ -275,13 +274,12 @@ pub trait ScmUiFramework: Sync + Send + Debug {
|
||||
/// ## 调用时机
|
||||
///
|
||||
/// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
|
||||
#[no_mangle]
|
||||
pub extern "C" fn scm_init() {
|
||||
pub fn scm_init() {
|
||||
SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
|
||||
|
||||
textui_init_no_alloc();
|
||||
|
||||
c_uart_send_str(UartPort::COM1.to_u16(), "\nfinish_scm_init\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes());
|
||||
}
|
||||
|
||||
/// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上
|
||||
@ -381,10 +379,7 @@ pub fn scm_enable_put_to_window() {
|
||||
.enable()
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
if r.is_negative() {
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"scm_enable_put_to_window() failed.\n\0".as_ptr(),
|
||||
);
|
||||
send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -402,10 +397,7 @@ pub fn scm_disable_put_to_window() {
|
||||
.disable()
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
if r.is_negative() {
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"scm_disable_put_to_window() failed.\n\0".as_ptr(),
|
||||
);
|
||||
send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,7 +406,7 @@ pub fn scm_disable_put_to_window() {
|
||||
pub extern "C" fn scm_reinit() -> i32 {
|
||||
let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno());
|
||||
if r.is_negative() {
|
||||
c_uart_send_str(UartPort::COM1.to_u16(), "scm reinit failed.\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
|
||||
video::video_refresh_manager,
|
||||
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||
},
|
||||
kdebug, kinfo,
|
||||
libs::{
|
||||
@ -86,10 +85,7 @@ pub unsafe fn textui_framwork_init() {
|
||||
scm_register(textui_framework()).expect("register textui framework failed");
|
||||
kdebug!("textui framework init success");
|
||||
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"\ntext ui initialized\n\0".as_ptr(),
|
||||
);
|
||||
send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes());
|
||||
unsafe { TEXTUI_IS_INIT = true };
|
||||
} else {
|
||||
panic!("Try to init TEXTUI_FRAMEWORK twice!");
|
||||
@ -756,7 +752,7 @@ impl TextuiWindow {
|
||||
//进行换行操作
|
||||
if character == '\n' {
|
||||
// 换行时还需要输出\r
|
||||
c_uart_send(UartPort::COM1.to_u16(), b'\r');
|
||||
send_to_default_serial8250_port(&[b'\r']);
|
||||
if is_enable_window == true {
|
||||
self.textui_new_line()?;
|
||||
}
|
||||
@ -837,7 +833,7 @@ impl TextuiWindow {
|
||||
} else {
|
||||
// 输出其他字符
|
||||
|
||||
c_uart_send(UartPort::COM1.to_u16(), character as u8);
|
||||
send_to_default_serial8250_port(&[character as u8]);
|
||||
|
||||
if is_enable_window == true {
|
||||
if let TextuiVline::Chromatic(vline) =
|
||||
@ -902,10 +898,7 @@ impl TextUiFramework {
|
||||
impl ScmUiFramework for TextUiFramework {
|
||||
// 安装ui框架的回调函数
|
||||
fn install(&self) -> Result<i32, SystemError> {
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"\ntextui_install_handler\n\0".as_ptr(),
|
||||
);
|
||||
send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes());
|
||||
return Ok(0);
|
||||
}
|
||||
// 卸载ui框架的回调函数
|
||||
@ -1015,7 +1008,7 @@ pub fn textui_putchar(
|
||||
pub extern "C" fn rs_textui_init() -> i32 {
|
||||
let r = textui_init().unwrap_or_else(|e| e.to_posix_errno());
|
||||
if r.is_negative() {
|
||||
c_uart_send_str(UartPort::COM1.to_u16(), "textui init failed.\n\0".as_ptr());
|
||||
send_to_default_serial8250_port("textui init failed.\n\0".as_bytes());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send, UartPort},
|
||||
video::video_refresh_manager,
|
||||
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
@ -43,13 +42,12 @@ pub fn no_init_textui_putchar_window(
|
||||
if unlikely(character == '\0') {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
c_uart_send(UartPort::COM1.to_u16(), character as u8);
|
||||
send_to_default_serial8250_port(&[character as u8]);
|
||||
|
||||
// 进行换行操作
|
||||
if unlikely(character == '\n') {
|
||||
// 换行时还需要输出\r
|
||||
c_uart_send(UartPort::COM1.to_u16(), b'\r');
|
||||
send_to_default_serial8250_port(&[b'\r']);
|
||||
if is_put_to_window == true {
|
||||
NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
|
||||
NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
|
||||
|
@ -201,16 +201,25 @@ impl WaitQueue {
|
||||
let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
|
||||
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
|
||||
while let Some(to_wakeup) = guard.wait_list.pop_front() {
|
||||
let mut wake = false;
|
||||
if let Some(state) = state {
|
||||
if to_wakeup.sched_info().state() == state {
|
||||
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
|
||||
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
|
||||
});
|
||||
continue;
|
||||
wake = true;
|
||||
}
|
||||
} else {
|
||||
wake = true;
|
||||
}
|
||||
|
||||
if wake {
|
||||
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
|
||||
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
to_push_back.push(to_wakeup);
|
||||
}
|
||||
to_push_back.push(to_wakeup);
|
||||
}
|
||||
|
||||
for to_wakeup in to_push_back {
|
||||
guard.wait_list.push_back(to_wakeup);
|
||||
}
|
||||
|
@ -27,18 +27,16 @@
|
||||
#include "driver/mouse/ps2_mouse.h"
|
||||
#include "driver/multiboot2/multiboot2.h"
|
||||
#include <driver/timers/HPET/HPET.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <time/timer.h>
|
||||
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
|
||||
extern int rs_driver_init();
|
||||
extern int rs_tty_init();
|
||||
extern void rs_softirq_init();
|
||||
extern void rs_mm_init();
|
||||
extern int rs_video_init();
|
||||
extern void rs_kthread_init();
|
||||
extern void rs_init_intertrait();
|
||||
extern void rs_init_before_mem_init();
|
||||
|
||||
ul bsp_idt_size, bsp_gdt_size;
|
||||
|
||||
@ -72,10 +70,8 @@ void reload_idt()
|
||||
// 初始化系统各模块
|
||||
void system_initialize()
|
||||
{
|
||||
c_uart_init(COM1, 115200);
|
||||
rs_init_before_mem_init();
|
||||
|
||||
rs_video_init();
|
||||
scm_init();
|
||||
// 重新加载gdt和idt
|
||||
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
||||
|
||||
@ -131,7 +127,6 @@ void system_initialize()
|
||||
vfs_init();
|
||||
|
||||
rs_driver_init();
|
||||
rs_tty_init();
|
||||
|
||||
rs_kthread_init();
|
||||
io_mfence();
|
||||
|
@ -14,8 +14,11 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAX_PATH_LEN 4096
|
||||
|
||||
// 当前工作目录(在main_loop中初始化)
|
||||
char *shell_current_path = NULL;
|
||||
|
||||
/**
|
||||
* @brief shell 内建函数的主命令与处理函数的映射表
|
||||
*
|
||||
@ -181,16 +184,18 @@ int shell_cmd_cd(int argc, char **argv)
|
||||
if (ec == 0)
|
||||
{
|
||||
// 获取新的路径字符串
|
||||
char *new_path = (char *)malloc(dest_len + 2);
|
||||
memset(new_path, 0, dest_len + 2);
|
||||
strncpy(new_path, argv[1], dest_len);
|
||||
char *new_path = (char *)malloc(MAX_PATH_LEN);
|
||||
if (new_path==NULL) {
|
||||
goto fail;
|
||||
}
|
||||
memset(new_path, 0, MAX_PATH_LEN);
|
||||
getcwd(new_path, MAX_PATH_LEN);
|
||||
|
||||
// 释放原有的路径字符串的内存空间
|
||||
free(shell_current_path);
|
||||
|
||||
shell_current_path = new_path;
|
||||
|
||||
shell_current_path[dest_len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -216,7 +221,7 @@ int shell_cmd_cd(int argc, char **argv)
|
||||
|
||||
// 拼接出新的字符串
|
||||
char *new_path = (char *)malloc(new_len + 2);
|
||||
memset(new_path, 0, sizeof(new_path));
|
||||
memset(new_path, 0, new_len);
|
||||
strncpy(new_path, shell_current_path, current_dir_len);
|
||||
|
||||
if (current_dir_len > 1)
|
||||
@ -225,10 +230,16 @@ int shell_cmd_cd(int argc, char **argv)
|
||||
int x = chdir(new_path);
|
||||
if (x == 0) // 成功切换目录
|
||||
{
|
||||
free(new_path);
|
||||
free(shell_current_path);
|
||||
// printf("new_path=%s, newlen= %d\n", new_path, new_len);
|
||||
new_path[new_len + 1] = '\0';
|
||||
shell_current_path = new_path;
|
||||
|
||||
char * pwd = malloc(MAX_PATH_LEN);
|
||||
if (pwd==NULL) {
|
||||
goto fail;
|
||||
}
|
||||
memset(pwd, 0, MAX_PATH_LEN);
|
||||
getcwd(pwd, MAX_PATH_LEN);
|
||||
shell_current_path = pwd;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
|
@ -131,6 +131,7 @@ pid_t getpid(void);
|
||||
int dup(int fd);
|
||||
|
||||
int dup2(int ofd, int nfd);
|
||||
char *getcwd(char* buf, size_t size);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern "C" */
|
||||
|
@ -235,4 +235,9 @@ int dup(int fd)
|
||||
int dup2(int ofd, int nfd)
|
||||
{
|
||||
return syscall_invoke(SYS_DUP2, ofd, nfd, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
char *getcwd(char* buf, size_t size)
|
||||
{
|
||||
return syscall_invoke(SYS_GETCWD, buf, size, 0, 0, 0, 0, 0, 0);
|
||||
}
|
@ -50,6 +50,8 @@
|
||||
#define SYS_GETSOCKNAME 41 // 获取socket的名字
|
||||
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
|
||||
|
||||
#define SYS_GETCWD 48
|
||||
|
||||
/**
|
||||
* @brief 用户态系统调用函数
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user