mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 00:46:31 +00:00
完成与Linux兼容的Ntty (#517)
* 已经完成的功能: - 写:printf能够正常在tty输出 - 读:与键盘驱动接上 - 信号: 能够正常通过ctrl向前台进程发送信号 * 支持目前的shell,改动printk使其与新版tty兼容。 * 删除原有tty文件夹,并更改新tty文件名 * 添加clear清屏程序 * 实现tty部分ioctl,更改部分问题
This commit is contained in:
71
kernel/src/driver/serial/mod.rs
Normal file
71
kernel/src/driver/serial/mod.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use core::{fmt::Debug, sync::atomic::AtomicU32};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{driver::base::device::device_number::DeviceNumber, mm::VirtAddr};
|
||||
|
||||
use self::serial8250::serial8250_manager;
|
||||
|
||||
pub mod serial8250;
|
||||
|
||||
pub trait UartDriver: Debug + Send + Sync {
|
||||
fn device_number(&self) -> DeviceNumber;
|
||||
|
||||
/// 获取最大的设备数量
|
||||
fn max_devs_num(&self) -> i32;
|
||||
|
||||
// todo: 获取指向console的指针(在我们系统里面,将来可能是改进后的Textui Window)
|
||||
}
|
||||
|
||||
/// 串口端口应当实现的trait
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.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://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720
|
||||
#[allow(dead_code)]
|
||||
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(());
|
||||
}
|
539
kernel/src/driver/serial/serial8250/mod.rs
Normal file
539
kernel/src/driver/serial/serial8250/mod.rs
Normal file
@ -0,0 +1,539 @@
|
||||
use core::{
|
||||
any::Any,
|
||||
sync::atomic::{AtomicBool, AtomicI32, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device,
|
||||
DeviceKObjType, DeviceState, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
platform::{
|
||||
platform_device::{platform_device_manager, PlatformDevice},
|
||||
platform_driver::{platform_driver_manager, PlatformDriver},
|
||||
},
|
||||
},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/// 标记serial8250是否已经初始化
|
||||
static mut INITIALIZED: bool = false;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Serial8250Manager;
|
||||
|
||||
impl Serial8250Manager {
|
||||
/// 初始化串口设备(在内存管理初始化之前)
|
||||
pub fn early_init(&self) -> Result<(), SystemError> {
|
||||
// todo: riscv64: 串口设备初始化
|
||||
#[cfg(not(target_arch = "riscv64"))]
|
||||
serial8250_pio_port_early_init()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 初始化serial8250设备、驱动
|
||||
///
|
||||
/// 应当在设备驱动模型初始化之后调用这里
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.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);
|
||||
|
||||
serial8250_isa_dev.set_driver(Some(Arc::downgrade(
|
||||
&(serial8250_isa_driver.clone() as Arc<dyn Driver>),
|
||||
)));
|
||||
// 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;
|
||||
})?;
|
||||
|
||||
// 把驱动注册到platform总线
|
||||
platform_driver_manager()
|
||||
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
|
||||
|
||||
unsafe {
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 把uart端口与uart driver、uart device绑定
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.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://code.dragonos.org.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<Weak<dyn Bus>> {
|
||||
self.inner.read().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Weak<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(), None);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fn set_class(&self, _class: Option<Arc<dyn Class>>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
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>) {
|
||||
// 不允许修改
|
||||
}
|
||||
|
||||
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<Weak<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://code.dragonos.org.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<Weak<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)]
|
||||
#[allow(dead_code)]
|
||||
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 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.retain(|d| !Arc::ptr_eq(d, device));
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.read().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Weak<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]) {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
send_to_serial8250_pio_com1(s);
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
if unsafe { INITIALIZED } {
|
||||
todo!("riscv64: send_to_default_serial8250_port")
|
||||
} else {
|
||||
crate::arch::driver::sbi::console_putstr(s);
|
||||
}
|
||||
}
|
||||
}
|
297
kernel/src/driver/serial/serial8250/serial8250_pio.rs
Normal file
297
kernel/src/driver/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::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
|
||||
libs::rwlock::RwLock,
|
||||
};
|
||||
use system_error::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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user