Skip to content

Commit 6dfc67c

Browse files
committed
serial: implement receive FIFO flush via FCR
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]>
1 parent 956f8c1 commit 6dfc67c

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

vm-superio/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
# Upcoming version
4+
5+
## Changed
6+
7+
- Implemented receive FIFO flushing via the FCR register for the `Serial`
8+
device ([#83](https://github.com/rust-vmm/vm-superio/issues/83)).
9+
310
# v0.8.0
411

512
## Changed

vm-superio/src/serial.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::Trigger;
2525
const DATA_OFFSET: u8 = 0;
2626
const IER_OFFSET: u8 = 1;
2727
const IIR_OFFSET: u8 = 2;
28+
const FCR_OFFSET: u8 = IIR_OFFSET;
2829
const LCR_OFFSET: u8 = 3;
2930
const MCR_OFFSET: u8 = 4;
3031
const LSR_OFFSET: u8 = 5;
@@ -50,6 +51,8 @@ const IIR_NONE_BIT: u8 = 0b0000_0001;
5051
const IIR_THR_EMPTY_BIT: u8 = 0b0000_0010;
5152
const IIR_RDA_BIT: u8 = 0b0000_0100;
5253

54+
const FCR_FLUSH_IN_BIT: u8 = 0b0000_0010;
55+
5356
const LCR_DLAB_BIT: u8 = 0b1000_0000;
5457

5558
const LSR_DATA_READY_BIT: u8 = 0b0000_0001;
@@ -625,7 +628,14 @@ impl<T: Trigger, EV: SerialEvents, W: Write> Serial<T, EV, W> {
625628
LCR_OFFSET => self.line_control = value,
626629
MCR_OFFSET => self.modem_control = value,
627630
SCR_OFFSET => self.scratch = value,
628-
// We are not interested in writing to other offsets (such as FCR offset).
631+
FCR_OFFSET => {
632+
// Clear the receive FIFO
633+
if value & FCR_FLUSH_IN_BIT != 0 {
634+
self.in_buffer.clear();
635+
self.clear_lsr_rda_bit();
636+
self.events.in_buffer_empty();
637+
}
638+
}
629639
_ => {}
630640
}
631641
Ok(())

0 commit comments

Comments
 (0)