qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes
@ 2011-04-12 22:29 Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 1/4] lm32: fix exception handling Michael Walle
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Michael Walle @ 2011-04-12 22:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias

This patchset combines some lm32/bsp fixes and support for the new
Milkymist minimac2 hardware.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/4] lm32: fix exception handling
  2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
@ 2011-04-12 22:29 ` Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 2/4] milkymist-vgafb: fix console resizing Michael Walle
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Michael Walle @ 2011-04-12 22:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias, Michael Walle

Global interrupt enable bit is already saved within the exception handler
helper routine. Thus remove extra code in translation routines.

Additionally, debug exceptions has always DEBA as base address.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 target-lm32/helper.c    |    6 +-----
 target-lm32/translate.c |   26 --------------------------
 2 files changed, 1 insertions(+), 31 deletions(-)

diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 318e2cf..4f3e7e0 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -76,11 +76,7 @@ void do_interrupt(CPUState *env)
         env->regs[R_BA] = env->pc;
         env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
         env->ie &= ~IE_IE;
-        if (env->dc & DC_RE) {
-            env->pc = env->deba + (env->exception_index * 32);
-        } else {
-            env->pc = env->eba + (env->exception_index * 32);
-        }
+        env->pc = env->deba + (env->exception_index * 32);
         log_cpu_state_mask(CPU_LOG_INT, env, 0);
         break;
     default:
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index ccdf959..2cfa253 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -614,36 +614,10 @@ static void dec_scall(DisasContext *dc)
     t0 = tcg_temp_new();
     l1 = gen_new_label();
 
-    /* save IE.IE */
-    tcg_gen_andi_tl(t0, cpu_ie, IE_IE);
-
-    /* IE.IE = 0 */
-    tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
-
     if (dc->imm5 == 7) {
-        /* IE.EIE = IE.IE */
-        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_EIE);
-        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
-        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_EIE);
-        gen_set_label(l1);
-
-        /* gpr[ea] = PC */
-        tcg_gen_movi_tl(cpu_R[R_EA], dc->pc);
-        tcg_temp_free(t0);
-
         tcg_gen_movi_tl(cpu_pc, dc->pc);
         t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
     } else {
-        /* IE.BIE = IE.IE */
-        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_BIE);
-        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
-        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_BIE);
-        gen_set_label(l1);
-
-        /* gpr[ba] = PC */
-        tcg_gen_movi_tl(cpu_R[R_BA], dc->pc);
-        tcg_temp_free(t0);
-
         tcg_gen_movi_tl(cpu_pc, dc->pc);
         t_gen_raise_exception(dc, EXCP_BREAKPOINT);
     }
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/4] milkymist-vgafb: fix console resizing
  2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 1/4] lm32: fix exception handling Michael Walle
@ 2011-04-12 22:29 ` Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 3/4] milkymist-sysctl: fix timers Michael Walle
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Michael Walle @ 2011-04-12 22:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias, Michael Walle

After enabling the framebuffer, ensure that the console is resized.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 hw/milkymist-vgafb.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 8922731..2e55e42 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -199,6 +199,9 @@ vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     addr >>= 2;
     switch (addr) {
     case R_CTRL:
+        s->regs[addr] = value;
+        vgafb_resize(s);
+        break;
     case R_HSYNC_START:
     case R_HSYNC_END:
     case R_HSCAN:
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 3/4] milkymist-sysctl: fix timers
  2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 1/4] lm32: fix exception handling Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 2/4] milkymist-vgafb: fix console resizing Michael Walle
@ 2011-04-12 22:29 ` Michael Walle
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 4/4] lm32: add Milkymist Minimac2 support Michael Walle
  2011-05-02 20:10 ` [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
  4 siblings, 0 replies; 6+ messages in thread
From: Michael Walle @ 2011-04-12 22:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias, Michael Walle

Prevent timers from firing right after starting.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 hw/milkymist-sysctl.c |   26 +++++++-------------------
 1 files changed, 7 insertions(+), 19 deletions(-)

diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index eaea543..6bd0cb9 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -140,24 +140,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     case R_GPIO_OUT:
     case R_GPIO_INTEN:
     case R_TIMER0_COUNTER:
-        if (value > s->regs[R_TIMER0_COUNTER]) {
-            value = s->regs[R_TIMER0_COUNTER];
-            error_report("milkymist_sysctl: timer0: trying to write a "
-                    "value greater than the limit. Clipping.");
-        }
-        /* milkymist timer counts up */
-        value = s->regs[R_TIMER0_COUNTER] - value;
-        ptimer_set_count(s->ptimer0, value);
-        break;
     case R_TIMER1_COUNTER:
-        if (value > s->regs[R_TIMER1_COUNTER]) {
-            value = s->regs[R_TIMER1_COUNTER];
-            error_report("milkymist_sysctl: timer1: trying to write a "
-                    "value greater than the limit. Clipping.");
-        }
-        /* milkymist timer counts up */
-        value = s->regs[R_TIMER1_COUNTER] - value;
-        ptimer_set_count(s->ptimer1, value);
+        s->regs[addr] = value;
         break;
     case R_TIMER0_COMPARE:
         ptimer_set_limit(s->ptimer0, value, 0);
@@ -170,10 +154,12 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     case R_TIMER0_CONTROL:
         s->regs[addr] = value;
         if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
-            trace_milkymist_sysctl_start_timer1();
+            trace_milkymist_sysctl_start_timer0();
+            ptimer_set_count(s->ptimer0,
+                    s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]);
             ptimer_run(s->ptimer0, 0);
         } else {
-            trace_milkymist_sysctl_stop_timer1();
+            trace_milkymist_sysctl_stop_timer0();
             ptimer_stop(s->ptimer0);
         }
         break;
