feat: 添加serial console,支持non-graphic启动 (#947)

Signed-off-by: longjin <longjin@dragonos.org>
This commit is contained in:
LoGin 2024-10-01 11:35:48 +08:00 committed by GitHub
parent 103f13024b
commit d031d46fd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 780 additions and 292 deletions

View File

@ -91,6 +91,11 @@ write_diskimage-uefi:
# 不编译直接启动QEMU # 不编译直接启动QEMU
qemu: qemu:
sh -c "cd tools && bash run-qemu.sh --bios=legacy --display=window && cd .." sh -c "cd tools && bash run-qemu.sh --bios=legacy --display=window && cd .."
# 不编译直接启动QEMU,不显示图像
qemu-nographic:
sh -c "cd tools && bash run-qemu.sh --bios=legacy --display=nographic && cd .."
# 不编译直接启动QEMU(UEFI) # 不编译直接启动QEMU(UEFI)
qemu-uefi: qemu-uefi:
sh -c "cd tools && bash run-qemu.sh --bios=uefi --display=window && cd .." sh -c "cd tools && bash run-qemu.sh --bios=uefi --display=window && cd .."

View File

@ -242,6 +242,7 @@ make run-docker
- Docker编译并写入磁盘镜像,: `make docker` - Docker编译并写入磁盘镜像,: `make docker`
- Docker编译写入磁盘镜像并在QEMU中运行: `make run-docker` - Docker编译写入磁盘镜像并在QEMU中运行: `make run-docker`
- 不编译,直接从已有的磁盘镜像启动: `make qemu` - 不编译,直接从已有的磁盘镜像启动: `make qemu`
- 不编译,直接从已有的磁盘镜像启动(无图形模式): `make qemu-nographic`
- 清理编译产生的文件: `make clean` - 清理编译产生的文件: `make clean`
- 编译文档: `make docs` 需要手动安装sphinx以及docs下的`requirements.txt`中的依赖) - 编译文档: `make docs` 需要手动安装sphinx以及docs下的`requirements.txt`中的依赖)
- 清理文档: `make clean-docs` - 清理文档: `make clean-docs`

View File

