qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v3] e1000: add the ability to select among several s


From: Romain Dolbeau
Subject: [Qemu-devel] [PATCH v3] e1000: add the ability to select among several specific types of e1000[e]; 82566DM emulation ; some pointers to documentations and details.
Date: Wed, 5 Mar 2014 15:14:06 +0100

Try to implement proper QOM

Signed-off-by: Romain Dolbeau <address@hidden>
---
 hw/net/e1000.c      |  394 +++++++++++++++++++++++++++++++++++++++++++++++----
 hw/net/e1000_regs.h |  149 ++++++++++++++++---
 2 files changed, 492 insertions(+), 51 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 8387443..9737ecf 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1,8 +1,10 @@
 /*
  * QEMU e1000 emulation
  *
- * Software developer's manual:
- * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
+ * Software developer's manual (PCI, PCI-X):
+ * <http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf>
+ * Software developer's manual (PCIe):
+ * 
<http://www.intel.com/content/dam/www/public/us/en/documents/manuals/pcie-gbe-controllers-open-source-manual.pdf>
  *
  * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
  * Copyright (c) 2008 Qumranet
@@ -10,6 +12,8 @@
  * Copyright (c) 2007 Dan Aloni
  * Copyright (c) 2004 Antony T Curtis
  *
+ * Additional modifications (c) 2014 Romain Dolbeau
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -58,6 +62,7 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
 #define IOPORT_SIZE       0x40
 #define PNPMMIO_SIZE      0x20000
+#define FLASH_RSIZE       0x80
 #define MIN_BUF_SIZE      60 /* Min. octets in an ethernet frame sans FCS */
 
 /* this is the size past which hardware will drop packets when setting LPE=0 */
@@ -69,10 +74,12 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
 /*
  * HW models:
- *  E1000_DEV_ID_82540EM works with Windows and Linux
- *  E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
- *     appears to perform better than 82540EM, but breaks with Linux 2.6.18
+ *  E1000_DEV_ID_82540EM works with Windows and Linux, and is the default
  *  E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
+ *  E1000_DEV_ID_82545EM_COPPER appears to work with OSX 10.9[.1]; not well 
tested
+ *  E1000_DEV_ID_ICH9_IGP_AMT appears to work with Linux kernel 3.12; not well 
tested
+ *  It seems those 3 are mostly identical anyway, so picking one
+ *  over the others is a matter of guest support.
  *  Others never tested
  */
 enum { E1000_DEVID = E1000_DEV_ID_82540EM };
@@ -81,10 +88,24 @@ enum { E1000_DEVID = E1000_DEV_ID_82540EM };
  * May need to specify additional MAC-to-PHY entries --
  * Intel's Windows driver refuses to initialize unless they match
  */