@@ -181,6 +167,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
         s->regs[addr] = value;
         if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
             trace_milkymist_sysctl_start_timer1();
+            ptimer_set_count(s->ptimer1,
+                    s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]);
             ptimer_run(s->ptimer1, 0);
         } else {
             trace_milkymist_sysctl_stop_timer1();
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 4/4] lm32: add Milkymist Minimac2 support
  2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
                   ` (2 preceding siblings ...)
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 3/4] milkymist-sysctl: fix timers Michael Walle
@ 2011-04-12 22:29 ` Michael Walle
  2011-05-02 20:10 ` [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
  4 siblings, 0 replies; 6+ messages in thread
From: Michael Walle @ 2011-04-12 22:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias, Michael Walle

This patch adds support for Milkymist's minimal Ethernet MAC v2. It
superseds minimac1.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 Makefile.target         |    2 +-
 hw/milkymist-hw.h       |   20 ++
 hw/milkymist-minimac.c  |  568 -----------------------------------------------
 hw/milkymist-minimac2.c |  539 ++++++++++++++++++++++++++++++++++++++++++++
 hw/milkymist.c          |    2 +-
 trace-events            |   23 +-
 6 files changed, 573 insertions(+), 581 deletions(-)
 delete mode 100644 hw/milkymist-minimac.c
 create mode 100644 hw/milkymist-minimac2.c

diff --git a/Makefile.target b/Makefile.target
index d5761b7..89a59fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -271,7 +271,7 @@ obj-lm32-y += lm32_sys.o
 obj-lm32-y += milkymist-ac97.o
 obj-lm32-y += milkymist-hpdmc.o
 obj-lm32-y += milkymist-memcard.o
-obj-lm32-y += milkymist-minimac.o
+obj-lm32-y += milkymist-minimac2.o
 obj-lm32-y += milkymist-pfpu.o
 obj-lm32-y += milkymist-softusb.o
 obj-lm32-y += milkymist-sysctl.o
diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index 15acdbc..20de68e 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -1,6 +1,9 @@
 #ifndef QEMU_HW_MILKYMIST_H
 #define QEMU_HW_MILKYMIST_H
 
+#include "qdev.h"
+#include "qdev-addr.h"
+
 static inline DeviceState *milkymist_uart_create(target_phys_addr_t base,
         qemu_irq rx_irq, qemu_irq tx_irq)
 {
@@ -183,6 +186,23 @@ static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base,
     return dev;
 }
 
+static inline DeviceState *milkymist_minimac2_create(target_phys_addr_t base,
+        target_phys_addr_t buffers_base, qemu_irq rx_irq, qemu_irq tx_irq)
+{
+    DeviceState *dev;
+
+    qemu_check_nic_model(&nd_table[0], "minimac2");
+    dev = qdev_create(NULL, "milkymist-minimac2");
+    qdev_prop_set_taddr(dev, "buffers_base", buffers_base);
+    qdev_set_nic_properties(dev, &nd_table[0]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+
+    return dev;
+}
+
 static inline DeviceState *milkymist_softusb_create(target_phys_addr_t base,
         qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size,
         uint32_t dmem_base, uint32_t dmem_size)
diff --git a/hw/milkymist-minimac.c b/hw/milkymist-minimac.c
deleted file mode 100644
index b07f18d..0000000
--- a/hw/milkymist-minimac.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- *  QEMU model of the Milkymist minimac block.
- *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- *   http://www.milkymist.org/socdoc/minimac.pdf
- *
- */
-
-#include "hw.h"
-#include "sysbus.h"
-#include "trace.h"
-#include "net.h"
-#include "qemu-error.h"
-
-#include <zlib.h>
-
-enum {
-    R_SETUP = 0,
-    R_MDIO,
-    R_STATE0,
-    R_ADDR0,
-    R_COUNT0,
-    R_STATE1,
-    R_ADDR1,
-    R_COUNT1,
-    R_STATE2,
-    R_ADDR2,
-    R_COUNT2,
-    R_STATE3,
-    R_ADDR3,
-    R_COUNT3,
-    R_TXADDR,
-    R_TXCOUNT,
-    R_MAX
-};
-
-enum {
-    SETUP_RX_RST = (1<<0),
-    SETUP_TX_RST = (1<<2),
-};
-
-enum {
-    MDIO_DO  = (1<<0),
-    MDIO_DI  = (1<<1),
-    MDIO_OE  = (1<<2),
-    MDIO_CLK = (1<<3),
-};
-
-enum {
-    STATE_EMPTY   = 0,
-    STATE_LOADED  = 1,
-    STATE_PENDING = 2,
-};
-
-enum {
-    MDIO_OP_WRITE = 1,
-    MDIO_OP_READ  = 2,
-};
-
-enum mdio_state {
-    MDIO_STATE_IDLE,
-    MDIO_STATE_READING,
-    MDIO_STATE_WRITING,
-};
-
-enum {
-    R_PHY_ID1  = 2,
-    R_PHY_ID2  = 3,
-    R_PHY_MAX  = 32
-};
-
-#define MINIMAC_MTU 1530
-
-struct MilkymistMinimacMdioState {
-    int last_clk;
-    int count;
-    uint32_t data;
-    uint16_t data_out;
-    int state;
-
-    uint8_t phy_addr;
-    uint8_t reg_addr;
-};
-typedef struct MilkymistMinimacMdioState MilkymistMinimacMdioState;
-
-struct MilkymistMinimacState {
-    SysBusDevice busdev;
-    NICState *nic;
-    NICConf conf;
-    char *phy_model;
-
-    qemu_irq rx_irq;
-    qemu_irq tx_irq;
-
-    uint32_t regs[R_MAX];
-
-    MilkymistMinimacMdioState mdio;
-
-    uint16_t phy_regs[R_PHY_MAX];
-};
-typedef struct MilkymistMinimacState MilkymistMinimacState;
-
-static const uint8_t preamble_sfd[] = {
-        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
-};
-
-static void minimac_mdio_write_reg(MilkymistMinimacState *s,
-        uint8_t phy_addr, uint8_t reg_addr, uint16_t value)
-{
-    trace_milkymist_minimac_mdio_write(phy_addr, reg_addr, value);
-
-    /* nop */
-}
-
-static uint16_t minimac_mdio_read_reg(MilkymistMinimacState *s,
-        uint8_t phy_addr, uint8_t reg_addr)
-{
-    uint16_t r = s->phy_regs[reg_addr];
-
-    trace_milkymist_minimac_mdio_read(phy_addr, reg_addr, r);
-
-    return r;
-}
-
-static void minimac_update_mdio(MilkymistMinimacState *s)
-{
-    MilkymistMinimacMdioState *m = &s->mdio;
-
-    /* detect rising clk edge */
-    if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) {
-        /* shift data in */
-        int bit = ((s->regs[R_MDIO] & MDIO_DO)
-                   && (s->regs[R_MDIO] & MDIO_OE)) ? 1 : 0;
-        m->data = (m->data << 1) | bit;
-
-        /* check for sync */
-        if (m->data == 0xffffffff) {
-            m->count = 32;
-        }
-
-        if (m->count == 16) {
-            uint8_t start = (m->data >> 14) & 0x3;
-            uint8_t op = (m->data >> 12) & 0x3;
-            uint8_t ta = (m->data) & 0x3;
-
-            if (start == 1 && op == MDIO_OP_WRITE && ta == 2) {
-                m->state = MDIO_STATE_WRITING;
-            } else if (start == 1 && op == MDIO_OP_READ && (ta & 1) == 0) {
-                m->state = MDIO_STATE_READING;
-            } else {
-                m->state = MDIO_STATE_IDLE;
-            }
-
-            if (m->state != MDIO_STATE_IDLE) {
-                m->phy_addr = (m->data >> 7) & 0x1f;
-                m->reg_addr = (m->data >> 2) & 0x1f;
-            }
-
-            if (m->state == MDIO_STATE_READING) {
-                m->data_out = minimac_mdio_read_reg(s, m->phy_addr,
-                        m->reg_addr);
-            }
-        }
-
-        if (m->count < 16 && m->state == MDIO_STATE_READING) {
-            int bit = (m->data_out & 0x8000) ? 1 : 0;
-            m->data_out <<= 1;
-
-            if (bit) {
-                s->regs[R_MDIO] |= MDIO_DI;
-            } else {
-                s->regs[R_MDIO] &= ~MDIO_DI;
-            }
-        }
-
-        if (m->count == 0 && m->state) {
-            if (m->state == MDIO_STATE_WRITING) {
-                uint16_t data = m->data & 0xffff;
-                minimac_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
-            }
-            m->state = MDIO_STATE_IDLE;
-        }
-        m->count--;
-    }
-
-    m->last_clk = (s->regs[R_MDIO] & MDIO_CLK) ? 1 : 0;
-}
-
-static size_t assemble_frame(uint8_t *buf, size_t size,
-        const uint8_t *payload, size_t payload_size)
-{
-    uint32_t crc;
-
-    if (size < payload_size + 12) {
-        error_report("milkymist_minimac: received too big ethernet frame");
-        return 0;
-    }
-
-    /* prepend preamble and sfd */
-    memcpy(buf, preamble_sfd, 8);
-
-    /* now copy the payload */
-    memcpy(buf + 8, payload, payload_size);
-
-    /* pad frame if needed */
-    if (payload_size < 60) {
-        memset(buf + payload_size + 8, 0, 60 - payload_size);
-        payload_size = 60;
-    }
-
-    /* append fcs */
-    crc = cpu_to_le32(crc32(0, buf + 8, payload_size));
-    memcpy(buf + payload_size + 8, &crc, 4);
-
-    return payload_size + 12;
-}
-
-static void minimac_tx(MilkymistMinimacState *s)
-{
-    uint8_t buf[MINIMAC_MTU];
-    uint32_t txcount = s->regs[R_TXCOUNT];
-
-    /* do nothing if transmission logic is in reset */
-    if (s->regs[R_SETUP] & SETUP_TX_RST) {
-        return;
-    }
-
-    if (txcount < 64) {
-        error_report("milkymist_minimac: ethernet frame too small (%u < %u)\n",
-                txcount, 64);
-        return;
-    }
-
-    if (txcount > MINIMAC_MTU) {
-        error_report("milkymist_minimac: MTU exceeded (%u > %u)\n",
-                txcount, MINIMAC_MTU);
-        return;
-    }
-
-    /* dma */
-    cpu_physical_memory_read(s->regs[R_TXADDR], buf, txcount);
-
-    if (memcmp(buf, preamble_sfd, 8) != 0) {
-        error_report("milkymist_minimac: frame doesn't contain the preamble "
-                "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n",
-                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
-        return;
-    }
-
-    trace_milkymist_minimac_tx_frame(txcount - 12);
-
-    /* send packet, skipping preamble and sfd */
-    qemu_send_packet_raw(&s->nic->nc, buf + 8, txcount - 12);
-
-    s->regs[R_TXCOUNT] = 0;
-
-    trace_milkymist_minimac_pulse_irq_tx();
-    qemu_irq_pulse(s->tx_irq);
-}
-
-static ssize_t minimac_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
-{
-    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    uint32_t r_addr;
-    uint32_t r_count;
-    uint32_t r_state;
-
-    uint8_t frame_buf[MINIMAC_MTU];
-    size_t frame_size;
-
-    trace_milkymist_minimac_rx_frame(buf, size);
-
-    /* discard frames if nic is in reset */
-    if (s->regs[R_SETUP] & SETUP_RX_RST) {
-        return size;
-    }
-
-    /* choose appropriate slot */
-    if (s->regs[R_STATE0] == STATE_LOADED) {
-        r_addr = R_ADDR0;
-        r_count = R_COUNT0;
-        r_state = R_STATE0;
-    } else if (s->regs[R_STATE1] == STATE_LOADED) {
-        r_addr = R_ADDR1;
-        r_count = R_COUNT1;
-        r_state = R_STATE1;
-    } else if (s->regs[R_STATE2] == STATE_LOADED) {
-        r_addr = R_ADDR2;
-        r_count = R_COUNT2;
-        r_state = R_STATE2;
-    } else if (s->regs[R_STATE3] == STATE_LOADED) {
-        r_addr = R_ADDR3;
-        r_count = R_COUNT3;
-        r_state = R_STATE3;
-    } else {
-        trace_milkymist_minimac_drop_rx_frame(buf);
-        return size;
-    }
-
-    /* assemble frame */
-    frame_size = assemble_frame(frame_buf, sizeof(frame_buf), buf, size);
-
-    if (frame_size == 0) {
-        return size;
-    }
-
-    trace_milkymist_minimac_rx_transfer(buf, frame_size);
-
-    /* do dma */
-    cpu_physical_memory_write(s->regs[r_addr], frame_buf, frame_size);
-
-    /* update slot */
-    s->regs[r_count] = frame_size;
-    s->regs[r_state] = STATE_PENDING;
-
-    trace_milkymist_minimac_pulse_irq_rx();
-    qemu_irq_pulse(s->rx_irq);
-
-    return size;
-}
-
-static uint32_t
-minimac_read(void *opaque, target_phys_addr_t addr)
-{
-    MilkymistMinimacState *s = opaque;
-    uint32_t r = 0;
-
-    addr >>= 2;
-    switch (addr) {
-    case R_SETUP:
-    case R_MDIO:
-    case R_STATE0:
-    case R_ADDR0:
-    case R_COUNT0:
-    case R_STATE1:
-    case R_ADDR1:
-    case R_COUNT1:
-    case R_STATE2:
-    case R_ADDR2:
-    case R_COUNT2:
-    case R_STATE3:
-    case R_ADDR3:
-    case R_COUNT3:
-    case R_TXADDR:
-    case R_TXCOUNT:
-        r = s->regs[addr];
-        break;
-
-    default:
-        error_report("milkymist_minimac: read access to unknown register 0x"
-                TARGET_FMT_plx, addr << 2);
-        break;
-    }
-
-    trace_milkymist_minimac_memory_read(addr << 2, r);
-
-    return r;
-}
-
-static void
-minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    MilkymistMinimacState *s = opaque;
-
-    trace_milkymist_minimac_memory_read(addr, value);
-
-    addr >>= 2;
-    switch (addr) {
-    case R_MDIO:
-    {
-        /* MDIO_DI is read only */
-        int mdio_di = (s->regs[R_MDIO] & MDIO_DI);
-        s->regs[R_MDIO] = value;
-        if (mdio_di) {
-            s->regs[R_MDIO] |= mdio_di;
-        } else {
-            s->regs[R_MDIO] &= ~mdio_di;
-        }
-
-        minimac_update_mdio(s);
-    } break;
-    case R_TXCOUNT:
-        s->regs[addr] = value;
-        if (value > 0) {
-            minimac_tx(s);
-        }
-        break;
-    case R_SETUP:
-    case R_STATE0:
-    case R_ADDR0:
-    case R_COUNT0:
-    case R_STATE1:
-    case R_ADDR1:
-    case R_COUNT1:
-    case R_STATE2:
-    case R_ADDR2:
-    case R_COUNT2:
-    case R_STATE3:
-    case R_ADDR3:
-    case R_COUNT3:
-    case R_TXADDR:
-        s->regs[addr] = value;
-        break;
-
-    default:
-        error_report("milkymist_minimac: write access to unknown register 0x"
-                TARGET_FMT_plx, addr << 2);
-        break;
-    }
-}
-
-static CPUReadMemoryFunc * const minimac_read_fn[] = {
-    NULL,
-    NULL,
-    &minimac_read,
-};
-
-static CPUWriteMemoryFunc * const minimac_write_fn[] = {
-    NULL,
-    NULL,
-    &minimac_write,
-};
-
-static int minimac_can_rx(VLANClientState *nc)
-{
-    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    /* discard frames if nic is in reset */
-    if (s->regs[R_SETUP] & SETUP_RX_RST) {
-        return 1;
-    }
-
-    if (s->regs[R_STATE0] == STATE_LOADED) {
-        return 1;
-    }
-    if (s->regs[R_STATE1] == STATE_LOADED) {
-        return 1;
-    }
-    if (s->regs[R_STATE2] == STATE_LOADED) {
-        return 1;
-    }
-    if (s->regs[R_STATE3] == STATE_LOADED) {
-        return 1;
-    }
-
-    return 0;
-}
-
-static void minimac_cleanup(VLANClientState *nc)
-{
-    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    s->nic = NULL;
-}
-
-static void milkymist_minimac_reset(DeviceState *d)
-{
-    MilkymistMinimacState *s =
-            container_of(d, MilkymistMinimacState, busdev.qdev);
-    int i;
-
-    for (i = 0; i < R_MAX; i++) {
-        s->regs[i] = 0;
-    }
-    for (i = 0; i < R_PHY_MAX; i++) {
-        s->phy_regs[i] = 0;
-    }
-
-    /* defaults */
-    s->phy_regs[R_PHY_ID1] = 0x0022; /* Micrel KSZ8001L */
-    s->phy_regs[R_PHY_ID2] = 0x161a;
-}
-
-static NetClientInfo net_milkymist_minimac_info = {
-    .type = NET_CLIENT_TYPE_NIC,
-    .size = sizeof(NICState),
-    .can_receive = minimac_can_rx,
-    .receive = minimac_rx,
-    .cleanup = minimac_cleanup,
-};
-
-static int milkymist_minimac_init(SysBusDevice *dev)
-{
-    MilkymistMinimacState *s = FROM_SYSBUS(typeof(*s), dev);
-    int regs;
-
-    sysbus_init_irq(dev, &s->rx_irq);
-    sysbus_init_irq(dev, &s->tx_irq);
-
-    regs = cpu_register_io_memory(minimac_read_fn, minimac_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, regs);
-
-    qemu_macaddr_default_if_unset(&s->conf.macaddr);
-    s->nic = qemu_new_nic(&net_milkymist_minimac_info, &s->conf,
-                          dev->qdev.info->name, dev->qdev.id, s);
-    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_milkymist_minimac_mdio = {
-    .name = "milkymist_minimac_mdio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT32(last_clk, MilkymistMinimacMdioState),
-        VMSTATE_INT32(count, MilkymistMinimacMdioState),
-        VMSTATE_UINT32(data, MilkymistMinimacMdioState),
-        VMSTATE_UINT16(data_out, MilkymistMinimacMdioState),
-        VMSTATE_INT32(state, MilkymistMinimacMdioState),
-        VMSTATE_UINT8(phy_addr, MilkymistMinimacMdioState),
-        VMSTATE_UINT8(reg_addr, MilkymistMinimacMdioState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_milkymist_minimac = {
-    .name = "milkymist-minimac",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, MilkymistMinimacState, R_MAX),
-        VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimacState, R_PHY_MAX),
-        VMSTATE_STRUCT(mdio, MilkymistMinimacState, 0,
-                vmstate_milkymist_minimac_mdio, MilkymistMinimacMdioState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static SysBusDeviceInfo milkymist_minimac_info = {
-    .init = milkymist_minimac_init,
-    .qdev.name  = "milkymist-minimac",
-    .qdev.size  = sizeof(MilkymistMinimacState),
-    .qdev.vmsd  = &vmstate_milkymist_minimac,
-    .qdev.reset = milkymist_minimac_reset,
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(MilkymistMinimacState, conf),
-        DEFINE_PROP_STRING("phy_model", MilkymistMinimacState, phy_model),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void milkymist_minimac_register(void)
-{
-    sysbus_register_withprop(&milkymist_minimac_info);
-}
-
-device_init(milkymist_minimac_register)
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
new file mode 100644
index 0000000..c4e2818
--- /dev/null
+++ b/hw/milkymist-minimac2.c
@@ -0,0 +1,539 @@
+/*
+ *  QEMU model of the Milkymist minimac2 block.
+ *
+ *  Copyright (c) 2011 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   not available yet
+ *
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "net.h"
+#include "qemu-error.h"
+#include "qdev-addr.h"
+
+#include <zlib.h>
+
+enum {
+    R_SETUP = 0,
+    R_MDIO,
+    R_STATE0,
+    R_COUNT0,
+    R_STATE1,
+    R_COUNT1,
+    R_TXCOUNT,
+    R_MAX
+};
+
+enum {
+    SETUP_PHY_RST = (1<<0),
+};
+
+enum {
+    MDIO_DO  = (1<<0),
+    MDIO_DI  = (1<<1),
+    MDIO_OE  = (1<<2),
+    MDIO_CLK = (1<<3),
+};
+
+enum {
+    STATE_EMPTY   = 0,
+    STATE_LOADED  = 1,
+    STATE_PENDING = 2,
+};
+
+enum {
+    MDIO_OP_WRITE = 1,
+    MDIO_OP_READ  = 2,
+};
+
+enum mdio_state {
+    MDIO_STATE_IDLE,
+    MDIO_STATE_READING,
+    MDIO_STATE_WRITING,
+};
+
+enum {
+    R_PHY_ID1  = 2,
+    R_PHY_ID2  = 3,
+    R_PHY_MAX  = 32
+};
+
+#define MINIMAC2_MTU 1530
+#define MINIMAC2_BUFFER_SIZE 2048
+
+struct MilkymistMinimac2MdioState {
+    int last_clk;
+    int count;
+    uint32_t data;
+    uint16_t data_out;
+    int state;
+
+    uint8_t phy_addr;
+    uint8_t reg_addr;
+};
+typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState;
+
+struct MilkymistMinimac2State {
+    SysBusDevice busdev;
+    NICState *nic;
+    NICConf conf;
+    char *phy_model;
+    target_phys_addr_t buffers_base;
+
+    qemu_irq rx_irq;
+    qemu_irq tx_irq;
+
+    uint32_t regs[R_MAX];
+
+    MilkymistMinimac2MdioState mdio;
+
+    uint16_t phy_regs[R_PHY_MAX];
+
+    uint8_t *rx0_buf;
+    uint8_t *rx1_buf;
+    uint8_t *tx_buf;
+};
+typedef struct MilkymistMinimac2State MilkymistMinimac2State;
+
+static const uint8_t preamble_sfd[] = {
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
+};
+
+static void minimac2_mdio_write_reg(MilkymistMinimac2State *s,
+        uint8_t phy_addr, uint8_t reg_addr, uint16_t value)
+{
+    trace_milkymist_minimac2_mdio_write(phy_addr, reg_addr, value);
+
+    /* nop */
+}
+
+static uint16_t minimac2_mdio_read_reg(MilkymistMinimac2State *s,
+        uint8_t phy_addr, uint8_t reg_addr)
+{
+    uint16_t r = s->phy_regs[reg_addr];
+
+    trace_milkymist_minimac2_mdio_read(phy_addr, reg_addr, r);
+
+    return r;
+}
+
+static void minimac2_update_mdio(MilkymistMinimac2State *s)
+{
+    MilkymistMinimac2MdioState *m = &s->mdio;
+
+    /* detect rising clk edge */
+    if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) {
+        /* shift data in */
+        int bit = ((s->regs[R_MDIO] & MDIO_DO)
+                   && (s->regs[R_MDIO] & MDIO_OE)) ? 1 : 0;
+        m->data = (m->data << 1) | bit;
+
+        /* check for sync */
+        if (m->data == 0xffffffff) {
+            m->count = 32;
+        }
+
+        if (m->count == 16) {
+            uint8_t start = (m->data >> 14) & 0x3;
+            uint8_t op = (m->data >> 12) & 0x3;
+            uint8_t ta = (m->data) & 0x3;
+
+            if (start == 1 && op == MDIO_OP_WRITE && ta == 2) {
+                m->state = MDIO_STATE_WRITING;
+            } else if (start == 1 && op == MDIO_OP_READ && (ta & 1) == 0) {
+                m->state = MDIO_STATE_READING;
+            } else {
+                m->state = MDIO_STATE_IDLE;
+            }
+
+            if (m->state != MDIO_STATE_IDLE) {
+                m->phy_addr = (m->data >> 7) & 0x1f;
+                m->reg_addr = (m->data >> 2) & 0x1f;
+            }
+
+            if (m->state == MDIO_STATE_READING) {
+                m->data_out = minimac2_mdio_read_reg(s, m->phy_addr,
+                        m->reg_addr);
+            }
+        }
+
+        if (m->count < 16 && m->state == MDIO_STATE_READING) {
+            int bit = (m->data_out & 0x8000) ? 1 : 0;
+            m->data_out <<= 1;
+
+            if (bit) {
+                s->regs[R_MDIO] |= MDIO_DI;
+            } else {
+                s->regs[R_MDIO] &= ~MDIO_DI;
+            }
+        }
+
+        if (m->count == 0 && m->state) {
+            if (m->state == MDIO_STATE_WRITING) {
+                uint16_t data = m->data & 0xffff;
+                minimac2_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
+            }
+            m->state = MDIO_STATE_IDLE;
+        }
+        m->count--;
+    }
+
+    m->last_clk = (s->regs[R_MDIO] & MDIO_CLK) ? 1 : 0;
+}
+
+static size_t assemble_frame(uint8_t *buf, size_t size,
+        const uint8_t *payload, size_t payload_size)
+{
+    uint32_t crc;
+
+    if (size < payload_size + 12) {
+        error_report("milkymist_minimac2: received too big ethernet frame");
+        return 0;
+    }
+
+    /* prepend preamble and sfd */
+    memcpy(buf, preamble_sfd, 8);
+
+    /* now copy the payload */
+    memcpy(buf + 8, payload, payload_size);
+
+    /* pad frame if needed */
+    if (payload_size < 60) {
+        memset(buf + payload_size + 8, 0, 60 - payload_size);
+        payload_size = 60;
+    }
+
+    /* append fcs */
+    crc = cpu_to_le32(crc32(0, buf + 8, payload_size));
+    memcpy(buf + payload_size + 8, &crc, 4);
+
+    return payload_size + 12;
+}
+
+static void minimac2_tx(MilkymistMinimac2State *s)
+{
+    uint32_t txcount = s->regs[R_TXCOUNT];
+    uint8_t *buf = s->tx_buf;
+
+    if (txcount < 64) {
+        error_report("milkymist_minimac2: ethernet frame too small (%u < %u)\n",
+                txcount, 64);
+        goto err;
+    }
+
+    if (txcount > MINIMAC2_MTU) {
+        error_report("milkymist_minimac2: MTU exceeded (%u > %u)\n",
+                txcount, MINIMAC2_MTU);
+        goto err;
+    }
+
+    if (memcmp(buf, preamble_sfd, 8) != 0) {
+        error_report("milkymist_minimac2: frame doesn't contain the preamble "
+                "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n",
+                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+        goto err;
+    }
+
+    trace_milkymist_minimac2_tx_frame(txcount - 12);
+
+    /* send packet, skipping preamble and sfd */
+    qemu_send_packet_raw(&s->nic->nc, buf + 8, txcount - 12);
+
+    s->regs[R_TXCOUNT] = 0;
+
+err:
+    trace_milkymist_minimac2_pulse_irq_tx();
+    qemu_irq_pulse(s->tx_irq);
+}
+
+static void update_rx_interrupt(MilkymistMinimac2State *s)
+{
+    if (s->regs[R_STATE0] == STATE_PENDING
+            || s->regs[R_STATE1] == STATE_PENDING) {
+        trace_milkymist_minimac2_raise_irq_rx();
+        qemu_irq_raise(s->rx_irq);
+    } else {
+        trace_milkymist_minimac2_lower_irq_rx();
+        qemu_irq_lower(s->rx_irq);
+    }
+}
+
+static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    uint32_t r_count;
+    uint32_t r_state;
+    uint8_t *rx_buf;
+
+    size_t frame_size;
+
+    trace_milkymist_minimac2_rx_frame(buf, size);
+
+    /* choose appropriate slot */
+    if (s->regs[R_STATE0] == STATE_LOADED) {
+        r_count = R_COUNT0;
+        r_state = R_STATE0;
+        rx_buf = s->rx0_buf;
+    } else if (s->regs[R_STATE1] == STATE_LOADED) {
+        r_count = R_COUNT1;
+        r_state = R_STATE1;
+        rx_buf = s->rx1_buf;
+    } else {
+        trace_milkymist_minimac2_drop_rx_frame(buf);
+        return size;
+    }
+
+    /* assemble frame */
+    frame_size = assemble_frame(rx_buf, MINIMAC2_BUFFER_SIZE, buf, size);
+
+    if (frame_size == 0) {
+        return size;
+    }
+
+    trace_milkymist_minimac2_rx_transfer(rx_buf, frame_size);
+
+    /* update slot */
+    s->regs[r_count] = frame_size;
+    s->regs[r_state] = STATE_PENDING;
+
+    update_rx_interrupt(s);
+
+    return size;
+}
+
+static uint32_t
+minimac2_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistMinimac2State *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SETUP:
+    case R_MDIO:
+    case R_STATE0:
+    case R_COUNT0:
+    case R_STATE1:
+    case R_COUNT1:
+    case R_TXCOUNT:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_minimac2: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_minimac2_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void
+minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistMinimac2State *s = opaque;
+
+    trace_milkymist_minimac2_memory_read(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_MDIO:
+    {
+        /* MDIO_DI is read only */
+        int mdio_di = (s->regs[R_MDIO] & MDIO_DI);
+        s->regs[R_MDIO] = value;
+        if (mdio_di) {
+            s->regs[R_MDIO] |= mdio_di;
+        } else {
+            s->regs[R_MDIO] &= ~mdio_di;
+        }
+
+        minimac2_update_mdio(s);
+    } break;
+    case R_TXCOUNT:
+        s->regs[addr] = value;
+        if (value > 0) {
+            minimac2_tx(s);
+        }
+        break;
+    case R_STATE0:
+    case R_STATE1:
+        s->regs[addr] = value;
+        update_rx_interrupt(s);
+        break;
+    case R_SETUP:
+    case R_COUNT0:
+    case R_COUNT1:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_minimac2: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const minimac2_read_fn[] = {
+    NULL,
+    NULL,
+    &minimac2_read,
+};
+
+static CPUWriteMemoryFunc * const minimac2_write_fn[] = {
+    NULL,
+    NULL,
+    &minimac2_write,
+};
+
+static int minimac2_can_rx(VLANClientState *nc)
+{
+    MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    if (s->regs[R_STATE0] == STATE_LOADED) {
+        return 1;
+    }
+    if (s->regs[R_STATE1] == STATE_LOADED) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void minimac2_cleanup(VLANClientState *nc)
+{
+    MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    s->nic = NULL;
+}
+
+static void milkymist_minimac2_reset(DeviceState *d)
+{
+    MilkymistMinimac2State *s =
+            container_of(d, MilkymistMinimac2State, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    for (i = 0; i < R_PHY_MAX; i++) {
+        s->phy_regs[i] = 0;
+    }
+
+    /* defaults */
+    s->phy_regs[R_PHY_ID1] = 0x0022; /* Micrel KSZ8001L */
+    s->phy_regs[R_PHY_ID2] = 0x161a;
+}
+
+static NetClientInfo net_milkymist_minimac2_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = minimac2_can_rx,
+    .receive = minimac2_rx,
+    .cleanup = minimac2_cleanup,
+};
+
+static int milkymist_minimac2_init(SysBusDevice *dev)
+{
+    MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev);
+    int regs;
+    ram_addr_t buffers;
+    size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
+
+    sysbus_init_irq(dev, &s->rx_irq);
+    sysbus_init_irq(dev, &s->tx_irq);
+
+    regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, regs);
+
+    /* register buffers memory */
+    buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size);
+    s->rx0_buf = qemu_get_ram_ptr(buffers);
+    s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
+    s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
+
+    cpu_register_physical_memory(s->buffers_base, buffers_size,
+            buffers | IO_MEM_RAM);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_minimac2_mdio = {
+    .name = "milkymist-minimac2-mdio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(last_clk, MilkymistMinimac2MdioState),
+        VMSTATE_INT32(count, MilkymistMinimac2MdioState),
+        VMSTATE_UINT32(data, MilkymistMinimac2MdioState),
+        VMSTATE_UINT16(data_out, MilkymistMinimac2MdioState),
+        VMSTATE_INT32(state, MilkymistMinimac2MdioState),
+        VMSTATE_UINT8(phy_addr, MilkymistMinimac2MdioState),
+        VMSTATE_UINT8(reg_addr, MilkymistMinimac2MdioState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_milkymist_minimac2 = {
+    .name = "milkymist-minimac2",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistMinimac2State, R_MAX),
+        VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimac2State, R_PHY_MAX),
+        VMSTATE_STRUCT(mdio, MilkymistMinimac2State, 0,
+                vmstate_milkymist_minimac2_mdio, MilkymistMinimac2MdioState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_minimac2_info = {
+    .init = milkymist_minimac2_init,
+    .qdev.name  = "milkymist-minimac2",
+    .qdev.size  = sizeof(MilkymistMinimac2State),
+    .qdev.vmsd  = &vmstate_milkymist_minimac2,
+    .qdev.reset = milkymist_minimac2_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
+                buffers_base, 0),
+        DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
+        DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void milkymist_minimac2_register(void)
+{
+    sysbus_register_withprop(&milkymist_minimac2_info);
+}
+
+device_init(milkymist_minimac2_register)
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 8defad8..7879840 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -156,7 +156,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
     milkymist_ac97_create(0x60005000, irq[5], irq[6], irq[7], irq[8]);
     milkymist_pfpu_create(0x60006000, irq[9]);
     milkymist_tmu2_create(0x60007000, irq[10]);
-    milkymist_minimac_create(0x60008000, irq[11], irq[12]);
+    milkymist_minimac2_create(0x60008000, 0x30000000, irq[11], irq[12]);
     milkymist_softusb_create(0x6000f000, irq[17],
             0x20000000, 0x1000, 0x20020000, 0x2000);
 
diff --git a/trace-events b/trace-events
index 703b745..c7d898f 100644
--- a/trace-events
+++ b/trace-events
@@ -308,17 +308,18 @@ disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x v
 disable milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
 disable milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
 
-# hw/milkymist-minimac.c
-disable milkymist_minimac_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-disable milkymist_minimac_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-disable milkymist_minimac_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-disable milkymist_minimac_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-disable milkymist_minimac_tx_frame(uint32_t length) "length %u"
-disable milkymist_minimac_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
-disable milkymist_minimac_drop_rx_frame(const void *buf) "buf %p"
-disable milkymist_minimac_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
-disable milkymist_minimac_pulse_irq_rx(void) "Pulse IRQ RX"
-disable milkymist_minimac_pulse_irq_tx(void) "Pulse IRQ TX"
+# hw/milkymist-minimac2.c
+disable milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac2_tx_frame(uint32_t length) "length %u"
+disable milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
+disable milkymist_minimac2_drop_rx_frame(const void *buf) "buf %p"
+disable milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
+disable milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX"
+disable milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX"
+disable milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX"
 
 # hw/milkymist-pfpu.c
 disable milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes
  2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
                   ` (3 preceding siblings ...)
  2011-04-12 22:29 ` [Qemu-devel] [PATCH 4/4] lm32: add Milkymist Minimac2 support Michael Walle
@ 2011-05-02 20:10 ` Michael Walle
  4 siblings, 0 replies; 6+ messages in thread
From: Michael Walle @ 2011-05-02 20:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias

Am Mittwoch 13 April 2011, 00:29:32 schrieb Michael Walle:
> This patchset combines some lm32/bsp fixes and support for the new
> Milkymist minimac2 hardware.

Ping :)

-- 
Michael

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-05-02 20:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-12 22:29 [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle
2011-04-12 22:29 ` [Qemu-devel] [PATCH 1/4] lm32: fix exception handling Michael Walle
2011-04-12 22:29 ` [Qemu-devel] [PATCH 2/4] milkymist-vgafb: fix console resizing Michael Walle
2011-04-12 22:29 ` [Qemu-devel] [PATCH 3/4] milkymist-sysctl: fix timers Michael Walle
2011-04-12 22:29 ` [Qemu-devel] [PATCH 4/4] lm32: add Milkymist Minimac2 support Michael Walle
2011-05-02 20:10 ` [Qemu-devel] [PATCH 0/4] lm32 and BSP fixes Michael Walle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).