sysutils: add serial console program

This commit is contained in:
2025-10-10 09:21:20 +03:00
parent 33474c10d3
commit 312458b8f0
14 changed files with 266 additions and 12 deletions
+25 -2
View File
@@ -64,6 +64,20 @@ pub trait TerminalOutput: Sync + Send {
}
Ok(written)
}
fn baud_rate(&self) -> u32 {
115200
}
fn set_baud_rate(&self, baud: u32) -> Result<(), Error> {
if baud == 115200 {
Ok(())
} else {
log::warn!(
"[this] TerminalOutput impl does not support baud rate changes (want {baud})"
);
Err(Error::NotImplemented)
}
}
}
struct InputBuffer {
@@ -72,7 +86,8 @@ struct InputBuffer {
}
impl<O: TerminalOutput> Terminal<O> {
pub fn from_parts(config: TerminalOptions, input: TerminalInput, output: O) -> Self {
pub fn from_parts(mut config: TerminalOptions, input: TerminalInput, output: O) -> Self {
config.baud_rate = output.baud_rate();
Self {
input,
output,
@@ -212,7 +227,15 @@ impl<O: TerminalOutput> Terminal<O> {
TerminalRequestVariant::SetTerminalOptions => {
let options = device::SetTerminalOptions::load_request(input)?;
self.input.flush();
*self.config.write() = options;
let need_baud_change = {
let mut cfg = self.config.write();
let need_baud_change = cfg.baud_rate != options.baud_rate;
*cfg = options;
need_baud_change
};
if need_baud_change {
self.output.set_baud_rate(options.baud_rate)?;
}
device::SetTerminalOptions::store_response(&(), buffer)
}
TerminalRequestVariant::GetTerminalOptions => {
+32
View File
@@ -17,8 +17,11 @@ use libk_util::sync::IrqSafeSpinlock;
struct Regs {
dr: IoPort<u8>,
lsr: IoPort<u8>,
lcr: IoPort<u8>,
ier: IoPort<u8>,
isr: IoPort<u8>,
baud_rate: u32,
}
struct PortInner {
@@ -78,6 +81,30 @@ impl TerminalOutput for PortInner {
}
Ok(bytes.len())
}
fn baud_rate(&self) -> u32 {
self.regs.lock().baud_rate
}
fn set_baud_rate(&self, baud: u32) -> Result<(), Error> {
if baud > 115200 {
log::warn!("Tried to set baud rate for COM port beyond 115200: {baud}");
return Err(Error::InvalidArgument);
}
let div = 115200 / baud;
let mut regs = self.regs.lock();
regs.lcr.write(regs.lcr.read() | (1 << 7));
regs.dr.write(div as u8);
regs.ier.write((div >> 8) as u8);
regs.lcr.write(regs.lcr.read() & !(1 << 7));
regs.baud_rate = baud;
Ok(())
}
}
impl DebugSink for Port {
@@ -114,6 +141,8 @@ impl Device for Port {
}
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
self.terminal.output().set_baud_rate(115200)?;
DEVICE_REGISTRY
.serial_terminal
.register(self.terminal.clone(), Some(self.clone()))
@@ -149,6 +178,9 @@ impl Port {
lsr: IoPort::new(base + 5),
ier: IoPort::new(base + 1),
isr: IoPort::new(base + 2),
lcr: IoPort::new(base + 3),
baud_rate: 0,
}),
};
let terminal = Terminal::from_parts(TerminalOptions::const_default(), input, output);