完成与Linux兼容的Ntty (#517)

* 已经完成的功能:
- 写:printf能够正常在tty输出
- 读:与键盘驱动接上
- 信号: 能够正常通过ctrl向前台进程发送信号

* 支持目前的shell,改动printk使其与新版tty兼容。

* 删除原有tty文件夹,并更改新tty文件名

* 添加clear清屏程序

* 实现tty部分ioctl,更改部分问题
This commit is contained in:
GnoCiYeH
2024-02-26 15:27:19 +08:00
committed by GitHub
parent 9993c0fc61
commit 52da9a5937
62 changed files with 8843 additions and 928 deletions

View 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(());
}

View 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);
}
}
}

View File

@ -0,0 +1,297 @@
//! PIO的串口驱动
use core::{
hint::spin_loop,
sync::atomic::{AtomicBool, Ordering},
};
use alloc::sync::{Arc, Weak};
use crate::{
arch::{io::PortIOArch, CurrentPortIOArch},
driver::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);
}
}