Try to implement proper QOM Signed-off-by: Romain Dolbeau <rom...@dolbeau.org> --- 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