Wait until serial tx buffer is empty
All checks were successful
Continuous Integration / Check (push) Successful in 1m9s
Continuous Integration / Clippy (push) Successful in 1m12s

This commit is contained in:
August 2025-11-04 16:32:03 -05:00
parent b02c34fd1d
commit 07136397d0
Signed by: shibedrill
GPG Key ID: 5FE0CB25945EFAA2

View File

@ -9,6 +9,8 @@ use num_derive::FromPrimitive;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
use crate::arch::asm::nop;
/// Represents an x86 port-mapped serial port. /// Represents an x86 port-mapped serial port.
pub struct SerialPort { pub struct SerialPort {
base_port: Port<u8>, base_port: Port<u8>,
@ -21,6 +23,7 @@ pub struct SerialPort {
scratch: Port<u8>, scratch: Port<u8>,
fifo_register: u8, fifo_register: u8,
pub crlf: Crlf, pub crlf: Crlf,
pub wait_tx_clear: bool,
} }
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
@ -123,7 +126,6 @@ pub enum ModemStatus {
DataCarrierDetect = 0b10000000, DataCarrierDetect = 0b10000000,
} }
// TODO: Ensure we don't clobber the tx buffer and prevent some data from getting printed
impl SerialPort { impl SerialPort {
pub fn log_write(&mut self, msg: &str) { pub fn log_write(&mut self, msg: &str) {
if self.crlf == Crlf::Crlf { if self.crlf == Crlf::Crlf {
@ -140,10 +142,18 @@ impl SerialPort {
} }
} }
/// Get whether the transmit buffer is empty.
pub fn is_transmit_empty(&mut self) -> bool { pub fn is_transmit_empty(&mut self) -> bool {
self.get_interrupt_state() != InterruptState::TransmitterEmpty self.get_line_status().contains(LineStatus::TransmitterEmpty)
} }
fn block_until_transmit_empty(&mut self) {
while !self.is_transmit_empty() {
nop();
}
}
/// Write a message with a newline appended to the serial port.
pub fn log_writeln(&mut self, msg: &str) { pub fn log_writeln(&mut self, msg: &str) {
self.log_write(msg); self.log_write(msg);
self.log_write("\n"); self.log_write("\n");
@ -162,6 +172,7 @@ impl SerialPort {
scratch: Port::new(port_addr + 7), scratch: Port::new(port_addr + 7),
fifo_register: 0, fifo_register: 0,
crlf: Crlf::Crlf, crlf: Crlf::Crlf,
wait_tx_clear: true,
}; };
// ensure this is false // ensure this is false
port.set_dlab(false); port.set_dlab(false);
@ -190,6 +201,10 @@ impl SerialPort {
} }
/// Write a single character to the TX buffer. /// Write a single character to the TX buffer.
pub fn write_char(&mut self, c: char) { pub fn write_char(&mut self, c: char) {
// Wait for the TX Buffer to be empty
if self.wait_tx_clear {
self.block_until_transmit_empty();
}
unsafe { self.base_port.write(c as u8) }; unsafe { self.base_port.write(c as u8) };
} }