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 1661f3c91aSChetan Pant * version 2.1 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 28e8d40465SPeter Maydell #include "qemu/osdep.h" 2983c9f4caSPaolo Bonzini #include "hw/pci/pci.h" 30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 31d6454270SMarkus Armbruster #include "migration/vmstate.h" 32*a1d7e475SChristina Wang #include "net/eth.h" 331422e32dSPaolo Bonzini #include "net/net.h" 347200ac3cSMark McLoughlin #include "net/checksum.h" 359c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 369c17d615SPaolo Bonzini #include "sysemu/dma.h" 3797410ddeSVincenzo Maffione #include "qemu/iov.h" 380b8fa32fSMarkus Armbruster #include "qemu/module.h" 3920302e71SMichael S. Tsirkin #include "qemu/range.h" 407c23b892Sbalrog 41093454e2SDmitry Fleytman #include "e1000x_common.h" 421001cf45SJason Wang #include "trace.h" 43db1015e9SEduardo Habkost #include "qom/object.h" 447c23b892Sbalrog 453b274301SLeonid Bloch static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 463b274301SLeonid Bloch 47b4053c64SJason Wang /* #define E1000_DEBUG */ 487c23b892Sbalrog 4927124888SJes Sorensen #ifdef E1000_DEBUG 507c23b892Sbalrog enum { 517c23b892Sbalrog DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT, 527c23b892Sbalrog DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM, 537c23b892Sbalrog DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR, 54f9c1cdf4SJason Wang DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET, 557c23b892Sbalrog }; 567c23b892Sbalrog #define DBGBIT(x) (1<<DEBUG_##x) 577c23b892Sbalrog static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); 587c23b892Sbalrog 596c7f4b47SBlue Swirl #define DBGOUT(what, fmt, ...) do { \ 607c23b892Sbalrog if (debugflags & DBGBIT(what)) \ 616c7f4b47SBlue Swirl fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \ 627c23b892Sbalrog } while (0) 637c23b892Sbalrog #else 646c7f4b47SBlue Swirl #define DBGOUT(what, fmt, ...) do {} while (0) 657c23b892Sbalrog #endif 667c23b892Sbalrog 677c23b892Sbalrog #define IOPORT_SIZE 0x40 68e94bbefeSaurel32 #define PNPMMIO_SIZE 0x20000 6978aeb23eSStefan Hajnoczi #define MIN_BUF_SIZE 60 /* Min. octets in an ethernet frame sans FCS */ 707c23b892Sbalrog 7197410ddeSVincenzo Maffione #define MAXIMUM_ETHERNET_HDR_LEN (14+4) 7297410ddeSVincenzo Maffione 737c23b892Sbalrog /* 747c23b892Sbalrog * HW models: 758597f2e1SGabriel L. Somlo * E1000_DEV_ID_82540EM works with Windows, Linux, and OS X <= 10.8 767c23b892Sbalrog * E1000_DEV_ID_82544GC_COPPER appears to work; not well tested 778597f2e1SGabriel L. Somlo * E1000_DEV_ID_82545EM_COPPER works with Linux and OS X >= 10.6 787c23b892Sbalrog * Others never tested 797c23b892Sbalrog */ 807c23b892Sbalrog 81db1015e9SEduardo Habkost struct E1000State_st { 82b08340d5SAndreas Färber /*< private >*/ 83b08340d5SAndreas Färber PCIDevice parent_obj; 84b08340d5SAndreas Färber /*< public >*/ 85b08340d5SAndreas Färber 86a03e2aecSMark McLoughlin NICState *nic; 87fbdaa002SGerd Hoffmann NICConf conf; 88ad00a9b9SAvi Kivity MemoryRegion mmio; 89ad00a9b9SAvi Kivity MemoryRegion io; 907c23b892Sbalrog 917c23b892Sbalrog uint32_t mac_reg[0x8000]; 927c23b892Sbalrog uint16_t phy_reg[0x20]; 937c23b892Sbalrog uint16_t eeprom_data[64]; 947c23b892Sbalrog 957c23b892Sbalrog uint32_t rxbuf_size; 967c23b892Sbalrog uint32_t rxbuf_min_shift; 977c23b892Sbalrog struct e1000_tx { 987c23b892Sbalrog unsigned char header[256]; 998f2e8d1fSaliguori unsigned char vlan_header[4]; 100b10fec9bSStefan Weil /* Fields vlan and data must not be reordered or separated. */ 1018f2e8d1fSaliguori unsigned char vlan[4]; 1027c23b892Sbalrog unsigned char data[0x10000]; 1037c23b892Sbalrog uint16_t size; 1048f2e8d1fSaliguori unsigned char vlan_needed; 1057d08c73eSEd Swierk via Qemu-devel unsigned char sum_needed; 1067d08c73eSEd Swierk via Qemu-devel bool cptse; 107093454e2SDmitry Fleytman e1000x_txd_props props; 108d62644b4SEd Swierk via Qemu-devel e1000x_txd_props tso_props; 1097c23b892Sbalrog uint16_t tso_frames; 1107c23b892Sbalrog } tx; 1117c23b892Sbalrog 1127c23b892Sbalrog struct { 11320f3e863SLeonid Bloch uint32_t val_in; /* shifted in from guest driver */ 1147c23b892Sbalrog uint16_t bitnum_in; 1157c23b892Sbalrog uint16_t bitnum_out; 1167c23b892Sbalrog uint16_t reading; 1177c23b892Sbalrog uint32_t old_eecd; 1187c23b892Sbalrog } eecd_state; 119b9d03e35SJason Wang 120b9d03e35SJason Wang QEMUTimer *autoneg_timer; 1212af234e6SMichael S. Tsirkin 122e9845f09SVincenzo Maffione QEMUTimer *mit_timer; /* Mitigation timer. */ 123e9845f09SVincenzo Maffione bool mit_timer_on; /* Mitigation timer is running. */ 124e9845f09SVincenzo Maffione bool mit_irq_level; /* Tracks interrupt pin level. */ 125e9845f09SVincenzo Maffione uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */ 126e9845f09SVincenzo Maffione 127157628d0Syuchenlin QEMUTimer *flush_queue_timer; 128157628d0Syuchenlin 1292af234e6SMichael S. Tsirkin /* Compatibility flags for migration to/from qemu 1.3.0 and older */ 1302af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG_BIT 0 131e9845f09SVincenzo Maffione #define E1000_FLAG_MIT_BIT 1 1329e117734SLeonid Bloch #define E1000_FLAG_MAC_BIT 2 13346f2a9ecSDr. David Alan Gilbert #define E1000_FLAG_TSO_BIT 3 134*a1d7e475SChristina Wang #define E1000_FLAG_VET_BIT 4 1352af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) 136e9845f09SVincenzo Maffione #define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT) 1379e117734SLeonid Bloch #define E1000_FLAG_MAC (1 << E1000_FLAG_MAC_BIT) 13846f2a9ecSDr. David Alan Gilbert #define E1000_FLAG_TSO (1 << E1000_FLAG_TSO_BIT) 139*a1d7e475SChristina Wang #define E1000_FLAG_VET (1 << E1000_FLAG_VET_BIT) 140*a1d7e475SChristina Wang 1412af234e6SMichael S. Tsirkin uint32_t compat_flags; 1423c4053c5SDr. David Alan Gilbert bool received_tx_tso; 143ff214d42SDr. David Alan Gilbert bool use_tso_for_migration; 14459354484SDr. David Alan Gilbert e1000x_txd_props mig_props; 145db1015e9SEduardo Habkost }; 146db1015e9SEduardo Habkost typedef struct E1000State_st E1000State; 1477c23b892Sbalrog 148bc0f0674SLeonid Bloch #define chkflag(x) (s->compat_flags & E1000_FLAG_##x) 149bc0f0674SLeonid Bloch 150db1015e9SEduardo Habkost struct E1000BaseClass { 1518597f2e1SGabriel L. Somlo PCIDeviceClass parent_class; 1528597f2e1SGabriel L. Somlo uint16_t phy_id2; 153db1015e9SEduardo Habkost }; 154db1015e9SEduardo Habkost typedef struct E1000BaseClass E1000BaseClass; 1558597f2e1SGabriel L. Somlo 1568597f2e1SGabriel L. Somlo #define TYPE_E1000_BASE "e1000-base" 157567a3c9eSPeter Crosthwaite 1588110fa1dSEduardo Habkost DECLARE_OBJ_CHECKERS(E1000State, E1000BaseClass, 1598110fa1dSEduardo Habkost E1000, TYPE_E1000_BASE) 1608597f2e1SGabriel L. Somlo 161567a3c9eSPeter Crosthwaite 16271aadd3cSJason Wang static void 16371aadd3cSJason Wang e1000_link_up(E1000State *s) 16471aadd3cSJason Wang { 165093454e2SDmitry Fleytman e1000x_update_regs_on_link_up(s->mac_reg, s->phy_reg); 166093454e2SDmitry Fleytman 167093454e2SDmitry Fleytman /* E1000_STATUS_LU is tested by e1000_can_receive() */ 168093454e2SDmitry Fleytman qemu_flush_queued_packets(qemu_get_queue(s->nic)); 169093454e2SDmitry Fleytman } 170093454e2SDmitry Fleytman 171093454e2SDmitry Fleytman static void 172093454e2SDmitry Fleytman e1000_autoneg_done(E1000State *s) 173093454e2SDmitry Fleytman { 174093454e2SDmitry Fleytman e1000x_update_regs_on_autoneg_done(s->mac_reg, s->phy_reg); 1755df6a185SStefan Hajnoczi 1765df6a185SStefan Hajnoczi /* E1000_STATUS_LU is tested by e1000_can_receive() */ 1775df6a185SStefan Hajnoczi qemu_flush_queued_packets(qemu_get_queue(s->nic)); 17871aadd3cSJason Wang } 17971aadd3cSJason Wang 1801195fed9SGabriel L. Somlo static bool 1811195fed9SGabriel L. Somlo have_autoneg(E1000State *s) 1821195fed9SGabriel L. Somlo { 183bc0f0674SLeonid Bloch return chkflag(AUTONEG) && (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN); 1841195fed9SGabriel L. Somlo } 1851195fed9SGabriel L. Somlo 186b9d03e35SJason Wang static void 187b9d03e35SJason Wang set_phy_ctrl(E1000State *s, int index, uint16_t val) 188b9d03e35SJason Wang { 1891195fed9SGabriel L. Somlo /* bits 0-5 reserved; MII_CR_[RESTART_AUTO_NEG,RESET] are self clearing */ 1901195fed9SGabriel L. Somlo s->phy_reg[PHY_CTRL] = val & ~(0x3f | 1911195fed9SGabriel L. Somlo MII_CR_RESET | 1921195fed9SGabriel L. Somlo MII_CR_RESTART_AUTO_NEG); 1931195fed9SGabriel L. Somlo 1942af234e6SMichael S. Tsirkin /* 1952af234e6SMichael S. Tsirkin * QEMU 1.3 does not support link auto-negotiation emulation, so if we 1962af234e6SMichael S. Tsirkin * migrate during auto negotiation, after migration the link will be 1972af234e6SMichael S. Tsirkin * down. 1982af234e6SMichael S. Tsirkin */ 1991195fed9SGabriel L. Somlo if (have_autoneg(s) && (val & MII_CR_RESTART_AUTO_NEG)) { 200093454e2SDmitry Fleytman e1000x_restart_autoneg(s->mac_reg, s->phy_reg, s->autoneg_timer); 201b9d03e35SJason Wang } 202b9d03e35SJason Wang } 203b9d03e35SJason Wang 204b9d03e35SJason Wang static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = { 205b9d03e35SJason Wang [PHY_CTRL] = set_phy_ctrl, 206b9d03e35SJason Wang }; 207b9d03e35SJason Wang 208b9d03e35SJason Wang enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) }; 209b9d03e35SJason Wang 2107c23b892Sbalrog enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W }; 21188b4e9dbSblueswir1 static const char phy_regcap[0x20] = { 2127c23b892Sbalrog [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW, 2137c23b892Sbalrog [PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW, 2147c23b892Sbalrog [PHY_CTRL] = PHY_RW, [PHY_1000T_CTRL] = PHY_RW, 2157c23b892Sbalrog [PHY_LP_ABILITY] = PHY_R, [PHY_1000T_STATUS] = PHY_R, 2167c23b892Sbalrog [PHY_AUTONEG_ADV] = PHY_RW, [M88E1000_RX_ERR_CNTR] = PHY_R, 2176883b591SGabriel L. Somlo [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R, 2186883b591SGabriel L. Somlo [PHY_AUTONEG_EXP] = PHY_R, 2197c23b892Sbalrog }; 2207c23b892Sbalrog 2218597f2e1SGabriel L. Somlo /* PHY_ID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */ 222814cd3acSMichael S. Tsirkin static const uint16_t phy_reg_init[] = { 2239616c290SGabriel L. Somlo [PHY_CTRL] = MII_CR_SPEED_SELECT_MSB | 2249616c290SGabriel L. Somlo MII_CR_FULL_DUPLEX | 2259616c290SGabriel L. Somlo MII_CR_AUTO_NEG_EN, 2269616c290SGabriel L. Somlo 2279616c290SGabriel L. Somlo [PHY_STATUS] = MII_SR_EXTENDED_CAPS | 2289616c290SGabriel L. Somlo MII_SR_LINK_STATUS | /* link initially up */ 2299616c290SGabriel L. Somlo MII_SR_AUTONEG_CAPS | 2309616c290SGabriel L. Somlo /* MII_SR_AUTONEG_COMPLETE: initially NOT completed */ 2319616c290SGabriel L. Somlo MII_SR_PREAMBLE_SUPPRESS | 2329616c290SGabriel L. Somlo MII_SR_EXTENDED_STATUS | 2339616c290SGabriel L. Somlo MII_SR_10T_HD_CAPS | 2349616c290SGabriel L. Somlo MII_SR_10T_FD_CAPS | 2359616c290SGabriel L. Somlo MII_SR_100X_HD_CAPS | 2369616c290SGabriel L. Somlo MII_SR_100X_FD_CAPS, 2379616c290SGabriel L. Somlo 2389616c290SGabriel L. Somlo [PHY_ID1] = 0x141, 2399616c290SGabriel L. Somlo /* [PHY_ID2] configured per DevId, from e1000_reset() */ 2409616c290SGabriel L. Somlo [PHY_AUTONEG_ADV] = 0xde1, 2419616c290SGabriel L. Somlo [PHY_LP_ABILITY] = 0x1e0, 2429616c290SGabriel L. Somlo [PHY_1000T_CTRL] = 0x0e00, 2439616c290SGabriel L. Somlo [PHY_1000T_STATUS] = 0x3c00, 2449616c290SGabriel L. Somlo [M88E1000_PHY_SPEC_CTRL] = 0x360, 245814cd3acSMichael S. Tsirkin [M88E1000_PHY_SPEC_STATUS] = 0xac00, 2469616c290SGabriel L. Somlo [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, 247814cd3acSMichael S. Tsirkin }; 248814cd3acSMichael S. Tsirkin 249814cd3acSMichael S. Tsirkin static const uint32_t mac_reg_init[] = { 250814cd3acSMichael S. Tsirkin [PBA] = 0x00100030, 251814cd3acSMichael S. Tsirkin [LEDCTL] = 0x602, 252814cd3acSMichael S. Tsirkin [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | 253814cd3acSMichael S. Tsirkin E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, 254814cd3acSMichael S. Tsirkin [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | 255814cd3acSMichael S. Tsirkin E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | 256814cd3acSMichael S. Tsirkin E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | 257814cd3acSMichael S. Tsirkin E1000_STATUS_LU, 258814cd3acSMichael S. Tsirkin [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | 259814cd3acSMichael S. Tsirkin E1000_MANC_ARP_EN | E1000_MANC_0298_EN | 260814cd3acSMichael S. Tsirkin E1000_MANC_RMCP_EN, 261814cd3acSMichael S. Tsirkin }; 262814cd3acSMichael S. Tsirkin 263e9845f09SVincenzo Maffione /* Helper function, *curr == 0 means the value is not set */ 264e9845f09SVincenzo Maffione static inline void 265e9845f09SVincenzo Maffione mit_update_delay(uint32_t *curr, uint32_t value) 266e9845f09SVincenzo Maffione { 267e9845f09SVincenzo Maffione if (value && (*curr == 0 || value < *curr)) { 268e9845f09SVincenzo Maffione *curr = value; 269e9845f09SVincenzo Maffione } 270e9845f09SVincenzo Maffione } 271e9845f09SVincenzo Maffione 2727c23b892Sbalrog static void 2737c23b892Sbalrog set_interrupt_cause(E1000State *s, int index, uint32_t val) 2747c23b892Sbalrog { 275b08340d5SAndreas Färber PCIDevice *d = PCI_DEVICE(s); 276e9845f09SVincenzo Maffione uint32_t pending_ints; 277e9845f09SVincenzo Maffione uint32_t mit_delay; 278b08340d5SAndreas Färber 2797c23b892Sbalrog s->mac_reg[ICR] = val; 280a52a8841SMichael S. Tsirkin 281a52a8841SMichael S. Tsirkin /* 282a52a8841SMichael S. Tsirkin * Make sure ICR and ICS registers have the same value. 283a52a8841SMichael S. Tsirkin * The spec says that the ICS register is write-only. However in practice, 284a52a8841SMichael S. Tsirkin * on real hardware ICS is readable, and for reads it has the same value as 285a52a8841SMichael S. Tsirkin * ICR (except that ICS does not have the clear on read behaviour of ICR). 286a52a8841SMichael S. Tsirkin * 287a52a8841SMichael S. Tsirkin * The VxWorks PRO/1000 driver uses this behaviour. 288a52a8841SMichael S. Tsirkin */ 289b1332393SBill Paul s->mac_reg[ICS] = val; 290a52a8841SMichael S. Tsirkin 291e9845f09SVincenzo Maffione pending_ints = (s->mac_reg[IMS] & s->mac_reg[ICR]); 292e9845f09SVincenzo Maffione if (!s->mit_irq_level && pending_ints) { 293e9845f09SVincenzo Maffione /* 294e9845f09SVincenzo Maffione * Here we detect a potential raising edge. We postpone raising the 295e9845f09SVincenzo Maffione * interrupt line if we are inside the mitigation delay window 296e9845f09SVincenzo Maffione * (s->mit_timer_on == 1). 297e9845f09SVincenzo Maffione * We provide a partial implementation of interrupt mitigation, 298e9845f09SVincenzo Maffione * emulating only RADV, TADV and ITR (lower 16 bits, 1024ns units for 299e9845f09SVincenzo Maffione * RADV and TADV, 256ns units for ITR). RDTR is only used to enable 300e9845f09SVincenzo Maffione * RADV; relative timers based on TIDV and RDTR are not implemented. 301e9845f09SVincenzo Maffione */ 302e9845f09SVincenzo Maffione if (s->mit_timer_on) { 303e9845f09SVincenzo Maffione return; 304e9845f09SVincenzo Maffione } 305bc0f0674SLeonid Bloch if (chkflag(MIT)) { 306e9845f09SVincenzo Maffione /* Compute the next mitigation delay according to pending 307e9845f09SVincenzo Maffione * interrupts and the current values of RADV (provided 308e9845f09SVincenzo Maffione * RDTR!=0), TADV and ITR. 309e9845f09SVincenzo Maffione * Then rearm the timer. 310e9845f09SVincenzo Maffione */ 311e9845f09SVincenzo Maffione mit_delay = 0; 312e9845f09SVincenzo Maffione if (s->mit_ide && 313e9845f09SVincenzo Maffione (pending_ints & (E1000_ICR_TXQE | E1000_ICR_TXDW))) { 314e9845f09SVincenzo Maffione mit_update_delay(&mit_delay, s->mac_reg[TADV] * 4); 315e9845f09SVincenzo Maffione } 316e9845f09SVincenzo Maffione if (s->mac_reg[RDTR] && (pending_ints & E1000_ICS_RXT0)) { 317e9845f09SVincenzo Maffione mit_update_delay(&mit_delay, s->mac_reg[RADV] * 4); 318e9845f09SVincenzo Maffione } 319e9845f09SVincenzo Maffione mit_update_delay(&mit_delay, s->mac_reg[ITR]); 320e9845f09SVincenzo Maffione 32174004e8cSSameeh Jubran /* 32274004e8cSSameeh Jubran * According to e1000 SPEC, the Ethernet controller guarantees 32374004e8cSSameeh Jubran * a maximum observable interrupt rate of 7813 interrupts/sec. 32474004e8cSSameeh Jubran * Thus if mit_delay < 500 then the delay should be set to the 32574004e8cSSameeh Jubran * minimum delay possible which is 500. 32674004e8cSSameeh Jubran */ 32774004e8cSSameeh Jubran mit_delay = (mit_delay < 500) ? 500 : mit_delay; 32874004e8cSSameeh Jubran 329e9845f09SVincenzo Maffione s->mit_timer_on = 1; 330e9845f09SVincenzo Maffione timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 331e9845f09SVincenzo Maffione mit_delay * 256); 332e9845f09SVincenzo Maffione s->mit_ide = 0; 333e9845f09SVincenzo Maffione } 334e9845f09SVincenzo Maffione } 335e9845f09SVincenzo Maffione 336e9845f09SVincenzo Maffione s->mit_irq_level = (pending_ints != 0); 3379e64f8a3SMarcel Apfelbaum pci_set_irq(d, s->mit_irq_level); 338e9845f09SVincenzo Maffione } 339e9845f09SVincenzo Maffione 340e9845f09SVincenzo Maffione static void 341e9845f09SVincenzo Maffione e1000_mit_timer(void *opaque) 342e9845f09SVincenzo Maffione { 343e9845f09SVincenzo Maffione E1000State *s = opaque; 344e9845f09SVincenzo Maffione 345e9845f09SVincenzo Maffione s->mit_timer_on = 0; 346e9845f09SVincenzo Maffione /* Call set_interrupt_cause to update the irq level (if necessary). */ 347e9845f09SVincenzo Maffione set_interrupt_cause(s, 0, s->mac_reg[ICR]); 3487c23b892Sbalrog } 3497c23b892Sbalrog 3507c23b892Sbalrog static void 3517c23b892Sbalrog set_ics(E1000State *s, int index, uint32_t val) 3527c23b892Sbalrog { 3537c23b892Sbalrog DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR], 3547c23b892Sbalrog s->mac_reg[IMS]); 3557c23b892Sbalrog set_interrupt_cause(s, 0, val | s->mac_reg[ICR]); 3567c23b892Sbalrog } 3577c23b892Sbalrog 358d52aec95SGabriel L. Somlo static void 359d52aec95SGabriel L. Somlo e1000_autoneg_timer(void *opaque) 360d52aec95SGabriel L. Somlo { 361d52aec95SGabriel L. Somlo E1000State *s = opaque; 362d52aec95SGabriel L. Somlo if (!qemu_get_queue(s->nic)->link_down) { 363093454e2SDmitry Fleytman e1000_autoneg_done(s); 364d52aec95SGabriel L. Somlo set_ics(s, 0, E1000_ICS_LSC); /* signal link status change to guest */ 365d52aec95SGabriel L. Somlo } 366d52aec95SGabriel L. Somlo } 367d52aec95SGabriel L. Somlo 368*a1d7e475SChristina Wang static bool e1000_vet_init_need(void *opaque) 369*a1d7e475SChristina Wang { 370*a1d7e475SChristina Wang E1000State *s = opaque; 371*a1d7e475SChristina Wang 372*a1d7e475SChristina Wang return chkflag(VET); 373*a1d7e475SChristina Wang } 374*a1d7e475SChristina Wang 375814cd3acSMichael S. Tsirkin static void e1000_reset(void *opaque) 376814cd3acSMichael S. Tsirkin { 377814cd3acSMichael S. Tsirkin E1000State *d = opaque; 378c51325d8SEduardo Habkost E1000BaseClass *edc = E1000_GET_CLASS(d); 379372254c6SGabriel L. Somlo uint8_t *macaddr = d->conf.macaddr.a; 380814cd3acSMichael S. Tsirkin 381bc72ad67SAlex Bligh timer_del(d->autoneg_timer); 382e9845f09SVincenzo Maffione timer_del(d->mit_timer); 383157628d0Syuchenlin timer_del(d->flush_queue_timer); 384e9845f09SVincenzo Maffione d->mit_timer_on = 0; 385e9845f09SVincenzo Maffione d->mit_irq_level = 0; 386e9845f09SVincenzo Maffione d->mit_ide = 0; 387814cd3acSMichael S. Tsirkin memset(d->phy_reg, 0, sizeof d->phy_reg); 388814cd3acSMichael S. Tsirkin memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); 3898597f2e1SGabriel L. Somlo d->phy_reg[PHY_ID2] = edc->phy_id2; 390814cd3acSMichael S. Tsirkin memset(d->mac_reg, 0, sizeof d->mac_reg); 391814cd3acSMichael S. Tsirkin memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); 392814cd3acSMichael S. Tsirkin d->rxbuf_min_shift = 1; 393814cd3acSMichael S. Tsirkin memset(&d->tx, 0, sizeof d->tx); 394814cd3acSMichael S. Tsirkin 395b356f76dSJason Wang if (qemu_get_queue(d->nic)->link_down) { 396093454e2SDmitry Fleytman e1000x_update_regs_on_link_down(d->mac_reg, d->phy_reg); 397814cd3acSMichael S. Tsirkin } 398372254c6SGabriel L. Somlo 399093454e2SDmitry Fleytman e1000x_reset_mac_addr(d->nic, d->mac_reg, macaddr); 400*a1d7e475SChristina Wang 401*a1d7e475SChristina Wang if (e1000_vet_init_need(d)) { 402*a1d7e475SChristina Wang d->mac_reg[VET] = ETH_P_VLAN; 403*a1d7e475SChristina Wang } 404814cd3acSMichael S. Tsirkin } 405814cd3acSMichael S. Tsirkin 4067c23b892Sbalrog static void 407cab3c825SKevin Wolf set_ctrl(E1000State *s, int index, uint32_t val) 408cab3c825SKevin Wolf { 409cab3c825SKevin Wolf /* RST is self clearing */ 410cab3c825SKevin Wolf s->mac_reg[CTRL] = val & ~E1000_CTRL_RST; 411cab3c825SKevin Wolf } 412cab3c825SKevin Wolf 413cab3c825SKevin Wolf static void 414157628d0Syuchenlin e1000_flush_queue_timer(void *opaque) 415157628d0Syuchenlin { 416157628d0Syuchenlin E1000State *s = opaque; 417157628d0Syuchenlin 418157628d0Syuchenlin qemu_flush_queued_packets(qemu_get_queue(s->nic)); 419157628d0Syuchenlin } 420157628d0Syuchenlin 421157628d0Syuchenlin static void 4227c23b892Sbalrog set_rx_control(E1000State *s, int index, uint32_t val) 4237c23b892Sbalrog { 4247c23b892Sbalrog s->mac_reg[RCTL] = val; 425093454e2SDmitry Fleytman s->rxbuf_size = e1000x_rxbufsize(val); 4267c23b892Sbalrog s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; 4277c23b892Sbalrog DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], 4287c23b892Sbalrog s->mac_reg[RCTL]); 429157628d0Syuchenlin timer_mod(s->flush_queue_timer, 430157628d0Syuchenlin qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); 4317c23b892Sbalrog } 4327c23b892Sbalrog 4337c23b892Sbalrog static void 4347c23b892Sbalrog set_mdic(E1000State *s, int index, uint32_t val) 4357c23b892Sbalrog { 4367c23b892Sbalrog uint32_t data = val & E1000_MDIC_DATA_MASK; 4377c23b892Sbalrog uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); 4387c23b892Sbalrog 4397c23b892Sbalrog if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy # 4407c23b892Sbalrog val = s->mac_reg[MDIC] | E1000_MDIC_ERROR; 4417c23b892Sbalrog else if (val & E1000_MDIC_OP_READ) { 4427c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr); 4437c23b892Sbalrog if (!(phy_regcap[addr] & PHY_R)) { 4447c23b892Sbalrog DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr); 4457c23b892Sbalrog val |= E1000_MDIC_ERROR; 4467c23b892Sbalrog } else 4477c23b892Sbalrog val = (val ^ data) | s->phy_reg[addr]; 4487c23b892Sbalrog } else if (val & E1000_MDIC_OP_WRITE) { 4497c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data); 4507c23b892Sbalrog if (!(phy_regcap[addr] & PHY_W)) { 4517c23b892Sbalrog DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr); 4527c23b892Sbalrog val |= E1000_MDIC_ERROR; 453b9d03e35SJason Wang } else { 454b9d03e35SJason Wang if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) { 455b9d03e35SJason Wang phyreg_writeops[addr](s, index, data); 4561195fed9SGabriel L. Somlo } else { 4577c23b892Sbalrog s->phy_reg[addr] = data; 4587c23b892Sbalrog } 459b9d03e35SJason Wang } 4601195fed9SGabriel L. Somlo } 4617c23b892Sbalrog s->mac_reg[MDIC] = val | E1000_MDIC_READY; 46217fbbb0bSJason Wang 46317fbbb0bSJason Wang if (val & E1000_MDIC_INT_EN) { 4647c23b892Sbalrog set_ics(s, 0, E1000_ICR_MDAC); 4657c23b892Sbalrog } 46617fbbb0bSJason Wang } 4677c23b892Sbalrog 4687c23b892Sbalrog static uint32_t 4697c23b892Sbalrog get_eecd(E1000State *s, int index) 4707c23b892Sbalrog { 4717c23b892Sbalrog uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd; 4727c23b892Sbalrog 4737c23b892Sbalrog DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n", 4747c23b892Sbalrog s->eecd_state.bitnum_out, s->eecd_state.reading); 4757c23b892Sbalrog if (!s->eecd_state.reading || 4767c23b892Sbalrog ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >> 4777c23b892Sbalrog ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1) 4787c23b892Sbalrog ret |= E1000_EECD_DO; 4797c23b892Sbalrog return ret; 4807c23b892Sbalrog } 4817c23b892Sbalrog 4827c23b892Sbalrog static void 4837c23b892Sbalrog set_eecd(E1000State *s, int index, uint32_t val) 4847c23b892Sbalrog { 4857c23b892Sbalrog uint32_t oldval = s->eecd_state.old_eecd; 4867c23b892Sbalrog 4877c23b892Sbalrog s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS | 4887c23b892Sbalrog E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ); 48920f3e863SLeonid Bloch if (!(E1000_EECD_CS & val)) { /* CS inactive; nothing to do */ 4909651ac55SIzumi Tsutsui return; 49120f3e863SLeonid Bloch } 49220f3e863SLeonid Bloch if (E1000_EECD_CS & (val ^ oldval)) { /* CS rise edge; reset state */ 4939651ac55SIzumi Tsutsui s->eecd_state.val_in = 0; 4949651ac55SIzumi Tsutsui s->eecd_state.bitnum_in = 0; 4959651ac55SIzumi Tsutsui s->eecd_state.bitnum_out = 0; 4969651ac55SIzumi Tsutsui s->eecd_state.reading = 0; 4979651ac55SIzumi Tsutsui } 49820f3e863SLeonid Bloch if (!(E1000_EECD_SK & (val ^ oldval))) { /* no clock edge */ 4997c23b892Sbalrog return; 50020f3e863SLeonid Bloch } 50120f3e863SLeonid Bloch if (!(E1000_EECD_SK & val)) { /* falling edge */ 5027c23b892Sbalrog s->eecd_state.bitnum_out++; 5037c23b892Sbalrog return; 5047c23b892Sbalrog } 5057c23b892Sbalrog s->eecd_state.val_in <<= 1; 5067c23b892Sbalrog if (val & E1000_EECD_DI) 5077c23b892Sbalrog s->eecd_state.val_in |= 1; 5087c23b892Sbalrog if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) { 5097c23b892Sbalrog s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1; 5107c23b892Sbalrog s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) == 5117c23b892Sbalrog EEPROM_READ_OPCODE_MICROWIRE); 5127c23b892Sbalrog } 5137c23b892Sbalrog DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n", 5147c23b892Sbalrog s->eecd_state.bitnum_in, s->eecd_state.bitnum_out, 5157c23b892Sbalrog s->eecd_state.reading); 5167c23b892Sbalrog } 5177c23b892Sbalrog 5187c23b892Sbalrog static uint32_t 5197c23b892Sbalrog flash_eerd_read(E1000State *s, int x) 5207c23b892Sbalrog { 5217c23b892Sbalrog unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START; 5227c23b892Sbalrog 523b1332393SBill Paul if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0) 524b1332393SBill Paul return (s->mac_reg[EERD]); 525b1332393SBill Paul 5267c23b892Sbalrog if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG) 527b1332393SBill Paul return (E1000_EEPROM_RW_REG_DONE | r); 528b1332393SBill Paul 529b1332393SBill Paul return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) | 530b1332393SBill Paul E1000_EEPROM_RW_REG_DONE | r); 5317c23b892Sbalrog } 5327c23b892Sbalrog 5337c23b892Sbalrog static void 5347c23b892Sbalrog putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse) 5357c23b892Sbalrog { 536c6a6a5e3Saliguori uint32_t sum; 537c6a6a5e3Saliguori 5387c23b892Sbalrog if (cse && cse < n) 5397c23b892Sbalrog n = cse + 1; 540c6a6a5e3Saliguori if (sloc < n-1) { 541c6a6a5e3Saliguori sum = net_checksum_add(n-css, data+css); 5420dacea92SEd Swierk stw_be_p(data + sloc, net_checksum_finish_nozero(sum)); 543c6a6a5e3Saliguori } 5447c23b892Sbalrog } 5457c23b892Sbalrog 5461f67f92cSLeonid Bloch static inline void 5473b274301SLeonid Bloch inc_tx_bcast_or_mcast_count(E1000State *s, const unsigned char *arr) 5483b274301SLeonid Bloch { 5493b274301SLeonid Bloch if (!memcmp(arr, bcast, sizeof bcast)) { 550093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, BPTC); 5513b274301SLeonid Bloch } else if (arr[0] & 1) { 552093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, MPTC); 5533b274301SLeonid Bloch } 5543b274301SLeonid Bloch } 5553b274301SLeonid Bloch 55645e93764SLeonid Bloch static void 55793e37d76SJason Wang e1000_send_packet(E1000State *s, const uint8_t *buf, int size) 55893e37d76SJason Wang { 5593b274301SLeonid Bloch static const int PTCregs[6] = { PTC64, PTC127, PTC255, PTC511, 5603b274301SLeonid Bloch PTC1023, PTC1522 }; 5613b274301SLeonid Bloch 562b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 56393e37d76SJason Wang if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) { 5641caff034SJason Wang qemu_receive_packet(nc, buf, size); 56593e37d76SJason Wang } else { 566b356f76dSJason Wang qemu_send_packet(nc, buf, size); 56793e37d76SJason Wang } 5683b274301SLeonid Bloch inc_tx_bcast_or_mcast_count(s, buf); 569093454e2SDmitry Fleytman e1000x_increase_size_stats(s->mac_reg, PTCregs, size); 57093e37d76SJason Wang } 57193e37d76SJason Wang 57293e37d76SJason Wang static void 5737c23b892Sbalrog xmit_seg(E1000State *s) 5747c23b892Sbalrog { 57514e60aaeSPeter Maydell uint16_t len; 57645e93764SLeonid Bloch unsigned int frames = s->tx.tso_frames, css, sofar; 5777c23b892Sbalrog struct e1000_tx *tp = &s->tx; 578d62644b4SEd Swierk via Qemu-devel struct e1000x_txd_props *props = tp->cptse ? &tp->tso_props : &tp->props; 5797c23b892Sbalrog 580d62644b4SEd Swierk via Qemu-devel if (tp->cptse) { 581d62644b4SEd Swierk via Qemu-devel css = props->ipcss; 5827c23b892Sbalrog DBGOUT(TXSUM, "frames %d size %d ipcss %d\n", 5837c23b892Sbalrog frames, tp->size, css); 584d62644b4SEd Swierk via Qemu-devel if (props->ip) { /* IPv4 */ 585d8ee2591SPeter Maydell stw_be_p(tp->data+css+2, tp->size - css); 586d8ee2591SPeter Maydell stw_be_p(tp->data+css+4, 58714e60aaeSPeter Maydell lduw_be_p(tp->data + css + 4) + frames); 58820f3e863SLeonid Bloch } else { /* IPv6 */ 589d8ee2591SPeter Maydell stw_be_p(tp->data+css+4, tp->size - css); 59020f3e863SLeonid Bloch } 591d62644b4SEd Swierk via Qemu-devel css = props->tucss; 5927c23b892Sbalrog len = tp->size - css; 593d62644b4SEd Swierk via Qemu-devel DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", props->tcp, css, len); 594d62644b4SEd Swierk via Qemu-devel if (props->tcp) { 595d62644b4SEd Swierk via Qemu-devel sofar = frames * props->mss; 5966bd194abSPeter Maydell stl_be_p(tp->data+css+4, ldl_be_p(tp->data+css+4)+sofar); /* seq */ 597d62644b4SEd Swierk via Qemu-devel if (props->paylen - sofar > props->mss) { 59820f3e863SLeonid Bloch tp->data[css + 13] &= ~9; /* PSH, FIN */ 5993b274301SLeonid Bloch } else if (frames) { 600093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, TSCTC); 6013b274301SLeonid Bloch } 602d62644b4SEd Swierk via Qemu-devel } else { /* UDP */ 603d8ee2591SPeter Maydell stw_be_p(tp->data+css+4, len); 604d62644b4SEd Swierk via Qemu-devel } 6057d08c73eSEd Swierk via Qemu-devel if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { 606e685b4ebSAlex Williamson unsigned int phsum; 6077c23b892Sbalrog // add pseudo-header length before checksum calculation 608d62644b4SEd Swierk via Qemu-devel void *sp = tp->data + props->tucso; 60914e60aaeSPeter Maydell 61014e60aaeSPeter Maydell phsum = lduw_be_p(sp) + len; 611e685b4ebSAlex Williamson phsum = (phsum >> 16) + (phsum & 0xffff); 612d8ee2591SPeter Maydell stw_be_p(sp, phsum); 6137c23b892Sbalrog } 6147c23b892Sbalrog tp->tso_frames++; 6157c23b892Sbalrog } 6167c23b892Sbalrog 6177d08c73eSEd Swierk via Qemu-devel if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { 618d62644b4SEd Swierk via Qemu-devel putsum(tp->data, tp->size, props->tucso, props->tucss, props->tucse); 619093454e2SDmitry Fleytman } 6207d08c73eSEd Swierk via Qemu-devel if (tp->sum_needed & E1000_TXD_POPTS_IXSM) { 621d62644b4SEd Swierk via Qemu-devel putsum(tp->data, tp->size, props->ipcso, props->ipcss, props->ipcse); 622093454e2SDmitry Fleytman } 6238f2e8d1fSaliguori if (tp->vlan_needed) { 624b10fec9bSStefan Weil memmove(tp->vlan, tp->data, 4); 625b10fec9bSStefan Weil memmove(tp->data, tp->data + 4, 8); 6268f2e8d1fSaliguori memcpy(tp->data + 8, tp->vlan_header, 4); 62793e37d76SJason Wang e1000_send_packet(s, tp->vlan, tp->size + 4); 62820f3e863SLeonid Bloch } else { 62993e37d76SJason Wang e1000_send_packet(s, tp->data, tp->size); 63020f3e863SLeonid Bloch } 63120f3e863SLeonid Bloch 632093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, TPT); 633093454e2SDmitry Fleytman e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size); 6341f67f92cSLeonid Bloch s->mac_reg[GPTC] = s->mac_reg[TPT]; 6353b274301SLeonid Bloch s->mac_reg[GOTCL] = s->mac_reg[TOTL]; 6363b274301SLeonid Bloch s->mac_reg[GOTCH] = s->mac_reg[TOTH]; 6377c23b892Sbalrog } 6387c23b892Sbalrog 6397c23b892Sbalrog static void 6407c23b892Sbalrog process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) 6417c23b892Sbalrog { 642b08340d5SAndreas Färber PCIDevice *d = PCI_DEVICE(s); 6437c23b892Sbalrog uint32_t txd_lower = le32_to_cpu(dp->lower.data); 6447c23b892Sbalrog uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); 645093454e2SDmitry Fleytman unsigned int split_size = txd_lower & 0xffff, bytes, sz; 646a0ae17a6SAndrew Jones unsigned int msh = 0xfffff; 6477c23b892Sbalrog uint64_t addr; 6487c23b892Sbalrog struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; 6497c23b892Sbalrog struct e1000_tx *tp = &s->tx; 6507c23b892Sbalrog 651e9845f09SVincenzo Maffione s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE); 65220f3e863SLeonid Bloch if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */ 653d62644b4SEd Swierk via Qemu-devel if (le32_to_cpu(xp->cmd_and_length) & E1000_TXD_CMD_TSE) { 654d62644b4SEd Swierk via Qemu-devel e1000x_read_tx_ctx_descr(xp, &tp->tso_props); 655ff214d42SDr. David Alan Gilbert s->use_tso_for_migration = 1; 6567c23b892Sbalrog tp->tso_frames = 0; 657d62644b4SEd Swierk via Qemu-devel } else { 658d62644b4SEd Swierk via Qemu-devel e1000x_read_tx_ctx_descr(xp, &tp->props); 659ff214d42SDr. David Alan Gilbert s->use_tso_for_migration = 0; 6607c23b892Sbalrog } 6617c23b892Sbalrog return; 6621b0009dbSbalrog } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { 6631b0009dbSbalrog // data descriptor 664735e77ecSStefan Hajnoczi if (tp->size == 0) { 6657d08c73eSEd Swierk via Qemu-devel tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8; 666735e77ecSStefan Hajnoczi } 6677d08c73eSEd Swierk via Qemu-devel tp->cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0; 66843ad7e3eSJes Sorensen } else { 6691b0009dbSbalrog // legacy descriptor 6707d08c73eSEd Swierk via Qemu-devel tp->cptse = 0; 67143ad7e3eSJes Sorensen } 6727c23b892Sbalrog 673093454e2SDmitry Fleytman if (e1000x_vlan_enabled(s->mac_reg) && 674093454e2SDmitry Fleytman e1000x_is_vlan_txd(txd_lower) && 6757d08c73eSEd Swierk via Qemu-devel (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) { 6768f2e8d1fSaliguori tp->vlan_needed = 1; 677d8ee2591SPeter Maydell stw_be_p(tp->vlan_header, 6784e60a250SShannon Zhao le16_to_cpu(s->mac_reg[VET])); 679d8ee2591SPeter Maydell stw_be_p(tp->vlan_header + 2, 6808f2e8d1fSaliguori le16_to_cpu(dp->upper.fields.special)); 6818f2e8d1fSaliguori } 6828f2e8d1fSaliguori 6837c23b892Sbalrog addr = le64_to_cpu(dp->buffer_addr); 684d62644b4SEd Swierk via Qemu-devel if (tp->cptse) { 685d62644b4SEd Swierk via Qemu-devel msh = tp->tso_props.hdr_len + tp->tso_props.mss; 6867c23b892Sbalrog do { 6877c23b892Sbalrog bytes = split_size; 6883de46e6fSJason Wang if (tp->size >= msh) { 6893de46e6fSJason Wang goto eop; 6903de46e6fSJason Wang } 6917c23b892Sbalrog if (tp->size + bytes > msh) 6927c23b892Sbalrog bytes = msh - tp->size; 69365f82df0SAnthony Liguori 69465f82df0SAnthony Liguori bytes = MIN(sizeof(tp->data) - tp->size, bytes); 695b08340d5SAndreas Färber pci_dma_read(d, addr, tp->data + tp->size, bytes); 696a0ae17a6SAndrew Jones sz = tp->size + bytes; 697d62644b4SEd Swierk via Qemu-devel if (sz >= tp->tso_props.hdr_len 698d62644b4SEd Swierk via Qemu-devel && tp->size < tp->tso_props.hdr_len) { 699d62644b4SEd Swierk via Qemu-devel memmove(tp->header, tp->data, tp->tso_props.hdr_len); 700a0ae17a6SAndrew Jones } 7017c23b892Sbalrog tp->size = sz; 7027c23b892Sbalrog addr += bytes; 7037c23b892Sbalrog if (sz == msh) { 7047c23b892Sbalrog xmit_seg(s); 705d62644b4SEd Swierk via Qemu-devel memmove(tp->data, tp->header, tp->tso_props.hdr_len); 706d62644b4SEd Swierk via Qemu-devel tp->size = tp->tso_props.hdr_len; 7077c23b892Sbalrog } 708b947ac2bSP J P split_size -= bytes; 709b947ac2bSP J P } while (bytes && split_size); 7101b0009dbSbalrog } else { 71165f82df0SAnthony Liguori split_size = MIN(sizeof(tp->data) - tp->size, split_size); 712b08340d5SAndreas Färber pci_dma_read(d, addr, tp->data + tp->size, split_size); 7131b0009dbSbalrog tp->size += split_size; 7141b0009dbSbalrog } 7157c23b892Sbalrog 7163de46e6fSJason Wang eop: 7177c23b892Sbalrog if (!(txd_lower & E1000_TXD_CMD_EOP)) 7187c23b892Sbalrog return; 719d62644b4SEd Swierk via Qemu-devel if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) { 7207c23b892Sbalrog xmit_seg(s); 721a0ae17a6SAndrew Jones } 7227c23b892Sbalrog tp->tso_frames = 0; 7237d08c73eSEd Swierk via Qemu-devel tp->sum_needed = 0; 7248f2e8d1fSaliguori tp->vlan_needed = 0; 7257c23b892Sbalrog tp->size = 0; 7267d08c73eSEd Swierk via Qemu-devel tp->cptse = 0; 7277c23b892Sbalrog } 7287c23b892Sbalrog 7297c23b892Sbalrog static uint32_t 73062ecbd35SEduard - Gabriel Munteanu txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp) 7317c23b892Sbalrog { 732b08340d5SAndreas Färber PCIDevice *d = PCI_DEVICE(s); 7337c23b892Sbalrog uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data); 7347c23b892Sbalrog 7357c23b892Sbalrog if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS))) 7367c23b892Sbalrog return 0; 7377c23b892Sbalrog txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) & 7387c23b892Sbalrog ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU); 7397c23b892Sbalrog dp->upper.data = cpu_to_le32(txd_upper); 740b08340d5SAndreas Färber pci_dma_write(d, base + ((char *)&dp->upper - (char *)dp), 74100c3a05bSDavid Gibson &dp->upper, sizeof(dp->upper)); 7427c23b892Sbalrog return E1000_ICR_TXDW; 7437c23b892Sbalrog } 7447c23b892Sbalrog 745d17161f6SKevin Wolf static uint64_t tx_desc_base(E1000State *s) 746d17161f6SKevin Wolf { 747d17161f6SKevin Wolf uint64_t bah = s->mac_reg[TDBAH]; 748d17161f6SKevin Wolf uint64_t bal = s->mac_reg[TDBAL] & ~0xf; 749d17161f6SKevin Wolf 750d17161f6SKevin Wolf return (bah << 32) + bal; 751d17161f6SKevin Wolf } 752d17161f6SKevin Wolf 7537c23b892Sbalrog static void 7547c23b892Sbalrog start_xmit(E1000State *s) 7557c23b892Sbalrog { 756b08340d5SAndreas Färber PCIDevice *d = PCI_DEVICE(s); 75762ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 7587c23b892Sbalrog struct e1000_tx_desc desc; 7597c23b892Sbalrog uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE; 7607c23b892Sbalrog 7617c23b892Sbalrog if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) { 7627c23b892Sbalrog DBGOUT(TX, "tx disabled\n"); 7637c23b892Sbalrog return; 7647c23b892Sbalrog } 7657c23b892Sbalrog 7667c23b892Sbalrog while (s->mac_reg[TDH] != s->mac_reg[TDT]) { 767d17161f6SKevin Wolf base = tx_desc_base(s) + 7687c23b892Sbalrog sizeof(struct e1000_tx_desc) * s->mac_reg[TDH]; 769b08340d5SAndreas Färber pci_dma_read(d, base, &desc, sizeof(desc)); 7707c23b892Sbalrog 7717c23b892Sbalrog DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH], 7726106075bSths (void *)(intptr_t)desc.buffer_addr, desc.lower.data, 7737c23b892Sbalrog desc.upper.data); 7747c23b892Sbalrog 7757c23b892Sbalrog process_tx_desc(s, &desc); 77662ecbd35SEduard - Gabriel Munteanu cause |= txdesc_writeback(s, base, &desc); 7777c23b892Sbalrog 7787c23b892Sbalrog if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN]) 7797c23b892Sbalrog s->mac_reg[TDH] = 0; 7807c23b892Sbalrog /* 7817c23b892Sbalrog * the following could happen only if guest sw assigns 7827c23b892Sbalrog * bogus values to TDT/TDLEN. 7837c23b892Sbalrog * there's nothing too intelligent we could do about this. 7847c23b892Sbalrog */ 785dd793a74SLaszlo Ersek if (s->mac_reg[TDH] == tdh_start || 786dd793a74SLaszlo Ersek tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) { 7877c23b892Sbalrog DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", 7887c23b892Sbalrog tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); 7897c23b892Sbalrog break; 7907c23b892Sbalrog } 7917c23b892Sbalrog } 7927c23b892Sbalrog set_ics(s, 0, cause); 7937c23b892Sbalrog } 7947c23b892Sbalrog 7957c23b892Sbalrog static int 7967c23b892Sbalrog receive_filter(E1000State *s, const uint8_t *buf, int size) 7977c23b892Sbalrog { 798093454e2SDmitry Fleytman uint32_t rctl = s->mac_reg[RCTL]; 7994aeea330SLeonid Bloch int isbcast = !memcmp(buf, bcast, sizeof bcast), ismcast = (buf[0] & 1); 8007c23b892Sbalrog 801093454e2SDmitry Fleytman if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) && 802093454e2SDmitry Fleytman e1000x_vlan_rx_filter_enabled(s->mac_reg)) { 80314e60aaeSPeter Maydell uint16_t vid = lduw_be_p(buf + 14); 80414e60aaeSPeter Maydell uint32_t vfta = ldl_le_p((uint32_t*)(s->mac_reg + VFTA) + 8058f2e8d1fSaliguori ((vid >> 5) & 0x7f)); 8068f2e8d1fSaliguori if ((vfta & (1 << (vid & 0x1f))) == 0) 8078f2e8d1fSaliguori return 0; 8088f2e8d1fSaliguori } 8098f2e8d1fSaliguori 8104aeea330SLeonid Bloch if (!isbcast && !ismcast && (rctl & E1000_RCTL_UPE)) { /* promiscuous ucast */ 8117c23b892Sbalrog return 1; 8124aeea330SLeonid Bloch } 8137c23b892Sbalrog 8144aeea330SLeonid Bloch if (ismcast && (rctl & E1000_RCTL_MPE)) { /* promiscuous mcast */ 815093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, MPRC); 8167c23b892Sbalrog return 1; 8174aeea330SLeonid Bloch } 8187c23b892Sbalrog 8194aeea330SLeonid Bloch if (isbcast && (rctl & E1000_RCTL_BAM)) { /* broadcast enabled */ 820093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(s->mac_reg, BPRC); 8217c23b892Sbalrog return 1; 8224aeea330SLeonid Bloch } 8237c23b892Sbalrog 824093454e2SDmitry Fleytman return e1000x_rx_group_filter(s->mac_reg, buf); 8257c23b892Sbalrog } 8267c23b892Sbalrog 82799ed7e30Saliguori static void 8284e68f7a0SStefan Hajnoczi e1000_set_link_status(NetClientState *nc) 82999ed7e30Saliguori { 830cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 83199ed7e30Saliguori uint32_t old_status = s->mac_reg[STATUS]; 83299ed7e30Saliguori 833d4044c2aSBjørn Mork if (nc->link_down) { 834093454e2SDmitry Fleytman e1000x_update_regs_on_link_down(s->mac_reg, s->phy_reg); 835d4044c2aSBjørn Mork } else { 836d7a41552SGabriel L. Somlo if (have_autoneg(s) && 8376a2acedbSGabriel L. Somlo !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) { 838093454e2SDmitry Fleytman e1000x_restart_autoneg(s->mac_reg, s->phy_reg, s->autoneg_timer); 8396a2acedbSGabriel L. Somlo } else { 84071aadd3cSJason Wang e1000_link_up(s); 841d4044c2aSBjørn Mork } 8426a2acedbSGabriel L. Somlo } 84399ed7e30Saliguori 84499ed7e30Saliguori if (s->mac_reg[STATUS] != old_status) 84599ed7e30Saliguori set_ics(s, 0, E1000_ICR_LSC); 84699ed7e30Saliguori } 84799ed7e30Saliguori 848322fd48aSMichael S. Tsirkin static bool e1000_has_rxbufs(E1000State *s, size_t total_size) 849322fd48aSMichael S. Tsirkin { 850322fd48aSMichael S. Tsirkin int bufs; 851322fd48aSMichael S. Tsirkin /* Fast-path short packets */ 852322fd48aSMichael S. Tsirkin if (total_size <= s->rxbuf_size) { 853e5b8b0d4SDmitry Fleytman return s->mac_reg[RDH] != s->mac_reg[RDT]; 854322fd48aSMichael S. Tsirkin } 855322fd48aSMichael S. Tsirkin if (s->mac_reg[RDH] < s->mac_reg[RDT]) { 856322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDT] - s->mac_reg[RDH]; 857e5b8b0d4SDmitry Fleytman } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) { 858322fd48aSMichael S. Tsirkin bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + 859322fd48aSMichael S. Tsirkin s->mac_reg[RDT] - s->mac_reg[RDH]; 860322fd48aSMichael S. Tsirkin } else { 861322fd48aSMichael S. Tsirkin return false; 862322fd48aSMichael S. Tsirkin } 863322fd48aSMichael S. Tsirkin return total_size <= bufs * s->rxbuf_size; 864322fd48aSMichael S. Tsirkin } 865322fd48aSMichael S. Tsirkin 866b8c4b67eSPhilippe Mathieu-Daudé static bool 8674e68f7a0SStefan Hajnoczi e1000_can_receive(NetClientState *nc) 8686cdfab28SMichael S. Tsirkin { 869cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 8706cdfab28SMichael S. Tsirkin 871093454e2SDmitry Fleytman return e1000x_rx_ready(&s->parent_obj, s->mac_reg) && 872157628d0Syuchenlin e1000_has_rxbufs(s, 1) && !timer_pending(s->flush_queue_timer); 8736cdfab28SMichael S. Tsirkin } 8746cdfab28SMichael S. Tsirkin 875d17161f6SKevin Wolf static uint64_t rx_desc_base(E1000State *s) 876d17161f6SKevin Wolf { 877d17161f6SKevin Wolf uint64_t bah = s->mac_reg[RDBAH]; 878d17161f6SKevin Wolf uint64_t bal = s->mac_reg[RDBAL] & ~0xf; 879d17161f6SKevin Wolf 880d17161f6SKevin Wolf return (bah << 32) + bal; 881d17161f6SKevin Wolf } 882d17161f6SKevin Wolf 8831001cf45SJason Wang static void 8841001cf45SJason Wang e1000_receiver_overrun(E1000State *s, size_t size) 8851001cf45SJason Wang { 8861001cf45SJason Wang trace_e1000_receiver_overrun(size, s->mac_reg[RDH], s->mac_reg[RDT]); 8871001cf45SJason Wang e1000x_inc_reg_if_not_full(s->mac_reg, RNBC); 8881001cf45SJason Wang e1000x_inc_reg_if_not_full(s->mac_reg, MPC); 8891001cf45SJason Wang set_ics(s, 0, E1000_ICS_RXO); 8901001cf45SJason Wang } 8911001cf45SJason Wang 8924f1c942bSMark McLoughlin static ssize_t 89397410ddeSVincenzo Maffione e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) 8947c23b892Sbalrog { 895cc1f0f45SJason Wang E1000State *s = qemu_get_nic_opaque(nc); 896b08340d5SAndreas Färber PCIDevice *d = PCI_DEVICE(s); 8977c23b892Sbalrog struct e1000_rx_desc desc; 89862ecbd35SEduard - Gabriel Munteanu dma_addr_t base; 8997c23b892Sbalrog unsigned int n, rdt; 9007c23b892Sbalrog uint32_t rdh_start; 9018f2e8d1fSaliguori uint16_t vlan_special = 0; 90297410ddeSVincenzo Maffione uint8_t vlan_status = 0; 90378aeb23eSStefan Hajnoczi uint8_t min_buf[MIN_BUF_SIZE]; 90497410ddeSVincenzo Maffione struct iovec min_iov; 90597410ddeSVincenzo Maffione uint8_t *filter_buf = iov->iov_base; 90697410ddeSVincenzo Maffione size_t size = iov_size(iov, iovcnt); 90797410ddeSVincenzo Maffione size_t iov_ofs = 0; 908b19487e2SMichael S. Tsirkin size_t desc_offset; 909b19487e2SMichael S. Tsirkin size_t desc_size; 910b19487e2SMichael S. Tsirkin size_t total_size; 9117c23b892Sbalrog 912093454e2SDmitry Fleytman if (!e1000x_hw_rx_enabled(s->mac_reg)) { 913ddcb73b7SMichael S. Tsirkin return -1; 914ddcb73b7SMichael S. Tsirkin } 9157c23b892Sbalrog 916157628d0Syuchenlin if (timer_pending(s->flush_queue_timer)) { 917157628d0Syuchenlin return 0; 918157628d0Syuchenlin } 919157628d0Syuchenlin 92078aeb23eSStefan Hajnoczi /* Pad to minimum Ethernet frame length */ 92178aeb23eSStefan Hajnoczi if (size < sizeof(min_buf)) { 92297410ddeSVincenzo Maffione iov_to_buf(iov, iovcnt, 0, min_buf, size); 92378aeb23eSStefan Hajnoczi memset(&min_buf[size], 0, sizeof(min_buf) - size); 92497410ddeSVincenzo Maffione min_iov.iov_base = filter_buf = min_buf; 92597410ddeSVincenzo Maffione min_iov.iov_len = size = sizeof(min_buf); 92697410ddeSVincenzo Maffione iovcnt = 1; 92797410ddeSVincenzo Maffione iov = &min_iov; 92897410ddeSVincenzo Maffione } else if (iov->iov_len < MAXIMUM_ETHERNET_HDR_LEN) { 92997410ddeSVincenzo Maffione /* This is very unlikely, but may happen. */ 93097410ddeSVincenzo Maffione iov_to_buf(iov, iovcnt, 0, min_buf, MAXIMUM_ETHERNET_HDR_LEN); 93197410ddeSVincenzo Maffione filter_buf = min_buf; 93278aeb23eSStefan Hajnoczi } 93378aeb23eSStefan Hajnoczi 934b0d9ffcdSMichael Contreras /* Discard oversized packets if !LPE and !SBP. */ 935093454e2SDmitry Fleytman if (e1000x_is_oversized(s->mac_reg, size)) { 936b0d9ffcdSMichael Contreras return size; 937b0d9ffcdSMichael Contreras } 938b0d9ffcdSMichael Contreras 93997410ddeSVincenzo Maffione if (!receive_filter(s, filter_buf, size)) { 9404f1c942bSMark McLoughlin return size; 94197410ddeSVincenzo Maffione } 9427c23b892Sbalrog 943093454e2SDmitry Fleytman if (e1000x_vlan_enabled(s->mac_reg) && 944093454e2SDmitry Fleytman e1000x_is_vlan_packet(filter_buf, le16_to_cpu(s->mac_reg[VET]))) { 94514e60aaeSPeter Maydell vlan_special = cpu_to_le16(lduw_be_p(filter_buf + 14)); 94697410ddeSVincenzo Maffione iov_ofs = 4; 94797410ddeSVincenzo Maffione if (filter_buf == iov->iov_base) { 94897410ddeSVincenzo Maffione memmove(filter_buf + 4, filter_buf, 12); 94997410ddeSVincenzo Maffione } else { 95097410ddeSVincenzo Maffione iov_from_buf(iov, iovcnt, 4, filter_buf, 12); 95197410ddeSVincenzo Maffione while (iov->iov_len <= iov_ofs) { 95297410ddeSVincenzo Maffione iov_ofs -= iov->iov_len; 95397410ddeSVincenzo Maffione iov++; 95497410ddeSVincenzo Maffione } 95597410ddeSVincenzo Maffione } 9568f2e8d1fSaliguori vlan_status = E1000_RXD_STAT_VP; 9578f2e8d1fSaliguori size -= 4; 9588f2e8d1fSaliguori } 9598f2e8d1fSaliguori 9607c23b892Sbalrog rdh_start = s->mac_reg[RDH]; 961b19487e2SMichael S. Tsirkin desc_offset = 0; 962093454e2SDmitry Fleytman total_size = size + e1000x_fcs_len(s->mac_reg); 963322fd48aSMichael S. Tsirkin if (!e1000_has_rxbufs(s, total_size)) { 9641001cf45SJason Wang e1000_receiver_overrun(s, total_size); 965322fd48aSMichael S. Tsirkin return -1; 966322fd48aSMichael S. Tsirkin } 9677c23b892Sbalrog do { 968b19487e2SMichael S. Tsirkin desc_size = total_size - desc_offset; 969b19487e2SMichael S. Tsirkin if (desc_size > s->rxbuf_size) { 970b19487e2SMichael S. Tsirkin desc_size = s->rxbuf_size; 971b19487e2SMichael S. Tsirkin } 972d17161f6SKevin Wolf base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH]; 973b08340d5SAndreas Färber pci_dma_read(d, base, &desc, sizeof(desc)); 9748f2e8d1fSaliguori desc.special = vlan_special; 9758f2e8d1fSaliguori desc.status |= (vlan_status | E1000_RXD_STAT_DD); 9767c23b892Sbalrog if (desc.buffer_addr) { 977b19487e2SMichael S. Tsirkin if (desc_offset < size) { 97897410ddeSVincenzo Maffione size_t iov_copy; 97997410ddeSVincenzo Maffione hwaddr ba = le64_to_cpu(desc.buffer_addr); 980b19487e2SMichael S. Tsirkin size_t copy_size = size - desc_offset; 981b19487e2SMichael S. Tsirkin if (copy_size > s->rxbuf_size) { 982b19487e2SMichael S. Tsirkin copy_size = s->rxbuf_size; 983b19487e2SMichael S. Tsirkin } 98497410ddeSVincenzo Maffione do { 98597410ddeSVincenzo Maffione iov_copy = MIN(copy_size, iov->iov_len - iov_ofs); 98697410ddeSVincenzo Maffione pci_dma_write(d, ba, iov->iov_base + iov_ofs, iov_copy); 98797410ddeSVincenzo Maffione copy_size -= iov_copy; 98897410ddeSVincenzo Maffione ba += iov_copy; 98997410ddeSVincenzo Maffione iov_ofs += iov_copy; 99097410ddeSVincenzo Maffione if (iov_ofs == iov->iov_len) { 99197410ddeSVincenzo Maffione iov++; 99297410ddeSVincenzo Maffione iov_ofs = 0; 99397410ddeSVincenzo Maffione } 99497410ddeSVincenzo Maffione } while (copy_size); 995b19487e2SMichael S. Tsirkin } 996b19487e2SMichael S. Tsirkin desc_offset += desc_size; 997b19487e2SMichael S. Tsirkin desc.length = cpu_to_le16(desc_size); 998ee912ccfSMichael S. Tsirkin if (desc_offset >= total_size) { 9997c23b892Sbalrog desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM; 1000b19487e2SMichael S. Tsirkin } else { 1001ee912ccfSMichael S. Tsirkin /* Guest zeroing out status is not a hardware requirement. 1002ee912ccfSMichael S. Tsirkin Clear EOP in case guest didn't do it. */ 1003ee912ccfSMichael S. Tsirkin desc.status &= ~E1000_RXD_STAT_EOP; 1004b19487e2SMichael S. Tsirkin } 100543ad7e3eSJes Sorensen } else { // as per intel docs; skip descriptors with null buf addr 10067c23b892Sbalrog DBGOUT(RX, "Null RX descriptor!!\n"); 100743ad7e3eSJes Sorensen } 1008b08340d5SAndreas Färber pci_dma_write(d, base, &desc, sizeof(desc)); 10097c23b892Sbalrog 10107c23b892Sbalrog if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) 10117c23b892Sbalrog s->mac_reg[RDH] = 0; 10127c23b892Sbalrog /* see comment in start_xmit; same here */ 1013dd793a74SLaszlo Ersek if (s->mac_reg[RDH] == rdh_start || 1014dd793a74SLaszlo Ersek rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) { 10157c23b892Sbalrog DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", 10167c23b892Sbalrog rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); 10171001cf45SJason Wang e1000_receiver_overrun(s, total_size); 10184f1c942bSMark McLoughlin return -1; 10197c23b892Sbalrog } 1020b19487e2SMichael S. Tsirkin } while (desc_offset < total_size); 10217c23b892Sbalrog 1022093454e2SDmitry Fleytman e1000x_update_rx_total_stats(s->mac_reg, size, total_size); 10237c23b892Sbalrog 10247c23b892Sbalrog n = E1000_ICS_RXT0; 10257c23b892Sbalrog if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH]) 10267c23b892Sbalrog rdt += s->mac_reg[RDLEN] / sizeof(desc); 1027bf16cc8fSaliguori if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >> 1028bf16cc8fSaliguori s->rxbuf_min_shift) 10297c23b892Sbalrog n |= E1000_ICS_RXDMT0; 10307c23b892Sbalrog 10317c23b892Sbalrog set_ics(s, 0, n); 10324f1c942bSMark McLoughlin 10334f1c942bSMark McLoughlin return size; 10347c23b892Sbalrog } 10357c23b892Sbalrog 103697410ddeSVincenzo Maffione static ssize_t 103797410ddeSVincenzo Maffione e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) 103897410ddeSVincenzo Maffione { 103997410ddeSVincenzo Maffione const struct iovec iov = { 104097410ddeSVincenzo Maffione .iov_base = (uint8_t *)buf, 104197410ddeSVincenzo Maffione .iov_len = size 104297410ddeSVincenzo Maffione }; 104397410ddeSVincenzo Maffione 104497410ddeSVincenzo Maffione return e1000_receive_iov(nc, &iov, 1); 104597410ddeSVincenzo Maffione } 104697410ddeSVincenzo Maffione 10477c23b892Sbalrog static uint32_t 10487c23b892Sbalrog mac_readreg(E1000State *s, int index) 10497c23b892Sbalrog { 10507c23b892Sbalrog return s->mac_reg[index]; 10517c23b892Sbalrog } 10527c23b892Sbalrog 10537c23b892Sbalrog static uint32_t 105472ea771cSLeonid Bloch mac_low4_read(E1000State *s, int index) 105572ea771cSLeonid Bloch { 105672ea771cSLeonid Bloch return s->mac_reg[index] & 0xf; 105772ea771cSLeonid Bloch } 105872ea771cSLeonid Bloch 105972ea771cSLeonid Bloch static uint32_t 106072ea771cSLeonid Bloch mac_low11_read(E1000State *s, int index) 106172ea771cSLeonid Bloch { 106272ea771cSLeonid Bloch return s->mac_reg[index] & 0x7ff; 106372ea771cSLeonid Bloch } 106472ea771cSLeonid Bloch 106572ea771cSLeonid Bloch static uint32_t 106672ea771cSLeonid Bloch mac_low13_read(E1000State *s, int index) 106772ea771cSLeonid Bloch { 106872ea771cSLeonid Bloch return s->mac_reg[index] & 0x1fff; 106972ea771cSLeonid Bloch } 107072ea771cSLeonid Bloch 107172ea771cSLeonid Bloch static uint32_t 107272ea771cSLeonid Bloch mac_low16_read(E1000State *s, int index) 107372ea771cSLeonid Bloch { 107472ea771cSLeonid Bloch return s->mac_reg[index] & 0xffff; 107572ea771cSLeonid Bloch } 107672ea771cSLeonid Bloch 107772ea771cSLeonid Bloch static uint32_t 10787c23b892Sbalrog mac_icr_read(E1000State *s, int index) 10797c23b892Sbalrog { 10807c23b892Sbalrog uint32_t ret = s->mac_reg[ICR]; 10817c23b892Sbalrog 10827c23b892Sbalrog DBGOUT(INTERRUPT, "ICR read: %x\n", ret); 10837c23b892Sbalrog set_interrupt_cause(s, 0, 0); 10847c23b892Sbalrog return ret; 10857c23b892Sbalrog } 10867c23b892Sbalrog 10877c23b892Sbalrog static uint32_t 10887c23b892Sbalrog mac_read_clr4(E1000State *s, int index) 10897c23b892Sbalrog { 10907c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 10917c23b892Sbalrog 10927c23b892Sbalrog s->mac_reg[index] = 0; 10937c23b892Sbalrog return ret; 10947c23b892Sbalrog } 10957c23b892Sbalrog 10967c23b892Sbalrog static uint32_t 10977c23b892Sbalrog mac_read_clr8(E1000State *s, int index) 10987c23b892Sbalrog { 10997c23b892Sbalrog uint32_t ret = s->mac_reg[index]; 11007c23b892Sbalrog 11017c23b892Sbalrog s->mac_reg[index] = 0; 11027c23b892Sbalrog s->mac_reg[index-1] = 0; 11037c23b892Sbalrog return ret; 11047c23b892Sbalrog } 11057c23b892Sbalrog 11067c23b892Sbalrog static void 11077c23b892Sbalrog mac_writereg(E1000State *s, int index, uint32_t val) 11087c23b892Sbalrog { 11097c36507cSAmos Kong uint32_t macaddr[2]; 11107c36507cSAmos Kong 11117c23b892Sbalrog s->mac_reg[index] = val; 11127c36507cSAmos Kong 111390d131fbSMichael S. Tsirkin if (index == RA + 1) { 11147c36507cSAmos Kong macaddr[0] = cpu_to_le32(s->mac_reg[RA]); 11157c36507cSAmos Kong macaddr[1] = cpu_to_le32(s->mac_reg[RA + 1]); 11167c36507cSAmos Kong qemu_format_nic_info_str(qemu_get_queue(s->nic), (uint8_t *)macaddr); 11177c36507cSAmos Kong } 11187c23b892Sbalrog } 11197c23b892Sbalrog 11207c23b892Sbalrog static void 11217c23b892Sbalrog set_rdt(E1000State *s, int index, uint32_t val) 11227c23b892Sbalrog { 11237c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 1124e8b4c680SPaolo Bonzini if (e1000_has_rxbufs(s, 1)) { 1125b356f76dSJason Wang qemu_flush_queued_packets(qemu_get_queue(s->nic)); 1126e8b4c680SPaolo Bonzini } 11277c23b892Sbalrog } 11287c23b892Sbalrog 11297c23b892Sbalrog static void 11307c23b892Sbalrog set_16bit(E1000State *s, int index, uint32_t val) 11317c23b892Sbalrog { 11327c23b892Sbalrog s->mac_reg[index] = val & 0xffff; 11337c23b892Sbalrog } 11347c23b892Sbalrog 11357c23b892Sbalrog static void 11367c23b892Sbalrog set_dlen(E1000State *s, int index, uint32_t val) 11377c23b892Sbalrog { 11387c23b892Sbalrog s->mac_reg[index] = val & 0xfff80; 11397c23b892Sbalrog } 11407c23b892Sbalrog 11417c23b892Sbalrog static void 11427c23b892Sbalrog set_tctl(E1000State *s, int index, uint32_t val) 11437c23b892Sbalrog { 11447c23b892Sbalrog s->mac_reg[index] = val; 11457c23b892Sbalrog s->mac_reg[TDT] &= 0xffff; 11467c23b892Sbalrog start_xmit(s); 11477c23b892Sbalrog } 11487c23b892Sbalrog 11497c23b892Sbalrog static void 11507c23b892Sbalrog set_icr(E1000State *s, int index, uint32_t val) 11517c23b892Sbalrog { 11527c23b892Sbalrog DBGOUT(INTERRUPT, "set_icr %x\n", val); 11537c23b892Sbalrog set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val); 11547c23b892Sbalrog } 11557c23b892Sbalrog 11567c23b892Sbalrog static void 11577c23b892Sbalrog set_imc(E1000State *s, int index, uint32_t val) 11587c23b892Sbalrog { 11597c23b892Sbalrog s->mac_reg[IMS] &= ~val; 11607c23b892Sbalrog set_ics(s, 0, 0); 11617c23b892Sbalrog } 11627c23b892Sbalrog 11637c23b892Sbalrog static void 11647c23b892Sbalrog set_ims(E1000State *s, int index, uint32_t val) 11657c23b892Sbalrog { 11667c23b892Sbalrog s->mac_reg[IMS] |= val; 11677c23b892Sbalrog set_ics(s, 0, 0); 11687c23b892Sbalrog } 11697c23b892Sbalrog 11707c23b892Sbalrog #define getreg(x) [x] = mac_readreg 11713b6b3a27SPhilippe Mathieu-Daudé typedef uint32_t (*readops)(E1000State *, int); 1172da5cf9a4SPhilippe Mathieu-Daudé static const readops macreg_readops[] = { 11737c23b892Sbalrog getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL), 11747c23b892Sbalrog getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL), 11757c23b892Sbalrog getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS), 11767c23b892Sbalrog getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL), 1177b1332393SBill Paul getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS), 1178a00b2335SKay Ackermann getreg(TDBAL), getreg(TDBAH), getreg(RDBAH), getreg(RDBAL), 1179e9845f09SVincenzo Maffione getreg(TDLEN), getreg(RDLEN), getreg(RDTR), getreg(RADV), 118072ea771cSLeonid Bloch getreg(TADV), getreg(ITR), getreg(FCRUC), getreg(IPAV), 118172ea771cSLeonid Bloch getreg(WUC), getreg(WUS), getreg(SCC), getreg(ECOL), 118272ea771cSLeonid Bloch getreg(MCC), getreg(LATECOL), getreg(COLC), getreg(DC), 1183757704f1SKamil Rytarowski getreg(TNCRS), getreg(SEQEC), getreg(CEXTERR), getreg(RLEC), 118472ea771cSLeonid Bloch getreg(XONRXC), getreg(XONTXC), getreg(XOFFRXC), getreg(XOFFTXC), 118572ea771cSLeonid Bloch getreg(RFC), getreg(RJC), getreg(RNBC), getreg(TSCTFC), 11863b274301SLeonid Bloch getreg(MGTPRC), getreg(MGTPDC), getreg(MGTPTC), getreg(GORCL), 11873b274301SLeonid Bloch getreg(GOTCL), 11887c23b892Sbalrog 118920f3e863SLeonid Bloch [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, 11903b274301SLeonid Bloch [GOTCH] = mac_read_clr8, [GORCH] = mac_read_clr8, 11913b274301SLeonid Bloch [PRC64] = mac_read_clr4, [PRC127] = mac_read_clr4, 11923b274301SLeonid Bloch [PRC255] = mac_read_clr4, [PRC511] = mac_read_clr4, 11933b274301SLeonid Bloch [PRC1023] = mac_read_clr4, [PRC1522] = mac_read_clr4, 11943b274301SLeonid Bloch [PTC64] = mac_read_clr4, [PTC127] = mac_read_clr4, 11953b274301SLeonid Bloch [PTC255] = mac_read_clr4, [PTC511] = mac_read_clr4, 11963b274301SLeonid Bloch [PTC1023] = mac_read_clr4, [PTC1522] = mac_read_clr4, 119720f3e863SLeonid Bloch [GPRC] = mac_read_clr4, [GPTC] = mac_read_clr4, 119820f3e863SLeonid Bloch [TPT] = mac_read_clr4, [TPR] = mac_read_clr4, 11993b274301SLeonid Bloch [RUC] = mac_read_clr4, [ROC] = mac_read_clr4, 12003b274301SLeonid Bloch [BPRC] = mac_read_clr4, [MPRC] = mac_read_clr4, 12013b274301SLeonid Bloch [TSCTC] = mac_read_clr4, [BPTC] = mac_read_clr4, 12023b274301SLeonid Bloch [MPTC] = mac_read_clr4, 120320f3e863SLeonid Bloch [ICR] = mac_icr_read, [EECD] = get_eecd, 120420f3e863SLeonid Bloch [EERD] = flash_eerd_read, 120572ea771cSLeonid Bloch [RDFH] = mac_low13_read, [RDFT] = mac_low13_read, 120672ea771cSLeonid Bloch [RDFHS] = mac_low13_read, [RDFTS] = mac_low13_read, 120772ea771cSLeonid Bloch [RDFPC] = mac_low13_read, 120872ea771cSLeonid Bloch [TDFH] = mac_low11_read, [TDFT] = mac_low11_read, 120972ea771cSLeonid Bloch [TDFHS] = mac_low13_read, [TDFTS] = mac_low13_read, 121072ea771cSLeonid Bloch [TDFPC] = mac_low13_read, 121172ea771cSLeonid Bloch [AIT] = mac_low16_read, 121220f3e863SLeonid Bloch 12137c23b892Sbalrog [CRCERRS ... MPC] = &mac_readreg, 121472ea771cSLeonid Bloch [IP6AT ... IP6AT+3] = &mac_readreg, [IP4AT ... IP4AT+6] = &mac_readreg, 121572ea771cSLeonid Bloch [FFLT ... FFLT+6] = &mac_low11_read, 12167c23b892Sbalrog [RA ... RA+31] = &mac_readreg, 121772ea771cSLeonid Bloch [WUPM ... WUPM+31] = &mac_readreg, 12187c23b892Sbalrog [MTA ... MTA+127] = &mac_readreg, 12198f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_readreg, 122072ea771cSLeonid Bloch [FFMT ... FFMT+254] = &mac_low4_read, 122172ea771cSLeonid Bloch [FFVT ... FFVT+254] = &mac_readreg, 122272ea771cSLeonid Bloch [PBM ... PBM+16383] = &mac_readreg, 12237c23b892Sbalrog }; 1224b1503cdaSmalc enum { NREADOPS = ARRAY_SIZE(macreg_readops) }; 12257c23b892Sbalrog 12267c23b892Sbalrog #define putreg(x) [x] = mac_writereg 12273b6b3a27SPhilippe Mathieu-Daudé typedef void (*writeops)(E1000State *, int, uint32_t); 1228da5cf9a4SPhilippe Mathieu-Daudé static const writeops macreg_writeops[] = { 12297c23b892Sbalrog putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC), 12307c23b892Sbalrog putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH), 123172ea771cSLeonid Bloch putreg(RDBAL), putreg(LEDCTL), putreg(VET), putreg(FCRUC), 123272ea771cSLeonid Bloch putreg(TDFH), putreg(TDFT), putreg(TDFHS), putreg(TDFTS), 123372ea771cSLeonid Bloch putreg(TDFPC), putreg(RDFH), putreg(RDFT), putreg(RDFHS), 123472ea771cSLeonid Bloch putreg(RDFTS), putreg(RDFPC), putreg(IPAV), putreg(WUC), 123572ea771cSLeonid Bloch putreg(WUS), putreg(AIT), 123620f3e863SLeonid Bloch 12377c23b892Sbalrog [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl, 12387c23b892Sbalrog [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics, 12397c23b892Sbalrog [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt, 12407c23b892Sbalrog [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr, 1241cab3c825SKevin Wolf [EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl, 1242e9845f09SVincenzo Maffione [RDTR] = set_16bit, [RADV] = set_16bit, [TADV] = set_16bit, 1243e9845f09SVincenzo Maffione [ITR] = set_16bit, 124420f3e863SLeonid Bloch 124572ea771cSLeonid Bloch [IP6AT ... IP6AT+3] = &mac_writereg, [IP4AT ... IP4AT+6] = &mac_writereg, 124672ea771cSLeonid Bloch [FFLT ... FFLT+6] = &mac_writereg, 12477c23b892Sbalrog [RA ... RA+31] = &mac_writereg, 124872ea771cSLeonid Bloch [WUPM ... WUPM+31] = &mac_writereg, 12497c23b892Sbalrog [MTA ... MTA+127] = &mac_writereg, 12508f2e8d1fSaliguori [VFTA ... VFTA+127] = &mac_writereg, 125172ea771cSLeonid Bloch [FFMT ... FFMT+254] = &mac_writereg, [FFVT ... FFVT+254] = &mac_writereg, 125272ea771cSLeonid Bloch [PBM ... PBM+16383] = &mac_writereg, 12537c23b892Sbalrog }; 1254b9d03e35SJason Wang 1255b1503cdaSmalc enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; 12567c23b892Sbalrog 1257bc0f0674SLeonid Bloch enum { MAC_ACCESS_PARTIAL = 1, MAC_ACCESS_FLAG_NEEDED = 2 }; 1258bc0f0674SLeonid Bloch 1259bc0f0674SLeonid Bloch #define markflag(x) ((E1000_FLAG_##x << 2) | MAC_ACCESS_FLAG_NEEDED) 1260bc0f0674SLeonid Bloch /* In the array below the meaning of the bits is: [f|f|f|f|f|f|n|p] 1261bc0f0674SLeonid Bloch * f - flag bits (up to 6 possible flags) 1262bc0f0674SLeonid Bloch * n - flag needed 1263bc0f0674SLeonid Bloch * p - partially implenented */ 1264bc0f0674SLeonid Bloch static const uint8_t mac_reg_access[0x8000] = { 1265bc0f0674SLeonid Bloch [RDTR] = markflag(MIT), [TADV] = markflag(MIT), 1266bc0f0674SLeonid Bloch [RADV] = markflag(MIT), [ITR] = markflag(MIT), 126772ea771cSLeonid Bloch 126872ea771cSLeonid Bloch [IPAV] = markflag(MAC), [WUC] = markflag(MAC), 126972ea771cSLeonid Bloch [IP6AT] = markflag(MAC), [IP4AT] = markflag(MAC), 127072ea771cSLeonid Bloch [FFVT] = markflag(MAC), [WUPM] = markflag(MAC), 127172ea771cSLeonid Bloch [ECOL] = markflag(MAC), [MCC] = markflag(MAC), 127272ea771cSLeonid Bloch [DC] = markflag(MAC), [TNCRS] = markflag(MAC), 127372ea771cSLeonid Bloch [RLEC] = markflag(MAC), [XONRXC] = markflag(MAC), 127472ea771cSLeonid Bloch [XOFFTXC] = markflag(MAC), [RFC] = markflag(MAC), 127572ea771cSLeonid Bloch [TSCTFC] = markflag(MAC), [MGTPRC] = markflag(MAC), 127672ea771cSLeonid Bloch [WUS] = markflag(MAC), [AIT] = markflag(MAC), 127772ea771cSLeonid Bloch [FFLT] = markflag(MAC), [FFMT] = markflag(MAC), 127872ea771cSLeonid Bloch [SCC] = markflag(MAC), [FCRUC] = markflag(MAC), 127972ea771cSLeonid Bloch [LATECOL] = markflag(MAC), [COLC] = markflag(MAC), 1280757704f1SKamil Rytarowski [SEQEC] = markflag(MAC), [CEXTERR] = markflag(MAC), 128172ea771cSLeonid Bloch [XONTXC] = markflag(MAC), [XOFFRXC] = markflag(MAC), 128272ea771cSLeonid Bloch [RJC] = markflag(MAC), [RNBC] = markflag(MAC), 128372ea771cSLeonid Bloch [MGTPDC] = markflag(MAC), [MGTPTC] = markflag(MAC), 12843b274301SLeonid Bloch [RUC] = markflag(MAC), [ROC] = markflag(MAC), 12853b274301SLeonid Bloch [GORCL] = markflag(MAC), [GORCH] = markflag(MAC), 12863b274301SLeonid Bloch [GOTCL] = markflag(MAC), [GOTCH] = markflag(MAC), 12873b274301SLeonid Bloch [BPRC] = markflag(MAC), [MPRC] = markflag(MAC), 12883b274301SLeonid Bloch [TSCTC] = markflag(MAC), [PRC64] = markflag(MAC), 12893b274301SLeonid Bloch [PRC127] = markflag(MAC), [PRC255] = markflag(MAC), 12903b274301SLeonid Bloch [PRC511] = markflag(MAC), [PRC1023] = markflag(MAC), 12913b274301SLeonid Bloch [PRC1522] = markflag(MAC), [PTC64] = markflag(MAC), 12923b274301SLeonid Bloch [PTC127] = markflag(MAC), [PTC255] = markflag(MAC), 12933b274301SLeonid Bloch [PTC511] = markflag(MAC), [PTC1023] = markflag(MAC), 12943b274301SLeonid Bloch [PTC1522] = markflag(MAC), [MPTC] = markflag(MAC), 12953b274301SLeonid Bloch [BPTC] = markflag(MAC), 129672ea771cSLeonid Bloch 129772ea771cSLeonid Bloch [TDFH] = markflag(MAC) | MAC_ACCESS_PARTIAL, 129872ea771cSLeonid Bloch [TDFT] = markflag(MAC) | MAC_ACCESS_PARTIAL, 129972ea771cSLeonid Bloch [TDFHS] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130072ea771cSLeonid Bloch [TDFTS] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130172ea771cSLeonid Bloch [TDFPC] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130272ea771cSLeonid Bloch [RDFH] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130372ea771cSLeonid Bloch [RDFT] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130472ea771cSLeonid Bloch [RDFHS] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130572ea771cSLeonid Bloch [RDFTS] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130672ea771cSLeonid Bloch [RDFPC] = markflag(MAC) | MAC_ACCESS_PARTIAL, 130772ea771cSLeonid Bloch [PBM] = markflag(MAC) | MAC_ACCESS_PARTIAL, 1308bc0f0674SLeonid Bloch }; 1309bc0f0674SLeonid Bloch 13107c23b892Sbalrog static void 1311a8170e5eSAvi Kivity e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val, 1312ad00a9b9SAvi Kivity unsigned size) 13137c23b892Sbalrog { 13147c23b892Sbalrog E1000State *s = opaque; 13158da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 13167c23b892Sbalrog 131743ad7e3eSJes Sorensen if (index < NWRITEOPS && macreg_writeops[index]) { 1318bc0f0674SLeonid Bloch if (!(mac_reg_access[index] & MAC_ACCESS_FLAG_NEEDED) 1319bc0f0674SLeonid Bloch || (s->compat_flags & (mac_reg_access[index] >> 2))) { 1320bc0f0674SLeonid Bloch if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) { 1321bc0f0674SLeonid Bloch DBGOUT(GENERAL, "Writing to register at offset: 0x%08x. " 1322bc0f0674SLeonid Bloch "It is not fully implemented.\n", index<<2); 1323bc0f0674SLeonid Bloch } 13246b59fc74Saurel32 macreg_writeops[index](s, index, val); 1325bc0f0674SLeonid Bloch } else { /* "flag needed" bit is set, but the flag is not active */ 1326bc0f0674SLeonid Bloch DBGOUT(MMIO, "MMIO write attempt to disabled reg. addr=0x%08x\n", 1327bc0f0674SLeonid Bloch index<<2); 1328bc0f0674SLeonid Bloch } 132943ad7e3eSJes Sorensen } else if (index < NREADOPS && macreg_readops[index]) { 1330bc0f0674SLeonid Bloch DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", 1331bc0f0674SLeonid Bloch index<<2, val); 133243ad7e3eSJes Sorensen } else { 1333ad00a9b9SAvi Kivity DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n", 13347c23b892Sbalrog index<<2, val); 13357c23b892Sbalrog } 133643ad7e3eSJes Sorensen } 13377c23b892Sbalrog 1338ad00a9b9SAvi Kivity static uint64_t 1339a8170e5eSAvi Kivity e1000_mmio_read(void *opaque, hwaddr addr, unsigned size) 13407c23b892Sbalrog { 13417c23b892Sbalrog E1000State *s = opaque; 13428da3ff18Spbrook unsigned int index = (addr & 0x1ffff) >> 2; 13437c23b892Sbalrog 1344bc0f0674SLeonid Bloch if (index < NREADOPS && macreg_readops[index]) { 1345bc0f0674SLeonid Bloch if (!(mac_reg_access[index] & MAC_ACCESS_FLAG_NEEDED) 1346bc0f0674SLeonid Bloch || (s->compat_flags & (mac_reg_access[index] >> 2))) { 1347bc0f0674SLeonid Bloch if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) { 1348bc0f0674SLeonid Bloch DBGOUT(GENERAL, "Reading register at offset: 0x%08x. " 1349bc0f0674SLeonid Bloch "It is not fully implemented.\n", index<<2); 13506b59fc74Saurel32 } 1351bc0f0674SLeonid Bloch return macreg_readops[index](s, index); 1352bc0f0674SLeonid Bloch } else { /* "flag needed" bit is set, but the flag is not active */ 1353bc0f0674SLeonid Bloch DBGOUT(MMIO, "MMIO read attempt of disabled reg. addr=0x%08x\n", 1354bc0f0674SLeonid Bloch index<<2); 1355bc0f0674SLeonid Bloch } 1356bc0f0674SLeonid Bloch } else { 13577c23b892Sbalrog DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2); 1358bc0f0674SLeonid Bloch } 13597c23b892Sbalrog return 0; 13607c23b892Sbalrog } 13617c23b892Sbalrog 1362ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_mmio_ops = { 1363ad00a9b9SAvi Kivity .read = e1000_mmio_read, 1364ad00a9b9SAvi Kivity .write = e1000_mmio_write, 1365ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1366ad00a9b9SAvi Kivity .impl = { 1367ad00a9b9SAvi Kivity .min_access_size = 4, 1368ad00a9b9SAvi Kivity .max_access_size = 4, 1369ad00a9b9SAvi Kivity }, 1370ad00a9b9SAvi Kivity }; 1371ad00a9b9SAvi Kivity 1372a8170e5eSAvi Kivity static uint64_t e1000_io_read(void *opaque, hwaddr addr, 1373ad00a9b9SAvi Kivity unsigned size) 13747c23b892Sbalrog { 1375ad00a9b9SAvi Kivity E1000State *s = opaque; 1376ad00a9b9SAvi Kivity 1377ad00a9b9SAvi Kivity (void)s; 1378ad00a9b9SAvi Kivity return 0; 13797c23b892Sbalrog } 13807c23b892Sbalrog 1381a8170e5eSAvi Kivity static void e1000_io_write(void *opaque, hwaddr addr, 1382ad00a9b9SAvi Kivity uint64_t val, unsigned size) 13837c23b892Sbalrog { 1384ad00a9b9SAvi Kivity E1000State *s = opaque; 1385ad00a9b9SAvi Kivity 1386ad00a9b9SAvi Kivity (void)s; 13877c23b892Sbalrog } 13887c23b892Sbalrog 1389ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_io_ops = { 1390ad00a9b9SAvi Kivity .read = e1000_io_read, 1391ad00a9b9SAvi Kivity .write = e1000_io_write, 1392ad00a9b9SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 1393ad00a9b9SAvi Kivity }; 1394ad00a9b9SAvi Kivity 1395e482dc3eSJuan Quintela static bool is_version_1(void *opaque, int version_id) 13967c23b892Sbalrog { 1397e482dc3eSJuan Quintela return version_id == 1; 13987c23b892Sbalrog } 13997c23b892Sbalrog 140044b1ff31SDr. David Alan Gilbert static int e1000_pre_save(void *opaque) 1401ddcb73b7SMichael S. Tsirkin { 1402ddcb73b7SMichael S. Tsirkin E1000State *s = opaque; 1403ddcb73b7SMichael S. Tsirkin NetClientState *nc = qemu_get_queue(s->nic); 14042af234e6SMichael S. Tsirkin 1405ddcb73b7SMichael S. Tsirkin /* 14066a2acedbSGabriel L. Somlo * If link is down and auto-negotiation is supported and ongoing, 14076a2acedbSGabriel L. Somlo * complete auto-negotiation immediately. This allows us to look 14086a2acedbSGabriel L. Somlo * at MII_SR_AUTONEG_COMPLETE to infer link status on load. 1409ddcb73b7SMichael S. Tsirkin */ 1410d7a41552SGabriel L. Somlo if (nc->link_down && have_autoneg(s)) { 1411ddcb73b7SMichael S. Tsirkin s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; 1412ddcb73b7SMichael S. Tsirkin } 141344b1ff31SDr. David Alan Gilbert 1414ff214d42SDr. David Alan Gilbert /* Decide which set of props to migrate in the main structure */ 1415ff214d42SDr. David Alan Gilbert if (chkflag(TSO) || !s->use_tso_for_migration) { 1416ff214d42SDr. David Alan Gilbert /* Either we're migrating with the extra subsection, in which 1417ff214d42SDr. David Alan Gilbert * case the mig_props is always 'props' OR 1418ff214d42SDr. David Alan Gilbert * we've not got the subsection, but 'props' was the last 1419ff214d42SDr. David Alan Gilbert * updated. 1420ff214d42SDr. David Alan Gilbert */ 142159354484SDr. David Alan Gilbert s->mig_props = s->tx.props; 1422ff214d42SDr. David Alan Gilbert } else { 1423ff214d42SDr. David Alan Gilbert /* We're not using the subsection, and 'tso_props' was 1424ff214d42SDr. David Alan Gilbert * the last updated. 1425ff214d42SDr. David Alan Gilbert */ 1426ff214d42SDr. David Alan Gilbert s->mig_props = s->tx.tso_props; 1427ff214d42SDr. David Alan Gilbert } 142844b1ff31SDr. David Alan Gilbert return 0; 1429ddcb73b7SMichael S. Tsirkin } 1430ddcb73b7SMichael S. Tsirkin 1431e4b82364SAmos Kong static int e1000_post_load(void *opaque, int version_id) 1432e4b82364SAmos Kong { 1433e4b82364SAmos Kong E1000State *s = opaque; 1434b356f76dSJason Wang NetClientState *nc = qemu_get_queue(s->nic); 1435e4b82364SAmos Kong 1436bc0f0674SLeonid Bloch if (!chkflag(MIT)) { 1437e9845f09SVincenzo Maffione s->mac_reg[ITR] = s->mac_reg[RDTR] = s->mac_reg[RADV] = 1438e9845f09SVincenzo Maffione s->mac_reg[TADV] = 0; 1439e9845f09SVincenzo Maffione s->mit_irq_level = false; 1440e9845f09SVincenzo Maffione } 1441e9845f09SVincenzo Maffione s->mit_ide = 0; 1442f46efa9bSJason Wang s->mit_timer_on = true; 1443f46efa9bSJason Wang timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1); 1444e9845f09SVincenzo Maffione 1445e4b82364SAmos Kong /* nc.link_down can't be migrated, so infer link_down according 1446ddcb73b7SMichael S. Tsirkin * to link status bit in mac_reg[STATUS]. 1447ddcb73b7SMichael S. Tsirkin * Alternatively, restart link negotiation if it was in progress. */ 1448b356f76dSJason Wang nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0; 14492af234e6SMichael S. Tsirkin 1450d7a41552SGabriel L. Somlo if (have_autoneg(s) && 1451ddcb73b7SMichael S. Tsirkin !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) { 1452ddcb73b7SMichael S. Tsirkin nc->link_down = false; 1453d7a41552SGabriel L. Somlo timer_mod(s->autoneg_timer, 1454d7a41552SGabriel L. Somlo qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500); 1455ddcb73b7SMichael S. Tsirkin } 1456e4b82364SAmos Kong 145759354484SDr. David Alan Gilbert s->tx.props = s->mig_props; 14583c4053c5SDr. David Alan Gilbert if (!s->received_tx_tso) { 14593c4053c5SDr. David Alan Gilbert /* We received only one set of offload data (tx.props) 14603c4053c5SDr. David Alan Gilbert * and haven't got tx.tso_props. The best we can do 14613c4053c5SDr. David Alan Gilbert * is dupe the data. 14623c4053c5SDr. David Alan Gilbert */ 146359354484SDr. David Alan Gilbert s->tx.tso_props = s->mig_props; 14643c4053c5SDr. David Alan Gilbert } 14653c4053c5SDr. David Alan Gilbert return 0; 14663c4053c5SDr. David Alan Gilbert } 14673c4053c5SDr. David Alan Gilbert 14683c4053c5SDr. David Alan Gilbert static int e1000_tx_tso_post_load(void *opaque, int version_id) 14693c4053c5SDr. David Alan Gilbert { 14703c4053c5SDr. David Alan Gilbert E1000State *s = opaque; 14713c4053c5SDr. David Alan Gilbert s->received_tx_tso = true; 1472e4b82364SAmos Kong return 0; 1473e4b82364SAmos Kong } 1474e4b82364SAmos Kong 1475e9845f09SVincenzo Maffione static bool e1000_mit_state_needed(void *opaque) 1476e9845f09SVincenzo Maffione { 1477e9845f09SVincenzo Maffione E1000State *s = opaque; 1478e9845f09SVincenzo Maffione 1479bc0f0674SLeonid Bloch return chkflag(MIT); 1480e9845f09SVincenzo Maffione } 1481e9845f09SVincenzo Maffione 14829e117734SLeonid Bloch static bool e1000_full_mac_needed(void *opaque) 14839e117734SLeonid Bloch { 14849e117734SLeonid Bloch E1000State *s = opaque; 14859e117734SLeonid Bloch 1486bc0f0674SLeonid Bloch return chkflag(MAC); 14879e117734SLeonid Bloch } 14889e117734SLeonid Bloch 148946f2a9ecSDr. David Alan Gilbert static bool e1000_tso_state_needed(void *opaque) 149046f2a9ecSDr. David Alan Gilbert { 149146f2a9ecSDr. David Alan Gilbert E1000State *s = opaque; 149246f2a9ecSDr. David Alan Gilbert 149346f2a9ecSDr. David Alan Gilbert return chkflag(TSO); 149446f2a9ecSDr. David Alan Gilbert } 149546f2a9ecSDr. David Alan Gilbert 1496e9845f09SVincenzo Maffione static const VMStateDescription vmstate_e1000_mit_state = { 1497e9845f09SVincenzo Maffione .name = "e1000/mit_state", 1498e9845f09SVincenzo Maffione .version_id = 1, 1499e9845f09SVincenzo Maffione .minimum_version_id = 1, 15005cd8cadaSJuan Quintela .needed = e1000_mit_state_needed, 1501e9845f09SVincenzo Maffione .fields = (VMStateField[]) { 1502e9845f09SVincenzo Maffione VMSTATE_UINT32(mac_reg[RDTR], E1000State), 1503e9845f09SVincenzo Maffione VMSTATE_UINT32(mac_reg[RADV], E1000State), 1504e9845f09SVincenzo Maffione VMSTATE_UINT32(mac_reg[TADV], E1000State), 1505e9845f09SVincenzo Maffione VMSTATE_UINT32(mac_reg[ITR], E1000State), 1506e9845f09SVincenzo Maffione VMSTATE_BOOL(mit_irq_level, E1000State), 1507e9845f09SVincenzo Maffione VMSTATE_END_OF_LIST() 1508e9845f09SVincenzo Maffione } 1509e9845f09SVincenzo Maffione }; 1510e9845f09SVincenzo Maffione 15119e117734SLeonid Bloch static const VMStateDescription vmstate_e1000_full_mac_state = { 15129e117734SLeonid Bloch .name = "e1000/full_mac_state", 15139e117734SLeonid Bloch .version_id = 1, 15149e117734SLeonid Bloch .minimum_version_id = 1, 15159e117734SLeonid Bloch .needed = e1000_full_mac_needed, 15169e117734SLeonid Bloch .fields = (VMStateField[]) { 15179e117734SLeonid Bloch VMSTATE_UINT32_ARRAY(mac_reg, E1000State, 0x8000), 15189e117734SLeonid Bloch VMSTATE_END_OF_LIST() 15199e117734SLeonid Bloch } 15209e117734SLeonid Bloch }; 15219e117734SLeonid Bloch 15224ae4bf5bSDr. David Alan Gilbert static const VMStateDescription vmstate_e1000_tx_tso_state = { 15234ae4bf5bSDr. David Alan Gilbert .name = "e1000/tx_tso_state", 15244ae4bf5bSDr. David Alan Gilbert .version_id = 1, 15254ae4bf5bSDr. David Alan Gilbert .minimum_version_id = 1, 152646f2a9ecSDr. David Alan Gilbert .needed = e1000_tso_state_needed, 15273c4053c5SDr. David Alan Gilbert .post_load = e1000_tx_tso_post_load, 15284ae4bf5bSDr. David Alan Gilbert .fields = (VMStateField[]) { 15294ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT8(tx.tso_props.ipcss, E1000State), 15304ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT8(tx.tso_props.ipcso, E1000State), 15314ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT16(tx.tso_props.ipcse, E1000State), 15324ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT8(tx.tso_props.tucss, E1000State), 15334ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT8(tx.tso_props.tucso, E1000State), 15344ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT16(tx.tso_props.tucse, E1000State), 15354ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT32(tx.tso_props.paylen, E1000State), 15364ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT8(tx.tso_props.hdr_len, E1000State), 15374ae4bf5bSDr. David Alan Gilbert VMSTATE_UINT16(tx.tso_props.mss, E1000State), 15384ae4bf5bSDr. David Alan Gilbert VMSTATE_INT8(tx.tso_props.ip, E1000State), 15394ae4bf5bSDr. David Alan Gilbert VMSTATE_INT8(tx.tso_props.tcp, E1000State), 15404ae4bf5bSDr. David Alan Gilbert VMSTATE_END_OF_LIST() 15414ae4bf5bSDr. David Alan Gilbert } 15424ae4bf5bSDr. David Alan Gilbert }; 15434ae4bf5bSDr. David Alan Gilbert 1544e482dc3eSJuan Quintela static const VMStateDescription vmstate_e1000 = { 1545e482dc3eSJuan Quintela .name = "e1000", 15464ae4bf5bSDr. David Alan Gilbert .version_id = 2, 1547e482dc3eSJuan Quintela .minimum_version_id = 1, 1548ddcb73b7SMichael S. Tsirkin .pre_save = e1000_pre_save, 1549e4b82364SAmos Kong .post_load = e1000_post_load, 1550e482dc3eSJuan Quintela .fields = (VMStateField[]) { 1551b08340d5SAndreas Färber VMSTATE_PCI_DEVICE(parent_obj, E1000State), 1552e482dc3eSJuan Quintela VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */ 1553e482dc3eSJuan Quintela VMSTATE_UNUSED(4), /* Was mmio_base. */ 1554e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_size, E1000State), 1555e482dc3eSJuan Quintela VMSTATE_UINT32(rxbuf_min_shift, E1000State), 1556e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.val_in, E1000State), 1557e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_in, E1000State), 1558e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.bitnum_out, E1000State), 1559e482dc3eSJuan Quintela VMSTATE_UINT16(eecd_state.reading, E1000State), 1560e482dc3eSJuan Quintela VMSTATE_UINT32(eecd_state.old_eecd, E1000State), 156159354484SDr. David Alan Gilbert VMSTATE_UINT8(mig_props.ipcss, E1000State), 156259354484SDr. David Alan Gilbert VMSTATE_UINT8(mig_props.ipcso, E1000State), 156359354484SDr. David Alan Gilbert VMSTATE_UINT16(mig_props.ipcse, E1000State), 156459354484SDr. David Alan Gilbert VMSTATE_UINT8(mig_props.tucss, E1000State), 156559354484SDr. David Alan Gilbert VMSTATE_UINT8(mig_props.tucso, E1000State), 156659354484SDr. David Alan Gilbert VMSTATE_UINT16(mig_props.tucse, E1000State), 156759354484SDr. David Alan Gilbert VMSTATE_UINT32(mig_props.paylen, E1000State), 156859354484SDr. David Alan Gilbert VMSTATE_UINT8(mig_props.hdr_len, E1000State), 156959354484SDr. David Alan Gilbert VMSTATE_UINT16(mig_props.mss, E1000State), 1570e482dc3eSJuan Quintela VMSTATE_UINT16(tx.size, E1000State), 1571e482dc3eSJuan Quintela VMSTATE_UINT16(tx.tso_frames, E1000State), 15727d08c73eSEd Swierk via Qemu-devel VMSTATE_UINT8(tx.sum_needed, E1000State), 157359354484SDr. David Alan Gilbert VMSTATE_INT8(mig_props.ip, E1000State), 157459354484SDr. David Alan Gilbert VMSTATE_INT8(mig_props.tcp, E1000State), 1575e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.header, E1000State), 1576e482dc3eSJuan Quintela VMSTATE_BUFFER(tx.data, E1000State), 1577e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64), 1578e482dc3eSJuan Quintela VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20), 1579e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[CTRL], E1000State), 1580e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EECD], E1000State), 1581e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[EERD], E1000State), 1582e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPRC], E1000State), 1583e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[GPTC], E1000State), 1584e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICR], E1000State), 1585e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[ICS], E1000State), 1586e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMC], E1000State), 1587e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[IMS], E1000State), 1588e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[LEDCTL], E1000State), 1589e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MANC], E1000State), 1590e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MDIC], E1000State), 1591e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[MPC], E1000State), 1592e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[PBA], E1000State), 1593e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RCTL], E1000State), 1594e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAH], E1000State), 1595e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDBAL], E1000State), 1596e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDH], E1000State), 1597e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDLEN], E1000State), 1598e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[RDT], E1000State), 1599e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[STATUS], E1000State), 1600e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[SWSM], E1000State), 1601e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TCTL], E1000State), 1602e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAH], E1000State), 1603e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDBAL], E1000State), 1604e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDH], E1000State), 1605e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDLEN], E1000State), 1606e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TDT], E1000State), 1607e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORH], E1000State), 1608e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TORL], E1000State), 1609e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTH], E1000State), 1610e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TOTL], E1000State), 1611e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPR], E1000State), 1612e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TPT], E1000State), 1613e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[TXDCTL], E1000State), 1614e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[WUFC], E1000State), 1615e482dc3eSJuan Quintela VMSTATE_UINT32(mac_reg[VET], E1000State), 1616e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32), 1617e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128), 1618e482dc3eSJuan Quintela VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128), 1619e482dc3eSJuan Quintela VMSTATE_END_OF_LIST() 1620e9845f09SVincenzo Maffione }, 16215cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 16225cd8cadaSJuan Quintela &vmstate_e1000_mit_state, 16239e117734SLeonid Bloch &vmstate_e1000_full_mac_state, 16244ae4bf5bSDr. David Alan Gilbert &vmstate_e1000_tx_tso_state, 16255cd8cadaSJuan Quintela NULL 16267c23b892Sbalrog } 1627e482dc3eSJuan Quintela }; 16287c23b892Sbalrog 16298597f2e1SGabriel L. Somlo /* 16308597f2e1SGabriel L. Somlo * EEPROM contents documented in Tables 5-2 and 5-3, pp. 98-102. 163180867bdbSPhilippe Mathieu-Daudé * Note: A valid DevId will be inserted during pci_e1000_realize(). 16328597f2e1SGabriel L. Somlo */ 163388b4e9dbSblueswir1 static const uint16_t e1000_eeprom_template[64] = { 16347c23b892Sbalrog 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 16358597f2e1SGabriel L. Somlo 0x3000, 0x1000, 0x6403, 0 /*DevId*/, 0x8086, 0 /*DevId*/, 0x8086, 0x3040, 16367c23b892Sbalrog 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700, 16377c23b892Sbalrog 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706, 16387c23b892Sbalrog 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff, 16397c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 16407c23b892Sbalrog 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 16417c23b892Sbalrog 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 16427c23b892Sbalrog }; 16437c23b892Sbalrog 16447c23b892Sbalrog /* PCI interface */ 16457c23b892Sbalrog 16467c23b892Sbalrog static void 1647ad00a9b9SAvi Kivity e1000_mmio_setup(E1000State *d) 16487c23b892Sbalrog { 1649f65ed4c1Saliguori int i; 1650f65ed4c1Saliguori const uint32_t excluded_regs[] = { 1651f65ed4c1Saliguori E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, 1652f65ed4c1Saliguori E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE 1653f65ed4c1Saliguori }; 1654f65ed4c1Saliguori 1655eedfac6fSPaolo Bonzini memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d, 1656eedfac6fSPaolo Bonzini "e1000-mmio", PNPMMIO_SIZE); 1657ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]); 1658f65ed4c1Saliguori for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) 1659ad00a9b9SAvi Kivity memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4, 1660ad00a9b9SAvi Kivity excluded_regs[i+1] - excluded_regs[i] - 4); 1661eedfac6fSPaolo Bonzini memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE); 16627c23b892Sbalrog } 16637c23b892Sbalrog 1664b946a153Saliguori static void 16654b09be85Saliguori pci_e1000_uninit(PCIDevice *dev) 16664b09be85Saliguori { 1667567a3c9eSPeter Crosthwaite E1000State *d = E1000(dev); 16684b09be85Saliguori 1669bc72ad67SAlex Bligh timer_free(d->autoneg_timer); 1670e9845f09SVincenzo Maffione timer_free(d->mit_timer); 1671157628d0Syuchenlin timer_free(d->flush_queue_timer); 1672948ecf21SJason Wang qemu_del_nic(d->nic); 16734b09be85Saliguori } 16744b09be85Saliguori 1675a03e2aecSMark McLoughlin static NetClientInfo net_e1000_info = { 1676f394b2e2SEric Blake .type = NET_CLIENT_DRIVER_NIC, 1677a03e2aecSMark McLoughlin .size = sizeof(NICState), 1678a03e2aecSMark McLoughlin .can_receive = e1000_can_receive, 1679a03e2aecSMark McLoughlin .receive = e1000_receive, 168097410ddeSVincenzo Maffione .receive_iov = e1000_receive_iov, 1681a03e2aecSMark McLoughlin .link_status_changed = e1000_set_link_status, 1682a03e2aecSMark McLoughlin }; 1683a03e2aecSMark McLoughlin 168420302e71SMichael S. Tsirkin static void e1000_write_config(PCIDevice *pci_dev, uint32_t address, 168520302e71SMichael S. Tsirkin uint32_t val, int len) 168620302e71SMichael S. Tsirkin { 168720302e71SMichael S. Tsirkin E1000State *s = E1000(pci_dev); 168820302e71SMichael S. Tsirkin 168920302e71SMichael S. Tsirkin pci_default_write_config(pci_dev, address, val, len); 169020302e71SMichael S. Tsirkin 169120302e71SMichael S. Tsirkin if (range_covers_byte(address, len, PCI_COMMAND) && 169220302e71SMichael S. Tsirkin (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { 169320302e71SMichael S. Tsirkin qemu_flush_queued_packets(qemu_get_queue(s->nic)); 169420302e71SMichael S. Tsirkin } 169520302e71SMichael S. Tsirkin } 169620302e71SMichael S. Tsirkin 16979af21dbeSMarkus Armbruster static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) 16987c23b892Sbalrog { 1699567a3c9eSPeter Crosthwaite DeviceState *dev = DEVICE(pci_dev); 1700567a3c9eSPeter Crosthwaite E1000State *d = E1000(pci_dev); 17017c23b892Sbalrog uint8_t *pci_conf; 1702fbdaa002SGerd Hoffmann uint8_t *macaddr; 1703aff427a1SChris Wright 170420302e71SMichael S. Tsirkin pci_dev->config_write = e1000_write_config; 170520302e71SMichael S. Tsirkin 1706b08340d5SAndreas Färber pci_conf = pci_dev->config; 17077c23b892Sbalrog 1708a9cbacb0SMichael S. Tsirkin /* TODO: RST# value should be 0, PCI spec 6.2.4 */ 1709a9cbacb0SMichael S. Tsirkin pci_conf[PCI_CACHE_LINE_SIZE] = 0x10; 17107c23b892Sbalrog 1711817e0b6fSMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ 17127c23b892Sbalrog 1713ad00a9b9SAvi Kivity e1000_mmio_setup(d); 17147c23b892Sbalrog 1715b08340d5SAndreas Färber pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 17167c23b892Sbalrog 1717b08340d5SAndreas Färber pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io); 17187c23b892Sbalrog 1719fbdaa002SGerd Hoffmann qemu_macaddr_default_if_unset(&d->conf.macaddr); 1720fbdaa002SGerd Hoffmann macaddr = d->conf.macaddr.a; 1721093454e2SDmitry Fleytman 1722093454e2SDmitry Fleytman e1000x_core_prepare_eeprom(d->eeprom_data, 1723093454e2SDmitry Fleytman e1000_eeprom_template, 1724093454e2SDmitry Fleytman sizeof(e1000_eeprom_template), 1725093454e2SDmitry Fleytman PCI_DEVICE_GET_CLASS(pci_dev)->device_id, 1726093454e2SDmitry Fleytman macaddr); 17277c23b892Sbalrog 1728a03e2aecSMark McLoughlin d->nic = qemu_new_nic(&net_e1000_info, &d->conf, 1729567a3c9eSPeter Crosthwaite object_get_typename(OBJECT(d)), dev->id, d); 17307c23b892Sbalrog 1731b356f76dSJason Wang qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); 17321ca4d09aSGleb Natapov 1733bc72ad67SAlex Bligh d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d); 1734e9845f09SVincenzo Maffione d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); 1735157628d0Syuchenlin d->flush_queue_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, 1736157628d0Syuchenlin e1000_flush_queue_timer, d); 17377c23b892Sbalrog } 17389d07d757SPaul Brook 1739fbdaa002SGerd Hoffmann static void qdev_e1000_reset(DeviceState *dev) 1740fbdaa002SGerd Hoffmann { 1741567a3c9eSPeter Crosthwaite E1000State *d = E1000(dev); 1742fbdaa002SGerd Hoffmann e1000_reset(d); 1743fbdaa002SGerd Hoffmann } 1744fbdaa002SGerd Hoffmann 174540021f08SAnthony Liguori static Property e1000_properties[] = { 1746fbdaa002SGerd Hoffmann DEFINE_NIC_PROPERTIES(E1000State, conf), 17472af234e6SMichael S. Tsirkin DEFINE_PROP_BIT("autonegotiation", E1000State, 17482af234e6SMichael S. Tsirkin compat_flags, E1000_FLAG_AUTONEG_BIT, true), 1749e9845f09SVincenzo Maffione DEFINE_PROP_BIT("mitigation", E1000State, 1750e9845f09SVincenzo Maffione compat_flags, E1000_FLAG_MIT_BIT, true), 1751ba63ec85SLeonid Bloch DEFINE_PROP_BIT("extra_mac_registers", E1000State, 1752ba63ec85SLeonid Bloch compat_flags, E1000_FLAG_MAC_BIT, true), 175346f2a9ecSDr. David Alan Gilbert DEFINE_PROP_BIT("migrate_tso_props", E1000State, 175446f2a9ecSDr. David Alan Gilbert compat_flags, E1000_FLAG_TSO_BIT, true), 1755*a1d7e475SChristina Wang DEFINE_PROP_BIT("init-vet", E1000State, 1756*a1d7e475SChristina Wang compat_flags, E1000_FLAG_VET_BIT, true), 1757fbdaa002SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 175840021f08SAnthony Liguori }; 175940021f08SAnthony Liguori 17608597f2e1SGabriel L. Somlo typedef struct E1000Info { 17618597f2e1SGabriel L. Somlo const char *name; 17628597f2e1SGabriel L. Somlo uint16_t device_id; 17638597f2e1SGabriel L. Somlo uint8_t revision; 17648597f2e1SGabriel L. Somlo uint16_t phy_id2; 17658597f2e1SGabriel L. Somlo } E1000Info; 17668597f2e1SGabriel L. Somlo 176740021f08SAnthony Liguori static void e1000_class_init(ObjectClass *klass, void *data) 176840021f08SAnthony Liguori { 176939bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 177040021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1771c51325d8SEduardo Habkost E1000BaseClass *e = E1000_CLASS(klass); 17728597f2e1SGabriel L. Somlo const E1000Info *info = data; 177340021f08SAnthony Liguori 17749af21dbeSMarkus Armbruster k->realize = pci_e1000_realize; 177540021f08SAnthony Liguori k->exit = pci_e1000_uninit; 1776c45e5b5bSGerd Hoffmann k->romfile = "efi-e1000.rom"; 177740021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_INTEL; 17788597f2e1SGabriel L. Somlo k->device_id = info->device_id; 17798597f2e1SGabriel L. Somlo k->revision = info->revision; 17808597f2e1SGabriel L. Somlo e->phy_id2 = info->phy_id2; 178140021f08SAnthony Liguori k->class_id = PCI_CLASS_NETWORK_ETHERNET; 1782125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 178339bffca2SAnthony Liguori dc->desc = "Intel Gigabit Ethernet"; 178439bffca2SAnthony Liguori dc->reset = qdev_e1000_reset; 178539bffca2SAnthony Liguori dc->vmsd = &vmstate_e1000; 17864f67d30bSMarc-André Lureau device_class_set_props(dc, e1000_properties); 1787fbdaa002SGerd Hoffmann } 178840021f08SAnthony Liguori 17895df3bf62SGonglei static void e1000_instance_init(Object *obj) 17905df3bf62SGonglei { 17915df3bf62SGonglei E1000State *n = E1000(obj); 17925df3bf62SGonglei device_add_bootindex_property(obj, &n->conf.bootindex, 17935df3bf62SGonglei "bootindex", "/ethernet-phy@0", 179440c2281cSMarkus Armbruster DEVICE(n)); 17955df3bf62SGonglei } 17965df3bf62SGonglei 17978597f2e1SGabriel L. Somlo static const TypeInfo e1000_base_info = { 17988597f2e1SGabriel L. Somlo .name = TYPE_E1000_BASE, 179939bffca2SAnthony Liguori .parent = TYPE_PCI_DEVICE, 180039bffca2SAnthony Liguori .instance_size = sizeof(E1000State), 18015df3bf62SGonglei .instance_init = e1000_instance_init, 18028597f2e1SGabriel L. Somlo .class_size = sizeof(E1000BaseClass), 18038597f2e1SGabriel L. Somlo .abstract = true, 1804fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 1805fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 1806fd3b02c8SEduardo Habkost { }, 1807fd3b02c8SEduardo Habkost }, 18088597f2e1SGabriel L. Somlo }; 18098597f2e1SGabriel L. Somlo 18108597f2e1SGabriel L. Somlo static const E1000Info e1000_devices[] = { 18118597f2e1SGabriel L. Somlo { 181283044020SJason Wang .name = "e1000", 18138597f2e1SGabriel L. Somlo .device_id = E1000_DEV_ID_82540EM, 18148597f2e1SGabriel L. Somlo .revision = 0x03, 18158597f2e1SGabriel L. Somlo .phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT, 18168597f2e1SGabriel L. Somlo }, 18178597f2e1SGabriel L. Somlo { 18188597f2e1SGabriel L. Somlo .name = "e1000-82544gc", 18198597f2e1SGabriel L. Somlo .device_id = E1000_DEV_ID_82544GC_COPPER, 18208597f2e1SGabriel L. Somlo .revision = 0x03, 18218597f2e1SGabriel L. Somlo .phy_id2 = E1000_PHY_ID2_82544x, 18228597f2e1SGabriel L. Somlo }, 18238597f2e1SGabriel L. Somlo { 18248597f2e1SGabriel L. Somlo .name = "e1000-82545em", 18258597f2e1SGabriel L. Somlo .device_id = E1000_DEV_ID_82545EM_COPPER, 18268597f2e1SGabriel L. Somlo .revision = 0x03, 18278597f2e1SGabriel L. Somlo .phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT, 18288597f2e1SGabriel L. Somlo }, 18298597f2e1SGabriel L. Somlo }; 18308597f2e1SGabriel L. Somlo 183183f7d43aSAndreas Färber static void e1000_register_types(void) 18329d07d757SPaul Brook { 18338597f2e1SGabriel L. Somlo int i; 18348597f2e1SGabriel L. Somlo 18358597f2e1SGabriel L. Somlo type_register_static(&e1000_base_info); 18368597f2e1SGabriel L. Somlo for (i = 0; i < ARRAY_SIZE(e1000_devices); i++) { 18378597f2e1SGabriel L. Somlo const E1000Info *info = &e1000_devices[i]; 18388597f2e1SGabriel L. Somlo TypeInfo type_info = {}; 18398597f2e1SGabriel L. Somlo 18408597f2e1SGabriel L. Somlo type_info.name = info->name; 18418597f2e1SGabriel L. Somlo type_info.parent = TYPE_E1000_BASE; 18428597f2e1SGabriel L. Somlo type_info.class_data = (void *)info; 18438597f2e1SGabriel L. Somlo type_info.class_init = e1000_class_init; 18448597f2e1SGabriel L. Somlo 18458597f2e1SGabriel L. Somlo type_register(&type_info); 18468597f2e1SGabriel L. Somlo } 18479d07d757SPaul Brook } 18489d07d757SPaul Brook 184983f7d43aSAndreas Färber type_init(e1000_register_types) 1850