sysutils: add serial console program
This commit is contained in:
@@ -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 => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user