[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