|
1 | 1 | use bitflags::bitflags; |
2 | | -#[cfg(feature = "fmt")] |
3 | | -use core::fmt; |
| 2 | +use core::fmt::{self, Display, Formatter}; |
4 | 3 |
|
5 | 4 | use crate::registers::Registers; |
6 | 5 |
|
@@ -93,6 +92,21 @@ pub enum Parity { |
93 | 92 | Space, |
94 | 93 | } |
95 | 94 |
|
| 95 | +/// An error encountered which trying to transmit data. |
| 96 | +#[derive(Copy, Clone, Debug, Eq, PartialEq)] |
| 97 | +pub enum TransmitError { |
| 98 | + /// The transmit buffer is full, try again later. |
| 99 | + BufferFull, |
| 100 | +} |
| 101 | + |
| 102 | +impl Display for TransmitError { |
| 103 | + fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
| 104 | + f.write_str(match self { |
| 105 | + Self::BufferFull => "UART buffer full", |
| 106 | + }) |
| 107 | + } |
| 108 | +} |
| 109 | + |
96 | 110 | /// # MMIO version of an 8250 UART. |
97 | 111 | /// |
98 | 112 | /// **Note** This is only tested on the NS16550 compatible UART used in QEMU 5.0 virt machine of RISC-V. |
@@ -156,10 +170,13 @@ impl<'a> MmioUart8250<'a> { |
156 | 170 | } |
157 | 171 |
|
158 | 172 | /// Writes a byte to the UART. |
159 | | - /// |
160 | | - /// TODO: This currently ignores errors. |
161 | | - pub fn write_byte(&self, byte: u8) { |
162 | | - self.write_thr(byte); |
| 173 | + pub fn write_byte(&self, byte: u8) -> Result<(), TransmitError> { |
| 174 | + if self.is_transmitter_holding_register_empty() { |
| 175 | + self.write_thr(byte); |
| 176 | + Ok(()) |
| 177 | + } else { |
| 178 | + Err(TransmitError::BufferFull) |
| 179 | + } |
163 | 180 | } |
164 | 181 |
|
165 | 182 | /// write THR (offset + 0) |
@@ -545,12 +562,14 @@ impl<'a> MmioUart8250<'a> { |
545 | 562 | self.lsr().contains(LSR::RFE) |
546 | 563 | } |
547 | 564 |
|
548 | | - /// get whether data holding registers are empty |
| 565 | + /// Gets whether data holding registers are empty, i.e. the UART has finished transmitting all |
| 566 | + /// the data it has been given. |
549 | 567 | pub fn is_data_holding_registers_empty(&self) -> bool { |
550 | 568 | self.lsr().contains(LSR::DHRE) |
551 | 569 | } |
552 | 570 |
|
553 | | - /// get whether transmitter holding register is empty |
| 571 | + /// Gets whether transmitter holding register is empty, i.e. the UART is ready to be given more |
| 572 | + /// data to transmit. |
554 | 573 | pub fn is_transmitter_holding_register_empty(&self) -> bool { |
555 | 574 | self.lsr().contains(LSR::THRE) |
556 | 575 | } |
@@ -652,7 +671,8 @@ impl<'a> MmioUart8250<'a> { |
652 | 671 | impl<'a> fmt::Write for MmioUart8250<'a> { |
653 | 672 | fn write_str(&mut self, s: &str) -> fmt::Result { |
654 | 673 | for c in s.as_bytes() { |
655 | | - self.write_byte(*c); |
| 674 | + // If buffer is full, keep retrying. |
| 675 | + while self.write_byte(*c) == Err(TransmitError::BufferFull) {} |
656 | 676 | } |
657 | 677 | Ok(()) |
658 | 678 | } |
@@ -684,8 +704,14 @@ mod tests { |
684 | 704 | let mut fake_registers: [u8; 8] = [0; 8]; |
685 | 705 | let uart = unsafe { MmioUart8250::new(&mut fake_registers as *mut u8 as usize) }; |
686 | 706 |
|
687 | | - uart.write_byte(0x42); |
| 707 | + // Pretend that the transmit buffer is full. |
| 708 | + fake_registers[5] = 0; |
| 709 | + assert_eq!(uart.write_byte(0x42), Err(TransmitError::BufferFull)); |
| 710 | + assert_eq!(fake_registers[0], 0); |
688 | 711 |
|
| 712 | + // Pretend that the transmit buffer is available. |
| 713 | + fake_registers[5] = 0b0010_0000; |
| 714 | + assert_eq!(uart.write_byte(0x42), Ok(())); |
689 | 715 | assert_eq!(fake_registers[0], 0x42); |
690 | 716 | } |
691 | 717 |
|
|
0 commit comments