blob: 986ed9cf79833eca4b6ed050a23585145cd10dcd [file] [log] [blame]
balrog7c23b892008-02-03 02:20:18 +00001/*
2 * QEMU e1000 emulation
3 *
Michael S. Tsirkin2758aa52009-12-23 17:05:21 +02004 * Software developer's manual:
5 * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
6 *
balrog7c23b892008-02-03 02:20:18 +00007 * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
8 * Copyright (c) 2008 Qumranet
9 * Based on work done by:
10 * Copyright (c) 2007 Dan Aloni
11 * Copyright (c) 2004 Antony T Curtis
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000024 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
balrog7c23b892008-02-03 02:20:18 +000025 */
26
27
28#include "hw.h"
29#include "pci.h"
30#include "net.h"
Mark McLoughlin7200ac32009-10-22 17:49:03 +010031#include "net/checksum.h"
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +020032#include "loader.h"
Gleb Natapov1ca4d092010-12-08 13:35:05 +020033#include "sysemu.h"
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +110034#include "dma.h"
balrog7c23b892008-02-03 02:20:18 +000035
balrog7c23b892008-02-03 02:20:18 +000036#include "e1000_hw.h"
37
Jes Sorensen27124882010-06-14 17:05:17 +020038#define E1000_DEBUG
balrog7c23b892008-02-03 02:20:18 +000039
Jes Sorensen27124882010-06-14 17:05:17 +020040#ifdef E1000_DEBUG
balrog7c23b892008-02-03 02:20:18 +000041enum {
42 DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
43 DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
44 DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR,
45 DEBUG_RXFILTER, DEBUG_NOTYET,
46};
47#define DBGBIT(x) (1<<DEBUG_##x)
48static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
49
Blue Swirl6c7f4b42009-05-13 18:09:29 +000050#define DBGOUT(what, fmt, ...) do { \
balrog7c23b892008-02-03 02:20:18 +000051 if (debugflags & DBGBIT(what)) \
Blue Swirl6c7f4b42009-05-13 18:09:29 +000052 fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \
balrog7c23b892008-02-03 02:20:18 +000053 } while (0)
54#else
Blue Swirl6c7f4b42009-05-13 18:09:29 +000055#define DBGOUT(what, fmt, ...) do {} while (0)
balrog7c23b892008-02-03 02:20:18 +000056#endif
57
58#define IOPORT_SIZE 0x40
aurel32e94bbef2008-03-10 00:02:10 +000059#define PNPMMIO_SIZE 0x20000
Stefan Hajnoczi78aeb232010-09-18 21:43:45 +010060#define MIN_BUF_SIZE 60 /* Min. octets in an ethernet frame sans FCS */
balrog7c23b892008-02-03 02:20:18 +000061
62/*
63 * HW models:
64 * E1000_DEV_ID_82540EM works with Windows and Linux
65 * E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
66 * appears to perform better than 82540EM, but breaks with Linux 2.6.18
67 * E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
68 * Others never tested
69 */
70enum { E1000_DEVID = E1000_DEV_ID_82540EM };
71
72/*
73 * May need to specify additional MAC-to-PHY entries --
74 * Intel's Windows driver refuses to initialize unless they match
75 */
76enum {
77 PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ? 0xcc2 :
78 E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ? 0xc30 :
79 /* default to E1000_DEV_ID_82540EM */ 0xc20
80};
81
82typedef struct E1000State_st {
83 PCIDevice dev;
Mark McLoughlina03e2ae2009-11-25 18:49:12 +000084 NICState *nic;
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +020085 NICConf conf;
Avi Kivityad00a9b2011-08-08 16:09:08 +030086 MemoryRegion mmio;
87 MemoryRegion io;
balrog7c23b892008-02-03 02:20:18 +000088
89 uint32_t mac_reg[0x8000];
90 uint16_t phy_reg[0x20];
91 uint16_t eeprom_data[64];
92
93 uint32_t rxbuf_size;
94 uint32_t rxbuf_min_shift;
95 int check_rxov;
96 struct e1000_tx {
97 unsigned char header[256];
aliguori8f2e8d12008-11-21 16:25:17 +000098 unsigned char vlan_header[4];
Stefan Weilb10fec92009-11-19 19:44:55 +010099 /* Fields vlan and data must not be reordered or separated. */
aliguori8f2e8d12008-11-21 16:25:17 +0000100 unsigned char vlan[4];
balrog7c23b892008-02-03 02:20:18 +0000101 unsigned char data[0x10000];
102 uint16_t size;
103 unsigned char sum_needed;
aliguori8f2e8d12008-11-21 16:25:17 +0000104 unsigned char vlan_needed;
balrog7c23b892008-02-03 02:20:18 +0000105 uint8_t ipcss;
106 uint8_t ipcso;
107 uint16_t ipcse;
108 uint8_t tucss;
109 uint8_t tucso;
110 uint16_t tucse;
111 uint8_t hdr_len;
112 uint16_t mss;
113 uint32_t paylen;
114 uint16_t tso_frames;
115 char tse;
blueswir1b6c4f712008-10-02 19:14:17 +0000116 int8_t ip;
117 int8_t tcp;
balrog1b0009d2008-07-16 12:39:45 +0000118 char cptse; // current packet tse bit
balrog7c23b892008-02-03 02:20:18 +0000119 } tx;
120
121 struct {
122 uint32_t val_in; // shifted in from guest driver
123 uint16_t bitnum_in;
124 uint16_t bitnum_out;
125 uint16_t reading;
126 uint32_t old_eecd;
127 } eecd_state;
128} E1000State;
129
130#define defreg(x) x = (E1000_##x>>2)
131enum {
132 defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC),
133 defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC),
134 defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC),
135 defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH),
136 defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT),
137 defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH),
138 defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT),
139 defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL),
140 defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC),
aliguori8f2e8d12008-11-21 16:25:17 +0000141 defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA),
142 defreg(VET),
balrog7c23b892008-02-03 02:20:18 +0000143};
144
145enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
blueswir188b4e9d2008-10-02 18:24:21 +0000146static const char phy_regcap[0x20] = {
balrog7c23b892008-02-03 02:20:18 +0000147 [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
148 [PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW,
149 [PHY_CTRL] = PHY_RW, [PHY_1000T_CTRL] = PHY_RW,
150 [PHY_LP_ABILITY] = PHY_R, [PHY_1000T_STATUS] = PHY_R,
151 [PHY_AUTONEG_ADV] = PHY_RW, [M88E1000_RX_ERR_CNTR] = PHY_R,
aurel32700f6e22008-03-28 22:31:22 +0000152 [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R
balrog7c23b892008-02-03 02:20:18 +0000153};
154
155static void
balrog7c23b892008-02-03 02:20:18 +0000156set_interrupt_cause(E1000State *s, int index, uint32_t val)
157{
158 if (val)
159 val |= E1000_ICR_INT_ASSERTED;
160 s->mac_reg[ICR] = val;
Bill Paulb1332392009-07-29 10:22:55 -0700161 s->mac_reg[ICS] = val;
Blue Swirlbc26e552009-06-17 17:01:03 +0000162 qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
balrog7c23b892008-02-03 02:20:18 +0000163}
164
165static void
166set_ics(E1000State *s, int index, uint32_t val)
167{
168 DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR],
169 s->mac_reg[IMS]);
170 set_interrupt_cause(s, 0, val | s->mac_reg[ICR]);
171}
172
173static int
174rxbufsize(uint32_t v)
175{
176 v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
177 E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
178 E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
179 switch (v) {
180 case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
181 return 16384;
182 case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
183 return 8192;
184 case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
185 return 4096;
186 case E1000_RCTL_SZ_1024:
187 return 1024;
188 case E1000_RCTL_SZ_512:
189 return 512;
190 case E1000_RCTL_SZ_256:
191 return 256;
192 }
193 return 2048;
194}
195
196static void
Kevin Wolfcab3c822009-05-23 11:21:33 +0200197set_ctrl(E1000State *s, int index, uint32_t val)
198{
199 /* RST is self clearing */
200 s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
201}
202
203static void
balrog7c23b892008-02-03 02:20:18 +0000204set_rx_control(E1000State *s, int index, uint32_t val)
205{
206 s->mac_reg[RCTL] = val;
207 s->rxbuf_size = rxbufsize(val);
208 s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
209 DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
210 s->mac_reg[RCTL]);
211}
212
213static void
214set_mdic(E1000State *s, int index, uint32_t val)
215{
216 uint32_t data = val & E1000_MDIC_DATA_MASK;
217 uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
218
219 if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy #
220 val = s->mac_reg[MDIC] | E1000_MDIC_ERROR;
221 else if (val & E1000_MDIC_OP_READ) {
222 DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr);
223 if (!(phy_regcap[addr] & PHY_R)) {
224 DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr);
225 val |= E1000_MDIC_ERROR;
226 } else
227 val = (val ^ data) | s->phy_reg[addr];
228 } else if (val & E1000_MDIC_OP_WRITE) {
229 DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data);
230 if (!(phy_regcap[addr] & PHY_W)) {
231 DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
232 val |= E1000_MDIC_ERROR;
233 } else
234 s->phy_reg[addr] = data;
235 }
236 s->mac_reg[MDIC] = val | E1000_MDIC_READY;
237 set_ics(s, 0, E1000_ICR_MDAC);
238}
239
240static uint32_t
241get_eecd(E1000State *s, int index)
242{
243 uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd;
244
245 DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n",
246 s->eecd_state.bitnum_out, s->eecd_state.reading);
247 if (!s->eecd_state.reading ||
248 ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >>
249 ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1)
250 ret |= E1000_EECD_DO;
251 return ret;
252}
253
254static void
255set_eecd(E1000State *s, int index, uint32_t val)
256{
257 uint32_t oldval = s->eecd_state.old_eecd;
258
259 s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS |
260 E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ);
Izumi Tsutsui9651ac52010-07-10 23:03:45 +0900261 if (!(E1000_EECD_CS & val)) // CS inactive; nothing to do
262 return;
263 if (E1000_EECD_CS & (val ^ oldval)) { // CS rise edge; reset state
264 s->eecd_state.val_in = 0;
265 s->eecd_state.bitnum_in = 0;
266 s->eecd_state.bitnum_out = 0;
267 s->eecd_state.reading = 0;
268 }
balrog7c23b892008-02-03 02:20:18 +0000269 if (!(E1000_EECD_SK & (val ^ oldval))) // no clock edge
270 return;
271 if (!(E1000_EECD_SK & val)) { // falling edge
272 s->eecd_state.bitnum_out++;
273 return;
274 }
balrog7c23b892008-02-03 02:20:18 +0000275 s->eecd_state.val_in <<= 1;
276 if (val & E1000_EECD_DI)
277 s->eecd_state.val_in |= 1;
278 if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) {
279 s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1;
280 s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) ==
281 EEPROM_READ_OPCODE_MICROWIRE);
282 }
283 DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n",
284 s->eecd_state.bitnum_in, s->eecd_state.bitnum_out,
285 s->eecd_state.reading);
286}
287
288static uint32_t
289flash_eerd_read(E1000State *s, int x)
290{
291 unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START;
292
Bill Paulb1332392009-07-29 10:22:55 -0700293 if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0)
294 return (s->mac_reg[EERD]);
295
balrog7c23b892008-02-03 02:20:18 +0000296 if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG)
Bill Paulb1332392009-07-29 10:22:55 -0700297 return (E1000_EEPROM_RW_REG_DONE | r);
298
299 return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
300 E1000_EEPROM_RW_REG_DONE | r);
balrog7c23b892008-02-03 02:20:18 +0000301}
302
balrog7c23b892008-02-03 02:20:18 +0000303static void
304putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
305{
aliguoric6a6a5e2008-07-29 19:41:19 +0000306 uint32_t sum;
307
balrog7c23b892008-02-03 02:20:18 +0000308 if (cse && cse < n)
309 n = cse + 1;
aliguoric6a6a5e2008-07-29 19:41:19 +0000310 if (sloc < n-1) {
311 sum = net_checksum_add(n-css, data+css);
balrog7c23b892008-02-03 02:20:18 +0000312 cpu_to_be16wu((uint16_t *)(data + sloc),
aliguoric6a6a5e2008-07-29 19:41:19 +0000313 net_checksum_finish(sum));
314 }
balrog7c23b892008-02-03 02:20:18 +0000315}
316
aliguori8f2e8d12008-11-21 16:25:17 +0000317static inline int
318vlan_enabled(E1000State *s)
319{
320 return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0);
321}
322
323static inline int
324vlan_rx_filter_enabled(E1000State *s)
325{
326 return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0);
327}
328
329static inline int
330is_vlan_packet(E1000State *s, const uint8_t *buf)
331{
332 return (be16_to_cpup((uint16_t *)(buf + 12)) ==
333 le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
334}
335
336static inline int
337is_vlan_txd(uint32_t txd_lower)
338{
339 return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
340}
341
Michael S. Tsirkin55e8d1c2010-07-12 20:41:02 +0300342/* FCS aka Ethernet CRC-32. We don't get it from backends and can't
343 * fill it in, just pad descriptor length by 4 bytes unless guest
Michael S. Tsirkina05e8a62010-09-02 17:47:43 +0300344 * told us to strip it off the packet. */
Michael S. Tsirkin55e8d1c2010-07-12 20:41:02 +0300345static inline int
346fcs_len(E1000State *s)
347{
348 return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
349}
350
balrog7c23b892008-02-03 02:20:18 +0000351static void
352xmit_seg(E1000State *s)
353{
354 uint16_t len, *sp;
355 unsigned int frames = s->tx.tso_frames, css, sofar, n;
356 struct e1000_tx *tp = &s->tx;
357
balrog1b0009d2008-07-16 12:39:45 +0000358 if (tp->tse && tp->cptse) {
balrog7c23b892008-02-03 02:20:18 +0000359 css = tp->ipcss;
360 DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
361 frames, tp->size, css);
362 if (tp->ip) { // IPv4
363 cpu_to_be16wu((uint16_t *)(tp->data+css+2),
364 tp->size - css);
365 cpu_to_be16wu((uint16_t *)(tp->data+css+4),
366 be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
367 } else // IPv6
368 cpu_to_be16wu((uint16_t *)(tp->data+css+4),
369 tp->size - css);
370 css = tp->tucss;
371 len = tp->size - css;
372 DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
373 if (tp->tcp) {
374 sofar = frames * tp->mss;
375 cpu_to_be32wu((uint32_t *)(tp->data+css+4), // seq
aurel3288738c02008-03-28 22:30:48 +0000376 be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar);
balrog7c23b892008-02-03 02:20:18 +0000377 if (tp->paylen - sofar > tp->mss)
378 tp->data[css + 13] &= ~9; // PSH, FIN
379 } else // UDP
380 cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
381 if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
Alex Williamsone685b4e2010-11-05 14:52:08 -0600382 unsigned int phsum;
balrog7c23b892008-02-03 02:20:18 +0000383 // add pseudo-header length before checksum calculation
384 sp = (uint16_t *)(tp->data + tp->tucso);
Alex Williamsone685b4e2010-11-05 14:52:08 -0600385 phsum = be16_to_cpup(sp) + len;
386 phsum = (phsum >> 16) + (phsum & 0xffff);
387 cpu_to_be16wu(sp, phsum);
balrog7c23b892008-02-03 02:20:18 +0000388 }
389 tp->tso_frames++;
390 }
391
392 if (tp->sum_needed & E1000_TXD_POPTS_TXSM)
393 putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);
394 if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
395 putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
aliguori8f2e8d12008-11-21 16:25:17 +0000396 if (tp->vlan_needed) {
Stefan Weilb10fec92009-11-19 19:44:55 +0100397 memmove(tp->vlan, tp->data, 4);
398 memmove(tp->data, tp->data + 4, 8);
aliguori8f2e8d12008-11-21 16:25:17 +0000399 memcpy(tp->data + 8, tp->vlan_header, 4);
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000400 qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4);
aliguori8f2e8d12008-11-21 16:25:17 +0000401 } else
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000402 qemu_send_packet(&s->nic->nc, tp->data, tp->size);
balrog7c23b892008-02-03 02:20:18 +0000403 s->mac_reg[TPT]++;
404 s->mac_reg[GPTC]++;
405 n = s->mac_reg[TOTL];
406 if ((s->mac_reg[TOTL] += s->tx.size) < n)
407 s->mac_reg[TOTH]++;
408}
409
410static void
411process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
412{
413 uint32_t txd_lower = le32_to_cpu(dp->lower.data);
414 uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
415 unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
416 unsigned int msh = 0xfffff, hdr = 0;
417 uint64_t addr;
418 struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
419 struct e1000_tx *tp = &s->tx;
420
421 if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor
422 op = le32_to_cpu(xp->cmd_and_length);
423 tp->ipcss = xp->lower_setup.ip_fields.ipcss;
424 tp->ipcso = xp->lower_setup.ip_fields.ipcso;
425 tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);
426 tp->tucss = xp->upper_setup.tcp_fields.tucss;
427 tp->tucso = xp->upper_setup.tcp_fields.tucso;
428 tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);
429 tp->paylen = op & 0xfffff;
430 tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;
431 tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);
432 tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
433 tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
434 tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
435 tp->tso_frames = 0;
436 if (tp->tucso == 0) { // this is probably wrong
437 DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
438 tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
439 }
440 return;
balrog1b0009d2008-07-16 12:39:45 +0000441 } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
442 // data descriptor
Stefan Hajnoczi735e77e2011-03-07 20:04:07 +0000443 if (tp->size == 0) {
444 tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
445 }
balrog1b0009d2008-07-16 12:39:45 +0000446 tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100447 } else {
balrog1b0009d2008-07-16 12:39:45 +0000448 // legacy descriptor
449 tp->cptse = 0;
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100450 }
balrog7c23b892008-02-03 02:20:18 +0000451
aliguori8f2e8d12008-11-21 16:25:17 +0000452 if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
453 (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
454 tp->vlan_needed = 1;
455 cpu_to_be16wu((uint16_t *)(tp->vlan_header),
456 le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
457 cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2),
458 le16_to_cpu(dp->upper.fields.special));
459 }
460
balrog7c23b892008-02-03 02:20:18 +0000461 addr = le64_to_cpu(dp->buffer_addr);
balrog1b0009d2008-07-16 12:39:45 +0000462 if (tp->tse && tp->cptse) {
balrog7c23b892008-02-03 02:20:18 +0000463 hdr = tp->hdr_len;
464 msh = hdr + tp->mss;
balrog1b0009d2008-07-16 12:39:45 +0000465 do {
466 bytes = split_size;
467 if (tp->size + bytes > msh)
468 bytes = msh - tp->size;
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100469 pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
balrog1b0009d2008-07-16 12:39:45 +0000470 if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
471 memmove(tp->header, tp->data, hdr);
472 tp->size = sz;
473 addr += bytes;
474 if (sz == msh) {
475 xmit_seg(s);
476 memmove(tp->data, tp->header, hdr);
477 tp->size = hdr;
478 }
479 } while (split_size -= bytes);
480 } else if (!tp->tse && tp->cptse) {
481 // context descriptor TSE is not set, while data descriptor TSE is set
482 DBGOUT(TXERR, "TCP segmentaion Error\n");
483 } else {
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100484 pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size);
balrog1b0009d2008-07-16 12:39:45 +0000485 tp->size += split_size;
balrog7c23b892008-02-03 02:20:18 +0000486 }
balrog7c23b892008-02-03 02:20:18 +0000487
488 if (!(txd_lower & E1000_TXD_CMD_EOP))
489 return;
balrog1b0009d2008-07-16 12:39:45 +0000490 if (!(tp->tse && tp->cptse && tp->size < hdr))
balrog7c23b892008-02-03 02:20:18 +0000491 xmit_seg(s);
492 tp->tso_frames = 0;
493 tp->sum_needed = 0;
aliguori8f2e8d12008-11-21 16:25:17 +0000494 tp->vlan_needed = 0;
balrog7c23b892008-02-03 02:20:18 +0000495 tp->size = 0;
balrog1b0009d2008-07-16 12:39:45 +0000496 tp->cptse = 0;
balrog7c23b892008-02-03 02:20:18 +0000497}
498
499static uint32_t
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100500txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
balrog7c23b892008-02-03 02:20:18 +0000501{
502 uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
503
504 if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))
505 return 0;
506 txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
507 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
508 dp->upper.data = cpu_to_le32(txd_upper);
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100509 pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp),
510 (void *)&dp->upper, sizeof(dp->upper));
balrog7c23b892008-02-03 02:20:18 +0000511 return E1000_ICR_TXDW;
512}
513
Kevin Wolfd17161f2011-03-26 19:37:56 +0100514static uint64_t tx_desc_base(E1000State *s)
515{
516 uint64_t bah = s->mac_reg[TDBAH];
517 uint64_t bal = s->mac_reg[TDBAL] & ~0xf;
518
519 return (bah << 32) + bal;
520}
521
balrog7c23b892008-02-03 02:20:18 +0000522static void
523start_xmit(E1000State *s)
524{
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100525 dma_addr_t base;
balrog7c23b892008-02-03 02:20:18 +0000526 struct e1000_tx_desc desc;
527 uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
528
529 if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) {
530 DBGOUT(TX, "tx disabled\n");
531 return;
532 }
533
534 while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
Kevin Wolfd17161f2011-03-26 19:37:56 +0100535 base = tx_desc_base(s) +
balrog7c23b892008-02-03 02:20:18 +0000536 sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100537 pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
balrog7c23b892008-02-03 02:20:18 +0000538
539 DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
ths61060752008-05-13 14:35:34 +0000540 (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
balrog7c23b892008-02-03 02:20:18 +0000541 desc.upper.data);
542
543 process_tx_desc(s, &desc);
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100544 cause |= txdesc_writeback(s, base, &desc);
balrog7c23b892008-02-03 02:20:18 +0000545
546 if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])
547 s->mac_reg[TDH] = 0;
548 /*
549 * the following could happen only if guest sw assigns
550 * bogus values to TDT/TDLEN.
551 * there's nothing too intelligent we could do about this.
552 */
553 if (s->mac_reg[TDH] == tdh_start) {
554 DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
555 tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
556 break;
557 }
558 }
559 set_ics(s, 0, cause);
560}
561
562static int
563receive_filter(E1000State *s, const uint8_t *buf, int size)
564{
Blue Swirlaf2960f2010-05-14 19:32:18 +0000565 static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
566 static const int mta_shift[] = {4, 3, 2, 0};
balrog7c23b892008-02-03 02:20:18 +0000567 uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
568
aliguori8f2e8d12008-11-21 16:25:17 +0000569 if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
570 uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14));
571 uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) +
572 ((vid >> 5) & 0x7f));
573 if ((vfta & (1 << (vid & 0x1f))) == 0)
574 return 0;
575 }
576
balrog7c23b892008-02-03 02:20:18 +0000577 if (rctl & E1000_RCTL_UPE) // promiscuous
578 return 1;
579
580 if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast
581 return 1;
582
583 if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast))
584 return 1;
585
586 for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {
587 if (!(rp[1] & E1000_RAH_AV))
588 continue;
589 ra[0] = cpu_to_le32(rp[0]);
590 ra[1] = cpu_to_le32(rp[1]);
591 if (!memcmp(buf, (uint8_t *)ra, 6)) {
592 DBGOUT(RXFILTER,
593 "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
594 (int)(rp - s->mac_reg - RA)/2,
595 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
596 return 1;
597 }
598 }
599 DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",
600 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
601
602 f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
603 f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
604 if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f)))
605 return 1;
606 DBGOUT(RXFILTER,
607 "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",
608 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
609 (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,
610 s->mac_reg[MTA + (f >> 5)]);
611
612 return 0;
613}
614
aliguori99ed7e32009-01-08 19:45:50 +0000615static void
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000616e1000_set_link_status(VLANClientState *nc)
aliguori99ed7e32009-01-08 19:45:50 +0000617{
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000618 E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
aliguori99ed7e32009-01-08 19:45:50 +0000619 uint32_t old_status = s->mac_reg[STATUS];
620
Bjørn Morkd4044c22011-08-17 11:03:14 +0200621 if (nc->link_down) {
aliguori99ed7e32009-01-08 19:45:50 +0000622 s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
Bjørn Morkd4044c22011-08-17 11:03:14 +0200623 s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
624 } else {
aliguori99ed7e32009-01-08 19:45:50 +0000625 s->mac_reg[STATUS] |= E1000_STATUS_LU;
Bjørn Morkd4044c22011-08-17 11:03:14 +0200626 s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
627 }
aliguori99ed7e32009-01-08 19:45:50 +0000628
629 if (s->mac_reg[STATUS] != old_status)
630 set_ics(s, 0, E1000_ICR_LSC);
631}
632
Michael S. Tsirkin322fd482011-02-15 18:27:55 +0200633static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
634{
635 int bufs;
636 /* Fast-path short packets */
637 if (total_size <= s->rxbuf_size) {
638 return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov;
639 }
640 if (s->mac_reg[RDH] < s->mac_reg[RDT]) {
641 bufs = s->mac_reg[RDT] - s->mac_reg[RDH];
642 } else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) {
643 bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) +
644 s->mac_reg[RDT] - s->mac_reg[RDH];
645 } else {
646 return false;
647 }
648 return total_size <= bufs * s->rxbuf_size;
649}
650
Michael S. Tsirkin6cdfab22011-03-27 13:37:35 +0200651static int
652e1000_can_receive(VLANClientState *nc)
653{
654 E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
655
656 return (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
657}
658
Kevin Wolfd17161f2011-03-26 19:37:56 +0100659static uint64_t rx_desc_base(E1000State *s)
660{
661 uint64_t bah = s->mac_reg[RDBAH];
662 uint64_t bal = s->mac_reg[RDBAL] & ~0xf;
663
664 return (bah << 32) + bal;
665}
666
Mark McLoughlin4f1c9422009-05-18 13:40:55 +0100667static ssize_t
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000668e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
balrog7c23b892008-02-03 02:20:18 +0000669{
Mark McLoughlina03e2ae2009-11-25 18:49:12 +0000670 E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
balrog7c23b892008-02-03 02:20:18 +0000671 struct e1000_rx_desc desc;
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100672 dma_addr_t base;
balrog7c23b892008-02-03 02:20:18 +0000673 unsigned int n, rdt;
674 uint32_t rdh_start;
aliguori8f2e8d12008-11-21 16:25:17 +0000675 uint16_t vlan_special = 0;
676 uint8_t vlan_status = 0, vlan_offset = 0;
Stefan Hajnoczi78aeb232010-09-18 21:43:45 +0100677 uint8_t min_buf[MIN_BUF_SIZE];
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200678 size_t desc_offset;
679 size_t desc_size;
680 size_t total_size;
balrog7c23b892008-02-03 02:20:18 +0000681
682 if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
Mark McLoughlin4f1c9422009-05-18 13:40:55 +0100683 return -1;
balrog7c23b892008-02-03 02:20:18 +0000684
Stefan Hajnoczi78aeb232010-09-18 21:43:45 +0100685 /* Pad to minimum Ethernet frame length */
686 if (size < sizeof(min_buf)) {
687 memcpy(min_buf, buf, size);
688 memset(&min_buf[size], 0, sizeof(min_buf) - size);
689 buf = min_buf;
690 size = sizeof(min_buf);
691 }
692
balrog7c23b892008-02-03 02:20:18 +0000693 if (!receive_filter(s, buf, size))
Mark McLoughlin4f1c9422009-05-18 13:40:55 +0100694 return size;
balrog7c23b892008-02-03 02:20:18 +0000695
aliguori8f2e8d12008-11-21 16:25:17 +0000696 if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
697 vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
Thomas Monjalon98835fe2010-03-31 11:22:51 +0200698 memmove((uint8_t *)buf + 4, buf, 12);
aliguori8f2e8d12008-11-21 16:25:17 +0000699 vlan_status = E1000_RXD_STAT_VP;
700 vlan_offset = 4;
701 size -= 4;
702 }
703
balrog7c23b892008-02-03 02:20:18 +0000704 rdh_start = s->mac_reg[RDH];
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200705 desc_offset = 0;
706 total_size = size + fcs_len(s);
Michael S. Tsirkin322fd482011-02-15 18:27:55 +0200707 if (!e1000_has_rxbufs(s, total_size)) {
708 set_ics(s, 0, E1000_ICS_RXO);
709 return -1;
710 }
balrog7c23b892008-02-03 02:20:18 +0000711 do {
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200712 desc_size = total_size - desc_offset;
713 if (desc_size > s->rxbuf_size) {
714 desc_size = s->rxbuf_size;
715 }
Kevin Wolfd17161f2011-03-26 19:37:56 +0100716 base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100717 pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
aliguori8f2e8d12008-11-21 16:25:17 +0000718 desc.special = vlan_special;
719 desc.status |= (vlan_status | E1000_RXD_STAT_DD);
balrog7c23b892008-02-03 02:20:18 +0000720 if (desc.buffer_addr) {
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200721 if (desc_offset < size) {
722 size_t copy_size = size - desc_offset;
723 if (copy_size > s->rxbuf_size) {
724 copy_size = s->rxbuf_size;
725 }
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100726 pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr),
727 (void *)(buf + desc_offset + vlan_offset),
728 copy_size);
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200729 }
730 desc_offset += desc_size;
Michael S. Tsirkinee912ccf2011-02-15 18:27:52 +0200731 desc.length = cpu_to_le16(desc_size);
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200732 if (desc_offset >= total_size) {
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200733 desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM;
734 } else {
Michael S. Tsirkinee912ccf2011-02-15 18:27:52 +0200735 /* Guest zeroing out status is not a hardware requirement.
736 Clear EOP in case guest didn't do it. */
737 desc.status &= ~E1000_RXD_STAT_EOP;
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200738 }
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100739 } else { // as per intel docs; skip descriptors with null buf addr
balrog7c23b892008-02-03 02:20:18 +0000740 DBGOUT(RX, "Null RX descriptor!!\n");
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100741 }
Eduard - Gabriel Munteanu62ecbd32011-10-31 17:06:52 +1100742 pci_dma_write(&s->dev, base, (void *)&desc, sizeof(desc));
balrog7c23b892008-02-03 02:20:18 +0000743
744 if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
745 s->mac_reg[RDH] = 0;
746 s->check_rxov = 1;
747 /* see comment in start_xmit; same here */
748 if (s->mac_reg[RDH] == rdh_start) {
749 DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
750 rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
751 set_ics(s, 0, E1000_ICS_RXO);
Mark McLoughlin4f1c9422009-05-18 13:40:55 +0100752 return -1;
balrog7c23b892008-02-03 02:20:18 +0000753 }
Michael S. Tsirkinb19487e2011-02-15 18:27:48 +0200754 } while (desc_offset < total_size);
balrog7c23b892008-02-03 02:20:18 +0000755
756 s->mac_reg[GPRC]++;
757 s->mac_reg[TPR]++;
Michael S. Tsirkina05e8a62010-09-02 17:47:43 +0300758 /* TOR - Total Octets Received:
759 * This register includes bytes received in a packet from the <Destination
760 * Address> field through the <CRC> field, inclusively.
761 */
762 n = s->mac_reg[TORL] + size + /* Always include FCS length. */ 4;
763 if (n < s->mac_reg[TORL])
balrog7c23b892008-02-03 02:20:18 +0000764 s->mac_reg[TORH]++;
Michael S. Tsirkina05e8a62010-09-02 17:47:43 +0300765 s->mac_reg[TORL] = n;
balrog7c23b892008-02-03 02:20:18 +0000766
767 n = E1000_ICS_RXT0;
768 if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
769 rdt += s->mac_reg[RDLEN] / sizeof(desc);
aliguoribf16cc82009-03-20 16:13:47 +0000770 if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
771 s->rxbuf_min_shift)
balrog7c23b892008-02-03 02:20:18 +0000772 n |= E1000_ICS_RXDMT0;
773
774 set_ics(s, 0, n);
Mark McLoughlin4f1c9422009-05-18 13:40:55 +0100775
776 return size;
balrog7c23b892008-02-03 02:20:18 +0000777}
778
779static uint32_t
780mac_readreg(E1000State *s, int index)
781{
782 return s->mac_reg[index];
783}
784
785static uint32_t
786mac_icr_read(E1000State *s, int index)
787{
788 uint32_t ret = s->mac_reg[ICR];
789
790 DBGOUT(INTERRUPT, "ICR read: %x\n", ret);
791 set_interrupt_cause(s, 0, 0);
792 return ret;
793}
794
795static uint32_t
796mac_read_clr4(E1000State *s, int index)
797{
798 uint32_t ret = s->mac_reg[index];
799
800 s->mac_reg[index] = 0;
801 return ret;
802}
803
804static uint32_t
805mac_read_clr8(E1000State *s, int index)
806{
807 uint32_t ret = s->mac_reg[index];
808
809 s->mac_reg[index] = 0;
810 s->mac_reg[index-1] = 0;
811 return ret;
812}
813
814static void
815mac_writereg(E1000State *s, int index, uint32_t val)
816{
817 s->mac_reg[index] = val;
818}
819
820static void
821set_rdt(E1000State *s, int index, uint32_t val)
822{
823 s->check_rxov = 0;
824 s->mac_reg[index] = val & 0xffff;
825}
826
827static void
828set_16bit(E1000State *s, int index, uint32_t val)
829{
830 s->mac_reg[index] = val & 0xffff;
831}
832
833static void
834set_dlen(E1000State *s, int index, uint32_t val)
835{
836 s->mac_reg[index] = val & 0xfff80;
837}
838
839static void
840set_tctl(E1000State *s, int index, uint32_t val)
841{
842 s->mac_reg[index] = val;
843 s->mac_reg[TDT] &= 0xffff;
844 start_xmit(s);
845}
846
847static void
848set_icr(E1000State *s, int index, uint32_t val)
849{
850 DBGOUT(INTERRUPT, "set_icr %x\n", val);
851 set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val);
852}
853
854static void
855set_imc(E1000State *s, int index, uint32_t val)
856{
857 s->mac_reg[IMS] &= ~val;
858 set_ics(s, 0, 0);
859}
860
861static void
862set_ims(E1000State *s, int index, uint32_t val)
863{
864 s->mac_reg[IMS] |= val;
865 set_ics(s, 0, 0);
866}
867
868#define getreg(x) [x] = mac_readreg
869static uint32_t (*macreg_readops[])(E1000State *, int) = {
870 getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL),
871 getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL),
872 getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS),
873 getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL),
Bill Paulb1332392009-07-29 10:22:55 -0700874 getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS),
Kay Ackermanna00b2332009-10-31 18:29:43 +0100875 getreg(TDBAL), getreg(TDBAH), getreg(RDBAH), getreg(RDBAL),
876 getreg(TDLEN), getreg(RDLEN),
balrog7c23b892008-02-03 02:20:18 +0000877
878 [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
879 [GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4,
880 [ICR] = mac_icr_read, [EECD] = get_eecd, [EERD] = flash_eerd_read,
881 [CRCERRS ... MPC] = &mac_readreg,
882 [RA ... RA+31] = &mac_readreg,
883 [MTA ... MTA+127] = &mac_readreg,
aliguori8f2e8d12008-11-21 16:25:17 +0000884 [VFTA ... VFTA+127] = &mac_readreg,
balrog7c23b892008-02-03 02:20:18 +0000885};
malcb1503cd2008-12-22 20:33:55 +0000886enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
balrog7c23b892008-02-03 02:20:18 +0000887
888#define putreg(x) [x] = mac_writereg
889static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
890 putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC),
891 putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH),
Kevin Wolfcab3c822009-05-23 11:21:33 +0200892 putreg(RDBAL), putreg(LEDCTL), putreg(VET),
balrog7c23b892008-02-03 02:20:18 +0000893 [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl,
894 [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics,
895 [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
896 [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
Kevin Wolfcab3c822009-05-23 11:21:33 +0200897 [EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl,
balrog7c23b892008-02-03 02:20:18 +0000898 [RA ... RA+31] = &mac_writereg,
899 [MTA ... MTA+127] = &mac_writereg,
aliguori8f2e8d12008-11-21 16:25:17 +0000900 [VFTA ... VFTA+127] = &mac_writereg,
balrog7c23b892008-02-03 02:20:18 +0000901};
malcb1503cd2008-12-22 20:33:55 +0000902enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
balrog7c23b892008-02-03 02:20:18 +0000903
904static void
Avi Kivityad00a9b2011-08-08 16:09:08 +0300905e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val,
906 unsigned size)
balrog7c23b892008-02-03 02:20:18 +0000907{
908 E1000State *s = opaque;
pbrook8da3ff12008-12-01 18:59:50 +0000909 unsigned int index = (addr & 0x1ffff) >> 2;
balrog7c23b892008-02-03 02:20:18 +0000910
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100911 if (index < NWRITEOPS && macreg_writeops[index]) {
aurel326b59fc72008-03-13 19:18:26 +0000912 macreg_writeops[index](s, index, val);
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100913 } else if (index < NREADOPS && macreg_readops[index]) {
Avi Kivityad00a9b2011-08-08 16:09:08 +0300914 DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val);
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100915 } else {
Avi Kivityad00a9b2011-08-08 16:09:08 +0300916 DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n",
balrog7c23b892008-02-03 02:20:18 +0000917 index<<2, val);
Jes Sorensen43ad7e32010-11-11 16:10:04 +0100918 }
balrog7c23b892008-02-03 02:20:18 +0000919}
920
Avi Kivityad00a9b2011-08-08 16:09:08 +0300921static uint64_t
922e1000_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size)
balrog7c23b892008-02-03 02:20:18 +0000923{
924 E1000State *s = opaque;
pbrook8da3ff12008-12-01 18:59:50 +0000925 unsigned int index = (addr & 0x1ffff) >> 2;
balrog7c23b892008-02-03 02:20:18 +0000926
927 if (index < NREADOPS && macreg_readops[index])
aurel326b59fc72008-03-13 19:18:26 +0000928 {
Alexander Graf32600a32010-12-08 12:05:42 +0100929 return macreg_readops[index](s, index);
aurel326b59fc72008-03-13 19:18:26 +0000930 }
balrog7c23b892008-02-03 02:20:18 +0000931 DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2);
932 return 0;
933}
934
Avi Kivityad00a9b2011-08-08 16:09:08 +0300935static const MemoryRegionOps e1000_mmio_ops = {
936 .read = e1000_mmio_read,
937 .write = e1000_mmio_write,
938 .endianness = DEVICE_LITTLE_ENDIAN,
939 .impl = {
940 .min_access_size = 4,
941 .max_access_size = 4,
942 },
943};
944
945static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr,
946 unsigned size)
balrog7c23b892008-02-03 02:20:18 +0000947{
Avi Kivityad00a9b2011-08-08 16:09:08 +0300948 E1000State *s = opaque;
949
950 (void)s;
951 return 0;
balrog7c23b892008-02-03 02:20:18 +0000952}
953
Avi Kivityad00a9b2011-08-08 16:09:08 +0300954static void e1000_io_write(void *opaque, target_phys_addr_t addr,
955 uint64_t val, unsigned size)
balrog7c23b892008-02-03 02:20:18 +0000956{
Avi Kivityad00a9b2011-08-08 16:09:08 +0300957 E1000State *s = opaque;
958
959 (void)s;
balrog7c23b892008-02-03 02:20:18 +0000960}
961
Avi Kivityad00a9b2011-08-08 16:09:08 +0300962static const MemoryRegionOps e1000_io_ops = {
963 .read = e1000_io_read,
964 .write = e1000_io_write,
965 .endianness = DEVICE_LITTLE_ENDIAN,
966};
967
Juan Quintelae482dc32009-10-19 20:06:05 +0200968static bool is_version_1(void *opaque, int version_id)
balrog7c23b892008-02-03 02:20:18 +0000969{
Juan Quintelae482dc32009-10-19 20:06:05 +0200970 return version_id == 1;
balrog7c23b892008-02-03 02:20:18 +0000971}
972
Juan Quintelae482dc32009-10-19 20:06:05 +0200973static const VMStateDescription vmstate_e1000 = {
974 .name = "e1000",
975 .version_id = 2,
976 .minimum_version_id = 1,
977 .minimum_version_id_old = 1,
978 .fields = (VMStateField []) {
979 VMSTATE_PCI_DEVICE(dev, E1000State),
980 VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */
981 VMSTATE_UNUSED(4), /* Was mmio_base. */
982 VMSTATE_UINT32(rxbuf_size, E1000State),
983 VMSTATE_UINT32(rxbuf_min_shift, E1000State),
984 VMSTATE_UINT32(eecd_state.val_in, E1000State),
985 VMSTATE_UINT16(eecd_state.bitnum_in, E1000State),
986 VMSTATE_UINT16(eecd_state.bitnum_out, E1000State),
987 VMSTATE_UINT16(eecd_state.reading, E1000State),
988 VMSTATE_UINT32(eecd_state.old_eecd, E1000State),
989 VMSTATE_UINT8(tx.ipcss, E1000State),
990 VMSTATE_UINT8(tx.ipcso, E1000State),
991 VMSTATE_UINT16(tx.ipcse, E1000State),
992 VMSTATE_UINT8(tx.tucss, E1000State),
993 VMSTATE_UINT8(tx.tucso, E1000State),
994 VMSTATE_UINT16(tx.tucse, E1000State),
995 VMSTATE_UINT32(tx.paylen, E1000State),
996 VMSTATE_UINT8(tx.hdr_len, E1000State),
997 VMSTATE_UINT16(tx.mss, E1000State),
998 VMSTATE_UINT16(tx.size, E1000State),
999 VMSTATE_UINT16(tx.tso_frames, E1000State),
1000 VMSTATE_UINT8(tx.sum_needed, E1000State),
1001 VMSTATE_INT8(tx.ip, E1000State),
1002 VMSTATE_INT8(tx.tcp, E1000State),
1003 VMSTATE_BUFFER(tx.header, E1000State),
1004 VMSTATE_BUFFER(tx.data, E1000State),
1005 VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64),
1006 VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20),
1007 VMSTATE_UINT32(mac_reg[CTRL], E1000State),
1008 VMSTATE_UINT32(mac_reg[EECD], E1000State),
1009 VMSTATE_UINT32(mac_reg[EERD], E1000State),
1010 VMSTATE_UINT32(mac_reg[GPRC], E1000State),
1011 VMSTATE_UINT32(mac_reg[GPTC], E1000State),
1012 VMSTATE_UINT32(mac_reg[ICR], E1000State),
1013 VMSTATE_UINT32(mac_reg[ICS], E1000State),
1014 VMSTATE_UINT32(mac_reg[IMC], E1000State),
1015 VMSTATE_UINT32(mac_reg[IMS], E1000State),
1016 VMSTATE_UINT32(mac_reg[LEDCTL], E1000State),
1017 VMSTATE_UINT32(mac_reg[MANC], E1000State),
1018 VMSTATE_UINT32(mac_reg[MDIC], E1000State),
1019 VMSTATE_UINT32(mac_reg[MPC], E1000State),
1020 VMSTATE_UINT32(mac_reg[PBA], E1000State),
1021 VMSTATE_UINT32(mac_reg[RCTL], E1000State),
1022 VMSTATE_UINT32(mac_reg[RDBAH], E1000State),
1023 VMSTATE_UINT32(mac_reg[RDBAL], E1000State),
1024 VMSTATE_UINT32(mac_reg[RDH], E1000State),
1025 VMSTATE_UINT32(mac_reg[RDLEN], E1000State),
1026 VMSTATE_UINT32(mac_reg[RDT], E1000State),
1027 VMSTATE_UINT32(mac_reg[STATUS], E1000State),
1028 VMSTATE_UINT32(mac_reg[SWSM], E1000State),
1029 VMSTATE_UINT32(mac_reg[TCTL], E1000State),
1030 VMSTATE_UINT32(mac_reg[TDBAH], E1000State),
1031 VMSTATE_UINT32(mac_reg[TDBAL], E1000State),
1032 VMSTATE_UINT32(mac_reg[TDH], E1000State),
1033 VMSTATE_UINT32(mac_reg[TDLEN], E1000State),
1034 VMSTATE_UINT32(mac_reg[TDT], E1000State),
1035 VMSTATE_UINT32(mac_reg[TORH], E1000State),
1036 VMSTATE_UINT32(mac_reg[TORL], E1000State),
1037 VMSTATE_UINT32(mac_reg[TOTH], E1000State),
1038 VMSTATE_UINT32(mac_reg[TOTL], E1000State),
1039 VMSTATE_UINT32(mac_reg[TPR], E1000State),
1040 VMSTATE_UINT32(mac_reg[TPT], E1000State),
1041 VMSTATE_UINT32(mac_reg[TXDCTL], E1000State),
1042 VMSTATE_UINT32(mac_reg[WUFC], E1000State),
1043 VMSTATE_UINT32(mac_reg[VET], E1000State),
1044 VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
1045 VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
1046 VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
1047 VMSTATE_END_OF_LIST()
1048 }
1049};
balrog7c23b892008-02-03 02:20:18 +00001050
blueswir188b4e9d2008-10-02 18:24:21 +00001051static const uint16_t e1000_eeprom_template[64] = {
balrog7c23b892008-02-03 02:20:18 +00001052 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
1053 0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
1054 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700,
1055 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706,
1056 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff,
1057 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1058 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1059 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
1060};
1061
blueswir188b4e9d2008-10-02 18:24:21 +00001062static const uint16_t phy_reg_init[] = {
balrog7c23b892008-02-03 02:20:18 +00001063 [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up
1064 [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
1065 [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
1066 [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
1067 [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
aurel32700f6e22008-03-28 22:31:22 +00001068 [M88E1000_PHY_SPEC_STATUS] = 0xac00,
balrog7c23b892008-02-03 02:20:18 +00001069};
1070
blueswir188b4e9d2008-10-02 18:24:21 +00001071static const uint32_t mac_reg_init[] = {
balrog7c23b892008-02-03 02:20:18 +00001072 [PBA] = 0x00100030,
1073 [LEDCTL] = 0x602,
1074 [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
1075 E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
1076 [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
1077 E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
1078 E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
1079 E1000_STATUS_LU,
1080 [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
1081 E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
1082 E1000_MANC_RMCP_EN,
1083};
1084
1085/* PCI interface */
1086
balrog7c23b892008-02-03 02:20:18 +00001087static void
Avi Kivityad00a9b2011-08-08 16:09:08 +03001088e1000_mmio_setup(E1000State *d)
balrog7c23b892008-02-03 02:20:18 +00001089{
aliguorif65ed4c2008-12-09 20:09:57 +00001090 int i;
1091 const uint32_t excluded_regs[] = {
1092 E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
1093 E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
1094 };
1095
Avi Kivityad00a9b2011-08-08 16:09:08 +03001096 memory_region_init_io(&d->mmio, &e1000_mmio_ops, d, "e1000-mmio",
1097 PNPMMIO_SIZE);
1098 memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]);
aliguorif65ed4c2008-12-09 20:09:57 +00001099 for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
Avi Kivityad00a9b2011-08-08 16:09:08 +03001100 memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
1101 excluded_regs[i+1] - excluded_regs[i] - 4);
1102 memory_region_init_io(&d->io, &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
balrog7c23b892008-02-03 02:20:18 +00001103}
1104
aliguorib946a152009-04-17 17:11:08 +00001105static void
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001106e1000_cleanup(VLANClientState *nc)
aliguorib946a152009-04-17 17:11:08 +00001107{
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001108 E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
aliguorib946a152009-04-17 17:11:08 +00001109
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001110 s->nic = NULL;
aliguorib946a152009-04-17 17:11:08 +00001111}
1112
aliguori4b09be82009-02-11 15:21:22 +00001113static int
1114pci_e1000_uninit(PCIDevice *dev)
1115{
Juan Quintela7d9e52b2009-08-24 18:43:00 +02001116 E1000State *d = DO_UPCAST(E1000State, dev, dev);
aliguori4b09be82009-02-11 15:21:22 +00001117
Avi Kivityad00a9b2011-08-08 16:09:08 +03001118 memory_region_destroy(&d->mmio);
1119 memory_region_destroy(&d->io);
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001120 qemu_del_vlan_client(&d->nic->nc);
aliguori4b09be82009-02-11 15:21:22 +00001121 return 0;
1122}
1123
Blue Swirl32c86e92009-06-09 15:02:00 +00001124static void e1000_reset(void *opaque)
1125{
1126 E1000State *d = opaque;
1127
1128 memset(d->phy_reg, 0, sizeof d->phy_reg);
1129 memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
1130 memset(d->mac_reg, 0, sizeof d->mac_reg);
1131 memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
1132 d->rxbuf_min_shift = 1;
1133 memset(&d->tx, 0, sizeof d->tx);
1134}
1135
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001136static NetClientInfo net_e1000_info = {
1137 .type = NET_CLIENT_TYPE_NIC,
1138 .size = sizeof(NICState),
1139 .can_receive = e1000_can_receive,
1140 .receive = e1000_receive,
1141 .cleanup = e1000_cleanup,
1142 .link_status_changed = e1000_set_link_status,
1143};
1144
Gerd Hoffmann81a322d2009-08-14 10:36:05 +02001145static int pci_e1000_init(PCIDevice *pci_dev)
balrog7c23b892008-02-03 02:20:18 +00001146{
Juan Quintela7d9e52b2009-08-24 18:43:00 +02001147 E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
balrog7c23b892008-02-03 02:20:18 +00001148 uint8_t *pci_conf;
balrog7c23b892008-02-03 02:20:18 +00001149 uint16_t checksum = 0;
balrog7c23b892008-02-03 02:20:18 +00001150 int i;
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001151 uint8_t *macaddr;
Chris Wrightaff427a2008-04-21 16:02:48 -07001152
balrog7c23b892008-02-03 02:20:18 +00001153 pci_conf = d->dev.config;
balrog7c23b892008-02-03 02:20:18 +00001154
Michael S. Tsirkina9cbacb2009-12-10 15:23:59 +02001155 /* TODO: RST# value should be 0, PCI spec 6.2.4 */
1156 pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;
balrog7c23b892008-02-03 02:20:18 +00001157
Michael S. Tsirkin817e0b62011-09-11 13:40:23 +03001158 pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
balrog7c23b892008-02-03 02:20:18 +00001159
Avi Kivityad00a9b2011-08-08 16:09:08 +03001160 e1000_mmio_setup(d);
balrog7c23b892008-02-03 02:20:18 +00001161
Avi Kivitye824b2c2011-08-08 16:09:31 +03001162 pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
balrog7c23b892008-02-03 02:20:18 +00001163
Avi Kivitye824b2c2011-08-08 16:09:31 +03001164 pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
balrog7c23b892008-02-03 02:20:18 +00001165
balrog7c23b892008-02-03 02:20:18 +00001166 memmove(d->eeprom_data, e1000_eeprom_template,
1167 sizeof e1000_eeprom_template);
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001168 qemu_macaddr_default_if_unset(&d->conf.macaddr);
1169 macaddr = d->conf.macaddr.a;
balrog7c23b892008-02-03 02:20:18 +00001170 for (i = 0; i < 3; i++)
Paul Brook9d07d752009-05-14 22:35:07 +01001171 d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
balrog7c23b892008-02-03 02:20:18 +00001172 for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
1173 checksum += d->eeprom_data[i];
1174 checksum = (uint16_t) EEPROM_SUM - checksum;
1175 d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
1176
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001177 d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
1178 d->dev.qdev.info->name, d->dev.qdev.id, d);
balrog7c23b892008-02-03 02:20:18 +00001179
Mark McLoughlina03e2ae2009-11-25 18:49:12 +00001180 qemu_format_nic_info_str(&d->nic->nc, macaddr);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001181
1182 add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
1183
Gerd Hoffmann81a322d2009-08-14 10:36:05 +02001184 return 0;
balrog7c23b892008-02-03 02:20:18 +00001185}
Paul Brook9d07d752009-05-14 22:35:07 +01001186
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001187static void qdev_e1000_reset(DeviceState *dev)
1188{
1189 E1000State *d = DO_UPCAST(E1000State, dev.qdev, dev);
1190 e1000_reset(d);
1191}
1192
Gerd Hoffmann0aab0d32009-06-30 14:12:07 +02001193static PCIDeviceInfo e1000_info = {
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001194 .qdev.name = "e1000",
1195 .qdev.desc = "Intel Gigabit Ethernet",
1196 .qdev.size = sizeof(E1000State),
1197 .qdev.reset = qdev_e1000_reset,
Juan Quintelabe73cfe2009-12-02 12:36:46 +01001198 .qdev.vmsd = &vmstate_e1000,
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001199 .init = pci_e1000_init,
1200 .exit = pci_e1000_uninit,
Alex Williamson5ee8ad72011-04-18 11:46:01 -06001201 .romfile = "pxe-e1000.rom",
Isaku Yamahatae72d5c92011-05-25 10:58:09 +09001202 .vendor_id = PCI_VENDOR_ID_INTEL,
1203 .device_id = E1000_DEVID,
1204 .revision = 0x03,
1205 .class_id = PCI_CLASS_NETWORK_ETHERNET,
Gerd Hoffmannfbdaa002009-10-21 15:25:31 +02001206 .qdev.props = (Property[]) {
1207 DEFINE_NIC_PROPERTIES(E1000State, conf),
1208 DEFINE_PROP_END_OF_LIST(),
1209 }
Gerd Hoffmann0aab0d32009-06-30 14:12:07 +02001210};
1211
Paul Brook9d07d752009-05-14 22:35:07 +01001212static void e1000_register_devices(void)
1213{
Gerd Hoffmann0aab0d32009-06-30 14:12:07 +02001214 pci_qdev_register(&e1000_info);
Paul Brook9d07d752009-05-14 22:35:07 +01001215}
1216
1217device_init(e1000_register_devices)