Skip to content

Commit

Permalink
serial: implement receive FIFO flush via FCR
Browse files Browse the repository at this point in the history
The FIFO Control Register (FCR) controls the behavior of the receive
and transmit FIFO buffers of the device. The current implementation
does not emulate this register, as FIFO buffers are always enabled.
However, there are two bits in this register that control flushing of
said FIFOS. The transmission FIFO is already flushed by the current
implementation on every write, but the receive FIFO is not. This is
problematic, as some driver implementations (e.g. FreeBSD's) rely on
being able to clear this buffer via the corresponding bit.

Implement the correct behavior when a driver sets this bit by clearing
`in_buffer`. Since there is no more data in the receive FIFO, the
data-ready bit in the Line Status Register (LSR) must be cleared as
well, in case it was set.

Fixes: rust-vmm#83
Signed-off-by: Carlos López <[email protected]>
  • Loading branch information
00xc committed Nov 22, 2024
1 parent 2c84bc9 commit a1a9b1d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
7 changes: 7 additions & 0 deletions vm-superio/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

# Upcoming version

## Changed

- Implemented receive FIFO flushing via the FCR register for the `Serial`
device ([#83](https://github.com/rust-vmm/vm-superio/issues/83)).

# v0.8.0

## Changed
Expand Down
12 changes: 11 additions & 1 deletion vm-superio/src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::Trigger;
const DATA_OFFSET: u8 = 0;
const IER_OFFSET: u8 = 1;
const IIR_OFFSET: u8 = 2;
const FCR_OFFSET: u8 = IIR_OFFSET;
const LCR_OFFSET: u8 = 3;
const MCR_OFFSET: u8 = 4;
const LSR_OFFSET: u8 = 5;
Expand All @@ -50,6 +51,8 @@ const IIR_NONE_BIT: u8 = 0b0000_0001;
const IIR_THR_EMPTY_BIT: u8 = 0b0000_0010;
const IIR_RDA_BIT: u8 = 0b0000_0100;

const FCR_FLUSH_IN_BIT: u8 = 0b0000_0010;

const LCR_DLAB_BIT: u8 = 0b1000_0000;

const LSR_DATA_READY_BIT: u8 = 0b0000_0001;
Expand Down Expand Up @@ -625,7 +628,14 @@ impl<T: Trigger, EV: SerialEvents, W: Write> Serial<T, EV, W> {
LCR_OFFSET => self.line_control = value,
MCR_OFFSET => self.modem_control = value,
SCR_OFFSET => self.scratch = value,
// We are not interested in writing to other offsets (such as FCR offset).
FCR_OFFSET => {
// Clear the receive FIFO
if value & FCR_FLUSH_IN_BIT != 0 {
self.in_buffer.clear();
self.clear_lsr_rda_bit();
self.events.in_buffer_empty();
}
}
_ => {}
}
Ok(())
Expand Down

0 comments on commit a1a9b1d

Please sign in to comment.