xref: /qemu/hw/net/e1000.c (revision 9e64f8a3fcc88a508990a62ecc5a1269e41272ad)
17c23b892Sbalrog /*
27c23b892Sbalrog  * QEMU e1000 emulation
37c23b892Sbalrog  *
42758aa52SMichael S. Tsirkin  * Software developer's manual:
52758aa52SMichael S. Tsirkin  * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
62758aa52SMichael S. Tsirkin  *
77c23b892Sbalrog  * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
87c23b892Sbalrog  * Copyright (c) 2008 Qumranet
97c23b892Sbalrog  * Based on work done by:
107c23b892Sbalrog  * Copyright (c) 2007 Dan Aloni
117c23b892Sbalrog  * Copyright (c) 2004 Antony T Curtis
127c23b892Sbalrog  *
137c23b892Sbalrog  * This library is free software; you can redistribute it and/or
147c23b892Sbalrog  * modify it under the terms of the GNU Lesser General Public
157c23b892Sbalrog  * License as published by the Free Software Foundation; either
167c23b892Sbalrog  * version 2 of the License, or (at your option) any later version.
177c23b892Sbalrog  *
187c23b892Sbalrog  * This library is distributed in the hope that it will be useful,
197c23b892Sbalrog  * but WITHOUT ANY WARRANTY; without even the implied warranty of
207c23b892Sbalrog  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
217c23b892Sbalrog  * Lesser General Public License for more details.
227c23b892Sbalrog  *
237c23b892Sbalrog  * You should have received a copy of the GNU Lesser General Public
248167ee88SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
257c23b892Sbalrog  */
267c23b892Sbalrog 
277c23b892Sbalrog 
2883c9f4caSPaolo Bonzini #include "hw/hw.h"
2983c9f4caSPaolo Bonzini #include "hw/pci/pci.h"
301422e32dSPaolo Bonzini #include "net/net.h"
317200ac3cSMark McLoughlin #include "net/checksum.h"
3283c9f4caSPaolo Bonzini #include "hw/loader.h"
339c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
349c17d615SPaolo Bonzini #include "sysemu/dma.h"
357c23b892Sbalrog 
3647b43a1fSPaolo Bonzini #include "e1000_regs.h"
377c23b892Sbalrog 
3827124888SJes Sorensen #define E1000_DEBUG
397c23b892Sbalrog 
4027124888SJes Sorensen #ifdef E1000_DEBUG
417c23b892Sbalrog enum {
427c23b892Sbalrog     DEBUG_GENERAL,	DEBUG_IO,	DEBUG_MMIO,	DEBUG_INTERRUPT,
437c23b892Sbalrog     DEBUG_RX,		DEBUG_TX,	DEBUG_MDIC,	DEBUG_EEPROM,
447c23b892Sbalrog     DEBUG_UNKNOWN,	DEBUG_TXSUM,	DEBUG_TXERR,	DEBUG_RXERR,
45f9c1cdf4SJason Wang     DEBUG_RXFILTER,     DEBUG_PHY,      DEBUG_NOTYET,
467c23b892Sbalrog };
477c23b892Sbalrog #define DBGBIT(x)	(1<<DEBUG_##x)
487c23b892Sbalrog static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
497c23b892Sbalrog 
506c7f4b47SBlue Swirl #define	DBGOUT(what, fmt, ...) do { \
517c23b892Sbalrog     if (debugflags & DBGBIT(what)) \
526c7f4b47SBlue Swirl         fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \
537c23b892Sbalrog     } while (0)
547c23b892Sbalrog #else
556c7f4b47SBlue Swirl #define	DBGOUT(what, fmt, ...) do {} while (0)
567c23b892Sbalrog #endif
577c23b892Sbalrog 
587c23b892Sbalrog #define IOPORT_SIZE       0x40
59e94bbefeSaurel32 #define PNPMMIO_SIZE      0x20000
6078aeb23eSStefan Hajnoczi #define MIN_BUF_SIZE      60 /* Min. octets in an ethernet frame sans FCS */
617c23b892Sbalrog 
62b0d9ffcdSMichael Contreras /* this is the size past which hardware will drop packets when setting LPE=0 */
63b0d9ffcdSMichael Contreras #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
642c0331f4SMichael Contreras /* this is the size past which hardware will drop packets when setting LPE=1 */
652c0331f4SMichael Contreras #define MAXIMUM_ETHERNET_LPE_SIZE 16384
66b0d9ffcdSMichael Contreras 
677c23b892Sbalrog /*
687c23b892Sbalrog  * HW models:
697c23b892Sbalrog  *  E1000_DEV_ID_82540EM works with Windows and Linux
707c23b892Sbalrog  *  E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
717c23b892Sbalrog  *	appears to perform better than 82540EM, but breaks with Linux 2.6.18
727c23b892Sbalrog  *  E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
737c23b892Sbalrog  *  Others never tested
747c23b892Sbalrog  */
757c23b892Sbalrog enum { E1000_DEVID = E1000_DEV_ID_82540EM };
767c23b892Sbalrog 
777c23b892Sbalrog /*
787c23b892Sbalrog  * May need to specify additional MAC-to-PHY entries --
797c23b892Sbalrog  * Intel's Windows driver refuses to initialize unless they match
807c23b892Sbalrog  */
817c23b892Sbalrog enum {
827c23b892Sbalrog     PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ?		0xcc2 :
837c23b892Sbalrog                    E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ?	0xc30 :
847c23b892Sbalrog                    /* default to E1000_DEV_ID_82540EM */	0xc20
857c23b892Sbalrog };
867c23b892Sbalrog 
877c23b892Sbalrog typedef struct E1000State_st {
88b08340d5SAndreas Färber     /*< private >*/
89b08340d5SAndreas Färber     PCIDevice parent_obj;
90b08340d5SAndreas Färber     /*< public >*/
91b08340d5SAndreas Färber 
92a03e2aecSMark McLoughlin     NICState *nic;
93fbdaa002SGerd Hoffmann     NICConf conf;
94ad00a9b9SAvi Kivity     MemoryRegion mmio;
95ad00a9b9SAvi Kivity     MemoryRegion io;
967c23b892Sbalrog 
977c23b892Sbalrog     uint32_t mac_reg[0x8000];
987c23b892Sbalrog     uint16_t phy_reg[0x20];
997c23b892Sbalrog     uint16_t eeprom_data[64];
1007c23b892Sbalrog 
1017c23b892Sbalrog     uint32_t rxbuf_size;
1027c23b892Sbalrog     uint32_t rxbuf_min_shift;
1037c23b892Sbalrog     struct e1000_tx {
1047c23b892Sbalrog         unsigned char header[256];
1058f2e8d1fSaliguori         unsigned char vlan_header[4];
106b10fec9bSStefan Weil         /* Fields vlan and data must not be reordered or separated. */
1078f2e8d1fSaliguori         unsigned char vlan[4];
1087c23b892Sbalrog         unsigned char data[0x10000];
1097c23b892Sbalrog         uint16_t size;
1107c23b892Sbalrog         unsigned char sum_needed;
1118f2e8d1fSaliguori         unsigned char vlan_needed;
1127c23b892Sbalrog         uint8_t ipcss;
1137c23b892Sbalrog         uint8_t ipcso;
1147c23b892Sbalrog         uint16_t ipcse;
1157c23b892Sbalrog         uint8_t tucss;
1167c23b892Sbalrog         uint8_t tucso;
1177c23b892Sbalrog         uint16_t tucse;
1187c23b892Sbalrog         uint8_t hdr_len;
1197c23b892Sbalrog         uint16_t mss;
1207c23b892Sbalrog         uint32_t paylen;
1217c23b892Sbalrog         uint16_t tso_frames;
1227c23b892Sbalrog         char tse;
123b6c4f71fSblueswir1         int8_t ip;
124b6c4f71fSblueswir1         int8_t tcp;
1251b0009dbSbalrog         char cptse;     // current packet tse bit
1267c23b892Sbalrog     } tx;
1277c23b892Sbalrog 
1287c23b892Sbalrog     struct {
1297c23b892Sbalrog         uint32_t val_in;	// shifted in from guest driver
1307c23b892Sbalrog         uint16_t bitnum_in;
1317c23b892Sbalrog         uint16_t bitnum_out;
1327c23b892Sbalrog         uint16_t reading;
1337c23b892Sbalrog         uint32_t old_eecd;
1347c23b892Sbalrog     } eecd_state;
135b9d03e35SJason Wang 
136b9d03e35SJason Wang     QEMUTimer *autoneg_timer;
1372af234e6SMichael S. Tsirkin 
138e9845f09SVincenzo Maffione     QEMUTimer *mit_timer;      /* Mitigation timer. */
139e9845f09SVincenzo Maffione     bool mit_timer_on;         /* Mitigation timer is running. */
140e9845f09SVincenzo Maffione     bool mit_irq_level;        /* Tracks interrupt pin level. */
141e9845f09SVincenzo Maffione     uint32_t mit_ide;          /* Tracks E1000_TXD_CMD_IDE bit. */
142e9845f09SVincenzo Maffione 
1432af234e6SMichael S. Tsirkin /* Compatibility flags for migration to/from qemu 1.3.0 and older */
1442af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG_BIT 0
145e9845f09SVincenzo Maffione #define E1000_FLAG_MIT_BIT 1
1462af234e6SMichael S. Tsirkin #define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT)
147e9845f09SVincenzo Maffione #define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT)
1482af234e6SMichael S. Tsirkin     uint32_t compat_flags;
1497c23b892Sbalrog } E1000State;
1507c23b892Sbalrog 
151567a3c9eSPeter Crosthwaite #define TYPE_E1000 "e1000"
152567a3c9eSPeter Crosthwaite 
153567a3c9eSPeter Crosthwaite #define E1000(obj) \
154567a3c9eSPeter Crosthwaite     OBJECT_CHECK(E1000State, (obj), TYPE_E1000)
155567a3c9eSPeter Crosthwaite 
1567c23b892Sbalrog #define	defreg(x)	x = (E1000_##x>>2)
1577c23b892Sbalrog enum {
1587c23b892Sbalrog     defreg(CTRL),	defreg(EECD),	defreg(EERD),	defreg(GPRC),
1597c23b892Sbalrog     defreg(GPTC),	defreg(ICR),	defreg(ICS),	defreg(IMC),
1607c23b892Sbalrog     defreg(IMS),	defreg(LEDCTL),	defreg(MANC),	defreg(MDIC),
1617c23b892Sbalrog     defreg(MPC),	defreg(PBA),	defreg(RCTL),	defreg(RDBAH),
1627c23b892Sbalrog     defreg(RDBAL),	defreg(RDH),	defreg(RDLEN),	defreg(RDT),
1637c23b892Sbalrog     defreg(STATUS),	defreg(SWSM),	defreg(TCTL),	defreg(TDBAH),
1647c23b892Sbalrog     defreg(TDBAL),	defreg(TDH),	defreg(TDLEN),	defreg(TDT),
1657c23b892Sbalrog     defreg(TORH),	defreg(TORL),	defreg(TOTH),	defreg(TOTL),
1667c23b892Sbalrog     defreg(TPR),	defreg(TPT),	defreg(TXDCTL),	defreg(WUFC),
1678f2e8d1fSaliguori     defreg(RA),		defreg(MTA),	defreg(CRCERRS),defreg(VFTA),
168e9845f09SVincenzo Maffione     defreg(VET),        defreg(RDTR),   defreg(RADV),   defreg(TADV),
169e9845f09SVincenzo Maffione     defreg(ITR),
1707c23b892Sbalrog };
1717c23b892Sbalrog 
17271aadd3cSJason Wang static void
17371aadd3cSJason Wang e1000_link_down(E1000State *s)
17471aadd3cSJason Wang {
17571aadd3cSJason Wang     s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
17671aadd3cSJason Wang     s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
17771aadd3cSJason Wang }
17871aadd3cSJason Wang 
17971aadd3cSJason Wang static void
18071aadd3cSJason Wang e1000_link_up(E1000State *s)
18171aadd3cSJason Wang {
18271aadd3cSJason Wang     s->mac_reg[STATUS] |= E1000_STATUS_LU;
18371aadd3cSJason Wang     s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
18471aadd3cSJason Wang }
18571aadd3cSJason Wang 
186b9d03e35SJason Wang static void
187b9d03e35SJason Wang set_phy_ctrl(E1000State *s, int index, uint16_t val)
188b9d03e35SJason Wang {
1892af234e6SMichael S. Tsirkin     /*
1902af234e6SMichael S. Tsirkin      * QEMU 1.3 does not support link auto-negotiation emulation, so if we
1912af234e6SMichael S. Tsirkin      * migrate during auto negotiation, after migration the link will be
1922af234e6SMichael S. Tsirkin      * down.
1932af234e6SMichael S. Tsirkin      */
1942af234e6SMichael S. Tsirkin     if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
1952af234e6SMichael S. Tsirkin         return;
1962af234e6SMichael S. Tsirkin     }
197b9d03e35SJason Wang     if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
198b9d03e35SJason Wang         e1000_link_down(s);
199b9d03e35SJason Wang         s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
200b9d03e35SJason Wang         DBGOUT(PHY, "Start link auto negotiation\n");
201bc72ad67SAlex Bligh         timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
202b9d03e35SJason Wang     }
203b9d03e35SJason Wang }
204b9d03e35SJason Wang 
205b9d03e35SJason Wang static void
206b9d03e35SJason Wang e1000_autoneg_timer(void *opaque)
207b9d03e35SJason Wang {
208b9d03e35SJason Wang     E1000State *s = opaque;
209ddcb73b7SMichael S. Tsirkin     if (!qemu_get_queue(s->nic)->link_down) {
210b9d03e35SJason Wang         e1000_link_up(s);
211ddcb73b7SMichael S. Tsirkin     }
212b9d03e35SJason Wang     s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
213b9d03e35SJason Wang     DBGOUT(PHY, "Auto negotiation is completed\n");
214b9d03e35SJason Wang }
215b9d03e35SJason Wang 
216b9d03e35SJason Wang static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
217b9d03e35SJason Wang     [PHY_CTRL] = set_phy_ctrl,
218b9d03e35SJason Wang };
219b9d03e35SJason Wang 
220b9d03e35SJason Wang enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) };
221b9d03e35SJason Wang 
2227c23b892Sbalrog enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
22388b4e9dbSblueswir1 static const char phy_regcap[0x20] = {
2247c23b892Sbalrog     [PHY_STATUS] = PHY_R,	[M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
2257c23b892Sbalrog     [PHY_ID1] = PHY_R,		[M88E1000_PHY_SPEC_CTRL] = PHY_RW,
2267c23b892Sbalrog     [PHY_CTRL] = PHY_RW,	[PHY_1000T_CTRL] = PHY_RW,
2277c23b892Sbalrog     [PHY_LP_ABILITY] = PHY_R,	[PHY_1000T_STATUS] = PHY_R,
2287c23b892Sbalrog     [PHY_AUTONEG_ADV] = PHY_RW,	[M88E1000_RX_ERR_CNTR] = PHY_R,
229700f6e2cSaurel32     [PHY_ID2] = PHY_R,		[M88E1000_PHY_SPEC_STATUS] = PHY_R
2307c23b892Sbalrog };
2317c23b892Sbalrog 
232814cd3acSMichael S. Tsirkin static const uint16_t phy_reg_init[] = {
233b9d03e35SJason Wang     [PHY_CTRL] = 0x1140,
234b9d03e35SJason Wang     [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
235814cd3acSMichael S. Tsirkin     [PHY_ID1] = 0x141,				[PHY_ID2] = PHY_ID2_INIT,
236814cd3acSMichael S. Tsirkin     [PHY_1000T_CTRL] = 0x0e00,			[M88E1000_PHY_SPEC_CTRL] = 0x360,
237814cd3acSMichael S. Tsirkin     [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60,	[PHY_AUTONEG_ADV] = 0xde1,
238814cd3acSMichael S. Tsirkin     [PHY_LP_ABILITY] = 0x1e0,			[PHY_1000T_STATUS] = 0x3c00,
239814cd3acSMichael S. Tsirkin     [M88E1000_PHY_SPEC_STATUS] = 0xac00,
240814cd3acSMichael S. Tsirkin };
241814cd3acSMichael S. Tsirkin 
242814cd3acSMichael S. Tsirkin static const uint32_t mac_reg_init[] = {
243814cd3acSMichael S. Tsirkin     [PBA] =     0x00100030,
244814cd3acSMichael S. Tsirkin     [LEDCTL] =  0x602,
245814cd3acSMichael S. Tsirkin     [CTRL] =    E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
246814cd3acSMichael S. Tsirkin                 E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
247814cd3acSMichael S. Tsirkin     [STATUS] =  0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
248814cd3acSMichael S. Tsirkin                 E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
249814cd3acSMichael S. Tsirkin                 E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
250814cd3acSMichael S. Tsirkin                 E1000_STATUS_LU,
251814cd3acSMichael S. Tsirkin     [MANC] =    E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
252814cd3acSMichael S. Tsirkin                 E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
253814cd3acSMichael S. Tsirkin                 E1000_MANC_RMCP_EN,
254814cd3acSMichael S. Tsirkin };
255814cd3acSMichael S. Tsirkin 
256e9845f09SVincenzo Maffione /* Helper function, *curr == 0 means the value is not set */
257e9845f09SVincenzo Maffione static inline void
258e9845f09SVincenzo Maffione mit_update_delay(uint32_t *curr, uint32_t value)
259e9845f09SVincenzo Maffione {
260e9845f09SVincenzo Maffione     if (value && (*curr == 0 || value < *curr)) {
261e9845f09SVincenzo Maffione         *curr = value;
262e9845f09SVincenzo Maffione     }
263e9845f09SVincenzo Maffione }
264e9845f09SVincenzo Maffione 
2657c23b892Sbalrog static void
2667c23b892Sbalrog set_interrupt_cause(E1000State *s, int index, uint32_t val)
2677c23b892Sbalrog {
268b08340d5SAndreas Färber     PCIDevice *d = PCI_DEVICE(s);
269e9845f09SVincenzo Maffione     uint32_t pending_ints;
270e9845f09SVincenzo Maffione     uint32_t mit_delay;
271b08340d5SAndreas Färber 
272f1219091SJason Wang     if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
273f1219091SJason Wang         /* Only for 8257x */
2747c23b892Sbalrog         val |= E1000_ICR_INT_ASSERTED;
275f1219091SJason Wang     }
2767c23b892Sbalrog     s->mac_reg[ICR] = val;
277a52a8841SMichael S. Tsirkin 
278a52a8841SMichael S. Tsirkin     /*
279a52a8841SMichael S. Tsirkin      * Make sure ICR and ICS registers have the same value.
280a52a8841SMichael S. Tsirkin      * The spec says that the ICS register is write-only.  However in practice,
281a52a8841SMichael S. Tsirkin      * on real hardware ICS is readable, and for reads it has the same value as
282a52a8841SMichael S. Tsirkin      * ICR (except that ICS does not have the clear on read behaviour of ICR).
283a52a8841SMichael S. Tsirkin      *
284a52a8841SMichael S. Tsirkin      * The VxWorks PRO/1000 driver uses this behaviour.
285a52a8841SMichael S. Tsirkin      */
286b1332393SBill Paul     s->mac_reg[ICS] = val;
287a52a8841SMichael S. Tsirkin 
288e9845f09SVincenzo Maffione     pending_ints = (s->mac_reg[IMS] & s->mac_reg[ICR]);
289e9845f09SVincenzo Maffione     if (!s->mit_irq_level && pending_ints) {
290e9845f09SVincenzo Maffione         /*
291e9845f09SVincenzo Maffione          * Here we detect a potential raising edge. We postpone raising the
292e9845f09SVincenzo Maffione          * interrupt line if we are inside the mitigation delay window
293e9845f09SVincenzo Maffione          * (s->mit_timer_on == 1).
294e9845f09SVincenzo Maffione          * We provide a partial implementation of interrupt mitigation,
295e9845f09SVincenzo Maffione          * emulating only RADV, TADV and ITR (lower 16 bits, 1024ns units for
296e9845f09SVincenzo Maffione          * RADV and TADV, 256ns units for ITR). RDTR is only used to enable
297e9845f09SVincenzo Maffione          * RADV; relative timers based on TIDV and RDTR are not implemented.
298e9845f09SVincenzo Maffione          */
299e9845f09SVincenzo Maffione         if (s->mit_timer_on) {
300e9845f09SVincenzo Maffione             return;
301e9845f09SVincenzo Maffione         }
302e9845f09SVincenzo Maffione         if (s->compat_flags & E1000_FLAG_MIT) {
303e9845f09SVincenzo Maffione             /* Compute the next mitigation delay according to pending
304e9845f09SVincenzo Maffione              * interrupts and the current values of RADV (provided
305e9845f09SVincenzo Maffione              * RDTR!=0), TADV and ITR.
306e9845f09SVincenzo Maffione              * Then rearm the timer.
307e9845f09SVincenzo Maffione              */
308e9845f09SVincenzo Maffione             mit_delay = 0;
309e9845f09SVincenzo Maffione             if (s->mit_ide &&
310e9845f09SVincenzo Maffione                     (pending_ints & (E1000_ICR_TXQE | E1000_ICR_TXDW))) {
311e9845f09SVincenzo Maffione                 mit_update_delay(&mit_delay, s->mac_reg[TADV] * 4);
312e9845f09SVincenzo Maffione             }
313e9845f09SVincenzo Maffione             if (s->mac_reg[RDTR] && (pending_ints & E1000_ICS_RXT0)) {
314e9845f09SVincenzo Maffione                 mit_update_delay(&mit_delay, s->mac_reg[RADV] * 4);
315e9845f09SVincenzo Maffione             }
316e9845f09SVincenzo Maffione             mit_update_delay(&mit_delay, s->mac_reg[ITR]);
317e9845f09SVincenzo Maffione 
318e9845f09SVincenzo Maffione             if (mit_delay) {
319e9845f09SVincenzo Maffione                 s->mit_timer_on = 1;
320e9845f09SVincenzo Maffione                 timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
321e9845f09SVincenzo Maffione                           mit_delay * 256);
322e9845f09SVincenzo Maffione             }
323e9845f09SVincenzo Maffione             s->mit_ide = 0;
324e9845f09SVincenzo Maffione         }
325e9845f09SVincenzo Maffione     }
326e9845f09SVincenzo Maffione 
327e9845f09SVincenzo Maffione     s->mit_irq_level = (pending_ints != 0);
328*9e64f8a3SMarcel Apfelbaum     pci_set_irq(d, s->mit_irq_level);
329e9845f09SVincenzo Maffione }
330e9845f09SVincenzo Maffione 
331e9845f09SVincenzo Maffione static void
332e9845f09SVincenzo Maffione e1000_mit_timer(void *opaque)
333e9845f09SVincenzo Maffione {
334e9845f09SVincenzo Maffione     E1000State *s = opaque;
335e9845f09SVincenzo Maffione 
336e9845f09SVincenzo Maffione     s->mit_timer_on = 0;
337e9845f09SVincenzo Maffione     /* Call set_interrupt_cause to update the irq level (if necessary). */
338e9845f09SVincenzo Maffione     set_interrupt_cause(s, 0, s->mac_reg[ICR]);
3397c23b892Sbalrog }
3407c23b892Sbalrog 
3417c23b892Sbalrog static void
3427c23b892Sbalrog set_ics(E1000State *s, int index, uint32_t val)
3437c23b892Sbalrog {
3447c23b892Sbalrog     DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR],
3457c23b892Sbalrog         s->mac_reg[IMS]);
3467c23b892Sbalrog     set_interrupt_cause(s, 0, val | s->mac_reg[ICR]);
3477c23b892Sbalrog }
3487c23b892Sbalrog 
3497c23b892Sbalrog static int
3507c23b892Sbalrog rxbufsize(uint32_t v)
3517c23b892Sbalrog {
3527c23b892Sbalrog     v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
3537c23b892Sbalrog          E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
3547c23b892Sbalrog          E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
3557c23b892Sbalrog     switch (v) {
3567c23b892Sbalrog     case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
3577c23b892Sbalrog         return 16384;
3587c23b892Sbalrog     case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
3597c23b892Sbalrog         return 8192;
3607c23b892Sbalrog     case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
3617c23b892Sbalrog         return 4096;
3627c23b892Sbalrog     case E1000_RCTL_SZ_1024:
3637c23b892Sbalrog         return 1024;
3647c23b892Sbalrog     case E1000_RCTL_SZ_512:
3657c23b892Sbalrog         return 512;
3667c23b892Sbalrog     case E1000_RCTL_SZ_256:
3677c23b892Sbalrog         return 256;
3687c23b892Sbalrog     }
3697c23b892Sbalrog     return 2048;
3707c23b892Sbalrog }
3717c23b892Sbalrog 
372814cd3acSMichael S. Tsirkin static void e1000_reset(void *opaque)
373814cd3acSMichael S. Tsirkin {
374814cd3acSMichael S. Tsirkin     E1000State *d = opaque;
375372254c6SGabriel L. Somlo     uint8_t *macaddr = d->conf.macaddr.a;
376372254c6SGabriel L. Somlo     int i;
377814cd3acSMichael S. Tsirkin 
378bc72ad67SAlex Bligh     timer_del(d->autoneg_timer);
379e9845f09SVincenzo Maffione     timer_del(d->mit_timer);
380e9845f09SVincenzo Maffione     d->mit_timer_on = 0;
381e9845f09SVincenzo Maffione     d->mit_irq_level = 0;
382e9845f09SVincenzo Maffione     d->mit_ide = 0;
383814cd3acSMichael S. Tsirkin     memset(d->phy_reg, 0, sizeof d->phy_reg);
384814cd3acSMichael S. Tsirkin     memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
385814cd3acSMichael S. Tsirkin     memset(d->mac_reg, 0, sizeof d->mac_reg);
386814cd3acSMichael S. Tsirkin     memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
387814cd3acSMichael S. Tsirkin     d->rxbuf_min_shift = 1;
388814cd3acSMichael S. Tsirkin     memset(&d->tx, 0, sizeof d->tx);
389814cd3acSMichael S. Tsirkin 
390b356f76dSJason Wang     if (qemu_get_queue(d->nic)->link_down) {
39171aadd3cSJason Wang         e1000_link_down(d);
392814cd3acSMichael S. Tsirkin     }
393372254c6SGabriel L. Somlo 
394372254c6SGabriel L. Somlo     /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */
395372254c6SGabriel L. Somlo     d->mac_reg[RA] = 0;
396372254c6SGabriel L. Somlo     d->mac_reg[RA + 1] = E1000_RAH_AV;
397372254c6SGabriel L. Somlo     for (i = 0; i < 4; i++) {
398372254c6SGabriel L. Somlo         d->mac_reg[RA] |= macaddr[i] << (8 * i);
399372254c6SGabriel L. Somlo         d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0;
400372254c6SGabriel L. Somlo     }
401814cd3acSMichael S. Tsirkin }
402814cd3acSMichael S. Tsirkin 
4037c23b892Sbalrog static void
404cab3c825SKevin Wolf set_ctrl(E1000State *s, int index, uint32_t val)
405cab3c825SKevin Wolf {
406cab3c825SKevin Wolf     /* RST is self clearing */
407cab3c825SKevin Wolf     s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
408cab3c825SKevin Wolf }
409cab3c825SKevin Wolf 
410cab3c825SKevin Wolf static void
4117c23b892Sbalrog set_rx_control(E1000State *s, int index, uint32_t val)
4127c23b892Sbalrog {
4137c23b892Sbalrog     s->mac_reg[RCTL] = val;
4147c23b892Sbalrog     s->rxbuf_size = rxbufsize(val);
4157c23b892Sbalrog     s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
4167c23b892Sbalrog     DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
4177c23b892Sbalrog            s->mac_reg[RCTL]);
418b356f76dSJason Wang     qemu_flush_queued_packets(qemu_get_queue(s->nic));
4197c23b892Sbalrog }
4207c23b892Sbalrog 
4217c23b892Sbalrog static void
4227c23b892Sbalrog set_mdic(E1000State *s, int index, uint32_t val)
4237c23b892Sbalrog {
4247c23b892Sbalrog     uint32_t data = val & E1000_MDIC_DATA_MASK;
4257c23b892Sbalrog     uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
4267c23b892Sbalrog 
4277c23b892Sbalrog     if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy #
4287c23b892Sbalrog         val = s->mac_reg[MDIC] | E1000_MDIC_ERROR;
4297c23b892Sbalrog     else if (val & E1000_MDIC_OP_READ) {
4307c23b892Sbalrog         DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr);
4317c23b892Sbalrog         if (!(phy_regcap[addr] & PHY_R)) {
4327c23b892Sbalrog             DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr);
4337c23b892Sbalrog             val |= E1000_MDIC_ERROR;
4347c23b892Sbalrog         } else
4357c23b892Sbalrog             val = (val ^ data) | s->phy_reg[addr];
4367c23b892Sbalrog     } else if (val & E1000_MDIC_OP_WRITE) {
4377c23b892Sbalrog         DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data);
4387c23b892Sbalrog         if (!(phy_regcap[addr] & PHY_W)) {
4397c23b892Sbalrog             DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
4407c23b892Sbalrog             val |= E1000_MDIC_ERROR;
441b9d03e35SJason Wang         } else {
442b9d03e35SJason Wang             if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
443b9d03e35SJason Wang                 phyreg_writeops[addr](s, index, data);
444b9d03e35SJason Wang             }
4457c23b892Sbalrog             s->phy_reg[addr] = data;
4467c23b892Sbalrog         }
447b9d03e35SJason Wang     }
4487c23b892Sbalrog     s->mac_reg[MDIC] = val | E1000_MDIC_READY;
44917fbbb0bSJason Wang 
45017fbbb0bSJason Wang     if (val & E1000_MDIC_INT_EN) {
4517c23b892Sbalrog         set_ics(s, 0, E1000_ICR_MDAC);
4527c23b892Sbalrog     }
45317fbbb0bSJason Wang }
4547c23b892Sbalrog 
4557c23b892Sbalrog static uint32_t
4567c23b892Sbalrog get_eecd(E1000State *s, int index)
4577c23b892Sbalrog {
4587c23b892Sbalrog     uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd;
4597c23b892Sbalrog 
4607c23b892Sbalrog     DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n",
4617c23b892Sbalrog            s->eecd_state.bitnum_out, s->eecd_state.reading);
4627c23b892Sbalrog     if (!s->eecd_state.reading ||
4637c23b892Sbalrog         ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >>
4647c23b892Sbalrog           ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1)
4657c23b892Sbalrog         ret |= E1000_EECD_DO;
4667c23b892Sbalrog     return ret;
4677c23b892Sbalrog }
4687c23b892Sbalrog 
4697c23b892Sbalrog static void
4707c23b892Sbalrog set_eecd(E1000State *s, int index, uint32_t val)
4717c23b892Sbalrog {
4727c23b892Sbalrog     uint32_t oldval = s->eecd_state.old_eecd;
4737c23b892Sbalrog 
4747c23b892Sbalrog     s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS |
4757c23b892Sbalrog             E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ);
4769651ac55SIzumi Tsutsui     if (!(E1000_EECD_CS & val))			// CS inactive; nothing to do
4779651ac55SIzumi Tsutsui 	return;
4789651ac55SIzumi Tsutsui     if (E1000_EECD_CS & (val ^ oldval)) {	// CS rise edge; reset state
4799651ac55SIzumi Tsutsui 	s->eecd_state.val_in = 0;
4809651ac55SIzumi Tsutsui 	s->eecd_state.bitnum_in = 0;
4819651ac55SIzumi Tsutsui 	s->eecd_state.bitnum_out = 0;
4829651ac55SIzumi Tsutsui 	s->eecd_state.reading = 0;
4839651ac55SIzumi Tsutsui     }
4847c23b892Sbalrog     if (!(E1000_EECD_SK & (val ^ oldval)))	// no clock edge
4857c23b892Sbalrog         return;
4867c23b892Sbalrog     if (!(E1000_EECD_SK & val)) {		// falling edge
4877c23b892Sbalrog         s->eecd_state.bitnum_out++;
4887c23b892Sbalrog         return;
4897c23b892Sbalrog     }
4907c23b892Sbalrog     s->eecd_state.val_in <<= 1;
4917c23b892Sbalrog     if (val & E1000_EECD_DI)
4927c23b892Sbalrog         s->eecd_state.val_in |= 1;
4937c23b892Sbalrog     if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) {
4947c23b892Sbalrog         s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1;
4957c23b892Sbalrog         s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) ==
4967c23b892Sbalrog             EEPROM_READ_OPCODE_MICROWIRE);
4977c23b892Sbalrog     }
4987c23b892Sbalrog     DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n",
4997c23b892Sbalrog            s->eecd_state.bitnum_in, s->eecd_state.bitnum_out,
5007c23b892Sbalrog            s->eecd_state.reading);
5017c23b892Sbalrog }
5027c23b892Sbalrog 
5037c23b892Sbalrog static uint32_t
5047c23b892Sbalrog flash_eerd_read(E1000State *s, int x)
5057c23b892Sbalrog {
5067c23b892Sbalrog     unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START;
5077c23b892Sbalrog 
508b1332393SBill Paul     if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0)
509b1332393SBill Paul         return (s->mac_reg[EERD]);
510b1332393SBill Paul 
5117c23b892Sbalrog     if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG)
512b1332393SBill Paul         return (E1000_EEPROM_RW_REG_DONE | r);
513b1332393SBill Paul 
514b1332393SBill Paul     return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
515b1332393SBill Paul            E1000_EEPROM_RW_REG_DONE | r);
5167c23b892Sbalrog }
5177c23b892Sbalrog 
5187c23b892Sbalrog static void
5197c23b892Sbalrog putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
5207c23b892Sbalrog {
521c6a6a5e3Saliguori     uint32_t sum;
522c6a6a5e3Saliguori 
5237c23b892Sbalrog     if (cse && cse < n)
5247c23b892Sbalrog         n = cse + 1;
525c6a6a5e3Saliguori     if (sloc < n-1) {
526c6a6a5e3Saliguori         sum = net_checksum_add(n-css, data+css);
5277c23b892Sbalrog         cpu_to_be16wu((uint16_t *)(data + sloc),
528c6a6a5e3Saliguori                       net_checksum_finish(sum));
529c6a6a5e3Saliguori     }
5307c23b892Sbalrog }
5317c23b892Sbalrog 
5328f2e8d1fSaliguori static inline int
5338f2e8d1fSaliguori vlan_enabled(E1000State *s)
5348f2e8d1fSaliguori {
5358f2e8d1fSaliguori     return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0);
5368f2e8d1fSaliguori }
5378f2e8d1fSaliguori 
5388f2e8d1fSaliguori static inline int
5398f2e8d1fSaliguori vlan_rx_filter_enabled(E1000State *s)
5408f2e8d1fSaliguori {
5418f2e8d1fSaliguori     return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0);
5428f2e8d1fSaliguori }
5438f2e8d1fSaliguori 
5448f2e8d1fSaliguori static inline int
5458f2e8d1fSaliguori is_vlan_packet(E1000State *s, const uint8_t *buf)
5468f2e8d1fSaliguori {
5478f2e8d1fSaliguori     return (be16_to_cpup((uint16_t *)(buf + 12)) ==
5488f2e8d1fSaliguori                 le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
5498f2e8d1fSaliguori }
5508f2e8d1fSaliguori 
5518f2e8d1fSaliguori static inline int
5528f2e8d1fSaliguori is_vlan_txd(uint32_t txd_lower)
5538f2e8d1fSaliguori {
5548f2e8d1fSaliguori     return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
5558f2e8d1fSaliguori }
5568f2e8d1fSaliguori 
55755e8d1ceSMichael S. Tsirkin /* FCS aka Ethernet CRC-32. We don't get it from backends and can't
55855e8d1ceSMichael S. Tsirkin  * fill it in, just pad descriptor length by 4 bytes unless guest
559a05e8a6eSMichael S. Tsirkin  * told us to strip it off the packet. */
56055e8d1ceSMichael S. Tsirkin static inline int
56155e8d1ceSMichael S. Tsirkin fcs_len(E1000State *s)
56255e8d1ceSMichael S. Tsirkin {
56355e8d1ceSMichael S. Tsirkin     return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
56455e8d1ceSMichael S. Tsirkin }
56555e8d1ceSMichael S. Tsirkin 
5667c23b892Sbalrog static void
56793e37d76SJason Wang e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
56893e37d76SJason Wang {
569b356f76dSJason Wang     NetClientState *nc = qemu_get_queue(s->nic);
57093e37d76SJason Wang     if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
571b356f76dSJason Wang         nc->info->receive(nc, buf, size);
57293e37d76SJason Wang     } else {
573b356f76dSJason Wang         qemu_send_packet(nc, buf, size);
57493e37d76SJason Wang     }
57593e37d76SJason Wang }
57693e37d76SJason Wang 
57793e37d76SJason Wang static void
5787c23b892Sbalrog xmit_seg(E1000State *s)
5797c23b892Sbalrog {
5807c23b892Sbalrog     uint16_t len, *sp;
5817c23b892Sbalrog     unsigned int frames = s->tx.tso_frames, css, sofar, n;
5827c23b892Sbalrog     struct e1000_tx *tp = &s->tx;
5837c23b892Sbalrog 
5841b0009dbSbalrog     if (tp->tse && tp->cptse) {
5857c23b892Sbalrog         css = tp->ipcss;
5867c23b892Sbalrog         DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
5877c23b892Sbalrog                frames, tp->size, css);
5887c23b892Sbalrog         if (tp->ip) {		// IPv4
5897c23b892Sbalrog             cpu_to_be16wu((uint16_t *)(tp->data+css+2),
5907c23b892Sbalrog                           tp->size - css);
5917c23b892Sbalrog             cpu_to_be16wu((uint16_t *)(tp->data+css+4),
5927c23b892Sbalrog                           be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
5937c23b892Sbalrog         } else			// IPv6
5947c23b892Sbalrog             cpu_to_be16wu((uint16_t *)(tp->data+css+4),
5957c23b892Sbalrog                           tp->size - css);
5967c23b892Sbalrog         css = tp->tucss;
5977c23b892Sbalrog         len = tp->size - css;
5987c23b892Sbalrog         DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
5997c23b892Sbalrog         if (tp->tcp) {
6007c23b892Sbalrog             sofar = frames * tp->mss;
6017c23b892Sbalrog             cpu_to_be32wu((uint32_t *)(tp->data+css+4),	// seq
60288738c09Saurel32                 be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar);
6037c23b892Sbalrog             if (tp->paylen - sofar > tp->mss)
6047c23b892Sbalrog                 tp->data[css + 13] &= ~9;		// PSH, FIN
6057c23b892Sbalrog         } else	// UDP
6067c23b892Sbalrog             cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
6077c23b892Sbalrog         if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
608e685b4ebSAlex Williamson             unsigned int phsum;
6097c23b892Sbalrog             // add pseudo-header length before checksum calculation
6107c23b892Sbalrog             sp = (uint16_t *)(tp->data + tp->tucso);
611e685b4ebSAlex Williamson             phsum = be16_to_cpup(sp) + len;
612e685b4ebSAlex Williamson             phsum = (phsum >> 16) + (phsum & 0xffff);
613e685b4ebSAlex Williamson             cpu_to_be16wu(sp, phsum);
6147c23b892Sbalrog         }
6157c23b892Sbalrog         tp->tso_frames++;
6167c23b892Sbalrog     }
6177c23b892Sbalrog 
6187c23b892Sbalrog     if (tp->sum_needed & E1000_TXD_POPTS_TXSM)
6197c23b892Sbalrog         putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);
6207c23b892Sbalrog     if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
6217c23b892Sbalrog         putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
6228f2e8d1fSaliguori     if (tp->vlan_needed) {
623b10fec9bSStefan Weil         memmove(tp->vlan, tp->data, 4);
624b10fec9bSStefan Weil         memmove(tp->data, tp->data + 4, 8);
6258f2e8d1fSaliguori         memcpy(tp->data + 8, tp->vlan_header, 4);
62693e37d76SJason Wang         e1000_send_packet(s, tp->vlan, tp->size + 4);
6278f2e8d1fSaliguori     } else
62893e37d76SJason Wang         e1000_send_packet(s, tp->data, tp->size);
6297c23b892Sbalrog     s->mac_reg[TPT]++;
6307c23b892Sbalrog     s->mac_reg[GPTC]++;
6317c23b892Sbalrog     n = s->mac_reg[TOTL];
6327c23b892Sbalrog     if ((s->mac_reg[TOTL] += s->tx.size) < n)
6337c23b892Sbalrog         s->mac_reg[TOTH]++;
6347c23b892Sbalrog }
6357c23b892Sbalrog 
6367c23b892Sbalrog static void
6377c23b892Sbalrog process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
6387c23b892Sbalrog {
639b08340d5SAndreas Färber     PCIDevice *d = PCI_DEVICE(s);
6407c23b892Sbalrog     uint32_t txd_lower = le32_to_cpu(dp->lower.data);
6417c23b892Sbalrog     uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
6427c23b892Sbalrog     unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
643a0ae17a6SAndrew Jones     unsigned int msh = 0xfffff;
6447c23b892Sbalrog     uint64_t addr;
6457c23b892Sbalrog     struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
6467c23b892Sbalrog     struct e1000_tx *tp = &s->tx;
6477c23b892Sbalrog 
648e9845f09SVincenzo Maffione     s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);
6497c23b892Sbalrog     if (dtype == E1000_TXD_CMD_DEXT) {	// context descriptor
6507c23b892Sbalrog         op = le32_to_cpu(xp->cmd_and_length);
6517c23b892Sbalrog         tp->ipcss = xp->lower_setup.ip_fields.ipcss;
6527c23b892Sbalrog         tp->ipcso = xp->lower_setup.ip_fields.ipcso;
6537c23b892Sbalrog         tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);
6547c23b892Sbalrog         tp->tucss = xp->upper_setup.tcp_fields.tucss;
6557c23b892Sbalrog         tp->tucso = xp->upper_setup.tcp_fields.tucso;
6567c23b892Sbalrog         tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);
6577c23b892Sbalrog         tp->paylen = op & 0xfffff;
6587c23b892Sbalrog         tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;
6597c23b892Sbalrog         tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);
6607c23b892Sbalrog         tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
6617c23b892Sbalrog         tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
6627c23b892Sbalrog         tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
6637c23b892Sbalrog         tp->tso_frames = 0;
6647c23b892Sbalrog         if (tp->tucso == 0) {	// this is probably wrong
6657c23b892Sbalrog             DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
6667c23b892Sbalrog             tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
6677c23b892Sbalrog         }
6687c23b892Sbalrog         return;
6691b0009dbSbalrog     } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
6701b0009dbSbalrog         // data descriptor
671735e77ecSStefan Hajnoczi         if (tp->size == 0) {
6727c23b892Sbalrog             tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
673735e77ecSStefan Hajnoczi         }
6741b0009dbSbalrog         tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
67543ad7e3eSJes Sorensen     } else {
6761b0009dbSbalrog         // legacy descriptor
6771b0009dbSbalrog         tp->cptse = 0;
67843ad7e3eSJes Sorensen     }
6797c23b892Sbalrog 
6808f2e8d1fSaliguori     if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
6818f2e8d1fSaliguori         (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
6828f2e8d1fSaliguori         tp->vlan_needed = 1;
6838f2e8d1fSaliguori         cpu_to_be16wu((uint16_t *)(tp->vlan_header),
6848f2e8d1fSaliguori                       le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
6858f2e8d1fSaliguori         cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2),
6868f2e8d1fSaliguori                       le16_to_cpu(dp->upper.fields.special));
6878f2e8d1fSaliguori     }
6888f2e8d1fSaliguori 
6897c23b892Sbalrog     addr = le64_to_cpu(dp->buffer_addr);
6901b0009dbSbalrog     if (tp->tse && tp->cptse) {
691a0ae17a6SAndrew Jones         msh = tp->hdr_len + tp->mss;
6927c23b892Sbalrog         do {
6937c23b892Sbalrog             bytes = split_size;
6947c23b892Sbalrog             if (tp->size + bytes > msh)
6957c23b892Sbalrog                 bytes = msh - tp->size;
69665f82df0SAnthony Liguori 
69765f82df0SAnthony Liguori             bytes = MIN(sizeof(tp->data) - tp->size, bytes);
698b08340d5SAndreas Färber             pci_dma_read(d, addr, tp->data + tp->size, bytes);
699a0ae17a6SAndrew Jones             sz = tp->size + bytes;
700a0ae17a6SAndrew Jones             if (sz >= tp->hdr_len && tp->size < tp->hdr_len) {
701a0ae17a6SAndrew Jones                 memmove(tp->header, tp->data, tp->hdr_len);
702a0ae17a6SAndrew Jones             }
7037c23b892Sbalrog             tp->size = sz;
7047c23b892Sbalrog             addr += bytes;
7057c23b892Sbalrog             if (sz == msh) {
7067c23b892Sbalrog                 xmit_seg(s);
707a0ae17a6SAndrew Jones                 memmove(tp->data, tp->header, tp->hdr_len);
708a0ae17a6SAndrew Jones                 tp->size = tp->hdr_len;
7097c23b892Sbalrog             }
7107c23b892Sbalrog         } while (split_size -= bytes);
7111b0009dbSbalrog     } else if (!tp->tse && tp->cptse) {
7121b0009dbSbalrog         // context descriptor TSE is not set, while data descriptor TSE is set
713362f5fb5SStefan Weil         DBGOUT(TXERR, "TCP segmentation error\n");
7141b0009dbSbalrog     } else {
71565f82df0SAnthony Liguori         split_size = MIN(sizeof(tp->data) - tp->size, split_size);
716b08340d5SAndreas Färber         pci_dma_read(d, addr, tp->data + tp->size, split_size);
7171b0009dbSbalrog         tp->size += split_size;
7181b0009dbSbalrog     }
7197c23b892Sbalrog 
7207c23b892Sbalrog     if (!(txd_lower & E1000_TXD_CMD_EOP))
7217c23b892Sbalrog         return;
722a0ae17a6SAndrew Jones     if (!(tp->tse && tp->cptse && tp->size < tp->hdr_len)) {
7237c23b892Sbalrog         xmit_seg(s);
724a0ae17a6SAndrew Jones     }
7257c23b892Sbalrog     tp->tso_frames = 0;
7267c23b892Sbalrog     tp->sum_needed = 0;
7278f2e8d1fSaliguori     tp->vlan_needed = 0;
7287c23b892Sbalrog     tp->size = 0;
7291b0009dbSbalrog     tp->cptse = 0;
7307c23b892Sbalrog }
7317c23b892Sbalrog 
7327c23b892Sbalrog static uint32_t
73362ecbd35SEduard - Gabriel Munteanu txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
7347c23b892Sbalrog {
735b08340d5SAndreas Färber     PCIDevice *d = PCI_DEVICE(s);
7367c23b892Sbalrog     uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
7377c23b892Sbalrog 
7387c23b892Sbalrog     if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))
7397c23b892Sbalrog         return 0;
7407c23b892Sbalrog     txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
7417c23b892Sbalrog                 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
7427c23b892Sbalrog     dp->upper.data = cpu_to_le32(txd_upper);
743b08340d5SAndreas Färber     pci_dma_write(d, base + ((char *)&dp->upper - (char *)dp),
74400c3a05bSDavid Gibson                   &dp->upper, sizeof(dp->upper));
7457c23b892Sbalrog     return E1000_ICR_TXDW;
7467c23b892Sbalrog }
7477c23b892Sbalrog 
748d17161f6SKevin Wolf static uint64_t tx_desc_base(E1000State *s)
749d17161f6SKevin Wolf {
750d17161f6SKevin Wolf     uint64_t bah = s->mac_reg[TDBAH];
751d17161f6SKevin Wolf     uint64_t bal = s->mac_reg[TDBAL] & ~0xf;
752d17161f6SKevin Wolf 
753d17161f6SKevin Wolf     return (bah << 32) + bal;
754d17161f6SKevin Wolf }
755d17161f6SKevin Wolf 
7567c23b892Sbalrog static void
7577c23b892Sbalrog start_xmit(E1000State *s)
7587c23b892Sbalrog {
759b08340d5SAndreas Färber     PCIDevice *d = PCI_DEVICE(s);
76062ecbd35SEduard - Gabriel Munteanu     dma_addr_t base;
7617c23b892Sbalrog     struct e1000_tx_desc desc;
7627c23b892Sbalrog     uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
7637c23b892Sbalrog 
7647c23b892Sbalrog     if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) {
7657c23b892Sbalrog         DBGOUT(TX, "tx disabled\n");
7667c23b892Sbalrog         return;
7677c23b892Sbalrog     }
7687c23b892Sbalrog 
7697c23b892Sbalrog     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
770d17161f6SKevin Wolf         base = tx_desc_base(s) +
7717c23b892Sbalrog                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
772b08340d5SAndreas Färber         pci_dma_read(d, base, &desc, sizeof(desc));
7737c23b892Sbalrog 
7747c23b892Sbalrog         DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
7756106075bSths                (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
7767c23b892Sbalrog                desc.upper.data);
7777c23b892Sbalrog 
7787c23b892Sbalrog         process_tx_desc(s, &desc);
77962ecbd35SEduard - Gabriel Munteanu         cause |= txdesc_writeback(s, base, &desc);
7807c23b892Sbalrog 
7817c23b892Sbalrog         if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])
7827c23b892Sbalrog             s->mac_reg[TDH] = 0;
7837c23b892Sbalrog         /*
7847c23b892Sbalrog          * the following could happen only if guest sw assigns
7857c23b892Sbalrog          * bogus values to TDT/TDLEN.
7867c23b892Sbalrog          * there's nothing too intelligent we could do about this.
7877c23b892Sbalrog          */
7887c23b892Sbalrog         if (s->mac_reg[TDH] == tdh_start) {
7897c23b892Sbalrog             DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
7907c23b892Sbalrog                    tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
7917c23b892Sbalrog             break;
7927c23b892Sbalrog         }
7937c23b892Sbalrog     }
7947c23b892Sbalrog     set_ics(s, 0, cause);
7957c23b892Sbalrog }
7967c23b892Sbalrog 
7977c23b892Sbalrog static int
7987c23b892Sbalrog receive_filter(E1000State *s, const uint8_t *buf, int size)
7997c23b892Sbalrog {
800af2960f9SBlue Swirl     static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
801af2960f9SBlue Swirl     static const int mta_shift[] = {4, 3, 2, 0};
8027c23b892Sbalrog     uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
8037c23b892Sbalrog 
8048f2e8d1fSaliguori     if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
8058f2e8d1fSaliguori         uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14));
8068f2e8d1fSaliguori         uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) +
8078f2e8d1fSaliguori                                      ((vid >> 5) & 0x7f));
8088f2e8d1fSaliguori         if ((vfta & (1 << (vid & 0x1f))) == 0)
8098f2e8d1fSaliguori             return 0;
8108f2e8d1fSaliguori     }
8118f2e8d1fSaliguori 
8127c23b892Sbalrog     if (rctl & E1000_RCTL_UPE)			// promiscuous
8137c23b892Sbalrog         return 1;
8147c23b892Sbalrog 
8157c23b892Sbalrog     if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE))	// promiscuous mcast
8167c23b892Sbalrog         return 1;
8177c23b892Sbalrog 
8187c23b892Sbalrog     if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast))
8197c23b892Sbalrog         return 1;
8207c23b892Sbalrog 
8217c23b892Sbalrog     for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {
8227c23b892Sbalrog         if (!(rp[1] & E1000_RAH_AV))
8237c23b892Sbalrog             continue;
8247c23b892Sbalrog         ra[0] = cpu_to_le32(rp[0]);
8257c23b892Sbalrog         ra[1] = cpu_to_le32(rp[1]);
8267c23b892Sbalrog         if (!memcmp(buf, (uint8_t *)ra, 6)) {
8277c23b892Sbalrog             DBGOUT(RXFILTER,
8287c23b892Sbalrog                    "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
8297c23b892Sbalrog                    (int)(rp - s->mac_reg - RA)/2,
8307c23b892Sbalrog                    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
8317c23b892Sbalrog             return 1;
8327c23b892Sbalrog         }
8337c23b892Sbalrog     }
8347c23b892Sbalrog     DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",
8357c23b892Sbalrog            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
8367c23b892Sbalrog 
8377c23b892Sbalrog     f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
8387c23b892Sbalrog     f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
8397c23b892Sbalrog     if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f)))
8407c23b892Sbalrog         return 1;
8417c23b892Sbalrog     DBGOUT(RXFILTER,
8427c23b892Sbalrog            "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",
8437c23b892Sbalrog            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
8447c23b892Sbalrog            (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,
8457c23b892Sbalrog            s->mac_reg[MTA + (f >> 5)]);
8467c23b892Sbalrog 
8477c23b892Sbalrog     return 0;
8487c23b892Sbalrog }
8497c23b892Sbalrog 
85099ed7e30Saliguori static void
8514e68f7a0SStefan Hajnoczi e1000_set_link_status(NetClientState *nc)
85299ed7e30Saliguori {
853cc1f0f45SJason Wang     E1000State *s = qemu_get_nic_opaque(nc);
85499ed7e30Saliguori     uint32_t old_status = s->mac_reg[STATUS];
85599ed7e30Saliguori 
856d4044c2aSBjørn Mork     if (nc->link_down) {
85771aadd3cSJason Wang         e1000_link_down(s);
858d4044c2aSBjørn Mork     } else {
85971aadd3cSJason Wang         e1000_link_up(s);
860d4044c2aSBjørn Mork     }
86199ed7e30Saliguori 
86299ed7e30Saliguori     if (s->mac_reg[STATUS] != old_status)
86399ed7e30Saliguori         set_ics(s, 0, E1000_ICR_LSC);
86499ed7e30Saliguori }
86599ed7e30Saliguori 
866322fd48aSMichael S. Tsirkin static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
867322fd48aSMichael S. Tsirkin {
868322fd48aSMichael S. Tsirkin     int bufs;
869322fd48aSMichael S. Tsirkin     /* Fast-path short packets */
870322fd48aSMichael S. Tsirkin     if (total_size <= s->rxbuf_size) {
871e5b8b0d4SDmitry Fleytman         return s->mac_reg[RDH] != s->mac_reg[RDT];
872322fd48aSMichael S. Tsirkin     }
873322fd48aSMichael S. Tsirkin     if (s->mac_reg[RDH] < s->mac_reg[RDT]) {
874322fd48aSMichael S. Tsirkin         bufs = s->mac_reg[RDT] - s->mac_reg[RDH];
875e5b8b0d4SDmitry Fleytman     } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) {
876322fd48aSMichael S. Tsirkin         bufs = s->mac_reg[RDLEN] /  sizeof(struct e1000_rx_desc) +
877322fd48aSMichael S. Tsirkin             s->mac_reg[RDT] - s->mac_reg[RDH];
878322fd48aSMichael S. Tsirkin     } else {
879322fd48aSMichael S. Tsirkin         return false;
880322fd48aSMichael S. Tsirkin     }
881322fd48aSMichael S. Tsirkin     return total_size <= bufs * s->rxbuf_size;
882322fd48aSMichael S. Tsirkin }
883322fd48aSMichael S. Tsirkin 
8846cdfab28SMichael S. Tsirkin static int
8854e68f7a0SStefan Hajnoczi e1000_can_receive(NetClientState *nc)
8866cdfab28SMichael S. Tsirkin {
887cc1f0f45SJason Wang     E1000State *s = qemu_get_nic_opaque(nc);
8886cdfab28SMichael S. Tsirkin 
889ddcb73b7SMichael S. Tsirkin     return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
890ddcb73b7SMichael S. Tsirkin         (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
8916cdfab28SMichael S. Tsirkin }
8926cdfab28SMichael S. Tsirkin 
893d17161f6SKevin Wolf static uint64_t rx_desc_base(E1000State *s)
894d17161f6SKevin Wolf {
895d17161f6SKevin Wolf     uint64_t bah = s->mac_reg[RDBAH];
896d17161f6SKevin Wolf     uint64_t bal = s->mac_reg[RDBAL] & ~0xf;
897d17161f6SKevin Wolf 
898d17161f6SKevin Wolf     return (bah << 32) + bal;
899d17161f6SKevin Wolf }
900d17161f6SKevin Wolf 
9014f1c942bSMark McLoughlin static ssize_t
9024e68f7a0SStefan Hajnoczi e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
9037c23b892Sbalrog {
904cc1f0f45SJason Wang     E1000State *s = qemu_get_nic_opaque(nc);
905b08340d5SAndreas Färber     PCIDevice *d = PCI_DEVICE(s);
9067c23b892Sbalrog     struct e1000_rx_desc desc;
90762ecbd35SEduard - Gabriel Munteanu     dma_addr_t base;
9087c23b892Sbalrog     unsigned int n, rdt;
9097c23b892Sbalrog     uint32_t rdh_start;
9108f2e8d1fSaliguori     uint16_t vlan_special = 0;
9118f2e8d1fSaliguori     uint8_t vlan_status = 0, vlan_offset = 0;
91278aeb23eSStefan Hajnoczi     uint8_t min_buf[MIN_BUF_SIZE];
913b19487e2SMichael S. Tsirkin     size_t desc_offset;
914b19487e2SMichael S. Tsirkin     size_t desc_size;
915b19487e2SMichael S. Tsirkin     size_t total_size;
9167c23b892Sbalrog 
917ddcb73b7SMichael S. Tsirkin     if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) {
9184f1c942bSMark McLoughlin         return -1;
919ddcb73b7SMichael S. Tsirkin     }
920ddcb73b7SMichael S. Tsirkin 
921ddcb73b7SMichael S. Tsirkin     if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) {
922ddcb73b7SMichael S. Tsirkin         return -1;
923ddcb73b7SMichael S. Tsirkin     }
9247c23b892Sbalrog 
92578aeb23eSStefan Hajnoczi     /* Pad to minimum Ethernet frame length */
92678aeb23eSStefan Hajnoczi     if (size < sizeof(min_buf)) {
92778aeb23eSStefan Hajnoczi         memcpy(min_buf, buf, size);
92878aeb23eSStefan Hajnoczi         memset(&min_buf[size], 0, sizeof(min_buf) - size);
92978aeb23eSStefan Hajnoczi         buf = min_buf;
93078aeb23eSStefan Hajnoczi         size = sizeof(min_buf);
93178aeb23eSStefan Hajnoczi     }
93278aeb23eSStefan Hajnoczi 
933b0d9ffcdSMichael Contreras     /* Discard oversized packets if !LPE and !SBP. */
9342c0331f4SMichael Contreras     if ((size > MAXIMUM_ETHERNET_LPE_SIZE ||
9352c0331f4SMichael Contreras         (size > MAXIMUM_ETHERNET_VLAN_SIZE
9362c0331f4SMichael Contreras         && !(s->mac_reg[RCTL] & E1000_RCTL_LPE)))
937b0d9ffcdSMichael Contreras         && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) {
938b0d9ffcdSMichael Contreras         return size;
939b0d9ffcdSMichael Contreras     }
940b0d9ffcdSMichael Contreras 
9417c23b892Sbalrog     if (!receive_filter(s, buf, size))
9424f1c942bSMark McLoughlin         return size;
9437c23b892Sbalrog 
9448f2e8d1fSaliguori     if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
9458f2e8d1fSaliguori         vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
94698835fe3SThomas Monjalon         memmove((uint8_t *)buf + 4, buf, 12);
9478f2e8d1fSaliguori         vlan_status = E1000_RXD_STAT_VP;
9488f2e8d1fSaliguori         vlan_offset = 4;
9498f2e8d1fSaliguori         size -= 4;
9508f2e8d1fSaliguori     }
9518f2e8d1fSaliguori 
9527c23b892Sbalrog     rdh_start = s->mac_reg[RDH];
953b19487e2SMichael S. Tsirkin     desc_offset = 0;
954b19487e2SMichael S. Tsirkin     total_size = size + fcs_len(s);
955322fd48aSMichael S. Tsirkin     if (!e1000_has_rxbufs(s, total_size)) {
956322fd48aSMichael S. Tsirkin             set_ics(s, 0, E1000_ICS_RXO);
957322fd48aSMichael S. Tsirkin             return -1;
958322fd48aSMichael S. Tsirkin     }
9597c23b892Sbalrog     do {
960b19487e2SMichael S. Tsirkin         desc_size = total_size - desc_offset;
961b19487e2SMichael S. Tsirkin         if (desc_size > s->rxbuf_size) {
962b19487e2SMichael S. Tsirkin             desc_size = s->rxbuf_size;
963b19487e2SMichael S. Tsirkin         }
964d17161f6SKevin Wolf         base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
965b08340d5SAndreas Färber         pci_dma_read(d, base, &desc, sizeof(desc));
9668f2e8d1fSaliguori         desc.special = vlan_special;
9678f2e8d1fSaliguori         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
9687c23b892Sbalrog         if (desc.buffer_addr) {
969b19487e2SMichael S. Tsirkin             if (desc_offset < size) {
970b19487e2SMichael S. Tsirkin                 size_t copy_size = size - desc_offset;
971b19487e2SMichael S. Tsirkin                 if (copy_size > s->rxbuf_size) {
972b19487e2SMichael S. Tsirkin                     copy_size = s->rxbuf_size;
973b19487e2SMichael S. Tsirkin                 }
974b08340d5SAndreas Färber                 pci_dma_write(d, le64_to_cpu(desc.buffer_addr),
97500c3a05bSDavid Gibson                               buf + desc_offset + vlan_offset, copy_size);
976b19487e2SMichael S. Tsirkin             }
977b19487e2SMichael S. Tsirkin             desc_offset += desc_size;
978b19487e2SMichael S. Tsirkin             desc.length = cpu_to_le16(desc_size);
979ee912ccfSMichael S. Tsirkin             if (desc_offset >= total_size) {
9807c23b892Sbalrog                 desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM;
981b19487e2SMichael S. Tsirkin             } else {
982ee912ccfSMichael S. Tsirkin                 /* Guest zeroing out status is not a hardware requirement.
983ee912ccfSMichael S. Tsirkin                    Clear EOP in case guest didn't do it. */
984ee912ccfSMichael S. Tsirkin                 desc.status &= ~E1000_RXD_STAT_EOP;
985b19487e2SMichael S. Tsirkin             }
98643ad7e3eSJes Sorensen         } else { // as per intel docs; skip descriptors with null buf addr
9877c23b892Sbalrog             DBGOUT(RX, "Null RX descriptor!!\n");
98843ad7e3eSJes Sorensen         }
989b08340d5SAndreas Färber         pci_dma_write(d, base, &desc, sizeof(desc));
9907c23b892Sbalrog 
9917c23b892Sbalrog         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
9927c23b892Sbalrog             s->mac_reg[RDH] = 0;
9937c23b892Sbalrog         /* see comment in start_xmit; same here */
9947c23b892Sbalrog         if (s->mac_reg[RDH] == rdh_start) {
9957c23b892Sbalrog             DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
9967c23b892Sbalrog                    rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
9977c23b892Sbalrog             set_ics(s, 0, E1000_ICS_RXO);
9984f1c942bSMark McLoughlin             return -1;
9997c23b892Sbalrog         }
1000b19487e2SMichael S. Tsirkin     } while (desc_offset < total_size);
10017c23b892Sbalrog 
10027c23b892Sbalrog     s->mac_reg[GPRC]++;
10037c23b892Sbalrog     s->mac_reg[TPR]++;
1004a05e8a6eSMichael S. Tsirkin     /* TOR - Total Octets Received:
1005a05e8a6eSMichael S. Tsirkin      * This register includes bytes received in a packet from the <Destination
1006a05e8a6eSMichael S. Tsirkin      * Address> field through the <CRC> field, inclusively.
1007a05e8a6eSMichael S. Tsirkin      */
1008a05e8a6eSMichael S. Tsirkin     n = s->mac_reg[TORL] + size + /* Always include FCS length. */ 4;
1009a05e8a6eSMichael S. Tsirkin     if (n < s->mac_reg[TORL])
10107c23b892Sbalrog         s->mac_reg[TORH]++;
1011a05e8a6eSMichael S. Tsirkin     s->mac_reg[TORL] = n;
10127c23b892Sbalrog 
10137c23b892Sbalrog     n = E1000_ICS_RXT0;
10147c23b892Sbalrog     if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
10157c23b892Sbalrog         rdt += s->mac_reg[RDLEN] / sizeof(desc);
1016bf16cc8fSaliguori     if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
1017bf16cc8fSaliguori         s->rxbuf_min_shift)
10187c23b892Sbalrog         n |= E1000_ICS_RXDMT0;
10197c23b892Sbalrog 
10207c23b892Sbalrog     set_ics(s, 0, n);
10214f1c942bSMark McLoughlin 
10224f1c942bSMark McLoughlin     return size;
10237c23b892Sbalrog }
10247c23b892Sbalrog 
10257c23b892Sbalrog static uint32_t
10267c23b892Sbalrog mac_readreg(E1000State *s, int index)
10277c23b892Sbalrog {
10287c23b892Sbalrog     return s->mac_reg[index];
10297c23b892Sbalrog }
10307c23b892Sbalrog 
10317c23b892Sbalrog static uint32_t
10327c23b892Sbalrog mac_icr_read(E1000State *s, int index)
10337c23b892Sbalrog {
10347c23b892Sbalrog     uint32_t ret = s->mac_reg[ICR];
10357c23b892Sbalrog 
10367c23b892Sbalrog     DBGOUT(INTERRUPT, "ICR read: %x\n", ret);
10377c23b892Sbalrog     set_interrupt_cause(s, 0, 0);
10387c23b892Sbalrog     return ret;
10397c23b892Sbalrog }
10407c23b892Sbalrog 
10417c23b892Sbalrog static uint32_t
10427c23b892Sbalrog mac_read_clr4(E1000State *s, int index)
10437c23b892Sbalrog {
10447c23b892Sbalrog     uint32_t ret = s->mac_reg[index];
10457c23b892Sbalrog 
10467c23b892Sbalrog     s->mac_reg[index] = 0;
10477c23b892Sbalrog     return ret;
10487c23b892Sbalrog }
10497c23b892Sbalrog 
10507c23b892Sbalrog static uint32_t
10517c23b892Sbalrog mac_read_clr8(E1000State *s, int index)
10527c23b892Sbalrog {
10537c23b892Sbalrog     uint32_t ret = s->mac_reg[index];
10547c23b892Sbalrog 
10557c23b892Sbalrog     s->mac_reg[index] = 0;
10567c23b892Sbalrog     s->mac_reg[index-1] = 0;
10577c23b892Sbalrog     return ret;
10587c23b892Sbalrog }
10597c23b892Sbalrog 
10607c23b892Sbalrog static void
10617c23b892Sbalrog mac_writereg(E1000State *s, int index, uint32_t val)
10627c23b892Sbalrog {
10637c23b892Sbalrog     s->mac_reg[index] = val;
10647c23b892Sbalrog }
10657c23b892Sbalrog 
10667c23b892Sbalrog static void
10677c23b892Sbalrog set_rdt(E1000State *s, int index, uint32_t val)
10687c23b892Sbalrog {
10697c23b892Sbalrog     s->mac_reg[index] = val & 0xffff;
1070e8b4c680SPaolo Bonzini     if (e1000_has_rxbufs(s, 1)) {
1071b356f76dSJason Wang         qemu_flush_queued_packets(qemu_get_queue(s->nic));
1072e8b4c680SPaolo Bonzini     }
10737c23b892Sbalrog }
10747c23b892Sbalrog 
10757c23b892Sbalrog static void
10767c23b892Sbalrog set_16bit(E1000State *s, int index, uint32_t val)
10777c23b892Sbalrog {
10787c23b892Sbalrog     s->mac_reg[index] = val & 0xffff;
10797c23b892Sbalrog }
10807c23b892Sbalrog 
10817c23b892Sbalrog static void
10827c23b892Sbalrog set_dlen(E1000State *s, int index, uint32_t val)
10837c23b892Sbalrog {
10847c23b892Sbalrog     s->mac_reg[index] = val & 0xfff80;
10857c23b892Sbalrog }
10867c23b892Sbalrog 
10877c23b892Sbalrog static void
10887c23b892Sbalrog set_tctl(E1000State *s, int index, uint32_t val)
10897c23b892Sbalrog {
10907c23b892Sbalrog     s->mac_reg[index] = val;
10917c23b892Sbalrog     s->mac_reg[TDT] &= 0xffff;
10927c23b892Sbalrog     start_xmit(s);
10937c23b892Sbalrog }
10947c23b892Sbalrog 
10957c23b892Sbalrog static void
10967c23b892Sbalrog set_icr(E1000State *s, int index, uint32_t val)
10977c23b892Sbalrog {
10987c23b892Sbalrog     DBGOUT(INTERRUPT, "set_icr %x\n", val);
10997c23b892Sbalrog     set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val);
11007c23b892Sbalrog }
11017c23b892Sbalrog 
11027c23b892Sbalrog static void
11037c23b892Sbalrog set_imc(E1000State *s, int index, uint32_t val)
11047c23b892Sbalrog {
11057c23b892Sbalrog     s->mac_reg[IMS] &= ~val;
11067c23b892Sbalrog     set_ics(s, 0, 0);
11077c23b892Sbalrog }
11087c23b892Sbalrog 
11097c23b892Sbalrog static void
11107c23b892Sbalrog set_ims(E1000State *s, int index, uint32_t val)
11117c23b892Sbalrog {
11127c23b892Sbalrog     s->mac_reg[IMS] |= val;
11137c23b892Sbalrog     set_ics(s, 0, 0);
11147c23b892Sbalrog }
11157c23b892Sbalrog 
11167c23b892Sbalrog #define getreg(x)	[x] = mac_readreg
11177c23b892Sbalrog static uint32_t (*macreg_readops[])(E1000State *, int) = {
11187c23b892Sbalrog     getreg(PBA),	getreg(RCTL),	getreg(TDH),	getreg(TXDCTL),
11197c23b892Sbalrog     getreg(WUFC),	getreg(TDT),	getreg(CTRL),	getreg(LEDCTL),
11207c23b892Sbalrog     getreg(MANC),	getreg(MDIC),	getreg(SWSM),	getreg(STATUS),
11217c23b892Sbalrog     getreg(TORL),	getreg(TOTL),	getreg(IMS),	getreg(TCTL),
1122b1332393SBill Paul     getreg(RDH),	getreg(RDT),	getreg(VET),	getreg(ICS),
1123a00b2335SKay Ackermann     getreg(TDBAL),	getreg(TDBAH),	getreg(RDBAH),	getreg(RDBAL),
1124e9845f09SVincenzo Maffione     getreg(TDLEN),      getreg(RDLEN),  getreg(RDTR),   getreg(RADV),
1125e9845f09SVincenzo Maffione     getreg(TADV),       getreg(ITR),
11267c23b892Sbalrog 
11277c23b892Sbalrog     [TOTH] = mac_read_clr8,	[TORH] = mac_read_clr8,	[GPRC] = mac_read_clr4,
11287c23b892Sbalrog     [GPTC] = mac_read_clr4,	[TPR] = mac_read_clr4,	[TPT] = mac_read_clr4,
11297c23b892Sbalrog     [ICR] = mac_icr_read,	[EECD] = get_eecd,	[EERD] = flash_eerd_read,
11307c23b892Sbalrog     [CRCERRS ... MPC] = &mac_readreg,
11317c23b892Sbalrog     [RA ... RA+31] = &mac_readreg,
11327c23b892Sbalrog     [MTA ... MTA+127] = &mac_readreg,
11338f2e8d1fSaliguori     [VFTA ... VFTA+127] = &mac_readreg,
11347c23b892Sbalrog };
1135b1503cdaSmalc enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
11367c23b892Sbalrog 
11377c23b892Sbalrog #define putreg(x)	[x] = mac_writereg
11387c23b892Sbalrog static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
11397c23b892Sbalrog     putreg(PBA),	putreg(EERD),	putreg(SWSM),	putreg(WUFC),
11407c23b892Sbalrog     putreg(TDBAL),	putreg(TDBAH),	putreg(TXDCTL),	putreg(RDBAH),
1141cab3c825SKevin Wolf     putreg(RDBAL),	putreg(LEDCTL), putreg(VET),
11427c23b892Sbalrog     [TDLEN] = set_dlen,	[RDLEN] = set_dlen,	[TCTL] = set_tctl,
11437c23b892Sbalrog     [TDT] = set_tctl,	[MDIC] = set_mdic,	[ICS] = set_ics,
11447c23b892Sbalrog     [TDH] = set_16bit,	[RDH] = set_16bit,	[RDT] = set_rdt,
11457c23b892Sbalrog     [IMC] = set_imc,	[IMS] = set_ims,	[ICR] = set_icr,
1146cab3c825SKevin Wolf     [EECD] = set_eecd,	[RCTL] = set_rx_control, [CTRL] = set_ctrl,
1147e9845f09SVincenzo Maffione     [RDTR] = set_16bit, [RADV] = set_16bit,     [TADV] = set_16bit,
1148e9845f09SVincenzo Maffione     [ITR] = set_16bit,
11497c23b892Sbalrog     [RA ... RA+31] = &mac_writereg,
11507c23b892Sbalrog     [MTA ... MTA+127] = &mac_writereg,
11518f2e8d1fSaliguori     [VFTA ... VFTA+127] = &mac_writereg,
11527c23b892Sbalrog };
1153b9d03e35SJason Wang 
1154b1503cdaSmalc enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
11557c23b892Sbalrog 
11567c23b892Sbalrog static void
1157a8170e5eSAvi Kivity e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val,
1158ad00a9b9SAvi Kivity                  unsigned size)
11597c23b892Sbalrog {
11607c23b892Sbalrog     E1000State *s = opaque;
11618da3ff18Spbrook     unsigned int index = (addr & 0x1ffff) >> 2;
11627c23b892Sbalrog 
116343ad7e3eSJes Sorensen     if (index < NWRITEOPS && macreg_writeops[index]) {
11646b59fc74Saurel32         macreg_writeops[index](s, index, val);
116543ad7e3eSJes Sorensen     } else if (index < NREADOPS && macreg_readops[index]) {
1166ad00a9b9SAvi Kivity         DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val);
116743ad7e3eSJes Sorensen     } else {
1168ad00a9b9SAvi Kivity         DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n",
11697c23b892Sbalrog                index<<2, val);
11707c23b892Sbalrog     }
117143ad7e3eSJes Sorensen }
11727c23b892Sbalrog 
1173ad00a9b9SAvi Kivity static uint64_t
1174a8170e5eSAvi Kivity e1000_mmio_read(void *opaque, hwaddr addr, unsigned size)
11757c23b892Sbalrog {
11767c23b892Sbalrog     E1000State *s = opaque;
11778da3ff18Spbrook     unsigned int index = (addr & 0x1ffff) >> 2;
11787c23b892Sbalrog 
11797c23b892Sbalrog     if (index < NREADOPS && macreg_readops[index])
11806b59fc74Saurel32     {
118132600a30SAlexander Graf         return macreg_readops[index](s, index);
11826b59fc74Saurel32     }
11837c23b892Sbalrog     DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2);
11847c23b892Sbalrog     return 0;
11857c23b892Sbalrog }
11867c23b892Sbalrog 
1187ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_mmio_ops = {
1188ad00a9b9SAvi Kivity     .read = e1000_mmio_read,
1189ad00a9b9SAvi Kivity     .write = e1000_mmio_write,
1190ad00a9b9SAvi Kivity     .endianness = DEVICE_LITTLE_ENDIAN,
1191ad00a9b9SAvi Kivity     .impl = {
1192ad00a9b9SAvi Kivity         .min_access_size = 4,
1193ad00a9b9SAvi Kivity         .max_access_size = 4,
1194ad00a9b9SAvi Kivity     },
1195ad00a9b9SAvi Kivity };
1196ad00a9b9SAvi Kivity 
1197a8170e5eSAvi Kivity static uint64_t e1000_io_read(void *opaque, hwaddr addr,
1198ad00a9b9SAvi Kivity                               unsigned size)
11997c23b892Sbalrog {
1200ad00a9b9SAvi Kivity     E1000State *s = opaque;
1201ad00a9b9SAvi Kivity 
1202ad00a9b9SAvi Kivity     (void)s;
1203ad00a9b9SAvi Kivity     return 0;
12047c23b892Sbalrog }
12057c23b892Sbalrog 
1206a8170e5eSAvi Kivity static void e1000_io_write(void *opaque, hwaddr addr,
1207ad00a9b9SAvi Kivity                            uint64_t val, unsigned size)
12087c23b892Sbalrog {
1209ad00a9b9SAvi Kivity     E1000State *s = opaque;
1210ad00a9b9SAvi Kivity 
1211ad00a9b9SAvi Kivity     (void)s;
12127c23b892Sbalrog }
12137c23b892Sbalrog 
1214ad00a9b9SAvi Kivity static const MemoryRegionOps e1000_io_ops = {
1215ad00a9b9SAvi Kivity     .read = e1000_io_read,
1216ad00a9b9SAvi Kivity     .write = e1000_io_write,
1217ad00a9b9SAvi Kivity     .endianness = DEVICE_LITTLE_ENDIAN,
1218ad00a9b9SAvi Kivity };
1219ad00a9b9SAvi Kivity 
1220e482dc3eSJuan Quintela static bool is_version_1(void *opaque, int version_id)
12217c23b892Sbalrog {
1222e482dc3eSJuan Quintela     return version_id == 1;
12237c23b892Sbalrog }
12247c23b892Sbalrog 
1225ddcb73b7SMichael S. Tsirkin static void e1000_pre_save(void *opaque)
1226ddcb73b7SMichael S. Tsirkin {
1227ddcb73b7SMichael S. Tsirkin     E1000State *s = opaque;
1228ddcb73b7SMichael S. Tsirkin     NetClientState *nc = qemu_get_queue(s->nic);
12292af234e6SMichael S. Tsirkin 
1230e9845f09SVincenzo Maffione     /* If the mitigation timer is active, emulate a timeout now. */
1231e9845f09SVincenzo Maffione     if (s->mit_timer_on) {
1232e9845f09SVincenzo Maffione         e1000_mit_timer(s);
1233e9845f09SVincenzo Maffione     }
1234e9845f09SVincenzo Maffione 
12352af234e6SMichael S. Tsirkin     if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
12362af234e6SMichael S. Tsirkin         return;
12372af234e6SMichael S. Tsirkin     }
12382af234e6SMichael S. Tsirkin 
1239ddcb73b7SMichael S. Tsirkin     /*
1240ddcb73b7SMichael S. Tsirkin      * If link is down and auto-negotiation is ongoing, complete
1241ddcb73b7SMichael S. Tsirkin      * auto-negotiation immediately.  This allows is to look at
1242ddcb73b7SMichael S. Tsirkin      * MII_SR_AUTONEG_COMPLETE to infer link status on load.
1243ddcb73b7SMichael S. Tsirkin      */
1244ddcb73b7SMichael S. Tsirkin     if (nc->link_down &&
1245ddcb73b7SMichael S. Tsirkin         s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
1246ddcb73b7SMichael S. Tsirkin         s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) {
1247ddcb73b7SMichael S. Tsirkin          s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
1248ddcb73b7SMichael S. Tsirkin     }
1249ddcb73b7SMichael S. Tsirkin }
1250ddcb73b7SMichael S. Tsirkin 
1251e4b82364SAmos Kong static int e1000_post_load(void *opaque, int version_id)
1252e4b82364SAmos Kong {
1253e4b82364SAmos Kong     E1000State *s = opaque;
1254b356f76dSJason Wang     NetClientState *nc = qemu_get_queue(s->nic);
1255e4b82364SAmos Kong 
1256e9845f09SVincenzo Maffione     if (!(s->compat_flags & E1000_FLAG_MIT)) {
1257e9845f09SVincenzo Maffione         s->mac_reg[ITR] = s->mac_reg[RDTR] = s->mac_reg[RADV] =
1258e9845f09SVincenzo Maffione             s->mac_reg[TADV] = 0;
1259e9845f09SVincenzo Maffione         s->mit_irq_level = false;
1260e9845f09SVincenzo Maffione     }
1261e9845f09SVincenzo Maffione     s->mit_ide = 0;
1262e9845f09SVincenzo Maffione     s->mit_timer_on = false;
1263e9845f09SVincenzo Maffione 
1264e4b82364SAmos Kong     /* nc.link_down can't be migrated, so infer link_down according
1265ddcb73b7SMichael S. Tsirkin      * to link status bit in mac_reg[STATUS].
1266ddcb73b7SMichael S. Tsirkin      * Alternatively, restart link negotiation if it was in progress. */
1267b356f76dSJason Wang     nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
12682af234e6SMichael S. Tsirkin 
12692af234e6SMichael S. Tsirkin     if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
12702af234e6SMichael S. Tsirkin         return 0;
12712af234e6SMichael S. Tsirkin     }
12722af234e6SMichael S. Tsirkin 
1273ddcb73b7SMichael S. Tsirkin     if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
1274ddcb73b7SMichael S. Tsirkin         s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
1275ddcb73b7SMichael S. Tsirkin         !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
1276ddcb73b7SMichael S. Tsirkin         nc->link_down = false;
1277bc72ad67SAlex Bligh         timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
1278ddcb73b7SMichael S. Tsirkin     }
1279e4b82364SAmos Kong 
1280e4b82364SAmos Kong     return 0;
1281e4b82364SAmos Kong }
1282e4b82364SAmos Kong 
1283e9845f09SVincenzo Maffione static bool e1000_mit_state_needed(void *opaque)
1284e9845f09SVincenzo Maffione {
1285e9845f09SVincenzo Maffione     E1000State *s = opaque;
1286e9845f09SVincenzo Maffione 
1287e9845f09SVincenzo Maffione     return s->compat_flags & E1000_FLAG_MIT;
1288e9845f09SVincenzo Maffione }
1289e9845f09SVincenzo Maffione 
1290e9845f09SVincenzo Maffione static const VMStateDescription vmstate_e1000_mit_state = {
1291e9845f09SVincenzo Maffione     .name = "e1000/mit_state",
1292e9845f09SVincenzo Maffione     .version_id = 1,
1293e9845f09SVincenzo Maffione     .minimum_version_id = 1,
1294e9845f09SVincenzo Maffione     .minimum_version_id_old = 1,
1295e9845f09SVincenzo Maffione     .fields    = (VMStateField[]) {
1296e9845f09SVincenzo Maffione         VMSTATE_UINT32(mac_reg[RDTR], E1000State),
1297e9845f09SVincenzo Maffione         VMSTATE_UINT32(mac_reg[RADV], E1000State),
1298e9845f09SVincenzo Maffione         VMSTATE_UINT32(mac_reg[TADV], E1000State),
1299e9845f09SVincenzo Maffione         VMSTATE_UINT32(mac_reg[ITR], E1000State),
1300e9845f09SVincenzo Maffione         VMSTATE_BOOL(mit_irq_level, E1000State),
1301e9845f09SVincenzo Maffione         VMSTATE_END_OF_LIST()
1302e9845f09SVincenzo Maffione     }
1303e9845f09SVincenzo Maffione };
1304e9845f09SVincenzo Maffione 
1305e482dc3eSJuan Quintela static const VMStateDescription vmstate_e1000 = {
1306e482dc3eSJuan Quintela     .name = "e1000",
1307e482dc3eSJuan Quintela     .version_id = 2,
1308e482dc3eSJuan Quintela     .minimum_version_id = 1,
1309e482dc3eSJuan Quintela     .minimum_version_id_old = 1,
1310ddcb73b7SMichael S. Tsirkin     .pre_save = e1000_pre_save,
1311e4b82364SAmos Kong     .post_load = e1000_post_load,
1312e482dc3eSJuan Quintela     .fields      = (VMStateField []) {
1313b08340d5SAndreas Färber         VMSTATE_PCI_DEVICE(parent_obj, E1000State),
1314e482dc3eSJuan Quintela         VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */
1315e482dc3eSJuan Quintela         VMSTATE_UNUSED(4), /* Was mmio_base.  */
1316e482dc3eSJuan Quintela         VMSTATE_UINT32(rxbuf_size, E1000State),
1317e482dc3eSJuan Quintela         VMSTATE_UINT32(rxbuf_min_shift, E1000State),
1318e482dc3eSJuan Quintela         VMSTATE_UINT32(eecd_state.val_in, E1000State),
1319e482dc3eSJuan Quintela         VMSTATE_UINT16(eecd_state.bitnum_in, E1000State),
1320e482dc3eSJuan Quintela         VMSTATE_UINT16(eecd_state.bitnum_out, E1000State),
1321e482dc3eSJuan Quintela         VMSTATE_UINT16(eecd_state.reading, E1000State),
1322e482dc3eSJuan Quintela         VMSTATE_UINT32(eecd_state.old_eecd, E1000State),
1323e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.ipcss, E1000State),
1324e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.ipcso, E1000State),
1325e482dc3eSJuan Quintela         VMSTATE_UINT16(tx.ipcse, E1000State),
1326e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.tucss, E1000State),
1327e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.tucso, E1000State),
1328e482dc3eSJuan Quintela         VMSTATE_UINT16(tx.tucse, E1000State),
1329e482dc3eSJuan Quintela         VMSTATE_UINT32(tx.paylen, E1000State),
1330e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.hdr_len, E1000State),
1331e482dc3eSJuan Quintela         VMSTATE_UINT16(tx.mss, E1000State),
1332e482dc3eSJuan Quintela         VMSTATE_UINT16(tx.size, E1000State),
1333e482dc3eSJuan Quintela         VMSTATE_UINT16(tx.tso_frames, E1000State),
1334e482dc3eSJuan Quintela         VMSTATE_UINT8(tx.sum_needed, E1000State),
1335e482dc3eSJuan Quintela         VMSTATE_INT8(tx.ip, E1000State),
1336e482dc3eSJuan Quintela         VMSTATE_INT8(tx.tcp, E1000State),
1337e482dc3eSJuan Quintela         VMSTATE_BUFFER(tx.header, E1000State),
1338e482dc3eSJuan Quintela         VMSTATE_BUFFER(tx.data, E1000State),
1339e482dc3eSJuan Quintela         VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64),
1340e482dc3eSJuan Quintela         VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20),
1341e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[CTRL], E1000State),
1342e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[EECD], E1000State),
1343e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[EERD], E1000State),
1344e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[GPRC], E1000State),
1345e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[GPTC], E1000State),
1346e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[ICR], E1000State),
1347e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[ICS], E1000State),
1348e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[IMC], E1000State),
1349e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[IMS], E1000State),
1350e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[LEDCTL], E1000State),
1351e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[MANC], E1000State),
1352e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[MDIC], E1000State),
1353e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[MPC], E1000State),
1354e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[PBA], E1000State),
1355e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RCTL], E1000State),
1356e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RDBAH], E1000State),
1357e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RDBAL], E1000State),
1358e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RDH], E1000State),
1359e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RDLEN], E1000State),
1360e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[RDT], E1000State),
1361e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[STATUS], E1000State),
1362e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[SWSM], E1000State),
1363e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TCTL], E1000State),
1364e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TDBAH], E1000State),
1365e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TDBAL], E1000State),
1366e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TDH], E1000State),
1367e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TDLEN], E1000State),
1368e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TDT], E1000State),
1369e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TORH], E1000State),
1370e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TORL], E1000State),
1371e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TOTH], E1000State),
1372e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TOTL], E1000State),
1373e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TPR], E1000State),
1374e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TPT], E1000State),
1375e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[TXDCTL], E1000State),
1376e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[WUFC], E1000State),
1377e482dc3eSJuan Quintela         VMSTATE_UINT32(mac_reg[VET], E1000State),
1378e482dc3eSJuan Quintela         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
1379e482dc3eSJuan Quintela         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
1380e482dc3eSJuan Quintela         VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
1381e482dc3eSJuan Quintela         VMSTATE_END_OF_LIST()
1382e9845f09SVincenzo Maffione     },
1383e9845f09SVincenzo Maffione     .subsections = (VMStateSubsection[]) {
1384e9845f09SVincenzo Maffione         {
1385e9845f09SVincenzo Maffione             .vmsd = &vmstate_e1000_mit_state,
1386e9845f09SVincenzo Maffione             .needed = e1000_mit_state_needed,
1387e9845f09SVincenzo Maffione         }, {
1388e9845f09SVincenzo Maffione             /* empty */
1389e9845f09SVincenzo Maffione         }
13907c23b892Sbalrog     }
1391e482dc3eSJuan Quintela };
13927c23b892Sbalrog 
139388b4e9dbSblueswir1 static const uint16_t e1000_eeprom_template[64] = {
13947c23b892Sbalrog     0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
13957c23b892Sbalrog     0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
13967c23b892Sbalrog     0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
13977c23b892Sbalrog     0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
13987c23b892Sbalrog     0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
13997c23b892Sbalrog     0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
14007c23b892Sbalrog     0x0100, 0x4000, 0x121c, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
14017c23b892Sbalrog     0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
14027c23b892Sbalrog };
14037c23b892Sbalrog 
14047c23b892Sbalrog /* PCI interface */
14057c23b892Sbalrog 
14067c23b892Sbalrog static void
1407ad00a9b9SAvi Kivity e1000_mmio_setup(E1000State *d)
14087c23b892Sbalrog {
1409f65ed4c1Saliguori     int i;
1410f65ed4c1Saliguori     const uint32_t excluded_regs[] = {
1411f65ed4c1Saliguori         E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
1412f65ed4c1Saliguori         E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
1413f65ed4c1Saliguori     };
1414f65ed4c1Saliguori 
1415eedfac6fSPaolo Bonzini     memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d,
1416eedfac6fSPaolo Bonzini                           "e1000-mmio", PNPMMIO_SIZE);
1417ad00a9b9SAvi Kivity     memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]);
1418f65ed4c1Saliguori     for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
1419ad00a9b9SAvi Kivity         memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
1420ad00a9b9SAvi Kivity                                      excluded_regs[i+1] - excluded_regs[i] - 4);
1421eedfac6fSPaolo Bonzini     memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
14227c23b892Sbalrog }
14237c23b892Sbalrog 
1424b946a153Saliguori static void
14254e68f7a0SStefan Hajnoczi e1000_cleanup(NetClientState *nc)
1426b946a153Saliguori {
1427cc1f0f45SJason Wang     E1000State *s = qemu_get_nic_opaque(nc);
1428b946a153Saliguori 
1429a03e2aecSMark McLoughlin     s->nic = NULL;
1430b946a153Saliguori }
1431b946a153Saliguori 
1432f90c2bcdSAlex Williamson static void
14334b09be85Saliguori pci_e1000_uninit(PCIDevice *dev)
14344b09be85Saliguori {
1435567a3c9eSPeter Crosthwaite     E1000State *d = E1000(dev);
14364b09be85Saliguori 
1437bc72ad67SAlex Bligh     timer_del(d->autoneg_timer);
1438bc72ad67SAlex Bligh     timer_free(d->autoneg_timer);
1439e9845f09SVincenzo Maffione     timer_del(d->mit_timer);
1440e9845f09SVincenzo Maffione     timer_free(d->mit_timer);
1441ad00a9b9SAvi Kivity     memory_region_destroy(&d->mmio);
1442ad00a9b9SAvi Kivity     memory_region_destroy(&d->io);
1443948ecf21SJason Wang     qemu_del_nic(d->nic);
14444b09be85Saliguori }
14454b09be85Saliguori 
1446a03e2aecSMark McLoughlin static NetClientInfo net_e1000_info = {
14472be64a68SLaszlo Ersek     .type = NET_CLIENT_OPTIONS_KIND_NIC,
1448a03e2aecSMark McLoughlin     .size = sizeof(NICState),
1449a03e2aecSMark McLoughlin     .can_receive = e1000_can_receive,
1450a03e2aecSMark McLoughlin     .receive = e1000_receive,
1451a03e2aecSMark McLoughlin     .cleanup = e1000_cleanup,
1452a03e2aecSMark McLoughlin     .link_status_changed = e1000_set_link_status,
1453a03e2aecSMark McLoughlin };
1454a03e2aecSMark McLoughlin 
145581a322d4SGerd Hoffmann static int pci_e1000_init(PCIDevice *pci_dev)
14567c23b892Sbalrog {
1457567a3c9eSPeter Crosthwaite     DeviceState *dev = DEVICE(pci_dev);
1458567a3c9eSPeter Crosthwaite     E1000State *d = E1000(pci_dev);
14597c23b892Sbalrog     uint8_t *pci_conf;
14607c23b892Sbalrog     uint16_t checksum = 0;
14617c23b892Sbalrog     int i;
1462fbdaa002SGerd Hoffmann     uint8_t *macaddr;
1463aff427a1SChris Wright 
1464b08340d5SAndreas Färber     pci_conf = pci_dev->config;
14657c23b892Sbalrog 
1466a9cbacb0SMichael S. Tsirkin     /* TODO: RST# value should be 0, PCI spec 6.2.4 */
1467a9cbacb0SMichael S. Tsirkin     pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;
14687c23b892Sbalrog 
1469817e0b6fSMichael S. Tsirkin     pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
14707c23b892Sbalrog 
1471ad00a9b9SAvi Kivity     e1000_mmio_setup(d);
14727c23b892Sbalrog 
1473b08340d5SAndreas Färber     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
14747c23b892Sbalrog 
1475b08340d5SAndreas Färber     pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
14767c23b892Sbalrog 
14777c23b892Sbalrog     memmove(d->eeprom_data, e1000_eeprom_template,
14787c23b892Sbalrog         sizeof e1000_eeprom_template);
1479fbdaa002SGerd Hoffmann     qemu_macaddr_default_if_unset(&d->conf.macaddr);
1480fbdaa002SGerd Hoffmann     macaddr = d->conf.macaddr.a;
14817c23b892Sbalrog     for (i = 0; i < 3; i++)
14829d07d757SPaul Brook         d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
14837c23b892Sbalrog     for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
14847c23b892Sbalrog         checksum += d->eeprom_data[i];
14857c23b892Sbalrog     checksum = (uint16_t) EEPROM_SUM - checksum;
14867c23b892Sbalrog     d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
14877c23b892Sbalrog 
1488a03e2aecSMark McLoughlin     d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
1489567a3c9eSPeter Crosthwaite                           object_get_typename(OBJECT(d)), dev->id, d);
14907c23b892Sbalrog 
1491b356f76dSJason Wang     qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
14921ca4d09aSGleb Natapov 
1493567a3c9eSPeter Crosthwaite     add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
14941ca4d09aSGleb Natapov 
1495bc72ad67SAlex Bligh     d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
1496e9845f09SVincenzo Maffione     d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
1497b9d03e35SJason Wang 
149881a322d4SGerd Hoffmann     return 0;
14997c23b892Sbalrog }
15009d07d757SPaul Brook 
1501fbdaa002SGerd Hoffmann static void qdev_e1000_reset(DeviceState *dev)
1502fbdaa002SGerd Hoffmann {
1503567a3c9eSPeter Crosthwaite     E1000State *d = E1000(dev);
1504fbdaa002SGerd Hoffmann     e1000_reset(d);
1505fbdaa002SGerd Hoffmann }
1506fbdaa002SGerd Hoffmann 
150740021f08SAnthony Liguori static Property e1000_properties[] = {
1508fbdaa002SGerd Hoffmann     DEFINE_NIC_PROPERTIES(E1000State, conf),
15092af234e6SMichael S. Tsirkin     DEFINE_PROP_BIT("autonegotiation", E1000State,
15102af234e6SMichael S. Tsirkin                     compat_flags, E1000_FLAG_AUTONEG_BIT, true),
1511e9845f09SVincenzo Maffione     DEFINE_PROP_BIT("mitigation", E1000State,
1512e9845f09SVincenzo Maffione                     compat_flags, E1000_FLAG_MIT_BIT, true),
1513fbdaa002SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
151440021f08SAnthony Liguori };
151540021f08SAnthony Liguori 
151640021f08SAnthony Liguori static void e1000_class_init(ObjectClass *klass, void *data)
151740021f08SAnthony Liguori {
151839bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
151940021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
152040021f08SAnthony Liguori 
152140021f08SAnthony Liguori     k->init = pci_e1000_init;
152240021f08SAnthony Liguori     k->exit = pci_e1000_uninit;
1523c45e5b5bSGerd Hoffmann     k->romfile = "efi-e1000.rom";
152440021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_INTEL;
152540021f08SAnthony Liguori     k->device_id = E1000_DEVID;
152640021f08SAnthony Liguori     k->revision = 0x03;
152740021f08SAnthony Liguori     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
1528125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
152939bffca2SAnthony Liguori     dc->desc = "Intel Gigabit Ethernet";
153039bffca2SAnthony Liguori     dc->reset = qdev_e1000_reset;
153139bffca2SAnthony Liguori     dc->vmsd = &vmstate_e1000;
153239bffca2SAnthony Liguori     dc->props = e1000_properties;
1533fbdaa002SGerd Hoffmann }
153440021f08SAnthony Liguori 
15358c43a6f0SAndreas Färber static const TypeInfo e1000_info = {
1536567a3c9eSPeter Crosthwaite     .name          = TYPE_E1000,
153739bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
153839bffca2SAnthony Liguori     .instance_size = sizeof(E1000State),
153940021f08SAnthony Liguori     .class_init    = e1000_class_init,
15400aab0d3aSGerd Hoffmann };
15410aab0d3aSGerd Hoffmann 
154283f7d43aSAndreas Färber static void e1000_register_types(void)
15439d07d757SPaul Brook {
154439bffca2SAnthony Liguori     type_register_static(&e1000_info);
15459d07d757SPaul Brook }
15469d07d757SPaul Brook 
154783f7d43aSAndreas Färber type_init(e1000_register_types)
1548