@ -403,7 +403,7 @@ pub fn ioapic_init(ignore: &'static [IrqNumber]) {
} }
// 绑定irqchip // 绑定irqchip
for i in 32..256 { for i in IoApic::VECTOR_BASE as u32..256 {
let irq = IrqNumber::new(i); let irq = IrqNumber::new(i);
if ignore.contains(&irq) { if ignore.contains(&irq) {

View File

@ -58,7 +58,6 @@ macro_rules! interrupt_handler {
push rax push rax
mov rsi, {irqnum} mov rsi, {irqnum}
jmp x86_64_do_irq jmp x86_64_do_irq
// jmp do_IRQ
" "
), ),
irqnum = const($name), irqnum = const($name),

View File

@ -3,22 +3,27 @@ use core::{fmt::Debug, sync::atomic::AtomicU32};
use alloc::sync::Arc; use alloc::sync::Arc;
use system_error::SystemError; use system_error::SystemError;
use crate::{driver::base::device::device_number::DeviceNumber, mm::VirtAddr}; use crate::mm::VirtAddr;
use self::serial8250::serial8250_manager; use self::serial8250::serial8250_manager;
use super::tty::{
termios::{ControlMode, InputMode, LocalMode, OutputMode, Termios, INIT_CONTORL_CHARACTERS},
tty_ldisc::LineDisciplineType,
};
pub mod serial8250; pub mod serial8250;
#[allow(dead_code)] #[allow(dead_code)]
pub trait UartDriver: Debug + Send + Sync { pub trait UartDriver: Debug + Send + Sync {
fn device_number(&self) -> DeviceNumber;
/// 获取最大的设备数量 /// 获取最大的设备数量
fn max_devs_num(&self) -> i32; fn max_devs_num(&self) -> i32;
// todo: 获取指向console的指针在我们系统里面将来可能是改进后的Textui Window // todo: 获取指向console的指针在我们系统里面将来可能是改进后的Textui Window
} }
pub const SERIAL_BAUDRATE: BaudRate = BaudRate::new(115200);
/// 串口端口应当实现的trait /// 串口端口应当实现的trait
/// ///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serial_core.h#428 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serial_core.h#428
@ -43,16 +48,41 @@ pub trait UartPort {
int_like!(BaudRate, AtomicBaudRate, u32, AtomicU32); int_like!(BaudRate, AtomicBaudRate, u32, AtomicU32);
int_like!(DivisorFraction, u32); int_like!(DivisorFraction, u32);
lazy_static! {
pub static ref TTY_SERIAL_DEFAULT_TERMIOS: Termios = {
Termios {
input_mode: InputMode::ICRNL | InputMode::IXON | InputMode::IUTF8,
output_mode: OutputMode::OPOST | OutputMode::ONLCR,
control_mode: ControlMode::B115200
| ControlMode::CREAD
| ControlMode::HUPCL
| ControlMode::CS8,
local_mode: LocalMode::ISIG
| LocalMode::ICANON
| LocalMode::ECHO
| LocalMode::ECHOE
| LocalMode::ECHOK
| LocalMode::ECHOCTL
| LocalMode::ECHOKE
| LocalMode::IEXTEN,
control_characters: INIT_CONTORL_CHARACTERS,
line: LineDisciplineType::NTty,
input_speed: SERIAL_BAUDRATE.data(),
output_speed: SERIAL_BAUDRATE.data(),
}
};
}
#[inline(always)] #[inline(always)]
#[allow(dead_code)] #[allow(dead_code)]
pub(super) fn uart_manager() -> &'static UartManager { pub(super) fn uart_manager() -> &'static UartManager {
&UartManager &UartManager
} }
#[derive(Debug)] #[derive(Debug)]
pub(super) struct UartManager; pub(super) struct UartManager;
impl UartManager { impl UartManager {
pub const NR_TTY_SERIAL_MAX: u32 = 128;
/// todo: 把uart设备注册到tty层 /// todo: 把uart设备注册到tty层
/// ///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720

View File

@ -12,27 +12,35 @@ use log::error;
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
driver::base::{ driver::{
class::Class, base::{
device::{ class::Class,
bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device, device::{
DeviceCommonData, DeviceKObjType, DeviceState, DeviceType, IdTable, bus::Bus, device_manager, device_number::Major, driver::Driver, Device,
}, DeviceCommonData, DeviceKObjType, DeviceState, DeviceType, IdTable,
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, },
kset::KSet, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
platform::{ kset::KSet,
platform_device::{platform_device_manager, PlatformDevice}, platform::{
platform_driver::{platform_driver_manager, PlatformDriver}, platform_device::{platform_device_manager, PlatformDevice},
platform_driver::{platform_driver_manager, PlatformDriver},
},
}, },
tty::tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType},
}, },
filesystem::kernfs::KernFSInode, filesystem::kernfs::KernFSInode,
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use self::serial8250_pio::{send_to_serial8250_pio_com1, serial8250_pio_port_early_init}; #[cfg(target_arch = "x86_64")]
use self::serial8250_pio::{
send_to_default_serial8250_pio_port, serial8250_pio_port_early_init,
serial_8250_pio_register_tty_devices, Serial8250PIOTtyDriverInner,
};
use super::{uart_manager, UartDriver, UartPort}; use super::{uart_manager, UartDriver, UartManager, UartPort, TTY_SERIAL_DEFAULT_TERMIOS};
#[cfg(target_arch = "x86_64")]
mod serial8250_pio; mod serial8250_pio;
static mut SERIAL8250_ISA_DEVICES: Option<Arc<Serial8250ISADevices>> = None; static mut SERIAL8250_ISA_DEVICES: Option<Arc<Serial8250ISADevices>> = None;
@ -62,6 +70,8 @@ static mut INITIALIZED: bool = false;
pub(super) struct Serial8250Manager; pub(super) struct Serial8250Manager;
impl Serial8250Manager { impl Serial8250Manager {
pub const TTY_SERIAL_MINOR_START: u32 = 64;
/// 初始化串口设备(在内存管理初始化之前) /// 初始化串口设备(在内存管理初始化之前)
pub fn early_init(&self) -> Result<(), SystemError> { pub fn early_init(&self) -> Result<(), SystemError> {
// todo: riscv64: 串口设备初始化 // todo: riscv64: 串口设备初始化
@ -109,6 +119,7 @@ impl Serial8250Manager {
return e; return e;
})?; })?;
self.serial_tty_init()?;
unsafe { unsafe {
INITIALIZED = true; INITIALIZED = true;
} }
@ -116,6 +127,34 @@ impl Serial8250Manager {
return Ok(()); return Ok(());
} }
#[cfg(target_arch = "riscv64")]
fn serial_tty_init(&self) -> Result<(), SystemError> {
Ok(())
}
#[cfg(target_arch = "x86_64")]
fn serial_tty_init(&self) -> Result<(), SystemError> {
let serial8250_tty_driver = TtyDriver::new(
UartManager::NR_TTY_SERIAL_MAX,
"ttyS",
0,
Major::TTY_MAJOR,
Self::TTY_SERIAL_MINOR_START,
TtyDriverType::Serial,
*TTY_SERIAL_DEFAULT_TERMIOS,
Arc::new(Serial8250PIOTtyDriverInner::new()),
None,
);
TtyDriverManager::tty_register_driver(serial8250_tty_driver)?;
if let Err(e) = serial_8250_pio_register_tty_devices() {
if e != SystemError::ENODEV {
return Err(e);
}
}
Ok(())
}
/// 把uart端口与uart driver、uart device绑定 /// 把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 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#553
@ -124,6 +163,7 @@ impl Serial8250Manager {
uart_driver: &Arc<Serial8250ISADriver>, uart_driver: &Arc<Serial8250ISADriver>,
devs: &Arc<Serial8250ISADevices>, devs: &Arc<Serial8250ISADevices>,
) { ) {
#[cfg(target_arch = "x86_64")]
self.bind_pio_ports(uart_driver, devs); self.bind_pio_ports(uart_driver, devs);
} }
@ -394,10 +434,6 @@ impl Serial8250ISADriver {
} }
impl UartDriver for Serial8250ISADriver { impl UartDriver for Serial8250ISADriver {
fn device_number(&self) -> DeviceNumber {
todo!()
}
fn max_devs_num(&self) -> i32 { fn max_devs_num(&self) -> i32 {
todo!() todo!()
} }
@ -522,7 +558,7 @@ impl KObject for Serial8250ISADriver {
/// 临时函数,用于向默认的串口发送数据 /// 临时函数,用于向默认的串口发送数据
pub fn send_to_default_serial8250_port(s: &[u8]) { pub fn send_to_default_serial8250_port(s: &[u8]) {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
send_to_serial8250_pio_com1(s); send_to_default_serial8250_pio_port(s);
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
{ {

View File

@ -5,11 +5,33 @@ use core::{
sync::atomic::{AtomicBool, Ordering}, sync::atomic::{AtomicBool, Ordering},
}; };
use alloc::sync::{Arc, Weak}; use alloc::{
string::ToString,
sync::{Arc, Weak},
};
use crate::{ use crate::{
arch::{io::PortIOArch, CurrentPortIOArch}, arch::{driver::apic::ioapic::IoApic, io::PortIOArch, CurrentPortIOArch},
driver::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort}, driver::{
base::device::{
device_number::{DeviceNumber, Major},
DeviceId,
},
serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
tty::{
kthread::send_to_tty_refresh_thread,
termios::WindowSize,
tty_core::{TtyCore, TtyCoreData},
tty_driver::{TtyDriver, TtyDriverManager, TtyOperation},
virtual_terminal::{vc_manager, VirtConsole},
},
},
exception::{
irqdata::IrqHandlerData,
irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
manage::irq_manager,
IrqNumber,
},
libs::rwlock::RwLock, libs::rwlock::RwLock,
}; };
use system_error::SystemError; use system_error::SystemError;
@ -19,6 +41,8 @@ use super::{Serial8250ISADevices, Serial8250ISADriver, Serial8250Manager, Serial
static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] = static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] =
[None, None, None, None, None, None, None, None]; [None, None, None, None, None, None, None, None];
const SERIAL_8250_PIO_IRQ: IrqNumber = IrqNumber::new(IoApic::VECTOR_BASE as u32 + 4);
impl Serial8250Manager { impl Serial8250Manager {
#[allow(static_mut_refs)] #[allow(static_mut_refs)]
pub(super) fn bind_pio_ports( pub(super) fn bind_pio_ports(
@ -34,7 +58,7 @@ impl Serial8250Manager {
} }
macro_rules! init_port { macro_rules! init_port {
($port_num:expr, $baudrate:expr) => { ($port_num:expr) => {
unsafe { unsafe {
let port = Serial8250PIOPort::new( let port = Serial8250PIOPort::new(
match $port_num { match $port_num {
@ -48,12 +72,17 @@ macro_rules! init_port {
8 => Serial8250PortBase::COM8, 8 => Serial8250PortBase::COM8,
_ => panic!("invalid port number"), _ => panic!("invalid port number"),
}, },
BaudRate::new($baudrate), crate::driver::serial::SERIAL_BAUDRATE,
); );
if let Ok(port) = port { if let Ok(port) = port {
if port.init().is_ok() { if port.init().is_ok() {
PIO_PORTS[$port_num - 1] = Some(port); PIO_PORTS[$port_num - 1] = Some(port);
true
} else {
false
} }
} else {
false
} }
} }
}; };
@ -62,8 +91,9 @@ macro_rules! init_port {
/// 在内存管理初始化之前,初始化串口设备 /// 在内存管理初始化之前,初始化串口设备
pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> { pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> {
for i in 1..=8 { for i in 1..=8 {
init_port!(i, 115200); init_port!(i);
} }
return Ok(()); return Ok(());
} }
@ -100,7 +130,6 @@ impl Serial8250PIOPort {
} }
let port = self.iobase as u16; let port = self.iobase as u16;
unsafe { unsafe {
CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts
self.set_divisor(self.baudrate.load(Ordering::SeqCst)) self.set_divisor(self.baudrate.load(Ordering::SeqCst))
@ -119,7 +148,9 @@ impl Serial8250PIOPort {
// If serial is not faulty set it in normal operation mode // If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
CurrentPortIOArch::out8(port + 4, 0x08); CurrentPortIOArch::out8(port + 4, 0x0b);
CurrentPortIOArch::out8(port + 1, 0x01); // Enable interrupts
} }
return Ok(()); return Ok(());
@ -168,13 +199,12 @@ impl Serial8250PIOPort {
} }
} }
/// 读取一个字节 /// 读取一个字节如果没有数据则返回None
#[allow(dead_code)] fn read_one_byte(&self) -> Option<u8> {
fn read_one_byte(&self) -> u8 { if !self.serial_received() {
while !self.serial_received() { return None;
spin_loop();
} }
return self.serial_in(0) as u8; return Some(self.serial_in(0) as u8);
} }
} }
@ -235,7 +265,14 @@ impl UartPort for Serial8250PIOPort {
} }
fn handle_irq(&self) -> Result<(), SystemError> { fn handle_irq(&self) -> Result<(), SystemError> {
todo!("serial8250_pio::handle_irq") if let Some(c) = self.read_one_byte() {
send_to_tty_refresh_thread(&[c]);
}
Ok(())
}
fn iobase(&self) -> Option<usize> {
Some(self.iobase as usize)
} }
} }
@ -280,8 +317,140 @@ pub enum Serial8250PortBase {
} }
/// 临时函数用于向COM1发送数据 /// 临时函数用于向COM1发送数据
pub fn send_to_serial8250_pio_com1(s: &[u8]) { pub fn send_to_default_serial8250_pio_port(s: &[u8]) {
if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } { if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } {
port.send_bytes(s); port.send_bytes(s);
} }
} }
#[derive(Debug)]
pub(super) struct Serial8250PIOTtyDriverInner;
impl Serial8250PIOTtyDriverInner {
pub fn new() -> Self {
Self
}
fn do_install(
&self,
driver: Arc<TtyDriver>,
tty: Arc<TtyCore>,
vc: Arc<VirtConsole>,
) -> Result<(), SystemError> {
driver.standard_install(tty.clone())?;
vc.port().setup_internal_tty(Arc::downgrade(&tty));
tty.set_port(vc.port());
vc.devfs_setup()?;
Ok(())
}
}
impl TtyOperation for Serial8250PIOTtyDriverInner {
fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
Ok(())
}
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
let index = tty.index();
if tty.index() >= unsafe { PIO_PORTS.len() } {
return Err(SystemError::ENODEV);
}
let pio_port = unsafe { PIO_PORTS[index].as_ref() }.ok_or(SystemError::ENODEV)?;
pio_port.send_bytes(&buf[..nr]);
Ok(nr)
}
fn flush_chars(&self, _tty: &TtyCoreData) {}
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
self.write(tty, &[ch], 1).map(|_| ())
}
fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
Err(SystemError::ENOIOCTLCMD)
}
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
Ok(())
}
fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
*tty.core().window_size_write() = winsize;
Ok(())
}
fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
if tty.core().index() >= unsafe { PIO_PORTS.len() } {
return Err(SystemError::ENODEV);
}
let vc = VirtConsole::new(None);
let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
self.do_install(driver, tty, vc.clone()).inspect_err(|_| {
vc_manager().free(vc_index);
})?;
Ok(())
}
}
pub(super) fn serial_8250_pio_register_tty_devices() -> Result<(), SystemError> {
let (_, driver) = TtyDriverManager::lookup_tty_driver(DeviceNumber::new(
Major::TTY_MAJOR,
Serial8250Manager::TTY_SERIAL_MINOR_START,
))
.ok_or(SystemError::ENODEV)?;
for (i, port) in unsafe { PIO_PORTS.iter() }.enumerate() {
if let Some(port) = port {
let core = driver.init_tty_device(Some(i)).inspect_err(|_| {
log::error!(
"failed to init tty device for serial 8250 pio port {}, port iobase: {:?}",
i,
port.iobase
);
})?;
core.resize( core.clone(), WindowSize::DEFAULT)
.inspect_err(|_| {
log::error!(
"failed to resize tty device for serial 8250 pio port {}, port iobase: {:?}",
i,
port.iobase
);
})?;
}
}
irq_manager()
.request_irq(
SERIAL_8250_PIO_IRQ,
"serial8250_pio".to_string(),
&Serial8250IrqHandler,
IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING,
Some(DeviceId::new(Some("serial8250_pio"), None).unwrap()),
)
.inspect_err(|e| {
log::error!("failed to request irq for serial 8250 pio: {:?}", e);
})?;
Ok(())
}
#[derive(Debug)]
struct Serial8250IrqHandler;
impl IrqHandler for Serial8250IrqHandler {
fn handle(
&self,
_irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
_dynamic_data: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
for port in unsafe { PIO_PORTS.iter() }.flatten() {
port.handle_irq()?;
}
Ok(IrqReturn::Handled)
}
}

