get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/811613/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 811613,
    "url": "http://patchwork.ozlabs.org/api/patches/811613/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1504879106-2225-2-git-send-email-mark.cave-ayland@ilande.co.uk/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1504879106-2225-2-git-send-email-mark.cave-ayland@ilande.co.uk>",
    "list_archive_url": null,
    "date": "2017-09-08T13:58:25",
    "name": "[1/2] net: add Sun HME (Happy Meal Ethernet) on-board NIC",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "6243de17f916cdb8fbd1ac372c12a53ef5a0bc95",
    "submitter": {
        "id": 12451,
        "url": "http://patchwork.ozlabs.org/api/people/12451/?format=api",
        "name": "Mark Cave-Ayland",
        "email": "mark.cave-ayland@ilande.co.uk"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1504879106-2225-2-git-send-email-mark.cave-ayland@ilande.co.uk/mbox/",
    "series": [
        {
            "id": 2222,
            "url": "http://patchwork.ozlabs.org/api/series/2222/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2222",
            "date": "2017-09-08T13:58:24",
            "name": "sun4u: add Sun HME (Happy Meal Ethernet) on-board NIC",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/2222/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/811613/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/811613/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xpfBm3tzVz9s7G\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  9 Sep 2017 00:01:52 +1000 (AEST)",
            "from localhost ([::1]:45585 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dqJqw-0004WW-Lk\n\tfor incoming@patchwork.ozlabs.org; Fri, 08 Sep 2017 10:01:50 -0400",
            "from eggs.gnu.org ([2001:4830:134:3::10]:42504)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <mark.cave-ayland@ilande.co.uk>) id 1dqJnz-00026i-El\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 09:58:55 -0400",
            "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <mark.cave-ayland@ilande.co.uk>) id 1dqJnv-0005fq-8W\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 09:58:47 -0400",
            "from chuckie.co.uk ([82.165.15.123]:53047\n\thelo=s16892447.onlinehome-server.info)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <mark.cave-ayland@ilande.co.uk>)\n\tid 1dqJnu-0005dk-Qd\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 09:58:43 -0400",
            "from host109-147-184-220.range109-147.btcentralplus.com\n\t([109.147.184.220] helo=kentang.home)\n\tby s16892447.onlinehome-server.info with esmtpsa\n\t(TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.76)\n\t(envelope-from <mark.cave-ayland@ilande.co.uk>)\n\tid 1dqJns-0003B2-Vy; Fri, 08 Sep 2017 14:58:45 +0100"
        ],
        "From": "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>",
        "To": "qemu-devel@nongnu.org,\n\tatar4qemu@gmail.com",
        "Date": "Fri,  8 Sep 2017 14:58:25 +0100",
        "Message-Id": "<1504879106-2225-2-git-send-email-mark.cave-ayland@ilande.co.uk>",
        "X-Mailer": "git-send-email 1.7.10.4",
        "In-Reply-To": "<1504879106-2225-1-git-send-email-mark.cave-ayland@ilande.co.uk>",
        "References": "<1504879106-2225-1-git-send-email-mark.cave-ayland@ilande.co.uk>",
        "X-SA-Exim-Connect-IP": "109.147.184.220",
        "X-SA-Exim-Mail-From": "mark.cave-ayland@ilande.co.uk",
        "X-SA-Exim-Version": "4.2.1 (built Sun, 08 Jan 2012 02:45:44 +0000)",
        "X-SA-Exim-Scanned": "Yes (on s16892447.onlinehome-server.info)",
        "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 3.x [fuzzy]",
        "X-Received-From": "82.165.15.123",
        "Subject": "[Qemu-devel] [PATCH 1/2] net: add Sun HME (Happy Meal Ethernet)\n\ton-board NIC",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.21",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"
    },
    "content": "Enable it by default for the sparc64-softmmu configuration.\n\nSigned-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>\n---\n default-configs/sparc64-softmmu.mak |    1 +\n hw/net/Makefile.objs                |    1 +\n hw/net/sunhme.c                     |  978 +++++++++++++++++++++++++++++++++++\n hw/net/trace-events                 |   29 ++\n include/hw/net/mii.h                |    4 +\n include/hw/pci/pci_ids.h            |    1 +\n 6 files changed, 1014 insertions(+)\n create mode 100644 hw/net/sunhme.c",
    "diff": "diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak\nindex d07876a..3e177bb 100644\n--- a/default-configs/sparc64-softmmu.mak\n+++ b/default-configs/sparc64-softmmu.mak\n@@ -12,6 +12,7 @@ CONFIG_FDC=y\n CONFIG_IDE_ISA=y\n CONFIG_IDE_CMD646=y\n CONFIG_PCI_APB=y\n+CONFIG_SUNHME=y\n CONFIG_MC146818RTC=y\n CONFIG_ISA_TESTDEV=y\n CONFIG_EMPTY_SLOT=y\ndiff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs\nindex 5ddaffe..0fdc5a0 100644\n--- a/hw/net/Makefile.objs\n+++ b/hw/net/Makefile.objs\n@@ -26,6 +26,7 @@ common-obj-$(CONFIG_IMX_FEC) += imx_fec.o\n common-obj-$(CONFIG_CADENCE) += cadence_gem.o\n common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o\n common-obj-$(CONFIG_LANCE) += lance.o\n+common-obj-$(CONFIG_SUNHME) += sunhme.o\n common-obj-$(CONFIG_FTGMAC100) += ftgmac100.o\n \n obj-$(CONFIG_ETRAXFS) += etraxfs_eth.o\ndiff --git a/hw/net/sunhme.c b/hw/net/sunhme.c\nnew file mode 100644\nindex 0000000..60277ad\n--- /dev/null\n+++ b/hw/net/sunhme.c\n@@ -0,0 +1,978 @@\n+/*\n+ * QEMU Sun Happy Meal Ethernet emulation\n+ *\n+ * Copyright (c) 2017 Mark Cave-Ayland\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"hw/hw.h\"\n+#include \"hw/pci/pci.h\"\n+#include \"hw/net/mii.h\"\n+#include \"net/net.h\"\n+#include \"net/checksum.h\"\n+#include \"net/eth.h\"\n+#include \"sysemu/sysemu.h\"\n+#include \"trace.h\"\n+\n+#define HME_REG_SIZE                   0x8000\n+\n+#define HME_SEB_REG_SIZE               0x2000\n+\n+#define HME_SEBI_RESET                 0x0\n+#define HME_SEB_RESET_ETX              0x1\n+#define HME_SEB_RESET_ERX              0x2\n+\n+#define HME_SEBI_STAT                  0x100\n+#define HME_SEBI_STAT_LINUXBUG         0x108\n+#define HME_SEB_STAT_RXTOHOST          0x10000\n+#define HME_SEB_STAT_MIFIRQ            0x800000\n+#define HME_SEB_STAT_HOSTTOTX          0x1000000\n+#define HME_SEB_STAT_TXALL             0x2000000\n+\n+#define HME_SEBI_IMASK                 0x104\n+#define HME_SEBI_IMASK_LINUXBUG        0x10c\n+\n+#define HME_ETX_REG_SIZE               0x2000\n+\n+#define HME_ETXI_PENDING               0x0\n+\n+#define HME_ETXI_RING                  0x8\n+#define HME_ETXI_RING_ADDR             0xffffff00\n+#define HME_ETXI_RING_OFFSET           0xff\n+\n+#define HME_ETXI_RSIZE                 0x2c\n+\n+#define HME_ERX_REG_SIZE               0x2000\n+\n+#define HME_ERXI_CFG                   0x0\n+#define HME_ERX_CFG_RINGSIZE           0x600\n+#define HME_ERX_CFG_RINGSIZE_SHIFT     9\n+#define HME_ERX_CFG_BYTEOFFSET         0x38\n+#define HME_ERX_CFG_BYTEOFFSET_SHIFT   3\n+#define HME_ERX_CFG_CSUMSTART          0x7f0000\n+#define HME_ERX_CFG_CSUMSHIFT          16\n+\n+#define HME_ERXI_RING                  0x4\n+#define HME_ERXI_RING_ADDR             0xffffff00\n+#define HME_ERXI_RING_OFFSET           0xff\n+\n+#define HME_MAC_REG_SIZE               0x1000\n+\n+#define HME_MACI_TXCFG                 0x20c\n+#define HME_MAC_TXCFG_ENABLE           0x1\n+\n+#define HME_MACI_RXCFG                 0x30c\n+#define HME_MAC_RXCFG_ENABLE           0x1\n+#define HME_MAC_RXCFG_PMISC            0x40\n+#define HME_MAC_RXCFG_HENABLE          0x800\n+\n+#define HME_MACI_MACADDR2              0x318\n+#define HME_MACI_MACADDR1              0x31c\n+#define HME_MACI_MACADDR0              0x320\n+\n+#define HME_MACI_HASHTAB3              0x340\n+#define HME_MACI_HASHTAB2              0x344\n+#define HME_MACI_HASHTAB1              0x348\n+#define HME_MACI_HASHTAB0              0x34c\n+\n+#define HME_MIF_REG_SIZE               0x20\n+\n+#define HME_MIFI_FO                    0xc\n+#define HME_MIF_FO_ST                  0xc0000000\n+#define HME_MIF_FO_ST_SHIFT            30\n+#define HME_MIF_FO_OPC                 0x30000000\n+#define HME_MIF_FO_OPC_SHIFT           28\n+#define HME_MIF_FO_PHYAD               0x0f800000\n+#define HME_MIF_FO_PHYAD_SHIFT         23\n+#define HME_MIF_FO_REGAD               0x007c0000\n+#define HME_MIF_FO_REGAD_SHIFT         18\n+#define HME_MIF_FO_TAMSB               0x20000\n+#define HME_MIF_FO_TALSB               0x10000\n+#define HME_MIF_FO_DATA                0xffff\n+\n+#define HME_MIFI_CFG                   0x10\n+#define HME_MIF_CFG_MDI0               0x100\n+#define HME_MIF_CFG_MDI1               0x200\n+\n+#define HME_MIFI_IMASK                 0x14\n+\n+#define HME_MIFI_STAT                  0x18\n+\n+\n+/* Wired HME PHY addresses */\n+#define HME_PHYAD_INTERNAL     1\n+#define HME_PHYAD_EXTERNAL     0\n+\n+#define MII_COMMAND_START      0x1\n+#define MII_COMMAND_READ       0x2\n+#define MII_COMMAND_WRITE      0x1\n+\n+#define TYPE_SUNHME \"sunhme\"\n+#define SUNHME(obj) OBJECT_CHECK(SunHMEState, (obj), TYPE_SUNHME)\n+\n+/* Maximum size of buffer */\n+#define HME_FIFO_SIZE          0x800\n+\n+/* Size of TX/RX descriptor */\n+#define HME_DESC_SIZE          0x8\n+\n+#define HME_XD_OWN             0x80000000\n+#define HME_XD_OFL             0x40000000\n+#define HME_XD_SOP             0x40000000\n+#define HME_XD_EOP             0x20000000\n+#define HME_XD_RXLENMSK        0x3fff0000\n+#define HME_XD_RXLENSHIFT      16\n+#define HME_XD_RXCKSUM         0xffff\n+#define HME_XD_TXLENMSK        0x00001fff\n+#define HME_XD_TXCKSUM         0x10000000\n+#define HME_XD_TXCSSTUFF       0xff00000\n+#define HME_XD_TXCSSTUFFSHIFT  20\n+#define HME_XD_TXCSSTART       0xfc000\n+#define HME_XD_TXCSSTARTSHIFT  14\n+\n+#define HME_MII_REGS_SIZE      0x20\n+\n+typedef struct SunHMEState {\n+    /*< private >*/\n+    PCIDevice parent_obj;\n+\n+    NICState *nic;\n+    NICConf conf;\n+\n+    MemoryRegion hme;\n+    MemoryRegion sebreg;\n+    MemoryRegion etxreg;\n+    MemoryRegion erxreg;\n+    MemoryRegion macreg;\n+    MemoryRegion mifreg;\n+\n+    uint32_t sebregs[HME_SEB_REG_SIZE >> 2];\n+    uint32_t etxregs[HME_ETX_REG_SIZE >> 2];\n+    uint32_t erxregs[HME_ERX_REG_SIZE >> 2];\n+    uint32_t macregs[HME_MAC_REG_SIZE >> 2];\n+    uint32_t mifregs[HME_MIF_REG_SIZE >> 2];\n+\n+    uint16_t miiregs[HME_MII_REGS_SIZE];\n+} SunHMEState;\n+\n+static Property sunhme_properties[] = {\n+    DEFINE_NIC_PROPERTIES(SunHMEState, conf),\n+    DEFINE_PROP_END_OF_LIST(),\n+};\n+\n+static void sunhme_reset_tx(SunHMEState *s)\n+{\n+    /* Indicate TX reset complete */\n+    s->sebregs[HME_SEBI_RESET] &= ~HME_SEB_RESET_ETX;\n+}\n+\n+static void sunhme_reset_rx(SunHMEState *s)\n+{\n+    /* Indicate RX reset complete */\n+    s->sebregs[HME_SEBI_RESET] &= ~HME_SEB_RESET_ERX;\n+}\n+\n+static void sunhme_update_irq(SunHMEState *s)\n+{\n+    PCIDevice *d = PCI_DEVICE(s);\n+    int level;\n+\n+    /* MIF interrupt mask (16-bit) */\n+    uint32_t mifmask = ~(s->mifregs[HME_MIFI_IMASK >> 2]) & 0xffff;\n+    uint32_t mif = s->mifregs[HME_MIFI_STAT >> 2] & mifmask;\n+\n+    /* Main SEB interrupt mask (include MIF status from above) */\n+    uint32_t sebmask = ~(s->sebregs[HME_SEBI_IMASK >> 2]) &\n+                       ~HME_SEB_STAT_MIFIRQ;\n+    uint32_t seb = s->sebregs[HME_SEBI_STAT >> 2] & sebmask;\n+    if (mif) {\n+        seb |= HME_SEB_STAT_MIFIRQ;\n+    }\n+\n+    level = (seb ? 1 : 0);\n+    pci_set_irq(d, level);\n+}\n+\n+static void sunhme_seb_write(void *opaque, hwaddr addr,\n+                          uint64_t val, unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+\n+    trace_sunhme_seb_write(addr, val);\n+\n+    /* Handly buggy Linux drivers before 4.13 which have\n+       the wrong offsets for HME_SEBI_STAT and HME_SEBI_IMASK */\n+    switch (addr) {\n+    case HME_SEBI_STAT_LINUXBUG:\n+        addr = HME_SEBI_STAT;\n+        break;\n+    case HME_SEBI_IMASK_LINUXBUG:\n+        addr = HME_SEBI_IMASK;\n+        break;\n+    default:\n+        break;\n+    }\n+\n+    switch (addr) {\n+    case HME_SEBI_RESET:\n+        if (val & HME_SEB_RESET_ETX) {\n+            sunhme_reset_tx(s);\n+        }\n+        if (val & HME_SEB_RESET_ERX) {\n+            sunhme_reset_rx(s);\n+        }\n+        val = s->sebregs[HME_SEBI_RESET >> 2];\n+        break;\n+    }\n+\n+    s->sebregs[addr >> 2] = val;\n+}\n+\n+static uint64_t sunhme_seb_read(void *opaque, hwaddr addr,\n+                             unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint64_t val;\n+\n+    /* Handly buggy Linux drivers before 4.13 which have\n+       the wrong offsets for HME_SEBI_STAT and HME_SEBI_IMASK */\n+    switch (addr) {\n+    case HME_SEBI_STAT_LINUXBUG:\n+        addr = HME_SEBI_STAT;\n+        break;\n+    case HME_SEBI_IMASK_LINUXBUG:\n+        addr = HME_SEBI_IMASK;\n+        break;\n+    default:\n+        break;\n+    }\n+\n+    val = s->sebregs[addr >> 2];\n+\n+    switch (addr) {\n+    case HME_SEBI_STAT:\n+        /* Autoclear status (except MIF) */\n+        s->sebregs[HME_SEBI_STAT >> 2] &= HME_SEB_STAT_MIFIRQ;\n+        sunhme_update_irq(s);\n+        break;\n+    }\n+\n+    trace_sunhme_seb_read(addr, val);\n+\n+    return val;\n+}\n+\n+static const MemoryRegionOps sunhme_seb_ops = {\n+    .read = sunhme_seb_read,\n+    .write = sunhme_seb_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+    },\n+};\n+\n+static void sunhme_transmit(SunHMEState *s);\n+\n+static void sunhme_etx_write(void *opaque, hwaddr addr,\n+                          uint64_t val, unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+\n+    trace_sunhme_etx_write(addr, val);\n+\n+    switch (addr) {\n+    case HME_ETXI_PENDING:\n+        if (val) {\n+            sunhme_transmit(s);\n+        }\n+        break;\n+    }\n+\n+    s->etxregs[addr >> 2] = val;\n+}\n+\n+static uint64_t sunhme_etx_read(void *opaque, hwaddr addr,\n+                             unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint64_t val;\n+\n+    val = s->etxregs[addr >> 2];\n+\n+    trace_sunhme_etx_read(addr, val);\n+\n+    return val;\n+}\n+\n+static const MemoryRegionOps sunhme_etx_ops = {\n+    .read = sunhme_etx_read,\n+    .write = sunhme_etx_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+    },\n+};\n+\n+static void sunhme_erx_write(void *opaque, hwaddr addr,\n+                          uint64_t val, unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+\n+    trace_sunhme_erx_write(addr, val);\n+\n+    s->erxregs[addr >> 2] = val;\n+}\n+\n+static uint64_t sunhme_erx_read(void *opaque, hwaddr addr,\n+                             unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint64_t val;\n+\n+    val = s->erxregs[addr >> 2];\n+\n+    trace_sunhme_erx_read(addr, val);\n+\n+    return val;\n+}\n+\n+static const MemoryRegionOps sunhme_erx_ops = {\n+    .read = sunhme_erx_read,\n+    .write = sunhme_erx_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+    },\n+};\n+\n+static void sunhme_mac_write(void *opaque, hwaddr addr,\n+                          uint64_t val, unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+\n+    trace_sunhme_mac_write(addr, val);\n+\n+    s->macregs[addr >> 2] = val;\n+}\n+\n+static uint64_t sunhme_mac_read(void *opaque, hwaddr addr,\n+                             unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint64_t val;\n+\n+    val = s->macregs[addr >> 2];\n+\n+    trace_sunhme_mac_read(addr, val);\n+\n+    return val;\n+}\n+\n+static const MemoryRegionOps sunhme_mac_ops = {\n+    .read = sunhme_mac_read,\n+    .write = sunhme_mac_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+    },\n+};\n+\n+static void sunhme_mii_write(SunHMEState *s, uint8_t reg, uint16_t data)\n+{\n+    trace_sunhme_mii_write(reg, data);\n+\n+    switch (reg) {\n+    case MII_BMCR:\n+        if (data & MII_BMCR_RESET) {\n+            /* Autoclear reset bit, enable auto negotiation */\n+            data &= ~MII_BMCR_RESET;\n+            data |= MII_BMCR_AUTOEN;\n+        }\n+        if (data & MII_BMCR_ANRESTART) {\n+            /* Autoclear auto negotiation restart */\n+            data &= ~MII_BMCR_ANRESTART;\n+\n+            /* Indicate negotiation complete */\n+            s->miiregs[MII_BMSR] |= MII_BMSR_AN_COMP;\n+\n+            if (!qemu_get_queue(s->nic)->link_down) {\n+                s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;\n+                s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;\n+            }\n+        }\n+        break;\n+    }\n+\n+    s->miiregs[reg] = data;\n+}\n+\n+static uint16_t sunhme_mii_read(SunHMEState *s, uint8_t reg)\n+{\n+    uint16_t data = s->miiregs[reg];\n+\n+    trace_sunhme_mii_read(reg, data);\n+\n+    return data;\n+}\n+\n+static void sunhme_mif_write(void *opaque, hwaddr addr,\n+                          uint64_t val, unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint8_t cmd, reg;\n+    uint16_t data;\n+\n+    trace_sunhme_mif_write(addr, val);\n+\n+    switch (addr) {\n+    case HME_MIFI_CFG:\n+        /* Mask the read-only bits */\n+        val &= ~(HME_MIF_CFG_MDI0 | HME_MIF_CFG_MDI1);\n+        val |= s->mifregs[HME_MIFI_CFG >> 2] &\n+               (HME_MIF_CFG_MDI0 | HME_MIF_CFG_MDI1);\n+        break;\n+    case HME_MIFI_FO:\n+        /* Detect start of MII command */\n+        if ((val & HME_MIF_FO_ST) >> HME_MIF_FO_ST_SHIFT\n+                != MII_COMMAND_START) {\n+            val |= HME_MIF_FO_TALSB;\n+            break;\n+        }\n+\n+        /* Internal phy only */\n+        if ((val & HME_MIF_FO_PHYAD) >> HME_MIF_FO_PHYAD_SHIFT\n+                != HME_PHYAD_INTERNAL) {\n+            val |= HME_MIF_FO_TALSB;\n+            break;\n+        }\n+\n+        cmd = (val & HME_MIF_FO_OPC) >> HME_MIF_FO_OPC_SHIFT;\n+        reg = (val & HME_MIF_FO_REGAD) >> HME_MIF_FO_REGAD_SHIFT;\n+        data = (val & HME_MIF_FO_DATA);\n+\n+        switch (cmd) {\n+        case MII_COMMAND_WRITE:\n+            sunhme_mii_write(s, reg, data);\n+            break;\n+\n+        case MII_COMMAND_READ:\n+            val &= ~HME_MIF_FO_DATA;\n+            val |= sunhme_mii_read(s, reg);\n+            break;\n+        }\n+\n+        val |= HME_MIF_FO_TALSB;\n+        break;\n+    }\n+\n+    s->mifregs[addr >> 2] = val;\n+}\n+\n+static uint64_t sunhme_mif_read(void *opaque, hwaddr addr,\n+                             unsigned size)\n+{\n+    SunHMEState *s = SUNHME(opaque);\n+    uint64_t val;\n+\n+    val = s->mifregs[addr >> 2];\n+\n+    switch (addr) {\n+    case HME_MIFI_STAT:\n+        /* Autoclear MIF interrupt status */\n+        s->mifregs[HME_MIFI_STAT >> 2] = 0;\n+        sunhme_update_irq(s);\n+        break;\n+    }\n+\n+    trace_sunhme_mif_read(addr, val);\n+\n+    return val;\n+}\n+\n+static const MemoryRegionOps sunhme_mif_ops = {\n+    .read = sunhme_mif_read,\n+    .write = sunhme_mif_write,\n+    .endianness = DEVICE_LITTLE_ENDIAN,\n+    .valid = {\n+        .min_access_size = 4,\n+        .max_access_size = 4,\n+    },\n+};\n+\n+static void sunhme_transmit_frame(SunHMEState *s, uint8_t *buf, int size)\n+{\n+    qemu_send_packet(qemu_get_queue(s->nic), buf, size);\n+}\n+\n+static inline int sunhme_get_tx_ring_count(SunHMEState *s)\n+{\n+    return (s->etxregs[HME_ETXI_RSIZE >> 2] + 1) << 4;\n+}\n+\n+static inline int sunhme_get_tx_ring_nr(SunHMEState *s)\n+{\n+    return s->etxregs[HME_ETXI_RING >> 2] & HME_ETXI_RING_OFFSET;\n+}\n+\n+static inline void sunhme_set_tx_ring_nr(SunHMEState *s, int i)\n+{\n+    uint32_t ring = s->etxregs[HME_ETXI_RING >> 2] & ~HME_ETXI_RING_OFFSET;\n+    ring |= i & HME_ETXI_RING_OFFSET;\n+\n+    s->etxregs[HME_ETXI_RING >> 2] = ring;\n+}\n+\n+static void sunhme_transmit(SunHMEState *s)\n+{\n+    PCIDevice *d = PCI_DEVICE(s);\n+    dma_addr_t tb, addr;\n+    uint32_t intstatus, status, buffer, sum = 0;\n+    int cr, nr, len, xmit_pos, csum_offset = 0, csum_stuff_offset = 0;\n+    uint16_t csum = 0;\n+    uint8_t xmit_buffer[HME_FIFO_SIZE];\n+\n+    tb = s->etxregs[HME_ETXI_RING >> 2] & HME_ETXI_RING_ADDR;\n+    nr = sunhme_get_tx_ring_count(s);\n+    cr = sunhme_get_tx_ring_nr(s);\n+\n+    pci_dma_read(d, tb + cr * HME_DESC_SIZE, &status, 4);\n+    pci_dma_read(d, tb + cr * HME_DESC_SIZE + 4, &buffer, 4);\n+\n+    xmit_pos = 0;\n+    while (status & HME_XD_OWN) {\n+        trace_sunhme_tx_desc(buffer, status, cr, nr);\n+\n+        /* Copy data into transmit buffer */\n+        addr = buffer;\n+        len = status & HME_XD_TXLENMSK;\n+\n+        if (xmit_pos + len > HME_FIFO_SIZE) {\n+            len = HME_FIFO_SIZE - xmit_pos;\n+        }\n+\n+        pci_dma_read(d, addr, &xmit_buffer[xmit_pos], len);\n+        xmit_pos += len;\n+\n+        /* Detect start of packet for TX checksum */\n+        if (status & HME_XD_SOP) {\n+            sum = 0;\n+            csum_offset = (status & HME_XD_TXCSSTART) >> HME_XD_TXCSSTARTSHIFT;\n+            csum_stuff_offset = (status & HME_XD_TXCSSTUFF) >>\n+                                HME_XD_TXCSSTUFFSHIFT;\n+        }\n+\n+        if (status & HME_XD_TXCKSUM) {\n+            /* Only start calculation from csum_offset */\n+            if (xmit_pos - len <= csum_offset && xmit_pos > csum_offset) {\n+                sum += net_checksum_add(xmit_pos - csum_offset,\n+                                        xmit_buffer + csum_offset);\n+                trace_sunhme_tx_xsum_add(csum_offset, xmit_pos - csum_offset);\n+            } else {\n+                sum += net_checksum_add(len, xmit_buffer + xmit_pos - len);\n+                trace_sunhme_tx_xsum_add(xmit_pos - len, len);\n+            }\n+        }\n+\n+        /* Detect end of packet for TX checksum */\n+        if (status & HME_XD_EOP) {\n+            /* Stuff the checksum if required */\n+            if (status & HME_XD_TXCKSUM) {\n+                csum = net_checksum_finish(sum);\n+                stw_be_p(xmit_buffer + csum_stuff_offset, csum);\n+                trace_sunhme_tx_xsum_stuff(csum, csum_stuff_offset);\n+            }\n+\n+            if (s->macregs[HME_MACI_TXCFG >> 2] & HME_MAC_TXCFG_ENABLE) {\n+                sunhme_transmit_frame(s, xmit_buffer, xmit_pos);\n+                trace_sunhme_tx_done(xmit_pos);\n+            }\n+        }\n+\n+        /* Update status */\n+        status &= ~HME_XD_OWN;\n+        pci_dma_write(d, tb + cr * HME_DESC_SIZE, &status, 4);\n+\n+        /* Move onto next descriptor */\n+        cr++;\n+        if (cr >= nr) {\n+            cr = 0;\n+        }\n+        sunhme_set_tx_ring_nr(s, cr);\n+\n+        pci_dma_read(d, tb + cr * HME_DESC_SIZE, &status, 4);\n+        pci_dma_read(d, tb + cr * HME_DESC_SIZE + 4, &buffer, 4);\n+\n+        /* Indicate TX complete */\n+        intstatus = s->sebregs[HME_SEBI_STAT >> 2];\n+        intstatus |= HME_SEB_STAT_HOSTTOTX;\n+        s->sebregs[HME_SEBI_STAT >> 2] = intstatus;\n+\n+        /* Autoclear TX pending */\n+        s->etxregs[HME_ETXI_PENDING >> 2] = 0;\n+\n+        sunhme_update_irq(s);\n+    }\n+\n+    /* TX FIFO now clear */\n+    intstatus = s->sebregs[HME_SEBI_STAT >> 2];\n+    intstatus |= HME_SEB_STAT_TXALL;\n+    s->sebregs[HME_SEBI_STAT >> 2] = intstatus;\n+    sunhme_update_irq(s);\n+}\n+\n+static int sunhme_can_receive(NetClientState *nc)\n+{\n+    SunHMEState *s = qemu_get_nic_opaque(nc);\n+\n+    return s->macregs[HME_MAC_RXCFG_ENABLE >> 2] & HME_MAC_RXCFG_ENABLE;\n+}\n+\n+static void sunhme_link_status_changed(NetClientState *nc)\n+{\n+    SunHMEState *s = qemu_get_nic_opaque(nc);\n+\n+    if (nc->link_down) {\n+        s->miiregs[MII_ANLPAR] &= ~MII_ANLPAR_TXFD;\n+        s->miiregs[MII_BMSR] &= ~MII_BMSR_LINK_ST;\n+    } else {\n+        s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;\n+        s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;\n+    }\n+\n+    /* Exact bits unknown */\n+    s->mifregs[HME_MIFI_STAT >> 2] = 0xffff;\n+    sunhme_update_irq(s);\n+}\n+\n+static inline int sunhme_get_rx_ring_count(SunHMEState *s)\n+{\n+    uint32_t rings = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_RINGSIZE)\n+                      >> HME_ERX_CFG_RINGSIZE_SHIFT;\n+\n+    switch (rings) {\n+    case 0:\n+        return 32;\n+    case 1:\n+        return 64;\n+    case 2:\n+        return 128;\n+    case 3:\n+        return 256;\n+    }\n+\n+    return 0;\n+}\n+\n+static inline int sunhme_get_rx_ring_nr(SunHMEState *s)\n+{\n+    return s->erxregs[HME_ERXI_RING >> 2] & HME_ERXI_RING_OFFSET;\n+}\n+\n+static inline void sunhme_set_rx_ring_nr(SunHMEState *s, int i)\n+{\n+    uint32_t ring = s->erxregs[HME_ERXI_RING >> 2] & ~HME_ERXI_RING_OFFSET;\n+    ring |= i & HME_ERXI_RING_OFFSET;\n+\n+    s->erxregs[HME_ERXI_RING >> 2] = ring;\n+}\n+\n+#define POLYNOMIAL_LE 0xedb88320\n+static uint32_t sunhme_crc32_le(const uint8_t *p, int len)\n+{\n+    uint32_t crc;\n+    int carry, i, j;\n+    uint8_t b;\n+\n+    crc = 0xffffffff;\n+    for (i = 0; i < len; i++) {\n+        b = *p++;\n+        for (j = 0; j < 8; j++) {\n+            carry = (crc & 0x1) ^ (b & 0x01);\n+            crc >>= 1;\n+            b >>= 1;\n+            if (carry) {\n+                crc = crc ^ POLYNOMIAL_LE;\n+            }\n+        }\n+    }\n+\n+    return crc;\n+}\n+\n+#define MIN_BUF_SIZE 60\n+\n+static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,\n+                              size_t size)\n+{\n+    SunHMEState *s = qemu_get_nic_opaque(nc);\n+    PCIDevice *d = PCI_DEVICE(s);\n+    dma_addr_t rb, addr;\n+    uint32_t intstatus, status, buffer, buffersize, sum;\n+    uint16_t csum;\n+    uint8_t buf1[60];\n+    int nr, cr, len, rxoffset, csum_offset;\n+\n+    trace_sunhme_rx_incoming(size);\n+\n+    /* Do nothing if MAC RX disabled */\n+    if (!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE)) {\n+        return -1;\n+    }\n+\n+    trace_sunhme_rx_filter_destmac(buf[0], buf[1], buf[2],\n+                                   buf[3], buf[4], buf[5]);\n+\n+    /* Check destination MAC address */\n+    if (!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_PMISC)) {\n+        /* Try and match local MAC address */\n+        if (((s->macregs[HME_MACI_MACADDR0 >> 2] & 0xff00) >> 8) == buf[0] &&\n+             (s->macregs[HME_MACI_MACADDR0 >> 2] & 0xff) == buf[1] &&\n+            ((s->macregs[HME_MACI_MACADDR1 >> 2] & 0xff00) >> 8) == buf[2] &&\n+             (s->macregs[HME_MACI_MACADDR1 >> 2] & 0xff) == buf[3] &&\n+            ((s->macregs[HME_MACI_MACADDR2 >> 2] & 0xff00) >> 8) == buf[4] &&\n+             (s->macregs[HME_MACI_MACADDR2 >> 2] & 0xff) == buf[5]) {\n+            /* Matched local MAC address */\n+            trace_sunhme_rx_filter_local_match();\n+        } else if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff &&\n+                   buf[3] == 0xff && buf[4] == 0xff && buf[5] == 0xff) {\n+            /* Matched broadcast address */\n+            trace_sunhme_rx_filter_bcast_match();\n+        } else if (s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_HENABLE) {\n+            /* Didn't match local address, check hash filter */\n+            int mcast_idx = sunhme_crc32_le(buf, 6) >> 26;\n+            if (!(s->macregs[(HME_MACI_HASHTAB0 >> 2) - (mcast_idx >> 4)] &\n+                    (1 << (mcast_idx & 0xf)))) {\n+                /* Didn't match hash filter */\n+                trace_sunhme_rx_filter_hash_nomatch();\n+                trace_sunhme_rx_filter_reject();\n+                return 0;\n+            } else {\n+                trace_sunhme_rx_filter_hash_match();\n+            }\n+        } else {\n+            /* Not for us */\n+            trace_sunhme_rx_filter_reject();\n+            return 0;\n+        }\n+    } else {\n+        trace_sunhme_rx_filter_promisc_match();\n+    }\n+\n+    trace_sunhme_rx_filter_accept();\n+\n+    /* If too small buffer, then expand it */\n+    if (size < MIN_BUF_SIZE) {\n+        memcpy(buf1, buf, size);\n+        memset(buf1 + size, 0, MIN_BUF_SIZE - size);\n+        buf = buf1;\n+        size = MIN_BUF_SIZE;\n+    }\n+\n+    rb = s->erxregs[HME_ERXI_RING >> 2] & HME_ERXI_RING_ADDR;\n+    nr = sunhme_get_rx_ring_count(s);\n+    cr = sunhme_get_rx_ring_nr(s);\n+\n+    pci_dma_read(d, rb + cr * HME_DESC_SIZE, &status, 4);\n+    pci_dma_read(d, rb + cr * HME_DESC_SIZE + 4, &buffer, 4);\n+\n+    rxoffset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_BYTEOFFSET) >>\n+                HME_ERX_CFG_BYTEOFFSET_SHIFT;\n+\n+    addr = buffer + rxoffset;\n+    buffersize = (status & HME_XD_RXLENMSK) >> HME_XD_RXLENSHIFT;\n+\n+    /* Detect receive overflow */\n+    len = size;\n+    if (size > buffersize) {\n+        status |= HME_XD_OFL;\n+        len = buffersize;\n+    }\n+\n+    pci_dma_write(d, addr, buf, len);\n+\n+    trace_sunhme_rx_desc(buffer, rxoffset, status, len, cr, nr);\n+\n+    /* Calculate the receive checksum */\n+    csum_offset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_CSUMSTART) >>\n+                  HME_ERX_CFG_CSUMSHIFT << 1;\n+    sum = 0;\n+    sum += net_checksum_add(len - csum_offset, (uint8_t *)buf + csum_offset);\n+    csum = net_checksum_finish(sum);\n+\n+    trace_sunhme_rx_xsum_calc(csum);\n+\n+    /* Update status */\n+    status &= ~HME_XD_OWN;\n+    status &= ~HME_XD_RXLENMSK;\n+    status |= len << HME_XD_RXLENSHIFT;\n+    status &= ~HME_XD_RXCKSUM;\n+    status |= csum;\n+\n+    pci_dma_write(d, rb + cr * HME_DESC_SIZE, &status, 4);\n+\n+    cr++;\n+    if (cr >= nr) {\n+        cr = 0;\n+    }\n+\n+    sunhme_set_rx_ring_nr(s, cr);\n+\n+    /* Indicate RX complete */\n+    intstatus = s->sebregs[HME_SEBI_STAT >> 2];\n+    intstatus |= HME_SEB_STAT_RXTOHOST;\n+    s->sebregs[HME_SEBI_STAT >> 2] = intstatus;\n+\n+    sunhme_update_irq(s);\n+\n+    return len;\n+}\n+\n+static NetClientInfo net_sunhme_info = {\n+    .type = NET_CLIENT_DRIVER_NIC,\n+    .size = sizeof(NICState),\n+    .can_receive = sunhme_can_receive,\n+    .receive = sunhme_receive,\n+    .link_status_changed = sunhme_link_status_changed,\n+};\n+\n+static void sunhme_realize(PCIDevice *pci_dev, Error **errp)\n+{\n+    SunHMEState *s = SUNHME(pci_dev);\n+    DeviceState *d = DEVICE(pci_dev);\n+    uint8_t *pci_conf;\n+\n+    pci_conf = pci_dev->config;\n+    pci_conf[PCI_INTERRUPT_PIN] = 1;    /* interrupt pin A */\n+\n+    memory_region_init(&s->hme, OBJECT(pci_dev), \"sunhme\", HME_REG_SIZE);\n+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->hme);\n+\n+    memory_region_init_io(&s->sebreg, OBJECT(pci_dev), &sunhme_seb_ops, s,\n+                          \"sunhme.seb\", HME_SEB_REG_SIZE);\n+    memory_region_add_subregion(&s->hme, 0, &s->sebreg);\n+\n+    memory_region_init_io(&s->etxreg, OBJECT(pci_dev), &sunhme_etx_ops, s,\n+                          \"sunhme.etx\", HME_ETX_REG_SIZE);\n+    memory_region_add_subregion(&s->hme, 0x2000, &s->etxreg);\n+\n+    memory_region_init_io(&s->erxreg, OBJECT(pci_dev), &sunhme_erx_ops, s,\n+                          \"sunhme.erx\", HME_ERX_REG_SIZE);\n+    memory_region_add_subregion(&s->hme, 0x4000, &s->erxreg);\n+\n+    memory_region_init_io(&s->macreg, OBJECT(pci_dev), &sunhme_mac_ops, s,\n+                          \"sunhme.mac\", HME_MAC_REG_SIZE);\n+    memory_region_add_subregion(&s->hme, 0x6000, &s->macreg);\n+\n+    memory_region_init_io(&s->mifreg, OBJECT(pci_dev), &sunhme_mif_ops, s,\n+                          \"sunhme.mif\", HME_MIF_REG_SIZE);\n+    memory_region_add_subregion(&s->hme, 0x7000, &s->mifreg);\n+\n+    qemu_macaddr_default_if_unset(&s->conf.macaddr);\n+    s->nic = qemu_new_nic(&net_sunhme_info, &s->conf,\n+                          object_get_typename(OBJECT(d)), d->id, s);\n+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);\n+}\n+\n+static void sunhme_instance_init(Object *obj)\n+{\n+    SunHMEState *s = SUNHME(obj);\n+\n+    device_add_bootindex_property(obj, &s->conf.bootindex,\n+                                  \"bootindex\", \"/ethernet-phy@0\",\n+                                  DEVICE(obj), NULL);\n+}\n+\n+static void sunhme_reset(DeviceState *ds)\n+{\n+    SunHMEState *s = SUNHME(ds);\n+\n+    /* Configure internal transceiver */\n+    s->mifregs[HME_MIFI_CFG >> 2] |= HME_MIF_CFG_MDI0;\n+\n+    /* Advetise auto, 100Mbps FD */\n+    s->miiregs[MII_ANAR] = MII_ANAR_TXFD;\n+    s->miiregs[MII_BMSR] = MII_BMSR_AUTONEG | MII_BMSR_100TX_FD |\n+                           MII_BMSR_AN_COMP;\n+\n+    if (!qemu_get_queue(s->nic)->link_down) {\n+        s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;\n+        s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;\n+    }\n+\n+    /* Set manufacturer */\n+    s->miiregs[MII_PHYID1] = DP83840_PHYID1;\n+    s->miiregs[MII_PHYID2] = DP83840_PHYID2;\n+\n+    /* Configure default interrupt mask */\n+    s->mifregs[HME_MIFI_IMASK >> 2] = 0xffff;\n+    s->sebregs[HME_SEBI_IMASK >> 2] = 0xff7fffff;\n+}\n+\n+static const VMStateDescription vmstate_hme = {\n+    .name = \"sunhme\",\n+    .version_id = 0,\n+    .minimum_version_id = 0,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_PCI_DEVICE(parent_obj, SunHMEState),\n+        VMSTATE_MACADDR(conf.macaddr, SunHMEState),\n+        VMSTATE_UINT32_ARRAY(sebregs, SunHMEState, (HME_SEB_REG_SIZE >> 2)),\n+        VMSTATE_UINT32_ARRAY(etxregs, SunHMEState, (HME_ETX_REG_SIZE >> 2)),\n+        VMSTATE_UINT32_ARRAY(erxregs, SunHMEState, (HME_ERX_REG_SIZE >> 2)),\n+        VMSTATE_UINT32_ARRAY(macregs, SunHMEState, (HME_MAC_REG_SIZE >> 2)),\n+        VMSTATE_UINT32_ARRAY(mifregs, SunHMEState, (HME_MIF_REG_SIZE >> 2)),\n+        VMSTATE_UINT16_ARRAY(miiregs, SunHMEState, HME_MII_REGS_SIZE),\n+        VMSTATE_END_OF_LIST()\n+    }\n+};\n+\n+static void sunhme_class_init(ObjectClass *klass, void *data)\n+{\n+    DeviceClass *dc = DEVICE_CLASS(klass);\n+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);\n+\n+    k->realize = sunhme_realize;\n+    k->vendor_id = PCI_VENDOR_ID_SUN;\n+    k->device_id = PCI_DEVICE_ID_SUN_HME;\n+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;\n+    dc->vmsd = &vmstate_hme;\n+    dc->reset = sunhme_reset;\n+    dc->props = sunhme_properties;\n+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);\n+}\n+\n+static const TypeInfo sunhme_info = {\n+    .name          = TYPE_SUNHME,\n+    .parent        = TYPE_PCI_DEVICE,\n+    .class_init    = sunhme_class_init,\n+    .instance_size = sizeof(SunHMEState),\n+    .instance_init = sunhme_instance_init,\n+};\n+\n+static void sunhme_register_types(void)\n+{\n+    type_register_static(&sunhme_info);\n+}\n+\n+type_init(sunhme_register_types)\ndiff --git a/hw/net/trace-events b/hw/net/trace-events\nindex 27e5482..7328bb9 100644\n--- a/hw/net/trace-events\n+++ b/hw/net/trace-events\n@@ -278,3 +278,32 @@ spapr_vlan_h_send_logical_lan(uint64_t reg, uint64_t continue_token) \"H_SEND_LOG\n spapr_vlan_h_send_logical_lan_rxbufs(uint32_t rx_bufs) \"rxbufs = %\"PRIu32\n spapr_vlan_h_send_logical_lan_buf_desc(uint64_t buf) \"   buf desc: 0x%\"PRIx64\n spapr_vlan_h_send_logical_lan_total(int nbufs, unsigned total_len) \"%d buffers, total length 0x%x\"\n+\n+# hw/net/sunhme.c\n+sunhme_seb_write(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_seb_read(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_etx_write(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_etx_read(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_erx_write(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_erx_read(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_mac_write(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_mac_read(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_mii_write(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_mii_read(uint8_t addr, uint16_t value) \"addr 0x%x value 0x%x\"\n+sunhme_mif_write(uint8_t addr, uint16_t value) \"addr 0x%x value 0x%x\"\n+sunhme_mif_read(uint64_t addr, uint64_t value) \"addr 0x%\"PRIx64\" value 0x%\"PRIx64\n+sunhme_tx_desc(uint64_t buffer, uint32_t status, int cr, int nr) \"addr 0x%\"PRIx64\" status 0x%\"PRIx32 \" (ring %d/%d)\"\n+sunhme_tx_xsum_add(int offset, int len) \"adding xsum at offset %d, len %d\"\n+sunhme_tx_xsum_stuff(uint16_t xsum, int offset) \"stuffing xsum 0x%x at offset %d\"\n+sunhme_tx_done(int len) \"successfully transmitted frame with len %d\"\n+sunhme_rx_incoming(size_t len) \"received incoming frame with len %zu\"\n+sunhme_rx_filter_destmac(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) \"received frame for MAC: %02x:%02x:%02x:%02x:%02x:%02x\"\n+sunhme_rx_filter_local_match(void) \"incoming frame matches local MAC address\"\n+sunhme_rx_filter_bcast_match(void) \"incoming frame matches broadcast MAC address\"\n+sunhme_rx_filter_hash_nomatch(void) \"incoming MAC address not in hash table\"\n+sunhme_rx_filter_hash_match(void) \"incoming MAC address found in hash table\"\n+sunhme_rx_filter_promisc_match(void) \"incoming frame accepted due to promiscuous mode\"\n+sunhme_rx_filter_reject(void) \"rejecting incoming frame\"\n+sunhme_rx_filter_accept(void) \"accepting incoming frame\"\n+sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) \"addr 0x%\"PRIx32\"(+0x%x) status 0x%\"PRIx32 \" len %d (ring %d/%d)\"\n+sunhme_rx_xsum_calc(uint16_t xsum) \"calculated incoming xsum as 0x%x\"\ndiff --git a/include/hw/net/mii.h b/include/hw/net/mii.h\nindex 6ce48a6..4ae4dcc 100644\n--- a/include/hw/net/mii.h\n+++ b/include/hw/net/mii.h\n@@ -104,6 +104,10 @@\n #define RTL8211E_PHYID1     0x001c\n #define RTL8211E_PHYID2     0xc915\n \n+/* National Semiconductor DP83840 */\n+#define DP83840_PHYID1      0x2000\n+#define DP83840_PHYID2      0x5c01\n+\n /* National Semiconductor DP83848 */\n #define DP83848_PHYID1      0x2000\n #define DP83848_PHYID2      0x5c90\ndiff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h\nindex 3752ddc..7308e75 100644\n--- a/include/hw/pci/pci_ids.h\n+++ b/include/hw/pci/pci_ids.h\n@@ -186,6 +186,7 @@\n \n #define PCI_VENDOR_ID_SUN                0x108e\n #define PCI_DEVICE_ID_SUN_EBUS           0x1000\n+#define PCI_DEVICE_ID_SUN_HME            0x1001\n #define PCI_DEVICE_ID_SUN_SIMBA          0x5000\n #define PCI_DEVICE_ID_SUN_SABRE          0xa000\n \n",
    "prefixes": [
        "1/2"
    ]
}