From nobody Fri Dec 19 17:17:29 2025 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) 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=temperror (zoho.com: Error in retrieving data from DNS) 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 1509072707396132.17035140676785; Thu, 26 Oct 2017 19:51:47 -0700 (PDT) Received: from localhost ([::1]:55524 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e7ukF-0004cT-JN for importer@patchew.org; Thu, 26 Oct 2017 22:51:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46827) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e7uib-0003dk-Dp for qemu-devel@nongnu.org; Thu, 26 Oct 2017 22:49:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e7uiY-0002no-9O for qemu-devel@nongnu.org; Thu, 26 Oct 2017 22:49:57 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:44087) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1e7uiY-0002n7-18 for qemu-devel@nongnu.org; Thu, 26 Oct 2017 22:49:54 -0400 Received: by mail-pf0-x242.google.com with SMTP id x7so3921848pfa.1 for ; Thu, 26 Oct 2017 19:49:53 -0700 (PDT) Received: from localhost.localdomain ([104.153.224.169]) by smtp.gmail.com with ESMTPSA id u7sm11030522pfh.142.2017.10.26.19.49.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Oct 2017 19:49:52 -0700 (PDT) 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=0tUBOYXNuvdq49uDGepeSThnNknZIDHc/X1Ons6zfe4=; b=TxketOb5hxvSjflAaI9tZhEAZBarizfiAdxhGY9uxHwIWqh8iN22KFhaXI3inv3U8H gpHA8Rg/BBVF+JGh8XUxAUzI9StV7sLx8L7IUVsYP205un5ak5SlW8t8PHmWPKxGdXX4 PtO1x/Uf7hGDe62+xMkpbpF6KGtayzH6WsSGE= 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=0tUBOYXNuvdq49uDGepeSThnNknZIDHc/X1Ons6zfe4=; b=exYSK5tCs5AnhhDdTnvgkTuaxkzsk9kyAnAVj8JpiFQTf/icVcITroY4ObJ9WsJI3c fBM7uxDya4HMDxLPB+8adCSu7tI3msbhvm1/zTINZQYzNxB89I/LisMRxKLbqsA48Vxu KCDd+hQ6aTMEOkRjw+4ghEoy2gyieeXYrFnHXfOQqIJPI9qwgG9PBjIjNvWqqc/a+1jE DuZz2Owfr7SSxHbUhmq0mXqivLt2zuKrafNpaxXdNbi/k5UTE/CO5icx0zIgqO79A8Pm g/czRt9+yQH2URPIXhYINeBZnsxvzrwkcZHXNqmNGG0i1rRIV/osYIu0wCYwIRr7efOU EN1w== X-Gm-Message-State: AMCzsaX0B5WGDMmcnivLqmjpM5ARHa4q1rDOQBpGdBPGVoeIij1lwRNs mGkKTxQj1VYXl5f/HSdIonAomQ== X-Google-Smtp-Source: ABhQp+THjLU6zhA+8cTlCI472x8JdY1c+Lss1vwMGXxs2dDT6G/ZjMOVIr3xsTcMSaJEb5ZUT3BG1A== X-Received: by 10.98.223.15 with SMTP id u15mr7335190pfg.115.1509072592906; Thu, 26 Oct 2017 19:49:52 -0700 (PDT) To: Ed Swierk , qemu-devel@nongnu.org Date: Thu, 26 Oct 2017 19:49:04 -0700 Message-Id: <1509072544-89012-3-git-send-email-eswierk@skyportsystems.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1509072544-89012-1-git-send-email-eswierk@skyportsystems.com> References: <1509072544-89012-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::242 Subject: [Qemu-devel] [PATCH 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: Dmitry Fleytman , Leonid Bloch , Jason Wang , Stefan Hajnoczi , Peter Maydell 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_6 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. Among other deficiencies, this version does not handle migration. But it should work well enough to start testing e1000-ng devices with a variety of guest OSes. Signed-off-by: Ed Swierk --- hw/net/e1000e.c | 50 +++++++++++++++++++++ hw/net/e1000e_core.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++-= ---- hw/net/e1000e_core.h | 12 ++++++ 3 files changed, 171 insertions(+), 11 deletions(-) diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 100979c..5f75a41 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; @@ -776,6 +787,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..f667631 100644 --- a/hw/net/e1000e_core.h +++ b/hw/net/e1000e_core.h @@ -59,6 +59,7 @@ 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; =20 uint32_t mac[E1000E_MAC_SIZE]; uint16_t phy[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]; @@ -108,6 +109,17 @@ struct E1000Core { =20 uint8_t permanent_mac[ETH_ALEN]; =20 + int eerw_done; + int eerw_addr_shift; + int eerw_addr_mask; + 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