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 1417c23b892Sbalrog #define defreg(x) x = (E1000_##x>>2) 1427c23b892Sbalrog enum { 1437c23b892Sbalrog defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), 1447c23b892Sbalrog defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), 1457c23b892Sbalrog defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), 1467c23b892Sbalrog defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH), 1477c23b892Sbalrog defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT), 1487c23b892Sbalrog defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), 1497c23b892Sbalrog defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), 1507c23b892Sbalrog defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL), 1517c23b892Sbalrog defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC), 1528f2e8d1fSaliguori defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA), 1538f2e8d1fSaliguori defreg(VET), 1547c23b892Sbalrog }; 1557c23b892Sbalrog 15671aadd3cSJason Wang static void 15771aadd3cSJason Wang e1000_link_down(E1000State *s) 15871aadd3cSJason Wang { 15971aadd3cSJason Wang s->mac_reg[STATUS] &= ~E1000_STATUS_LU; 16071aadd3cSJason Wang s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS; 16171aadd3cSJason Wang } 16271aadd3cSJason Wang 16371aadd3cSJason Wang static void 16471aadd3cSJason Wang e1000_link_up(E1000State *s) 16571aadd3cSJason Wang { 16671aadd3cSJason Wang s->mac_reg[STATUS] |= E1000_STATUS_LU; 16771aadd3cSJason Wang s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS; 16871aadd3cSJason Wang } 16971aadd3cSJason Wang 170b9d03e35SJason Wang static void 171b9d03e35SJason Wang set_phy_ctrl(E1000State *s, int index, uint16_t val) 172b9d03e35SJason Wang { 1732af234e6SMichael S. Tsirkin /* 1742af234e6SMichael S. Tsirkin * QEMU 1.3 does not support link auto-negotiation emulation, so if we 1752af234e6SMichael S. Tsirkin * migrate during auto negotiation, after migration the link will be 1762af234e6SMichael S. Tsirkin * down. 1772af234e6SMichael S. Tsirkin */ 1782af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 1792af234e6SMichael S. Tsirkin return; 1802af234e6SMichael S. Tsirkin } 181b9d03e35SJason Wang if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) { 182b9d03e35SJason Wang e1000_link_down(s); 183b9d03e35SJason Wang s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; 184b9d03e35SJason Wang DBGOUT(PHY, "Start link auto negotiation\n"); 185b9d03e35SJason Wang qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); 186b9d03e35SJason Wang } 187b9d03e35SJason Wang } 188b9d03e35SJason Wang 189b9d03e35SJason Wang static void 190b9d03e35SJason Wang e1000_autoneg_timer(void *opaque) 191b9d03e35SJason Wang { 192b9d03e35SJason Wang E1000State *s = opaque; 193ddcb73b7SMichael S. Tsirkin if (!qemu_get_queue(s->nic)->link_down) { 194b9d03e35SJason Wang e1000_link_up(s); 195ddcb73b7SMichael S. Tsirkin } 196b9d03e35SJason Wang s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; 197b9d03e35SJason Wang DBGOUT(PHY, "Auto negotiation is completed\n"); 198b9d03e35SJason Wang } 199b9d03e35SJason Wang 200b9d03e35SJason Wang static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = { 201b9d03e35SJason Wang [PHY_CTRL] = set_phy_ctrl, 202b9d03e35SJason Wang }; 203b9d03e35SJason Wang 204b9d03e35SJason Wang enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) }; 205b9d03e35SJason Wang 2067c23b892Sbalrog enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W }; 20788b4e9dbSblueswir1 static const char phy_regcap[0x20] = { 2087c23b892Sbalrog [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW, 2097c23b892Sbalrog [PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW, 2107c23b892Sbalrog [PHY_CTRL] = PHY_RW, [PHY_1000T_CTRL] = PHY_RW, 2117c23b892Sbalrog [PHY_LP_ABILITY] = PHY_R, [PHY_1000T_STATUS] = PHY_R, 2127c23b892Sbalrog [PHY_AUTONEG_ADV] = PHY_RW, [M88E1000_RX_ERR_CNTR] = PHY_R, 213700f6e2cSaurel32 [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R 2147c23b892Sbalrog }; 2157c23b892Sbalrog 216814cd3acSMichael S. Tsirkin static const uint16_t phy_reg_init[] = { 217b9d03e35SJason Wang [PHY_CTRL] = 0x1140, 218b9d03e35SJason Wang [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */ 219814cd3acSMichael S. Tsirkin [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT, 220814cd3acSMichael S. Tsirkin [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360, 221814cd3acSMichael S. Tsirkin [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1, 222814cd3acSMichael S. Tsirkin [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00, 223814cd3acSMichael S. Tsirkin [M88E1000_PHY_SPEC_STATUS] = 0xac00, 224814cd3acSMichael S. Tsirkin }; 225814cd3acSMichael S. Tsirkin 226814cd3acSMichael S. Tsirkin static const uint32_t mac_reg_init[] = { 227814cd3acSMichael S. Tsirkin [PBA] = 0x00100030, 228814cd3acSMichael S. Tsirkin [LEDCTL] = 0x602, 229814cd3acSMichael S. Tsirkin [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | 230814cd3acSMichael S. Tsirkin E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, 231814cd3acSMichael S. Tsirkin [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | 232814cd3acSMichael S. Tsirkin E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | 233814cd3acSMichael S. Tsirkin E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | 234814cd3acSMichael S. Tsirkin E1000_STATUS_LU, 235814cd3acSMichael S. Tsirkin [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | 236814cd3acSMichael S. Tsirkin E1000_MANC_ARP_EN | E1000_MANC_0298_EN | 237814cd3acSMichael S. Tsirkin E1000_MANC_RMCP_EN, 238814cd3acSMichael S. Tsirkin }; 239814cd3acSMichael S. Tsirkin 2407c23b892Sbalrog static void 2417c23b892Sbalrog set_interrupt_cause(E1000State *s, int index, uint32_t val) 2427c23b892Sbalrog { 243f1219091SJason Wang if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) { 244f1219091SJason Wang /* Only for 8257x */ 2457c23b892Sbalrog val |= E1000_ICR_INT_ASSERTED; 246f1219091SJason Wang } 2477c23b892Sbalrog s->mac_reg[ICR] = val; 248a52a8841SMichael S. Tsirkin 249a52a8841SMichael S. Tsirkin /* 250a52a8841SMichael S. Tsirkin * Make sure ICR and ICS registers have the same value. 251a52a8841SMichael S. Tsirkin * The spec says that the ICS register is write-only. However in practice, 252a52a8841SMichael S. Tsirkin * on real hardware ICS is readable, and for reads it has the same value as 253a52a8841SMichael S. Tsirkin * ICR (except that ICS does not have the clear on read behaviour of ICR). 254a52a8841SMichael S. Tsirkin * 255a52a8841SMichael S. Tsirkin * The VxWorks PRO/1000 driver uses this behaviour. 256a52a8841SMichael S. Tsirkin */ 257b1332393SBill Paul s->mac_reg[ICS] = val; 258a52a8841SMichael S. Tsirkin 259bc26e55aSBlue Swirl qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0); 2607c23b892Sbalrog } 2617c23b892Sbalrog 2627c23b892Sbalrog static void 2637c23b892Sbalrog set_ics(E1000State *s, int index, uint32_t val) 2647c23b892Sbalrog { 2657c23b892Sbalrog DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR], 2667c23b892Sbalrog s->mac_reg[IMS]); 2677c23b892Sbalrog set_interrupt_cause(s, 0, val | s->mac_reg[ICR]); 2687c23b892Sbalrog } 2697c23b892Sbalrog 2707c23b892Sbalrog static int 2717c23b892Sbalrog rxbufsize(uint32_t v) 2727c23b892Sbalrog { 2737c23b892Sbalrog v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 | 2747c23b892Sbalrog E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 | 2757c23b892Sbalrog E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256; 2767c23b892Sbalrog switch (v) { 2777c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384: 2787c23b892Sbalrog return 16384; 2797c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192: 2807c23b892Sbalrog return 8192; 2817c23b892Sbalrog case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096: 2827c23b892Sbalrog return 4096; 2837c23b892Sbalrog case E1000_RCTL_SZ_1024: 2847c23b892Sbalrog return 1024; 2857c23b892Sbalrog case E1000_RCTL_SZ_512: 2867c23b892Sbalrog return 512; 2877c23b892Sbalrog case E1000_RCTL_SZ_256: 2887c23b892Sbalrog return 256; 2897c23b892Sbalrog } 2907c23b892Sbalrog return 2048; 2917c23b892Sbalrog } 2927c23b892Sbalrog 293814cd3acSMichael S. Tsirkin static void e1000_reset(void *opaque) 294814cd3acSMichael S. Tsirkin { 295814cd3acSMichael S. Tsirkin E1000State *d = opaque; 296372254c6SGabriel L. Somlo uint8_t *macaddr = d->conf.macaddr.a; 297372254c6SGabriel L. Somlo int i; 298814cd3acSMichael S. Tsirkin 299b9d03e35SJason Wang qemu_del_timer(d->autoneg_timer); 300814cd3acSMichael S. Tsirkin memset(d->phy_reg, 0, sizeof d->phy_reg); 301814cd3acSMichael S. Tsirkin memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); 302814cd3acSMichael S. Tsirkin memset(d->mac_reg, 0, sizeof d->mac_reg); 303814cd3acSMichael S. Tsirkin memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); 304814cd3acSMichael S. Tsirkin d->rxbuf_min_shift = 1; 305814cd3acSMichael S. Tsirkin memset(&d->tx, 0, sizeof d->tx); 306814cd3acSMichael S. Tsirkin 307b356f76dSJason Wang if (qemu_get_queue(d->nic)->link_down) { 30871aadd3cSJason Wang e1000_link_down(d); 309814cd3acSMichael S. Tsirkin } 310372254c6SGabriel L. Somlo 311372254c6SGabriel L. Somlo /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */ 312372254c6SGabriel L. Somlo d->mac_reg[RA] = 0; 313372254c6SGabriel L. Somlo d->mac_reg[RA + 1] = E1000_RAH_AV; 314372254c6SGabriel L. Somlo for (i = 0; i < 4; i++) { 315372254c6SGabriel L. Somlo d->mac_reg[RA] |= macaddr[i] << (8 * i); 316372254c6SGabriel L. Somlo d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0; 317372254c6SGabriel L. Somlo } 318814cd3acSMichael S. Tsirkin } 319814cd3acSMichael S. Tsirkin 3207c23b892Sbalrog static void 321cab3c825SKevin Wolf set_ctrl(E1000State *s, int index, uint32_t val) 322cab3c825SKevin Wolf { 323cab3c825SKevin Wolf /* RST is self clearing */ 324cab3c825SKevin Wolf s->mac_reg[CTRL] = val & ~E1000_CTRL_RST; 325cab3c825SKevin Wolf } 326cab3c825SKevin Wolf 327cab3c825SKevin Wolf static void 3287c23b892Sbalrog set_rx_control(E1000State *s, int index, uint32_t val) 3297c23b892Sbalrog { 3307c23b892Sbalrog s->mac_reg[RCTL] = val; 3317c23b892Sbalrog s->rxbuf_size = rxbufsize(val); 3327c23b892Sbalrog s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; 3337c23b892Sbalrog DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], 3347c23b892Sbalrog s->mac_reg[RCTL]); 335b356f76dSJason Wang qemu_flush_queued_packets(qemu_get_queue(s->nic)); 3367c23b892Sbalrog } 3377c23b892Sbalrog 3387c23b892Sbalrog static void 3397c23b892Sbalrog set_mdic(E1000State *s, int index, uint32_t val) 3407c23b892Sbalrog { 3417c23b892Sbalrog uint32_t data = val & E1000_MDIC_DATA_MASK; 3427c23b892Sbalrog uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); 3437c23b892Sbalrog 3447c23b892Sbalrog if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy # 3457c23b892Sbalrog val = s->mac_reg[MDIC] | E1000_MDIC_ERROR; 3467c23b892Sbalrog else if (val & E1000_MDIC_OP_READ) { 3477c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr); 3487c23b892Sbalrog if (!(phy_regcap[addr] & PHY_R)) { 3497c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr); 3507c23b892Sbalrog val |= E1000_MDIC_ERROR; 3517c23b892Sbalrog } else 3527c23b892Sbalrog val = (val ^ data) | s->phy_reg[addr]; 3537c23b892Sbalrog } else if (val & E1000_MDIC_OP_WRITE) { 3547c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data); 3557c23b892Sbalrog if (!(phy_regcap[addr] & PHY_W)) { 3567c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr); 3577c23b892Sbalrog val |= E1000_MDIC_ERROR; 358b9d03e35SJason Wang } else { 359b9d03e35SJason Wang if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) { 360b9d03e35SJason Wang phyreg_writeops[addr](s, index, data); 361b9d03e35SJason Wang } 3627c23b892Sbalrog s->phy_reg[addr] = data; 3637c23b892Sbalrog } 364b9d03e35SJason Wang } 3657c23b892Sbalrog s->mac_reg[MDIC] = val | E1000_MDIC_READY; 36617fbbb0bSJason Wang 36717fbbb0bSJason Wang if (val & E1000_MDIC_INT_EN) { 3687c23b892Sbalrog set_ics(s, 0, E1000_ICR_MDAC); 3697c23b892Sbalrog } 37017fbbb0bSJason Wang } 3717c23b892Sbalrog 3727c23b892Sbalrog static uint32_t 3737c23b892Sbalrog get_eecd(E1000State *s, int index) 3747c23b892Sbalrog { 3757c23b892Sbalrog uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd; 3767c23b892Sbalrog 3777c23b892Sbalrog DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n", 3787c23b892Sbalrog s->eecd_state.bitnum_out, s->eecd_state.reading); 3797c23b892Sbalrog if (!s->eecd_state.reading || 3807c23b892Sbalrog ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >> 3817c23b892Sbalrog ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1) 3827c23b892Sbalrog ret |= E1000_EECD_DO; 3837c23b892Sbalrog return ret; 3847c23b892Sbalrog } 3857c23b892Sbalrog 3867c23b892Sbalrog static void 3877c23b892Sbalrog set_eecd(E1000State *s, int index, uint32_t val) 3887c23b892Sbalrog { 3897c23b892Sbalrog uint32_t oldval = s->eecd_state.old_eecd; 3907c23b892Sbalrog 3917c23b892Sbalrog s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS | 3927c23b892Sbalrog E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ); 3939651ac55SIzumi Tsutsui if (!(E1000_EECD_CS & val)) // CS inactive; nothing to do 3949651ac55SIzumi Tsutsui return; 3959651ac55SIzumi Tsutsui if (E1000_EECD_CS & (val ^ oldval)) { // CS rise edge; reset state 3969651ac55SIzumi Tsutsui s->eecd_state.val_in = 0; 3979651ac55SIzumi Tsutsui s->eecd_state.bitnum_in = 0; 3989651ac55SIzumi Tsutsui s->eecd_state.bitnum_out = 0; 3999651ac55SIzumi Tsutsui s->eecd_state.reading = 0; 4009651ac55SIzumi Tsutsui } 4017c23b892Sbalrog if (!(E1000_EECD_SK & (val ^ oldval))) // no clock edge 4027c23b892Sbalrog return; 4037c23b892Sbalrog if (!(E1000_EECD_SK & val)) { // falling edge 4047c23b892Sbalrog s->eecd_state.bitnum_out++; 4057c23b892Sbalrog return; 4067c23b892Sbalrog } 4077c23b892Sbalrog s->eecd_state.val_in <<= 1; 4087c23b892Sbalrog if (val & E1000_EECD_DI) 4097c23b892Sbalrog s->eecd_state.val_in |= 1; 4107c23b892Sbalrog if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) { 4117c23b892Sbalrog s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1; 4127c23b892Sbalrog s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) == 4137c23b892Sbalrog EEPROM_READ_OPCODE_MICROWIRE); 4147c23b892Sbalrog } 4157c23b892Sbalrog DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n", 4167c23b892Sbalrog s->eecd_state.bitnum_in, s->eecd_state.bitnum_out, 4177c23b892Sbalrog s->eecd_state.reading); 4187c23b892Sbalrog } 4197c23b892Sbalrog 4207c23b892Sbalrog static uint32_t 4217c23b892Sbalrog flash_eerd_read(E1000State *s, int x) 4227c23b892Sbalrog { 4237c23b892Sbalrog unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START; 4247c23b892Sbalrog 425b1332393SBill Paul if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0) 426b1332393SBill Paul return (s->mac_reg[EERD]); 427b1332393SBill Paul 4287c23b892Sbalrog if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG) 429b1332393SBill Paul return (E1000_EEPROM_RW_REG_DONE | r); 430b1332393SBill Paul 431b1332393SBill Paul return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) | 432b1332393SBill Paul E1000_EEPROM_RW_REG_DONE | r); 4337c23b892Sbalrog } 4347c23b892Sbalrog 4357c23b892Sbalrog static void 4367c23b892Sbalrog putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse) 4377c23b892Sbalrog { 438c6a6a5e3Saliguori uint32_t sum; 439c6a6a5e3Saliguori 4407c23b892Sbalrog if (cse && cse < n) 4417c23b892Sbalrog n = cse + 1; 442c6a6a5e3Saliguori if (sloc < n-1) { 443c6a6a5e3Saliguori sum = net_checksum_add(n-css, data+css); 4447c23b892Sbalrog cpu_to_be16wu((uint16_t *)(data + sloc), 445c6a6a5e3Saliguori net_checksum_finish(sum)); 446c6a6a5e3Saliguori } 4477c23b892Sbalrog } 4487c23b892Sbalrog 4498f2e8d1fSaliguori static inline int 4508f2e8d1fSaliguori vlan_enabled(E1000State *s) 4518f2e8d1fSaliguori { 4528f2e8d1fSaliguori return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0); 4538f2e8d1fSaliguori } 4548f2e8d1fSaliguori 4558f2e8d1fSaliguori static inline int 4568f2e8d1fSaliguori vlan_rx_filter_enabled(E1000State *s) 4578f2e8d1fSaliguori { 4588f2e8d1fSaliguori return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0); 4598f2e8d1fSaliguori } 4608f2e8d1fSaliguori 4618f2e8d1fSaliguori static inline int 4628f2e8d1fSaliguori is_vlan_packet(E1000State *s, const uint8_t *buf) 4638f2e8d1fSaliguori { 4648f2e8d1fSaliguori return (be16_to_cpup((uint16_t *)(buf + 12)) == 4658f2e8d1fSaliguori le16_to_cpup((uint16_t *)(s->mac_reg + VET))); 4668f2e8d1fSaliguori } 4678f2e8d1fSaliguori 4688f2e8d1fSaliguori static inline int 4698f2e8d1fSaliguori is_vlan_txd(uint32_t txd_lower) 4708f2e8d1fSaliguori { 4718f2e8d1fSaliguori return ((txd_lower & E1000_TXD_CMD_VLE) != 0); 4728f2e8d1fSaliguori } 4738f2e8d1fSaliguori 47455e8d1ceSMichael S. Tsirkin /* FCS aka Ethernet CRC-32. We don't get it from backends and can't 47555e8d1ceSMichael S. Tsirkin * fill it in, just pad descriptor length by 4 bytes unless guest 476a05e8a6eSMichael S. Tsirkin * told us to strip it off the packet. */ 47755e8d1ceSMichael S. Tsirkin static inline int 47855e8d1ceSMichael S. Tsirkin fcs_len(E1000State *s) 47955e8d1ceSMichael S. Tsirkin { 48055e8d1ceSMichael S. Tsirkin return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4; 48155e8d1ceSMichael S. Tsirkin } 48255e8d1ceSMichael S. Tsirkin 4837c23b892Sbalrog static void 48493e37d76SJason Wang e1000_send_packet(E1000State *s, const uint8_t *buf, int size) 48593e37d76SJason Wang { 486b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 48793e37d76SJason Wang if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) { 488b356f76dSJason Wang nc->info->receive(nc, buf, size); 48993e37d76SJason Wang } else { 490b356f76dSJason Wang qemu_send_packet(nc, buf, size); 49193e37d76SJason Wang } 49293e37d76SJason Wang } 49393e37d76SJason Wang 49493e37d76SJason Wang static void 4957c23b892Sbalrog xmit_seg(E1000State *s) 4967c23b892Sbalrog { 4977c23b892Sbalrog uint16_t len, *sp; 4987c23b892Sbalrog unsigned int frames = s->tx.tso_frames, css, sofar, n; 4997c23b892Sbalrog struct e1000_tx *tp = &s->tx; 5007c23b892Sbalrog 5011b0009dbSbalrog if (tp->tse && tp->cptse) { 5027c23b892Sbalrog css = tp->ipcss; 5037c23b892Sbalrog DBGOUT(TXSUM, "frames %d size %d ipcss %d\n", 5047c23b892Sbalrog frames, tp->size, css); 5057c23b892Sbalrog if (tp->ip) { // IPv4 5067c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+2), 5077c23b892Sbalrog tp->size - css); 5087c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), 5097c23b892Sbalrog be16_to_cpup((uint16_t *)(tp->data+css+4))+frames); 5107c23b892Sbalrog } else // IPv6 5117c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), 5127c23b892Sbalrog tp->size - css); 5137c23b892Sbalrog css = tp->tucss; 5147c23b892Sbalrog len = tp->size - css; 5157c23b892Sbalrog DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len); 5167c23b892Sbalrog if (tp->tcp) { 5177c23b892Sbalrog sofar = frames * tp->mss; 5187c23b892Sbalrog cpu_to_be32wu((uint32_t *)(tp->data+css+4), // seq 51988738c09Saurel32 be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar); 5207c23b892Sbalrog if (tp->paylen - sofar > tp->mss) 5217c23b892Sbalrog tp->data[css + 13] &= ~9; // PSH, FIN 5227c23b892Sbalrog } else // UDP 5237c23b892Sbalrog cpu_to_be16wu((uint16_t *)(tp->data+css+4), len); 5247c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { 525e685b4ebSAlex Williamson unsigned int phsum; 5267c23b892Sbalrog // add pseudo-header length before checksum calculation 5277c23b892Sbalrog sp = (uint16_t *)(tp->data + tp->tucso); 528e685b4ebSAlex Williamson phsum = be16_to_cpup(sp) + len; 529e685b4ebSAlex Williamson phsum = (phsum >> 16) + (phsum & 0xffff); 530e685b4ebSAlex Williamson cpu_to_be16wu(sp, phsum); 5317c23b892Sbalrog } 5327c23b892Sbalrog tp->tso_frames++; 5337c23b892Sbalrog } 5347c23b892Sbalrog 5357c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_TXSM) 5367c23b892Sbalrog putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse); 5377c23b892Sbalrog if (tp->sum_needed & E1000_TXD_POPTS_IXSM) 5387c23b892Sbalrog putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse); 5398f2e8d1fSaliguori if (tp->vlan_needed) { 540b10fec9bSStefan Weil memmove(tp->vlan, tp->data, 4); 541b10fec9bSStefan Weil memmove(tp->data, tp->data + 4, 8); 5428f2e8d1fSaliguori memcpy(tp->data + 8, tp->vlan_header, 4); 54393e37d76SJason Wang e1000_send_packet(s, tp->vlan, tp->size + 4); 5448f2e8d1fSaliguori } else 54593e37d76SJason Wang e1000_send_packet(s, tp->data, tp->size); 5467c23b892Sbalrog s->mac_reg[TPT]++; 5477c23b892Sbalrog s->mac_reg[GPTC]++; 5487c23b892Sbalrog n = s->mac_reg[TOTL]; 5497c23b892Sbalrog if ((s->mac_reg[TOTL] += s->tx.size) < n) 5507c23b892Sbalrog s->mac_reg[TOTH]++; 5517c23b892Sbalrog } 5527c23b892Sbalrog 5537c23b892Sbalrog static void 5547c23b892Sbalrog process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) 5557c23b892Sbalrog { 5567c23b892Sbalrog uint32_t txd_lower = le32_to_cpu(dp->lower.data); 5577c23b892Sbalrog uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); 5587c23b892Sbalrog unsigned int split_size = txd_lower & 0xffff, bytes, sz, op; 5597c23b892Sbalrog unsigned int msh = 0xfffff, hdr = 0; 5607c23b892Sbalrog uint64_t addr; 5617c23b892Sbalrog struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; 5627c23b892Sbalrog struct e1000_tx *tp = &s->tx; 5637c23b892Sbalrog 5647c23b892Sbalrog if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor 5657c23b892Sbalrog op = le32_to_cpu(xp->cmd_and_length); 5667c23b892Sbalrog tp->ipcss = xp->lower_setup.ip_fields.ipcss; 5677c23b892Sbalrog tp->ipcso = xp->lower_setup.ip_fields.ipcso; 5687c23b892Sbalrog tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse); 5697c23b892Sbalrog tp->tucss = xp->upper_setup.tcp_fields.tucss; 5707c23b892Sbalrog tp->tucso = xp->upper_setup.tcp_fields.tucso; 5717c23b892Sbalrog tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse); 5727c23b892Sbalrog tp->paylen = op & 0xfffff; 5737c23b892Sbalrog tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len; 5747c23b892Sbalrog tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss); 5757c23b892Sbalrog tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0; 5767c23b892Sbalrog tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0; 5777c23b892Sbalrog tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0; 5787c23b892Sbalrog tp->tso_frames = 0; 5797c23b892Sbalrog if (tp->tucso == 0) { // this is probably wrong 5807c23b892Sbalrog DBGOUT(TXSUM, "TCP/UDP: cso 0!\n"); 5817c23b892Sbalrog tp->tucso = tp->tucss + (tp->tcp ? 16 : 6); 5827c23b892Sbalrog } 5837c23b892Sbalrog return; 5841b0009dbSbalrog } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { 5851b0009dbSbalrog // data descriptor 586735e77ecSStefan Hajnoczi if (tp->size == 0) { 5877c23b892Sbalrog tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8; 588735e77ecSStefan Hajnoczi } 5891b0009dbSbalrog tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0; 59043ad7e3eSJes Sorensen } else { 5911b0009dbSbalrog // legacy descriptor 5921b0009dbSbalrog tp->cptse = 0; 59343ad7e3eSJes Sorensen } 5947c23b892Sbalrog 5958f2e8d1fSaliguori if (vlan_enabled(s) && is_vlan_txd(txd_lower) && 5968f2e8d1fSaliguori (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) { 5978f2e8d1fSaliguori tp->vlan_needed = 1; 5988f2e8d1fSaliguori cpu_to_be16wu((uint16_t *)(tp->vlan_header), 5998f2e8d1fSaliguori le16_to_cpup((uint16_t *)(s->mac_reg + VET))); 6008f2e8d1fSaliguori cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2), 6018f2e8d1fSaliguori le16_to_cpu(dp->upper.fields.special)); 6028f2e8d1fSaliguori } 6038f2e8d1fSaliguori 6047c23b892Sbalrog addr = le64_to_cpu(dp->buffer_addr); 6051b0009dbSbalrog if (tp->tse && tp->cptse) { 6067c23b892Sbalrog hdr = tp->hdr_len; 6077c23b892Sbalrog msh = hdr + tp->mss; 6087c23b892Sbalrog do { 6097c23b892Sbalrog bytes = split_size; 6107c23b892Sbalrog if (tp->size + bytes > msh) 6117c23b892Sbalrog bytes = msh - tp->size; 61265f82df0SAnthony Liguori 61365f82df0SAnthony Liguori bytes = MIN(sizeof(tp->data) - tp->size, bytes); 61462ecbd35SEduard - Gabriel Munteanu pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes); 6157c23b892Sbalrog if ((sz = tp->size + bytes) >= hdr && tp->size < hdr) 6167c23b892Sbalrog memmove(tp->header, tp->data, hdr); 6177c23b892Sbalrog tp->size = sz; 6187c23b892Sbalrog addr += bytes; 6197c23b892Sbalrog if (sz == msh) { 6207c23b892Sbalrog xmit_seg(s); 6217c23b892Sbalrog memmove(tp->data, tp->header, hdr); 6227c23b892Sbalrog tp->size = hdr; 6237c23b892Sbalrog } 6247c23b892Sbalrog } while (split_size -= bytes); 6251b0009dbSbalrog } else if (!tp->tse && tp->cptse) { 6261b0009dbSbalrog // context descriptor TSE is not set, while data descriptor TSE is set 627362f5fb5SStefan Weil DBGOUT(TXERR, "TCP segmentation error\n"); 6281b0009dbSbalrog } else { 62965f82df0SAnthony Liguori split_size = MIN(sizeof(tp->data) - tp->size, split_size); 63062ecbd35SEduard - Gabriel Munteanu pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size); 6311b0009dbSbalrog tp->size += split_size; 6321b0009dbSbalrog } 6337c23b892Sbalrog 6347c23b892Sbalrog if (!(txd_lower & E1000_TXD_CMD_EOP)) 6357c23b892Sbalrog return; 6361b0009dbSbalrog if (!(tp->tse && tp->cptse && tp->size < hdr)) 6377c23b892Sbalrog xmit_seg(s); 6387c23b892Sbalrog tp->tso_frames = 0; 6397c23b892Sbalrog tp->sum_needed = 0; 6408f2e8d1fSaliguori tp->vlan_needed = 0; 6417c23b892Sbalrog tp->size = 0; 6421b0009dbSbalrog tp->cptse = 0; 6437c23b892Sbalrog } 6447c23b892Sbalrog 6457c23b892Sbalrog static uint32_t 64662ecbd35SEduard - Gabriel Munteanu txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp) 6477c23b892Sbalrog { 6487c23b892Sbalrog uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data); 6497c23b892Sbalrog 6507c23b892Sbalrog if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS))) 6517c23b892Sbalrog return 0; 6527c23b892Sbalrog txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) & 6537c23b892Sbalrog ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU); 6547c23b892Sbalrog dp->upper.data = cpu_to_le32(txd_upper); 65562ecbd35SEduard - Gabriel Munteanu pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp), 65600c3a05bSDavid Gibson &dp->upper, sizeof(dp->upper)); 6577c23b892Sbalrog return E1000_ICR_TXDW; 6587c23b892Sbalrog } 6597c23b892Sbalrog 660d17161f6SKevin Wolf static uint64_t tx_desc_base(E1000State *s) 661d17161f6SKevin Wolf { 662d17161f6SKevin Wolf uint64_t bah = s->mac_reg[TDBAH]; 663d17161f6SKevin Wolf uint64_t bal = s->mac_reg[TDBAL] & ~0xf; 664d17161f6SKevin Wolf 665d17161f6SKevin Wolf return (bah << 32) + bal; 666d17161f6SKevin Wolf } 667d17161f6SKevin Wolf 6687c23b892Sbalrog static void 6697c23b892Sbalrog start_xmit(E1000State *s) 6707c23b892Sbalrog { 67162ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 6727c23b892Sbalrog struct e1000_tx_desc desc; 6737c23b892Sbalrog uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE; 6747c23b892Sbalrog 6757c23b892Sbalrog if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) { 6767c23b892Sbalrog DBGOUT(TX, "tx disabled\n"); 6777c23b892Sbalrog return; 6787c23b892Sbalrog } 6797c23b892Sbalrog 6807c23b892Sbalrog while (s->mac_reg[TDH] != s->mac_reg[TDT]) { 681d17161f6SKevin Wolf base = tx_desc_base(s) + 6827c23b892Sbalrog sizeof(struct e1000_tx_desc) * s->mac_reg[TDH]; 68300c3a05bSDavid Gibson pci_dma_read(&s->dev, base, &desc, sizeof(desc)); 6847c23b892Sbalrog 6857c23b892Sbalrog DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH], 6866106075bSths (void *)(intptr_t)desc.buffer_addr, desc.lower.data, 6877c23b892Sbalrog desc.upper.data); 6887c23b892Sbalrog 6897c23b892Sbalrog process_tx_desc(s, &desc); 69062ecbd35SEduard - Gabriel Munteanu cause |= txdesc_writeback(s, base, &desc); 6917c23b892Sbalrog 6927c23b892Sbalrog if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN]) 6937c23b892Sbalrog s->mac_reg[TDH] = 0; 6947c23b892Sbalrog /* 6957c23b892Sbalrog * the following could happen only if guest sw assigns 6967c23b892Sbalrog * bogus values to TDT/TDLEN. 6977c23b892Sbalrog * there's nothing too intelligent we could do about this. 6987c23b892Sbalrog */ 6997c23b892Sbalrog if (s->mac_reg[TDH] == tdh_start) { 7007c23b892Sbalrog DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", 7017c23b892Sbalrog tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); 7027c23b892Sbalrog break; 7037c23b892Sbalrog } 7047c23b892Sbalrog } 7057c23b892Sbalrog set_ics(s, 0, cause); 7067c23b892Sbalrog } 7077c23b892Sbalrog 7087c23b892Sbalrog static int 7097c23b892Sbalrog receive_filter(E1000State *s, const uint8_t *buf, int size) 7107c23b892Sbalrog { 711af2960f9SBlue Swirl static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 712af2960f9SBlue Swirl static const int mta_shift[] = {4, 3, 2, 0}; 7137c23b892Sbalrog uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp; 7147c23b892Sbalrog 7158f2e8d1fSaliguori if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) { 7168f2e8d1fSaliguori uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14)); 7178f2e8d1fSaliguori uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) + 7188f2e8d1fSaliguori ((vid >> 5) & 0x7f)); 7198f2e8d1fSaliguori if ((vfta & (1 << (vid & 0x1f))) == 0) 7208f2e8d1fSaliguori return 0; 7218f2e8d1fSaliguori } 7228f2e8d1fSaliguori 7237c23b892Sbalrog if (rctl & E1000_RCTL_UPE) // promiscuous 7247c23b892Sbalrog return 1; 7257c23b892Sbalrog 7267c23b892Sbalrog if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast 7277c23b892Sbalrog return 1; 7287c23b892Sbalrog 7297c23b892Sbalrog if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast)) 7307c23b892Sbalrog return 1; 7317c23b892Sbalrog 7327c23b892Sbalrog for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) { 7337c23b892Sbalrog if (!(rp[1] & E1000_RAH_AV)) 7347c23b892Sbalrog continue; 7357c23b892Sbalrog ra[0] = cpu_to_le32(rp[0]); 7367c23b892Sbalrog ra[1] = cpu_to_le32(rp[1]); 7377c23b892Sbalrog if (!memcmp(buf, (uint8_t *)ra, 6)) { 7387c23b892Sbalrog DBGOUT(RXFILTER, 7397c23b892Sbalrog "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n", 7407c23b892Sbalrog (int)(rp - s->mac_reg - RA)/2, 7417c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 7427c23b892Sbalrog return 1; 7437c23b892Sbalrog } 7447c23b892Sbalrog } 7457c23b892Sbalrog DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n", 7467c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 7477c23b892Sbalrog 7487c23b892Sbalrog f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3]; 7497c23b892Sbalrog f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff; 7507c23b892Sbalrog if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f))) 7517c23b892Sbalrog return 1; 7527c23b892Sbalrog DBGOUT(RXFILTER, 7537c23b892Sbalrog "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n", 7547c23b892Sbalrog buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 7557c23b892Sbalrog (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5, 7567c23b892Sbalrog s->mac_reg[MTA + (f >> 5)]); 7577c23b892Sbalrog 7587c23b892Sbalrog return 0; 7597c23b892Sbalrog } 7607c23b892Sbalrog 76199ed7e30Saliguori static void 7624e68f7a0SStefan Hajnoczi e1000_set_link_status(NetClientState *nc) 76399ed7e30Saliguori { 764cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 76599ed7e30Saliguori uint32_t old_status = s->mac_reg[STATUS]; 76699ed7e30Saliguori 767d4044c2aSBjørn Mork if (nc->link_down) { 76871aadd3cSJason Wang e1000_link_down(s); 769d4044c2aSBjørn Mork } else { 77071aadd3cSJason Wang e1000_link_up(s); 771d4044c2aSBjørn Mork } 77299ed7e30Saliguori 77399ed7e30Saliguori if (s->mac_reg[STATUS] != old_status) 77499ed7e30Saliguori set_ics(s, 0, E1000_ICR_LSC); 77599ed7e30Saliguori } 77699ed7e30Saliguori 777322fd48aSMichael S. Tsirkin static bool e1000_has_rxbufs(E1000State *s, size_t total_size) 778322fd48aSMichael S. Tsirkin { 779322fd48aSMichael S. Tsirkin int bufs; 780322fd48aSMichael S. Tsirkin /* Fast-path short packets */ 781322fd48aSMichael S. Tsirkin if (total_size <= s->rxbuf_size) { 782e5b8b0d4SDmitry Fleytman return s->mac_reg[RDH] != s->mac_reg[RDT]; 783322fd48aSMichael S. Tsirkin } 784322fd48aSMichael S. Tsirkin if (s->mac_reg[RDH] < s->mac_reg[RDT]) { 785322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDT] - s->mac_reg[RDH]; 786e5b8b0d4SDmitry Fleytman } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) { 787322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + 788322fd48aSMichael S. Tsirkin s->mac_reg[RDT] - s->mac_reg[RDH]; 789322fd48aSMichael S. Tsirkin } else { 790322fd48aSMichael S. Tsirkin return false; 791322fd48aSMichael S. Tsirkin } 792322fd48aSMichael S. Tsirkin return total_size <= bufs * s->rxbuf_size; 793322fd48aSMichael S. Tsirkin } 794322fd48aSMichael S. Tsirkin 7956cdfab28SMichael S. Tsirkin static int 7964e68f7a0SStefan Hajnoczi e1000_can_receive(NetClientState *nc) 7976cdfab28SMichael S. Tsirkin { 798cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 7996cdfab28SMichael S. Tsirkin 800ddcb73b7SMichael S. Tsirkin return (s->mac_reg[STATUS] & E1000_STATUS_LU) && 801ddcb73b7SMichael S. Tsirkin (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1); 8026cdfab28SMichael S. Tsirkin } 8036cdfab28SMichael S. Tsirkin 804d17161f6SKevin Wolf static uint64_t rx_desc_base(E1000State *s) 805d17161f6SKevin Wolf { 806d17161f6SKevin Wolf uint64_t bah = s->mac_reg[RDBAH]; 807d17161f6SKevin Wolf uint64_t bal = s->mac_reg[RDBAL] & ~0xf; 808d17161f6SKevin Wolf 809d17161f6SKevin Wolf return (bah << 32) + bal; 810d17161f6SKevin Wolf } 811d17161f6SKevin Wolf 8124f1c942bSMark McLoughlin static ssize_t 8134e68f7a0SStefan Hajnoczi e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) 8147c23b892Sbalrog { 815cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 8167c23b892Sbalrog struct e1000_rx_desc desc; 81762ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 8187c23b892Sbalrog unsigned int n, rdt; 8197c23b892Sbalrog uint32_t rdh_start; 8208f2e8d1fSaliguori uint16_t vlan_special = 0; 8218f2e8d1fSaliguori uint8_t vlan_status = 0, vlan_offset = 0; 82278aeb23eSStefan Hajnoczi uint8_t min_buf[MIN_BUF_SIZE]; 823b19487e2SMichael S. Tsirkin size_t desc_offset; 824b19487e2SMichael S. Tsirkin size_t desc_size; 825b19487e2SMichael S. Tsirkin size_t total_size; 8267c23b892Sbalrog 827ddcb73b7SMichael S. Tsirkin if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) { 8284f1c942bSMark McLoughlin return -1; 829ddcb73b7SMichael S. Tsirkin } 830ddcb73b7SMichael S. Tsirkin 831ddcb73b7SMichael S. Tsirkin if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) { 832ddcb73b7SMichael S. Tsirkin return -1; 833ddcb73b7SMichael S. Tsirkin } 8347c23b892Sbalrog 83578aeb23eSStefan Hajnoczi /* Pad to minimum Ethernet frame length */ 83678aeb23eSStefan Hajnoczi if (size < sizeof(min_buf)) { 83778aeb23eSStefan Hajnoczi memcpy(min_buf, buf, size); 83878aeb23eSStefan Hajnoczi memset(&min_buf[size], 0, sizeof(min_buf) - size); 83978aeb23eSStefan Hajnoczi buf = min_buf; 84078aeb23eSStefan Hajnoczi size = sizeof(min_buf); 84178aeb23eSStefan Hajnoczi } 84278aeb23eSStefan Hajnoczi 843b0d9ffcdSMichael Contreras /* Discard oversized packets if !LPE and !SBP. */ 8442c0331f4SMichael Contreras if ((size > MAXIMUM_ETHERNET_LPE_SIZE || 8452c0331f4SMichael Contreras (size > MAXIMUM_ETHERNET_VLAN_SIZE 8462c0331f4SMichael Contreras && !(s->mac_reg[RCTL] & E1000_RCTL_LPE))) 847b0d9ffcdSMichael Contreras && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) { 848b0d9ffcdSMichael Contreras return size; 849b0d9ffcdSMichael Contreras } 850b0d9ffcdSMichael Contreras 8517c23b892Sbalrog if (!receive_filter(s, buf, size)) 8524f1c942bSMark McLoughlin return size; 8537c23b892Sbalrog 8548f2e8d1fSaliguori if (vlan_enabled(s) && is_vlan_packet(s, buf)) { 8558f2e8d1fSaliguori vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14))); 85698835fe3SThomas Monjalon memmove((uint8_t *)buf + 4, buf, 12); 8578f2e8d1fSaliguori vlan_status = E1000_RXD_STAT_VP; 8588f2e8d1fSaliguori vlan_offset = 4; 8598f2e8d1fSaliguori size -= 4; 8608f2e8d1fSaliguori } 8618f2e8d1fSaliguori 8627c23b892Sbalrog rdh_start = s->mac_reg[RDH]; 863b19487e2SMichael S. Tsirkin desc_offset = 0; 864b19487e2SMichael S. Tsirkin total_size = size + fcs_len(s); 865322fd48aSMichael S. Tsirkin if (!e1000_has_rxbufs(s, total_size)) { 866322fd48aSMichael S. Tsirkin set_ics(s, 0, E1000_ICS_RXO); 867322fd48aSMichael S. Tsirkin return -1; 868322fd48aSMichael S. Tsirkin } 8697c23b892Sbalrog do { 870b19487e2SMichael S. Tsirkin desc_size = total_size - desc_offset; 871b19487e2SMichael S. Tsirkin if (desc_size > s->rxbuf_size) { 872b19487e2SMichael S. Tsirkin desc_size = s->rxbuf_size; 873b19487e2SMichael S. Tsirkin } 874d17161f6SKevin Wolf base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH]; 87500c3a05bSDavid Gibson pci_dma_read(&s->dev, base, &desc, sizeof(desc)); 8768f2e8d1fSaliguori desc.special = vlan_special; 8778f2e8d1fSaliguori desc.status |= (vlan_status | E1000_RXD_STAT_DD); 8787c23b892Sbalrog if (desc.buffer_addr) { 879b19487e2SMichael S. Tsirkin if (desc_offset < size) { 880b19487e2SMichael S. Tsirkin size_t copy_size = size - desc_offset; 881b19487e2SMichael S. Tsirkin if (copy_size > s->rxbuf_size) { 882b19487e2SMichael S. Tsirkin copy_size = s->rxbuf_size; 883b19487e2SMichael S. Tsirkin } 88462ecbd35SEduard - Gabriel Munteanu pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr), 88500c3a05bSDavid Gibson buf + desc_offset + vlan_offset, copy_size); 886b19487e2SMichael S. Tsirkin } 887b19487e2SMichael S. Tsirkin desc_offset += desc_size; 888b19487e2SMichael S. Tsirkin desc.length = cpu_to_le16(desc_size); 889ee912ccfSMichael S. Tsirkin if (desc_offset >= total_size) { 8907c23b892Sbalrog desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM; 891b19487e2SMichael S. Tsirkin } else { 892ee912ccfSMichael S. Tsirkin /* Guest zeroing out status is not a hardware requirement. 893ee912ccfSMichael S. Tsirkin Clear EOP in case guest didn't do it. */ 894ee912ccfSMichael S. Tsirkin desc.status &= ~E1000_RXD_STAT_EOP; 895b19487e2SMichael S. Tsirkin } 89643ad7e3eSJes Sorensen } else { // as per intel docs; skip descriptors with null buf addr 8977c23b892Sbalrog DBGOUT(RX, "Null RX descriptor!!\n"); 89843ad7e3eSJes Sorensen } 89900c3a05bSDavid Gibson pci_dma_write(&s->dev, base, &desc, sizeof(desc)); 9007c23b892Sbalrog 9017c23b892Sbalrog if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) 9027c23b892Sbalrog s->mac_reg[RDH] = 0; 9037c23b892Sbalrog /* see comment in start_xmit; same here */ 9047c23b892Sbalrog if (s->mac_reg[RDH] == rdh_start) { 9057c23b892Sbalrog DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", 9067c23b892Sbalrog rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); 9077c23b892Sbalrog set_ics(s, 0, E1000_ICS_RXO); 9084f1c942bSMark McLoughlin return -1; 9097c23b892Sbalrog } 910b19487e2SMichael S. Tsirkin } while (desc_offset < total_size); 9117c23b892Sbalrog 9127c23b892Sbalrog s->mac_reg[GPRC]++; 9137c23b892Sbalrog s->mac_reg[TPR]++; 914a05e8a6eSMichael S. Tsirkin /* TOR - Total Octets Received: 915a05e8a6eSMichael S. Tsirkin * This register includes bytes received in a packet from the <Destination 916a05e8a6eSMichael S. Tsirkin * Address> field through the <CRC> field, inclusively. 917a05e8a6eSMichael S. Tsirkin */ 918a05e8a6eSMichael S. Tsirkin n = s->mac_reg[TORL] + size + /* Always include FCS length. */ 4; 919a05e8a6eSMichael S. Tsirkin if (n < s->mac_reg[TORL]) 9207c23b892Sbalrog s->mac_reg[TORH]++; 921a05e8a6eSMichael S. Tsirkin s->mac_reg[TORL] = n; 9227c23b892Sbalrog 9237c23b892Sbalrog n = E1000_ICS_RXT0; 9247c23b892Sbalrog if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH]) 9257c23b892Sbalrog rdt += s->mac_reg[RDLEN] / sizeof(desc); 926bf16cc8fSaliguori if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >> 927bf16cc8fSaliguori s->rxbuf_min_shift) 9287c23b892Sbalrog n |= E1000_ICS_RXDMT0; 9297c23b892Sbalrog 9307c23b892Sbalrog set_ics(s, 0, n); 9314f1c942bSMark McLoughlin 9324f1c942bSMark McLoughlin return size; 9337c23b892Sbalrog } 9347c23b892Sbalrog 9357c23b892Sbalrog static uint32_t 9367c23b892Sbalrog mac_readreg(E1000State *s, int index) 9377c23b892Sbalrog { 9387c23b892Sbalrog return s->mac_reg[index]; 9397c23b892Sbalrog } 9407c23b892Sbalrog 9417c23b892Sbalrog static uint32_t 9427c23b892Sbalrog mac_icr_read(E1000State *s, int index) 9437c23b892Sbalrog { 9447c23b892Sbalrog uint32_t ret = s->mac_reg[ICR]; 9457c23b892Sbalrog 9467c23b892Sbalrog DBGOUT(INTERRUPT, "ICR read: %x\n", ret); 9477c23b892Sbalrog set_interrupt_cause(s, 0, 0); 9487c23b892Sbalrog return ret; 9497c23b892Sbalrog } 9507c23b892Sbalrog 9517c23b892Sbalrog static uint32_t 9527c23b892Sbalrog mac_read_clr4(E1000State *s, int index) 9537c23b892Sbalrog { 9547c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 9557c23b892Sbalrog 9567c23b892Sbalrog s->mac_reg[index] = 0; 9577c23b892Sbalrog return ret; 9587c23b892Sbalrog } 9597c23b892Sbalrog 9607c23b892Sbalrog static uint32_t 9617c23b892Sbalrog mac_read_clr8(E1000State *s, int index) 9627c23b892Sbalrog { 9637c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 9647c23b892Sbalrog 9657c23b892Sbalrog s->mac_reg[index] = 0; 9667c23b892Sbalrog s->mac_reg[index-1] = 0; 9677c23b892Sbalrog return ret; 9687c23b892Sbalrog } 9697c23b892Sbalrog 9707c23b892Sbalrog static void 9717c23b892Sbalrog mac_writereg(E1000State *s, int index, uint32_t val) 9727c23b892Sbalrog { 9737c23b892Sbalrog s->mac_reg[index] = val; 9747c23b892Sbalrog } 9757c23b892Sbalrog 9767c23b892Sbalrog static void 9777c23b892Sbalrog set_rdt(E1000State *s, int index, uint32_t val) 9787c23b892Sbalrog { 9797c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 980e8b4c680SPaolo Bonzini if (e1000_has_rxbufs(s, 1)) { 981b356f76dSJason Wang qemu_flush_queued_packets(qemu_get_queue(s->nic)); 982e8b4c680SPaolo Bonzini } 9837c23b892Sbalrog } 9847c23b892Sbalrog 9857c23b892Sbalrog static void 9867c23b892Sbalrog set_16bit(E1000State *s, int index, uint32_t val) 9877c23b892Sbalrog { 9887c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 9897c23b892Sbalrog } 9907c23b892Sbalrog 9917c23b892Sbalrog static void 9927c23b892Sbalrog set_dlen(E1000State *s, int index, uint32_t val) 9937c23b892Sbalrog { 9947c23b892Sbalrog s->mac_reg[index] = val & 0xfff80; 9957c23b892Sbalrog } 9967c23b892Sbalrog 9977c23b892Sbalrog static void 9987c23b892Sbalrog set_tctl(E1000State *s, int index, uint32_t val) 9997c23b892Sbalrog { 10007c23b892Sbalrog s->mac_reg[index] = val; 10017c23b892Sbalrog s->mac_reg[TDT] &= 0xffff; 10027c23b892Sbalrog start_xmit(s); 10037c23b892Sbalrog } 10047c23b892Sbalrog 10057c23b892Sbalrog static void 10067c23b892Sbalrog set_icr(E1000State *s, int index, uint32_t val) 10077c23b892Sbalrog { 10087c23b892Sbalrog DBGOUT(INTERRUPT, "set_icr %x\n", val); 10097c23b892Sbalrog set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val); 10107c23b892Sbalrog } 10117c23b892Sbalrog 10127c23b892Sbalrog static void 10137c23b892Sbalrog set_imc(E1000State *s, int index, uint32_t val) 10147c23b892Sbalrog { 10157c23b892Sbalrog s->mac_reg[IMS] &= ~val; 10167c23b892Sbalrog set_ics(s, 0, 0); 10177c23b892Sbalrog } 10187c23b892Sbalrog 10197c23b892Sbalrog static void 10207c23b892Sbalrog set_ims(E1000State *s, int index, uint32_t val) 10217c23b892Sbalrog { 10227c23b892Sbalrog s->mac_reg[IMS] |= val; 10237c23b892Sbalrog set_ics(s, 0, 0); 10247c23b892Sbalrog } 10257c23b892Sbalrog 10267c23b892Sbalrog #define getreg(x) [x] = mac_readreg 10277c23b892Sbalrog static uint32_t (*macreg_readops[])(E1000State *, int) = { 10287c23b892Sbalrog getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL), 10297c23b892Sbalrog getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL), 10307c23b892Sbalrog getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS), 10317c23b892Sbalrog getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL), 1032b1332393SBill Paul getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS), 1033a00b2335SKay Ackermann getreg(TDBAL), getreg(TDBAH), getreg(RDBAH), getreg(RDBAL), 1034a00b2335SKay Ackermann getreg(TDLEN), getreg(RDLEN), 10357c23b892Sbalrog 10367c23b892Sbalrog [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4, 10377c23b892Sbalrog [GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4, 10387c23b892Sbalrog [ICR] = mac_icr_read, [EECD] = get_eecd, [EERD] = flash_eerd_read, 10397c23b892Sbalrog [CRCERRS ... MPC] = &mac_readreg, 10407c23b892Sbalrog [RA ... RA+31] = &mac_readreg, 10417c23b892Sbalrog [MTA ... MTA+127] = &mac_readreg, 10428f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_readreg, 10437c23b892Sbalrog }; 1044b1503cdaSmalc enum { NREADOPS = ARRAY_SIZE(macreg_readops) }; 10457c23b892Sbalrog 10467c23b892Sbalrog #define putreg(x) [x] = mac_writereg 10477c23b892Sbalrog static void (*macreg_writeops[])(E1000State *, int, uint32_t) = { 10487c23b892Sbalrog putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC), 10497c23b892Sbalrog putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH), 1050cab3c825SKevin Wolf putreg(RDBAL), putreg(LEDCTL), putreg(VET), 10517c23b892Sbalrog [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl, 10527c23b892Sbalrog [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics, 10537c23b892Sbalrog [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt, 10547c23b892Sbalrog [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr, 1055cab3c825SKevin Wolf [EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl, 10567c23b892Sbalrog [RA ... RA+31] = &mac_writereg, 10577c23b892Sbalrog [MTA ... MTA+127] = &mac_writereg, 10588f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_writereg, 10597c23b892Sbalrog }; 1060b9d03e35SJason Wang 1061b1503cdaSmalc enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; 10627c23b892Sbalrog 10637c23b892Sbalrog static void 1064a8170e5eSAvi Kivity e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val, 1065ad00a9b9SAvi Kivity unsigned size) 10667c23b892Sbalrog { 10677c23b892Sbalrog E1000State *s = opaque; 10688da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 10697c23b892Sbalrog 107043ad7e3eSJes Sorensen if (index < NWRITEOPS && macreg_writeops[index]) { 10716b59fc74Saurel32 macreg_writeops[index](s, index, val); 107243ad7e3eSJes Sorensen } else if (index < NREADOPS && macreg_readops[index]) { 1073ad00a9b9SAvi Kivity DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val); 107443ad7e3eSJes Sorensen } else { 1075ad00a9b9SAvi Kivity DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n", 10767c23b892Sbalrog index<<2, val); 10777c23b892Sbalrog } 107843ad7e3eSJes Sorensen } 10797c23b892Sbalrog 1080ad00a9b9SAvi Kivity static uint64_t 1081a8170e5eSAvi Kivity e1000_mmio_read(void *opaque, hwaddr addr, unsigned size) 10827c23b892Sbalrog { 10837c23b892Sbalrog E1000State *s = opaque; 10848da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 10857c23b892Sbalrog 10867c23b892Sbalrog if (index < NREADOPS && macreg_readops[index]) 10876b59fc74Saurel32 { 108832600a30SAlexander Graf return macreg_readops[index](s, index); 10896b59fc74Saurel32 } 10907c23b892Sbalrog DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2); 10917c23b892Sbalrog return 0; 10927c23b892Sbalrog } 10937c23b892Sbalrog 1094ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_mmio_ops = { 1095ad00a9b9SAvi Kivity .read = e1000_mmio_read, 1096ad00a9b9SAvi Kivity .write = e1000_mmio_write, 1097ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1098ad00a9b9SAvi Kivity .impl = { 1099ad00a9b9SAvi Kivity .min_access_size = 4, 1100ad00a9b9SAvi Kivity .max_access_size = 4, 1101ad00a9b9SAvi Kivity }, 1102ad00a9b9SAvi Kivity }; 1103ad00a9b9SAvi Kivity 1104a8170e5eSAvi Kivity static uint64_t e1000_io_read(void *opaque, hwaddr addr, 1105ad00a9b9SAvi Kivity unsigned size) 11067c23b892Sbalrog { 1107ad00a9b9SAvi Kivity E1000State *s = opaque; 1108ad00a9b9SAvi Kivity 1109ad00a9b9SAvi Kivity (void)s; 1110ad00a9b9SAvi Kivity return 0; 11117c23b892Sbalrog } 11127c23b892Sbalrog 1113a8170e5eSAvi Kivity static void e1000_io_write(void *opaque, hwaddr addr, 1114ad00a9b9SAvi Kivity uint64_t val, unsigned size) 11157c23b892Sbalrog { 1116ad00a9b9SAvi Kivity E1000State *s = opaque; 1117ad00a9b9SAvi Kivity 1118ad00a9b9SAvi Kivity (void)s; 11197c23b892Sbalrog } 11207c23b892Sbalrog 1121ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_io_ops = { 1122ad00a9b9SAvi Kivity .read = e1000_io_read, 1123ad00a9b9SAvi Kivity .write = e1000_io_write, 1124ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1125ad00a9b9SAvi Kivity }; 1126ad00a9b9SAvi Kivity 1127e482dc3eSJuan Quintela static bool is_version_1(void *opaque, int version_id) 11287c23b892Sbalrog { 1129e482dc3eSJuan Quintela return version_id == 1; 11307c23b892Sbalrog } 11317c23b892Sbalrog 1132ddcb73b7SMichael S. Tsirkin static void e1000_pre_save(void *opaque) 1133ddcb73b7SMichael S. Tsirkin { 1134ddcb73b7SMichael S. Tsirkin E1000State *s = opaque; 1135ddcb73b7SMichael S. Tsirkin NetClientState *nc = qemu_get_queue(s->nic); 11362af234e6SMichael S. Tsirkin 11372af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 11382af234e6SMichael S. Tsirkin return; 11392af234e6SMichael S. Tsirkin } 11402af234e6SMichael S. Tsirkin 1141ddcb73b7SMichael S. Tsirkin /* 1142ddcb73b7SMichael S. Tsirkin * If link is down and auto-negotiation is ongoing, complete 1143ddcb73b7SMichael S. Tsirkin * auto-negotiation immediately. This allows is to look at 1144ddcb73b7SMichael S. Tsirkin * MII_SR_AUTONEG_COMPLETE to infer link status on load. 1145ddcb73b7SMichael S. Tsirkin */ 1146ddcb73b7SMichael S. Tsirkin if (nc->link_down && 1147ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN && 1148ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) { 1149ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; 1150ddcb73b7SMichael S. Tsirkin } 1151ddcb73b7SMichael S. Tsirkin } 1152ddcb73b7SMichael S. Tsirkin 1153e4b82364SAmos Kong static int e1000_post_load(void *opaque, int version_id) 1154e4b82364SAmos Kong { 1155e4b82364SAmos Kong E1000State *s = opaque; 1156b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 1157e4b82364SAmos Kong 1158e4b82364SAmos Kong /* nc.link_down can't be migrated, so infer link_down according 1159ddcb73b7SMichael S. Tsirkin * to link status bit in mac_reg[STATUS]. 1160ddcb73b7SMichael S. Tsirkin * Alternatively, restart link negotiation if it was in progress. */ 1161b356f76dSJason Wang nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0; 11622af234e6SMichael S. Tsirkin 11632af234e6SMichael S. Tsirkin if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { 11642af234e6SMichael S. Tsirkin return 0; 11652af234e6SMichael S. Tsirkin } 11662af234e6SMichael S. Tsirkin 1167ddcb73b7SMichael S. Tsirkin if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN && 1168ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG && 1169ddcb73b7SMichael S. Tsirkin !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) { 1170ddcb73b7SMichael S. Tsirkin nc->link_down = false; 1171ddcb73b7SMichael S. Tsirkin qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); 1172ddcb73b7SMichael S. Tsirkin } 1173e4b82364SAmos Kong 1174e4b82364SAmos Kong return 0; 1175e4b82364SAmos Kong } 1176e4b82364SAmos Kong 1177e482dc3eSJuan Quintela static const VMStateDescription vmstate_e1000 = { 1178e482dc3eSJuan Quintela .name = "e1000", 1179e482dc3eSJuan Quintela .version_id = 2, 1180e482dc3eSJuan Quintela .minimum_version_id = 1, 1181e482dc3eSJuan Quintela .minimum_version_id_old = 1, 1182ddcb73b7SMichael S. Tsirkin .pre_save = e1000_pre_save, 1183e4b82364SAmos Kong .post_load = e1000_post_load, 1184e482dc3eSJuan Quintela .fields = (VMStateField []) { 1185e482dc3eSJuan Quintela VMSTATE_PCI_DEVICE(dev, E1000State), 1186e482dc3eSJuan Quintela VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */ 1187e482dc3eSJuan Quintela VMSTATE_UNUSED(4), /* Was mmio_base. */ 1188e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_size, E1000State), 1189e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_min_shift, E1000State), 1190e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.val_in, E1000State), 1191e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_in, E1000State), 1192e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_out, E1000State), 1193e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.reading, E1000State), 1194e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.old_eecd, E1000State), 1195e482dc3eSJuan Quintela VMSTATE_UINT8(tx.ipcss, E1000State), 1196e482dc3eSJuan Quintela VMSTATE_UINT8(tx.ipcso, E1000State), 1197e482dc3eSJuan Quintela VMSTATE_UINT16(tx.ipcse, E1000State), 1198e482dc3eSJuan Quintela VMSTATE_UINT8(tx.tucss, E1000State), 1199e482dc3eSJuan Quintela VMSTATE_UINT8(tx.tucso, E1000State), 1200e482dc3eSJuan Quintela VMSTATE_UINT16(tx.tucse, E1000State), 1201e482dc3eSJuan Quintela VMSTATE_UINT32(tx.paylen, E1000State), 1202e482dc3eSJuan Quintela VMSTATE_UINT8(tx.hdr_len, E1000State), 1203e482dc3eSJuan Quintela VMSTATE_UINT16(tx.mss, E1000State), 1204e482dc3eSJuan Quintela VMSTATE_UINT16(tx.size, E1000State), 1205e482dc3eSJuan Quintela VMSTATE_UINT16(tx.tso_frames, E1000State), 1206e482dc3eSJuan Quintela VMSTATE_UINT8(tx.sum_needed, E1000State), 1207e482dc3eSJuan Quintela VMSTATE_INT8(tx.ip, E1000State), 1208e482dc3eSJuan Quintela VMSTATE_INT8(tx.tcp, E1000State), 1209e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.header, E1000State), 1210e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.data, E1000State), 1211e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64), 1212e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20), 1213e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[CTRL], E1000State), 1214e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EECD], E1000State), 1215e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EERD], E1000State), 1216e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPRC], E1000State), 1217e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPTC], E1000State), 1218e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICR], E1000State), 1219e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICS], E1000State), 1220e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMC], E1000State), 1221e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMS], E1000State), 1222e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[LEDCTL], E1000State), 1223e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MANC], E1000State), 1224e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MDIC], E1000State), 1225e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MPC], E1000State), 1226e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[PBA], E1000State), 1227e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RCTL], E1000State), 1228e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAH], E1000State), 1229e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAL], E1000State), 1230e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDH], E1000State), 1231e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDLEN], E1000State), 1232e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDT], E1000State), 1233e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[STATUS], E1000State), 1234e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[SWSM], E1000State), 1235e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TCTL], E1000State), 1236e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAH], E1000State), 1237e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAL], E1000State), 1238e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDH], E1000State), 1239e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDLEN], E1000State), 1240e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDT], E1000State), 1241e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORH], E1000State), 1242e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORL], E1000State), 1243e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTH], E1000State), 1244e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTL], E1000State), 1245e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPR], E1000State), 1246e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPT], E1000State), 1247e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TXDCTL], E1000State), 1248e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[WUFC], E1000State), 1249e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[VET], E1000State), 1250e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32), 1251e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128), 1252e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128), 1253e482dc3eSJuan Quintela VMSTATE_END_OF_LIST() 12547c23b892Sbalrog } 1255e482dc3eSJuan Quintela }; 12567c23b892Sbalrog 125788b4e9dbSblueswir1 static const uint16_t e1000_eeprom_template[64] = { 12587c23b892Sbalrog 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 12597c23b892Sbalrog 0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040, 12607c23b892Sbalrog 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700, 12617c23b892Sbalrog 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706, 12627c23b892Sbalrog 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff, 12637c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 12647c23b892Sbalrog 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 12657c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 12667c23b892Sbalrog }; 12677c23b892Sbalrog 12687c23b892Sbalrog /* PCI interface */ 12697c23b892Sbalrog 12707c23b892Sbalrog static void 1271ad00a9b9SAvi Kivity e1000_mmio_setup(E1000State *d) 12727c23b892Sbalrog { 1273f65ed4c1Saliguori int i; 1274f65ed4c1Saliguori const uint32_t excluded_regs[] = { 1275f65ed4c1Saliguori E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, 1276f65ed4c1Saliguori E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE 1277f65ed4c1Saliguori }; 1278f65ed4c1Saliguori 1279*eedfac6fSPaolo Bonzini memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d, 1280*eedfac6fSPaolo Bonzini "e1000-mmio", PNPMMIO_SIZE); 1281ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]); 1282f65ed4c1Saliguori for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) 1283ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4, 1284ad00a9b9SAvi Kivity excluded_regs[i+1] - excluded_regs[i] - 4); 1285*eedfac6fSPaolo Bonzini memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE); 12867c23b892Sbalrog } 12877c23b892Sbalrog 1288b946a153Saliguori static void 12894e68f7a0SStefan Hajnoczi e1000_cleanup(NetClientState *nc) 1290b946a153Saliguori { 1291cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 1292b946a153Saliguori 1293a03e2aecSMark McLoughlin s->nic = NULL; 1294b946a153Saliguori } 1295b946a153Saliguori 1296f90c2bcdSAlex Williamson static void 12974b09be85Saliguori pci_e1000_uninit(PCIDevice *dev) 12984b09be85Saliguori { 12997d9e52bdSJuan Quintela E1000State *d = DO_UPCAST(E1000State, dev, dev); 13004b09be85Saliguori 1301b9d03e35SJason Wang qemu_del_timer(d->autoneg_timer); 1302b9d03e35SJason Wang qemu_free_timer(d->autoneg_timer); 1303ad00a9b9SAvi Kivity memory_region_destroy(&d->mmio); 1304ad00a9b9SAvi Kivity memory_region_destroy(&d->io); 1305948ecf21SJason Wang qemu_del_nic(d->nic); 13064b09be85Saliguori } 13074b09be85Saliguori 1308a03e2aecSMark McLoughlin static NetClientInfo net_e1000_info = { 13092be64a68SLaszlo Ersek .type = NET_CLIENT_OPTIONS_KIND_NIC, 1310a03e2aecSMark McLoughlin .size = sizeof(NICState), 1311a03e2aecSMark McLoughlin .can_receive = e1000_can_receive, 1312a03e2aecSMark McLoughlin .receive = e1000_receive, 1313a03e2aecSMark McLoughlin .cleanup = e1000_cleanup, 1314a03e2aecSMark McLoughlin .link_status_changed = e1000_set_link_status, 1315a03e2aecSMark McLoughlin }; 1316a03e2aecSMark McLoughlin 131781a322d4SGerd Hoffmann static int pci_e1000_init(PCIDevice *pci_dev) 13187c23b892Sbalrog { 13197d9e52bdSJuan Quintela E1000State *d = DO_UPCAST(E1000State, dev, pci_dev); 13207c23b892Sbalrog uint8_t *pci_conf; 13217c23b892Sbalrog uint16_t checksum = 0; 13227c23b892Sbalrog int i; 1323fbdaa002SGerd Hoffmann uint8_t *macaddr; 1324aff427a1SChris Wright 13257c23b892Sbalrog pci_conf = d->dev.config; 13267c23b892Sbalrog 1327a9cbacb0SMichael S. Tsirkin /* TODO: RST# value should be 0, PCI spec 6.2.4 */ 1328a9cbacb0SMichael S. Tsirkin pci_conf[PCI_CACHE_LINE_SIZE] = 0x10; 13297c23b892Sbalrog 1330817e0b6fSMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ 13317c23b892Sbalrog 1332ad00a9b9SAvi Kivity e1000_mmio_setup(d); 13337c23b892Sbalrog 1334e824b2ccSAvi Kivity pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 13357c23b892Sbalrog 1336e824b2ccSAvi Kivity pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io); 13377c23b892Sbalrog 13387c23b892Sbalrog memmove(d->eeprom_data, e1000_eeprom_template, 13397c23b892Sbalrog sizeof e1000_eeprom_template); 1340fbdaa002SGerd Hoffmann qemu_macaddr_default_if_unset(&d->conf.macaddr); 1341fbdaa002SGerd Hoffmann macaddr = d->conf.macaddr.a; 13427c23b892Sbalrog for (i = 0; i < 3; i++) 13439d07d757SPaul Brook d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i]; 13447c23b892Sbalrog for (i = 0; i < EEPROM_CHECKSUM_REG; i++) 13457c23b892Sbalrog checksum += d->eeprom_data[i]; 13467c23b892Sbalrog checksum = (uint16_t) EEPROM_SUM - checksum; 13477c23b892Sbalrog d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum; 13487c23b892Sbalrog 1349a03e2aecSMark McLoughlin d->nic = qemu_new_nic(&net_e1000_info, &d->conf, 1350f79f2bfcSAnthony Liguori object_get_typename(OBJECT(d)), d->dev.qdev.id, d); 13517c23b892Sbalrog 1352b356f76dSJason Wang qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); 13531ca4d09aSGleb Natapov 13541ca4d09aSGleb Natapov add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); 13551ca4d09aSGleb Natapov 1356b9d03e35SJason Wang d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d); 1357b9d03e35SJason Wang 135881a322d4SGerd Hoffmann return 0; 13597c23b892Sbalrog } 13609d07d757SPaul Brook 1361fbdaa002SGerd Hoffmann static void qdev_e1000_reset(DeviceState *dev) 1362fbdaa002SGerd Hoffmann { 1363fbdaa002SGerd Hoffmann E1000State *d = DO_UPCAST(E1000State, dev.qdev, dev); 1364fbdaa002SGerd Hoffmann e1000_reset(d); 1365fbdaa002SGerd Hoffmann } 1366fbdaa002SGerd Hoffmann 136740021f08SAnthony Liguori static Property e1000_properties[] = { 1368fbdaa002SGerd Hoffmann DEFINE_NIC_PROPERTIES(E1000State, conf), 13692af234e6SMichael S. Tsirkin DEFINE_PROP_BIT("autonegotiation", E1000State, 13702af234e6SMichael S. Tsirkin compat_flags, E1000_FLAG_AUTONEG_BIT, true), 1371fbdaa002SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 137240021f08SAnthony Liguori }; 137340021f08SAnthony Liguori 137440021f08SAnthony Liguori static void e1000_class_init(ObjectClass *klass, void *data) 137540021f08SAnthony Liguori { 137639bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 137740021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 137840021f08SAnthony Liguori 137940021f08SAnthony Liguori k->init = pci_e1000_init; 138040021f08SAnthony Liguori k->exit = pci_e1000_uninit; 1381c45e5b5bSGerd Hoffmann k->romfile = "efi-e1000.rom"; 138240021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_INTEL; 138340021f08SAnthony Liguori k->device_id = E1000_DEVID; 138440021f08SAnthony Liguori k->revision = 0x03; 138540021f08SAnthony Liguori k->class_id = PCI_CLASS_NETWORK_ETHERNET; 138639bffca2SAnthony Liguori dc->desc = "Intel Gigabit Ethernet"; 138739bffca2SAnthony Liguori dc->reset = qdev_e1000_reset; 138839bffca2SAnthony Liguori dc->vmsd = &vmstate_e1000; 138939bffca2SAnthony Liguori dc->props = e1000_properties; 1390fbdaa002SGerd Hoffmann } 139140021f08SAnthony Liguori 13928c43a6f0SAndreas Färber static const TypeInfo e1000_info = { 139340021f08SAnthony Liguori .name = "e1000", 139439bffca2SAnthony Liguori .parent = TYPE_PCI_DEVICE, 139539bffca2SAnthony Liguori .instance_size = sizeof(E1000State), 139640021f08SAnthony Liguori .class_init = e1000_class_init, 13970aab0d3aSGerd Hoffmann }; 13980aab0d3aSGerd Hoffmann 139983f7d43aSAndreas Färber static void e1000_register_types(void) 14009d07d757SPaul Brook { 140139bffca2SAnthony Liguori type_register_static(&e1000_info); 14029d07d757SPaul Brook } 14039d07d757SPaul Brook 140483f7d43aSAndreas Färber type_init(e1000_register_types) 1405