mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
rust: pl011: fix break errors and definition of Data struct
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> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f65314bdd0
commit
e1f9353334
2 changed files with 36 additions and 20 deletions
|
@ -30,8 +30,6 @@ const IBRD_MASK: u32 = 0xffff;
|
||||||
/// Fractional Baud Rate Divider, `UARTFBRD`
|
/// Fractional Baud Rate Divider, `UARTFBRD`
|
||||||
const FBRD_MASK: u32 = 0x3f;
|
const FBRD_MASK: u32 = 0x3f;
|
||||||
|
|
||||||
const DATA_BREAK: u32 = 1 << 10;
|
|
||||||
|
|
||||||
/// QEMU sourced constant.
|
/// QEMU sourced constant.
|
||||||
pub const PL011_FIFO_DEPTH: usize = 16_usize;
|
pub const PL011_FIFO_DEPTH: usize = 16_usize;
|
||||||
|
|
||||||
|
@ -75,7 +73,7 @@ pub struct PL011State {
|
||||||
pub dmacr: u32,
|
pub dmacr: u32,
|
||||||
pub int_enabled: u32,
|
pub int_enabled: u32,
|
||||||
pub int_level: u32,
|
pub int_level: u32,
|
||||||
pub read_fifo: [u32; PL011_FIFO_DEPTH],
|
pub read_fifo: [registers::Data; PL011_FIFO_DEPTH],
|
||||||
pub ilpr: u32,
|
pub ilpr: u32,
|
||||||
pub ibrd: u32,
|
pub ibrd: u32,
|
||||||
pub fbrd: u32,
|
pub fbrd: u32,
|
||||||
|
@ -210,10 +208,11 @@ impl PL011State {
|
||||||
self.int_level &= !registers::INT_RX;
|
self.int_level &= !registers::INT_RX;
|
||||||
}
|
}
|
||||||
// Update error bits.
|
// 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();
|
self.update();
|
||||||
// Must call qemu_chr_fe_accept_input, so return Continue:
|
// 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(RSR) => u8::from(self.receive_status_error_clear).into(),
|
||||||
Ok(FR) => u16::from(self.flags).into(),
|
Ok(FR) => u16::from(self.flags).into(),
|
||||||
|
@ -406,7 +405,7 @@ impl PL011State {
|
||||||
|
|
||||||
fn loopback_break(&mut self, enable: bool) {
|
fn loopback_break(&mut self, enable: bool) {
|
||||||
if enable {
|
if enable {
|
||||||
self.loopback_tx(DATA_BREAK);
|
self.loopback_tx(registers::Data::BREAK.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +469,7 @@ impl PL011State {
|
||||||
|
|
||||||
pub fn event(&mut self, event: QEMUChrEvent) {
|
pub fn event(&mut self, event: QEMUChrEvent) {
|
||||||
if event == bindings::QEMUChrEvent::CHR_EVENT_BREAK && !self.loopback_enabled() {
|
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 @@ impl PL011State {
|
||||||
let depth = self.fifo_depth();
|
let depth = self.fifo_depth();
|
||||||
assert!(depth > 0);
|
assert!(depth > 0);
|
||||||
let slot = (self.read_pos + self.read_count) & (depth - 1);
|
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.read_count += 1;
|
||||||
self.flags.set_receive_fifo_empty(false);
|
self.flags.set_receive_fifo_empty(false);
|
||||||
if self.read_count == depth {
|
if self.read_count == depth {
|
||||||
|
|
|
@ -139,6 +139,21 @@ pub mod registers {
|
||||||
//! unused thus treated as zero when read or written.
|
//! unused thus treated as zero when read or written.
|
||||||
use bilge::prelude::*;
|
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
|
// TODO: FIFO Mode has different semantics
|
||||||
/// Data Register, `UARTDR`
|
/// Data Register, `UARTDR`
|
||||||
///
|
///
|
||||||
|
@ -181,16 +196,18 @@ pub mod registers {
|
||||||
///
|
///
|
||||||
/// # Source
|
/// # Source
|
||||||
/// ARM DDI 0183G 3.3.1 Data Register, UARTDR
|
/// ARM DDI 0183G 3.3.1 Data Register, UARTDR
|
||||||
#[bitsize(16)]
|
#[bitsize(32)]
|
||||||
#[derive(Clone, Copy, DebugBits, FromBits)]
|
#[derive(Clone, Copy, Default, DebugBits, FromBits)]
|
||||||
#[doc(alias = "UARTDR")]
|
#[doc(alias = "UARTDR")]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
_reserved: u4,
|
|
||||||
pub data: u8,
|
pub data: u8,
|
||||||
pub framing_error: bool,
|
pub errors: Errors,
|
||||||
pub parity_error: bool,
|
_reserved: u16,
|
||||||
pub break_error: bool,
|
}
|
||||||
pub overrun_error: bool,
|
|
||||||
|
impl Data {
|
||||||
|
// bilge is not very const-friendly, unfortunately
|
||||||
|
pub const BREAK: Self = Self { value: 1 << 10 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIFO Mode has different semantics
|
// TODO: FIFO Mode has different semantics
|
||||||
|
@ -220,14 +237,14 @@ pub mod registers {
|
||||||
#[bitsize(8)]
|
#[bitsize(8)]
|
||||||
#[derive(Clone, Copy, DebugBits, FromBits)]
|
#[derive(Clone, Copy, DebugBits, FromBits)]
|
||||||
pub struct ReceiveStatusErrorClear {
|
pub struct ReceiveStatusErrorClear {
|
||||||
pub framing_error: bool,
|
pub errors: Errors,
|
||||||
pub parity_error: bool,
|
|
||||||
pub break_error: bool,
|
|
||||||
pub overrun_error: bool,
|
|
||||||
_reserved_unpredictable: u4,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReceiveStatusErrorClear {
|
impl ReceiveStatusErrorClear {
|
||||||
|
pub fn set_from_data(&mut self, data: Data) {
|
||||||
|
self.set_errors(data.errors());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
// All the bits are cleared to 0 on reset.
|
// All the bits are cleared to 0 on reset.
|
||||||
*self = Self::default();
|
*self = Self::default();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue