From patchwork Fri Feb 17 11:29:22 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 141776 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2BA07B6F9B for ; Fri, 17 Feb 2012 22:36:37 +1100 (EST) Received: from localhost ([::1]:50251 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyM78-0007sx-5f for incoming@patchwork.ozlabs.org; Fri, 17 Feb 2012 06:36:34 -0500 Received: from eggs.gnu.org ([140.186.70.92]:39182) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyM6u-0007rj-5Y for qemu-devel@nongnu.org; Fri, 17 Feb 2012 06:36:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RyM6h-0007tM-Hc for qemu-devel@nongnu.org; Fri, 17 Feb 2012 06:36:20 -0500 Received: from mnementh.archaic.org.uk ([81.2.115.146]:50496) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyM6g-0006Q6-Up for qemu-devel@nongnu.org; Fri, 17 Feb 2012 06:36:07 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1RyM0P-0003ox-Ds; Fri, 17 Feb 2012 11:29:37 +0000 From: Peter Maydell To: Anthony Liguori Date: Fri, 17 Feb 2012 11:29:22 +0000 Message-Id: <1329478177-14650-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1329478177-14650-1-git-send-email-peter.maydell@linaro.org> References: <1329478177-14650-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 81.2.115.146 Cc: qemu-devel@nongnu.org, Paul Brook Subject: [Qemu-devel] [PATCH 07/22] hw/lan9118: Add basic 16-bit mode support. 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 From: Evgeny Voevodin Signed-off-by: Evgeny Voevodin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/lan9118.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 118 insertions(+), 6 deletions(-) diff --git a/hw/lan9118.c b/hw/lan9118.c index aeb0c39..7b4fe87 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -235,11 +235,21 @@ typedef struct { int32_t rxp_offset; int32_t rxp_size; int32_t rxp_pad; + + uint32_t write_word_prev_offset; + uint32_t write_word_n; + uint16_t write_word_l; + uint16_t write_word_h; + uint32_t read_word_prev_offset; + uint32_t read_word_n; + uint32_t read_long; + + uint32_t mode_16bit; } lan9118_state; static const VMStateDescription vmstate_lan9118 = { .name = "lan9118", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_PTIMER(timer, lan9118_state), @@ -294,6 +304,14 @@ static const VMStateDescription vmstate_lan9118 = { VMSTATE_INT32(rxp_offset, lan9118_state), VMSTATE_INT32(rxp_size, lan9118_state), VMSTATE_INT32(rxp_pad, lan9118_state), + VMSTATE_UINT32_V(write_word_prev_offset, lan9118_state, 2), + VMSTATE_UINT32_V(write_word_n, lan9118_state, 2), + VMSTATE_UINT16_V(write_word_l, lan9118_state, 2), + VMSTATE_UINT16_V(write_word_h, lan9118_state, 2), + VMSTATE_UINT32_V(read_word_prev_offset, lan9118_state, 2), + VMSTATE_UINT32_V(read_word_n, lan9118_state, 2), + VMSTATE_UINT32_V(read_long, lan9118_state, 2), + VMSTATE_UINT32_V(mode_16bit, lan9118_state, 2), VMSTATE_END_OF_LIST() } }; @@ -390,7 +408,7 @@ static void lan9118_reset(DeviceState *d) s->fifo_int = 0x48000000; s->rx_cfg = 0; s->tx_cfg = 0; - s->hw_cfg = 0x00050000; + s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004; s->pmt_ctrl &= 0x45; s->gpio_cfg = 0; s->txp->fifo_used = 0; @@ -429,6 +447,9 @@ static void lan9118_reset(DeviceState *d) s->mac_mii_data = 0; s->mac_flow = 0; + s->read_word_n = 0; + s->write_word_n = 0; + phy_reset(s); s->eeprom_writable = 0; @@ -984,7 +1005,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset, { lan9118_state *s = (lan9118_state *)opaque; offset &= 0xff; - + //DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val); if (offset >= 0x20 && offset < 0x40) { /* TX FIFO */ @@ -1034,7 +1055,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset, /* SRST */ lan9118_reset(&s->busdev.qdev); } else { - s->hw_cfg = val & 0x003f300; + s->hw_cfg = (val & 0x003f300) | (s->hw_cfg & 0x4); } break; case CSR_RX_DP_CTRL: @@ -1113,6 +1134,46 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset, lan9118_update(s); } +static void lan9118_writew(void *opaque, target_phys_addr_t offset, + uint32_t val) +{ + lan9118_state *s = (lan9118_state *)opaque; + offset &= 0xff; + + if (s->write_word_prev_offset != (offset & ~0x3)) { + /* New offset, reset word counter */ + s->write_word_n = 0; + s->write_word_prev_offset = offset & ~0x3; + } + + if (offset & 0x2) { + s->write_word_h = val; + } else { + s->write_word_l = val; + } + + //DPRINTF("Writew reg 0x%02x = 0x%08x\n", (int)offset, val); + s->write_word_n++; + if (s->write_word_n == 2) { + s->write_word_n = 0; + lan9118_writel(s, offset & ~3, s->write_word_l + + (s->write_word_h << 16), 4); + } +} + +static void lan9118_16bit_mode_write(void *opaque, target_phys_addr_t offset, + uint64_t val, unsigned size) +{ + switch (size) { + case 2: + return lan9118_writew(opaque, offset, (uint32_t)val); + case 4: + return lan9118_writel(opaque, offset, val, size); + } + + hw_error("lan9118_write: Bad size 0x%x\n", size); +} + static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, unsigned size) { @@ -1149,7 +1210,7 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, case CSR_TX_CFG: return s->tx_cfg; case CSR_HW_CFG: - return s->hw_cfg | 0x4; + return s->hw_cfg; case CSR_RX_DP_CTRL: return 0; case CSR_RX_FIFO_INF: @@ -1187,12 +1248,60 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, return 0; } +static uint32_t lan9118_readw(void *opaque, target_phys_addr_t offset) +{ + lan9118_state *s = (lan9118_state *)opaque; + uint32_t val; + + if (s->read_word_prev_offset != (offset & ~0x3)) { + /* New offset, reset word counter */ + s->read_word_n = 0; + s->read_word_prev_offset = offset & ~0x3; + } + + s->read_word_n++; + if (s->read_word_n == 1) { + s->read_long = lan9118_readl(s, offset & ~3, 4); + } else { + s->read_word_n = 0; + } + + if (offset & 2) { + val = s->read_long >> 16; + } else { + val = s->read_long & 0xFFFF; + } + + //DPRINTF("Readw reg 0x%02x, val 0x%x\n", (int)offset, val); + return val; +} + +static uint64_t lan9118_16bit_mode_read(void *opaque, target_phys_addr_t offset, + unsigned size) +{ + switch (size) { + case 2: + return lan9118_readw(opaque, offset); + case 4: + return lan9118_readl(opaque, offset, size); + } + + hw_error("lan9118_read: Bad size 0x%x\n", size); + return 0; +} + static const MemoryRegionOps lan9118_mem_ops = { .read = lan9118_readl, .write = lan9118_writel, .endianness = DEVICE_NATIVE_ENDIAN, }; +static const MemoryRegionOps lan9118_16bit_mem_ops = { + .read = lan9118_16bit_mode_read, + .write = lan9118_16bit_mode_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + static void lan9118_cleanup(VLANClientState *nc) { lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1214,8 +1323,10 @@ static int lan9118_init1(SysBusDevice *dev) lan9118_state *s = FROM_SYSBUS(lan9118_state, dev); QEMUBH *bh; int i; + const MemoryRegionOps *mem_ops = + s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops; - memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100); + memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100); sysbus_init_mmio(dev, &s->mmio); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); @@ -1240,6 +1351,7 @@ static int lan9118_init1(SysBusDevice *dev) static Property lan9118_properties[] = { DEFINE_NIC_PROPERTIES(lan9118_state, conf), + DEFINE_PROP_UINT32("mode_16bit", lan9118_state, mode_16bit, 0), DEFINE_PROP_END_OF_LIST(), };