The Data struct is wrong, and does not show how bits 8-15 of DR
are the receive status. Fix it, and use it to fix break
errors ("c >> 8" in the C code does not translate to
"c.to_be_bytes()[3]").
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/hw/char/pl011/src/device.rs | 15 ++++++------
rust/hw/char/pl011/src/lib.rs | 41 ++++++++++++++++++++++----------
2 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs
index f2ee8763d8f..5e3a9c6f581 100644
--- a/rust/hw/char/pl011/src/device.rs
+++ b/rust/hw/char/pl011/src/device.rs
@@ -30,8 +30,6 @@
/// Fractional Baud Rate Divider, `UARTFBRD`
const FBRD_MASK: u32 = 0x3f;
-const DATA_BREAK: u32 = 1 << 10;
-
/// QEMU sourced constant.
pub const PL011_FIFO_DEPTH: usize = 16_usize;
@@ -75,7 +73,7 @@ pub struct PL011State {
pub dmacr: u32,
pub int_enabled: u32,
pub int_level: u32,
- pub read_fifo: [u32; PL011_FIFO_DEPTH],
+ pub read_fifo: [registers::Data; PL011_FIFO_DEPTH],
pub ilpr: u32,
pub ibrd: u32,
pub fbrd: u32,
@@ -210,10 +208,11 @@ pub fn read(&mut self, offset: hwaddr, _size: c_uint) -> std::ops::ControlFlow<u
self.int_level &= !registers::INT_RX;
}
// Update error bits.
- self.receive_status_error_clear = c.to_be_bytes()[3].into();
+ self.receive_status_error_clear.set_from_data(c);
self.update();
// Must call qemu_chr_fe_accept_input, so return Continue:
- return std::ops::ControlFlow::Continue(c.into());
+ let c = u32::from(c);
+ return std::ops::ControlFlow::Continue(u64::from(c));
}
Ok(RSR) => u8::from(self.receive_status_error_clear).into(),
Ok(FR) => u16::from(self.flags).into(),
@@ -406,7 +405,7 @@ fn loopback_mdmctrl(&mut self) {
fn loopback_break(&mut self, enable: bool) {
if enable {
- self.loopback_tx(DATA_BREAK);
+ self.loopback_tx(registers::Data::BREAK.into());
}
}
@@ -470,7 +469,7 @@ pub fn can_receive(&self) -> bool {
pub fn event(&mut self, event: QEMUChrEvent) {
if event == bindings::QEMUChrEvent::CHR_EVENT_BREAK && !self.loopback_enabled() {
- self.put_fifo(DATA_BREAK);
+ self.put_fifo(registers::Data::BREAK.into());
}
}
@@ -497,7 +496,7 @@ pub fn put_fifo(&mut self, value: c_uint) {
let depth = self.fifo_depth();
assert!(depth > 0);
let slot = (self.read_pos + self.read_count) & (depth - 1);
- self.read_fifo[slot] = value;
+ self.read_fifo[slot] = registers::Data::from(value);
self.read_count += 1;
self.flags.set_receive_fifo_empty(false);
if self.read_count == depth {
diff --git a/rust/hw/char/pl011/src/lib.rs b/rust/hw/char/pl011/src/lib.rs
index e3eacb0e6b9..463ae60543b 100644
--- a/rust/hw/char/pl011/src/lib.rs
+++ b/rust/hw/char/pl011/src/lib.rs
@@ -139,6 +139,21 @@ pub mod registers {
//! unused thus treated as zero when read or written.
use bilge::prelude::*;
+ /// Receive Status Register / Data Register common error bits
+ ///
+ /// The `UARTRSR` register is updated only when a read occurs
+ /// from the `UARTDR` register with the same status information
+ /// that can also be obtained by reading the `UARTDR` register
+ #[bitsize(8)]
+ #[derive(Clone, Copy, Default, DebugBits, FromBits)]
+ pub struct Errors {
+ pub framing_error: bool,
+ pub parity_error: bool,
+ pub break_error: bool,
+ pub overrun_error: bool,
+ _reserved_unpredictable: u4,
+ }
+
// TODO: FIFO Mode has different semantics
/// Data Register, `UARTDR`
///
@@ -181,16 +196,18 @@ pub mod registers {
///
/// # Source
/// ARM DDI 0183G 3.3.1 Data Register, UARTDR
- #[bitsize(16)]
- #[derive(Clone, Copy, DebugBits, FromBits)]
+ #[bitsize(32)]
+ #[derive(Clone, Copy, Default, DebugBits, FromBits)]
#[doc(alias = "UARTDR")]
pub struct Data {
- _reserved: u4,
pub data: u8,
- pub framing_error: bool,
- pub parity_error: bool,
- pub break_error: bool,
- pub overrun_error: bool,
+ pub errors: Errors,
+ _reserved: u16,
+ }
+
+ impl Data {
+ // bilge is not very const-friendly, unfortunately
+ pub const BREAK: Self = Self { value: 1 << 10 };
}
// TODO: FIFO Mode has different semantics
@@ -220,14 +237,14 @@ pub struct Data {
#[bitsize(8)]
#[derive(Clone, Copy, DebugBits, FromBits)]
pub struct ReceiveStatusErrorClear {
- pub framing_error: bool,
- pub parity_error: bool,
- pub break_error: bool,
- pub overrun_error: bool,
- _reserved_unpredictable: u4,
+ pub errors: Errors,
}
impl ReceiveStatusErrorClear {
+ pub fn set_from_data(&mut self, data: Data) {
+ self.set_errors(data.errors());
+ }
+
pub fn reset(&mut self) {
// All the bits are cleared to 0 on reset.
*self = Self::default();
--
2.47.1