-enum {
-    PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ?                0xcc2 :
-                   E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ?        0xc30 :
-                   /* default to E1000_DEV_ID_82540EM */       0xc20
+/* PHY_ID1:
+ * Most 8254x uses 0x141, but 82541xx and 82547GI/EI uses 0x2a8,
+ * and so do the 631xESB/632xESB, 82571EB/82572EI.
+ * The 82573E/82573V/82573L and 82563EB/82564EB also uses 0x141.
+ * <http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf> page 
250
+ * 
<http://www.intel.com/content/dam/www/public/us/en/documents/manuals/pcie-gbe-controllers-open-source-manual.pdf>
 page 305
+ */
+const uint16_t PHY_ID1_INIT[][2] = {
+  { E1000_DEV_ID_80003ES2LAN_COPPER_DPT, 0x2a8 },
+  { E1000_DEV_ID_ICH9_IGP_AMT, 0x2a8 },
+  { -1, 0x141 } /* default for 82540EM and many others */
+};
+const uint16_t PHY_ID2_INIT[][2] = {
+  { E1000_DEV_ID_82573L, 0xcc2 },
+  { E1000_DEV_ID_82544GC_COPPER, 0xc30 },
+  { E1000_DEV_ID_ICH9_IGP_AMT, 0x390 },
+  { -1, 0xc20 } /* default for 82540EM and many others; this one
+                   is a lot more device-specific than phy_id1 */
 };
 
 typedef struct E1000State_st {
@@ -95,12 +116,15 @@ typedef struct E1000State_st {
     NICState *nic;
     NICConf conf;
     MemoryRegion mmio;
+    MemoryRegion flash;
     MemoryRegion io;
 
     uint32_t mac_reg[0x8000];
     uint16_t phy_reg[0x20];
     uint16_t eeprom_data[64];
+    uint16_t flash_reg[FLASH_RSIZE];
 
+    uint32_t rxbuf_edesc;
     uint32_t rxbuf_size;
     uint32_t rxbuf_min_shift;
     struct e1000_tx {
@@ -151,7 +175,7 @@ typedef struct E1000State_st {
     uint32_t compat_flags;
 } E1000State;
 
-#define TYPE_E1000 "e1000"
+#define TYPE_E1000 "e1000_abstract"
 
 #define E1000(obj) \
     OBJECT_CHECK(E1000State, (obj), TYPE_E1000)
@@ -170,6 +194,7 @@ enum {
     defreg(RA),                defreg(MTA),    defreg(CRCERRS),defreg(VFTA),
     defreg(VET),        defreg(RDTR),   defreg(RADV),   defreg(TADV),
     defreg(ITR),
+    defreg(EXTCNF_CTRL), defreg(FWSM), defreg(KABGTXD), defreg(FACTPS),
 };
 
 static void
@@ -229,13 +254,19 @@ static const char phy_regcap[0x20] = {
     [PHY_CTRL] = PHY_RW,       [PHY_1000T_CTRL] = PHY_RW,
     [PHY_LP_ABILITY] = PHY_R,  [PHY_1000T_STATUS] = PHY_R,
     [PHY_AUTONEG_ADV] = PHY_RW,        [M88E1000_RX_ERR_CNTR] = PHY_R,
-    [PHY_ID2] = PHY_R,         [M88E1000_PHY_SPEC_STATUS] = PHY_R
+    [PHY_ID2] = PHY_R,          [M88E1000_PHY_SPEC_STATUS] = PHY_R,
+    [ICH_IGP_PHY_REGADD_ALT_MDIO] = PHY_RW /* ICH IGP ? */,
+    [PHY_AUTONEG_EXP] = PHY_RW, /* ICH IGP ? */
+    [PHY_EXT_STATUS] = PHY_RW, /* ICH IGP ? */
+    [M88E1000_INT_ENABLE] = PHY_RW, /* ICH IGP ? */
+    [M88E1000_INT_STATUS] = PHY_RW, /* ICH IGP ? */
 };
 
 static const uint16_t phy_reg_init[] = {
     [PHY_CTRL] = 0x1140,
     [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
-    [PHY_ID1] = 0x141,                         [PHY_ID2] = PHY_ID2_INIT,
+     /* both phy_id will be replaced */
+    [PHY_ID1] = 0x141,                          [PHY_ID2] = 0xc20,
     [PHY_1000T_CTRL] = 0x0e00,                 [M88E1000_PHY_SPEC_CTRL] = 
0x360,
     [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60,     [PHY_AUTONEG_ADV] = 0xde1,
     [PHY_LP_ABILITY] = 0x1e0,                  [PHY_1000T_STATUS] = 0x3c00,
@@ -269,10 +300,11 @@ static void
 set_interrupt_cause(E1000State *s, int index, uint32_t val)
 {
     PCIDevice *d = PCI_DEVICE(s);
+    PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(d);
     uint32_t pending_ints;
     uint32_t mit_delay;
 
-    if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
+    if (val && (pdc->device_id >= E1000_DEV_ID_82547EI_MOBILE)) {
         /* Only for 8257x */
         val |= E1000_ICR_INT_ASSERTED;
     }
@@ -375,8 +407,11 @@ rxbufsize(uint32_t v)
 static void e1000_reset(void *opaque)
 {
     E1000State *d = opaque;
+    PCIDevice *dev = PCI_DEVICE(d);
+    PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(dev);
     uint8_t *macaddr = d->conf.macaddr.a;
     int i;
+    uint16_t phy_id1 = -1, phy_id2 = -1;
 
     timer_del(d->autoneg_timer);
     timer_del(d->mit_timer);
@@ -385,6 +420,24 @@ static void e1000_reset(void *opaque)
     d->mit_ide = 0;
     memset(d->phy_reg, 0, sizeof d->phy_reg);
     memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
+    for (i = 0 ; PHY_ID1_INIT[i][0] != (uint16_t)-1 ; i++) {
+        if (PHY_ID1_INIT[i][0] == pdc->device_id) {
+            phy_id1 = PHY_ID1_INIT[i][1];
+        }
+    }
+    if (phy_id1 == (uint16_t)-1) {
+        phy_id1 = PHY_ID1_INIT[i][1];
+    }
+    for (i = 0 ; PHY_ID2_INIT[i][0] != (uint16_t)-1 ; i++) {
+        if (PHY_ID2_INIT[i][0] == pdc->device_id) {
+            phy_id2 = PHY_ID2_INIT[i][1];
+        }
+    }
+    if (phy_id2 == (uint16_t)-1) {
+        phy_id2 = PHY_ID2_INIT[i][1];
+    }
+    d->phy_reg[PHY_ID1] = phy_id1;
+    d->phy_reg[PHY_ID2] = phy_id2;
     memset(d->mac_reg, 0, sizeof d->mac_reg);
     memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
     d->rxbuf_min_shift = 1;
@@ -402,6 +455,13 @@ static void e1000_reset(void *opaque)
         d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0;
     }
     qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
+
+    /* reset flash (clear locks) */
+    memset(d->flash_reg, 0, FLASH_RSIZE*sizeof(uint16_t));
+    union ich8_hws_flash_status hsfsts;
+    hsfsts.regval = 0;
+    hsfsts.hsf_status.fldesvalid = 1;
+    d->flash_reg[ICH_FLASH_HSFSTS] = hsfsts.regval;
 }
 
 static void
@@ -409,6 +469,9 @@ set_ctrl(E1000State *s, int index, uint32_t val)
 {
     /* RST is self clearing */
     s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
+    if (val & E1000_CTRL_RST) {
+        e1000_reset(s);
+    }
 }
 
 static void
@@ -1017,7 +1080,17 @@ e1000_receive_iov(NetClientState *nc, const struct iovec 
*iov, int iovcnt)
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
-        pci_dma_write(d, base, &desc, sizeof(desc));
+        if (!s->rxbuf_edesc) {
+            pci_dma_write(d, base, &desc, sizeof(desc));
+        } else { /* extended rx descriptor */
+            union e1000_rx_desc_extended edesc;
+            edesc.wb.lower.mrq = 0;
+            edesc.wb.lower.hi_dword.rss = 0;
+            edesc.wb.upper.status_error = /* desc.errors << 24 | */ 
desc.status;
+            edesc.wb.upper.length = desc.length;
+            edesc.wb.upper.vlan = desc.special;
+            pci_dma_write(d, base, &edesc, sizeof(edesc));
+        }
 
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
@@ -1173,6 +1246,7 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
     getreg(TDBAL),     getreg(TDBAH),  getreg(RDBAH),  getreg(RDBAL),
     getreg(TDLEN),      getreg(RDLEN),  getreg(RDTR),   getreg(RADV),
     getreg(TADV),       getreg(ITR),
+    getreg(EXTCNF_CTRL), getreg(FWSM), getreg(KABGTXD), getreg(FACTPS),
 
     [TOTH] = mac_read_clr8,    [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
     [GPTC] = mac_read_clr4,    [TPR] = mac_read_clr4,  [TPT] = mac_read_clr4,
@@ -1189,6 +1263,7 @@ static void (*macreg_writeops[])(E1000State *, int, 
uint32_t) = {
     putreg(PBA),       putreg(EERD),   putreg(SWSM),   putreg(WUFC),
     putreg(TDBAL),     putreg(TDBAH),  putreg(TXDCTL), putreg(RDBAH),
     putreg(RDBAL),     putreg(LEDCTL), putreg(VET),
+    putreg(EXTCNF_CTRL), putreg(FWSM), putreg(KABGTXD), putreg(FACTPS),
     [TDLEN] = set_dlen,        [RDLEN] = set_dlen,     [TCTL] = set_tctl,
     [TDT] = set_tctl,  [MDIC] = set_mdic,      [ICS] = set_ics,
     [TDH] = set_16bit, [RDH] = set_16bit,      [RDT] = set_rdt,
@@ -1234,6 +1309,73 @@ e1000_mmio_read(void *opaque, hwaddr addr, unsigned size)
     return 0;
 }
 
+
+
+
+static void
+e1000_flash_write(void *opaque, hwaddr addr, uint64_t val,
+                 unsigned size)
+{
+    E1000State *s = opaque;
+    unsigned int index = addr % 2048;
+
+    if (index < FLASH_RSIZE) {
+        s->flash_reg[index] = val & 0xFFFF;
+        switch (index) {
+        case ICH_FLASH_HSFSTS: {
+            break;
+        }
+        case ICH_FLASH_HSFCTL: {
+            union ich8_hws_flash_ctrl ctrl;
+            ctrl.regval = s->flash_reg[ICH_FLASH_HSFCTL];
+            if (ctrl.hsf_ctrl.flcgo) {
+                /* says we're done, clear go,
+                   copy data to proper register */
+                union ich8_hws_flash_status hsfsts;
+                int fldbcount;
+                uint16_t offset;
+                uint16_t res;
+                hsfsts.regval = s->flash_reg[ICH_FLASH_HSFSTS];
+                hsfsts.hsf_status.flcdone = 1;
+                hsfsts.hsf_status.flcerr = 0;
+                s->flash_reg[ICH_FLASH_HSFSTS] = hsfsts.regval;
+                fldbcount = ctrl.hsf_ctrl.fldbcount;
+                ctrl.hsf_ctrl.flcgo = 0;
+                s->flash_reg[ICH_FLASH_HSFCTL] = ctrl.regval;
+                offset = s->flash_reg[ICH_FLASH_FADDR] >> 1;
+                res = s->eeprom_data[offset];
+                if (fldbcount == 0) {
+                    if (s->flash_reg[ICH_FLASH_FADDR] % 2) {
+                        res = res >> 8;
+                    } else {
+                        res = res & 0x00FF;
+                    }
+                }
+                s->flash_reg[ICH_FLASH_FDATA0] = res;
+            }
+        }
+        default:
+            break;
+        }
+    } else {
+        DBGOUT(UNKNOWN, "Flash unknown write addr=0x%08x,val=0x%08"PRIx64"\n",
+               index<<2, val);
+    }
+}
+
+static uint64_t
+e1000_flash_read(void *opaque, hwaddr addr, unsigned size)
+{
+    E1000State *s = opaque;
+    unsigned int index = addr % 2048;
+
+    if (index < FLASH_RSIZE) {
+        return s->flash_reg[index];
+    }
+    DBGOUT(UNKNOWN, "Flash unknown read addr=0x%08x\n", index<<2);
+    return 0;
+}
+
 static const MemoryRegionOps e1000_mmio_ops = {
     .read = e1000_mmio_read,
     .write = e1000_mmio_write,
@@ -1244,6 +1386,16 @@ static const MemoryRegionOps e1000_mmio_ops = {
     },
 };
 
+static const MemoryRegionOps e1000_flash_ops = {
+    .read = e1000_flash_read,
+    .write = e1000_flash_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
 static uint64_t e1000_io_read(void *opaque, hwaddr addr,
                               unsigned size)
 {
@@ -1425,6 +1577,8 @@ static const VMStateDescription vmstate_e1000 = {
         VMSTATE_UINT32(mac_reg[TXDCTL], E1000State),
         VMSTATE_UINT32(mac_reg[WUFC], E1000State),
         VMSTATE_UINT32(mac_reg[VET], E1000State),
+        VMSTATE_UINT32(mac_reg[EXTCNF_CTRL], E1000State),
+        VMSTATE_UINT32(mac_reg[FWSM], E1000State),
         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
@@ -1440,15 +1594,106 @@ static const VMStateDescription vmstate_e1000 = {
     }
 };
 
+/*
+ * The content of EEPROM is documented in the documentation
+ * PCI/X: "Table 5-2. Ethernet Controller Address Map" page 98 (except 
82544GC/EI and 82541ER)
+ * PCI/X: "Table 5-3. 82544GC/EI and 82541ER EEPROM Address Map" page 102
+ * PCIe: "Table 5-2. Ethernet Controller EEPROM Map" page 134
+ */
 static const uint16_t e1000_eeprom_template[64] = {
-    0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
-    0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
-    0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
-    0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
-    0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
-    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
-    0x0100, 0x4000, 0x121c, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
-    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
+    /* 00h - 02h: Ethernet address, will be overridden */
+    0x0000, 0x0000, 0x0000,
+    /* 03h: compatibility, this seems a bit device-specific
+            and probably should be overridden */
+    0x0000,
+    /* 04h: compatibility (PCIe) or SerDes config (most PCI/X) or LED */
+    0xffff,
+    /* 05h - 07h: EEprom version & OEM (PCIe other than 82573),
+                  compatibility (most PCI/X, 82573) */
+    0x0000, 0x0000, 0x0000,
+    /* 08h - 09h: PBA (irrelevant) */
+    0x3000, 0x1000,
+    /* 0ah: init control 1 */
+    0x6403,
+    /* 0bh - 0eh: PCI ID, will be overridden */
+    E1000_DEVID, 0x8086, E1000_DEVID, 0x8086,
+    /* 0fh: init control 2 */
+    0x3040,
+    /* 10h - 12h: seem quite device-specific with several variants */
+    0x0008, 0x2000, 0x7e14,
+    /* 13h: management */
+    0x0048,
+    /* 14h: init control 3 (2nd LAN?), not 82573 */
+    0x1000,
+    /* 15h - 16h: IPv4 (PCI/X) or  reserved (PCIe), not 82573 */
+    0x00d8, 0x0000,
+    /* 17h - 1Eh: Another batch of variants; IPv6 LAN in PCI/X
+     * but is FW Config Start Address (17h, most PCIe) followed
+     * by PCI init configuration and stuff
+     */
+    0x2700, 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000,
+    /* 1fh: mostly reserved (PCI/X), LED conf (PCIe) */
+    0x0706,
+    /* 20h - 21h: software defined pin controls, 21h: mostly control */
+    0x1008, 0x0000,
+    /* 22h - 23h: LAN power, management control (not 82573) */
+    0x0f04, 0x7fff,
+    /* 24h: init control 3 (again?) */
+    0x4d01,
+    /* 25h-2eh: either IP4/6 (PCI/X) or mostly reserved (PCIe) */
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    /* 2fh: LEDCTL Default (PCI/X) or Vital Product Data (VPD) Pointer (PCIe) 
*/
+    0xffff,
+    /* 30h-3eh: mostly PXE/boot stuff */
+    0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    /* 3fh: checksum to be computed */
+    0x0000
+};
+static const uint16_t e1000_ich8_flash_template[64] = {
+    /* 00h - 02h: Ethernet address, will be overridden */
+    0x0000, 0x0000, 0x0000,
+    /* 03h - 04h: reserved */
+    0x0800, 0xFFFF,
+    /* 05h - 07h: image version information, reserved*/
+    0x0000, 0xFFFF, 0xFFFF,
+    /* 08h - 09h: PBA (irrelevant) */
+    0x3000, 0x1000,
+    /* 0ah: init control 1 */
+    0x10c7,
+    /* 0bh - 0eh: PCI ID, will be overridden */
+    E1000_DEVID, 0x8086, E1000_DEVID, 0x8086,
+    /* 0fh: device revision id (ich9), reserved (ich8) */
+    0x0000, /* fixme */
+    /* 10h - 12h: LAN power consumption, reserved */
+    0x0D01, 0x0000, 0x0000,
+    /* 13h: Shared Initialization Control Word */
+    0x9607,
+    /* 14h - 16h: extended configuration word 1-3 */
+    0x7020, 0x3800, 0x0000,
+    /* 17h - 18h: LEDCTL 1, LEDCTL 0 2 */
+    0x8d07, 0x0684,
+    /* 19h - 1ah: future initialization words */
+    (0x0181 | 0x0040), 0x0800,
+    /* 1bh - 1dh: reserved */
+    0x0000, 0x294C, 0x294C,
+    /* 1eh - 1fh: device id (some devices) */
+    0x10BE, 0x10BF,
+    /* 20h - 21h: reserved */
+    0x294C, 0x294C,
+    /* 22h - 23h: device id (some devices) */
+    0x10bd, 0x294C,
+    /* 24h-2fh: reserved */
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff,
+    /* 30h-3eh: mostly PXE/boot stuff & reserved */
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    /* 3fh: checksum to be computed */
+    0x0000
 };
 
 /* PCI interface */
@@ -1468,6 +1713,10 @@ e1000_mmio_setup(E1000State *d)
     for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
         memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
                                      excluded_regs[i+1] - excluded_regs[i] - 
4);
+
+    memory_region_init_io(&d->flash, OBJECT(d), &e1000_flash_ops, d,
+                          "e1000-flash", FLASH_RSIZE);
+
     memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", 
IOPORT_SIZE);
 }
 
@@ -1506,6 +1755,7 @@ static NetClientInfo net_e1000_info = {
 static int pci_e1000_init(PCIDevice *pci_dev)
 {
     DeviceState *dev = DEVICE(pci_dev);
+    PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(pci_dev);
     E1000State *d = E1000(pci_dev);
     uint8_t *pci_conf;
     uint16_t checksum = 0;
@@ -1523,7 +1773,9 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
 
-    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->flash);
+
+    pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
@@ -1531,11 +1783,38 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     macaddr = d->conf.macaddr.a;
     for (i = 0; i < 3; i++)
         d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
+    /* update eeprom with the proper device_id */
+    d->eeprom_data[11] = pdc->device_id;
+    d->eeprom_data[13] = pdc->device_id;
     for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
         checksum += d->eeprom_data[i];
     checksum = (uint16_t) EEPROM_SUM - checksum;
     d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
-
+    d->rxbuf_edesc = 0;
+    if (pdc->device_id == E1000_DEV_ID_ICH9_IGP_AMT) {
+        /* fixme: other devices */
+        for (i = 0 ; i < EEPROM_CHECKSUM_REG; i++) {
+            d->eeprom_data[i] = e1000_ich8_flash_template[i];
+        }
+        for (i = 0; i < 3; i++) {
+            d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
+        }
+        d->eeprom_data[11] = pdc->device_id;
+        d->eeprom_data[13] = pdc->device_id;
+        checksum = 0;
+        for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
+            checksum += d->eeprom_data[i];
+        }
+        checksum = (uint16_t) EEPROM_SUM - checksum;
+        d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
+        /* init flash registers */
+        memset(d->flash_reg, 0, FLASH_RSIZE*sizeof(uint16_t));
+        union ich8_hws_flash_status hsfsts;
+        hsfsts.regval = 0;
+        hsfsts.hsf_status.fldesvalid = 1;
+        d->flash_reg[ICH_FLASH_HSFSTS] = hsfsts.regval;
+        d->rxbuf_edesc = 1;
+    }
     d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
                           object_get_typename(OBJECT(d)), dev->id, d);
 
@@ -1551,7 +1830,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 
 static void qdev_e1000_reset(DeviceState *dev)
 {
-    E1000State *d = E1000(dev);
+    PCIDevice *pci_dev = PCI_DEVICE(dev);
+    E1000State *d = E1000(pci_dev);
     e1000_reset(d);
 }
 
@@ -1564,17 +1844,26 @@ static Property e1000_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+typedef struct E1000Info E1000Info;
+struct E1000Info {
+    const char *name;
+    uint16_t   vendor_id;
+    uint16_t   device_id;
+    uint8_t    revision;
+};
+
 static void e1000_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    E1000Info *info = data;
 
     k->init = pci_e1000_init;
     k->exit = pci_e1000_uninit;
     k->romfile = "efi-e1000.rom";
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = E1000_DEVID;
-    k->revision = 0x03;
+    k->vendor_id = info->vendor_id;
+    k->device_id = info->device_id;
+    k->revision = info->revision;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     dc->desc = "Intel Gigabit Ethernet";
@@ -1583,16 +1872,59 @@ static void e1000_class_init(ObjectClass *klass, void 
*data)
     dc->props = e1000_properties;
 }
 
-static const TypeInfo e1000_info = {
+static E1000Info e1000_info_array[] = {
+    {
+        .name      = "e1000",
+        .vendor_id = PCI_VENDOR_ID_INTEL,
+        .device_id = E1000_DEVID,
+        .revision  = 0x03,
+    },
+    {
+        .name      = "82540EM",
+        .vendor_id = PCI_VENDOR_ID_INTEL,
+        .device_id = E1000_DEV_ID_82540EM,
+        .revision  = 0x03,
+    },
+    {
+        .name      = "82544GC",
+        .vendor_id = PCI_VENDOR_ID_INTEL,
+        .device_id = E1000_DEV_ID_82544GC_COPPER,
+        .revision  = 0x03,
+    },
+    {
+        .name      = "82545EM",
+        .vendor_id = PCI_VENDOR_ID_INTEL,
+        .device_id = E1000_DEV_ID_82545EM_COPPER,
+        .revision  = 0x03,
+    },
+    {
+        .name      = "82566DM",
+        .vendor_id = PCI_VENDOR_ID_INTEL,
+        .device_id = E1000_DEV_ID_ICH9_IGP_AMT,
+        .revision  = 0x00,
+    }
+};
+
+static const TypeInfo e1000_info_abstract = {
     .name          = TYPE_E1000,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(E1000State),
-    .class_init    = e1000_class_init,
+    .abstract      = true,
 };
 
 static void e1000_register_types(void)
 {
-    type_register_static(&e1000_info);
+    int i;
+    type_register_static(&e1000_info_abstract);
+    for (i = 0; i < ARRAY_SIZE(e1000_info_array); i++) {
+        TypeInfo e1000_info = {
+          .name = e1000_info_array[i].name,
+          .parent = TYPE_E1000,
+          .class_data = e1000_info_array + i,
+          .class_init    = e1000_class_init,
+        };
+        type_register(&e1000_info);
+    }
 }
 
 type_init(e1000_register_types)
diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index c9cb79e..0262174 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -34,46 +34,71 @@
 
 
 /* PCI Device IDs */
+/* Where is the documentation for those 3 ?
+   (they are nonetheless in e1000.ko) */
 #define E1000_DEV_ID_82542               0x1000
 #define E1000_DEV_ID_82543GC_FIBER       0x1001
 #define E1000_DEV_ID_82543GC_COPPER      0x1004
-#define E1000_DEV_ID_82544EI_COPPER      0x1008
-#define E1000_DEV_ID_82544EI_FIBER       0x1009
-#define E1000_DEV_ID_82544GC_COPPER      0x100C
-#define E1000_DEV_ID_82544GC_LOM         0x100D
+/* 
<http://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf>
+ * "PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's 
Manual"
+ * documents
+ * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx
+ * Those are handled by driver 'e1000'
+ */
 #define E1000_DEV_ID_82540EM             0x100E
 #define E1000_DEV_ID_82540EM_LOM         0x1015
 #define E1000_DEV_ID_82540EP_LOM         0x1016
 #define E1000_DEV_ID_82540EP             0x1017
 #define E1000_DEV_ID_82540EP_LP          0x101E
+
+#define E1000_DEV_ID_82541EI             0x1013
+#define E1000_DEV_ID_82541EI_MOBILE      0x1018
+#define E1000_DEV_ID_82541ER_LOM         0x1014
+#define E1000_DEV_ID_82541ER             0x1078
+#define E1000_DEV_ID_82541GI             0x1076
+#define E1000_DEV_ID_82541GI_MOBILE      0x1077
+#define E1000_DEV_ID_82541GI_LF          0x107C
+
+#define E1000_DEV_ID_82544EI_COPPER      0x1008
+#define E1000_DEV_ID_82544EI_FIBER       0x1009
+#define E1000_DEV_ID_82544GC_COPPER      0x100C
+#define E1000_DEV_ID_82544GC_LOM         0x100D
+
 #define E1000_DEV_ID_82545EM_COPPER      0x100F
 #define E1000_DEV_ID_82545EM_FIBER       0x1011
 #define E1000_DEV_ID_82545GM_COPPER      0x1026
 #define E1000_DEV_ID_82545GM_FIBER       0x1027
 #define E1000_DEV_ID_82545GM_SERDES      0x1028
+
 #define E1000_DEV_ID_82546EB_COPPER      0x1010
 #define E1000_DEV_ID_82546EB_FIBER       0x1012
 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
-#define E1000_DEV_ID_82541EI             0x1013
-#define E1000_DEV_ID_82541EI_MOBILE      0x1018
-#define E1000_DEV_ID_82541ER_LOM         0x1014
-#define E1000_DEV_ID_82541ER             0x1078
-#define E1000_DEV_ID_82547GI             0x1075
-#define E1000_DEV_ID_82541GI             0x1076
-#define E1000_DEV_ID_82541GI_MOBILE      0x1077
-#define E1000_DEV_ID_82541GI_LF          0x107C
 #define E1000_DEV_ID_82546GB_COPPER      0x1079
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
 #define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+
+#define E1000_DEV_ID_82547GI             0x1075
 #define E1000_DEV_ID_82547EI             0x1019
 #define E1000_DEV_ID_82547EI_MOBILE      0x101A
+/* 
<http://www.intel.com/content/dam/www/public/us/en/documents/manuals/pcie-gbe-controllers-open-source-manual.pdf>
+ * "PCIe* GbE Controllers Open Source Software Developer's Manual"
+ * documents:
+ * 631xESB/632xESB, 82563EB/82564EB, 82571EB/82572EI & 82573E/82573V/82573L
+ * Those are actually handled by driver 'e1000e', not 'e1000'
+ */
+/* it seems the next four are alternative names for 631xESB/632xESB */
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT     0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT     0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT     0x10BB
+
 #define E1000_DEV_ID_82571EB_COPPER      0x105E
 #define E1000_DEV_ID_82571EB_FIBER       0x105F
 #define E1000_DEV_ID_82571EB_SERDES      0x1060
 #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
-#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
 #define E1000_DEV_ID_82571EB_QUAD_FIBER  0x10A5
 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE  0x10BC
 #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
@@ -82,15 +107,18 @@
 #define E1000_DEV_ID_82572EI_FIBER       0x107E
 #define E1000_DEV_ID_82572EI_SERDES      0x107F
 #define E1000_DEV_ID_82572EI             0x10B9
+/* is the next one from the same document ? */
+#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
+
 #define E1000_DEV_ID_82573E              0x108B
 #define E1000_DEV_ID_82573E_IAMT         0x108C
 #define E1000_DEV_ID_82573L              0x109A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
-#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
-#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT     0x1098
-#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT     0x10BA
-#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT     0x10BB
 
+/* 
<http://www.intel.com/content/dam/doc/manual/i-o-controller-hub-8-9-10-82566-82567-82562v-software-dev-manual.pdf>
+ * and also
+ * 
<http://www.intel.com/content/dam/www/public/us/en/documents/design-guides/i-o-controller-hub-8-9-nvm-map-guide.pdf>
+ */
+#define E1000_DEV_ID_ICH8_82567V_3       0x1501
 #define E1000_DEV_ID_ICH8_IGP_M_AMT      0x1049
 #define E1000_DEV_ID_ICH8_IGP_AMT        0x104A
 #define E1000_DEV_ID_ICH8_IGP_C          0x104B
@@ -98,6 +126,21 @@
 #define E1000_DEV_ID_ICH8_IFE_GT         0x10C4
 #define E1000_DEV_ID_ICH8_IFE_G          0x10C5
 #define E1000_DEV_ID_ICH8_IGP_M          0x104D
+#define E1000_DEV_ID_ICH9_IGP_AMT        0x10BD
+#define E1000_DEV_ID_ICH9_BM             0x10E5
+#define E1000_DEV_ID_ICH9_IGP_M_AMT      0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M          0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_V        0x10CB
+#define E1000_DEV_ID_ICH9_IGP_C          0x294C
+#define E1000_DEV_ID_ICH9_IFE            0x10C0
+#define E1000_DEV_ID_ICH9_IFE_GT         0x10C3
+#define E1000_DEV_ID_ICH9_IFE_G          0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM       0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF       0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V        0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM       0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF       0x10DF
+
 
 /* Register Set. (82543, 82544)
  *
@@ -349,6 +392,8 @@
 #define M88E1000_PHY_VCO_REG_BIT8  0x100 /* Bits 8 & 11 are adjusted for */
 #define M88E1000_PHY_VCO_REG_BIT11 0x800    /* improved BER performance */
 
+#define ICH_IGP_PHY_REGADD_ALT_MDIO 0x1F
+
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
 #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
@@ -542,9 +587,9 @@
 #define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
 #define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
 #define E1000_EEPROM_RW_REG_DATA   16   /* Offset to data in EEPROM read/write 
registers */
-#define E1000_EEPROM_RW_REG_DONE   0x10 /* Offset to READ/WRITE done bit */
+#define E1000_EEPROM_RW_REG_DONE   0x2  /* Offset to READ/WRITE done bit */
 #define E1000_EEPROM_RW_REG_START  1    /* First bit for telling part to start 
operation */
-#define E1000_EEPROM_RW_ADDR_SHIFT 8    /* Shift to the address bits */
+#define E1000_EEPROM_RW_ADDR_SHIFT 2    /* Shift to the address bits */
 #define E1000_EEPROM_POLL_WRITE    1    /* Flag for polling for write complete 
*/
 #define E1000_EEPROM_POLL_READ     0    /* Flag for polling for read complete 
*/
 /* Register Bit Masks */
@@ -761,6 +806,31 @@ struct e1000_rx_desc {
     uint8_t errors;      /* Descriptor Errors */
     uint16_t special;
 };
+/* Receive Descriptor - Extended */
+union e1000_rx_desc_extended {
+        struct {
+                uint64_t buffer_addr;
+                uint64_t reserved;
+        } read;
+        struct {
+                struct {
+                        uint32_t mrq;     /* Multiple Rx Queues */
+                        union {
+                                uint32_t rss;     /* RSS Hash */
+                                struct {
+                                        uint16_t ip_id;   /* IP id */
+                                        uint16_t csum;    /* Packet Checksum */
+                                } csum_ip;
+                        } hi_dword;
+                } lower;
+                struct {
+                        uint32_t status_error;    /* ext status/error */
+                        uint16_t length;
+                        uint16_t vlan;    /* VLAN tag */
+                } upper;
+        } wb;                   /* writeback */
+};
+
 
 /* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
@@ -890,4 +960,43 @@ struct e1000_data_desc {
 /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
 #define EEPROM_SUM 0xBABA
 
+
+
+/* FLASH stuff ; straight from the linux driver */
+#define ICH_FLASH_GFPREG              0x0000
+#define ICH_FLASH_HSFSTS              0x0004
+#define ICH_FLASH_HSFCTL              0x0006
+#define ICH_FLASH_FADDR                       0x0008
+#define ICH_FLASH_FDATA0              0x0010
+#define ICH_FLASH_PR0                 0x0074
+/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
+/* Offset 04h HSFSTS */
+union ich8_hws_flash_status {
+        struct ich8_hsfsts {
+                uint16_t flcdone:1;  /* bit 0 Flash Cycle Done */
+                uint16_t flcerr:1;   /* bit 1 Flash Cycle Error */
+                uint16_t dael:1;     /* bit 2 Direct Access error Log */
+                uint16_t berasesz:2; /* bit 4:3 Sector Erase Size */
+                uint16_t flcinprog:1;        /* bit 5 flash cycle in Progress 
*/
+                uint16_t reserved1:2;        /* bit 13:6 Reserved */
+                uint16_t reserved2:6;        /* bit 13:6 Reserved */
+                uint16_t fldesvalid:1;       /* bit 14 Flash Descriptor Valid 
*/
+                uint16_t flockdn:1;  /* bit 15 Flash Config Lock-Down */
+        } hsf_status;
+        uint16_t regval;
+};
+
+/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */
+/* Offset 06h FLCTL */
+union ich8_hws_flash_ctrl {
+        struct ich8_hsflctl {
+                uint16_t flcgo:1;    /* 0 Flash Cycle Go */
+                uint16_t flcycle:2;  /* 2:1 Flash Cycle */
+                uint16_t reserved:5; /* 7:3 Reserved  */
+                uint16_t fldbcount:2;        /* 9:8 Flash Data Byte Count */
+                uint16_t flockdn:6;  /* 15:10 Reserved */
+        } hsf_ctrl;
+        uint16_t regval;
+};
+
 #endif /* _E1000_HW_H_ */
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]