17c23b892Sbalrog /* 27c23b892Sbalrog * QEMU e1000 emulation 37c23b892Sbalrog * 42758aa52SMichael S. Tsirkin * Software developer's manual: 52758aa52SMichael S. Tsirkin * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf 62758aa52SMichael S. Tsirkin * 77c23b892Sbalrog * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. 87c23b892Sbalrog * Copyright (c) 2008 Qumranet 97c23b892Sbalrog * Based on work done by: 107c23b892Sbalrog * Copyright (c) 2007 Dan Aloni 117c23b892Sbalrog * Copyright (c) 2004 Antony T Curtis 127c23b892Sbalrog * 137c23b892Sbalrog * This library is free software; you can redistribute it and/or 147c23b892Sbalrog * modify it under the terms of the GNU Lesser General Public 157c23b892Sbalrog * License as published by the Free Software Foundation; either 167c23b892Sbalrog * version 2 of the License, or (at your option) any later version. 177c23b892Sbalrog * 187c23b892Sbalrog * This library is distributed in the hope that it will be useful, 197c23b892Sbalrog * but WITHOUT ANY WARRANTY; without even the implied warranty of 207c23b892Sbalrog * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 217c23b892Sbalrog * Lesser General Public License for more details. 227c23b892Sbalrog * 237c23b892Sbalrog * You should have received a copy of the GNU Lesser General Public 248167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 257c23b892Sbalrog */ 267c23b892Sbalrog 277c23b892Sbalrog 2883c9f4caSPaolo Bonzini #include "hw/hw.h" 2983c9f4caSPaolo Bonzini #include "hw/pci/pci.h" 301422e32dSPaolo Bonzini #include "net/net.h" 317200ac3cSMark McLoughlin #include "net/checksum.h" 3283c9f4caSPaolo Bonzini #include "hw/loader.h" 339c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 349c17d615SPaolo Bonzini #include "sysemu/dma.h" 357c23b892Sbalrog 3647b43a1fSPaolo Bonzini #include "e1000_regs.h" 377c23b892Sbalrog 3827124888SJes Sorensen #define E1000_DEBUG 397c23b892Sbalrog 4027124888SJes Sorensen #ifdef E1000_DEBUG 417c23b892Sbalrog enum { 427c23b892Sbalrog DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT, 437c23b892Sbalrog DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM, 447c23b892Sbalrog DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR, 45f9c1cdf4SJason Wang DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET, 467c23b892Sbalrog }; 477c23b892Sbalrog #define DBGBIT(x) (1<<DEBUG_##x) 487c23b892Sbalrog static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); 497c23b892Sbalrog 506c7f4b47SBlue Swirl #define DBGOUT(what, fmt, ...) do { \ 517c23b892Sbalrog if (debugflags & DBGBIT(what)) \ 526c7f4b47SBlue Swirl fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \ 537c23b892Sbalrog } while (0) 547c23b892Sbalrog #else 556c7f4b47SBlue Swirl #define DBGOUT(what, fmt, ...) do {} while (0) 567c23b892Sbalrog #endif 577c23b892Sbalrog 587c23b892Sbalrog #define IOPORT_SIZE 0x40 59e94bbefeSaurel32 #define PNPMMIO_SIZE 0x20000 6078aeb23eSStefan Hajnoczi #define MIN_BUF_SIZE 60 /* Min. octets in an ethernet frame sans FCS */ 617c23b892Sbalrog 62b0d9ffcdSMichael Contreras /* this is the size past which hardware will drop packets when setting LPE=0 */ 63b0d9ffcdSMichael Contreras #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 642c0331f4SMichael Contreras /* this is the size past which hardware will drop packets when setting LPE=1 */ 652c0331f4SMichael Contreras #define MAXIMUM_ETHERNET_LPE_SIZE 16384 66b0d9ffcdSMichael Contreras 677c23b892Sbalrog /* 687c23b892Sbalrog * HW models: 697c23b892Sbalrog * E1000_DEV_ID_82540EM works with Windows and Linux 707c23b892Sbalrog * E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22, 717c23b892Sbalrog * appears to perform better than 82540EM, but breaks with Linux 2.6.18 727c23b892Sbalrog * E1000_DEV_ID_82544GC_COPPER appears to work; not well tested 737c23b892Sbalrog * Others never tested 747c23b892Sbalrog */ 757c23b892Sbalrog enum { E1000_DEVID = E1000_DEV_ID_82540EM }; 767c23b892Sbalrog 777c23b892Sbalrog /* 787c23b892Sbalrog * May need to specify additional MAC-to-PHY entries -- 797c23b892Sbalrog * Intel's Windows driver refuses to initialize unless they match 807c23b892Sbalrog */ 817c23b892Sbalrog enum { 827c23b892Sbalrog PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ? 0xcc2 : 837c23b892Sbalrog E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ? 0xc30 : 847c23b892Sbalrog /* default to E1000_DEV_ID_82540EM */ 0xc20 857c23b892Sbalrog }; 867c23b892Sbalrog 877c23b892Sbalrog typedef struct E1000State_st { 887c23b892Sbalrog PCIDevice dev; 89a03e2aecSMark McLoughlin NICState *nic; 90fbdaa002SGerd Hoffmann NICConf conf; 91ad00a9b9SAvi Kivity MemoryRegion mmio; 92ad00a9b9SAvi Kivity MemoryRegion io; 937c23b892Sbalrog 947c23b892Sbalrog uint32_t mac_reg[0x8000]; 957c23b892Sbalrog uint16_t phy_reg[0x20]; 967c23b892Sbalrog uint16_t eeprom_data[64]; 977c23b892Sbalrog 987c23b892Sbalrog uint32_t rxbuf_size; 997c23b892Sbalrog uint32_t rxbuf_min_shift; 1007c23b892Sbalrog struct e1000_tx { 1017c23b892Sbalrog unsigned char header[256]; 1028f2e8d1fSaliguori unsigned char vlan_header[4]; 103b10fec9bSStefan Weil /* Fields vlan and data must not be reordered or separated. */ 1048f2e8d1fSaliguori unsigned char vlan[4]; 1057c23b892Sbalrog unsigned char data[0x10000]; 1067c23b892Sbalrog uint16_t size; 1077c23b892Sbalrog unsigned char sum_needed; 1088f2e8d1fSaliguori unsigned char vlan_needed; 1097c23b892Sbalrog uint8_t ipcss; 1107c23b892Sbalrog uint8_t ipcso; 1117c23b892Sbalrog uint16_t ipcse; 1127c23b892Sbalrog uint8_t tucss; 1137c23b892Sbalrog uint8_t tucso; 1147c23b892Sbalrog uint16_t tucse; 1157c23b892Sbalrog uint8_t hdr_len; 1167c23b892Sbalrog uint16_t mss; 1177c23b892Sbalrog uint32_t paylen; 1187c23b892Sbalrog uint16_t tso_frames; 1197c23b892Sbalrog char tse; 120b6c4f71fSblueswir1 int8_t ip; 121b6c4f71fSblueswir1 int8_t tcp; 1221b0009dbSbalrog char cptse; // current packet tse bit 1237c23b892Sbalrog } tx; 1247c23b892Sbalrog 1257c23b892Sbalrog struct { 1267c23b892Sbalrog uint32_t val_in; // shifted in from guest driver 1277c23b892Sbalrog uint16_t bitnum_in; 1287c23b892Sbalrog uint16_t bitnum_out; 1297c23b892Sbalrog uint16_t reading; 1307c23b892Sbalrog uint32_t old_eecd; 1317c23b892Sbalrog } eecd_state; 132b9d03e35SJason Wang 133b9d03e35SJason Wang QEMUTimer *autoneg_timer; 1342af234e6SMichael S. Tsirkin 1352af234e6SMichael S. Tsirkin /* Compatibility flags for migration to/from qemu 1.3.0 and older */ 1362af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG_BIT 0 1372af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) 1382af234e6SMichael S. Tsirkin uint32_t compat_flags; 1397c23b892Sbalrog } E1000State; 1407c23b892Sbalrog 141*567a3c9eSPeter Crosthwaite #define TYPE_E1000 "e1000" 142*567a3c9eSPeter Crosthwaite 143*567a3c9eSPeter Crosthwaite #define E1000(obj) \ 144*567a3c9eSPeter Crosthwaite OBJECT_CHECK(E1000State, (obj), TYPE_E1000) 145*567a3c9eSPeter Crosthwaite 1467c23b892Sbalrog #define defreg(x) x = (E1000_##x>>2) 1477c23b892Sbalrog enum { 1487c23b892Sbalrog defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), 1497c23b892Sbalrog defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), 1507c23b892Sbalrog defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), 1517c23b892Sbalrog defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH), 1527c23b892Sbalrog defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT), 1537c23b892Sbalrog defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), 1547c23b892Sbalrog defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), 1557c23b892Sbalrog defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL), 1567c23b892Sbalrog defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC), 1578f2e8d1fSaliguori defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA), 1588f2e8d1fSaliguori defreg(VET), 1597c23b892Sbalrog }; 1607c23b892Sbalrog 16171aadd3cSJason Wang static void 16271aadd3cSJason Wang e1000_link_down(E1000State *s) 16371aadd3cSJason Wang { 16471aadd3cSJason Wang s->mac_reg[STATUS] &= ~E1000_STATUS_LU; 16571aadd3cSJason Wang s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS; 16671aadd3cSJason Wang } 16771aadd3cSJason Wang 16871aadd3cSJason Wang static void 16971aadd3cSJason Wang e1000_link_up(E1000State *s) 17071aadd3cSJason Wang { 17171aadd3cSJason Wang s->mac_reg[STATUS] |= E1000_STATUS_LU; 17271aadd3cSJason Wang s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS; 17371aadd3cSJason Wang } 17471aadd3cSJason Wang 175b9d03e35SJason Wang static void 176b9d03e35SJason Wang set_phy_ctrl(E1000State *s, int index, uint16_t val) 177b9d03e35SJason Wang { 1782af234e6SMichael S. Tsirkin /* 1792af234e6SMichael S. Tsirkin * QEMU 1.3 does not support link auto-negotiation emulation, so if we 1802af234e6SMichael S. Tsirkin * migrate during auto negotiation, after migration the link will be 1812af234e6SMichael S. Tsirkin * down. 1822af234e6SMichael S. Tsirkin */ 1832af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 1842af234e6SMichael S. Tsirkin return; 1852af234e6SMichael S. Tsirkin } 186b9d03e35SJason Wang if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) { 187b9d03e35SJason Wang e1000_link_down(s); 188b9d03e35SJason Wang s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; 189b9d03e35SJason Wang DBGOUT(PHY, "Start link auto negotiation\n"); 190b9d03e35SJason Wang qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); 191b9d03e35SJason Wang } 192b9d03e35SJason Wang } 193b9d03e35SJason Wang 194b9d03e35SJason Wang static void 195b9d03e35SJason Wang e1000_autoneg_timer(void *opaque) 196b9d03e35SJason Wang { 197b9d03e35SJason Wang E1000State *s = opaque; 198ddcb73b7SMichael S. Tsirkin if (!qemu_get_queue(s->nic)->link_down) { 199b9d03e35SJason Wang e1000_link_up(s); 200ddcb73b7SMichael S. Tsirkin } 201b9d03e35SJason Wang s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; 202b9d03e35SJason Wang DBGOUT(PHY, "Auto negotiation is completed\n"); 203b9d03e35SJason Wang } 204b9d03e35SJason Wang 205b9d03e35SJason Wang static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = { 206b9d03e35SJason Wang [PHY_CTRL] = set_phy_ctrl, 207b9d03e35SJason Wang }; 208b9d03e35SJason Wang 209b9d03e35SJason Wang enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) }; 210b9d03e35SJason Wang 2117c23b892Sbalrog enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W }; 21288b4e9dbSblueswir1 static const char phy_regcap[0x20] = { 2137c23b892Sbalrog [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW, 2147c23b892Sbalrog [PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW, 2157c23b892Sbalrog [PHY_CTRL] = PHY_RW, [PHY_1000T_CTRL] = PHY_RW, 2167c23b892Sbalrog [PHY_LP_ABILITY] = PHY_R, [PHY_1000T_STATUS] = PHY_R, 2177c23b892Sbalrog [PHY_AUTONEG_ADV] = PHY_RW, [M88E1000_RX_ERR_CNTR] = PHY_R, 218700f6e2cSaurel32 [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R 2197c23b892Sbalrog }; 2207c23b892Sbalrog 221814cd3acSMichael S. Tsirkin static const uint16_t phy_reg_init[] = { 222b9d03e35SJason Wang [PHY_CTRL] = 0x1140, 223b9d03e35SJason Wang [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */ 224814cd3acSMichael S. Tsirkin [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT, 225814cd3acSMichael S. Tsirkin [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360, 226814cd3acSMichael S. Tsirkin [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1, 227814cd3acSMichael S. Tsirkin [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00, 228814cd3acSMichael S. Tsirkin [M88E1000_PHY_SPEC_STATUS] = 0xac00, 229814cd3acSMichael S. Tsirkin }; 230814cd3acSMichael S. Tsirkin 231814cd3acSMichael S. Tsirkin static const uint32_t mac_reg_init[] = { 232814cd3acSMichael S. Tsirkin [PBA] = 0x00100030, 233814cd3acSMichael S. Tsirkin [LEDCTL] = 0x602, 234814cd3acSMichael S. Tsirkin [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | 235814cd3acSMichael S. Tsirkin E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, 236814cd3acSMichael S. Tsirkin [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | 237814cd3acSMichael S. Tsirkin E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | 238814cd3acSMichael S. Tsirkin E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | 239814cd3acSMichael S. Tsirkin E1000_STATUS_LU, 240814cd3acSMichael S. Tsirkin [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | 241814cd3acSMichael S. Tsirkin E1000_MANC_ARP_EN | E1000_MANC_0298_EN | 242814cd3acSMichael S. Tsirkin E1000_MANC_RMCP_EN, 243814cd3acSMichael S. Tsirkin }; 244814cd3acSMichael S. Tsirkin 2457c23b892Sbalrog static void 2467c23b892Sbalrog set_interrupt_cause(E1000State *s, int index, uint32_t val) 2477c23b892Sbalrog { 248f1219091SJason Wang if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) { 249f1219091SJason Wang /* Only for 8257x */ 2507c23b892Sbalrog val |= E1000_ICR_INT_ASSERTED; 251f1219091SJason Wang } 2527c23b892Sbalrog s->mac_reg[ICR] = val; 253a52a8841SMichael S. Tsirkin 254a52a8841SMichael S. Tsirkin /* 255a52a8841SMichael S. Tsirkin * Make sure ICR and ICS registers have the same value. 256a52a8841SMichael S. Tsirkin * The spec says that the ICS register is write-only. However in practice, 257a52a8841SMichael S. Tsirkin * on real hardware ICS is readable, and for reads it has the same value as 258a52a8841SMichael S. Tsirkin * ICR (except that ICS does not have the clear on read behaviour of ICR). 259a52a8841SMichael S. Tsirkin * 260a52a8841SMichael S. Tsirkin * The VxWorks PRO/1000 driver uses this behaviour. 261a52a8841SMichael S. Tsirkin */ 262b1332393SBill Paul s->mac_reg[ICS] = val; 263a52a8841SMichael S. Tsirkin 264bc26e55aSBlue Swirl qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0); 2657c23b892Sbalrog } 2667c23b892Sbalrog 2677c23b892Sbalrog static void 2687c23b892Sbalrog set_ics(E1000State *s, int index, uint32_t val) 2697c23b892Sbalrog { 2707c23b892Sbalrog DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR], 2717c23b892Sbalrog s->mac_reg[IMS]); 2727c23b892Sbalrog set_interrupt_cause(s, 0, val | s->mac_reg[ICR]); 2737c23b892Sbalrog } 2747c23b892Sbalrog 2757c23b892Sbalrog static int 2767c23b892Sbalrog rxbufsize(uint32_t v) 2777c23b892Sbalrog { 2787c23b892Sbalrog v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 | 2797c23b892Sbalrog E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 | 2807c23b892Sbalrog E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256; 2817c23b892Sbalrog switch (v) { 2827c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384: 2837c23b892Sbalrog return 16384; 2847c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192: 2857c23b892Sbalrog return 8192; 2867c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096: 2877c23b892Sbalrog return 4096; 2887c23b892Sbalrog case E1000_RCTL_SZ_1024: 2897c23b892Sbalrog return 1024; 2907c23b892Sbalrog case E1000_RCTL_SZ_512: 2917c23b892Sbalrog return 512; 2927c23b892Sbalrog case E1000_RCTL_SZ_256: 2937c23b892Sbalrog return 256; 2947c23b892Sbalrog } 2957c23b892Sbalrog return 2048; 2967c23b892Sbalrog } 2977c23b892Sbalrog 298814cd3acSMichael S. Tsirkin static void e1000_reset(void *opaque) 299814cd3acSMichael S. Tsirkin { 300814cd3acSMichael S. Tsirkin E1000State *d = opaque; 301372254c6SGabriel L. Somlo uint8_t *macaddr = d->conf.macaddr.a; 302372254c6SGabriel L. Somlo int i; 303814cd3acSMichael S. Tsirkin 304b9d03e35SJason Wang qemu_del_timer(d->autoneg_timer); 305814cd3acSMichael S. Tsirkin memset(d->phy_reg, 0, sizeof d->phy_reg); 306814cd3acSMichael S. Tsirkin memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); 307814cd3acSMichael S. Tsirkin memset(d->mac_reg, 0, sizeof d->mac_reg); 308814cd3acSMichael S. Tsirkin memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); 309814cd3acSMichael S. Tsirkin d->rxbuf_min_shift = 1; 310814cd3acSMichael S. Tsirkin memset(&d->tx, 0, sizeof d->tx); 311814cd3acSMichael S. Tsirkin 312b356f76dSJason Wang if (qemu_get_queue(d->nic)->link_down) { 31371aadd3cSJason Wang e1000_link_down(d); 314814cd3acSMichael S. Tsirkin } 315372254c6SGabriel L. Somlo 316372254c6SGabriel L. Somlo /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */ 317372254c6SGabriel L. Somlo d->mac_reg[RA] = 0; 318372254c6SGabriel L. Somlo d->mac_reg[RA + 1] = E1000_RAH_AV; 319372254c6SGabriel L. Somlo for (i = 0; i < 4; i++) { 320372254c6SGabriel L. Somlo d->mac_reg[RA] |= macaddr[i] << (8 * i); 321372254c6SGabriel L. Somlo d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0; 322372254c6SGabriel L. Somlo } 323814cd3acSMichael S. Tsirkin } 324814cd3acSMichael S. Tsirkin 3257c23b892Sbalrog static void 326cab3c825SKevin Wolf set_ctrl(E1000State *s, int index, uint32_t val) 327cab3c825SKevin Wolf { 328cab3c825SKevin Wolf /* RST is self clearing */ 329cab3c825SKevin Wolf s->mac_reg[CTRL] = val & ~E1000_CTRL_RST; 330cab3c825SKevin Wolf } 331cab3c825SKevin Wolf 332cab3c825SKevin Wolf static void 3337c23b892Sbalrog set_rx_control(E1000State *s, int index, uint32_t val) 3347c23b892Sbalrog { 3357c23b892Sbalrog s->mac_reg[RCTL] = val; 3367c23b892Sbalrog s->rxbuf_size = rxbufsize(val); 3377c23b892Sbalrog s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; 3387c23b892Sbalrog DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], 3397c23b892Sbalrog s->mac_reg[RCTL]); 340b356f76dSJason Wang qemu_flush_queued_packets(qemu_get_queue(s->nic)); 3417c23b892Sbalrog } 3427c23b892Sbalrog 3437c23b892Sbalrog static void 3447c23b892Sbalrog set_mdic(E1000State *s, int index, uint32_t val) 3457c23b892Sbalrog { 3467c23b892Sbalrog uint32_t data = val & E1000_MDIC_DATA_MASK; 3477c23b892Sbalrog uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); 3487c23b892Sbalrog 3497c23b892Sbalrog if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy # 3507c23b892Sbalrog val = s->mac_reg[MDIC] | E1000_MDIC_ERROR; 3517c23b892Sbalrog else if (val & E1000_MDIC_OP_READ) { 3527c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr); 3537c23b892Sbalrog if (!(phy_regcap[addr] & PHY_R)) { 3547c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr); 3557c23b892Sbalrog val |= E1000_MDIC_ERROR; 3567c23b892Sbalrog } else 3577c23b892Sbalrog val = (val ^ data) | s->phy_reg[addr]; 3587c23b892Sbalrog } else if (val & E1000_MDIC_OP_WRITE) { 3597c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data); 3607c23b892Sbalrog if (!(phy_regcap[addr] & PHY_W)) { 3617c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr); 3627c23b892Sbalrog val |= E1000_MDIC_ERROR; 363b9d03e35SJason Wang } else { 364b9d03e35SJason Wang if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) { 365b9d03e35SJason Wang phyreg_writeops[addr](s, index, data); 366b9d03e35SJason Wang } 3677c23b892Sbalrog s->phy_reg[addr] = data; 3687c23b892Sbalrog } 369b9d03e35SJason Wang } 3707c23b892Sbalrog s->mac_reg[MDIC] = val | E1000_MDIC_READY; 37117fbbb0bSJason Wang 37217fbbb0bSJason Wang if (val & E1000_MDIC_INT_EN) { 3737c23b892Sbalrog set_ics(s, 0, E1000_ICR_MDAC); 3747c23b892Sbalrog } 37517fbbb0bSJason Wang } 3767c23b892Sbalrog 3777c23b892Sbalrog static uint32_t 3787c23b892Sbalrog get_eecd(E1000State *s, int index) 3797c23b892Sbalrog { 3807c23b892Sbalrog uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd; 3817c23b892Sbalrog 3827c23b892Sbalrog DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n", 3837c23b892Sbalrog s->eecd_state.bitnum_out, s->eecd_state.reading); 3847c23b892Sbalrog if (!s->eecd_state.reading || 3857c23b892Sbalrog ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >> 3867c23b892Sbalrog ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1) 3877c23b892Sbalrog ret |= E1000_EECD_DO; 3887c23b892Sbalrog return ret; 3897c23b892Sbalrog } 3907c23b892Sbalrog 3917c23b892Sbalrog static void 3927c23b892Sbalrog set_eecd(E1000State *s, int index, uint32_t val) 3937c23b892Sbalrog { 3947c23b892Sbalrog uint32_t oldval = s->eecd_state.old_eecd; 3957c23b892Sbalrog 3967c23b892Sbalrog s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS | 3977c23b892Sbalrog E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ); 3989651ac55SIzumi Tsutsui if (!(E1000_EECD_CS & val)) // CS inactive; nothing to do 3999651ac55SIzumi Tsutsui return; 4009651ac55SIzumi Tsutsui if (E1000_EECD_CS & (val ^ oldval)) { // CS rise edge; reset state 4019651ac55SIzumi Tsutsui s->eecd_state.val_in = 0; 4029651ac55SIzumi Tsutsui s->eecd_state.bitnum_in = 0; 4039651ac55SIzumi Tsutsui s->eecd_state.bitnum_out = 0; 4049651ac55SIzumi Tsutsui s->eecd_state.reading = 0; 4059651ac55SIzumi Tsutsui } 4067c23b892Sbalrog if (!(E1000_EECD_SK & (val ^ oldval))) // no clock edge 4077c23b892Sbalrog return; 4087c23b892Sbalrog if (!(E1000_EECD_SK & val)) { // falling edge 4097c23b892Sbalrog s->eecd_state.bitnum_out++; 4107c23b892Sbalrog return; 4117c23b892Sbalrog } 4127c23b892Sbalrog s->eecd_state.val_in <<= 1; 4137c23b892Sbalrog if (val & E1000_EECD_DI) 4147c23b892Sbalrog s->eecd_state.val_in |= 1; 4157c23b892Sbalrog if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) { 4167c23b892Sbalrog s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1; 4177c23b892Sbalrog s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) == 4187c23b892Sbalrog EEPROM_READ_OPCODE_MICROWIRE); 4197c23b892Sbalrog } 4207c23b892Sbalrog DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n", 4217c23b892Sbalrog s->eecd_state.bitnum_in, s->eecd_state.bitnum_out, 4227c23b892Sbalrog s->eecd_state.reading); 4237c23b892Sbalrog } 4247c23b892Sbalrog 4257c23b892Sbalrog static uint32_t 4267c23b892Sbalrog flash_eerd_read(E1000State *s, int x) 4277c23b892Sbalrog { 4287c23b892Sbalrog unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START; 4297c23b892Sbalrog 430b1332393SBill Paul if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0) 431b1332393SBill Paul return (s->mac_reg[EERD]); 432b1332393SBill Paul 4337c23b892Sbalrog if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG) 434b1332393SBill Paul return (E1000_EEPROM_RW_REG_DONE | r); 435b1332393SBill Paul 436b1332393SBill Paul return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) | 437b1332393SBill Paul E1000_EEPROM_RW_REG_DONE | r); 4387c23b892Sbalrog } 4397c23b892Sbalrog 4407c23b892Sbalrog static void 4417c23b892Sbalrog putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse) 4427c23b892Sbalrog { 443c6a6a5e3Saliguori uint32_t sum; 444c6a6a5e3Saliguori 4457c23b892Sbalrog if (cse && cse < n) 4467c23b892Sbalrog n = cse + 1; 447c6a6a5e3Saliguori if (sloc < n-1) { 448c6a6a5e3Saliguori sum = net_checksum_add(n-css, data+css); 4497c23b892Sbalrog cpu_to_be16wu((uint16_t *)(data + sloc), 450c6a6a5e3Saliguori net_checksum_finish(sum)); 451c6a6a5e3Saliguori } 4527c23b892Sbalrog } 4537c23b892Sbalrog 4548f2e8d1fSaliguori static inline int 4558f2e8d1fSaliguori vlan_enabled(E1000State *s) 4568f2e8d1fSaliguori { 4578f2e8d1fSaliguori return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0); 4588f2e8d1fSaliguori } 4598f2e8d1fSaliguori 4608f2e8d1fSaliguori static inline int 4618f2e8d1fSaliguori vlan_rx_filter_enabled(E1000State *s) 4628f2e8d1fSaliguori { 4638f2e8d1fSaliguori return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0); 4648f2e8d1fSaliguori } 4658f2e8d1fSaliguori 4668f2e8d1fSaliguori static inline int 4678f2e8d1fSaliguori is_vlan_packet(E1000State *s, const uint8_t *buf) 4688f2e8d1fSaliguori { 4698f2e8d1fSaliguori return (be16_to_cpup((uint16_t *)(buf + 12)) == 4708f2e8d1fSaliguori le16_to_cpup((uint16_t *)(s->mac_reg + VET))); 4718f2e8d1fSaliguori } 4728f2e8d1fSaliguori 4738f2e8d1fSaliguori static inline int 4748f2e8d1fSaliguori is_vlan_txd(uint32_t txd_lower) 4758f2e8d1fSaliguori { 4768f2e8d1fSaliguori return ((txd_lower & E1000_TXD_CMD_VLE) != 0); 4778f2e8d1fSaliguori } 4788f2e8d1fSaliguori 47955e8d1ceSMichael S. Tsirkin /* FCS aka Ethernet CRC-32. We don't get it from backends and can't 48055e8d1ceSMichael S. Tsirkin * fill it in, just pad descriptor length by 4 bytes unless guest 481a05e8a6eSMichael S. Tsirkin * told us to strip it off the packet. */ 48255e8d1ceSMichael S. Tsirkin static inline int 48355e8d1ceSMichael S. Tsirkin fcs_len(E1000State *s) 48455e8d1ceSMichael S. Tsirkin { 48555e8d1ceSMichael S. Tsirkin return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4; 48655e8d1ceSMichael S. Tsirkin } 48755e8d1ceSMichael S. Tsirkin 4887c23b892Sbalrog static void 48993e37d76SJason Wang e1000_send_packet(E1000State *s, const uint8_t *buf, int size) 49093e37d76SJason Wang { 491b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 49293e37d76SJason Wang if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) { 493b356f76dSJason Wang nc->info->receive(nc, buf, size); 49493e37d76SJason Wang } else { 495b356f76dSJason Wang qemu_send_packet(nc, buf, size); 49693e37d76SJason Wang } 49793e37d76SJason Wang } 49893e37d76SJason Wang 49993e37d76SJason Wang static void 5007c23b892Sbalrog xmit_seg(E1000State *s) 5017c23b892Sbalrog { 5027c23b892Sbalrog uint16_t len, *sp; 5037c23b892Sbalrog unsigned int frames = s->tx.tso_frames, css, sofar, n; 5047c23b892Sbalrog struct e1000_tx *tp = &s->tx; 5057c23b892Sbalrog 5061b0009dbSbalrog if (tp->tse && tp->cptse) { 5077c23b892Sbalrog css = tp->ipcss; 5087c23b892Sbalrog DBGOUT(TXSUM, "frames %d size %d ipcss %d\n", 5097c23b892Sbalrog frames, tp->size, css); 5107c23b892Sbalrog if (tp->ip) { // IPv4 5117c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+2), 5127c23b892Sbalrog tp->size - css); 5137c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), 5147c23b892Sbalrog be16_to_cpup((uint16_t *)(tp->data+css+4))+frames); 5157c23b892Sbalrog } else // IPv6 5167c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), 5177c23b892Sbalrog tp->size - css); 5187c23b892Sbalrog css = tp->tucss; 5197c23b892Sbalrog len = tp->size - css; 5207c23b892Sbalrog DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len); 5217c23b892Sbalrog if (tp->tcp) { 5227c23b892Sbalrog sofar = frames * tp->mss; 5237c23b892Sbalrog cpu_to_be32wu((uint32_t *)(tp->data+css+4), // seq 52488738c09Saurel32 be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar); 5257c23b892Sbalrog if (tp->paylen - sofar > tp->mss) 5267c23b892Sbalrog tp->data[css + 13] &= ~9; // PSH, FIN 5277c23b892Sbalrog } else // UDP 5287c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), len); 5297c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { 530e685b4ebSAlex Williamson unsigned int phsum; 5317c23b892Sbalrog // add pseudo-header length before checksum calculation 5327c23b892Sbalrog sp = (uint16_t *)(tp->data + tp->tucso); 533e685b4ebSAlex Williamson phsum = be16_to_cpup(sp) + len; 534e685b4ebSAlex Williamson phsum = (phsum >> 16) + (phsum & 0xffff); 535e685b4ebSAlex Williamson cpu_to_be16wu(sp, phsum); 5367c23b892Sbalrog } 5377c23b892Sbalrog tp->tso_frames++; 5387c23b892Sbalrog } 5397c23b892Sbalrog 5407c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_TXSM) 5417c23b892Sbalrog putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse); 5427c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_IXSM) 5437c23b892Sbalrog putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse); 5448f2e8d1fSaliguori if (tp->vlan_needed) { 545b10fec9bSStefan Weil memmove(tp->vlan, tp->data, 4); 546b10fec9bSStefan Weil memmove(tp->data, tp->data + 4, 8); 5478f2e8d1fSaliguori memcpy(tp->data + 8, tp->vlan_header, 4); 54893e37d76SJason Wang e1000_send_packet(s, tp->vlan, tp->size + 4); 5498f2e8d1fSaliguori } else 55093e37d76SJason Wang e1000_send_packet(s, tp->data, tp->size); 5517c23b892Sbalrog s->mac_reg[TPT]++; 5527c23b892Sbalrog s->mac_reg[GPTC]++; 5537c23b892Sbalrog n = s->mac_reg[TOTL]; 5547c23b892Sbalrog if ((s->mac_reg[TOTL] += s->tx.size) < n) 5557c23b892Sbalrog s->mac_reg[TOTH]++; 5567c23b892Sbalrog } 5577c23b892Sbalrog 5587c23b892Sbalrog static void 5597c23b892Sbalrog process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) 5607c23b892Sbalrog { 5617c23b892Sbalrog uint32_t txd_lower = le32_to_cpu(dp->lower.data); 5627c23b892Sbalrog uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); 5637c23b892Sbalrog unsigned int split_size = txd_lower & 0xffff, bytes, sz, op; 564a0ae17a6SAndrew Jones unsigned int msh = 0xfffff; 5657c23b892Sbalrog uint64_t addr; 5667c23b892Sbalrog struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; 5677c23b892Sbalrog struct e1000_tx *tp = &s->tx; 5687c23b892Sbalrog 5697c23b892Sbalrog if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor 5707c23b892Sbalrog op = le32_to_cpu(xp->cmd_and_length); 5717c23b892Sbalrog tp->ipcss = xp->lower_setup.ip_fields.ipcss; 5727c23b892Sbalrog tp->ipcso = xp->lower_setup.ip_fields.ipcso; 5737c23b892Sbalrog tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse); 5747c23b892Sbalrog tp->tucss = xp->upper_setup.tcp_fields.tucss; 5757c23b892Sbalrog tp->tucso = xp->upper_setup.tcp_fields.tucso; 5767c23b892Sbalrog tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse); 5777c23b892Sbalrog tp->paylen = op & 0xfffff; 5787c23b892Sbalrog tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len; 5797c23b892Sbalrog tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss); 5807c23b892Sbalrog tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0; 5817c23b892Sbalrog tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0; 5827c23b892Sbalrog tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0; 5837c23b892Sbalrog tp->tso_frames = 0; 5847c23b892Sbalrog if (tp->tucso == 0) { // this is probably wrong 5857c23b892Sbalrog DBGOUT(TXSUM, "TCP/UDP: cso 0!\n"); 5867c23b892Sbalrog tp->tucso = tp->tucss + (tp->tcp ? 16 : 6); 5877c23b892Sbalrog } 5887c23b892Sbalrog return; 5891b0009dbSbalrog } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { 5901b0009dbSbalrog // data descriptor 591735e77ecSStefan Hajnoczi if (tp->size == 0) { 5927c23b892Sbalrog tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8; 593735e77ecSStefan Hajnoczi } 5941b0009dbSbalrog tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0; 59543ad7e3eSJes Sorensen } else { 5961b0009dbSbalrog // legacy descriptor 5971b0009dbSbalrog tp->cptse = 0; 59843ad7e3eSJes Sorensen } 5997c23b892Sbalrog 6008f2e8d1fSaliguori if (vlan_enabled(s) && is_vlan_txd(txd_lower) && 6018f2e8d1fSaliguori (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) { 6028f2e8d1fSaliguori tp->vlan_needed = 1; 6038f2e8d1fSaliguori cpu_to_be16wu((uint16_t *)(tp->vlan_header), 6048f2e8d1fSaliguori le16_to_cpup((uint16_t *)(s->mac_reg + VET))); 6058f2e8d1fSaliguori cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2), 6068f2e8d1fSaliguori le16_to_cpu(dp->upper.fields.special)); 6078f2e8d1fSaliguori } 6088f2e8d1fSaliguori 6097c23b892Sbalrog addr = le64_to_cpu(dp->buffer_addr); 6101b0009dbSbalrog if (tp->tse && tp->cptse) { 611a0ae17a6SAndrew Jones msh = tp->hdr_len + tp->mss; 6127c23b892Sbalrog do { 6137c23b892Sbalrog bytes = split_size; 6147c23b892Sbalrog if (tp->size + bytes > msh) 6157c23b892Sbalrog bytes = msh - tp->size; 61665f82df0SAnthony Liguori 61765f82df0SAnthony Liguori bytes = MIN(sizeof(tp->data) - tp->size, bytes); 61862ecbd35SEduard - Gabriel Munteanu pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes); 619a0ae17a6SAndrew Jones sz = tp->size + bytes; 620a0ae17a6SAndrew Jones if (sz >= tp->hdr_len && tp->size < tp->hdr_len) { 621a0ae17a6SAndrew Jones memmove(tp->header, tp->data, tp->hdr_len); 622a0ae17a6SAndrew Jones } 6237c23b892Sbalrog tp->size = sz; 6247c23b892Sbalrog addr += bytes; 6257c23b892Sbalrog if (sz == msh) { 6267c23b892Sbalrog xmit_seg(s); 627a0ae17a6SAndrew Jones memmove(tp->data, tp->header, tp->hdr_len); 628a0ae17a6SAndrew Jones tp->size = tp->hdr_len; 6297c23b892Sbalrog } 6307c23b892Sbalrog } while (split_size -= bytes); 6311b0009dbSbalrog } else if (!tp->tse && tp->cptse) { 6321b0009dbSbalrog // context descriptor TSE is not set, while data descriptor TSE is set 633362f5fb5SStefan Weil DBGOUT(TXERR, "TCP segmentation error\n"); 6341b0009dbSbalrog } else { 63565f82df0SAnthony Liguori split_size = MIN(sizeof(tp->data) - tp->size, split_size); 63662ecbd35SEduard - Gabriel Munteanu pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size); 6371b0009dbSbalrog tp->size += split_size; 6381b0009dbSbalrog } 6397c23b892Sbalrog 6407c23b892Sbalrog if (!(txd_lower & E1000_TXD_CMD_EOP)) 6417c23b892Sbalrog return; 642a0ae17a6SAndrew Jones if (!(tp->tse && tp->cptse && tp->size < tp->hdr_len)) { 6437c23b892Sbalrog xmit_seg(s); 644a0ae17a6SAndrew Jones } 6457c23b892Sbalrog tp->tso_frames = 0; 6467c23b892Sbalrog tp->sum_needed = 0; 6478f2e8d1fSaliguori tp->vlan_needed = 0; 6487c23b892Sbalrog tp->size = 0; 6491b0009dbSbalrog tp->cptse = 0; 6507c23b892Sbalrog } 6517c23b892Sbalrog 6527c23b892Sbalrog static uint32_t 65362ecbd35SEduard - Gabriel Munteanu txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp) 6547c23b892Sbalrog { 6557c23b892Sbalrog uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data); 6567c23b892Sbalrog 6577c23b892Sbalrog if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS))) 6587c23b892Sbalrog return 0; 6597c23b892Sbalrog txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) & 6607c23b892Sbalrog ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU); 6617c23b892Sbalrog dp->upper.data = cpu_to_le32(txd_upper); 66262ecbd35SEduard - Gabriel Munteanu pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp), 66300c3a05bSDavid Gibson &dp->upper, sizeof(dp->upper)); 6647c23b892Sbalrog return E1000_ICR_TXDW; 6657c23b892Sbalrog } 6667c23b892Sbalrog 667d17161f6SKevin Wolf static uint64_t tx_desc_base(E1000State *s) 668d17161f6SKevin Wolf { 669d17161f6SKevin Wolf uint64_t bah = s->mac_reg[TDBAH]; 670d17161f6SKevin Wolf uint64_t bal = s->mac_reg[TDBAL] & ~0xf; 671d17161f6SKevin Wolf 672d17161f6SKevin Wolf return (bah << 32) + bal; 673d17161f6SKevin Wolf } 674d17161f6SKevin Wolf 6757c23b892Sbalrog static void 6767c23b892Sbalrog start_xmit(E1000State *s) 6777c23b892Sbalrog { 67862ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 6797c23b892Sbalrog struct e1000_tx_desc desc; 6807c23b892Sbalrog uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE; 6817c23b892Sbalrog 6827c23b892Sbalrog if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) { 6837c23b892Sbalrog DBGOUT(TX, "tx disabled\n"); 6847c23b892Sbalrog return; 6857c23b892Sbalrog } 6867c23b892Sbalrog 6877c23b892Sbalrog while (s->mac_reg[TDH] != s->mac_reg[TDT]) { 688d17161f6SKevin Wolf base = tx_desc_base(s) + 6897c23b892Sbalrog sizeof(struct e1000_tx_desc) * s->mac_reg[TDH]; 69000c3a05bSDavid Gibson pci_dma_read(&s->dev, base, &desc, sizeof(desc)); 6917c23b892Sbalrog 6927c23b892Sbalrog DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH], 6936106075bSths (void *)(intptr_t)desc.buffer_addr, desc.lower.data, 6947c23b892Sbalrog desc.upper.data); 6957c23b892Sbalrog 6967c23b892Sbalrog process_tx_desc(s, &desc); 69762ecbd35SEduard - Gabriel Munteanu cause |= txdesc_writeback(s, base, &desc); 6987c23b892Sbalrog 6997c23b892Sbalrog if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN]) 7007c23b892Sbalrog s->mac_reg[TDH] = 0; 7017c23b892Sbalrog /* 7027c23b892Sbalrog * the following could happen only if guest sw assigns 7037c23b892Sbalrog * bogus values to TDT/TDLEN. 7047c23b892Sbalrog * there's nothing too intelligent we could do about this. 7057c23b892Sbalrog */ 7067c23b892Sbalrog if (s->mac_reg[TDH] == tdh_start) { 7077c23b892Sbalrog DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", 7087c23b892Sbalrog tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); 7097c23b892Sbalrog break; 7107c23b892Sbalrog } 7117c23b892Sbalrog } 7127c23b892Sbalrog set_ics(s, 0, cause); 7137c23b892Sbalrog } 7147c23b892Sbalrog 7157c23b892Sbalrog static int 7167c23b892Sbalrog receive_filter(E1000State *s, const uint8_t *buf, int size) 7177c23b892Sbalrog { 718af2960f9SBlue Swirl static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 719af2960f9SBlue Swirl static const int mta_shift[] = {4, 3, 2, 0}; 7207c23b892Sbalrog uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp; 7217c23b892Sbalrog 7228f2e8d1fSaliguori if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) { 7238f2e8d1fSaliguori uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14)); 7248f2e8d1fSaliguori uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) + 7258f2e8d1fSaliguori ((vid >> 5) & 0x7f)); 7268f2e8d1fSaliguori if ((vfta & (1 << (vid & 0x1f))) == 0) 7278f2e8d1fSaliguori return 0; 7288f2e8d1fSaliguori } 7298f2e8d1fSaliguori 7307c23b892Sbalrog if (rctl & E1000_RCTL_UPE) // promiscuous 7317c23b892Sbalrog return 1; 7327c23b892Sbalrog 7337c23b892Sbalrog if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast 7347c23b892Sbalrog return 1; 7357c23b892Sbalrog 7367c23b892Sbalrog if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast)) 7377c23b892Sbalrog return 1; 7387c23b892Sbalrog 7397c23b892Sbalrog for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) { 7407c23b892Sbalrog if (!(rp[1] & E1000_RAH_AV)) 7417c23b892Sbalrog continue; 7427c23b892Sbalrog ra[0] = cpu_to_le32(rp[0]); 7437c23b892Sbalrog ra[1] = cpu_to_le32(rp[1]); 7447c23b892Sbalrog if (!memcmp(buf, (uint8_t *)ra, 6)) { 7457c23b892Sbalrog DBGOUT(RXFILTER, 7467c23b892Sbalrog "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n", 7477c23b892Sbalrog (int)(rp - s->mac_reg - RA)/2, 7487c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 7497c23b892Sbalrog return 1; 7507c23b892Sbalrog } 7517c23b892Sbalrog } 7527c23b892Sbalrog DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n", 7537c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 7547c23b892Sbalrog 7557c23b892Sbalrog f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3]; 7567c23b892Sbalrog f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff; 7577c23b892Sbalrog if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f))) 7587c23b892Sbalrog return 1; 7597c23b892Sbalrog DBGOUT(RXFILTER, 7607c23b892Sbalrog "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n", 7617c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 7627c23b892Sbalrog (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5, 7637c23b892Sbalrog s->mac_reg[MTA + (f >> 5)]); 7647c23b892Sbalrog 7657c23b892Sbalrog return 0; 7667c23b892Sbalrog } 7677c23b892Sbalrog 76899ed7e30Saliguori static void 7694e68f7a0SStefan Hajnoczi e1000_set_link_status(NetClientState *nc) 77099ed7e30Saliguori { 771cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 77299ed7e30Saliguori uint32_t old_status = s->mac_reg[STATUS]; 77399ed7e30Saliguori 774d4044c2aSBjørn Mork if (nc->link_down) { 77571aadd3cSJason Wang e1000_link_down(s); 776d4044c2aSBjørn Mork } else { 77771aadd3cSJason Wang e1000_link_up(s); 778d4044c2aSBjørn Mork } 77999ed7e30Saliguori 78099ed7e30Saliguori if (s->mac_reg[STATUS] != old_status) 78199ed7e30Saliguori set_ics(s, 0, E1000_ICR_LSC); 78299ed7e30Saliguori } 78399ed7e30Saliguori 784322fd48aSMichael S. Tsirkin static bool e1000_has_rxbufs(E1000State *s, size_t total_size) 785322fd48aSMichael S. Tsirkin { 786322fd48aSMichael S. Tsirkin int bufs; 787322fd48aSMichael S. Tsirkin /* Fast-path short packets */ 788322fd48aSMichael S. Tsirkin if (total_size <= s->rxbuf_size) { 789e5b8b0d4SDmitry Fleytman return s->mac_reg[RDH] != s->mac_reg[RDT]; 790322fd48aSMichael S. Tsirkin } 791322fd48aSMichael S. Tsirkin if (s->mac_reg[RDH] < s->mac_reg[RDT]) { 792322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDT] - s->mac_reg[RDH]; 793e5b8b0d4SDmitry Fleytman } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) { 794322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + 795322fd48aSMichael S. Tsirkin s->mac_reg[RDT] - s->mac_reg[RDH]; 796322fd48aSMichael S. Tsirkin } else { 797322fd48aSMichael S. Tsirkin return false; 798322fd48aSMichael S. Tsirkin } 799322fd48aSMichael S. Tsirkin return total_size <= bufs * s->rxbuf_size; 800322fd48aSMichael S. Tsirkin } 801322fd48aSMichael S. Tsirkin 8026cdfab28SMichael S. Tsirkin static int 8034e68f7a0SStefan Hajnoczi e1000_can_receive(NetClientState *nc) 8046cdfab28SMichael S. Tsirkin { 805cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 8066cdfab28SMichael S. Tsirkin 807ddcb73b7SMichael S. Tsirkin return (s->mac_reg[STATUS] & E1000_STATUS_LU) && 808ddcb73b7SMichael S. Tsirkin (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1); 8096cdfab28SMichael S. Tsirkin } 8106cdfab28SMichael S. Tsirkin 811d17161f6SKevin Wolf static uint64_t rx_desc_base(E1000State *s) 812d17161f6SKevin Wolf { 813d17161f6SKevin Wolf uint64_t bah = s->mac_reg[RDBAH]; 814d17161f6SKevin Wolf uint64_t bal = s->mac_reg[RDBAL] & ~0xf; 815d17161f6SKevin Wolf 816d17161f6SKevin Wolf return (bah << 32) + bal; 817d17161f6SKevin Wolf } 818d17161f6SKevin Wolf 8194f1c942bSMark McLoughlin static ssize_t 8204e68f7a0SStefan Hajnoczi e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) 8217c23b892Sbalrog { 822cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 8237c23b892Sbalrog struct e1000_rx_desc desc; 82462ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 8257c23b892Sbalrog unsigned int n, rdt; 8267c23b892Sbalrog uint32_t rdh_start; 8278f2e8d1fSaliguori uint16_t vlan_special = 0; 8288f2e8d1fSaliguori uint8_t vlan_status = 0, vlan_offset = 0; 82978aeb23eSStefan Hajnoczi uint8_t min_buf[MIN_BUF_SIZE]; 830b19487e2SMichael S. Tsirkin size_t desc_offset; 831b19487e2SMichael S. Tsirkin size_t desc_size; 832b19487e2SMichael S. Tsirkin size_t total_size; 8337c23b892Sbalrog 834ddcb73b7SMichael S. Tsirkin if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) { 8354f1c942bSMark McLoughlin return -1; 836ddcb73b7SMichael S. Tsirkin } 837ddcb73b7SMichael S. Tsirkin 838ddcb73b7SMichael S. Tsirkin if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) { 839ddcb73b7SMichael S. Tsirkin return -1; 840ddcb73b7SMichael S. Tsirkin } 8417c23b892Sbalrog 84278aeb23eSStefan Hajnoczi /* Pad to minimum Ethernet frame length */ 84378aeb23eSStefan Hajnoczi if (size < sizeof(min_buf)) { 84478aeb23eSStefan Hajnoczi memcpy(min_buf, buf, size); 84578aeb23eSStefan Hajnoczi memset(&min_buf[size], 0, sizeof(min_buf) - size); 84678aeb23eSStefan Hajnoczi buf = min_buf; 84778aeb23eSStefan Hajnoczi size = sizeof(min_buf); 84878aeb23eSStefan Hajnoczi } 84978aeb23eSStefan Hajnoczi 850b0d9ffcdSMichael Contreras /* Discard oversized packets if !LPE and !SBP. */ 8512c0331f4SMichael Contreras if ((size > MAXIMUM_ETHERNET_LPE_SIZE || 8522c0331f4SMichael Contreras (size > MAXIMUM_ETHERNET_VLAN_SIZE 8532c0331f4SMichael Contreras && !(s->mac_reg[RCTL] & E1000_RCTL_LPE))) 854b0d9ffcdSMichael Contreras && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) { 855b0d9ffcdSMichael Contreras return size; 856b0d9ffcdSMichael Contreras } 857b0d9ffcdSMichael Contreras 8587c23b892Sbalrog if (!receive_filter(s, buf, size)) 8594f1c942bSMark McLoughlin return size; 8607c23b892Sbalrog 8618f2e8d1fSaliguori if (vlan_enabled(s) && is_vlan_packet(s, buf)) { 8628f2e8d1fSaliguori vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14))); 86398835fe3SThomas Monjalon memmove((uint8_t *)buf + 4, buf, 12); 8648f2e8d1fSaliguori vlan_status = E1000_RXD_STAT_VP; 8658f2e8d1fSaliguori vlan_offset = 4; 8668f2e8d1fSaliguori size -= 4; 8678f2e8d1fSaliguori } 8688f2e8d1fSaliguori 8697c23b892Sbalrog rdh_start = s->mac_reg[RDH]; 870b19487e2SMichael S. Tsirkin desc_offset = 0; 871b19487e2SMichael S. Tsirkin total_size = size + fcs_len(s); 872322fd48aSMichael S. Tsirkin if (!e1000_has_rxbufs(s, total_size)) { 873322fd48aSMichael S. Tsirkin set_ics(s, 0, E1000_ICS_RXO); 874322fd48aSMichael S. Tsirkin return -1; 875322fd48aSMichael S. Tsirkin } 8767c23b892Sbalrog do { 877b19487e2SMichael S. Tsirkin desc_size = total_size - desc_offset; 878b19487e2SMichael S. Tsirkin if (desc_size > s->rxbuf_size) { 879b19487e2SMichael S. Tsirkin desc_size = s->rxbuf_size; 880b19487e2SMichael S. Tsirkin } 881d17161f6SKevin Wolf base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH]; 88200c3a05bSDavid Gibson pci_dma_read(&s->dev, base, &desc, sizeof(desc)); 8838f2e8d1fSaliguori desc.special = vlan_special; 8848f2e8d1fSaliguori desc.status |= (vlan_status | E1000_RXD_STAT_DD); 8857c23b892Sbalrog if (desc.buffer_addr) { 886b19487e2SMichael S. Tsirkin if (desc_offset < size) { 887b19487e2SMichael S. Tsirkin size_t copy_size = size - desc_offset; 888b19487e2SMichael S. Tsirkin if (copy_size > s->rxbuf_size) { 889b19487e2SMichael S. Tsirkin copy_size = s->rxbuf_size; 890b19487e2SMichael S. Tsirkin } 89162ecbd35SEduard - Gabriel Munteanu pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr), 89200c3a05bSDavid Gibson buf + desc_offset + vlan_offset, copy_size); 893b19487e2SMichael S. Tsirkin } 894b19487e2SMichael S. Tsirkin desc_offset += desc_size; 895b19487e2SMichael S. Tsirkin desc.length = cpu_to_le16(desc_size); 896ee912ccfSMichael S. Tsirkin if (desc_offset >= total_size) { 8977c23b892Sbalrog desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM; 898b19487e2SMichael S. Tsirkin } else { 899ee912ccfSMichael S. Tsirkin /* Guest zeroing out status is not a hardware requirement. 900ee912ccfSMichael S. Tsirkin Clear EOP in case guest didn't do it. */ 901ee912ccfSMichael S. Tsirkin desc.status &= ~E1000_RXD_STAT_EOP; 902b19487e2SMichael S. Tsirkin } 90343ad7e3eSJes Sorensen } else { // as per intel docs; skip descriptors with null buf addr 9047c23b892Sbalrog DBGOUT(RX, "Null RX descriptor!!\n"); 90543ad7e3eSJes Sorensen } 90600c3a05bSDavid Gibson pci_dma_write(&s->dev, base, &desc, sizeof(desc)); 9077c23b892Sbalrog 9087c23b892Sbalrog if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) 9097c23b892Sbalrog s->mac_reg[RDH] = 0; 9107c23b892Sbalrog /* see comment in start_xmit; same here */ 9117c23b892Sbalrog if (s->mac_reg[RDH] == rdh_start) { 9127c23b892Sbalrog DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", 9137c23b892Sbalrog rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); 9147c23b892Sbalrog set_ics(s, 0, E1000_ICS_RXO); 9154f1c942bSMark McLoughlin return -1; 9167c23b892Sbalrog } 917b19487e2SMichael S. Tsirkin } while (desc_offset < total_size); 9187c23b892Sbalrog 9197c23b892Sbalrog s->mac_reg[GPRC]++; 9207c23b892Sbalrog s->mac_reg[TPR]++; 921a05e8a6eSMichael S. Tsirkin /* TOR - Total Octets Received: 922a05e8a6eSMichael S. Tsirkin * This register includes bytes received in a packet from the <Destination 923a05e8a6eSMichael S. Tsirkin * Address> field through the <CRC> field, inclusively. 924a05e8a6eSMichael S. Tsirkin */ 925a05e8a6eSMichael S. Tsirkin n = s->mac_reg[TORL] + size + /* Always include FCS length. */ 4; 926a05e8a6eSMichael S. Tsirkin if (n < s->mac_reg[TORL]) 9277c23b892Sbalrog s->mac_reg[TORH]++; 928a05e8a6eSMichael S. Tsirkin s->mac_reg[TORL] = n; 9297c23b892Sbalrog 9307c23b892Sbalrog n = E1000_ICS_RXT0; 9317c23b892Sbalrog if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH]) 9327c23b892Sbalrog rdt += s->mac_reg[RDLEN] / sizeof(desc); 933bf16cc8fSaliguori if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >> 934bf16cc8fSaliguori s->rxbuf_min_shift) 9357c23b892Sbalrog n |= E1000_ICS_RXDMT0; 9367c23b892Sbalrog 9377c23b892Sbalrog set_ics(s, 0, n); 9384f1c942bSMark McLoughlin 9394f1c942bSMark McLoughlin return size; 9407c23b892Sbalrog } 9417c23b892Sbalrog 9427c23b892Sbalrog static uint32_t 9437c23b892Sbalrog mac_readreg(E1000State *s, int index) 9447c23b892Sbalrog { 9457c23b892Sbalrog return s->mac_reg[index]; 9467c23b892Sbalrog } 9477c23b892Sbalrog 9487c23b892Sbalrog static uint32_t 9497c23b892Sbalrog mac_icr_read(E1000State *s, int index) 9507c23b892Sbalrog { 9517c23b892Sbalrog uint32_t ret = s->mac_reg[ICR]; 9527c23b892Sbalrog 9537c23b892Sbalrog DBGOUT(INTERRUPT, "ICR read: %x\n", ret); 9547c23b892Sbalrog set_interrupt_cause(s, 0, 0); 9557c23b892Sbalrog return ret; 9567c23b892Sbalrog } 9577c23b892Sbalrog 9587c23b892Sbalrog static uint32_t 9597c23b892Sbalrog mac_read_clr4(E1000State *s, int index) 9607c23b892Sbalrog { 9617c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 9627c23b892Sbalrog 9637c23b892Sbalrog s->mac_reg[index] = 0; 9647c23b892Sbalrog return ret; 9657c23b892Sbalrog } 9667c23b892Sbalrog 9677c23b892Sbalrog static uint32_t 9687c23b892Sbalrog mac_read_clr8(E1000State *s, int index) 9697c23b892Sbalrog { 9707c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 9717c23b892Sbalrog 9727c23b892Sbalrog s->mac_reg[index] = 0; 9737c23b892Sbalrog s->mac_reg[index-1] = 0; 9747c23b892Sbalrog return ret; 9757c23b892Sbalrog } 9767c23b892Sbalrog 9777c23b892Sbalrog static void 9787c23b892Sbalrog mac_writereg(E1000State *s, int index, uint32_t val) 9797c23b892Sbalrog { 9807c23b892Sbalrog s->mac_reg[index] = val; 9817c23b892Sbalrog } 9827c23b892Sbalrog 9837c23b892Sbalrog static void 9847c23b892Sbalrog set_rdt(E1000State *s, int index, uint32_t val) 9857c23b892Sbalrog { 9867c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 987e8b4c680SPaolo Bonzini if (e1000_has_rxbufs(s, 1)) { 988b356f76dSJason Wang qemu_flush_queued_packets(qemu_get_queue(s->nic)); 989e8b4c680SPaolo Bonzini } 9907c23b892Sbalrog } 9917c23b892Sbalrog 9927c23b892Sbalrog static void 9937c23b892Sbalrog set_16bit(E1000State *s, int index, uint32_t val) 9947c23b892Sbalrog { 9957c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 9967c23b892Sbalrog } 9977c23b892Sbalrog 9987c23b892Sbalrog static void 9997c23b892Sbalrog set_dlen(E1000State *s, int index, uint32_t val) 10007c23b892Sbalrog { 10017c23b892Sbalrog s->mac_reg[index] = val & 0xfff80; 10027c23b892Sbalrog } 10037c23b892Sbalrog 10047c23b892Sbalrog static void 10057c23b892Sbalrog set_tctl(E1000State *s, int index, uint32_t val) 10067c23b892Sbalrog { 10077c23b892Sbalrog s->mac_reg[index] = val; 10087c23b892Sbalrog s->mac_reg[TDT] &= 0xffff; 10097c23b892Sbalrog start_xmit(s); 10107c23b892Sbalrog } 10117c23b892Sbalrog 10127c23b892Sbalrog static void 10137c23b892Sbalrog set_icr(E1000State *s, int index, uint32_t val) 10147c23b892Sbalrog { 10157c23b892Sbalrog DBGOUT(INTERRUPT, "set_icr %x\n", val); 10167c23b892Sbalrog set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val); 10177c23b892Sbalrog } 10187c23b892Sbalrog 10197c23b892Sbalrog static void 10207c23b892Sbalrog set_imc(E1000State *s, int index, uint32_t val) 10217c23b892Sbalrog { 10227c23b892Sbalrog s->mac_reg[IMS] &= ~val; 10237c23b892Sbalrog set_ics(s, 0, 0); 10247c23b892Sbalrog } 10257c23b892Sbalrog 10267c23b892Sbalrog static void 10277c23b892Sbalrog set_ims(E1000State *s, int index, uint32_t val) 10287c23b892Sbalrog { 10297c23b892Sbalrog s->mac_reg[IMS] |= val; 10307c23b892Sbalrog set_ics(s, 0, 0); 10317c23b892Sbalrog } 10327c23b892Sbalrog 10337c23b892Sbalrog #define getreg(x) [x] = mac_readreg 10347c23b892Sbalrog static uint32_t (*macreg_readops[])(E1000State *, int) = { 10357c23b892Sbalrog getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL), 10367c23b892Sbalrog getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL), 10377c23b892Sbalrog getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS), 10387c23b892Sbalrog getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL), 1039b1332393SBill Paul getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS), 1040a00b2335SKay Ackermann getreg(TDBAL), getreg(TDBAH), getreg(RDBAH), getreg(RDBAL), 1041a00b2335SKay Ackermann getreg(TDLEN), getreg(RDLEN), 10427c23b892Sbalrog 10437c23b892Sbalrog [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4, 10447c23b892Sbalrog [GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4, 10457c23b892Sbalrog [ICR] = mac_icr_read, [EECD] = get_eecd, [EERD] = flash_eerd_read, 10467c23b892Sbalrog [CRCERRS ... MPC] = &mac_readreg, 10477c23b892Sbalrog [RA ... RA+31] = &mac_readreg, 10487c23b892Sbalrog [MTA ... MTA+127] = &mac_readreg, 10498f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_readreg, 10507c23b892Sbalrog }; 1051b1503cdaSmalc enum { NREADOPS = ARRAY_SIZE(macreg_readops) }; 10527c23b892Sbalrog 10537c23b892Sbalrog #define putreg(x) [x] = mac_writereg 10547c23b892Sbalrog static void (*macreg_writeops[])(E1000State *, int, uint32_t) = { 10557c23b892Sbalrog putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC), 10567c23b892Sbalrog putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH), 1057cab3c825SKevin Wolf putreg(RDBAL), putreg(LEDCTL), putreg(VET), 10587c23b892Sbalrog [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl, 10597c23b892Sbalrog [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics, 10607c23b892Sbalrog [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt, 10617c23b892Sbalrog [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr, 1062cab3c825SKevin Wolf [EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl, 10637c23b892Sbalrog [RA ... RA+31] = &mac_writereg, 10647c23b892Sbalrog [MTA ... MTA+127] = &mac_writereg, 10658f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_writereg, 10667c23b892Sbalrog }; 1067b9d03e35SJason Wang 1068b1503cdaSmalc enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; 10697c23b892Sbalrog 10707c23b892Sbalrog static void 1071a8170e5eSAvi Kivity e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val, 1072ad00a9b9SAvi Kivity unsigned size) 10737c23b892Sbalrog { 10747c23b892Sbalrog E1000State *s = opaque; 10758da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 10767c23b892Sbalrog 107743ad7e3eSJes Sorensen if (index < NWRITEOPS && macreg_writeops[index]) { 10786b59fc74Saurel32 macreg_writeops[index](s, index, val); 107943ad7e3eSJes Sorensen } else if (index < NREADOPS && macreg_readops[index]) { 1080ad00a9b9SAvi Kivity DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val); 108143ad7e3eSJes Sorensen } else { 1082ad00a9b9SAvi Kivity DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n", 10837c23b892Sbalrog index<<2, val); 10847c23b892Sbalrog } 108543ad7e3eSJes Sorensen } 10867c23b892Sbalrog 1087ad00a9b9SAvi Kivity static uint64_t 1088a8170e5eSAvi Kivity e1000_mmio_read(void *opaque, hwaddr addr, unsigned size) 10897c23b892Sbalrog { 10907c23b892Sbalrog E1000State *s = opaque; 10918da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 10927c23b892Sbalrog 10937c23b892Sbalrog if (index < NREADOPS && macreg_readops[index]) 10946b59fc74Saurel32 { 109532600a30SAlexander Graf return macreg_readops[index](s, index); 10966b59fc74Saurel32 } 10977c23b892Sbalrog DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2); 10987c23b892Sbalrog return 0; 10997c23b892Sbalrog } 11007c23b892Sbalrog 1101ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_mmio_ops = { 1102ad00a9b9SAvi Kivity .read = e1000_mmio_read, 1103ad00a9b9SAvi Kivity .write = e1000_mmio_write, 1104ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1105ad00a9b9SAvi Kivity .impl = { 1106ad00a9b9SAvi Kivity .min_access_size = 4, 1107ad00a9b9SAvi Kivity .max_access_size = 4, 1108ad00a9b9SAvi Kivity }, 1109ad00a9b9SAvi Kivity }; 1110ad00a9b9SAvi Kivity 1111a8170e5eSAvi Kivity static uint64_t e1000_io_read(void *opaque, hwaddr addr, 1112ad00a9b9SAvi Kivity unsigned size) 11137c23b892Sbalrog { 1114ad00a9b9SAvi Kivity E1000State *s = opaque; 1115ad00a9b9SAvi Kivity 1116ad00a9b9SAvi Kivity (void)s; 1117ad00a9b9SAvi Kivity return 0; 11187c23b892Sbalrog } 11197c23b892Sbalrog 1120a8170e5eSAvi Kivity static void e1000_io_write(void *opaque, hwaddr addr, 1121ad00a9b9SAvi Kivity uint64_t val, unsigned size) 11227c23b892Sbalrog { 1123ad00a9b9SAvi Kivity E1000State *s = opaque; 1124ad00a9b9SAvi Kivity 1125ad00a9b9SAvi Kivity (void)s; 11267c23b892Sbalrog } 11277c23b892Sbalrog 1128ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_io_ops = { 1129ad00a9b9SAvi Kivity .read = e1000_io_read, 1130ad00a9b9SAvi Kivity .write = e1000_io_write, 1131ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1132ad00a9b9SAvi Kivity }; 1133ad00a9b9SAvi Kivity 1134e482dc3eSJuan Quintela static bool is_version_1(void *opaque, int version_id) 11357c23b892Sbalrog { 1136e482dc3eSJuan Quintela return version_id == 1; 11377c23b892Sbalrog } 11387c23b892Sbalrog 1139ddcb73b7SMichael S. Tsirkin static void e1000_pre_save(void *opaque) 1140ddcb73b7SMichael S. Tsirkin { 1141ddcb73b7SMichael S. Tsirkin E1000State *s = opaque; 1142ddcb73b7SMichael S. Tsirkin NetClientState *nc = qemu_get_queue(s->nic); 11432af234e6SMichael S. Tsirkin 11442af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 11452af234e6SMichael S. Tsirkin return; 11462af234e6SMichael S. Tsirkin } 11472af234e6SMichael S. Tsirkin 1148ddcb73b7SMichael S. Tsirkin /* 1149ddcb73b7SMichael S. Tsirkin * If link is down and auto-negotiation is ongoing, complete 1150ddcb73b7SMichael S. Tsirkin * auto-negotiation immediately. This allows is to look at 1151ddcb73b7SMichael S. Tsirkin * MII_SR_AUTONEG_COMPLETE to infer link status on load. 1152ddcb73b7SMichael S. Tsirkin */ 1153ddcb73b7SMichael S. Tsirkin if (nc->link_down && 1154ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN && 1155ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) { 1156ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; 1157ddcb73b7SMichael S. Tsirkin } 1158ddcb73b7SMichael S. Tsirkin } 1159ddcb73b7SMichael S. Tsirkin 1160e4b82364SAmos Kong static int e1000_post_load(void *opaque, int version_id) 1161e4b82364SAmos Kong { 1162e4b82364SAmos Kong E1000State *s = opaque; 1163b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 1164e4b82364SAmos Kong 1165e4b82364SAmos Kong /* nc.link_down can't be migrated, so infer link_down according 1166ddcb73b7SMichael S. Tsirkin * to link status bit in mac_reg[STATUS]. 1167ddcb73b7SMichael S. Tsirkin * Alternatively, restart link negotiation if it was in progress. */ 1168b356f76dSJason Wang nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0; 11692af234e6SMichael S. Tsirkin 11702af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 11712af234e6SMichael S. Tsirkin return 0; 11722af234e6SMichael S. Tsirkin } 11732af234e6SMichael S. Tsirkin 1174ddcb73b7SMichael S. Tsirkin if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN && 1175ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG && 1176ddcb73b7SMichael S. Tsirkin !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) { 1177ddcb73b7SMichael S. Tsirkin nc->link_down = false; 1178ddcb73b7SMichael S. Tsirkin qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); 1179ddcb73b7SMichael S. Tsirkin } 1180e4b82364SAmos Kong 1181e4b82364SAmos Kong return 0; 1182e4b82364SAmos Kong } 1183e4b82364SAmos Kong 1184e482dc3eSJuan Quintela static const VMStateDescription vmstate_e1000 = { 1185e482dc3eSJuan Quintela .name = "e1000", 1186e482dc3eSJuan Quintela .version_id = 2, 1187e482dc3eSJuan Quintela .minimum_version_id = 1, 1188e482dc3eSJuan Quintela .minimum_version_id_old = 1, 1189ddcb73b7SMichael S. Tsirkin .pre_save = e1000_pre_save, 1190e4b82364SAmos Kong .post_load = e1000_post_load, 1191e482dc3eSJuan Quintela .fields = (VMStateField []) { 1192e482dc3eSJuan Quintela VMSTATE_PCI_DEVICE(dev, E1000State), 1193e482dc3eSJuan Quintela VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */ 1194e482dc3eSJuan Quintela VMSTATE_UNUSED(4), /* Was mmio_base. */ 1195e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_size, E1000State), 1196e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_min_shift, E1000State), 1197e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.val_in, E1000State), 1198e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_in, E1000State), 1199e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_out, E1000State), 1200e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.reading, E1000State), 1201e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.old_eecd, E1000State), 1202e482dc3eSJuan Quintela VMSTATE_UINT8(tx.ipcss, E1000State), 1203e482dc3eSJuan Quintela VMSTATE_UINT8(tx.ipcso, E1000State), 1204e482dc3eSJuan Quintela VMSTATE_UINT16(tx.ipcse, E1000State), 1205e482dc3eSJuan Quintela VMSTATE_UINT8(tx.tucss, E1000State), 1206e482dc3eSJuan Quintela VMSTATE_UINT8(tx.tucso, E1000State), 1207e482dc3eSJuan Quintela VMSTATE_UINT16(tx.tucse, E1000State), 1208e482dc3eSJuan Quintela VMSTATE_UINT32(tx.paylen, E1000State), 1209e482dc3eSJuan Quintela VMSTATE_UINT8(tx.hdr_len, E1000State), 1210e482dc3eSJuan Quintela VMSTATE_UINT16(tx.mss, E1000State), 1211e482dc3eSJuan Quintela VMSTATE_UINT16(tx.size, E1000State), 1212e482dc3eSJuan Quintela VMSTATE_UINT16(tx.tso_frames, E1000State), 1213e482dc3eSJuan Quintela VMSTATE_UINT8(tx.sum_needed, E1000State), 1214e482dc3eSJuan Quintela VMSTATE_INT8(tx.ip, E1000State), 1215e482dc3eSJuan Quintela VMSTATE_INT8(tx.tcp, E1000State), 1216e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.header, E1000State), 1217e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.data, E1000State), 1218e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64), 1219e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20), 1220e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[CTRL], E1000State), 1221e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EECD], E1000State), 1222e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EERD], E1000State), 1223e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPRC], E1000State), 1224e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPTC], E1000State), 1225e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICR], E1000State), 1226e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICS], E1000State), 1227e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMC], E1000State), 1228e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMS], E1000State), 1229e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[LEDCTL], E1000State), 1230e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MANC], E1000State), 1231e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MDIC], E1000State), 1232e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MPC], E1000State), 1233e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[PBA], E1000State), 1234e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RCTL], E1000State), 1235e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAH], E1000State), 1236e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAL], E1000State), 1237e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDH], E1000State), 1238e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDLEN], E1000State), 1239e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDT], E1000State), 1240e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[STATUS], E1000State), 1241e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[SWSM], E1000State), 1242e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TCTL], E1000State), 1243e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAH], E1000State), 1244e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAL], E1000State), 1245e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDH], E1000State), 1246e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDLEN], E1000State), 1247e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDT], E1000State), 1248e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORH], E1000State), 1249e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORL], E1000State), 1250e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTH], E1000State), 1251e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTL], E1000State), 1252e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPR], E1000State), 1253e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPT], E1000State), 1254e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TXDCTL], E1000State), 1255e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[WUFC], E1000State), 1256e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[VET], E1000State), 1257e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32), 1258e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128), 1259e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128), 1260e482dc3eSJuan Quintela VMSTATE_END_OF_LIST() 12617c23b892Sbalrog } 1262e482dc3eSJuan Quintela }; 12637c23b892Sbalrog 126488b4e9dbSblueswir1 static const uint16_t e1000_eeprom_template[64] = { 12657c23b892Sbalrog 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 12667c23b892Sbalrog 0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040, 12677c23b892Sbalrog 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700, 12687c23b892Sbalrog 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706, 12697c23b892Sbalrog 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff, 12707c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 12717c23b892Sbalrog 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 12727c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 12737c23b892Sbalrog }; 12747c23b892Sbalrog 12757c23b892Sbalrog /* PCI interface */ 12767c23b892Sbalrog 12777c23b892Sbalrog static void 1278ad00a9b9SAvi Kivity e1000_mmio_setup(E1000State *d) 12797c23b892Sbalrog { 1280f65ed4c1Saliguori int i; 1281f65ed4c1Saliguori const uint32_t excluded_regs[] = { 1282f65ed4c1Saliguori E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, 1283f65ed4c1Saliguori E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE 1284f65ed4c1Saliguori }; 1285f65ed4c1Saliguori 1286eedfac6fSPaolo Bonzini memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d, 1287eedfac6fSPaolo Bonzini "e1000-mmio", PNPMMIO_SIZE); 1288ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]); 1289f65ed4c1Saliguori for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) 1290ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4, 1291ad00a9b9SAvi Kivity excluded_regs[i+1] - excluded_regs[i] - 4); 1292eedfac6fSPaolo Bonzini memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE); 12937c23b892Sbalrog } 12947c23b892Sbalrog 1295b946a153Saliguori static void 12964e68f7a0SStefan Hajnoczi e1000_cleanup(NetClientState *nc) 1297b946a153Saliguori { 1298cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 1299b946a153Saliguori 1300a03e2aecSMark McLoughlin s->nic = NULL; 1301b946a153Saliguori } 1302b946a153Saliguori 1303f90c2bcdSAlex Williamson static void 13044b09be85Saliguori pci_e1000_uninit(PCIDevice *dev) 13054b09be85Saliguori { 1306*567a3c9eSPeter Crosthwaite E1000State *d = E1000(dev); 13074b09be85Saliguori 1308b9d03e35SJason Wang qemu_del_timer(d->autoneg_timer); 1309b9d03e35SJason Wang qemu_free_timer(d->autoneg_timer); 1310ad00a9b9SAvi Kivity memory_region_destroy(&d->mmio); 1311ad00a9b9SAvi Kivity memory_region_destroy(&d->io); 1312948ecf21SJason Wang qemu_del_nic(d->nic); 13134b09be85Saliguori } 13144b09be85Saliguori 1315a03e2aecSMark McLoughlin static NetClientInfo net_e1000_info = { 13162be64a68SLaszlo Ersek .type = NET_CLIENT_OPTIONS_KIND_NIC, 1317a03e2aecSMark McLoughlin .size = sizeof(NICState), 1318a03e2aecSMark McLoughlin .can_receive = e1000_can_receive, 1319a03e2aecSMark McLoughlin .receive = e1000_receive, 1320a03e2aecSMark McLoughlin .cleanup = e1000_cleanup, 1321a03e2aecSMark McLoughlin .link_status_changed = e1000_set_link_status, 1322a03e2aecSMark McLoughlin }; 1323a03e2aecSMark McLoughlin 132481a322d4SGerd Hoffmann static int pci_e1000_init(PCIDevice *pci_dev) 13257c23b892Sbalrog { 1326*567a3c9eSPeter Crosthwaite DeviceState *dev = DEVICE(pci_dev); 1327*567a3c9eSPeter Crosthwaite E1000State *d = E1000(pci_dev); 13287c23b892Sbalrog uint8_t *pci_conf; 13297c23b892Sbalrog uint16_t checksum = 0; 13307c23b892Sbalrog int i; 1331fbdaa002SGerd Hoffmann uint8_t *macaddr; 1332aff427a1SChris Wright 13337c23b892Sbalrog pci_conf = d->dev.config; 13347c23b892Sbalrog 1335a9cbacb0SMichael S. Tsirkin /* TODO: RST# value should be 0, PCI spec 6.2.4 */ 1336a9cbacb0SMichael S. Tsirkin pci_conf[PCI_CACHE_LINE_SIZE] = 0x10; 13377c23b892Sbalrog 1338817e0b6fSMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ 13397c23b892Sbalrog 1340ad00a9b9SAvi Kivity e1000_mmio_setup(d); 13417c23b892Sbalrog 1342e824b2ccSAvi Kivity pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 13437c23b892Sbalrog 1344e824b2ccSAvi Kivity pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io); 13457c23b892Sbalrog 13467c23b892Sbalrog memmove(d->eeprom_data, e1000_eeprom_template, 13477c23b892Sbalrog sizeof e1000_eeprom_template); 1348fbdaa002SGerd Hoffmann qemu_macaddr_default_if_unset(&d->conf.macaddr); 1349fbdaa002SGerd Hoffmann macaddr = d->conf.macaddr.a; 13507c23b892Sbalrog for (i = 0; i < 3; i++) 13519d07d757SPaul Brook d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i]; 13527c23b892Sbalrog for (i = 0; i < EEPROM_CHECKSUM_REG; i++) 13537c23b892Sbalrog checksum += d->eeprom_data[i]; 13547c23b892Sbalrog checksum = (uint16_t) EEPROM_SUM - checksum; 13557c23b892Sbalrog d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum; 13567c23b892Sbalrog 1357a03e2aecSMark McLoughlin d->nic = qemu_new_nic(&net_e1000_info, &d->conf, 1358*567a3c9eSPeter Crosthwaite object_get_typename(OBJECT(d)), dev->id, d); 13597c23b892Sbalrog 1360b356f76dSJason Wang qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); 13611ca4d09aSGleb Natapov 1362*567a3c9eSPeter Crosthwaite add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0"); 13631ca4d09aSGleb Natapov 1364b9d03e35SJason Wang d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d); 1365b9d03e35SJason Wang 136681a322d4SGerd Hoffmann return 0; 13677c23b892Sbalrog } 13689d07d757SPaul Brook 1369fbdaa002SGerd Hoffmann static void qdev_e1000_reset(DeviceState *dev) 1370fbdaa002SGerd Hoffmann { 1371*567a3c9eSPeter Crosthwaite E1000State *d = E1000(dev); 1372fbdaa002SGerd Hoffmann e1000_reset(d); 1373fbdaa002SGerd Hoffmann } 1374fbdaa002SGerd Hoffmann 137540021f08SAnthony Liguori static Property e1000_properties[] = { 1376fbdaa002SGerd Hoffmann DEFINE_NIC_PROPERTIES(E1000State, conf), 13772af234e6SMichael S. Tsirkin DEFINE_PROP_BIT("autonegotiation", E1000State, 13782af234e6SMichael S. Tsirkin compat_flags, E1000_FLAG_AUTONEG_BIT, true), 1379fbdaa002SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 138040021f08SAnthony Liguori }; 138140021f08SAnthony Liguori 138240021f08SAnthony Liguori static void e1000_class_init(ObjectClass *klass, void *data) 138340021f08SAnthony Liguori { 138439bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 138540021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 138640021f08SAnthony Liguori 138740021f08SAnthony Liguori k->init = pci_e1000_init; 138840021f08SAnthony Liguori k->exit = pci_e1000_uninit; 1389c45e5b5bSGerd Hoffmann k->romfile = "efi-e1000.rom"; 139040021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_INTEL; 139140021f08SAnthony Liguori k->device_id = E1000_DEVID; 139240021f08SAnthony Liguori k->revision = 0x03; 139340021f08SAnthony Liguori k->class_id = PCI_CLASS_NETWORK_ETHERNET; 139439bffca2SAnthony Liguori dc->desc = "Intel Gigabit Ethernet"; 139539bffca2SAnthony Liguori dc->reset = qdev_e1000_reset; 139639bffca2SAnthony Liguori dc->vmsd = &vmstate_e1000; 139739bffca2SAnthony Liguori dc->props = e1000_properties; 1398fbdaa002SGerd Hoffmann } 139940021f08SAnthony Liguori 14008c43a6f0SAndreas Färber static const TypeInfo e1000_info = { 1401*567a3c9eSPeter Crosthwaite .name = TYPE_E1000, 140239bffca2SAnthony Liguori .parent = TYPE_PCI_DEVICE, 140339bffca2SAnthony Liguori .instance_size = sizeof(E1000State), 140440021f08SAnthony Liguori .class_init = e1000_class_init, 14050aab0d3aSGerd Hoffmann }; 14060aab0d3aSGerd Hoffmann 140783f7d43aSAndreas Färber static void e1000_register_types(void) 14089d07d757SPaul Brook { 140939bffca2SAnthony Liguori type_register_static(&e1000_info); 14109d07d757SPaul Brook } 14119d07d757SPaul Brook 141283f7d43aSAndreas Färber type_init(e1000_register_types) 1413