qemu/hw/net/msf2-emac.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the Smartfusion2 Ethernet MAC.
   3 *
   4 * Copyright (c) 2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 *
  24 * Refer to section Ethernet MAC in the document:
  25 * UG0331: SmartFusion2 Microcontroller Subsystem User Guide
  26 * Datasheet URL:
  27 * https://www.microsemi.com/document-portal/cat_view/56661-internal-documents/
  28 * 56758-soc?lang=en&limit=20&limitstart=220
  29 */
  30
  31#include "qemu/osdep.h"
  32#include "qemu/log.h"
  33#include "qapi/error.h"
  34#include "hw/registerfields.h"
  35#include "hw/net/msf2-emac.h"
  36#include "hw/net/mii.h"
  37#include "hw/irq.h"
  38#include "hw/qdev-properties.h"
  39#include "migration/vmstate.h"
  40
  41REG32(CFG1, 0x0)
  42    FIELD(CFG1, RESET, 31, 1)
  43    FIELD(CFG1, RX_EN, 2, 1)
  44    FIELD(CFG1, TX_EN, 0, 1)
  45    FIELD(CFG1, LB_EN, 8, 1)
  46REG32(CFG2, 0x4)
  47REG32(IFG, 0x8)
  48REG32(HALF_DUPLEX, 0xc)
  49REG32(MAX_FRAME_LENGTH, 0x10)
  50REG32(MII_CMD, 0x24)
  51    FIELD(MII_CMD, READ, 0, 1)
  52REG32(MII_ADDR, 0x28)
  53    FIELD(MII_ADDR, REGADDR, 0, 5)
  54    FIELD(MII_ADDR, PHYADDR, 8, 5)
  55REG32(MII_CTL, 0x2c)
  56REG32(MII_STS, 0x30)
  57REG32(STA1, 0x40)
  58REG32(STA2, 0x44)
  59REG32(FIFO_CFG0, 0x48)
  60REG32(FIFO_CFG4, 0x58)
  61    FIELD(FIFO_CFG4, BCAST, 9, 1)
  62    FIELD(FIFO_CFG4, MCAST, 8, 1)
  63REG32(FIFO_CFG5, 0x5C)
  64    FIELD(FIFO_CFG5, BCAST, 9, 1)
  65    FIELD(FIFO_CFG5, MCAST, 8, 1)
  66REG32(DMA_TX_CTL, 0x180)
  67    FIELD(DMA_TX_CTL, EN, 0, 1)
  68REG32(DMA_TX_DESC, 0x184)
  69REG32(DMA_TX_STATUS, 0x188)
  70    FIELD(DMA_TX_STATUS, PKTCNT, 16, 8)
  71    FIELD(DMA_TX_STATUS, UNDERRUN, 1, 1)
  72    FIELD(DMA_TX_STATUS, PKT_SENT, 0, 1)
  73REG32(DMA_RX_CTL, 0x18c)
  74    FIELD(DMA_RX_CTL, EN, 0, 1)
  75REG32(DMA_RX_DESC, 0x190)
  76REG32(DMA_RX_STATUS, 0x194)
  77    FIELD(DMA_RX_STATUS, PKTCNT, 16, 8)
  78    FIELD(DMA_RX_STATUS, OVERFLOW, 2, 1)
  79    FIELD(DMA_RX_STATUS, PKT_RCVD, 0, 1)
  80REG32(DMA_IRQ_MASK, 0x198)
  81REG32(DMA_IRQ, 0x19c)
  82
  83#define EMPTY_MASK              (1 << 31)
  84#define PKT_SIZE                0x7FF
  85#define PHYADDR                 0x1
  86#define MAX_PKT_SIZE            2048
  87
  88typedef struct {
  89    uint32_t pktaddr;
  90    uint32_t pktsize;
  91    uint32_t next;
  92} EmacDesc;
  93
  94static uint32_t emac_get_isr(MSF2EmacState *s)
  95{
  96    uint32_t ier = s->regs[R_DMA_IRQ_MASK];
  97    uint32_t tx = s->regs[R_DMA_TX_STATUS] & 0xF;
  98    uint32_t rx = s->regs[R_DMA_RX_STATUS] & 0xF;
  99    uint32_t isr = (rx << 4) | tx;
 100
 101    s->regs[R_DMA_IRQ] = ier & isr;
 102    return s->regs[R_DMA_IRQ];
 103}
 104
 105static void emac_update_irq(MSF2EmacState *s)
 106{
 107    bool intr = emac_get_isr(s);
 108
 109    qemu_set_irq(s->irq, intr);
 110}
 111
 112static void emac_load_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
 113{
 114    address_space_read(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
 115    /* Convert from LE into host endianness. */
 116    d->pktaddr = le32_to_cpu(d->pktaddr);
 117    d->pktsize = le32_to_cpu(d->pktsize);
 118    d->next = le32_to_cpu(d->next);
 119}
 120
 121static void emac_store_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
 122{
 123    /* Convert from host endianness into LE. */
 124    d->pktaddr = cpu_to_le32(d->pktaddr);
 125    d->pktsize = cpu_to_le32(d->pktsize);
 126    d->next = cpu_to_le32(d->next);
 127
 128    address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
 129}
 130
 131static void msf2_dma_tx(MSF2EmacState *s)
 132{
 133    NetClientState *nc = qemu_get_queue(s->nic);
 134    hwaddr desc = s->regs[R_DMA_TX_DESC];
 135    uint8_t buf[MAX_PKT_SIZE];
 136    EmacDesc d;
 137    int size;
 138    uint8_t pktcnt;
 139    uint32_t status;
 140
 141    if (!(s->regs[R_CFG1] & R_CFG1_TX_EN_MASK)) {
 142        return;
 143    }
 144
 145    while (1) {
 146        emac_load_desc(s, &d, desc);
 147        if (d.pktsize & EMPTY_MASK) {
 148            break;
 149        }
 150        size = d.pktsize & PKT_SIZE;
 151        address_space_read(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED,
 152                           buf, size);
 153        /*
 154         * This is very basic way to send packets. Ideally there should be
 155         * a FIFO and packets should be sent out from FIFO only when
 156         * R_CFG1 bit 0 is set.
 157         */
 158        if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) {
 159            qemu_receive_packet(nc, buf, size);
 160        } else {
 161            qemu_send_packet(nc, buf, size);
 162        }
 163        d.pktsize |= EMPTY_MASK;
 164        emac_store_desc(s, &d, desc);
 165        /* update sent packets count */
 166        status = s->regs[R_DMA_TX_STATUS];
 167        pktcnt = FIELD_EX32(status, DMA_TX_STATUS, PKTCNT);
 168        pktcnt++;
 169        s->regs[R_DMA_TX_STATUS] = FIELD_DP32(status, DMA_TX_STATUS,
 170                                              PKTCNT, pktcnt);
 171        s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_PKT_SENT_MASK;
 172        desc = d.next;
 173    }
 174    s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_UNDERRUN_MASK;
 175    s->regs[R_DMA_TX_CTL] &= ~R_DMA_TX_CTL_EN_MASK;
 176}
 177
 178static void msf2_phy_update_link(MSF2EmacState *s)
 179{
 180    /* Autonegotiation status mirrors link status. */
 181    if (qemu_get_queue(s->nic)->link_down) {
 182        s->phy_regs[MII_BMSR] &= ~(MII_BMSR_AN_COMP |
 183                                   MII_BMSR_LINK_ST);
 184    } else {
 185        s->phy_regs[MII_BMSR] |= (MII_BMSR_AN_COMP |
 186                                  MII_BMSR_LINK_ST);
 187    }
 188}
 189
 190static void msf2_phy_reset(MSF2EmacState *s)
 191{
 192    memset(&s->phy_regs[0], 0, sizeof(s->phy_regs));
 193    s->phy_regs[MII_BMCR] = 0x1140;
 194    s->phy_regs[MII_BMSR] = 0x7968;
 195    s->phy_regs[MII_PHYID1] = 0x0022;
 196    s->phy_regs[MII_PHYID2] = 0x1550;
 197    s->phy_regs[MII_ANAR] = 0x01E1;
 198    s->phy_regs[MII_ANLPAR] = 0xCDE1;
 199
 200    msf2_phy_update_link(s);
 201}
 202
 203static void write_to_phy(MSF2EmacState *s)
 204{
 205    uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK;
 206    uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) &
 207                       R_MII_ADDR_REGADDR_MASK;
 208    uint16_t data = s->regs[R_MII_CTL] & 0xFFFF;
 209
 210    if (phy_addr != PHYADDR) {
 211        return;
 212    }
 213
 214    switch (reg_addr) {
 215    case MII_BMCR:
 216        if (data & MII_BMCR_RESET) {
 217            /* Phy reset */
 218            msf2_phy_reset(s);
 219            data &= ~MII_BMCR_RESET;
 220        }
 221        if (data & MII_BMCR_AUTOEN) {
 222            /* Complete autonegotiation immediately */
 223            data &= ~MII_BMCR_AUTOEN;
 224            s->phy_regs[MII_BMSR] |= MII_BMSR_AN_COMP;
 225        }
 226        break;
 227    }
 228
 229    s->phy_regs[reg_addr] = data;
 230}
 231
 232static uint16_t read_from_phy(MSF2EmacState *s)
 233{
 234    uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK;
 235    uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) &
 236                       R_MII_ADDR_REGADDR_MASK;
 237
 238    if (phy_addr == PHYADDR) {
 239        return s->phy_regs[reg_addr];
 240    } else {
 241        return 0xFFFF;
 242    }
 243}
 244
 245static void msf2_emac_do_reset(MSF2EmacState *s)
 246{
 247    memset(&s->regs[0], 0, sizeof(s->regs));
 248    s->regs[R_CFG1] = 0x80000000;
 249    s->regs[R_CFG2] = 0x00007000;
 250    s->regs[R_IFG] = 0x40605060;
 251    s->regs[R_HALF_DUPLEX] = 0x00A1F037;
 252    s->regs[R_MAX_FRAME_LENGTH] = 0x00000600;
 253    s->regs[R_FIFO_CFG5] = 0X3FFFF;
 254
 255    msf2_phy_reset(s);
 256}
 257
 258static uint64_t emac_read(void *opaque, hwaddr addr, unsigned int size)
 259{
 260    MSF2EmacState *s = opaque;
 261    uint32_t r = 0;
 262
 263    addr >>= 2;
 264
 265    switch (addr) {
 266    case R_DMA_IRQ:
 267        r = emac_get_isr(s);
 268        break;
 269    default:
 270        if (addr >= ARRAY_SIZE(s->regs)) {
 271            qemu_log_mask(LOG_GUEST_ERROR,
 272                          "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
 273                          addr * 4);
 274            return r;
 275        }
 276        r = s->regs[addr];
 277        break;
 278    }
 279    return r;
 280}
 281
 282static void emac_write(void *opaque, hwaddr addr, uint64_t val64,
 283        unsigned int size)
 284{
 285    MSF2EmacState *s = opaque;
 286    uint32_t value = val64;
 287    uint32_t enreqbits;
 288    uint8_t pktcnt;
 289
 290    addr >>= 2;
 291    switch (addr) {
 292    case R_DMA_TX_CTL:
 293        s->regs[addr] = value;
 294        if (value & R_DMA_TX_CTL_EN_MASK) {
 295            msf2_dma_tx(s);
 296        }
 297        break;
 298    case R_DMA_RX_CTL:
 299        s->regs[addr] = value;
 300        if (value & R_DMA_RX_CTL_EN_MASK) {
 301            s->rx_desc = s->regs[R_DMA_RX_DESC];
 302            qemu_flush_queued_packets(qemu_get_queue(s->nic));
 303        }
 304        break;
 305    case R_CFG1:
 306        s->regs[addr] = value;
 307        if (value & R_CFG1_RESET_MASK) {
 308            msf2_emac_do_reset(s);
 309        }
 310        break;
 311    case R_FIFO_CFG0:
 312       /*
 313        * For our implementation, turning on modules is instantaneous,
 314        * so the states requested via the *ENREQ bits appear in the
 315        * *ENRPLY bits immediately. Also the reset bits to reset PE-MCXMAC
 316        * module are not emulated here since it deals with start of frames,
 317        * inter-packet gap and control frames.
 318        */
 319        enreqbits = extract32(value, 8, 5);
 320        s->regs[addr] = deposit32(value, 16, 5, enreqbits);
 321        break;
 322    case R_DMA_TX_DESC:
 323        if (value & 0x3) {
 324            qemu_log_mask(LOG_GUEST_ERROR, "Tx Descriptor address should be"
 325                          " 32 bit aligned\n");
 326        }
 327        /* Ignore [1:0] bits */
 328        s->regs[addr] = value & ~3;
 329        break;
 330    case R_DMA_RX_DESC:
 331        if (value & 0x3) {
 332            qemu_log_mask(LOG_GUEST_ERROR, "Rx Descriptor address should be"
 333                          " 32 bit aligned\n");
 334        }
 335        /* Ignore [1:0] bits */
 336        s->regs[addr] = value & ~3;
 337        break;
 338    case R_DMA_TX_STATUS:
 339        if (value & R_DMA_TX_STATUS_UNDERRUN_MASK) {
 340            s->regs[addr] &= ~R_DMA_TX_STATUS_UNDERRUN_MASK;
 341        }
 342        if (value & R_DMA_TX_STATUS_PKT_SENT_MASK) {
 343            pktcnt = FIELD_EX32(s->regs[addr], DMA_TX_STATUS, PKTCNT);
 344            pktcnt--;
 345            s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_TX_STATUS,
 346                                       PKTCNT, pktcnt);
 347            if (pktcnt == 0) {
 348                s->regs[addr] &= ~R_DMA_TX_STATUS_PKT_SENT_MASK;
 349            }
 350        }
 351        break;
 352    case R_DMA_RX_STATUS:
 353        if (value & R_DMA_RX_STATUS_OVERFLOW_MASK) {
 354            s->regs[addr] &= ~R_DMA_RX_STATUS_OVERFLOW_MASK;
 355        }
 356        if (value & R_DMA_RX_STATUS_PKT_RCVD_MASK) {
 357            pktcnt = FIELD_EX32(s->regs[addr], DMA_RX_STATUS, PKTCNT);
 358            pktcnt--;
 359            s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_RX_STATUS,
 360                                       PKTCNT, pktcnt);
 361            if (pktcnt == 0) {
 362                s->regs[addr] &= ~R_DMA_RX_STATUS_PKT_RCVD_MASK;
 363            }
 364        }
 365        break;
 366    case R_DMA_IRQ:
 367        break;
 368    case R_MII_CMD:
 369        if (value & R_MII_CMD_READ_MASK) {
 370            s->regs[R_MII_STS] = read_from_phy(s);
 371        }
 372        break;
 373    case R_MII_CTL:
 374        s->regs[addr] = value;
 375        write_to_phy(s);
 376        break;
 377    case R_STA1:
 378        s->regs[addr] = value;
 379       /*
 380        * R_STA1 [31:24] : octet 1 of mac address
 381        * R_STA1 [23:16] : octet 2 of mac address
 382        * R_STA1 [15:8] : octet 3 of mac address
 383        * R_STA1 [7:0] : octet 4 of mac address
 384        */
 385        stl_be_p(s->mac_addr, value);
 386        break;
 387    case R_STA2:
 388        s->regs[addr] = value;
 389       /*
 390        * R_STA2 [31:24] : octet 5 of mac address
 391        * R_STA2 [23:16] : octet 6 of mac address
 392        */
 393        stw_be_p(s->mac_addr + 4, value >> 16);
 394        break;
 395    default:
 396        if (addr >= ARRAY_SIZE(s->regs)) {
 397            qemu_log_mask(LOG_GUEST_ERROR,
 398                          "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
 399                          addr * 4);
 400            return;
 401        }
 402        s->regs[addr] = value;
 403        break;
 404    }
 405    emac_update_irq(s);
 406}
 407
 408static const MemoryRegionOps emac_ops = {
 409    .read = emac_read,
 410    .write = emac_write,
 411    .endianness = DEVICE_NATIVE_ENDIAN,
 412    .impl = {
 413        .min_access_size = 4,
 414        .max_access_size = 4
 415    }
 416};
 417
 418static bool emac_can_rx(NetClientState *nc)
 419{
 420    MSF2EmacState *s = qemu_get_nic_opaque(nc);
 421
 422    return (s->regs[R_CFG1] & R_CFG1_RX_EN_MASK) &&
 423           (s->regs[R_DMA_RX_CTL] & R_DMA_RX_CTL_EN_MASK);
 424}
 425
 426static bool addr_filter_ok(MSF2EmacState *s, const uint8_t *buf)
 427{
 428    /* The broadcast MAC address: FF:FF:FF:FF:FF:FF */
 429    const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF,
 430                                              0xFF, 0xFF };
 431    bool bcast_en = true;
 432    bool mcast_en = true;
 433
 434    if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_BCAST_MASK) {
 435        bcast_en = true; /* Broadcast dont care for drop circuitry */
 436    } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_BCAST_MASK) {
 437        bcast_en = false;
 438    }
 439
 440    if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_MCAST_MASK) {
 441        mcast_en = true; /* Multicast dont care for drop circuitry */
 442    } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_MCAST_MASK) {
 443        mcast_en = false;
 444    }
 445
 446    if (!memcmp(buf, broadcast_addr, sizeof(broadcast_addr))) {
 447        return bcast_en;
 448    }
 449
 450    if (buf[0] & 1) {
 451        return mcast_en;
 452    }
 453
 454    return !memcmp(buf, s->mac_addr, sizeof(s->mac_addr));
 455}
 456
 457static ssize_t emac_rx(NetClientState *nc, const uint8_t *buf, size_t size)
 458{
 459    MSF2EmacState *s = qemu_get_nic_opaque(nc);
 460    EmacDesc d;
 461    uint8_t pktcnt;
 462    uint32_t status;
 463
 464    if (size > (s->regs[R_MAX_FRAME_LENGTH] & 0xFFFF)) {
 465        return size;
 466    }
 467    if (!addr_filter_ok(s, buf)) {
 468        return size;
 469    }
 470
 471    emac_load_desc(s, &d, s->rx_desc);
 472
 473    if (d.pktsize & EMPTY_MASK) {
 474        address_space_write(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED,
 475                            buf, size & PKT_SIZE);
 476        d.pktsize = size & PKT_SIZE;
 477        emac_store_desc(s, &d, s->rx_desc);
 478        /* update received packets count */
 479        status = s->regs[R_DMA_RX_STATUS];
 480        pktcnt = FIELD_EX32(status, DMA_RX_STATUS, PKTCNT);
 481        pktcnt++;
 482        s->regs[R_DMA_RX_STATUS] = FIELD_DP32(status, DMA_RX_STATUS,
 483                                              PKTCNT, pktcnt);
 484        s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_PKT_RCVD_MASK;
 485        s->rx_desc = d.next;
 486    } else {
 487        s->regs[R_DMA_RX_CTL] &= ~R_DMA_RX_CTL_EN_MASK;
 488        s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_OVERFLOW_MASK;
 489    }
 490    emac_update_irq(s);
 491    return size;
 492}
 493
 494static void msf2_emac_reset(DeviceState *dev)
 495{
 496    MSF2EmacState *s = MSS_EMAC(dev);
 497
 498    msf2_emac_do_reset(s);
 499}
 500
 501static void emac_set_link(NetClientState *nc)
 502{
 503    MSF2EmacState *s = qemu_get_nic_opaque(nc);
 504
 505    msf2_phy_update_link(s);
 506}
 507
 508static NetClientInfo net_msf2_emac_info = {
 509    .type = NET_CLIENT_DRIVER_NIC,
 510    .size = sizeof(NICState),
 511    .can_receive = emac_can_rx,
 512    .receive = emac_rx,
 513    .link_status_changed = emac_set_link,
 514};
 515
 516static void msf2_emac_realize(DeviceState *dev, Error **errp)
 517{
 518    MSF2EmacState *s = MSS_EMAC(dev);
 519
 520    if (!s->dma_mr) {
 521        error_setg(errp, "MSS_EMAC 'ahb-bus' link not set");
 522        return;
 523    }
 524
 525    address_space_init(&s->dma_as, s->dma_mr, "emac-ahb");
 526
 527    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 528    s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf,
 529                          object_get_typename(OBJECT(dev)), dev->id, s);
 530    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 531}
 532
 533static void msf2_emac_init(Object *obj)
 534{
 535    MSF2EmacState *s = MSS_EMAC(obj);
 536
 537    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
 538
 539    memory_region_init_io(&s->mmio, obj, &emac_ops, s,
 540                          "msf2-emac", R_MAX * 4);
 541    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 542}
 543
 544static Property msf2_emac_properties[] = {
 545    DEFINE_PROP_LINK("ahb-bus", MSF2EmacState, dma_mr,
 546                     TYPE_MEMORY_REGION, MemoryRegion *),
 547    DEFINE_NIC_PROPERTIES(MSF2EmacState, conf),
 548    DEFINE_PROP_END_OF_LIST(),
 549};
 550
 551static const VMStateDescription vmstate_msf2_emac = {
 552    .name = TYPE_MSS_EMAC,
 553    .version_id = 1,
 554    .minimum_version_id = 1,
 555    .fields = (VMStateField[]) {
 556        VMSTATE_UINT8_ARRAY(mac_addr, MSF2EmacState, ETH_ALEN),
 557        VMSTATE_UINT32(rx_desc, MSF2EmacState),
 558        VMSTATE_UINT16_ARRAY(phy_regs, MSF2EmacState, PHY_MAX_REGS),
 559        VMSTATE_UINT32_ARRAY(regs, MSF2EmacState, R_MAX),
 560        VMSTATE_END_OF_LIST()
 561    }
 562};
 563
 564static void msf2_emac_class_init(ObjectClass *klass, void *data)
 565{
 566    DeviceClass *dc = DEVICE_CLASS(klass);
 567
 568    dc->realize = msf2_emac_realize;
 569    dc->reset = msf2_emac_reset;
 570    dc->vmsd = &vmstate_msf2_emac;
 571    device_class_set_props(dc, msf2_emac_properties);
 572}
 573
 574static const TypeInfo msf2_emac_info = {
 575    .name          = TYPE_MSS_EMAC,
 576    .parent        = TYPE_SYS_BUS_DEVICE,
 577    .instance_size = sizeof(MSF2EmacState),
 578    .instance_init = msf2_emac_init,
 579    .class_init    = msf2_emac_class_init,
 580};
 581
 582static void msf2_emac_register_types(void)
 583{
 584    type_register_static(&msf2_emac_info);
 585}
 586
 587type_init(msf2_emac_register_types)
 588