View File

@ -1,13 +1,20 @@
use alloc::sync::Arc;
use system_error::SystemError; use system_error::SystemError;
use super::virtual_terminal::virtual_console::{ use super::virtual_terminal::{
CursorOperation, ScrollDir, VirtualConsoleData, VirtualConsoleIntensity, virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData, VirtualConsoleIntensity},
VirtConsole,
}; };
/// 终端切换相关的回调 /// 终端切换相关的回调
pub trait ConsoleSwitch: Sync + Send { pub trait ConsoleSwitch: Sync + Send {
/// 初始化会对vc_data进行一系列初始化操作 /// 初始化会对vc_data进行一系列初始化操作
fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError>; fn con_init(
&self,
vc: &Arc<VirtConsole>,
vc_data: &mut VirtualConsoleData,
init: bool,
) -> Result<(), SystemError>;
/// 进行释放等系列操作,目前未使用 /// 进行释放等系列操作,目前未使用
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -5,7 +5,7 @@ use kdepends::thingbuf::StaticThingBuf;
use crate::{ use crate::{
arch::CurrentIrqArch, arch::CurrentIrqArch,
driver::tty::virtual_terminal::virtual_console::CURRENT_VCNUM, driver::tty::virtual_terminal::vc_manager,
exception::InterruptArch, exception::InterruptArch,
process::{ process::{
kthread::{KernelThreadClosure, KernelThreadMechanism}, kthread::{KernelThreadClosure, KernelThreadMechanism},
@ -14,8 +14,6 @@ use crate::{
sched::{schedule, SchedMode}, sched::{schedule, SchedMode},
}; };
use super::tty_port::current_tty_port;
/// 用于缓存键盘输入的缓冲区 /// 用于缓存键盘输入的缓冲区
static KEYBUF: StaticThingBuf<u8, 512> = StaticThingBuf::new(); static KEYBUF: StaticThingBuf<u8, 512> = StaticThingBuf::new();
@ -51,8 +49,10 @@ fn tty_refresh_thread() -> i32 {
*item = KEYBUF.pop().unwrap(); *item = KEYBUF.pop().unwrap();
} }
if CURRENT_VCNUM.load(core::sync::atomic::Ordering::SeqCst) != -1 { if let Some(cur_vc) = vc_manager().current_vc() {
let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue); let _ = cur_vc
.port()
.receive_buf(&data[0..to_dequeue], &[], to_dequeue);
} else { } else {
// 这里由于stdio未初始化所以无法找到port // 这里由于stdio未初始化所以无法找到port
// TODO: 考虑改用双端队列,能够将丢失的输入插回 // TODO: 考虑改用双端队列,能够将丢失的输入插回

View File

@ -253,6 +253,7 @@ pub fn pty_init() -> Result<(), SystemError> {
TtyDriverType::Pty, TtyDriverType::Pty,
*TTY_STD_TERMIOS, *TTY_STD_TERMIOS,
Arc::new(Unix98PtyDriverInner::new()), Arc::new(Unix98PtyDriverInner::new()),
None,
); );
ptm_driver.set_subtype(TtyDriverSubType::PtyMaster); ptm_driver.set_subtype(TtyDriverSubType::PtyMaster);
let term = ptm_driver.init_termios_mut(); let term = ptm_driver.init_termios_mut();
@ -273,6 +274,7 @@ pub fn pty_init() -> Result<(), SystemError> {
TtyDriverType::Pty, TtyDriverType::Pty,
*TTY_STD_TERMIOS, *TTY_STD_TERMIOS,
Arc::new(Unix98PtyDriverInner::new()), Arc::new(Unix98PtyDriverInner::new()),
None,
); );
pts_driver.set_subtype(TtyDriverSubType::PtySlave); pts_driver.set_subtype(TtyDriverSubType::PtySlave);
let term = pts_driver.init_termios_mut(); let term = pts_driver.init_termios_mut();

View File

@ -263,7 +263,7 @@ pub fn ptmx_open(
let index = fsinfo.alloc_index()?; let index = fsinfo.alloc_index()?;
let tty = TtyDriver::init_tty_device(ptm_driver(), index)?; let tty = ptm_driver().init_tty_device(Some(index))?;
// 设置privdata // 设置privdata
*data = FilePrivateData::Tty(TtyFilePrivateData { *data = FilePrivateData::Tty(TtyFilePrivateData {

View File

@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType;
/// ## 窗口大小 /// ## 窗口大小
#[repr(C)] #[repr(C)]
#[derive(Debug, Default, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct WindowSize { pub struct WindowSize {
/// 行 /// 行
pub row: u16, pub row: u16,
@ -15,7 +15,8 @@ pub struct WindowSize {
} }
impl WindowSize { impl WindowSize {
pub fn new(row: u16, col: u16, xpixel: u16, ypixel: u16) -> Self { pub const DEFAULT: WindowSize = WindowSize::new(24, 80, 1, 1);
pub const fn new(row: u16, col: u16, xpixel: u16, ypixel: u16) -> Self {
Self { Self {
row, row,
col, col,
@ -25,6 +26,12 @@ impl WindowSize {
} }
} }
impl Default for WindowSize {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Termios { pub struct Termios {
pub input_mode: InputMode, pub input_mode: InputMode,
@ -63,7 +70,6 @@ impl PosixTermios {
} }
} }
#[allow(dead_code)]
pub fn to_kernel_termios(self) -> Termios { pub fn to_kernel_termios(self) -> Termios {
// TODO这里没有考虑非规范模式 // TODO这里没有考虑非规范模式
Termios { Termios {

View File

@ -11,7 +11,7 @@ use alloc::{
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
driver::{serial::serial8250::send_to_default_serial8250_port, tty::pty::ptm_driver}, driver::{base::device::device_number::DeviceNumber, tty::pty::ptm_driver},
libs::{ libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard}, rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard}, spinlock::{SpinLock, SpinLockGuard},
@ -25,13 +25,13 @@ use crate::{
use super::{ use super::{
termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize}, termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize},
tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation}, tty_driver::{TtyCorePrivateField, TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
tty_ldisc::{ tty_ldisc::{
ntty::{NTtyData, NTtyLinediscipline}, ntty::{NTtyData, NTtyLinediscipline},
TtyLineDiscipline, TtyLineDiscipline,
}, },
tty_port::TtyPort, tty_port::TtyPort,
virtual_terminal::{virtual_console::VirtualConsoleData, VIRT_CONSOLES}, virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData},
}; };
#[derive(Debug)] #[derive(Debug)]
@ -52,6 +52,9 @@ impl Drop for TtyCore {
impl TtyCore { impl TtyCore {
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> { pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
let name = driver.tty_line_name(index); let name = driver.tty_line_name(index);
let device_number = driver
.device_number(index)
.expect("Get tty device number failed.");
let termios = driver.init_termios(); let termios = driver.init_termios();
let core = TtyCoreData { let core = TtyCoreData {
tty_driver: driver, tty_driver: driver,
@ -64,11 +67,14 @@ impl TtyCore {
write_wq: EventWaitQueue::new(), write_wq: EventWaitQueue::new(),
port: RwLock::new(None), port: RwLock::new(None),
index, index,
vc_index: AtomicUsize::new(usize::MAX),
ctrl: SpinLock::new(TtyContorlInfo::default()), ctrl: SpinLock::new(TtyContorlInfo::default()),
closing: AtomicBool::new(false), closing: AtomicBool::new(false),
flow: SpinLock::new(TtyFlowState::default()), flow: SpinLock::new(TtyFlowState::default()),
link: RwLock::default(), link: RwLock::default(),
epitems: SpinLock::new(LinkedList::new()), epitems: SpinLock::new(LinkedList::new()),
device_number,
privete_fields: SpinLock::new(None),
}; };
return Arc::new(Self { return Arc::new(Self {
@ -84,6 +90,14 @@ impl TtyCore {
return &self.core; return &self.core;
} }
pub fn private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>> {
self.core.privete_fields.lock().clone()
}
pub fn set_private_fields(&self, fields: Arc<dyn TtyCorePrivateField>) {
*self.core.privete_fields.lock() = Some(fields);
}
#[inline] #[inline]
pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> { pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
self.line_discipline.clone() self.line_discipline.clone()
@ -231,7 +245,7 @@ impl TtyCore {
Ok(0) Ok(0)
} }
pub fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> { fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
let mut termios = tty.core().termios_write(); let mut termios = tty.core().termios_write();
let old_termios = *termios; let old_termios = *termios;
@ -252,7 +266,7 @@ impl TtyCore {
drop(termios); drop(termios);
let ld = tty.ldisc(); let ld = tty.ldisc();
ld.set_termios(tty, Some(old_termios))?; ld.set_termios(tty, Some(old_termios)).ok();
Ok(()) Ok(())
} }
@ -292,6 +306,7 @@ pub struct TtyCoreData {
flags: RwLock<TtyFlag>, flags: RwLock<TtyFlag>,
/// 在初始化时即确定不会更改,所以这里不用加锁 /// 在初始化时即确定不会更改,所以这里不用加锁
index: usize, index: usize,
vc_index: AtomicUsize,
count: AtomicUsize, count: AtomicUsize,
/// 窗口大小 /// 窗口大小
window_size: RwLock<WindowSize>, window_size: RwLock<WindowSize>,
@ -311,12 +326,16 @@ pub struct TtyCoreData {
link: RwLock<Weak<TtyCore>>, link: RwLock<Weak<TtyCore>>,
/// epitems /// epitems
epitems: SpinLock<LinkedList<Arc<EPollItem>>>, epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
/// 设备号
device_number: DeviceNumber,
privete_fields: SpinLock<Option<Arc<dyn TtyCorePrivateField>>>,
} }
impl TtyCoreData { impl TtyCoreData {
#[inline] #[inline]
pub fn driver(&self) -> Arc<TtyDriver> { pub fn driver(&self) -> &Arc<TtyDriver> {
self.tty_driver.clone() &self.tty_driver
} }
#[inline] #[inline]
@ -335,8 +354,12 @@ impl TtyCoreData {
} }
#[inline] #[inline]
pub fn name(&self) -> String { pub fn name(&self) -> &String {
self.name.clone() &self.name
}
pub fn device_number(&self) -> &DeviceNumber {
&self.device_number
} }
#[inline] #[inline]
@ -412,8 +435,20 @@ impl TtyCoreData {
} }
#[inline] #[inline]
pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> { pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
VIRT_CONSOLES[self.index].lock_irqsave() vc_manager().get(self.vc_index()?).unwrap().vc_data()
}
pub fn set_vc_index(&self, index: usize) {
self.vc_index.store(index, Ordering::SeqCst);
}
pub fn vc_index(&self) -> Option<usize> {
let x = self.vc_index.load(Ordering::SeqCst);
if x == usize::MAX {
return None;
}
return Some(x);
} }
#[inline] #[inline]
@ -469,7 +504,6 @@ impl TtyOperation for TtyCore {
#[inline] #[inline]
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
send_to_default_serial8250_port(buf);
return self.core().tty_driver.driver_funcs().write(tty, buf, nr); return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
} }

View File

@ -45,7 +45,7 @@ use super::{
sysfs::sys_class_tty_instance, sysfs::sys_class_tty_instance,
termios::WindowSize, termios::WindowSize,
tty_core::{TtyCore, TtyFlag, TtyIoctlCmd}, tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation}, tty_driver::{TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
tty_job_control::TtyJobCtrlManager, tty_job_control::TtyJobCtrlManager,
virtual_terminal::vty_init, virtual_terminal::vty_init,
}; };
@ -126,6 +126,10 @@ impl TtyDevice {
pub fn inner_write(&self) -> RwLockWriteGuard<InnerTtyDevice> { pub fn inner_write(&self) -> RwLockWriteGuard<InnerTtyDevice> {
self.inner.write() self.inner.write()
} }
pub fn name_ref(&self) -> &str {
&self.name
}
} }
impl IndexNode for TtyDevice { impl IndexNode for TtyDevice {
@ -145,7 +149,7 @@ impl IndexNode for TtyDevice {
let (index, driver) = let (index, driver) =
TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?; TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
let tty = TtyDriver::open_tty(index, driver)?; let tty = driver.open_tty(Some(index))?;
// 设置privdata // 设置privdata
*data = FilePrivateData::Tty(TtyFilePrivateData { *data = FilePrivateData::Tty(TtyFilePrivateData {
@ -592,15 +596,6 @@ impl TtyFilePrivateData {
#[unified_init(INITCALL_DEVICE)] #[unified_init(INITCALL_DEVICE)]
#[inline(never)] #[inline(never)]
pub fn tty_init() -> Result<(), SystemError> { pub fn tty_init() -> Result<(), SystemError> {
let tty = TtyDevice::new(
"tty0".to_string(),
IdTable::new(
String::from("tty0"),
Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
),
TtyType::Tty,
);
let console = TtyDevice::new( let console = TtyDevice::new(
"console".to_string(), "console".to_string(),
IdTable::new( IdTable::new(
@ -610,34 +605,8 @@ pub fn tty_init() -> Result<(), SystemError> {
TtyType::Tty, TtyType::Tty,
); );
// 注册tty设备 // 将设备注册到devfsTODO这里console设备应该与tty在一个设备group里面
// CharDevOps::cdev_add(
// tty.clone() as Arc<dyn CharDevice>,
// IdTable::new(
// String::from("tty0"),
// Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)),
// ),
// 1,
// )?;
// CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 0), 1, "/dev/tty")?;
// 注册console设备
// CharDevOps::cdev_add(
// console.clone() as Arc<dyn CharDevice>,
// IdTable::new(
// String::from("console"),
// Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
// ),
// 1,
// )?;
// CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 1), 1, "/dev/tty")?;
// 将这两个设备注册到devfsTODO这里console设备应该与tty在一个设备group里面
device_register(tty.clone())?;
device_register(console.clone())?; device_register(console.clone())?;
devfs_register(&tty.name.clone(), tty)?;
devfs_register(&console.name.clone(), console)?; devfs_register(&console.name.clone(), console)?;
serial_init()?; serial_init()?;

View File

@ -6,6 +6,7 @@ use alloc::{
vec::Vec, vec::Vec,
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use ida::IdAllocator;
use log::warn; use log::warn;
use system_error::SystemError; use system_error::SystemError;
@ -15,13 +16,17 @@ use crate::{
char::CharDevOps, char::CharDevOps,
device::{ device::{
device_number::{DeviceNumber, Major}, device_number::{DeviceNumber, Major},
device_register,
driver::Driver, driver::Driver,
IdTable,
}, },
kobject::KObject, kobject::KObject,
}, },
tty::tty_port::TtyPortState, tty::tty_port::TtyPortState,
}, },
filesystem::devfs::devfs_register,
libs::{ libs::{
lazy_init::Lazy,
rwlock::RwLock, rwlock::RwLock,
spinlock::{SpinLock, SpinLockGuard}, spinlock::{SpinLock, SpinLockGuard},
}, },
@ -30,6 +35,7 @@ use crate::{
use super::{ use super::{
termios::{Termios, WindowSize}, termios::{Termios, WindowSize},
tty_core::{TtyCore, TtyCoreData}, tty_core::{TtyCore, TtyCoreData},
tty_device::TtyDevice,
tty_ldisc::TtyLdiscManager, tty_ldisc::TtyLdiscManager,
tty_port::{DefaultTtyPort, TtyPort}, tty_port::{DefaultTtyPort, TtyPort},
}; };
@ -79,6 +85,7 @@ impl TtyDriverManager {
// 加入全局TtyDriver表 // 加入全局TtyDriver表
let driver = Arc::new(driver); let driver = Arc::new(driver);
driver.self_ref.init(Arc::downgrade(&driver));
TTY_DRIVERS.lock().push(driver.clone()); TTY_DRIVERS.lock().push(driver.clone());
// TODO: 加入procfs? // TODO: 加入procfs?
@ -87,6 +94,10 @@ impl TtyDriverManager {
} }
} }
/// tty 驱动程序的与设备相关的数据
pub trait TtyDriverPrivateField: Debug + Send + Sync {}
pub trait TtyCorePrivateField: Debug + Send + Sync {}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
#[cast_to([sync] Driver)] #[cast_to([sync] Driver)]
@ -121,7 +132,11 @@ pub struct TtyDriver {
ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>, ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>,
/// 管理的端口列表 /// 管理的端口列表
ports: RwLock<Vec<Arc<dyn TtyPort>>>, ports: RwLock<Vec<Arc<dyn TtyPort>>>,
// procfs入口? /// 与设备相关的私有数据
private_field: Option<Arc<dyn TtyDriverPrivateField>>,
/// id分配器
ida: SpinLock<IdAllocator>,
self_ref: Lazy<Weak<Self>>,
} }
impl TtyDriver { impl TtyDriver {
@ -135,6 +150,7 @@ impl TtyDriver {
tty_driver_type: TtyDriverType, tty_driver_type: TtyDriverType,
default_termios: Termios, default_termios: Termios,
driver_funcs: Arc<dyn TtyOperation>, driver_funcs: Arc<dyn TtyOperation>,
private_field: Option<Arc<dyn TtyDriverPrivateField>>,
) -> Self { ) -> Self {
let mut ports: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(count as usize); let mut ports: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(count as usize);
for _ in 0..count { for _ in 0..count {
@ -156,6 +172,9 @@ impl TtyDriver {
ttys: SpinLock::new(HashMap::new()), ttys: SpinLock::new(HashMap::new()),
saved_termios: Vec::with_capacity(count as usize), saved_termios: Vec::with_capacity(count as usize),
ports: RwLock::new(ports), ports: RwLock::new(ports),
private_field,
ida: SpinLock::new(IdAllocator::new(0, count as usize).unwrap()),
self_ref: Lazy::new(),
} }
} }
@ -179,6 +198,22 @@ impl TtyDriver {
self.driver_funcs.clone() self.driver_funcs.clone()
} }
/// ## 获取该驱动对应的设备的设备号
#[inline]
pub fn device_number(&self, index: usize) -> Option<DeviceNumber> {
if index >= self.device_count as usize {
return None;
}
Some(DeviceNumber::new(
self.major,
self.minor_start + index as u32,
))
}
fn self_ref(&self) -> Arc<Self> {
self.self_ref.get().upgrade().unwrap()
}
#[inline] #[inline]
pub fn init_termios(&self) -> Termios { pub fn init_termios(&self) -> Termios {
self.init_termios self.init_termios
@ -230,7 +265,7 @@ impl TtyDriver {
ret.ok() ret.ok()
} }
fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> { pub fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> {
let tty = tty_core.core(); let tty = tty_core.core();
tty.init_termios(); tty.init_termios();
// TODO:设置termios波特率 // TODO:设置termios波特率
@ -242,59 +277,81 @@ impl TtyDriver {
Ok(()) Ok(())
} }
fn driver_install_tty(driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { fn driver_install_tty(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
let res = tty.install(driver.clone(), tty.clone()); let res = tty.install(self.self_ref(), tty.clone());
if let Err(err) = res { if let Err(err) = res {
if err == SystemError::ENOSYS { if err == SystemError::ENOSYS {
return driver.standard_install(tty); return self.standard_install(tty);
} else { } else {
return Err(err); return Err(err);
} }
} }
driver.add_tty(tty); self.add_tty(tty);
Ok(()) Ok(())
} }
pub fn init_tty_device( pub fn init_tty_device(&self, index: Option<usize>) -> Result<Arc<TtyCore>, SystemError> {
driver: Arc<TtyDriver>, // 如果传入的index为None那么就自动分配index
index: usize, let idx: usize;
) -> Result<Arc<TtyCore>, SystemError> { if let Some(i) = index {
let tty = TtyCore::new(driver.clone(), index); if self.ida.lock().exists(i) {
return Err(SystemError::EINVAL);
}
idx = i;
} else {
idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?;
}
Self::driver_install_tty(driver.clone(), tty.clone())?; let tty = TtyCore::new(self.self_ref(), idx);
self.driver_install_tty(tty.clone())?;
let core = tty.core(); let core = tty.core();
if core.port().is_none() { if core.port().is_none() {
let ports = driver.ports.read(); let ports = self.ports.read();
ports[core.index()].setup_internal_tty(Arc::downgrade(&tty)); ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
tty.set_port(ports[core.index()].clone()); tty.set_port(ports[core.index()].clone());
} }
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?; TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
// 在devfs创建对应的文件
let device = TtyDevice::new(
core.name().clone(),
IdTable::new(self.tty_line_name(idx), Some(*core.device_number())),
super::tty_device::TtyType::Tty,
);
devfs_register(device.name_ref(), device.clone())?;
device_register(device)?;
Ok(tty) Ok(tty)
} }
/// ## 通过设备号找到对应驱动并且初始化Tty /// ## 通过设备号找到对应驱动并且初始化Tty
pub fn open_tty(index: usize, driver: Arc<TtyDriver>) -> Result<Arc<TtyCore>, SystemError> { pub fn open_tty(&self, index: Option<usize>) -> Result<Arc<TtyCore>, SystemError> {
let tty = match driver.lookup_tty(index) { let mut tty: Option<Arc<TtyCore>> = None;
Some(tty) => {
// TODO: 暂时这么写因为还没写TtyPort if index.is_some() {
if tty.core().port().is_none() { if let Some(t) = self.lookup_tty(index.unwrap()) {
warn!("{} port is None", tty.core().name()); if t.core().port().is_none() {
} else if tty.core().port().unwrap().state() == TtyPortState::KOPENED { warn!("{} port is None", t.core().name());
} else if t.core().port().unwrap().state() == TtyPortState::KOPENED {
return Err(SystemError::EBUSY); return Err(SystemError::EBUSY);
} }
tty.reopen()?; t.reopen()?;
tty tty = Some(t);
} }
None => Self::init_tty_device(driver, index)?, }
}; if tty.is_none() {
tty = Some(self.init_tty_device(index)?);
}
let tty = tty.ok_or(SystemError::ENODEV)?;
return Ok(tty); return Ok(tty);
} }
@ -447,7 +504,9 @@ pub trait TtyOperation: Sync + Send + Debug {
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>; fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError>; fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
} }
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -1209,7 +1209,8 @@ impl NTtyData {
if termios.output_mode.contains(OutputMode::OCRNL) { if termios.output_mode.contains(OutputMode::OCRNL) {
break; break;
} }
self.canon_cursor_column = self.cursor_column; self.cursor_column = 0;
self.canon_cursor_column = 0;
} }
'\t' => { '\t' => {
break; break;

View File

@ -1,4 +1,4 @@
use core::{fmt::Debug, sync::atomic::Ordering}; use core::fmt::Debug;
use alloc::sync::{Arc, Weak}; use alloc::sync::{Arc, Weak};
use kdepends::thingbuf::mpsc; use kdepends::thingbuf::mpsc;
@ -6,26 +6,10 @@ use system_error::SystemError;
use crate::libs::spinlock::{SpinLock, SpinLockGuard}; use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use super::{ use super::tty_core::TtyCore;
tty_core::TtyCore,
virtual_terminal::{virtual_console::CURRENT_VCNUM, VIRT_CONSOLES},
};
const TTY_PORT_BUFSIZE: usize = 4096; const TTY_PORT_BUFSIZE: usize = 4096;
/// 获取当前tty port
#[inline]
pub fn current_tty_port() -> Arc<dyn TtyPort> {
VIRT_CONSOLES[CURRENT_VCNUM.load(Ordering::SeqCst) as usize]
.lock_irqsave()
.port()
}
#[inline]
pub fn tty_port(index: usize) -> Arc<dyn TtyPort> {
VIRT_CONSOLES[index].lock_irqsave().port()
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub struct TtyPortData { pub struct TtyPortData {

View File

@ -1,22 +1,28 @@
use core::{fmt::Formatter, sync::atomic::Ordering}; use core::fmt::Formatter;
use alloc::{ use alloc::{
string::{String, ToString}, string::{String, ToString},
sync::Arc, sync::Arc,
vec::Vec,
}; };
use hashbrown::HashMap;
use ida::IdAllocator;
use system_error::SystemError; use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{ use crate::{
driver::base::device::{ driver::{
device_number::{DeviceNumber, Major}, base::device::{
device_register, IdTable, device_number::{DeviceNumber, Major},
device_register, IdTable,
},
serial::serial8250::send_to_default_serial8250_port,
}, },
filesystem::devfs::devfs_register, filesystem::devfs::{devfs_register, devfs_unregister},
libs::spinlock::SpinLock, init::initcall::INITCALL_LATE,
libs::{lazy_init::Lazy, rwlock::RwLock, spinlock::SpinLock},
}; };
use self::virtual_console::{VirtualConsoleData, CURRENT_VCNUM}; use self::virtual_console::VirtualConsoleData;
use super::{ use super::{
console::ConsoleSwitch, console::ConsoleSwitch,
@ -24,12 +30,13 @@ use super::{
tty_core::{TtyCore, TtyCoreData}, tty_core::{TtyCore, TtyCoreData},
tty_device::{TtyDevice, TtyType}, tty_device::{TtyDevice, TtyType},
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation}, tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation},
tty_port::{DefaultTtyPort, TtyPort},
}; };
pub mod console_map; pub mod console_map;
pub mod virtual_console; pub mod virtual_console;
pub const MAX_NR_CONSOLES: u32 = 63; pub const MAX_NR_CONSOLES: u32 = 64;
pub const VC_MAXCOL: usize = 32767; pub const VC_MAXCOL: usize = 32767;
pub const VC_MAXROW: usize = 32767; pub const VC_MAXROW: usize = 32767;
@ -48,14 +55,190 @@ pub const DEFAULT_BLUE: [u16; 16] = [
pub const COLOR_TABLE: &[u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15]; pub const COLOR_TABLE: &[u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15];
lazy_static! { lazy_static! {
pub static ref VIRT_CONSOLES: Vec<Arc<SpinLock<VirtualConsoleData>>> = { static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new();
let mut v = Vec::with_capacity(MAX_NR_CONSOLES as usize); }
for i in 0..MAX_NR_CONSOLES as usize {
v.push(Arc::new(SpinLock::new(VirtualConsoleData::new(i)))); /// 获取虚拟终端管理器
#[inline]
pub fn vc_manager() -> &'static VirtConsoleManager {
&VC_MANAGER
}
pub struct VirtConsole {
vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>,
port: Arc<dyn TtyPort>,
index: Lazy<usize>,
inner: SpinLock<InnerVirtConsole>,
}
struct InnerVirtConsole {
vcdev: Option<Arc<TtyDevice>>,
}
impl VirtConsole {
pub fn new(vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>) -> Arc<Self> {
Arc::new(Self {
vc_data,
port: Arc::new(DefaultTtyPort::new()),
index: Lazy::new(),
inner: SpinLock::new(InnerVirtConsole { vcdev: None }),
})
}
pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
self.vc_data.clone()
}
pub fn port(&self) -> Arc<dyn TtyPort> {
self.port.clone()
}
pub fn index(&self) -> Option<usize> {
self.index.try_get().cloned()
}
pub fn devfs_setup(&self) -> Result<(), SystemError> {
let tty_core = self
.port
.port_data()
.internal_tty()
.ok_or(SystemError::ENODEV)?;
let tty_core_data = tty_core.core();
let devnum = *tty_core_data.device_number();
let vcname = format!("vc{}", self.index.get());
// 注册虚拟终端设备并将虚拟终端设备加入到文件系统
let vcdev = TtyDevice::new(
vcname.clone(),
IdTable::new(vcname, Some(devnum)),
TtyType::Tty,
);
device_register(vcdev.clone())?;
devfs_register(vcdev.name_ref(), vcdev.clone())?;
tty_core_data.set_vc_index(*self.index.get());
self.inner.lock().vcdev = Some(vcdev);
Ok(())
}
fn devfs_remove(&self) {
let vcdev = self.inner.lock().vcdev.take();
if let Some(vcdev) = vcdev {
devfs_unregister(vcdev.name_ref(), vcdev.clone())
.inspect_err(|e| {
log::error!("virt console: devfs_unregister failed: {:?}", e);
})
.ok();
}
}
}
struct InnerVirtConsoleManager {
consoles: HashMap<usize, Arc<VirtConsole>>,
ida: IdAllocator,
}
pub struct VirtConsoleManager {
inner: SpinLock<InnerVirtConsoleManager>,
current_vc: RwLock<Option<(Arc<VirtConsole>, usize)>>,
}
impl VirtConsoleManager {
pub const DEFAULT_VC_NAMES: [&'static str; 4] = ["tty0", "ttyS0", "tty1", "ttyS1"];
pub fn new() -> Self {
let ida = IdAllocator::new(0, MAX_NR_CONSOLES as usize).unwrap();
let consoles = HashMap::new();
Self {
inner: SpinLock::new(InnerVirtConsoleManager { consoles, ida }),
current_vc: RwLock::new(None),
}
}
pub fn get(&self, index: usize) -> Option<Arc<VirtConsole>> {
let inner = self.inner.lock();
inner.consoles.get(&index).cloned()
}
pub fn alloc(&self, vc: Arc<VirtConsole>) -> Option<usize> {
let mut inner = self.inner.lock();
let index = inner.ida.alloc()?;
vc.index.init(index);
if let Some(vc_data) = vc.vc_data.as_ref() {
vc_data.lock().vc_index = index;
} }
v inner.consoles.insert(index, vc);
}; Some(index)
}
/// 释放虚拟终端
pub fn free(&self, index: usize) {
let mut inner = self.inner.lock();
if let Some(vc) = inner.consoles.remove(&index) {
vc.devfs_remove();
}
inner.ida.free(index);
}
/// 获取当前虚拟终端
pub fn current_vc(&self) -> Option<Arc<VirtConsole>> {
self.current_vc.read().as_ref().map(|(vc, _)| vc.clone())
}
pub fn current_vc_index(&self) -> Option<usize> {
self.current_vc.read().as_ref().map(|(_, index)| *index)
}
pub fn current_vc_tty_name(&self) -> Option<String> {
self.current_vc()
.and_then(|vc| vc.port().port_data().internal_tty())
.map(|tty| tty.core().name().to_string())
}
/// 设置当前虚拟终端
pub fn set_current_vc(&self, vc: Arc<VirtConsole>) {
let index = *vc.index.get();
*self.current_vc.write() = Some((vc, index));
}
/// 通过tty名称查找虚拟终端
///
/// # Arguments
///
/// * `name` - tty名称 (如ttyS0)
pub fn lookup_vc_by_tty_name(&self, name: &str) -> Option<Arc<VirtConsole>> {
let inner = self.inner.lock();
for (_index, vc) in inner.consoles.iter() {
let found = vc
.port
.port_data()
.internal_tty()
.map(|tty| tty.core().name().as_str() == name)
.unwrap_or(false);
if found {
return Some(vc.clone());
}
}
None
}
pub fn setup_default_vc(&self) {
// todo: 从内核启动参数中获取
for name in Self::DEFAULT_VC_NAMES.iter() {
if let Some(vc) = self.lookup_vc_by_tty_name(name) {
log::info!("Set default vc with tty device: {}", name);
self.set_current_vc(vc);
return;
}
}
panic!("virt console: setup default vc failed");
}
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
@ -119,7 +302,8 @@ impl TtyConsoleDriverInner {
fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> { fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
// 关闭中断 // 关闭中断
let mut vc_data = tty.vc_data_irqsave(); let vc_data = tty.vc_data().unwrap();
let mut vc_data_guard = vc_data.lock_irqsave();
let mut offset = 0; let mut offset = 0;
@ -130,7 +314,7 @@ impl TtyConsoleDriverInner {
let mut draw = DrawRegion::default(); let mut draw = DrawRegion::default();
// 首先隐藏光标再写 // 首先隐藏光标再写
vc_data.hide_cursor(); vc_data_guard.hide_cursor();
while nr != 0 { while nr != 0 {
if !rescan { if !rescan {
@ -139,7 +323,7 @@ impl TtyConsoleDriverInner {
nr -= 1; nr -= 1;
} }
let (tc, rescan_last) = vc_data.translate(&mut ch); let (tc, rescan_last) = vc_data_guard.translate(&mut ch);
if tc.is_none() { if tc.is_none() {
// 表示未转换完成 // 表示未转换完成
continue; continue;
@ -148,30 +332,30 @@ impl TtyConsoleDriverInner {
let tc = tc.unwrap(); let tc = tc.unwrap();
rescan = rescan_last; rescan = rescan_last;
if vc_data.is_control(tc, ch) { if vc_data_guard.is_control(tc, ch) {
vc_data.flush(&mut draw); vc_data_guard.flush(&mut draw);
vc_data.do_control(ch); vc_data_guard.do_control(ch);
continue; continue;
} }
if !vc_data.console_write_normal(tc, ch, &mut draw) { if !vc_data_guard.console_write_normal(tc, ch, &mut draw) {
continue; continue;
} }
} }
vc_data.flush(&mut draw); vc_data_guard.flush(&mut draw);
// TODO: notify update // TODO: notify update
return Ok(offset); return Ok(offset);
} }
}
impl TtyOperation for TtyConsoleDriverInner { fn do_install(&self, tty: Arc<TtyCore>, vc: &Arc<VirtConsole>) -> Result<(), SystemError> {
fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
let tty_core = tty.core(); let tty_core = tty.core();
let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock();
self.console.con_init(&mut vc_data, true)?; let binding = vc.vc_data().unwrap();
let mut vc_data = binding.lock();
self.console.con_init(vc, &mut vc_data, true)?;
if vc_data.complement_mask == 0 { if vc_data.complement_mask == 0 {
vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
} }
@ -206,11 +390,24 @@ impl TtyOperation for TtyConsoleDriverInner {
} }
// 设置tty的端口为vc端口 // 设置tty的端口为vc端口
vc_data.port().setup_internal_tty(Arc::downgrade(&tty)); vc.port().setup_internal_tty(Arc::downgrade(&tty));
tty.set_port(vc_data.port()); tty.set_port(vc.port());
vc.devfs_setup()?;
// 加入sysfs // 加入sysfs
CURRENT_VCNUM.store(tty_core.index() as isize, Ordering::SeqCst); Ok(())
}
}
impl TtyOperation for TtyConsoleDriverInner {
fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
let vc = VirtConsole::new(Some(Arc::new(SpinLock::new(VirtualConsoleData::new(
usize::MAX,
)))));
vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
self.do_install(tty, &vc)
.inspect_err(|_| vc_manager().free(vc.index().unwrap()))?;
Ok(()) Ok(())
} }
@ -228,6 +425,7 @@ impl TtyOperation for TtyConsoleDriverInner {
// if String::from_utf8_lossy(buf) == "Hello world!\n" { // if String::from_utf8_lossy(buf) == "Hello world!\n" {
// loop {} // loop {}
// } // }
send_to_default_serial8250_port(buf);
let ret = self.do_write(tty, buf, nr); let ret = self.do_write(tty, buf, nr);
self.flush_chars(tty); self.flush_chars(tty);
ret ret
@ -235,8 +433,9 @@ impl TtyOperation for TtyConsoleDriverInner {
#[inline(never)] #[inline(never)]
fn flush_chars(&self, tty: &TtyCoreData) { fn flush_chars(&self, tty: &TtyCoreData) {
let mut vc_data = tty.vc_data_irqsave(); let vc_data = tty.vc_data().unwrap();
vc_data.set_cursor(); let mut vc_data_guard = vc_data.lock_irqsave();
vc_data_guard.set_cursor();
} }
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
@ -295,49 +494,34 @@ pub struct DrawRegion {
// 初始化虚拟终端 // 初始化虚拟终端
#[inline(never)] #[inline(never)]
pub fn vty_init() -> Result<(), SystemError> { pub fn vty_init() -> Result<(), SystemError> {
// 注册虚拟终端设备并将虚拟终端设备加入到文件系统 if let Ok(tty_console_driver_inner) = TtyConsoleDriverInner::new() {
let vc0 = TtyDevice::new( let console_driver = TtyDriver::new(
"vc0".to_string(), MAX_NR_CONSOLES,
IdTable::new( "tty",
String::from("vc0"), 0,
Some(DeviceNumber::new(Major::TTY_MAJOR, 0)), Major::TTY_MAJOR,
), 0,
TtyType::Tty, TtyDriverType::Console,
); *TTY_STD_TERMIOS,
// 注册tty设备 Arc::new(tty_console_driver_inner),
// CharDevOps::cdev_add( None,
// vc0.clone() as Arc<dyn CharDevice>, );
// IdTable::new(
// String::from("vc0"),
// Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
// ),
// 1,
// )?;
// CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTY_MAJOR, 0), 1, "/dev/vc/0")?; TtyDriverManager::tty_register_driver(console_driver).inspect(|_| {
device_register(vc0.clone())?; log::error!("tty console: register driver failed");
devfs_register("vc0", vc0)?; })?;
}
// vcs_init?
let console_driver = TtyDriver::new(
MAX_NR_CONSOLES,
"tty",
1,
Major::TTY_MAJOR,
0,
TtyDriverType::Console,
*TTY_STD_TERMIOS,
Arc::new(TtyConsoleDriverInner::new()?),
);
TtyDriverManager::tty_register_driver(console_driver)?;
CURRENT_VCNUM.store(0, Ordering::SeqCst);
// 初始化键盘?
// TODO: 为vc
Ok(()) Ok(())
} }
#[unified_init(INITCALL_LATE)]
fn vty_late_init() -> Result<(), SystemError> {
let (_, console_driver) =
TtyDriverManager::lookup_tty_driver(DeviceNumber::new(Major::TTY_MAJOR, 0))
.ok_or(SystemError::ENODEV)?;
console_driver.init_tty_device(None)?;
vc_manager().setup_default_vc();
Ok(())
}

View File

@ -1,4 +1,4 @@
use core::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use alloc::{ use alloc::{
sync::{Arc, Weak}, sync::{Arc, Weak},
@ -10,11 +10,7 @@ use log::warn;
use crate::{ use crate::{
driver::{ driver::{
serial::serial8250::send_to_default_serial8250_port, serial::serial8250::send_to_default_serial8250_port,
tty::{ tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
console::ConsoleSwitch,
tty_port::{DefaultTtyPort, TtyPort},
ConsoleFont, KDMode,
},
}, },
libs::{font::FontDesc, rwlock::RwLock}, libs::{font::FontDesc, rwlock::RwLock},
process::Pid, process::Pid,
@ -22,7 +18,8 @@ use crate::{
use super::{ use super::{
console_map::{TranslationMap, TranslationMapType}, console_map::{TranslationMap, TranslationMapType},
Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN, DEFAULT_RED, vc_manager, Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN,
DEFAULT_RED,
}; };
pub(super) const NPAR: usize = 16; pub(super) const NPAR: usize = 16;
@ -34,14 +31,12 @@ lazy_static! {
} }
pub static CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false); pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
/// ## 虚拟控制台的信息 /// ## 虚拟控制台的信息
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VirtualConsoleData { pub struct VirtualConsoleData {
pub num: usize, pub vc_index: usize,
pub state: VirtualConsoleInfo, pub state: VirtualConsoleInfo,
pub saved_state: VirtualConsoleInfo, pub saved_state: VirtualConsoleInfo,
/// 最大列数 /// 最大列数
@ -146,9 +141,6 @@ pub struct VirtualConsoleData {
/// 对应的Console Driver funcs /// 对应的Console Driver funcs
driver_funcs: Option<Weak<dyn ConsoleSwitch>>, driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
/// 对应端口
port: Arc<dyn TtyPort>,
} }
impl VirtualConsoleData { impl VirtualConsoleData {
@ -210,16 +202,10 @@ impl VirtualConsoleData {
screen_buf: Default::default(), screen_buf: Default::default(),
driver_funcs: None, driver_funcs: None,
cursor_type: VcCursor::empty(), cursor_type: VcCursor::empty(),
num, vc_index: num,
port: Arc::new(DefaultTtyPort::new()),
} }
} }
#[inline]
pub fn port(&self) -> Arc<dyn TtyPort> {
self.port.clone()
}
pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) { pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
if let Some(rows) = rows { if let Some(rows) = rows {
self.rows = rows; self.rows = rows;
@ -245,12 +231,11 @@ impl VirtualConsoleData {
} }
pub fn is_visible(&self) -> bool { pub fn is_visible(&self) -> bool {
let cur_vc = CURRENT_VCNUM.load(Ordering::SeqCst); if let Some(cur_vc) = vc_manager().current_vc_index() {
if cur_vc == -1 { cur_vc == self.vc_index
return false; } else {
false
} }
cur_vc as usize == self.num
} }
fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> { fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {

View File

@ -5,7 +5,10 @@ use crate::driver::tty::{
console::ConsoleSwitch, console::ConsoleSwitch,
termios::WindowSize, termios::WindowSize,
tty_driver::TtyOperation, tty_driver::TtyOperation,
virtual_terminal::virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData}, virtual_terminal::{
virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData},
VirtConsole,
},
}; };
lazy_static! { lazy_static! {
@ -49,14 +52,19 @@ impl ConsoleSwitch for DummyConsole {
) -> Result<u8, SystemError> { ) -> Result<u8, SystemError> {
Ok(0) Ok(0)
} }
fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError> { fn con_init(
&self,
vc: &Arc<VirtConsole>,
vc_data: &mut VirtualConsoleData,
init: bool,
) -> Result<(), SystemError> {
vc_data.color_mode = true; vc_data.color_mode = true;
if init { if init {
vc_data.cols = Self::COLUNMS; vc_data.cols = Self::COLUNMS;
vc_data.rows = Self::ROWS; vc_data.rows = Self::ROWS;
} else { } else {
let tty = vc_data.port().port_data().tty().unwrap(); let tty = vc.port().port_data().tty().unwrap();
tty.resize( tty.resize(
tty.clone(), tty.clone(),
WindowSize::new(Self::ROWS as u16, Self::COLUNMS as u16, 0, 0), WindowSize::new(Self::ROWS as u16, Self::COLUNMS as u16, 0, 0),

View File

@ -8,7 +8,7 @@ use crate::{
console::ConsoleSwitch, console::ConsoleSwitch,
virtual_terminal::{ virtual_terminal::{
virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData}, virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData},
Color, Color, VirtConsole,
}, },
}, },
video::fbdev::base::{ video::fbdev::base::{
@ -174,6 +174,7 @@ impl BlittingFbConsole {
impl ConsoleSwitch for BlittingFbConsole { impl ConsoleSwitch for BlittingFbConsole {
fn con_init( fn con_init(
&self, &self,
_vc: &Arc<VirtConsole>,
vc_data: &mut VirtualConsoleData, vc_data: &mut VirtualConsoleData,
init: bool, init: bool,
) -> Result<(), system_error::SystemError> { ) -> Result<(), system_error::SystemError> {

View File

@ -156,7 +156,7 @@ impl IrqManager {
*action_guard.flags_mut() = flags; *action_guard.flags_mut() = flags;
*action_guard.dev_id_mut() = dev_id; *action_guard.dev_id_mut() = dev_id;
drop(action_guard); drop(action_guard);
debug!("to inner_setup_irq"); debug!("to inner_setup_irq: {irq:?}");
return self.inner_setup_irq(irq, irqaction, desc); return self.inner_setup_irq(irq, irqaction, desc);
} }

View File

@ -50,7 +50,7 @@ impl DevPtsFs {
let root_inode = Arc::new(LockedDevPtsFSInode::new()); let root_inode = Arc::new(LockedDevPtsFSInode::new());
let ret = Arc::new(Self { let ret = Arc::new(Self {
root_inode, root_inode,
pts_ida: SpinLock::new(IdAllocator::new(1, NR_UNIX98_PTY_MAX as usize).unwrap()), pts_ida: SpinLock::new(IdAllocator::new(0, NR_UNIX98_PTY_MAX as usize).unwrap()),
pts_count: AtomicU32::new(0), pts_count: AtomicU32::new(0),
}); });

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
driver::{ driver::{
serial::serial8250::send_to_default_serial8250_port, serial::serial8250::send_to_default_serial8250_port, tty::virtual_terminal::vc_manager,
tty::{tty_port::tty_port, virtual_terminal::virtual_console::CURRENT_VCNUM},
video::video_refresh_manager, video::video_refresh_manager,
}, },
libs::{ libs::{
@ -1031,8 +1030,7 @@ where
#[no_mangle] #[no_mangle]
pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 { pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 {
let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst); if let Some(current_vc) = vc_manager().current_vc() {
if current_vcnum != -1 {
// tty已经初始化了之后才输出到屏幕 // tty已经初始化了之后才输出到屏幕
let fr = (fr_color & 0x00ff0000) >> 16; let fr = (fr_color & 0x00ff0000) >> 16;
let fg = (fr_color & 0x0000ff00) >> 8; let fg = (fr_color & 0x0000ff00) >> 8;
@ -1044,7 +1042,7 @@ pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32)
"\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m", "\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m",
character as char character as char
); );
let port = tty_port(current_vcnum as usize); let port = current_vc.port();
let tty = port.port_data().internal_tty(); let tty = port.port_data().internal_tty();
if let Some(tty) = tty { if let Some(tty) = tty {
send_to_default_serial8250_port(&[character]); send_to_default_serial8250_port(&[character]);

View File

@ -1,7 +1,4 @@
use core::{ use core::fmt::{self, Write};
fmt::{self, Write},
sync::atomic::Ordering,
};
use alloc::string::ToString; use alloc::string::ToString;
use log::{info, Level, Log}; use log::{info, Level, Log};
@ -9,10 +6,7 @@ use log::{info, Level, Log};
use super::lib_ui::textui::{textui_putstr, FontColor}; use super::lib_ui::textui::{textui_putstr, FontColor};
use crate::{ use crate::{
driver::tty::{ driver::tty::{tty_driver::TtyOperation, virtual_terminal::vc_manager},
tty_driver::TtyOperation, tty_port::tty_port,
virtual_terminal::virtual_console::CURRENT_VCNUM,
},
filesystem::procfs::{ filesystem::procfs::{
kmsg::KMSG, kmsg::KMSG,
log::{LogLevel, LogMessage}, log::{LogLevel, LogMessage},
@ -44,10 +38,9 @@ impl PrintkWriter {
/// 并输出白底黑字 /// 并输出白底黑字
/// @param str: 要写入的字符 /// @param str: 要写入的字符
pub fn __write_string(&mut self, s: &str) { pub fn __write_string(&mut self, s: &str) {
let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst); if let Some(current_vc) = vc_manager().current_vc() {
if current_vcnum != -1 {
// tty已经初始化了之后才输出到屏幕 // tty已经初始化了之后才输出到屏幕
let port = tty_port(current_vcnum as usize); let port = current_vc.port();
let tty = port.port_data().internal_tty(); let tty = port.port_data().internal_tty();
if let Some(tty) = tty { if let Some(tty) = tty {
let _ = tty.write(tty.core(), s.as_bytes(), s.len()); let _ = tty.write(tty.core(), s.as_bytes(), s.len());

View File

@ -1,6 +1,7 @@
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
driver::tty::virtual_terminal::vc_manager,
filesystem::vfs::{ filesystem::vfs::{
file::{File, FileMode}, file::{File, FileMode},
ROOT_INODE, ROOT_INODE,
@ -13,9 +14,16 @@ pub fn stdio_init() -> Result<(), SystemError> {
if ProcessManager::current_pcb().pid() != Pid(1) { if ProcessManager::current_pcb().pid() != Pid(1) {
return Err(SystemError::EPERM); return Err(SystemError::EPERM);
} }
let tty_path = format!(
"/dev/{}",
vc_manager()
.current_vc_tty_name()
.expect("Init stdio: can't get tty name")
);
let tty_inode = ROOT_INODE() let tty_inode = ROOT_INODE()
.lookup("/dev/tty0") .lookup(&tty_path)
.expect("Init stdio: can't find tty0"); .unwrap_or_else(|_| panic!("Init stdio: can't find {}", tty_path));
let stdin = let stdin =
File::new(tty_inode.clone(), FileMode::O_RDONLY).expect("Init stdio: can't create stdin"); File::new(tty_inode.clone(), FileMode::O_RDONLY).expect("Init stdio: can't create stdin");
let stdout = let stdout =

View File

@ -77,6 +77,7 @@ QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
QEMU_ACCELARATE="" QEMU_ACCELARATE=""
QEMU_ARGUMENT="" QEMU_ARGUMENT=""
QEMU_DEVICES="" QEMU_DEVICES=""
BIOS_TYPE=""
#这个变量为true则使用virtio磁盘 #这个变量为true则使用virtio磁盘
VIRTIO_BLK_DEVICE=false VIRTIO_BLK_DEVICE=false
# 如果qemu_accel不为空 # 如果qemu_accel不为空
@ -109,6 +110,35 @@ if [ ${ARCH} == "riscv64" ]; then
QEMU_SERIAL="" QEMU_SERIAL=""
fi fi
while true;do
case "$1" in
--bios)
case "$2" in
uefi) #uefi启动新增ovmf.fd固件
BIOS_TYPE=uefi
;;
legacy)
BIOS_TYPE=legacy
;;
esac;shift 2;;
--display)
case "$2" in
vnc)
QEMU_ARGUMENT+=" -display vnc=:00"
;;
window)
;;
nographic)
QEMU_SERIAL=" -serial mon:stdio "
QEMU_MONITOR=""
QEMU_ARGUMENT+=" --nographic "
;;
esac;shift 2;;
*) break
esac
done
# ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么 # ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
@ -149,28 +179,7 @@ install_riscv_uboot()
if [ $flag_can_run -eq 1 ]; then if [ $flag_can_run -eq 1 ]; then
while true;do
case "$1" in
--bios)
case "$2" in
uefi) #uefi启动新增ovmf.fd固件
BIOS_TYPE=uefi
;;
legacy)
BIOS_TYPE=legacy
;;
esac;shift 2;;
--display)
case "$2" in
vnc)
QEMU_ARGUMENT+=" -display vnc=:00"
;;
window)
;;
esac;shift 2;;
*) break
esac
done
# 删除共享内存 # 删除共享内存
sudo rm -rf ${QEMU_MEMORY_BACKEND_PATH_PREFIX}/${QEMU_MEMORY_BACKEND} sudo rm -rf ${QEMU_MEMORY_BACKEND_PATH_PREFIX}/${QEMU_MEMORY_BACKEND}