Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/811613/?format=api
{ "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" ] }