From nobody Sat May 4 17:13:00 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510202486994784.608816197388; Wed, 8 Nov 2017 20:41:26 -0800 (PST) Received: from localhost ([::1]:35080 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCeeW-0003v2-5E for importer@patchew.org; Wed, 08 Nov 2017 23:41:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56638) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCecp-0002xT-E3 for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eCecn-0004hN-8i for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:35 -0500 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:45349) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eCecn-0004h9-0K for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:33 -0500 Received: by mail-pf0-x243.google.com with SMTP id d28so3441696pfe.2 for ; Wed, 08 Nov 2017 20:39:32 -0800 (PST) Received: from eswierk-sc.localdomain (67-207-112-138.static.wiline.com. [67.207.112.138]) by smtp.gmail.com with ESMTPSA id e71sm10730488pfk.55.2017.11.08.20.39.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Nov 2017 20:39:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skyportsystems.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=O98foaFGS2k3ekaIq74lTWxrw8k8eCRG6FZs9BQAkxM=; b=kUIzknKIOAP0RBKQ2iDGv3pXA35gFbN3J/zVDBYLbDweGfoxHH/p5Y+BIqxHL6nED3 GsPJ37XekV/07GQrxGCEo7EYKpmmyQrMej6Qfsj7HaoDGFvKPWQNh+bX7u3egHOa9FuZ J/IpJKofaDTpZQkfK0AC3bx/6ZpIE596WNTPM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=O98foaFGS2k3ekaIq74lTWxrw8k8eCRG6FZs9BQAkxM=; b=OqQ8pf3JRcm9T+Xd0k6cgl8FIPSogq/hoKgxfua5oemTnES8d8twDGfBdQwMRkDyIN WGMEtSmK6gbRmzK/RPAvYEezjidesJFkmt3u/xWHcIFEFf2lQmxKxhfAmNDqN7SB0Yr4 GbB25pySrS2/oa4SH8x/mhENQqsEeE3NztQ3Y8CvKTLu3tQRli/c28I/kdTrC/0bhhyu fyOWGL2nNDXGy7Rwp9vubPMFnmpcFfYhZESP9dAnuFnTuoZgPOHQs5BHW4JaREq9Tjr2 0+Mtb5zI56XTKdteaXalLKYFJZE0+hZMJM2rH0x2WiJTCpLB5JPJxHiC2HJjKm+pMSfb /3Mw== X-Gm-Message-State: AJaThX6uO8VBEVKsD6SvZ3VJaWLV7xWOfK9mjG7bkqddoBZGtTKXZA4a yNidCsqAKL04CJfFNW8uizwlvw== X-Google-Smtp-Source: ABhQp+SVWvDaRU/a1++SuQQ2o8+lTX0yKhxjtU4J67W2Ug6uZinuPUJsCirOWIoH0QFMd9r1K4jimg== X-Received: by 10.84.143.195 with SMTP id 61mr2577256plz.277.1510202371830; Wed, 08 Nov 2017 20:39:31 -0800 (PST) To: Jason Wang , Dmitry Fleytman , Leonid Bloch , Peter Maydell , Stefan Hajnoczi Date: Wed, 8 Nov 2017 20:39:16 -0800 Message-Id: <1510202357-124052-2-git-send-email-eswierk@skyportsystems.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1510202357-124052-1-git-send-email-eswierk@skyportsystems.com> References: <1509072544-89012-1-git-send-email-eswierk@skyportsystems.com> <1510202357-124052-1-git-send-email-eswierk@skyportsystems.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::243 Subject: [Qemu-devel] [PATCH v2 1/2] e1000e: Infrastructure for e1000-ng X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Ed Swierk via Qemu-devel Reply-To: Ed Swierk Cc: Ed Swierk , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Generalize e1000e to support e1000 and other devices with a similar register spec: - plain PCI instead of PCIe, skipping setup of MSI-X, AER, etc. - model-specific PHY ID2, register values and access permissions - model-specific EEPROM template and read/write methods This is just infrastructure, no functional changes. Signed-off-by: Ed Swierk --- hw/net/e1000e.c | 166 ++++++++++++++++++++++++++++++++++++++---------= ---- hw/net/e1000e_core.c | 131 +++++++++++++++++++++++----------------- hw/net/e1000e_core.h | 13 ++-- 3 files changed, 209 insertions(+), 101 deletions(-) diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index f1af279..7685ab0 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -49,8 +49,13 @@ #include "trace.h" #include "qapi/error.h" =20 -#define TYPE_E1000E "e1000e" -#define E1000E(obj) OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E) +#define TYPE_E1000E_BASE "e1000e-base" +#define E1000E(obj) \ + OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E_BASE) +#define E1000E_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(E1000EBaseClass, (klass), TYPE_E1000E_BASE) +#define E1000E_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(E1000EBaseClass, (obj), TYPE_E1000E_BASE) =20 typedef struct E1000EState { PCIDevice parent_obj; @@ -76,6 +81,28 @@ typedef struct E1000EState { =20 } E1000EState; =20 +typedef struct E1000EInfo { + const char *name; + const char *desc; + + uint16_t device_id; + uint8_t revision; + uint16_t subsystem_vendor_id; + uint16_t subsystem_id; + int is_express; + const char *romfile; + + const uint16_t *eeprom_templ; + uint32_t eeprom_size; + + uint16_t phy_id2; +} E1000EInfo; + +typedef struct E1000EBaseClass { + PCIDeviceClass parent_class; + const E1000EInfo *info; +} E1000EBaseClass; + #define E1000E_MMIO_IDX 0 #define E1000E_FLASH_IDX 1 #define E1000E_IO_IDX 2 @@ -416,7 +443,9 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Erro= r **errp) static const uint16_t e1000e_pcie_offset =3D 0x0E0; static const uint16_t e1000e_aer_offset =3D 0x100; static const uint16_t e1000e_dsn_offset =3D 0x140; + PCIDeviceClass *pc =3D PCI_DEVICE_GET_CLASS(pci_dev); E1000EState *s =3D E1000E(pci_dev); + E1000EBaseClass *edc =3D E1000E_DEVICE_GET_CLASS(s); uint8_t *macaddr; int ret; =20 @@ -427,6 +456,13 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Err= or **errp) pci_dev->config[PCI_CACHE_LINE_SIZE] =3D 0x10; pci_dev->config[PCI_INTERRUPT_PIN] =3D 1; =20 + if (s->subsys_ven =3D=3D (uint16_t)-1) { + s->subsys_ven =3D pci_get_word(pci_dev->config + PCI_SUBSYSTEM_VEN= DOR_ID); + } + if (s->subsys =3D=3D (uint16_t)-1) { + s->subsys =3D pci_get_word(pci_dev->config + PCI_SUBSYSTEM_ID); + } + pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, s->subsys_ven); pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, s->subsys); =20 @@ -453,19 +489,23 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Er= ror **errp) pci_register_bar(pci_dev, E1000E_IO_IDX, PCI_BASE_ADDRESS_SPACE_IO, &s->io); =20 - memory_region_init(&s->msix, OBJECT(s), "e1000e-msix", - E1000E_MSIX_SIZE); - pci_register_bar(pci_dev, E1000E_MSIX_IDX, - PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix); + if (pc->is_express) { + memory_region_init(&s->msix, OBJECT(s), "e1000e-msix", + E1000E_MSIX_SIZE); + pci_register_bar(pci_dev, E1000E_MSIX_IDX, + PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix); + } =20 /* Create networking backend */ qemu_macaddr_default_if_unset(&s->conf.macaddr); macaddr =3D s->conf.macaddr.a; =20 - e1000e_init_msix(s); + if (pc->is_express) { + e1000e_init_msix(s); =20 - if (pcie_endpoint_cap_v1_init(pci_dev, e1000e_pcie_offset) < 0) { - hw_error("Failed to initialize PCIe capability"); + if (pcie_endpoint_cap_v1_init(pci_dev, e1000e_pcie_offset) < 0) { + hw_error("Failed to initialize PCIe capability"); + } } =20 ret =3D msi_init(PCI_DEVICE(s), 0xD0, 1, true, false, NULL); @@ -473,18 +513,20 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Er= ror **errp) trace_e1000e_msi_init_fail(ret); } =20 - if (e1000e_add_pm_capability(pci_dev, e1000e_pmrb_offset, - PCI_PM_CAP_DSI) < 0) { - hw_error("Failed to initialize PM capability"); - } + if (pc->is_express) { + if (e1000e_add_pm_capability(pci_dev, e1000e_pmrb_offset, + PCI_PM_CAP_DSI) < 0) { + hw_error("Failed to initialize PM capability"); + } =20 - if (pcie_aer_init(pci_dev, PCI_ERR_VER, e1000e_aer_offset, - PCI_ERR_SIZEOF, NULL) < 0) { - hw_error("Failed to initialize AER capability"); - } + if (pcie_aer_init(pci_dev, PCI_ERR_VER, e1000e_aer_offset, + PCI_ERR_SIZEOF, NULL) < 0) { + hw_error("Failed to initialize AER capability"); + } =20 - pcie_dev_ser_num_init(pci_dev, e1000e_dsn_offset, - e1000e_gen_dsn(macaddr)); + pcie_dev_ser_num_init(pci_dev, e1000e_dsn_offset, + e1000e_gen_dsn(macaddr)); + } =20 e1000e_init_net_peer(s, pci_dev, macaddr); =20 @@ -492,25 +534,31 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Er= ror **errp) e1000e_core_realize(s); =20 e1000e_core_pci_realize(&s->core, - e1000e_eeprom_template, - sizeof(e1000e_eeprom_template), - macaddr); + edc->info->eeprom_templ, + edc->info->eeprom_size, + macaddr, + edc->info->phy_id2); } =20 static void e1000e_pci_uninit(PCIDevice *pci_dev) { + PCIDeviceClass *pc =3D PCI_DEVICE_GET_CLASS(pci_dev); E1000EState *s =3D E1000E(pci_dev); =20 trace_e1000e_cb_pci_uninit(); =20 e1000e_core_pci_uninit(&s->core); =20 - pcie_aer_exit(pci_dev); - pcie_cap_exit(pci_dev); + if (pc->is_express) { + pcie_aer_exit(pci_dev); + pcie_cap_exit(pci_dev); + } =20 qemu_del_nic(s->nic); =20 - e1000e_cleanup_msix(s); + if (pc->is_express) { + e1000e_cleanup_msix(s); + } msi_uninit(pci_dev); } =20 @@ -544,7 +592,7 @@ static int e1000e_post_load(void *opaque, int version_i= d) (s->subsys_ven !=3D s->subsys_ven_used)) { fprintf(stderr, "ERROR: Cannot migrate while device properties " - "(subsys/subsys_ven) differ"); + "(subsys/subsys_ven) differ\n"); return -1; } =20 @@ -655,10 +703,9 @@ static Property e1000e_properties[] =3D { DEFINE_NIC_PROPERTIES(E1000EState, conf), DEFINE_PROP_SIGNED("disable_vnet_hdr", E1000EState, disable_vnet, fals= e, e1000e_prop_disable_vnet, bool), - DEFINE_PROP_SIGNED("subsys_ven", E1000EState, subsys_ven, - PCI_VENDOR_ID_INTEL, + DEFINE_PROP_SIGNED("subsys_ven", E1000EState, subsys_ven, -1, e1000e_prop_subsys_ven, uint16_t), - DEFINE_PROP_SIGNED("subsys", E1000EState, subsys, 0, + DEFINE_PROP_SIGNED("subsys", E1000EState, subsys, -1, e1000e_prop_subsys, uint16_t), DEFINE_PROP_END_OF_LIST(), }; @@ -667,21 +714,27 @@ static void e1000e_class_init(ObjectClass *class, voi= d *data) { DeviceClass *dc =3D DEVICE_CLASS(class); PCIDeviceClass *c =3D PCI_DEVICE_CLASS(class); + E1000EBaseClass *edc =3D E1000E_DEVICE_CLASS(class); + const E1000EInfo *info =3D data; =20 c->realize =3D e1000e_pci_realize; c->exit =3D e1000e_pci_uninit; c->vendor_id =3D PCI_VENDOR_ID_INTEL; - c->device_id =3D E1000_DEV_ID_82574L; - c->revision =3D 0; - c->romfile =3D "efi-e1000e.rom"; + c->device_id =3D info->device_id; + c->revision =3D info->revision; c->class_id =3D PCI_CLASS_NETWORK_ETHERNET; - c->is_express =3D 1; + c->subsystem_vendor_id =3D info->subsystem_vendor_id; + c->subsystem_id =3D info->subsystem_id; + c->is_express =3D info->is_express; + c->romfile =3D info->romfile; =20 - dc->desc =3D "Intel 82574L GbE Controller"; + dc->desc =3D info->desc; dc->reset =3D e1000e_qdev_reset; dc->vmsd =3D &e1000e_vmstate; dc->props =3D e1000e_properties; =20 + edc->info =3D info; + e1000e_prop_disable_vnet =3D qdev_prop_uint8; e1000e_prop_disable_vnet.description =3D "Do not use virtio headers, " "perform SW offloads emulation " @@ -704,21 +757,52 @@ static void e1000e_instance_init(Object *obj) DEVICE(obj), NULL); } =20 -static const TypeInfo e1000e_info =3D { - .name =3D TYPE_E1000E, +static const TypeInfo e1000e_base_info =3D { + .name =3D TYPE_E1000E_BASE, .parent =3D TYPE_PCI_DEVICE, .instance_size =3D sizeof(E1000EState), - .class_init =3D e1000e_class_init, .instance_init =3D e1000e_instance_init, - .interfaces =3D (InterfaceInfo[]) { - { INTERFACE_PCIE_DEVICE }, - { } + .class_size =3D sizeof(E1000EBaseClass), + .abstract =3D true, +}; + +static const E1000EInfo e1000e_devices[] =3D { + { + .name =3D "e1000e", + .desc =3D "Intel 82574L GbE Controller", + .device_id =3D E1000_DEV_ID_82574L, + .revision =3D 0, + .subsystem_vendor_id =3D PCI_VENDOR_ID_INTEL, + .subsystem_id =3D 0, + .is_express =3D 1, + .romfile =3D "efi-e1000e.rom", + .eeprom_templ =3D e1000e_eeprom_template, + .eeprom_size =3D sizeof(e1000e_eeprom_template), + .phy_id2 =3D E1000_PHY_ID2_82574x, }, }; =20 static void e1000e_register_types(void) { - type_register_static(&e1000e_info); + int i; + + type_register_static(&e1000e_base_info); + for (i =3D 0; i < ARRAY_SIZE(e1000e_devices); i++) { + const E1000EInfo *info =3D &e1000e_devices[i]; + TypeInfo type_info =3D {}; + + type_info.name =3D info->name; + type_info.parent =3D TYPE_E1000E_BASE; + type_info.class_data =3D (void *)info; + type_info.class_init =3D e1000e_class_init; + type_info.interfaces =3D (InterfaceInfo[]) { + { info->is_express ? INTERFACE_PCIE_DEVICE + : INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { } + }; + + type_register(&type_info); + } } =20 type_init(e1000e_register_types) diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 43a8d89..959c697 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -2213,7 +2213,7 @@ e1000e_get_reg_index_with_offset(const uint16_t *mac_= reg_access, hwaddr addr) return index + (mac_reg_access[index] & 0xfffe); } =20 -static const char e1000e_phy_regcap[E1000E_PHY_PAGES][0x20] =3D { +static const char e1000e_phy_regcap[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE= ] =3D { [0] =3D { [PHY_CTRL] =3D PHY_ANYPAGE | PHY_RW, [PHY_STATUS] =3D PHY_ANYPAGE | PHY_R, @@ -2266,14 +2266,14 @@ e1000e_phy_reg_check_cap(E1000ECore *core, uint32_t= addr, char cap, uint8_t *page) { *page =3D - (e1000e_phy_regcap[0][addr] & PHY_ANYPAGE) ? 0 - : core->phy[0][PHY_PAG= E]; + ((*core->phy_regcap)[0][addr] & PHY_ANYPAGE) ? 0 + : core->phy[0][PHY_PAGE]; =20 if (*page >=3D E1000E_PHY_PAGES) { return false; } =20 - return e1000e_phy_regcap[*page][addr] & cap; + return (*core->phy_regcap)[*page][addr] & cap; } =20 static void @@ -2729,6 +2729,12 @@ e1000e_mac_setmacaddr(E1000ECore *core, int index, u= int32_t val) trace_e1000e_mac_set_sw(MAC_ARG(macaddr)); } =20 +static uint32_t +e1000e_get_eecd(E1000ECore *core, int index) +{ + return e1000e_mac_readreg(core, index); +} + static void e1000e_set_eecd(E1000ECore *core, int index, uint32_t val) { @@ -3028,6 +3034,7 @@ static uint32_t (*e1000e_macreg_readops[])(E1000ECore= *, int) =3D { [TARC1] =3D e1000e_get_tarc, [SWSM] =3D e1000e_mac_swsm_read, [IMS] =3D e1000e_mac_ims_read, + [EECD] =3D e1000e_get_eecd, =20 [CRCERRS ... MPC] =3D e1000e_mac_readreg, [IP6AT ... IP6AT + 3] =3D e1000e_mac_readreg, @@ -3305,56 +3312,6 @@ e1000e_vm_state_change(void *opaque, int running, Ru= nState state) } } =20 -void -e1000e_core_pci_realize(E1000ECore *core, - const uint16_t *eeprom_templ, - uint32_t eeprom_size, - const uint8_t *macaddr) -{ - int i; - - core->autoneg_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, - e1000e_autoneg_timer, core); - e1000e_intrmgr_pci_realize(core); - - core->vmstate =3D - qemu_add_vm_change_state_handler(e1000e_vm_state_change, core); - - for (i =3D 0; i < E1000E_NUM_QUEUES; i++) { - net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner, - E1000E_MAX_TX_FRAGS, core->has_vnet); - } - - net_rx_pkt_init(&core->rx_pkt, core->has_vnet); - - e1000x_core_prepare_eeprom(core->eeprom, - eeprom_templ, - eeprom_size, - PCI_DEVICE_GET_CLASS(core->owner)->device_i= d, - macaddr); - e1000e_update_rx_offloads(core); -} - -void -e1000e_core_pci_uninit(E1000ECore *core) -{ - int i; - - timer_del(core->autoneg_timer); - timer_free(core->autoneg_timer); - - e1000e_intrmgr_pci_unint(core); - - qemu_del_vm_change_state_handler(core->vmstate); - - for (i =3D 0; i < E1000E_NUM_QUEUES; i++) { - net_tx_pkt_reset(core->tx[i].tx_pkt); - net_tx_pkt_uninit(core->tx[i].tx_pkt); - } - - net_rx_pkt_uninit(core->rx_pkt); -} - static const uint16_t e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE] =3D { [0] =3D { @@ -3373,7 +3330,7 @@ e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE= _SIZE] =3D { MII_SR_100X_FD_CAPS, =20 [PHY_ID1] =3D 0x141, - [PHY_ID2] =3D E1000_PHY_ID2_82574x, + /* [PHY_ID2] set by e1000e_core_reset() */ [PHY_AUTONEG_ADV] =3D 0xde1, [PHY_LP_ABILITY] =3D 0x7e0, [PHY_AUTONEG_EXP] =3D BIT(2), @@ -3438,6 +3395,67 @@ static const uint32_t e1000e_mac_reg_init[] =3D { }; =20 void +e1000e_core_pci_realize(E1000ECore *core, + const uint16_t *eeprom_templ, + uint32_t eeprom_size, + const uint8_t *macaddr, + uint16_t phy_id2) +{ + int i; + + core->phy_id2 =3D phy_id2; + switch (phy_id2) { + case E1000_PHY_ID2_82574x: + core->phy_regcap =3D &e1000e_phy_regcap; + core->phy_reg_init =3D &e1000e_phy_reg_init; + break; + default: + g_assert_not_reached(); + } + + core->autoneg_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, + e1000e_autoneg_timer, core); + e1000e_intrmgr_pci_realize(core); + + core->vmstate =3D + qemu_add_vm_change_state_handler(e1000e_vm_state_change, core); + + for (i =3D 0; i < E1000E_NUM_QUEUES; i++) { + net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner, + E1000E_MAX_TX_FRAGS, core->has_vnet); + } + + net_rx_pkt_init(&core->rx_pkt, core->has_vnet); + + e1000x_core_prepare_eeprom(core->eeprom, + eeprom_templ, + eeprom_size, + PCI_DEVICE_GET_CLASS(core->owner)->device_i= d, + macaddr); + e1000e_update_rx_offloads(core); +} + +void +e1000e_core_pci_uninit(E1000ECore *core) +{ + int i; + + timer_del(core->autoneg_timer); + timer_free(core->autoneg_timer); + + e1000e_intrmgr_pci_unint(core); + + qemu_del_vm_change_state_handler(core->vmstate); + + for (i =3D 0; i < E1000E_NUM_QUEUES; i++) { + net_tx_pkt_reset(core->tx[i].tx_pkt); + net_tx_pkt_uninit(core->tx[i].tx_pkt); + } + + net_rx_pkt_uninit(core->rx_pkt); +} + +void e1000e_core_reset(E1000ECore *core) { int i; @@ -3447,7 +3465,8 @@ e1000e_core_reset(E1000ECore *core) e1000e_intrmgr_reset(core); =20 memset(core->phy, 0, sizeof core->phy); - memmove(core->phy, e1000e_phy_reg_init, sizeof e1000e_phy_reg_init); + memmove(core->phy, *core->phy_reg_init, sizeof *core->phy_reg_init); + core->phy[0][PHY_ID2] =3D core->phy_id2; memset(core->mac, 0, sizeof core->mac); memmove(core->mac, e1000e_mac_reg_init, sizeof e1000e_mac_reg_init); =20 diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h index 1ff6978..9ac6f32 100644 --- a/hw/net/e1000e_core.h +++ b/hw/net/e1000e_core.h @@ -56,6 +56,10 @@ typedef struct E1000IntrDelayTimer_st { } E1000IntrDelayTimer; =20 struct E1000Core { + uint16_t phy_id2; + const char (*phy_regcap)[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; + const uint16_t (*phy_reg_init)[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; + uint32_t mac[E1000E_MAC_SIZE]; uint16_t phy[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; uint16_t eeprom[E1000E_EEPROM_SIZE]; @@ -116,10 +120,11 @@ uint64_t e1000e_core_read(E1000ECore *core, hwaddr addr, unsigned size); =20 void -e1000e_core_pci_realize(E1000ECore *regs, - const uint16_t *eeprom_templ, - uint32_t eeprom_size, - const uint8_t *macaddr); +e1000e_core_pci_realize(E1000ECore *regs, + const uint16_t *eeprom_templ, + uint32_t eeprom_size, + const uint8_t *macaddr, + uint16_t phy_id2); =20 void e1000e_core_reset(E1000ECore *core); --=20 1.9.1 From nobody Sat May 4 17:13:00 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510202488901428.6895575476552; Wed, 8 Nov 2017 20:41:28 -0800 (PST) Received: from localhost ([::1]:35079 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCeeV-0003uq-Ad for importer@patchew.org; Wed, 08 Nov 2017 23:41:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56648) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCecq-0002xW-EI for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eCeco-0004hp-H2 for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:36 -0500 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:51830) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eCeco-0004hY-7I for qemu-devel@nongnu.org; Wed, 08 Nov 2017 23:39:34 -0500 Received: by mail-pf0-x244.google.com with SMTP id j28so1106243pfk.8 for ; Wed, 08 Nov 2017 20:39:34 -0800 (PST) Received: from eswierk-sc.localdomain (67-207-112-138.static.wiline.com. [67.207.112.138]) by smtp.gmail.com with ESMTPSA id e71sm10730488pfk.55.2017.11.08.20.39.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Nov 2017 20:39:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skyportsystems.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=i9Qhr/1VgAyjtW/8rnSORdBAwvVAE+Oj/ELg/e22sjw=; b=tBAGNw5pejndEt663fYn+qeAdEdidwgkaj4S80qIGktvA1P2bfZKTAqtYc0JGg0INp jVxA3xxIH/LDb0w0RfVKKqlteQULMSxAze+09PudKISWtj7ShwYZOxuEMwOXx2H5GpFk wyoGA8dfmxmZrA44z1Xn5HsYVRFb+uTRtuaO8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=i9Qhr/1VgAyjtW/8rnSORdBAwvVAE+Oj/ELg/e22sjw=; b=UJD2Wvi1hjStMFX1Pz2zdCrJcP359FYvsBda0K4Up0xxPEpLHN57tvlw58QnrxA4Jf 5HVqczBWra7g9UDnG+Zl0tSBvcpJGzcNz3vzCH7Ifg/YAx/ABRcT7j2nqn4LqAkYpgme u8j9gTSFMbme9vQuNgldKl/fOXYD616hrN6gl30Q73ox07vcnNbmm0LEH2Y8lGg5WLb+ X5ZxkH2Ap6eSmMagJq4J+2uSaiTPdWzZ5QwiWbHPW+HeAoyF62jV8wG7blqhb1Z6zzdn WmXKEcABjJYIAs809XBITlUtOtISmVObOkqkdVzfwpw1qr1kzDB0weiLb8iC8rG+5QeM 5moQ== X-Gm-Message-State: AJaThX7R60e7k9RYWMIq9JZtjpS/lghOTAY1pC6JkVIBi62nu0V3n4gp 8GL/AxcT3haZjL9NvlFOTlcp4w== X-Google-Smtp-Source: ABhQp+R6JOGTlpFBN1TPbkgDUtE22b1VQi+b7CRU/rXGO/8TbZAPGERhqoCCOHXHGd3RyU7WLz2Jaw== X-Received: by 10.84.138.1 with SMTP id 1mr2557761plo.156.1510202373114; Wed, 08 Nov 2017 20:39:33 -0800 (PST) To: Jason Wang , Dmitry Fleytman , Leonid Bloch , Peter Maydell , Stefan Hajnoczi Date: Wed, 8 Nov 2017 20:39:17 -0800 Message-Id: <1510202357-124052-3-git-send-email-eswierk@skyportsystems.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1510202357-124052-1-git-send-email-eswierk@skyportsystems.com> References: <1509072544-89012-1-git-send-email-eswierk@skyportsystems.com> <1510202357-124052-1-git-send-email-eswierk@skyportsystems.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::244 Subject: [Qemu-devel] [PATCH v2 2/2] e1000e: Add e1000-ng devices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Ed Swierk via Qemu-devel Reply-To: Ed Swierk Cc: Ed Swierk , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement e1000-compatible devices using the reworked e1000e code: - e1000-ng: Intel 82540EM - e1000-82544gc-ng: Intel 82544GC - e1000-82545em-ng: Intel 82545EM From a guest's perspective, these should be drop-in replacements for the existing e1000 devices. This version has undergone minimal testing, but should work well enough to start experimenting with e1000-ng devices with a variety of guest OSes. Signed-off-by: Ed Swierk --- hw/net/e1000e.c | 111 +++++++++++++++++++++++++++++++++++++++++++++-- hw/net/e1000e_core.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++-= ---- hw/net/e1000e_core.h | 12 ++++++ 3 files changed, 229 insertions(+), 14 deletions(-) diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 7685ab0..9ae5105 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -281,6 +281,17 @@ static const uint16_t e1000e_eeprom_template[64] =3D { 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0120, 0xffff, 0x0000, }; =20 +static const uint16_t e1000_eeprom_template[64] =3D { + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x00= 00, + 0x3000, 0x1000, 0x6403, 0 /*DevId*/, 0x8086, 0 /*DevId*/, 0x8086, 0x30= 40, + 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x27= 00, + 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x07= 06, + 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xff= ff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff= ff, + 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xff= ff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00= 00, +}; + static void e1000e_core_realize(E1000EState *s) { s->core.owner =3D &s->parent_obj; @@ -644,8 +655,8 @@ static const VMStateDescription e1000e_vmstate_intr_tim= er =3D { =20 static const VMStateDescription e1000e_vmstate =3D { .name =3D "e1000e", - .version_id =3D 1, - .minimum_version_id =3D 1, + .version_id =3D 2, + .minimum_version_id =3D 2, .pre_save =3D e1000e_pre_save, .post_load =3D e1000e_post_load, .fields =3D (VMStateField[]) { @@ -691,6 +702,61 @@ static const VMStateDescription e1000e_vmstate =3D { =20 VMSTATE_STRUCT_ARRAY(core.tx, E1000EState, E1000E_NUM_QUEUES, 0, e1000e_vmstate_tx, struct e1000e_tx), + + VMSTATE_UINT32(core.eecd_state.val_in, E1000EState), + VMSTATE_UINT16(core.eecd_state.bitnum_in, E1000EState), + VMSTATE_UINT16(core.eecd_state.bitnum_out, E1000EState), + VMSTATE_UINT16(core.eecd_state.reading, E1000EState), + VMSTATE_UINT32(core.eecd_state.old_eecd, E1000EState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription e1000_vmstate =3D { + .name =3D "e1000-ng", + .version_id =3D 1, + .minimum_version_id =3D 1, + .pre_save =3D e1000e_pre_save, + .post_load =3D e1000e_post_load, + .fields =3D (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, E1000EState), + + VMSTATE_UINT32(ioaddr, E1000EState), + VMSTATE_UINT32(core.rxbuf_min_shift, E1000EState), + VMSTATE_UINT8(core.rx_desc_len, E1000EState), + VMSTATE_UINT32_ARRAY(core.rxbuf_sizes, E1000EState, + E1000_PSRCTL_BUFFS_PER_DESC), + VMSTATE_UINT32(core.rx_desc_buf_size, E1000EState), + VMSTATE_UINT16_ARRAY(core.eeprom, E1000EState, E1000E_EEPROM_SIZE), + VMSTATE_UINT16_2DARRAY(core.phy, E1000EState, + E1000E_PHY_PAGES, E1000E_PHY_PAGE_SIZE), + VMSTATE_UINT32_ARRAY(core.mac, E1000EState, E1000E_MAC_SIZE), + VMSTATE_UINT8_ARRAY(core.permanent_mac, E1000EState, ETH_ALEN), + + VMSTATE_UINT32(core.delayed_causes, E1000EState), + + VMSTATE_UINT16(subsys, E1000EState), + VMSTATE_UINT16(subsys_ven, E1000EState), + + VMSTATE_E1000E_INTR_DELAY_TIMER(core.rdtr, E1000EState), + VMSTATE_E1000E_INTR_DELAY_TIMER(core.radv, E1000EState), + VMSTATE_E1000E_INTR_DELAY_TIMER(core.raid, E1000EState), + VMSTATE_E1000E_INTR_DELAY_TIMER(core.tadv, E1000EState), + VMSTATE_E1000E_INTR_DELAY_TIMER(core.tidv, E1000EState), + + VMSTATE_E1000E_INTR_DELAY_TIMER(core.itr, E1000EState), + VMSTATE_BOOL(core.itr_intr_pending, E1000EState), + + VMSTATE_UINT16(core.vet, E1000EState), + + VMSTATE_STRUCT_ARRAY(core.tx, E1000EState, E1000E_NUM_QUEUES, 0, + e1000e_vmstate_tx, struct e1000e_tx), + + VMSTATE_UINT32(core.eecd_state.val_in, E1000EState), + VMSTATE_UINT16(core.eecd_state.bitnum_in, E1000EState), + VMSTATE_UINT16(core.eecd_state.bitnum_out, E1000EState), + VMSTATE_UINT16(core.eecd_state.reading, E1000EState), + VMSTATE_UINT32(core.eecd_state.old_eecd, E1000EState), VMSTATE_END_OF_LIST() } }; @@ -730,7 +796,7 @@ static void e1000e_class_init(ObjectClass *class, void = *data) =20 dc->desc =3D info->desc; dc->reset =3D e1000e_qdev_reset; - dc->vmsd =3D &e1000e_vmstate; + dc->vmsd =3D info->is_express ? &e1000e_vmstate : &e1000_vmstate; dc->props =3D e1000e_properties; =20 edc->info =3D info; @@ -780,6 +846,45 @@ static const E1000EInfo e1000e_devices[] =3D { .eeprom_size =3D sizeof(e1000e_eeprom_template), .phy_id2 =3D E1000_PHY_ID2_82574x, }, + { + .name =3D "e1000-ng", + .desc =3D "Intel 82540EM Gigabit Ethernet Controlle= r", + .device_id =3D E1000_DEV_ID_82540EM, + .revision =3D 3, + .subsystem_vendor_id =3D PCI_SUBVENDOR_ID_REDHAT_QUMRANET, + .subsystem_id =3D PCI_SUBDEVICE_ID_QEMU, + .is_express =3D 0, + .romfile =3D "efi-e1000.rom", + .eeprom_templ =3D e1000_eeprom_template, + .eeprom_size =3D sizeof(e1000_eeprom_template), + .phy_id2 =3D E1000_PHY_ID2_8254xx_DEFAULT, + }, + { + .name =3D "e1000-82544gc-ng", + .desc =3D "Intel 82544GC Gigabit Ethernet Controlle= r", + .device_id =3D E1000_DEV_ID_82544GC_COPPER, + .revision =3D 3, + .subsystem_vendor_id =3D PCI_SUBVENDOR_ID_REDHAT_QUMRANET, + .subsystem_id =3D PCI_SUBDEVICE_ID_QEMU, + .is_express =3D 0, + .romfile =3D "efi-e1000.rom", + .eeprom_templ =3D e1000_eeprom_template, + .eeprom_size =3D sizeof(e1000_eeprom_template), + .phy_id2 =3D E1000_PHY_ID2_82544x, + }, + { + .name =3D "e1000-82545em-ng", + .desc =3D "Intel 82545EM Gigabit Ethernet Controlle= r", + .device_id =3D E1000_DEV_ID_82545EM_COPPER, + .revision =3D 3, + .subsystem_vendor_id =3D PCI_SUBVENDOR_ID_REDHAT_QUMRANET, + .subsystem_id =3D PCI_SUBDEVICE_ID_QEMU, + .is_express =3D 0, + .romfile =3D "efi-e1000.rom", + .eeprom_templ =3D e1000_eeprom_template, + .eeprom_size =3D sizeof(e1000_eeprom_template), + .phy_id2 =3D E1000_PHY_ID2_8254xx_DEFAULT, + }, }; =20 static void e1000e_register_types(void) diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 959c697..02a60a1 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -2261,6 +2261,24 @@ static const char e1000e_phy_regcap[E1000E_PHY_PAGES= ][E1000E_PHY_PAGE_SIZE] =3D { } }; =20 +static const char e1000_phy_regcap[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]= =3D { + [0] =3D { + [PHY_CTRL] =3D PHY_RW, + [PHY_STATUS] =3D PHY_R, + [PHY_ID1] =3D PHY_R, + [PHY_ID2] =3D PHY_R, + [PHY_AUTONEG_ADV] =3D PHY_RW, + [PHY_LP_ABILITY] =3D PHY_R, + [PHY_AUTONEG_EXP] =3D PHY_R, + [PHY_1000T_CTRL] =3D PHY_RW, + [PHY_1000T_STATUS] =3D PHY_R, + [M88E1000_PHY_SPEC_CTRL] =3D PHY_RW, + [M88E1000_PHY_SPEC_STATUS] =3D PHY_R, + [M88E1000_EXT_PHY_SPEC_CTRL] =3D PHY_RW, + [M88E1000_RX_ERR_CNTR] =3D PHY_R, + } +}; + static bool e1000e_phy_reg_check_cap(E1000ECore *core, uint32_t addr, char cap, uint8_t *page) @@ -2616,6 +2634,10 @@ e1000e_mac_icr_read(E1000ECore *core, int index) e1000e_clear_ims_bits(core, core->mac[IAM]); } =20 + if (core->clear_icr_on_read) { + core->mac[ICR] =3D 0; + } + trace_e1000e_irq_icr_read_exit(core->mac[ICR]); e1000e_update_interrupt_state(core); return ret; @@ -2732,50 +2754,83 @@ e1000e_mac_setmacaddr(E1000ECore *core, int index, = uint32_t val) static uint32_t e1000e_get_eecd(E1000ECore *core, int index) { - return e1000e_mac_readreg(core, index); + uint32_t ret =3D E1000_EECD_PRES | E1000_EECD_GNT | core->eecd_state.o= ld_eecd; + + if (!core->eecd_state.reading || + ((core->eeprom[(core->eecd_state.bitnum_out >> 4) & 0x3f] >> + ((core->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1) { + ret |=3D E1000_EECD_DO; + } + return ret; } =20 static void e1000e_set_eecd(E1000ECore *core, int index, uint32_t val) { - static const uint32_t ro_bits =3D E1000_EECD_PRES | - E1000_EECD_AUTO_RD | - E1000_EECD_SIZE_EX_MASK; + uint32_t oldval =3D core->eecd_state.old_eecd; =20 - core->mac[EECD] =3D (core->mac[EECD] & ro_bits) | (val & ~ro_bits); + core->eecd_state.old_eecd =3D val & (E1000_EECD_SK | E1000_EECD_CS | + E1000_EECD_DI | E1000_EECD_FWE_MASK= | + E1000_EECD_REQ); + if (!(E1000_EECD_CS & val)) { /* CS inactive; nothing to do */ + return; + } + if (E1000_EECD_CS & (val ^ oldval)) { /* CS rise edge; reset state */ + core->eecd_state.val_in =3D 0; + core->eecd_state.bitnum_in =3D 0; + core->eecd_state.bitnum_out =3D 0; + core->eecd_state.reading =3D 0; + } + if (!(E1000_EECD_SK & (val ^ oldval))) { /* no clock edge */ + return; + } + if (!(E1000_EECD_SK & val)) { /* falling edge */ + core->eecd_state.bitnum_out++; + return; + } + core->eecd_state.val_in <<=3D 1; + if (val & E1000_EECD_DI) { + core->eecd_state.val_in |=3D 1; + } + if (++core->eecd_state.bitnum_in =3D=3D 9 && !core->eecd_state.reading= ) { + core->eecd_state.bitnum_out =3D ((core->eecd_state.val_in & 0x3f) + << 4) - 1; + core->eecd_state.reading =3D (((core->eecd_state.val_in >> 6) & 7)= =3D=3D + EEPROM_READ_OPCODE_MICROWIRE); + } } =20 static void e1000e_set_eerd(E1000ECore *core, int index, uint32_t val) { - uint32_t addr =3D (val >> E1000_EERW_ADDR_SHIFT) & E1000_EERW_ADDR_MAS= K; + uint32_t addr =3D (val >> core->eerw_addr_shift) & core->eerw_addr_mas= k; uint32_t flags =3D 0; uint32_t data =3D 0; =20 if ((addr < E1000E_EEPROM_SIZE) && (val & E1000_EERW_START)) { data =3D core->eeprom[addr]; - flags =3D E1000_EERW_DONE; + flags =3D core->eerw_done; } =20 core->mac[EERD] =3D flags | - (addr << E1000_EERW_ADDR_SHIFT) | + (addr << core->eerw_addr_shift) | (data << E1000_EERW_DATA_SHIFT); } =20 static void e1000e_set_eewr(E1000ECore *core, int index, uint32_t val) { - uint32_t addr =3D (val >> E1000_EERW_ADDR_SHIFT) & E1000_EERW_ADDR_MAS= K; + uint32_t addr =3D (val >> core->eerw_addr_shift) & core->eerw_addr_mas= k; uint32_t data =3D (val >> E1000_EERW_DATA_SHIFT) & E1000_EERW_DATA_MAS= K; uint32_t flags =3D 0; =20 if ((addr < E1000E_EEPROM_SIZE) && (val & E1000_EERW_START)) { core->eeprom[addr] =3D data; - flags =3D E1000_EERW_DONE; + flags =3D core->eerw_done; } =20 core->mac[EERD] =3D flags | - (addr << E1000_EERW_ADDR_SHIFT) | + (addr << core->eerw_addr_shift) | (data << E1000_EERW_DATA_SHIFT); } =20 @@ -3352,6 +3407,36 @@ e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAG= E_SIZE] =3D { } }; =20 +static const uint16_t +e1000_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE] =3D { + [0] =3D { + [PHY_CTRL] =3D MII_CR_SPEED_SELECT_MSB | + MII_CR_FULL_DUPLEX | + MII_CR_AUTO_NEG_EN, + + [PHY_STATUS] =3D MII_SR_EXTENDED_CAPS | + MII_SR_LINK_STATUS | + MII_SR_AUTONEG_CAPS | + MII_SR_PREAMBLE_SUPPRESS | + MII_SR_EXTENDED_STATUS | + MII_SR_10T_HD_CAPS | + MII_SR_10T_FD_CAPS | + MII_SR_100X_HD_CAPS | + MII_SR_100X_FD_CAPS, + + [PHY_ID1] =3D 0x141, + /* [PHY_ID2] set by e1000e_core_reset() */ + [PHY_AUTONEG_ADV] =3D 0xde1, + [PHY_LP_ABILITY] =3D 0x1e0, + [PHY_1000T_CTRL] =3D 0x0e00, + [PHY_1000T_STATUS] =3D 0x3c00, + + [M88E1000_PHY_SPEC_CTRL] =3D 0x360, + [M88E1000_PHY_SPEC_STATUS] =3D 0xac00, + [M88E1000_EXT_PHY_SPEC_CTRL] =3D 0x0d60, + } +}; + static const uint32_t e1000e_mac_reg_init[] =3D { [PBA] =3D 0x00140014, [LEDCTL] =3D BIT(1) | BIT(8) | BIT(9) | BIT(15) | BIT(17) | BI= T(18), @@ -3408,6 +3493,19 @@ e1000e_core_pci_realize(E1000ECore *core, case E1000_PHY_ID2_82574x: core->phy_regcap =3D &e1000e_phy_regcap; core->phy_reg_init =3D &e1000e_phy_reg_init; + core->clear_icr_on_read =3D false; + core->eerw_done =3D BIT(1); + core->eerw_addr_shift =3D 2; + core->eerw_addr_mask =3D ((1L << 14) - 1); + break; + case E1000_PHY_ID2_8254xx_DEFAULT: + case E1000_PHY_ID2_82544x: + core->phy_regcap =3D &e1000_phy_regcap; + core->phy_reg_init =3D &e1000_phy_reg_init; + core->clear_icr_on_read =3D true; + core->eerw_done =3D BIT(4); + core->eerw_addr_shift =3D 8; + core->eerw_addr_mask =3D ((1L << 8) - 1); break; default: g_assert_not_reached(); diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h index 9ac6f32..0b318a4 100644 --- a/hw/net/e1000e_core.h +++ b/hw/net/e1000e_core.h @@ -59,6 +59,10 @@ struct E1000Core { uint16_t phy_id2; const char (*phy_regcap)[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; const uint16_t (*phy_reg_init)[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; + bool clear_icr_on_read; + int eerw_done; + int eerw_addr_shift; + int eerw_addr_mask; =20 uint32_t mac[E1000E_MAC_SIZE]; uint16_t phy[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; @@ -108,6 +112,14 @@ struct E1000Core { =20 uint8_t permanent_mac[ETH_ALEN]; =20 + struct { + uint32_t val_in; /* shifted in from guest driver */ + uint16_t bitnum_in; + uint16_t bitnum_out; + uint16_t reading; + uint32_t old_eecd; + } eecd_state; + NICState *owner_nic; PCIDevice *owner; void (*owner_start_recv)(PCIDevice *d); --=20 1.9.1