From patchwork Tue Apr 15 03:20:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Crosthwaite X-Patchwork-Id: 339144 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C793A140087 for ; Tue, 15 Apr 2014 13:21:30 +1000 (EST) Received: from localhost ([::1]:46774 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WZtw8-0004f1-Lg for incoming@patchwork.ozlabs.org; Mon, 14 Apr 2014 23:21:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36143) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WZtvU-0003AB-5r for qemu-devel@nongnu.org; Mon, 14 Apr 2014 23:20:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WZtvM-0005mL-CK for qemu-devel@nongnu.org; Mon, 14 Apr 2014 23:20:48 -0400 Received: from mail-qc0-f175.google.com ([209.85.216.175]:57154) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WZtvM-0005mH-7C for qemu-devel@nongnu.org; Mon, 14 Apr 2014 23:20:40 -0400 Received: by mail-qc0-f175.google.com with SMTP id e16so9702830qcx.20 for ; Mon, 14 Apr 2014 20:20:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=pZ5VkECO0skdho2qV1qBeo5Fzn42pXoR/77fo0oRJUY=; b=jiXhUQmLgiLrWFalW4xa7HeYKSdYJCcuCUN6VSia8TiYIoDd5HK9odPwfRJ1hmCeJK Y/8U6Jnhlsq3mucV7/5Yw0TQe/ajRhjBlPZXUK1XiXJ9Mmw+pMSKnzKLKGP+uTsPPU3U WqrtA9uCm0jHtn25nEi7hCNz+DN9xPrfKC7iv19e3jq3heW+4brjAX0cQdrlvjPXd4jo XzdfuJK12jC/3KyIlDShBfBqY/+Z1CO0fIy/AojoQyagaCtcKuhYqhabfeKSmEW8I26d SafuiSBgst8TX1B1W/DyZRBIEQHMf1PlP0C1CN69Y1qMZQRpIrNImB7/8rPQv9BybJ2C 5Xkw== X-Gm-Message-State: ALoCoQlFHLR7oOcywnggpGUEiBMQSkbrp+wiII68ItJHo+70NT65pz46IKItkOuJtZQH7LWWXO8V X-Received: by 10.224.60.71 with SMTP id o7mr24666627qah.38.1397532039860; Mon, 14 Apr 2014 20:20:39 -0700 (PDT) Received: from localhost ([149.199.62.254]) by mx.google.com with ESMTPSA id a6sm4380886qaj.15.2014.04.14.20.20.38 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 14 Apr 2014 20:20:39 -0700 (PDT) From: Peter Crosthwaite To: qemu-devel@nongnu.org Date: Mon, 14 Apr 2014 20:20:06 -0700 Message-Id: <8fda01258595ba2c6ba8b1b730c304264e861a78.1397531631.git.peter.crosthwaite@xilinx.com> X-Mailer: git-send-email 1.9.2.1.g06c4abd In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.216.175 Cc: b.galvani@gmail.com, peter.maydell@linaro.org, armbru@redhat.com, dslutz@verizon.com Subject: [Qemu-devel] [PATCH v4 4/4] ssi: pl022: Convert to use FIFO X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: Beniamino Galvani --- 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;