[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add T
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state |
Date: |
Mon, 16 Dec 2013 17:43:52 -0800 |
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>
---
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 a9700f7..f28e503 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.1
- [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 02/11] char/cadence_uart: Add missing uart_update_state, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 03/11] char/cadence_uart: Fix reset., Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 04/11] char/cadence_uart: s/r_fifo/rx_fifo, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 05/11] char/cadence_uart: Simplify status generation, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 06/11] char/cadence_uart: Define Missing SR/ISR fields, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state,
Peter Crosthwaite <=
- [Qemu-devel] [PATCH v1 08/11] char/cadence_uart: Fix can_receive logic, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 09/11] char/cadence_uart: Use the TX fifo for transmission, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 10/11] char/cadence_uart: Delete redundant rx rst logic, Peter Crosthwaite, 2013/12/16
- [Qemu-devel] [PATCH v1 11/11] char/cadence_uart: Implement Tx flow control, Peter Crosthwaite, 2013/12/16