diff mbox

[v4,4/4] ssi: pl022: Convert to use FIFO

Message ID 8fda01258595ba2c6ba8b1b730c304264e861a78.1397531631.git.peter.crosthwaite@xilinx.com
State New
Headers show

Commit Message

Peter Crosthwaite April 15, 2014, 3:20 a.m. UTC
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 <peter.crosthwaite@xilinx.com>
---

 hw/ssi/pl022.c | 101 ++++++++++++++++++++++++---------------------------------
 1 file changed, 42 insertions(+), 59 deletions(-)

Comments

Beniamino Galvani April 15, 2014, 6:45 p.m. UTC | #1
On Mon, Apr 14, 2014 at 08:20:06PM -0700, Peter Crosthwaite wrote:
> 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 <peter.crosthwaite@xilinx.com>
> ---
> 
>  hw/ssi/pl022.c | 101 ++++++++++++++++++++++++---------------------------------
>  1 file changed, 42 insertions(+), 59 deletions(-)

Reviewed-by: Beniamino Galvani <b.galvani@gmail.com>
diff mbox

Patch

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;