[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 4/4] ssi: pl022: Convert to use FIFO
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [PATCH v3 4/4] ssi: pl022: Convert to use FIFO |
Date: |
Wed, 9 Apr 2014 23:43:41 -0700 |
Use the FIFO API to factor out the ring buffer implementation code.
Cleans up the somewhat verbose VMS description as well (version bump
required).
Signed-off-by: Peter Crosthwaite <address@hidden>
---
hw/ssi/pl022.c | 101 ++++++++++++++++++++++++---------------------------------
1 file changed, 42 insertions(+), 59 deletions(-)
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
index 84bf87a..f8e734b 100644
--- a/hw/ssi/pl022.c
+++ b/hw/ssi/pl022.c
@@ -9,6 +9,7 @@
#include "hw/sysbus.h"
#include "hw/ssi.h"
+#include "qemu/fifo.h"
//#define DEBUG_PL022 1
@@ -42,6 +43,8 @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);}
while (0)
#define TYPE_PL022 "pl022"
#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
+#define PL022_FIFO_DEPTH 8
+
typedef struct PL022State {
SysBusDevice parent_obj;
@@ -53,13 +56,10 @@ typedef struct PL022State {
uint32_t cpsr;
uint32_t is;
uint32_t im;
- /* The FIFO head points to the next empty entry. */
- int tx_fifo_head;
- int rx_fifo_head;
- int tx_fifo_len;
- int rx_fifo_len;
- uint16_t tx_fifo[8];
- uint16_t rx_fifo[8];
+
+ Fifo tx_fifo;
+ Fifo rx_fifo;
+
qemu_irq irq;
SSIBus *ssi;
} PL022State;
@@ -69,30 +69,38 @@ static const unsigned char pl022_id[8] =
static void pl022_update(PL022State *s)
{
+ uint32_t tx_fifo_len = fifo_num_used(&s->tx_fifo);
+ uint32_t rx_fifo_len = fifo_num_used(&s->rx_fifo);
+
s->sr = 0;
- if (s->tx_fifo_len == 0)
+ if (tx_fifo_len == 0) {
s->sr |= PL022_SR_TFE;
- if (s->tx_fifo_len != 8)
+ }
+ if (tx_fifo_len != PL022_FIFO_DEPTH) {
s->sr |= PL022_SR_TNF;
- if (s->rx_fifo_len != 0)
+ }
+ if (rx_fifo_len != 0) {
s->sr |= PL022_SR_RNE;
- if (s->rx_fifo_len == 8)
+ }
+ if (rx_fifo_len == PL022_FIFO_DEPTH) {
s->sr |= PL022_SR_RFF;
- if (s->tx_fifo_len)
+ }
+ if (tx_fifo_len) {
s->sr |= PL022_SR_BSY;
+ }
s->is = 0;
- if (s->rx_fifo_len >= 4)
+ if (rx_fifo_len >= 4) {
s->is |= PL022_INT_RX;
- if (s->tx_fifo_len <= 4)
+ }
+ if (tx_fifo_len <= 4) {
s->is |= PL022_INT_TX;
+ }
qemu_set_irq(s->irq, (s->is & s->im) != 0);
}
static void pl022_xfer(PL022State *s)
{
- int i;
- int o;
int val;
if ((s->cr1 & PL022_CR1_SSE) == 0) {
@@ -101,9 +109,8 @@ static void pl022_xfer(PL022State *s)
return;
}
- DPRINTF("Maybe xfer %d/%d\n", s->tx_fifo_len, s->rx_fifo_len);
- i = (s->tx_fifo_head - s->tx_fifo_len) & 7;
- o = s->rx_fifo_head;
+ DPRINTF("Maybe xfer %" PRId32 "/%" PRId32 "\n",
+ fifo_num_used(&s->tx_fifo), fifo_num_used(&s->rx_fifo));
/* ??? We do not emulate the line speed.
This may break some applications. The are two problematic cases:
(a) A driver feeds data into the TX FIFO until it is full,
@@ -116,21 +123,16 @@ static void pl022_xfer(PL022State *s)
cause the RX FIFO to overflow. In practice much transmit-only code
falls into (a) because it flushes the RX FIFO to determine when
the transfer has completed. */
- while (s->tx_fifo_len && s->rx_fifo_len < 8) {
+ while (!fifo_is_empty(&s->tx_fifo) && !fifo_is_full(&s->rx_fifo)) {
DPRINTF("xfer\n");
- val = s->tx_fifo[i];
+ val = fifo_pop16(&s->tx_fifo);
if (s->cr1 & PL022_CR1_LBM) {
/* Loopback mode. */
} else {
val = ssi_transfer(s->ssi, val);
}
- s->rx_fifo[o] = val & s->bitmask;
- i = (i + 1) & 7;
- o = (o + 1) & 7;
- s->tx_fifo_len--;
- s->rx_fifo_len++;
+ fifo_push16(&s->rx_fifo, val & s->bitmask);
}
- s->rx_fifo_head = o;
pl022_update(s);
}
@@ -149,10 +151,9 @@ static uint64_t pl022_read(void *opaque, hwaddr offset,
case 0x04: /* CR1 */
return s->cr1;
case 0x08: /* DR */
- if (s->rx_fifo_len) {
- val = s->rx_fifo[(s->rx_fifo_head - s->rx_fifo_len) & 7];
+ if (!fifo_is_empty(&s->rx_fifo)) {
+ val = fifo_pop16(&s->rx_fifo);
DPRINTF("RX %02x\n", val);
- s->rx_fifo_len--;
pl022_xfer(s);
} else {
val = 0;
@@ -198,11 +199,9 @@ static void pl022_write(void *opaque, hwaddr offset,
pl022_xfer(s);
break;
case 0x08: /* DR */
- if (s->tx_fifo_len < 8) {
+ if (!fifo_is_full(&s->tx_fifo)) {
DPRINTF("TX %02x\n", (unsigned)value);
- s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
- s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
- s->tx_fifo_len++;
+ fifo_push16(&s->tx_fifo, value & s->bitmask);
pl022_xfer(s);
}
break;
@@ -227,8 +226,8 @@ static void pl022_write(void *opaque, hwaddr offset,
static void pl022_reset(PL022State *s)
{
- s->rx_fifo_len = 0;
- s->tx_fifo_len = 0;
+ fifo_reset(&s->rx_fifo);
+ fifo_reset(&s->tx_fifo);
s->im = 0;
s->is = PL022_INT_TX;
s->sr = PL022_SR_TFE | PL022_SR_TNF;
@@ -242,9 +241,9 @@ static const MemoryRegionOps pl022_ops = {
static const VMStateDescription vmstate_pl022 = {
.name = "pl022_ssp",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT32(cr0, PL022State),
VMSTATE_UINT32(cr1, PL022State),
@@ -253,26 +252,8 @@ static const VMStateDescription vmstate_pl022 = {
VMSTATE_UINT32(cpsr, PL022State),
VMSTATE_UINT32(is, PL022State),
VMSTATE_UINT32(im, PL022State),
- VMSTATE_INT32(tx_fifo_head, PL022State),
- VMSTATE_INT32(rx_fifo_head, PL022State),
- VMSTATE_INT32(tx_fifo_len, PL022State),
- VMSTATE_INT32(rx_fifo_len, PL022State),
- VMSTATE_UINT16(tx_fifo[0], PL022State),
- VMSTATE_UINT16(rx_fifo[0], PL022State),
- VMSTATE_UINT16(tx_fifo[1], PL022State),
- VMSTATE_UINT16(rx_fifo[1], PL022State),
- VMSTATE_UINT16(tx_fifo[2], PL022State),
- VMSTATE_UINT16(rx_fifo[2], PL022State),
- VMSTATE_UINT16(tx_fifo[3], PL022State),
- VMSTATE_UINT16(rx_fifo[3], PL022State),
- VMSTATE_UINT16(tx_fifo[4], PL022State),
- VMSTATE_UINT16(rx_fifo[4], PL022State),
- VMSTATE_UINT16(tx_fifo[5], PL022State),
- VMSTATE_UINT16(rx_fifo[5], PL022State),
- VMSTATE_UINT16(tx_fifo[6], PL022State),
- VMSTATE_UINT16(rx_fifo[6], PL022State),
- VMSTATE_UINT16(tx_fifo[7], PL022State),
- VMSTATE_UINT16(rx_fifo[7], PL022State),
+ VMSTATE_FIFO(tx_fifo, PL022State),
+ VMSTATE_FIFO(rx_fifo, PL022State),
VMSTATE_END_OF_LIST()
}
};
@@ -286,6 +267,8 @@ static int pl022_init(SysBusDevice *sbd)
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
s->ssi = ssi_create_bus(dev, "ssi");
+ fifo_create(&s->tx_fifo, PL022_FIFO_DEPTH, 16);
+ fifo_create(&s->rx_fifo, PL022_FIFO_DEPTH, 16);
pl022_reset(s);
vmstate_register(dev, -1, &vmstate_pl022, s);
return 0;
--
1.9.1.1.gbb9f595