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