qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controlle


From: Peter Crosthwaite
Subject: Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Date: Mon, 15 Jul 2013 12:00:24 +1000

Hi Fabien,

On Thu, Jul 11, 2013 at 3:10 AM, Fabien Chouteau <address@hidden> wrote:
> This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
>recieve
> Signed-off-by: Fabien Chouteau <address@hidden>
> ---
>  default-configs/ppc-softmmu.mak |    1 +
>  hw/net/Makefile.objs            |    1 +
>  hw/net/etsec.c                  |  472 +++++++++++++++++++++++++++
>  hw/net/etsec.h                  |  169 ++++++++++
>  hw/net/etsec_miim.c             |  146 +++++++++
>  hw/net/etsec_registers.c        |  295 +++++++++++++++++
>  hw/net/etsec_registers.h        |  302 ++++++++++++++++++
>  hw/net/etsec_rings.c            |  673 
> +++++++++++++++++++++++++++++++++++++++
>  8 files changed, 2059 insertions(+)
>  create mode 100644 hw/net/etsec.c
>  create mode 100644 hw/net/etsec.h
>  create mode 100644 hw/net/etsec_miim.c
>  create mode 100644 hw/net/etsec_registers.c
>  create mode 100644 hw/net/etsec_registers.h
>  create mode 100644 hw/net/etsec_rings.c
>
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index 73e4cc5..c7541cf 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -46,3 +46,4 @@ CONFIG_E500=y
>  CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
>  # For PReP
>  CONFIG_MC146818RTC=y
> +CONFIG_ETSEC=y
> diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
> index 951cca3..ca03c3f 100644
> --- a/hw/net/Makefile.objs
> +++ b/hw/net/Makefile.objs
> @@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o
>  obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o
>  obj-$(CONFIG_PSERIES) += spapr_llan.o
>  obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
> +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
>
>  obj-$(CONFIG_VIRTIO) += virtio-net.o
>  obj-y += vhost_net.o
> diff --git a/hw/net/etsec.c b/hw/net/etsec.c
> new file mode 100644
> index 0000000..4516b01
> --- /dev/null
> +++ b/hw/net/etsec.c
> @@ -0,0 +1,472 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "sysemu/sysemu.h"
> +#include "hw/sysbus.h"
> +#include "trace.h"
> +#include "hw/ptimer.h"
> +#include "hw/net/etsec.h"
> +#include "hw/net/etsec_registers.h"
> +
> +/* #define HEX_DUMP */
> +/* #define DEBUG_REGISTER */
> +
> +static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    eTSEC          *etsec     = opaque;
> +    uint32_t        reg_index = addr / 4;
> +    eTSEC_Register *reg       = NULL;
> +    uint32_t        ret       = 0x0;
> +
> +    assert(reg_index < REG_NUMBER);
> +
> +    reg = &etsec->regs[reg_index];
> +
> +
> +    switch (reg->access) {
> +    case ACC_WO:
> +        ret = 0x00000000;

worth a qemu_log_mask(LOG_GUEST_ERROR ?

> +        break;
> +
> +    case ACC_RW:
> +    case ACC_w1c:
> +    case ACC_RO:
> +    default:
> +        ret = reg->value;
> +        break;
> +    }
> +
> +#ifdef DEBUG_REGISTER
> +    printf("Read  0x%08x @ 0x" TARGET_FMT_plx
> +           "                            : %s (%s)\n",
> +           ret, addr, reg->name, reg->desc);
> +#endif
> +
> +    return ret;
> +}
> +
> +static void write_tstat(eTSEC          *etsec,
> +                        eTSEC_Register *reg,
> +                        uint32_t        reg_index,
> +                        uint32_t        value)
> +{
> +    int i = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        /* Check THLTi flag in TSTAT */
> +        if (value & (1 << (31 - i))) {
> +            walk_tx_ring(etsec, i);
> +        }
> +    }
> +
> +    /* Write 1 to clear */
> +    reg->value &= ~value;
> +}
> +
> +static void write_rstat(eTSEC          *etsec,
> +                        eTSEC_Register *reg,
> +                        uint32_t        reg_index,
> +                        uint32_t        value)
> +{
> +    int i = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        /* Check QHLTi flag in RSTAT */
> +        if (value & (1 << (23 - i)) && !(reg->value & (1 << (23 - i)))) {
> +            walk_rx_ring(etsec, i);
> +        }
> +    }
> +
> +    /* Write 1 to clear */
> +    reg->value &= ~value;
> +}
> +
> +static void write_tbasex(eTSEC          *etsec,
> +                         eTSEC_Register *reg,
> +                         uint32_t        reg_index,
> +                         uint32_t        value)
> +{
> +    reg->value = value & ~0x7;
> +
> +    /* Copy this value in the ring's TxBD pointer */
> +    etsec->regs[TBPTR0 + (reg_index - TBASE0)].value = value & ~0x7;
> +}
> +
> +static void write_rbasex(eTSEC          *etsec,
> +                         eTSEC_Register *reg,
> +                         uint32_t        reg_index,
> +                         uint32_t        value)
> +{
> +    reg->value = value & ~0x7;
> +
> +    /* Copy this value in the ring's RxBD pointer */
> +    etsec->regs[RBPTR0 + (reg_index - RBASE0)].value = value & ~0x7;
> +}
> +
> +static void write_ievent(eTSEC          *etsec,
> +                         eTSEC_Register *reg,
> +                         uint32_t        reg_index,
> +                         uint32_t        value)
> +{
> +    if (value & IEVENT_TXF) {
> +        qemu_irq_lower(etsec->tx_irq);
> +    }
> +    if (value & IEVENT_RXF) {
> +        qemu_irq_lower(etsec->rx_irq);
> +    }
> +
> +    /* Write 1 to clear */
> +    reg->value &= ~value;
> +}
> +
> +static void write_dmactrl(eTSEC          *etsec,
> +                          eTSEC_Register *reg,
> +                          uint32_t        reg_index,
> +                          uint32_t        value)
> +{
> +    reg->value = value;
> +
> +    if (value & DMACTRL_GRS) {
> +
> +        if (etsec->rx_buffer_len != 0) {
> +            /* Graceful receive stop delayed until end of frame */
> +        } else {
> +            /* Graceful receive stop now */
> +            etsec->regs[IEVENT].value |= IEVENT_GRSC;
> +            if (etsec->regs[IMASK].value & IMASK_GRSCEN) {
> +                qemu_irq_raise(etsec->err_irq);
> +            }
> +        }
> +    }
> +
> +    if (value & DMACTRL_GTS) {
> +
> +        if (etsec->tx_buffer_len != 0) {
> +            /* Graceful transmit stop delayed until end of frame */
> +        } else {
> +            /* Graceful transmit stop now */
> +            etsec->regs[IEVENT].value |= IEVENT_GTSC;
> +            if (etsec->regs[IMASK].value & IMASK_GTSCEN) {
> +                qemu_irq_raise(etsec->err_irq);
> +            }
> +        }
> +    }
> +
> +    if (!(value & DMACTRL_WOP)) {
> +        /* Start polling */
> +        ptimer_stop(etsec->ptimer);
> +        ptimer_set_count(etsec->ptimer, 1);
> +        ptimer_run(etsec->ptimer, 1);
> +    }
> +}
> +
> +static void etsec_write(void     *opaque,
> +                        hwaddr    addr,
> +                        uint64_t  value,
> +                        unsigned  size)
> +{
> +    eTSEC          *etsec     = opaque;
> +    uint32_t        reg_index = addr / 4;
> +    eTSEC_Register *reg       = NULL;
> +    uint32_t        before    = 0x0;
> +
> +    assert(reg_index < REG_NUMBER);
> +
> +    reg = &etsec->regs[reg_index];
> +    before = reg->value;
> +
> +    switch (reg_index) {
> +    case IEVENT:
> +        write_ievent(etsec, reg, reg_index, value);
> +        break;
> +
> +    case DMACTRL:
> +        write_dmactrl(etsec, reg, reg_index, value);
> +        break;
> +
> +    case TSTAT:
> +        write_tstat(etsec, reg, reg_index, value);
> +        break;
> +
> +    case RSTAT:
> +        write_rstat(etsec, reg, reg_index, value);
> +        break;
> +
> +    case TBASE0 ... TBASE7:
> +        write_tbasex(etsec, reg, reg_index, value);
> +        break;
> +
> +    case RBASE0 ... RBASE7:
> +        write_rbasex(etsec, reg, reg_index, value);
> +        break;
> +
> +    case MIIMCFG ... MIIMIND:
> +        write_miim(etsec, reg, reg_index, value);
> +        break;
> +
> +    default:
> +        /* Default handling */
> +        switch (reg->access) {
> +
> +        case ACC_RW:
> +        case ACC_WO:
> +            reg->value = value;
> +            break;
> +
> +        case ACC_w1c:
> +            reg->value &= ~value;
> +            break;
> +
> +        case ACC_RO:
> +        default:
> +            /* Read Only or Unknown register */
> +            break;
> +        }
> +    }
> +
> +#ifdef DEBUG_REGISTER
> +    printf("Write 0x%08x @ 0x" TARGET_FMT_plx" val:0x%08x->0x%08x : %s 
> (%s)\n",
> +           (unsigned int)value, addr, before, reg->value, reg->name, 
> reg->desc);

Last I knew, printf was a bad idea for error messages due to monitor
interference issue and nographic mode. But qemu_log or fprintf(stderr,
are both better alternatives.

> +#else
> +    (void)before; /* Unreferenced */
> +#endif
> +
> +}
> +
> +static const MemoryRegionOps etsec_ops = {
> +    .read = etsec_read,
> +    .write = etsec_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .impl = {
> +        .min_access_size = 4,
> +        .max_access_size = 4,
> +    },
> +};
> +
> +static void etsec_timer_hit(void *opaque)
> +{
> +    eTSEC *etsec = opaque;
> +
> +    ptimer_stop(etsec->ptimer);
> +
> +    if (!(etsec->regs[DMACTRL].value & DMACTRL_WOP)) {
> +
> +        if (!(etsec->regs[DMACTRL].value & DMACTRL_GTS)) {
> +            walk_tx_ring(etsec, 0);
> +        }
> +        ptimer_set_count(etsec->ptimer, 1);
> +        ptimer_run(etsec->ptimer, 1);
> +    }
> +}
> +
> +static void etsec_reset(DeviceState *d)
> +{
> +    eTSEC *etsec = container_of(d, eTSEC, busdev.qdev);
> +    int i = 0;
> +    int reg_index = 0;
> +
> +    /* Default value for all registers */
> +    for (i = 0; i < REG_NUMBER; i++) {
> +        etsec->regs[i].name   = "Reserved";
> +        etsec->regs[i].desc   = "";
> +        etsec->regs[i].access = ACC_UNKNOWN;
> +        etsec->regs[i].value  = 0x00000000;
> +    }
> +
> +    /* Set-up known registers */
> +    for (i = 0; eTSEC_registers_def[i].name != NULL; i++) {
> +
> +        reg_index = eTSEC_registers_def[i].offset / 4;
> +
> +        etsec->regs[reg_index].name   = eTSEC_registers_def[i].name;
> +        etsec->regs[reg_index].desc   = eTSEC_registers_def[i].desc;
> +        etsec->regs[reg_index].access = eTSEC_registers_def[i].access;
> +        etsec->regs[reg_index].value  = eTSEC_registers_def[i].reset;
> +    }
> +
> +    etsec->tx_buffer     = NULL;
> +    etsec->tx_buffer_len = 0;
> +    etsec->rx_buffer     = NULL;
> +    etsec->rx_buffer_len = 0;
> +
> +    etsec->phy_status =
> +        MII_SR_EXTENDED_CAPS    | MII_SR_LINK_STATUS   | MII_SR_AUTONEG_CAPS 
>  |
> +        MII_SR_AUTONEG_COMPLETE | MII_SR_PREAMBLE_SUPPRESS |
> +        MII_SR_EXTENDED_STATUS  | MII_SR_100T2_HD_CAPS | 
> MII_SR_100T2_FD_CAPS |
> +        MII_SR_10T_HD_CAPS      | MII_SR_10T_FD_CAPS   | MII_SR_100X_HD_CAPS 
>  |
> +        MII_SR_100X_FD_CAPS     | MII_SR_100T4_CAPS;
> +}
> +
> +static void etsec_cleanup(NetClientState *nc)
> +{
> +    /* printf("eTSEC cleanup\n"); */
> +}
> +
> +static int etsec_can_receive(NetClientState *nc)
> +{
> +    /* Yes we always can\ */
> +    return 1;

As a general rule this is a bad idea. Multiple ethernet controllers in
QEMU have tried this and had issues (particularly with the UBOOT
bootloader) with mass packet droppage. But You have access to the
information needed (the if conditions in rx_ring_write) to implement
this it seems.

> +}
> +
> +#ifdef HEX_DUMP
> +static void hex_dump(FILE *f, const uint8_t *buf, int size)
> +{
> +    int len, i, j, c;
> +
> +    for (i = 0; i < size; i += 16) {
> +        len = size - i;
> +        if (len > 16) {
> +            len = 16;
> +        }
> +        fprintf(f, "%08x ", i);
> +        for (j = 0; j < 16; j++) {
> +            if (j < len) {
> +                fprintf(f, " %02x", buf[i + j]);
> +            } else {
> +                fprintf(f, "   ");
> +            }
> +        }
> +        fprintf(f, " ");
> +        for (j = 0; j < len; j++) {
> +            c = buf[i + j];
> +            if (c < ' ' || c > '~') {
> +                c = '.';
> +            }
> +            fprintf(f, "%c", c);
> +        }
> +        fprintf(f, "\n");
> +    }
> +}
> +#endif
> +
> +static ssize_t etsec_receive(NetClientState *nc,
> +                             const uint8_t  *buf,
> +                             size_t          size)
> +{
> +    eTSEC *etsec = qemu_get_nic_opaque(nc);
> +
> +#if defined(HEX_DUMP)
> +    fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
> +    hex_dump(stderr, buf, size);
> +#endif
> +    rx_ring_write(etsec, buf, size);
> +    return size;
> +}
> +
> +
> +static void etsec_set_link_status(NetClientState *nc)
> +{
> +    eTSEC *etsec = qemu_get_nic_opaque(nc);
> +
> +    miim_link_status(etsec, nc);
> +}
> +
> +static NetClientInfo net_etsec_info = {
> +    .type = NET_CLIENT_OPTIONS_KIND_NIC,
> +    .size = sizeof(NICState),
> +    .can_receive = etsec_can_receive,
> +    .receive = etsec_receive,
> +    .cleanup = etsec_cleanup,
> +    .link_status_changed = etsec_set_link_status,
> +};
> +
> +static int etsec_init(SysBusDevice *dev)
> +{
> +    eTSEC *etsec = FROM_SYSBUS(typeof(*etsec), dev);

Define and use QOM cast macros instead, FROM_FOO macros are deprecated.

> +
> +    memory_region_init_io(&etsec->io_area, OBJECT(etsec), &etsec_ops, etsec,
> +                          "eTSEC", 0x1000);

Constant size memory_region_init_io should be migrated to the Object::Init fm.

> +
> +    sysbus_init_mmio(dev, &etsec->io_area);
> +
> +    sysbus_init_irq(dev, &etsec->tx_irq);
> +    sysbus_init_irq(dev, &etsec->rx_irq);
> +    sysbus_init_irq(dev, &etsec->err_irq);
> +
> +    etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf,
> +                              "eTSEC", etsec->busdev.qdev.id, etsec);
> +    qemu_format_nic_info_str(qemu_get_queue(etsec->nic), 
> etsec->conf.macaddr.a);
> +
> +
> +    etsec->bh     = qemu_bh_new(etsec_timer_hit, etsec);
> +    etsec->ptimer = ptimer_init(etsec->bh);
> +    ptimer_set_freq(etsec->ptimer, 100);
> +
> +    return 0;
> +}
> +
> +static Property etsec_properties[] = {
> +    DEFINE_NIC_PROPERTIES(eTSEC, conf),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void etsec_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +
> +    k->init = etsec_init;

SysBusDevice::init in depracated. Please use Device::realize instead.

> +    dc->reset = etsec_reset;
> +    dc->props = etsec_properties;
> +}
> +
> +static TypeInfo etsec_info = {
> +    .name          = "eTSEC",
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(eTSEC),
> +    .class_init    = etsec_class_init,
> +};
> +
> +static void etsec_register_types(void)
> +{
> +    type_register_static(&etsec_info);
> +}
> +
> +type_init(etsec_register_types)
> +
> +DeviceState *etsec_create(hwaddr         base,
> +                          MemoryRegion * mr,
> +                          NICInfo      * nd,
> +                          qemu_irq       tx_irq,
> +                          qemu_irq       rx_irq,
> +                          qemu_irq       err_irq)
> +{
> +    DeviceState *dev;
> +
> +    dev = qdev_create(NULL, "eTSEC");
> +    qdev_set_nic_properties(dev, nd);
> +
> +    if (qdev_init(dev)) {
> +        return NULL;
> +    }
> +
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, err_irq);
> +
> +    memory_region_add_subregion(mr, base,
> +                                SYS_BUS_DEVICE(dev)->mmio[0].memory);
> +
> +    return dev;
> +}
> diff --git a/hw/net/etsec.h b/hw/net/etsec.h
> new file mode 100644
> index 0000000..4fa9edc
> --- /dev/null
> +++ b/hw/net/etsec.h
> @@ -0,0 +1,169 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#ifndef _ETSEC_H_
> +#define _ETSEC_H_
> +
> +#include "hw/qdev.h"
> +#include "hw/sysbus.h"
> +#include "net/net.h"
> +#include "hw/ptimer.h"
> +
> +/* Buffer Descriptors */
> +
> +typedef struct eTSEC_rxtx_bd {
> +    uint16_t flags;
> +    uint16_t length;
> +    uint32_t bufptr;
> +} eTSEC_rxtx_bd;
> +
> +#define BD_WRAP       (1 << 13)
> +#define BD_INTERRUPT  (1 << 12)
> +#define BD_LAST       (1 << 11)
> +
> +#define BD_TX_READY     (1 << 15)
> +#define BD_TX_PADCRC    (1 << 14)
> +#define BD_TX_TC        (1 << 10)
> +#define BD_TX_PREDEF    (1 << 9)
> +#define BD_TX_HFELC     (1 << 7)
> +#define BD_TX_CFRL      (1 << 6)
> +#define BD_TX_RC_MASK   0xF
> +#define BD_TX_RC_OFFSET 0x2
> +#define BD_TX_TOEUN     (1 << 1)
> +#define BD_TX_TR        (1 << 0)
> +
> +#define BD_RX_EMPTY     (1 << 15)
> +#define BD_RX_RO1       (1 << 14)
> +#define BD_RX_FIRST     (1 << 10)
> +#define BD_RX_MISS      (1 << 8)
> +#define BD_RX_BROADCAST (1 << 7)
> +#define BD_RX_MULTICAST (1 << 6)
> +#define BD_RX_LG        (1 << 5)
> +#define BD_RX_NO        (1 << 4)
> +#define BD_RX_SH        (1 << 3)
> +#define BD_RX_CR        (1 << 2)
> +#define BD_RX_OV        (1 << 1)
> +#define BD_RX_TR        (1 << 0)
> +
> +/* Tx FCB flags */
> +#define FCB_TX_VLN     (1 << 7)
> +#define FCB_TX_IP      (1 << 6)
> +#define FCB_TX_IP6     (1 << 5)
> +#define FCB_TX_TUP     (1 << 4)
> +#define FCB_TX_UDP     (1 << 3)
> +#define FCB_TX_CIP     (1 << 2)
> +#define FCB_TX_CTU     (1 << 1)
> +#define FCB_TX_NPH     (1 << 0)
> +
> +/* PHY Status Register */
> +#define MII_SR_EXTENDED_CAPS     0x0001    /* Extended register capabilities 
> */
> +#define MII_SR_JABBER_DETECT     0x0002    /* Jabber Detected */
> +#define MII_SR_LINK_STATUS       0x0004    /* Link Status 1 = link */
> +#define MII_SR_AUTONEG_CAPS      0x0008    /* Auto Neg Capable */
> +#define MII_SR_REMOTE_FAULT      0x0010    /* Remote Fault Detect */
> +#define MII_SR_AUTONEG_COMPLETE  0x0020    /* Auto Neg Complete */
> +#define MII_SR_PREAMBLE_SUPPRESS 0x0040    /* Preamble may be suppressed */
> +#define MII_SR_EXTENDED_STATUS   0x0100    /* Ext. status info in Reg 0x0F */
> +#define MII_SR_100T2_HD_CAPS     0x0200    /* 100T2 Half Duplex Capable */
> +#define MII_SR_100T2_FD_CAPS     0x0400    /* 100T2 Full Duplex Capable */
> +#define MII_SR_10T_HD_CAPS       0x0800    /* 10T   Half Duplex Capable */
> +#define MII_SR_10T_FD_CAPS       0x1000    /* 10T   Full Duplex Capable */
> +#define MII_SR_100X_HD_CAPS      0x2000    /* 100X  Half Duplex Capable */
> +#define MII_SR_100X_FD_CAPS      0x4000    /* 100X  Full Duplex Capable */
> +#define MII_SR_100T4_CAPS        0x8000    /* 100T4 Capable */
> +
> +/* eTSEC */
> +
> +#define REG_NUMBER 1024
> +
> +typedef struct eTSEC_Register {
> +    const char *name;
> +    const char *desc;
> +    uint32_t    access;
> +    uint32_t    value;
> +} eTSEC_Register;
> +
> +typedef struct eTSEC {
> +    SysBusDevice  busdev;
> +
> +    MemoryRegion  io_area;
> +
> +    eTSEC_Register regs[REG_NUMBER];
> +
> +    NICState *nic;
> +    NICConf   conf;
> +
> +    /* Tx */
> +
> +    uint8_t       *tx_buffer;
> +    uint32_t       tx_buffer_len;
> +    eTSEC_rxtx_bd  first_bd;
> +
> +    /* Rx */
> +
> +    uint8_t       *rx_buffer;
> +    uint32_t       rx_buffer_len;
> +    uint32_t       rx_remaining_data;
> +    uint8_t        rx_first_in_frame;
> +    uint8_t        rx_fcb_size;
> +    eTSEC_rxtx_bd  rx_first_bd;
> +    uint8_t        rx_fcb[10];
> +    uint32_t       rx_padding;
> +
> +    /* IRQs */
> +    qemu_irq     tx_irq;
> +    qemu_irq     rx_irq;
> +    qemu_irq     err_irq;
> +
> +
> +    uint16_t phy_status;
> +    uint16_t phy_control;
> +
> +    /* Polling */
> +    QEMUBH *bh;
> +    struct ptimer_state *ptimer;
> +
> +} eTSEC;
> +
> +#define eTSEC_TRANSMIT 1
> +#define eTSEC_RECEIVE  2
> +
> +DeviceState *etsec_create(hwaddr        base,
> +                          MemoryRegion *mr,
> +                          NICInfo      *nd,
> +                          qemu_irq      tx_irq,
> +                          qemu_irq      rx_irq,
> +                          qemu_irq      err_irq);
> +
> +void walk_tx_ring(eTSEC *etsec, int ring_nbr);
> +void walk_rx_ring(eTSEC *etsec, int ring_nbr);
> +void rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size);
> +
> +void write_miim(eTSEC          *etsec,
> +                eTSEC_Register *reg,
> +                uint32_t        reg_index,
> +                uint32_t        value);
> +
> +void miim_link_status(eTSEC *etsec, NetClientState *nc);
> +
> +#endif /* ! _ETSEC_H_ */
> diff --git a/hw/net/etsec_miim.c b/hw/net/etsec_miim.c
> new file mode 100644
> index 0000000..2bd9f0d
> --- /dev/null
> +++ b/hw/net/etsec_miim.c
> @@ -0,0 +1,146 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "etsec.h"
> +#include "etsec_registers.h"
> +
> +/* #define DEBUG_MIIM */
> +
> +#define MIIM_CONTROL    0
> +#define MIIM_STATUS     1
> +#define MIIM_PHY_ID_1   2
> +#define MIIM_PHY_ID_2   3
> +#define MIIM_T2_STATUS  10
> +#define MIIM_EXT_STATUS 15
> +
> +static void miim_read_cycle(eTSEC *etsec)
> +{
> +    uint8_t  phy;
> +    uint8_t  addr;
> +    uint16_t value;
> +
> +    phy  = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
> +    (void)phy; /* Unreferenced */
> +    addr = etsec->regs[MIIMADD].value & 0x1F;
> +
> +    switch (addr) {
> +    case MIIM_CONTROL:
> +        value = etsec->phy_control;
> +        break;
> +    case MIIM_STATUS:
> +        value = etsec->phy_status;
> +        break;
> +    case MIIM_T2_STATUS:
> +        value = 0x1800;           /* Local and remote receivers OK */
> +        break;
> +    default:
> +        value = 0x0;
> +        break;
> +    };
> +
> +#ifdef DEBUG_MIIM
> +    printf("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
> +#endif
> +
> +    etsec->regs[MIIMSTAT].value = value;
> +}
> +
> +static void miim_write_cycle(eTSEC *etsec)
> +{
> +    uint8_t  phy;
> +    uint8_t  addr;
> +    uint16_t value;
> +
> +    phy   = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
> +    (void)phy; /* Unreferenced */
> +    addr  = etsec->regs[MIIMADD].value & 0x1F;
> +    value = etsec->regs[MIIMCON].value & 0xffff;
> +
> +#ifdef DEBUG_MIIM
> +    printf("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
> +#endif
> +
> +    switch (addr) {
> +    case MIIM_CONTROL:
> +        etsec->phy_control = value & ~(0x8100);
> +        break;
> +    default:
> +        break;
> +    };
> +}
> +
> +void write_miim(eTSEC          *etsec,
> +               eTSEC_Register *reg,
> +               uint32_t        reg_index,
> +               uint32_t        value)
> +{
> +
> +    switch (reg_index) {
> +
> +    case MIIMCOM:
> +        /* Read and scan cycle */
> +
> +        if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) {
> +            /* Read */
> +            miim_read_cycle(etsec);
> +        }
> +        reg->value = value;
> +        break;
> +
> +    case MIIMCON:
> +        reg->value = value & 0xffff;
> +        miim_write_cycle(etsec);
> +        break;
> +
> +    default:
> +        /* Default handling */
> +        switch (reg->access) {
> +
> +        case ACC_RW:
> +        case ACC_WO:
> +            reg->value = value;
> +            break;
> +
> +        case ACC_w1c:
> +            reg->value &= ~value;
> +            break;
> +
> +        case ACC_RO:
> +        default:
> +            /* Read Only or Unknown register */
> +            break;
> +        }
> +    }
> +
> +}
> +
> +void miim_link_status(eTSEC *etsec, NetClientState *nc)
> +{
> +    /* Set link status */
> +    if (nc->link_down) {
> +        etsec->phy_status &= ~MII_SR_LINK_STATUS;
> +    } else {
> +        etsec->phy_status |= MII_SR_LINK_STATUS;
> +    }
> +}
> diff --git a/hw/net/etsec_registers.c b/hw/net/etsec_registers.c
> new file mode 100644
> index 0000000..719a886
> --- /dev/null
> +++ b/hw/net/etsec_registers.c
> @@ -0,0 +1,295 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#include "etsec_registers.h"
> +
> +const eTSEC_Register_Definition eTSEC_registers_def[] = {
> +{0x000, "TSEC_ID",  "Controller ID register",    ACC_RO,  0x01240000},
> +{0x004, "TSEC_ID2", "Controller ID register 2",  ACC_RO,  0x003000F0},
> +{0x010, "IEVENT",   "Interrupt event register",  ACC_w1c, 0x00000000},
> +{0x014, "IMASK",    "Interrupt mask register",   ACC_RW,  0x00000000},
> +{0x018, "EDIS",     "Error disabled register",   ACC_RW,  0x00000000},
> +{0x020, "ECNTRL",   "Ethernet control register", ACC_RW,  0x00000040},
> +{0x028, "PTV",      "Pause time value register", ACC_RW,  0x00000000},
> +{0x02C, "DMACTRL",  "DMA control register",      ACC_RW,  0x00000000},
> +{0x030, "TBIPA",    "TBI PHY address register",  ACC_RW,  0x00000000},
> +
> +/* eTSEC FIFO Control and Status Registers */
> +
> +{0x058, "FIFO_RX_ALARM",          "FIFO receive alarm start threshold 
> register",    ACC_RW, 0x00000040},
> +{0x05C, "FIFO_RX_ALARM_SHUTOFF",  "FIFO receive alarm shut-off threshold 
> register", ACC_RW, 0x00000080},
> +{0x08C, "FIFO_TX_THR",            "FIFO transmit threshold register",        
>        ACC_RW, 0x00000080},
> +{0x098, "FIFO_TX_STARVE",         "FIFO transmit starve register",           
>        ACC_RW, 0x00000040},
> +{0x09C, "FIFO_TX_STARVE_SHUTOFF", "FIFO transmit starve shut-off register",  
>        ACC_RW, 0x00000080},
> +
> +/* eTSEC Transmit Control and Status Registers */
> +
> +{0x100, "TCTRL",        "Transmit control register",                ACC_RW,  
> 0x00000000},
> +{0x104, "TSTAT",        "Transmit status register",                 ACC_w1c, 
> 0x00000000},
> +{0x108, "DFVLAN",       "Default VLAN control word",                ACC_RW,  
> 0x81000000},
> +{0x110, "TXIC",         "Transmit interrupt coalescing register",   ACC_RW,  
> 0x00000000},
> +{0x114, "TQUEUE",       "Transmit queue control register",          ACC_RW,  
> 0x00008000},
> +{0x140, "TR03WT",       "TxBD Rings 0-3 round-robin weightings",    ACC_RW,  
> 0x00000000},
> +{0x144, "TR47WT",       "TxBD Rings 4-7 round-robin weightings",    ACC_RW,  
> 0x00000000},
> +{0x180, "TBDBPH",       "Tx data buffer pointer high bits",         ACC_RW,  
> 0x00000000},
> +{0x184, "TBPTR0",       "TxBD pointer for ring 0",                  ACC_RW,  
> 0x00000000},
> +{0x18C, "TBPTR1",       "TxBD pointer for ring 1",                  ACC_RW,  
> 0x00000000},
> +{0x194, "TBPTR2",       "TxBD pointer for ring 2",                  ACC_RW,  
> 0x00000000},
> +{0x19C, "TBPTR3",       "TxBD pointer for ring 3",                  ACC_RW,  
> 0x00000000},
> +{0x1A4, "TBPTR4",       "TxBD pointer for ring 4",                  ACC_RW,  
> 0x00000000},
> +{0x1AC, "TBPTR5",       "TxBD pointer for ring 5",                  ACC_RW,  
> 0x00000000},
> +{0x1B4, "TBPTR6",       "TxBD pointer for ring 6",                  ACC_RW,  
> 0x00000000},
> +{0x1BC, "TBPTR7",       "TxBD pointer for ring 7",                  ACC_RW,  
> 0x00000000},
> +{0x200, "TBASEH",       "TxBD base address high bits",              ACC_RW,  
> 0x00000000},
> +{0x204, "TBASE0",       "TxBD base address of ring 0",              ACC_RW,  
> 0x00000000},
> +{0x20C, "TBASE1",       "TxBD base address of ring 1",              ACC_RW,  
> 0x00000000},
> +{0x214, "TBASE2",       "TxBD base address of ring 2",              ACC_RW,  
> 0x00000000},
> +{0x21C, "TBASE3",       "TxBD base address of ring 3",              ACC_RW,  
> 0x00000000},
> +{0x224, "TBASE4",       "TxBD base address of ring 4",              ACC_RW,  
> 0x00000000},
> +{0x22C, "TBASE5",       "TxBD base address of ring 5",              ACC_RW,  
> 0x00000000},
> +{0x234, "TBASE6",       "TxBD base address of ring 6",              ACC_RW,  
> 0x00000000},
> +{0x23C, "TBASE7",       "TxBD base address of ring 7",              ACC_RW,  
> 0x00000000},
> +{0x280, "TMR_TXTS1_ID", "Tx time stamp identification tag (set 1)", ACC_RO,  
> 0x00000000},
> +{0x284, "TMR_TXTS2_ID", "Tx time stamp identification tag (set 2)", ACC_RO,  
> 0x00000000},
> +{0x2C0, "TMR_TXTS1_H",  "Tx time stamp high (set 1)",               ACC_RO,  
> 0x00000000},
> +{0x2C4, "TMR_TXTS1_L",  "Tx time stamp high (set 1)",               ACC_RO,  
> 0x00000000},
> +{0x2C8, "TMR_TXTS2_H",  "Tx time stamp high (set 2)",               ACC_RO,  
> 0x00000000},
> +{0x2CC, "TMR_TXTS2_L",  "Tx time stamp high (set 2)",               ACC_RO,  
> 0x00000000},
> +
> +/* eTSEC Receive Control and Status Registers */
> +
> +{0x300, "RCTRL",      "Receive control register",                     
> ACC_RW,  0x00000000},
> +{0x304, "RSTAT",      "Receive status register",                      
> ACC_w1c, 0x00000000},
> +{0x310, "RXIC",       "Receive interrupt coalescing register",        
> ACC_RW,  0x00000000},
> +{0x314, "RQUEUE",     "Receive queue control register.",              
> ACC_RW,  0x00800080},
> +{0x330, "RBIFX",      "Receive bit field extract control register",   
> ACC_RW,  0x00000000},
> +{0x334, "RQFAR",      "Receive queue filing table address register",  
> ACC_RW,  0x00000000},
> +{0x338, "RQFCR",      "Receive queue filing table control register",  
> ACC_RW,  0x00000000},
> +{0x33C, "RQFPR",      "Receive queue filing table property register", 
> ACC_RW,  0x00000000},
> +{0x340, "MRBLR",      "Maximum receive buffer length register",       
> ACC_RW,  0x00000000},
> +{0x380, "RBDBPH",     "Rx data buffer pointer high bits",             
> ACC_RW,  0x00000000},
> +{0x384, "RBPTR0",     "RxBD pointer for ring 0",                      
> ACC_RW,  0x00000000},
> +{0x38C, "RBPTR1",     "RxBD pointer for ring 1",                      
> ACC_RW,  0x00000000},
> +{0x394, "RBPTR2",     "RxBD pointer for ring 2",                      
> ACC_RW,  0x00000000},
> +{0x39C, "RBPTR3",     "RxBD pointer for ring 3",                      
> ACC_RW,  0x00000000},
> +{0x3A4, "RBPTR4",     "RxBD pointer for ring 4",                      
> ACC_RW,  0x00000000},
> +{0x3AC, "RBPTR5",     "RxBD pointer for ring 5",                      
> ACC_RW,  0x00000000},
> +{0x3B4, "RBPTR6",     "RxBD pointer for ring 6",                      
> ACC_RW,  0x00000000},
> +{0x3BC, "RBPTR7",     "RxBD pointer for ring 7",                      
> ACC_RW,  0x00000000},
> +{0x400, "RBASEH",     "RxBD base address high bits",                  
> ACC_RW,  0x00000000},
> +{0x404, "RBASE0",     "RxBD base address of ring 0",                  
> ACC_RW,  0x00000000},
> +{0x40C, "RBASE1",     "RxBD base address of ring 1",                  
> ACC_RW,  0x00000000},
> +{0x414, "RBASE2",     "RxBD base address of ring 2",                  
> ACC_RW,  0x00000000},
> +{0x41C, "RBASE3",     "RxBD base address of ring 3",                  
> ACC_RW,  0x00000000},
> +{0x424, "RBASE4",     "RxBD base address of ring 4",                  
> ACC_RW,  0x00000000},
> +{0x42C, "RBASE5",     "RxBD base address of ring 5",                  
> ACC_RW,  0x00000000},
> +{0x434, "RBASE6",     "RxBD base address of ring 6",                  
> ACC_RW,  0x00000000},
> +{0x43C, "RBASE7",     "RxBD base address of ring 7",                  
> ACC_RW,  0x00000000},
> +{0x4C0, "TMR_RXTS_H", "Rx timer time stamp register high",            
> ACC_RW,  0x00000000},
> +{0x4C4, "TMR_RXTS_L", "Rx timer time stamp register low",             
> ACC_RW,  0x00000000},
> +
> +/* eTSEC MAC Registers */
> +
> +{0x500, "MACCFG1",     "MAC configuration register 1",          ACC_RW, 
> 0x00000000},
> +{0x504, "MACCFG2",     "MAC configuration register 2",          ACC_RW, 
> 0x00007000},
> +{0x508, "IPGIFG",      "Inter-packet/inter-frame gap register", ACC_RW, 
> 0x40605060},
> +{0x50C, "HAFDUP",      "Half-duplex control",                   ACC_RW, 
> 0x00A1F037},
> +{0x510, "MAXFRM",      "Maximum frame length",                  ACC_RW, 
> 0x00000600},
> +{0x520, "MIIMCFG",     "MII management configuration",          ACC_RW, 
> 0x00000007},
> +{0x524, "MIIMCOM",     "MII management command",                ACC_RW, 
> 0x00000000},
> +{0x528, "MIIMADD",     "MII management address",                ACC_RW, 
> 0x00000000},
> +{0x52C, "MIIMCON",     "MII management control",                ACC_WO, 
> 0x00000000},
> +{0x530, "MIIMSTAT",    "MII management status",                 ACC_RO, 
> 0x00000000},
> +{0x534, "MIIMIND",     "MII management indicator",              ACC_RO, 
> 0x00000000},
> +{0x53C, "IFSTAT",      "Interface status",                      ACC_RO, 
> 0x00000000},
> +{0x540, "MACSTNADDR1", "MAC station address register 1",        ACC_RW, 
> 0x00000000},
> +{0x544, "MACSTNADDR2", "MAC station address register 2",        ACC_RW, 
> 0x00000000},
> +{0x548, "MAC01ADDR1",  "MAC exact match address 1, part 1",     ACC_RW, 
> 0x00000000},
> +{0x54C, "MAC01ADDR2",  "MAC exact match address 1, part 2",     ACC_RW, 
> 0x00000000},
> +{0x550, "MAC02ADDR1",  "MAC exact match address 2, part 1",     ACC_RW, 
> 0x00000000},
> +{0x554, "MAC02ADDR2",  "MAC exact match address 2, part 2",     ACC_RW, 
> 0x00000000},
> +{0x558, "MAC03ADDR1",  "MAC exact match address 3, part 1",     ACC_RW, 
> 0x00000000},
> +{0x55C, "MAC03ADDR2",  "MAC exact match address 3, part 2",     ACC_RW, 
> 0x00000000},
> +{0x560, "MAC04ADDR1",  "MAC exact match address 4, part 1",     ACC_RW, 
> 0x00000000},
> +{0x564, "MAC04ADDR2",  "MAC exact match address 4, part 2",     ACC_RW, 
> 0x00000000},
> +{0x568, "MAC05ADDR1",  "MAC exact match address 5, part 1",     ACC_RW, 
> 0x00000000},
> +{0x56C, "MAC05ADDR2",  "MAC exact match address 5, part 2",     ACC_RW, 
> 0x00000000},
> +{0x570, "MAC06ADDR1",  "MAC exact match address 6, part 1",     ACC_RW, 
> 0x00000000},
> +{0x574, "MAC06ADDR2",  "MAC exact match address 6, part 2",     ACC_RW, 
> 0x00000000},
> +{0x578, "MAC07ADDR1",  "MAC exact match address 7, part 1",     ACC_RW, 
> 0x00000000},
> +{0x57C, "MAC07ADDR2",  "MAC exact match address 7, part 2",     ACC_RW, 
> 0x00000000},
> +{0x580, "MAC08ADDR1",  "MAC exact match address 8, part 1",     ACC_RW, 
> 0x00000000},
> +{0x584, "MAC08ADDR2",  "MAC exact match address 8, part 2",     ACC_RW, 
> 0x00000000},
> +{0x588, "MAC09ADDR1",  "MAC exact match address 9, part 1",     ACC_RW, 
> 0x00000000},
> +{0x58C, "MAC09ADDR2",  "MAC exact match address 9, part 2",     ACC_RW, 
> 0x00000000},
> +{0x590, "MAC10ADDR1",  "MAC exact match address 10, part 1",    ACC_RW, 
> 0x00000000},
> +{0x594, "MAC10ADDR2",  "MAC exact match address 10, part 2",    ACC_RW, 
> 0x00000000},
> +{0x598, "MAC11ADDR1",  "MAC exact match address 11, part 1",    ACC_RW, 
> 0x00000000},
> +{0x59C, "MAC11ADDR2",  "MAC exact match address 11, part 2",    ACC_RW, 
> 0x00000000},
> +{0x5A0, "MAC12ADDR1",  "MAC exact match address 12, part 1",    ACC_RW, 
> 0x00000000},
> +{0x5A4, "MAC12ADDR2",  "MAC exact match address 12, part 2",    ACC_RW, 
> 0x00000000},
> +{0x5A8, "MAC13ADDR1",  "MAC exact match address 13, part 1",    ACC_RW, 
> 0x00000000},
> +{0x5AC, "MAC13ADDR2",  "MAC exact match address 13, part 2",    ACC_RW, 
> 0x00000000},
> +{0x5B0, "MAC14ADDR1",  "MAC exact match address 14, part 1",    ACC_RW, 
> 0x00000000},
> +{0x5B4, "MAC14ADDR2",  "MAC exact match address 14, part 2",    ACC_RW, 
> 0x00000000},
> +{0x5B8, "MAC15ADDR1",  "MAC exact match address 15, part 1",    ACC_RW, 
> 0x00000000},
> +{0x5BC, "MAC15ADDR2",  "MAC exact match address 15, part 2",    ACC_RW, 
> 0x00000000},
> +
> +/* eTSEC, "Transmit", "and", Receive, Counters */
> +
> +{0x680, "TR64",  "Transmit and receive 64-byte frame counter ",              
>      ACC_RW, 0x00000000},
> +{0x684, "TR127", "Transmit and receive 65- to 127-byte frame counter",       
>      ACC_RW, 0x00000000},
> +{0x688, "TR255", "Transmit and receive 128- to 255-byte frame counter",      
>      ACC_RW, 0x00000000},
> +{0x68C, "TR511", "Transmit and receive 256- to 511-byte frame counter",      
>      ACC_RW, 0x00000000},
> +{0x690, "TR1K",  "Transmit and receive 512- to 1023-byte frame counter",     
>      ACC_RW, 0x00000000},
> +{0x694, "TRMAX", "Transmit and receive 1024- to 1518-byte frame counter",    
>      ACC_RW, 0x00000000},
> +{0x698, "TRMGV", "Transmit and receive 1519- to 1522-byte good VLAN frame 
> count", ACC_RW, 0x00000000},
> +
> +/* eTSEC Receive Counters */
> +
> +{0x69C, "RBYT", "Receive byte counter",                  ACC_RW, 0x00000000},
> +{0x6A0, "RPKT", "Receive packet counter",                ACC_RW, 0x00000000},
> +{0x6A4, "RFCS", "Receive FCS error counter",             ACC_RW, 0x00000000},
> +{0x6A8, "RMCA", "Receive multicast packet counter",      ACC_RW, 0x00000000},
> +{0x6AC, "RBCA", "Receive broadcast packet counter",      ACC_RW, 0x00000000},
> +{0x6B0, "RXCF", "Receive control frame packet counter ", ACC_RW, 0x00000000},
> +{0x6B4, "RXPF", "Receive PAUSE frame packet counter",    ACC_RW, 0x00000000},
> +{0x6B8, "RXUO", "Receive unknown OP code counter ",      ACC_RW, 0x00000000},
> +{0x6BC, "RALN", "Receive alignment error counter ",      ACC_RW, 0x00000000},
> +{0x6C0, "RFLR", "Receive frame length error counter ",   ACC_RW, 0x00000000},
> +{0x6C4, "RCDE", "Receive code error counter ",           ACC_RW, 0x00000000},
> +{0x6C8, "RCSE", "Receive carrier sense error counter",   ACC_RW, 0x00000000},
> +{0x6CC, "RUND", "Receive undersize packet counter",      ACC_RW, 0x00000000},
> +{0x6D0, "ROVR", "Receive oversize packet counter ",      ACC_RW, 0x00000000},
> +{0x6D4, "RFRG", "Receive fragments counter",             ACC_RW, 0x00000000},
> +{0x6D8, "RJBR", "Receive jabber counter ",               ACC_RW, 0x00000000},
> +{0x6DC, "RDRP", "Receive drop counter",                  ACC_RW, 0x00000000},
> +
> +/* eTSEC Transmit Counters */
> +
> +{0x6E0, "TBYT", "Transmit byte counter",                       ACC_RW, 
> 0x00000000},
> +{0x6E4, "TPKT", "Transmit packet counter",                     ACC_RW, 
> 0x00000000},
> +{0x6E8, "TMCA", "Transmit multicast packet counter ",          ACC_RW, 
> 0x00000000},
> +{0x6EC, "TBCA", "Transmit broadcast packet counter ",          ACC_RW, 
> 0x00000000},
> +{0x6F0, "TXPF", "Transmit PAUSE control frame counter ",       ACC_RW, 
> 0x00000000},
> +{0x6F4, "TDFR", "Transmit deferral packet counter ",           ACC_RW, 
> 0x00000000},
> +{0x6F8, "TEDF", "Transmit excessive deferral packet counter ", ACC_RW, 
> 0x00000000},
> +{0x6FC, "TSCL", "Transmit single collision packet counter",    ACC_RW, 
> 0x00000000},
> +{0x700, "TMCL", "Transmit multiple collision packet counter",  ACC_RW, 
> 0x00000000},
> +{0x704, "TLCL", "Transmit late collision packet counter",      ACC_RW, 
> 0x00000000},
> +{0x708, "TXCL", "Transmit excessive collision packet counter", ACC_RW, 
> 0x00000000},
> +{0x70C, "TNCL", "Transmit total collision counter ",           ACC_RW, 
> 0x00000000},
> +{0x714, "TDRP", "Transmit drop frame counter",                 ACC_RW, 
> 0x00000000},
> +{0x718, "TJBR", "Transmit jabber frame counter ",              ACC_RW, 
> 0x00000000},
> +{0x71C, "TFCS", "Transmit FCS error counter",                  ACC_RW, 
> 0x00000000},
> +{0x720, "TXCF", "Transmit control frame counter ",             ACC_RW, 
> 0x00000000},
> +{0x724, "TOVR", "Transmit oversize frame counter",             ACC_RW, 
> 0x00000000},
> +{0x728, "TUND", "Transmit undersize frame counter ",           ACC_RW, 
> 0x00000000},
> +{0x72C, "TFRG", "Transmit fragments frame counter ",           ACC_RW, 
> 0x00000000},
> +
> +/* eTSEC Counter Control and TOE Statistics Registers */
> +
> +{0x730, "CAR1", "Carry register one register",           ACC_w1c, 
> 0x00000000},
> +{0x734, "CAR2", "Carry register two register ",          ACC_w1c, 
> 0x00000000},
> +{0x738, "CAM1", "Carry register one mask register ",     ACC_RW,  
> 0xFE03FFFF},
> +{0x73C, "CAM2", "Carry register two mask register ",     ACC_RW,  
> 0x000FFFFD},
> +{0x740, "RREJ", "Receive filer rejected packet counter", ACC_RW,  
> 0x00000000},
> +
> +/* Hash Function Registers */
> +
> +{0x800, "IGADDR0", "Individual/group address register 0", ACC_RW, 
> 0x00000000},
> +{0x804, "IGADDR1", "Individual/group address register 1", ACC_RW, 
> 0x00000000},
> +{0x808, "IGADDR2", "Individual/group address register 2", ACC_RW, 
> 0x00000000},
> +{0x80C, "IGADDR3", "Individual/group address register 3", ACC_RW, 
> 0x00000000},
> +{0x810, "IGADDR4", "Individual/group address register 4", ACC_RW, 
> 0x00000000},
> +{0x814, "IGADDR5", "Individual/group address register 5", ACC_RW, 
> 0x00000000},
> +{0x818, "IGADDR6", "Individual/group address register 6", ACC_RW, 
> 0x00000000},
> +{0x81C, "IGADDR7", "Individual/group address register 7", ACC_RW, 
> 0x00000000},
> +{0x880, "GADDR0",  "Group address register 0",            ACC_RW, 
> 0x00000000},
> +{0x884, "GADDR1",  "Group address register 1",            ACC_RW, 
> 0x00000000},
> +{0x888, "GADDR2",  "Group address register 2",            ACC_RW, 
> 0x00000000},
> +{0x88C, "GADDR3",  "Group address register 3",            ACC_RW, 
> 0x00000000},
> +{0x890, "GADDR4",  "Group address register 4",            ACC_RW, 
> 0x00000000},
> +{0x894, "GADDR5",  "Group address register 5",            ACC_RW, 
> 0x00000000},
> +{0x898, "GADDR6",  "Group address register 6",            ACC_RW, 
> 0x00000000},
> +{0x89C, "GADDR7",  "Group address register 7",            ACC_RW, 
> 0x00000000},
> +
> +/* eTSEC DMA Attribute Registers */
> +
> +{0xBF8, "ATTR",    "Attribute register",                                  
> ACC_RW, 0x00000000},
> +{0xBFC, "ATTRELI", "Attribute extract length and extract index register", 
> ACC_RW, 0x00000000},
> +
> +
> +/* eTSEC Lossless Flow Control Registers */
> +
> +{0xC00, "RQPRM0",  "Receive Queue Parameters register 0 ", ACC_RW, 
> 0x00000000},
> +{0xC04, "RQPRM1",  "Receive Queue Parameters register 1 ", ACC_RW, 
> 0x00000000},
> +{0xC08, "RQPRM2",  "Receive Queue Parameters register 2 ", ACC_RW, 
> 0x00000000},
> +{0xC0C, "RQPRM3",  "Receive Queue Parameters register 3 ", ACC_RW, 
> 0x00000000},
> +{0xC10, "RQPRM4",  "Receive Queue Parameters register 4 ", ACC_RW, 
> 0x00000000},
> +{0xC14, "RQPRM5",  "Receive Queue Parameters register 5 ", ACC_RW, 
> 0x00000000},
> +{0xC18, "RQPRM6",  "Receive Queue Parameters register 6 ", ACC_RW, 
> 0x00000000},
> +{0xC1C, "RQPRM7",  "Receive Queue Parameters register 7 ", ACC_RW, 
> 0x00000000},
> +{0xC44, "RFBPTR0", "Last Free RxBD pointer for ring 0",    ACC_RW, 
> 0x00000000},
> +{0xC4C, "RFBPTR1", "Last Free RxBD pointer for ring 1",    ACC_RW, 
> 0x00000000},
> +{0xC54, "RFBPTR2", "Last Free RxBD pointer for ring 2",    ACC_RW, 
> 0x00000000},
> +{0xC5C, "RFBPTR3", "Last Free RxBD pointer for ring 3",    ACC_RW, 
> 0x00000000},
> +{0xC64, "RFBPTR4", "Last Free RxBD pointer for ring 4",    ACC_RW, 
> 0x00000000},
> +{0xC6C, "RFBPTR5", "Last Free RxBD pointer for ring 5",    ACC_RW, 
> 0x00000000},
> +{0xC74, "RFBPTR6", "Last Free RxBD pointer for ring 6",    ACC_RW, 
> 0x00000000},
> +{0xC7C, "RFBPTR7", "Last Free RxBD pointer for ring 7",    ACC_RW, 
> 0x00000000},
> +
> +/* eTSEC Future Expansion Space */
> +
> +/* Reserved*/
> +
> +/* eTSEC IEEE 1588 Registers */
> +
> +{0xE00, "TMR_CTRL",     "Timer control register",                          
> ACC_RW,  0x00010001},
> +{0xE04, "TMR_TEVENT",   "time stamp event register",                       
> ACC_w1c, 0x00000000},
> +{0xE08, "TMR_TEMASK",   "Timer event mask register",                       
> ACC_RW,  0x00000000},
> +{0xE0C, "TMR_PEVENT",   "time stamp event register",                       
> ACC_RW,  0x00000000},
> +{0xE10, "TMR_PEMASK",   "Timer event mask register",                       
> ACC_RW,  0x00000000},
> +{0xE14, "TMR_STAT",     "time stamp status register",                      
> ACC_RW,  0x00000000},
> +{0xE18, "TMR_CNT_H",    "timer counter high register",                     
> ACC_RW,  0x00000000},
> +{0xE1C, "TMR_CNT_L",    "timer counter low register",                      
> ACC_RW,  0x00000000},
> +{0xE20, "TMR_ADD",      "Timer drift compensation addend register",        
> ACC_RW,  0x00000000},
> +{0xE24, "TMR_ACC",      "Timer accumulator register",                      
> ACC_RW,  0x00000000},
> +{0xE28, "TMR_PRSC",     "Timer prescale",                                  
> ACC_RW,  0x00000002},
> +{0xE30, "TMROFF_H",     "Timer offset high",                               
> ACC_RW,  0x00000000},
> +{0xE34, "TMROFF_L",     "Timer offset low",                                
> ACC_RW,  0x00000000},
> +{0xE40, "TMR_ALARM1_H", "Timer alarm 1 high register",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE44, "TMR_ALARM1_L", "Timer alarm 1 high register",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE48, "TMR_ALARM2_H", "Timer alarm 2 high register",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE4C, "TMR_ALARM2_L", "Timer alarm 2 high register",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE80, "TMR_FIPER1",   "Timer fixed period interval",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE84, "TMR_FIPER2",   "Timer fixed period interval",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xE88, "TMR_FIPER3",   "Timer fixed period interval",                     
> ACC_RW,  0xFFFFFFFF},
> +{0xEA0, "TMR_ETTS1_H",  "Time stamp of general purpose external trigger ", 
> ACC_RW,  0x00000000},
> +{0xEA4, "TMR_ETTS1_L",  "Time stamp of general purpose external trigger",  
> ACC_RW,  0x00000000},
> +{0xEA8, "TMR_ETTS2_H",  "Time stamp of general purpose external trigger ", 
> ACC_RW,  0x00000000},
> +{0xEAC, "TMR_ETTS2_L",  "Time stamp of general purpose external trigger",  
> ACC_RW,  0x00000000},
> +
> +/* End Of Table */
> +{0x0, 0x0, 0x0, 0x0, 0x0}
> +};
> diff --git a/hw/net/etsec_registers.h b/hw/net/etsec_registers.h
> new file mode 100644
> index 0000000..7faeaa9
> --- /dev/null
> +++ b/hw/net/etsec_registers.h
> @@ -0,0 +1,302 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#ifndef _ETSEC_REGISTERS_H_
> +#define _ETSEC_REGISTERS_H_
> +
> +#include <stdint.h>
> +
> +typedef struct eTSEC_Register_Definition {
> +    uint32_t offset;
> +    const char *name;
> +    const char *desc;
> +    uint32_t access;
> +    uint32_t reset;
> +} eTSEC_Register_Definition;
> +
> +#define ACC_RW      1           /* Read/Write */
> +#define ACC_RO      2           /* Read Only */
> +#define ACC_WO      3           /* Write Only */
> +#define ACC_w1c     4           /* Write 1 to clear */

ACC_W1C. Would it be cleaner with an enum instead?

> +#define ACC_UNKNOWN 4           /* Unknown register*/
> +
> +extern const eTSEC_Register_Definition eTSEC_registers_def[];
> +
> +#define DMACTRL_LE  (1 << 15)
> +#define DMACTRL_GRS (1 <<  4)
> +#define DMACTRL_GTS (1 <<  3)
> +#define DMACTRL_WOP (1 <<  0)
> +
> +#define IEVENT_RXF  (1 <<  7)
> +#define IEVENT_GRSC (1 <<  8)
> +#define IEVENT_RXB  (1 << 15)
> +#define IEVENT_TXF  (1 << 20)
> +#define IEVENT_TXB  (1 << 21)
> +#define IEVENT_TXC  (1 << 23)
> +#define IEVENT_GTSC (1 << 25)
> +#define IEVENT_BSY  (1 << 29)
> +#define IEVENT_RXC  (1 << 30)
> +
> +#define IMASK_RXFEN  (1 <<  7)
> +#define IMASK_GRSCEN (1 <<  8)
> +#define IMASK_RXBEN  (1 << 15)
> +#define IMASK_TXFEN  (1 << 20)
> +#define IMASK_TXBEN  (1 << 21)
> +#define IMASK_GTSCEN (1 << 25)
> +
> +#define MACCFG1_TX_EN  (1 << 0)
> +#define MACCFG1_RX_EN  (1 << 2)
> +
> +#define MACCFG2_CRC_EN  (1 << 1)
> +#define MACCFG2_PADCRC  (1 << 2)
> +
> +#define MIIMCOM_READ (1 << 0)
> +#define MIIMCOM_SCAN (1 << 1)
> +
> +#define RCTRL_PRSDEP_MASK   (0x3)
> +#define RCTRL_PRSDEP_OFFSET (6)
> +#define RCTRL_RSF           (1 << 2)
> +
> +/* Index of each register */
> +
> +#define TSEC_ID      (0x000 / 4)
> +#define TSEC_ID2     (0x004 / 4)
> +#define IEVENT       (0x010 / 4)
> +#define IMASK        (0x014 / 4)
> +#define EDIS         (0x018 / 4)
> +#define ECNTRL       (0x020 / 4)
> +#define PTV          (0x028 / 4)
> +#define DMACTRL      (0x02C / 4)
> +#define TBIPA        (0x030 / 4)
> +#define TCTRL        (0x100 / 4)
> +#define TSTAT        (0x104 / 4)
> +#define DFVLAN       (0x108 / 4)
> +#define TXIC         (0x110 / 4)
> +#define TQUEUE       (0x114 / 4)
> +#define TR03WT       (0x140 / 4)
> +#define TR47WT       (0x144 / 4)
> +#define TBDBPH       (0x180 / 4)
> +#define TBPTR0       (0x184 / 4)
> +#define TBPTR1       (0x18C / 4)
> +#define TBPTR2       (0x194 / 4)
> +#define TBPTR3       (0x19C / 4)
> +#define TBPTR4       (0x1A4 / 4)
> +#define TBPTR5       (0x1AC / 4)
> +#define TBPTR6       (0x1B4 / 4)
> +#define TBPTR7       (0x1BC / 4)
> +#define TBASEH       (0x200 / 4)
> +#define TBASE0       (0x204 / 4)
> +#define TBASE1       (0x20C / 4)
> +#define TBASE2       (0x214 / 4)
> +#define TBASE3       (0x21C / 4)
> +#define TBASE4       (0x224 / 4)
> +#define TBASE5       (0x22C / 4)
> +#define TBASE6       (0x234 / 4)
> +#define TBASE7       (0x23C / 4)
> +#define TMR_TXTS1_ID (0x280 / 4)
> +#define TMR_TXTS2_ID (0x284 / 4)
> +#define TMR_TXTS1_H  (0x2C0 / 4)
> +#define TMR_TXTS1_L  (0x2C4 / 4)
> +#define TMR_TXTS2_H  (0x2C8 / 4)
> +#define TMR_TXTS2_L  (0x2CC / 4)
> +#define RCTRL        (0x300 / 4)
> +#define RSTAT        (0x304 / 4)
> +#define RXIC         (0x310 / 4)
> +#define RQUEUE       (0x314 / 4)
> +#define RBIFX        (0x330 / 4)
> +#define RQFAR        (0x334 / 4)
> +#define RQFCR        (0x338 / 4)
> +#define RQFPR        (0x33C / 4)
> +#define MRBLR        (0x340 / 4)
> +#define RBDBPH       (0x380 / 4)
> +#define RBPTR0       (0x384 / 4)
> +#define RBPTR1       (0x38C / 4)
> +#define RBPTR2       (0x394 / 4)
> +#define RBPTR3       (0x39C / 4)
> +#define RBPTR4       (0x3A4 / 4)
> +#define RBPTR5       (0x3AC / 4)
> +#define RBPTR6       (0x3B4 / 4)
> +#define RBPTR7       (0x3BC / 4)
> +#define RBASEH       (0x400 / 4)
> +#define RBASE0       (0x404 / 4)
> +#define RBASE1       (0x40C / 4)
> +#define RBASE2       (0x414 / 4)
> +#define RBASE3       (0x41C / 4)
> +#define RBASE4       (0x424 / 4)
> +#define RBASE5       (0x42C / 4)
> +#define RBASE6       (0x434 / 4)
> +#define RBASE7       (0x43C / 4)
> +#define TMR_RXTS_H   (0x4C0 / 4)
> +#define TMR_RXTS_L   (0x4C4 / 4)
> +#define MACCFG1      (0x500 / 4)
> +#define MACCFG2      (0x504 / 4)
> +#define IPGIFG       (0x508 / 4)
> +#define HAFDUP       (0x50C / 4)
> +#define MAXFRM       (0x510 / 4)
> +#define MIIMCFG      (0x520 / 4)
> +#define MIIMCOM      (0x524 / 4)
> +#define MIIMADD      (0x528 / 4)
> +#define MIIMCON      (0x52C / 4)
> +#define MIIMSTAT     (0x530 / 4)
> +#define MIIMIND      (0x534 / 4)
> +#define IFSTAT       (0x53C / 4)
> +#define MACSTNADDR1  (0x540 / 4)
> +#define MACSTNADDR2  (0x544 / 4)
> +#define MAC01ADDR1   (0x548 / 4)
> +#define MAC01ADDR2   (0x54C / 4)
> +#define MAC02ADDR1   (0x550 / 4)
> +#define MAC02ADDR2   (0x554 / 4)
> +#define MAC03ADDR1   (0x558 / 4)
> +#define MAC03ADDR2   (0x55C / 4)
> +#define MAC04ADDR1   (0x560 / 4)
> +#define MAC04ADDR2   (0x564 / 4)
> +#define MAC05ADDR1   (0x568 / 4)
> +#define MAC05ADDR2   (0x56C / 4)
> +#define MAC06ADDR1   (0x570 / 4)
> +#define MAC06ADDR2   (0x574 / 4)
> +#define MAC07ADDR1   (0x578 / 4)
> +#define MAC07ADDR2   (0x57C / 4)
> +#define MAC08ADDR1   (0x580 / 4)
> +#define MAC08ADDR2   (0x584 / 4)
> +#define MAC09ADDR1   (0x588 / 4)
> +#define MAC09ADDR2   (0x58C / 4)
> +#define MAC10ADDR1   (0x590 / 4)
> +#define MAC10ADDR2   (0x594 / 4)
> +#define MAC11ADDR1   (0x598 / 4)
> +#define MAC11ADDR2   (0x59C / 4)
> +#define MAC12ADDR1   (0x5A0 / 4)
> +#define MAC12ADDR2   (0x5A4 / 4)
> +#define MAC13ADDR1   (0x5A8 / 4)
> +#define MAC13ADDR2   (0x5AC / 4)
> +#define MAC14ADDR1   (0x5B0 / 4)
> +#define MAC14ADDR2   (0x5B4 / 4)
> +#define MAC15ADDR1   (0x5B8 / 4)
> +#define MAC15ADDR2   (0x5BC / 4)
> +#define TR64         (0x680 / 4)
> +#define TR127        (0x684 / 4)
> +#define TR255        (0x688 / 4)
> +#define TR511        (0x68C / 4)
> +#define TR1K         (0x690 / 4)
> +#define TRMAX        (0x694 / 4)
> +#define TRMGV        (0x698 / 4)
> +#define RBYT         (0x69C / 4)
> +#define RPKT         (0x6A0 / 4)
> +#define RFCS         (0x6A4 / 4)
> +#define RMCA         (0x6A8 / 4)
> +#define RBCA         (0x6AC / 4)
> +#define RXCF         (0x6B0 / 4)
> +#define RXPF         (0x6B4 / 4)
> +#define RXUO         (0x6B8 / 4)
> +#define RALN         (0x6BC / 4)
> +#define RFLR         (0x6C0 / 4)
> +#define RCDE         (0x6C4 / 4)
> +#define RCSE         (0x6C8 / 4)
> +#define RUND         (0x6CC / 4)
> +#define ROVR         (0x6D0 / 4)
> +#define RFRG         (0x6D4 / 4)
> +#define RJBR         (0x6D8 / 4)
> +#define RDRP         (0x6DC / 4)
> +#define TBYT         (0x6E0 / 4)
> +#define TPKT         (0x6E4 / 4)
> +#define TMCA         (0x6E8 / 4)
> +#define TBCA         (0x6EC / 4)
> +#define TXPF         (0x6F0 / 4)
> +#define TDFR         (0x6F4 / 4)
> +#define TEDF         (0x6F8 / 4)
> +#define TSCL         (0x6FC / 4)
> +#define TMCL         (0x700 / 4)
> +#define TLCL         (0x704 / 4)
> +#define TXCL         (0x708 / 4)
> +#define TNCL         (0x70C / 4)
> +#define TDRP         (0x714 / 4)
> +#define TJBR         (0x718 / 4)
> +#define TFCS         (0x71C / 4)
> +#define TXCF         (0x720 / 4)
> +#define TOVR         (0x724 / 4)
> +#define TUND         (0x728 / 4)
> +#define TFRG         (0x72C / 4)
> +#define CAR1         (0x730 / 4)
> +#define CAR2         (0x734 / 4)
> +#define CAM1         (0x738 / 4)
> +#define CAM2         (0x73C / 4)
> +#define RREJ         (0x740 / 4)
> +#define IGADDR0      (0x800 / 4)
> +#define IGADDR1      (0x804 / 4)
> +#define IGADDR2      (0x808 / 4)
> +#define IGADDR3      (0x80C / 4)
> +#define IGADDR4      (0x810 / 4)
> +#define IGADDR5      (0x814 / 4)
> +#define IGADDR6      (0x818 / 4)
> +#define IGADDR7      (0x81C / 4)
> +#define GADDR0       (0x880 / 4)
> +#define GADDR1       (0x884 / 4)
> +#define GADDR2       (0x888 / 4)
> +#define GADDR3       (0x88C / 4)
> +#define GADDR4       (0x890 / 4)
> +#define GADDR5       (0x894 / 4)
> +#define GADDR6       (0x898 / 4)
> +#define GADDR7       (0x89C / 4)
> +#define ATTR         (0xBF8 / 4)
> +#define ATTRELI      (0xBFC / 4)
> +#define RQPRM0       (0xC00 / 4)
> +#define RQPRM1       (0xC04 / 4)
> +#define RQPRM2       (0xC08 / 4)
> +#define RQPRM3       (0xC0C / 4)
> +#define RQPRM4       (0xC10 / 4)
> +#define RQPRM5       (0xC14 / 4)
> +#define RQPRM6       (0xC18 / 4)
> +#define RQPRM7       (0xC1C / 4)
> +#define RFBPTR0      (0xC44 / 4)
> +#define RFBPTR1      (0xC4C / 4)
> +#define RFBPTR2      (0xC54 / 4)
> +#define RFBPTR3      (0xC5C / 4)
> +#define RFBPTR4      (0xC64 / 4)
> +#define RFBPTR5      (0xC6C / 4)
> +#define RFBPTR6      (0xC74 / 4)
> +#define RFBPTR7      (0xC7C / 4)
> +#define TMR_CTRL     (0xE00 / 4)
> +#define TMR_TEVENT   (0xE04 / 4)
> +#define TMR_TEMASK   (0xE08 / 4)
> +#define TMR_PEVENT   (0xE0C / 4)
> +#define TMR_PEMASK   (0xE10 / 4)
> +#define TMR_STAT     (0xE14 / 4)
> +#define TMR_CNT_H    (0xE18 / 4)
> +#define TMR_CNT_L    (0xE1C / 4)
> +#define TMR_ADD      (0xE20 / 4)
> +#define TMR_ACC      (0xE24 / 4)
> +#define TMR_PRSC     (0xE28 / 4)
> +#define TMROFF_H     (0xE30 / 4)
> +#define TMROFF_L     (0xE34 / 4)
> +#define TMR_ALARM1_H (0xE40 / 4)
> +#define TMR_ALARM1_L (0xE44 / 4)
> +#define TMR_ALARM2_H (0xE48 / 4)
> +#define TMR_ALARM2_L (0xE4C / 4)
> +#define TMR_FIPER1   (0xE80 / 4)
> +#define TMR_FIPER2   (0xE84 / 4)
> +#define TMR_FIPER3   (0xE88 / 4)
> +#define TMR_ETTS1_H  (0xEA0 / 4)
> +#define TMR_ETTS1_L  (0xEA4 / 4)
> +#define TMR_ETTS2_H  (0xEA8 / 4)
> +#define TMR_ETTS2_L  (0xEAC / 4)
> +
> +#endif /* ! _ETSEC_REGISTERS_H_ */
> diff --git a/hw/net/etsec_rings.c b/hw/net/etsec_rings.c
> new file mode 100644
> index 0000000..15c0616
> --- /dev/null
> +++ b/hw/net/etsec_rings.c
> @@ -0,0 +1,673 @@
> +/*
> + * QEMU Freescale eTSEC Emulator
> + *
> + * Copyright (c) 2011-2013 AdaCore
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#include "qemu/bswap.h"
> +#include "net/checksum.h"
> +
> +#include "etsec.h"
> +#include "etsec_registers.h"
> +
> +/* #define ETSEC_RING_DEBUG */
> +/* #define HEX_DUMP */
> +/* #define DEBUG_BD */
> +
> +#ifdef ETSEC_RING_DEBUG
> +#define RING_DEBUG(fmt, ...) printf("%s:%s " fmt, __func__ ,\
> +                                    etsec->nic->nc.name, ## __VA_ARGS__)
> +#else
> +#define RING_DEBUG(...)
> +#endif  /* ETSEC_RING_DEBUG */
> +
> +#define RING_DEBUG_A(fmt, ...) printf("%s:%s " fmt, __func__ ,\
> +                                      etsec->nic->nc.name, ## __VA_ARGS__)
> +
> +#ifdef DEBUG_BD
> +
> +static void print_tx_bd_flags(uint16_t flags)
> +{
> +    printf("      Ready: %d\n", !!(flags & BD_TX_READY));
> +    printf("      PAD/CRC: %d\n", !!(flags & BD_TX_PADCRC));
> +    printf("      Wrap: %d\n", !!(flags & BD_WRAP));
> +    printf("      Interrupt: %d\n", !!(flags & BD_INTERRUPT));
> +    printf("      Last in frame: %d\n", !!(flags & BD_LAST));
> +    printf("      Tx CRC: %d\n", !!(flags & BD_TX_TC));
> +    printf("      User-defined preamble / defer: %d\n",
> +           !!(flags & BD_TX_PREDEF));
> +    printf("      Huge frame enable / Late collision: %d\n",
> +           !!(flags & BD_TX_HFELC));
> +    printf("      Control frame / Retransmission Limit: %d\n",
> +           !!(flags & BD_TX_CFRL));
> +    printf("      Retry count: %d\n",
> +           (flags >> BD_TX_RC_OFFSET) & BD_TX_RC_MASK);
> +    printf("      Underrun / TCP/IP off-load enable: %d\n",
> +           !!(flags & BD_TX_TOEUN));
> +    printf("      Truncation: %d\n", !!(flags & BD_TX_TR));
> +}
> +
> +static void print_rx_bd_flags(uint16_t flags)
> +{
> +    printf("      Empty: %d\n", !!(flags & BD_RX_EMPTY));
> +    printf("      Receive software ownership: %d\n", !!(flags & BD_RX_RO1));
> +    printf("      Wrap: %d\n", !!(flags & BD_WRAP));
> +    printf("      Interrupt: %d\n", !!(flags & BD_INTERRUPT));
> +    printf("      Last in frame: %d\n", !!(flags & BD_LAST));
> +    printf("      First in frame: %d\n", !!(flags & BD_RX_FIRST));
> +    printf("      Miss: %d\n", !!(flags & BD_RX_MISS));
> +    printf("      Broadcast: %d\n", !!(flags & BD_RX_BROADCAST));
> +    printf("      Multicast: %d\n", !!(flags & BD_RX_MULTICAST));
> +    printf("      Rx frame length violation: %d\n", !!(flags & BD_RX_LG));
> +    printf("      Rx non-octet aligned frame: %d\n", !!(flags & BD_RX_NO));
> +    printf("      Short frame: %d\n", !!(flags & BD_RX_SH));
> +    printf("      Rx CRC Error: %d\n", !!(flags & BD_RX_CR));
> +    printf("      Overrun: %d\n", !!(flags & BD_RX_OV));
> +    printf("      Truncation: %d\n", !!(flags & BD_RX_TR));
> +}
> +
> +
> +static void print_bd(eTSEC_rxtx_bd bd, int mode, uint32_t index)
> +{
> +    printf("eTSEC %s Data Buffer Descriptor (%u)\n",
> +           mode == eTSEC_TRANSMIT ? "Transmit" : "Receive",
> +           index);
> +    printf("   Flags   : 0x%04x\n", bd.flags);
> +    if (mode == eTSEC_TRANSMIT) {
> +        print_tx_bd_flags(bd.flags);
> +    } else {
> +        print_rx_bd_flags(bd.flags);
> +    }
> +    printf("   Length  : 0x%04x\n", bd.length);
> +    printf("   Pointer : 0x%08x\n", bd.bufptr);
> +}
> +
> +#endif  /* DEBUG_BD */
> +
> +#ifdef HEX_DUMP
> +
> +static void hex_dump(FILE *f, const uint8_t *buf, int size)

can you just use qemu_hexdump?

check util/hexdump.c

Regards,
Peter



reply via email to

[Prev in Thread] Current Thread [Next in Thread]