[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 42/76] char/cadence_uart: Remove TX timer & add TX FI
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 42/76] char/cadence_uart: Remove TX timer & add TX FIFO state |
Date: |
Tue, 7 Jan 2014 20:03:38 +0000 |
From: Peter Crosthwaite <address@hidden>
This tx timer implementation is flawed. Despite the controller
attempting to time the guest visable assertion of the TX-empty status
bit (and corresponding interrupt) the controller is still transmitting
characters instantaneously. There is also no sense of multiple character
delay.
The only side effect of this timer is assertion of tx-empty status. So
just remove the timer completely and hold tx-empty as permanently
asserted (its reset status). This matches the actual behaviour of
instantaneous transmission.
While we are VMSD version bumping, add the tx_fifo as device state to
prepare for upcomming TxFIFO flow control. Implement the interrupt
generation logic for the TxFIFO occupancy.
Signed-off-by: Peter Crosthwaite <address@hidden>
Message-id: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
---
hw/char/cadence_uart.c | 44 +++++++++++++-------------------------------
1 file changed, 13 insertions(+), 31 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 216eed7..3eeadb1 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -121,13 +121,14 @@ typedef struct {
MemoryRegion iomem;
uint32_t r[R_MAX];
uint8_t rx_fifo[RX_FIFO_SIZE];
+ uint8_t tx_fifo[TX_FIFO_SIZE];
uint32_t rx_wpos;
uint32_t rx_count;
+ uint32_t tx_count;
uint64_t char_tx_time;
CharDriverState *chr;
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
- QEMUTimer *tx_time_handle;
} UartState;
static void uart_update_status(UartState *s)
@@ -138,8 +139,12 @@ static void uart_update_status(UartState *s)
s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
- s->r[R_SR] |= UART_SR_INTR_TEMPTY;
+ s->r[R_SR] |= s->tx_count == TX_FIFO_SIZE ? UART_SR_INTR_TFUL : 0;
+ s->r[R_SR] |= !s->tx_count ? UART_SR_INTR_TEMPTY : 0;
+ s->r[R_SR] |= s->tx_count >= s->r[R_TTRIG] ? UART_SR_TTRIG : 0;
+
s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
+ s->r[R_CISR] |= s->r[R_SR] & UART_SR_TTRIG ? UART_INTR_TTRIG : 0;
qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
}
@@ -152,24 +157,6 @@ static void fifo_trigger_update(void *opaque)
uart_update_status(s);
}
-static void uart_tx_redo(UartState *s)
-{
- uint64_t new_tx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- timer_mod(s->tx_time_handle, new_tx_time + s->char_tx_time);
-
- s->r[R_SR] |= UART_SR_INTR_TEMPTY;
-
- uart_update_status(s);
-}
-
-static void uart_tx_write(void *opaque)
-{
- UartState *s = (UartState *)opaque;
-
- uart_tx_redo(s);
-}
-
static void uart_rx_reset(UartState *s)
{
s->rx_wpos = 0;
@@ -181,6 +168,7 @@ static void uart_rx_reset(UartState *s)
static void uart_tx_reset(UartState *s)
{
+ s->tx_count = 0;
}
static void uart_send_breaks(UartState *s)
@@ -261,10 +249,6 @@ static void uart_ctrl_update(UartState *s)
s->r[R_CR] &= ~(UART_CR_TXRST | UART_CR_RXRST);
- if ((s->r[R_CR] & UART_CR_TX_EN) && !(s->r[R_CR] & UART_CR_TX_DIS)) {
- uart_tx_redo(s);
- }
-
if (s->r[R_CR] & UART_CR_STARTBRK && !(s->r[R_CR] & UART_CR_STOPBRK)) {
uart_send_breaks(s);
}
@@ -447,9 +431,6 @@ static int cadence_uart_init(SysBusDevice *dev)
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
(QEMUTimerCB *)fifo_trigger_update, s);
- s->tx_time_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- (QEMUTimerCB *)uart_tx_write, s);
-
s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
s->chr = qemu_char_get_next_serial();
@@ -473,17 +454,18 @@ static int cadence_uart_post_load(void *opaque, int
version_id)
static const VMStateDescription vmstate_cadence_uart = {
.name = "cadence_uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
.post_load = cadence_uart_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
VMSTATE_UINT8_ARRAY(rx_fifo, UartState, RX_FIFO_SIZE),
+ VMSTATE_UINT8_ARRAY(tx_fifo, UartState, RX_FIFO_SIZE),
VMSTATE_UINT32(rx_count, UartState),
+ VMSTATE_UINT32(tx_count, UartState),
VMSTATE_UINT32(rx_wpos, UartState),
VMSTATE_TIMER(fifo_trigger_handle, UartState),
- VMSTATE_TIMER(tx_time_handle, UartState),
VMSTATE_END_OF_LIST()
}
};
--
1.8.5
- [Qemu-devel] [PULL 27/76] target-arm: A64: Fix vector register access on bigendian hosts, (continued)
- [Qemu-devel] [PULL 27/76] target-arm: A64: Fix vector register access on bigendian hosts, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 50/76] target-arm: fix build with gcc 4.8.2, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 39/76] char/cadence_uart: s/r_fifo/rx_fifo, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 31/76] target-arm: A64: Add fmov (scalar, immediate) instruction, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 58/76] softfloat: Only raise Invalid when conversions to int are out of range, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 29/76] target-arm: A64: Add "Floating-point data-processing (2 source)" insns, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 40/76] char/cadence_uart: Simplify status generation, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 09/76] target-arm: A64: Add decoder skeleton for FP instructions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 46/76] char/cadence_uart: Implement Tx flow control, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 45/76] char/cadence_uart: Delete redundant rx rst logic, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 42/76] char/cadence_uart: Remove TX timer & add TX FIFO state,
Peter Maydell <=
- [Qemu-devel] [PULL 41/76] char/cadence_uart: Define Missing SR/ISR fields, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 55/76] softfloat: Add 16 bit integer to float conversions, Peter Maydell, 2014/01/07