blob: 2d16774dada273254f7292e24247857764ed0469 [file] [log] [blame]
balrog7c23b892008-02-03 02:20:18 +00001/*
2 * QEMU e1000 emulation
3 *
4 * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
5 * Copyright (c) 2008 Qumranet
6 * Based on work done by:
7 * Copyright (c) 2007 Dan Aloni
8 * Copyright (c) 2004 Antony T Curtis
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
aurel32fad6cb12009-01-04 22:05:52 +000022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
balrog7c23b892008-02-03 02:20:18 +000023 */
24
25
26#include "hw.h"
27#include "pci.h"
28#include "net.h"
29
balrog7c23b892008-02-03 02:20:18 +000030#include "e1000_hw.h"
31
32#define DEBUG
33
34#ifdef DEBUG
35enum {
36 DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
37 DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
38 DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR,
39 DEBUG_RXFILTER, DEBUG_NOTYET,
40};
41#define DBGBIT(x) (1<<DEBUG_##x)
42static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
43
44#define DBGOUT(what, fmt, params...) do { \
45 if (debugflags & DBGBIT(what)) \
46 fprintf(stderr, "e1000: " fmt, ##params); \
47 } while (0)
48#else
49#define DBGOUT(what, fmt, params...) do {} while (0)
50#endif
51
52#define IOPORT_SIZE 0x40
aurel32e94bbef2008-03-10 00:02:10 +000053#define PNPMMIO_SIZE 0x20000
balrog7c23b892008-02-03 02:20:18 +000054
55/*
56 * HW models:
57 * E1000_DEV_ID_82540EM works with Windows and Linux
58 * E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
59 * appears to perform better than 82540EM, but breaks with Linux 2.6.18
60 * E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
61 * Others never tested
62 */
63enum { E1000_DEVID = E1000_DEV_ID_82540EM };
64
65/*
66 * May need to specify additional MAC-to-PHY entries --
67 * Intel's Windows driver refuses to initialize unless they match
68 */
69enum {
70 PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ? 0xcc2 :
71 E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ? 0xc30 :
72 /* default to E1000_DEV_ID_82540EM */ 0xc20
73};
74
75typedef struct E1000State_st {
76 PCIDevice dev;
77 VLANClientState *vc;
balrog7c23b892008-02-03 02:20:18 +000078 int mmio_index;
79
80 uint32_t mac_reg[0x8000];
81 uint16_t phy_reg[0x20];
82 uint16_t eeprom_data[64];
83
84 uint32_t rxbuf_size;
85 uint32_t rxbuf_min_shift;
86 int check_rxov;
87 struct e1000_tx {
88 unsigned char header[256];
aliguori8f2e8d12008-11-21 16:25:17 +000089 unsigned char vlan_header[4];
90 unsigned char vlan[4];
balrog7c23b892008-02-03 02:20:18 +000091 unsigned char data[0x10000];
92 uint16_t size;
93 unsigned char sum_needed;
aliguori8f2e8d12008-11-21 16:25:17 +000094 unsigned char vlan_needed;
balrog7c23b892008-02-03 02:20:18 +000095 uint8_t ipcss;
96 uint8_t ipcso;
97 uint16_t ipcse;
98 uint8_t tucss;
99 uint8_t tucso;
100 uint16_t tucse;
101 uint8_t hdr_len;
102 uint16_t mss;
103 uint32_t paylen;
104 uint16_t tso_frames;
105 char tse;
blueswir1b6c4f712008-10-02 19:14:17 +0000106 int8_t ip;
107 int8_t tcp;
balrog1b0009d2008-07-16 12:39:45 +0000108 char cptse; // current packet tse bit
balrog7c23b892008-02-03 02:20:18 +0000109 } tx;
110
111 struct {
112 uint32_t val_in; // shifted in from guest driver
113 uint16_t bitnum_in;
114 uint16_t bitnum_out;
115 uint16_t reading;
116 uint32_t old_eecd;
117 } eecd_state;
118} E1000State;
119
120#define defreg(x) x = (E1000_##x>>2)
121enum {
122 defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC),
123 defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC),
124 defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC),
125 defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH),
126 defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT),
127 defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH),
128 defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT),
129 defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL),
130 defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC),
aliguori8f2e8d12008-11-21 16:25:17 +0000131 defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA),
132 defreg(VET),
balrog7c23b892008-02-03 02:20:18 +0000133};
134
135enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
blueswir188b4e9d2008-10-02 18:24:21 +0000136static const char phy_regcap[0x20] = {
balrog7c23b892008-02-03 02:20:18 +0000137 [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
138 [PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW,
139 [PHY_CTRL] = PHY_RW, [PHY_1000T_CTRL] = PHY_RW,
140 [PHY_LP_ABILITY] = PHY_R, [PHY_1000T_STATUS] = PHY_R,
141 [PHY_AUTONEG_ADV] = PHY_RW, [M88E1000_RX_ERR_CNTR] = PHY_R,
aurel32700f6e22008-03-28 22:31:22 +0000142 [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R
balrog7c23b892008-02-03 02:20:18 +0000143};
144
145static void
146ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
147 uint32_t size, int type)
148{
149 DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
150}
151
152static void
153set_interrupt_cause(E1000State *s, int index, uint32_t val)
154{
155 if (val)
156 val |= E1000_ICR_INT_ASSERTED;
157 s->mac_reg[ICR] = val;
158 qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
159}
160
161static void
162set_ics(E1000State *s, int index, uint32_t val)
163{
164 DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR],
165 s->mac_reg[IMS]);
166 set_interrupt_cause(s, 0, val | s->mac_reg[ICR]);
167}
168
169static int
170rxbufsize(uint32_t v)
171{
172 v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
173 E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
174 E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
175 switch (v) {
176 case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
177 return 16384;
178 case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
179 return 8192;
180 case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
181 return 4096;
182 case E1000_RCTL_SZ_1024:
183 return 1024;
184 case E1000_RCTL_SZ_512:
185 return 512;
186 case E1000_RCTL_SZ_256:
187 return 256;
188 }
189 return 2048;
190}
191
192static void
193set_rx_control(E1000State *s, int index, uint32_t val)
194{
195 s->mac_reg[RCTL] = val;
196 s->rxbuf_size = rxbufsize(val);
197 s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
198 DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
199 s->mac_reg[RCTL]);
200}
201
202static void
203set_mdic(E1000State *s, int index, uint32_t val)
204{
205 uint32_t data = val & E1000_MDIC_DATA_MASK;
206 uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
207
208 if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy #
209 val = s->mac_reg[MDIC] | E1000_MDIC_ERROR;
210 else if (val & E1000_MDIC_OP_READ) {
211 DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr);
212 if (!(phy_regcap[addr] & PHY_R)) {
213 DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr);
214 val |= E1000_MDIC_ERROR;
215 } else
216 val = (val ^ data) | s->phy_reg[addr];
217 } else if (val & E1000_MDIC_OP_WRITE) {
218 DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data);
219 if (!(phy_regcap[addr] & PHY_W)) {
220 DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
221 val |= E1000_MDIC_ERROR;
222 } else
223 s->phy_reg[addr] = data;
224 }
225 s->mac_reg[MDIC] = val | E1000_MDIC_READY;
226 set_ics(s, 0, E1000_ICR_MDAC);
227}
228
229static uint32_t
230get_eecd(E1000State *s, int index)
231{
232 uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd;
233
234 DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n",
235 s->eecd_state.bitnum_out, s->eecd_state.reading);
236 if (!s->eecd_state.reading ||
237 ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >>
238 ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1)
239 ret |= E1000_EECD_DO;
240 return ret;
241}
242
243static void
244set_eecd(E1000State *s, int index, uint32_t val)
245{
246 uint32_t oldval = s->eecd_state.old_eecd;
247
248 s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS |
249 E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ);
250 if (!(E1000_EECD_SK & (val ^ oldval))) // no clock edge
251 return;
252 if (!(E1000_EECD_SK & val)) { // falling edge
253 s->eecd_state.bitnum_out++;
254 return;
255 }
256 if (!(val & E1000_EECD_CS)) { // rising, no CS (EEPROM reset)
257 memset(&s->eecd_state, 0, sizeof s->eecd_state);
258 return;
259 }
260 s->eecd_state.val_in <<= 1;
261 if (val & E1000_EECD_DI)
262 s->eecd_state.val_in |= 1;
263 if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) {
264 s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1;
265 s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) ==
266 EEPROM_READ_OPCODE_MICROWIRE);
267 }
268 DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n",
269 s->eecd_state.bitnum_in, s->eecd_state.bitnum_out,
270 s->eecd_state.reading);
271}
272
273static uint32_t
274flash_eerd_read(E1000State *s, int x)
275{
276 unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START;
277
278 if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG)
279 return 0;
280 return (s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
281 E1000_EEPROM_RW_REG_DONE | r;
282}
283
balrog7c23b892008-02-03 02:20:18 +0000284static void
285putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
286{
aliguoric6a6a5e2008-07-29 19:41:19 +0000287 uint32_t sum;
288
balrog7c23b892008-02-03 02:20:18 +0000289 if (cse && cse < n)
290 n = cse + 1;
aliguoric6a6a5e2008-07-29 19:41:19 +0000291 if (sloc < n-1) {
292 sum = net_checksum_add(n-css, data+css);
balrog7c23b892008-02-03 02:20:18 +0000293 cpu_to_be16wu((uint16_t *)(data + sloc),
aliguoric6a6a5e2008-07-29 19:41:19 +0000294 net_checksum_finish(sum));
295 }
balrog7c23b892008-02-03 02:20:18 +0000296}
297
aliguori8f2e8d12008-11-21 16:25:17 +0000298static inline int
299vlan_enabled(E1000State *s)
300{
301 return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0);
302}
303
304static inline int
305vlan_rx_filter_enabled(E1000State *s)
306{
307 return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0);
308}
309
310static inline int
311is_vlan_packet(E1000State *s, const uint8_t *buf)
312{
313 return (be16_to_cpup((uint16_t *)(buf + 12)) ==
314 le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
315}
316
317static inline int
318is_vlan_txd(uint32_t txd_lower)
319{
320 return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
321}
322
balrog7c23b892008-02-03 02:20:18 +0000323static void
324xmit_seg(E1000State *s)
325{
326 uint16_t len, *sp;
327 unsigned int frames = s->tx.tso_frames, css, sofar, n;
328 struct e1000_tx *tp = &s->tx;
329
balrog1b0009d2008-07-16 12:39:45 +0000330 if (tp->tse && tp->cptse) {
balrog7c23b892008-02-03 02:20:18 +0000331 css = tp->ipcss;
332 DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
333 frames, tp->size, css);
334 if (tp->ip) { // IPv4
335 cpu_to_be16wu((uint16_t *)(tp->data+css+2),
336 tp->size - css);
337 cpu_to_be16wu((uint16_t *)(tp->data+css+4),
338 be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
339 } else // IPv6
340 cpu_to_be16wu((uint16_t *)(tp->data+css+4),
341 tp->size - css);
342 css = tp->tucss;
343 len = tp->size - css;
344 DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
345 if (tp->tcp) {
346 sofar = frames * tp->mss;
347 cpu_to_be32wu((uint32_t *)(tp->data+css+4), // seq
aurel3288738c02008-03-28 22:30:48 +0000348 be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar);
balrog7c23b892008-02-03 02:20:18 +0000349 if (tp->paylen - sofar > tp->mss)
350 tp->data[css + 13] &= ~9; // PSH, FIN
351 } else // UDP
352 cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
353 if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
354 // add pseudo-header length before checksum calculation
355 sp = (uint16_t *)(tp->data + tp->tucso);
356 cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
357 }
358 tp->tso_frames++;
359 }
360
361 if (tp->sum_needed & E1000_TXD_POPTS_TXSM)
362 putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);
363 if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
364 putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
aliguori8f2e8d12008-11-21 16:25:17 +0000365 if (tp->vlan_needed) {
366 memmove(tp->vlan, tp->data, 12);
367 memcpy(tp->data + 8, tp->vlan_header, 4);
368 qemu_send_packet(s->vc, tp->vlan, tp->size + 4);
369 } else
370 qemu_send_packet(s->vc, tp->data, tp->size);
balrog7c23b892008-02-03 02:20:18 +0000371 s->mac_reg[TPT]++;
372 s->mac_reg[GPTC]++;
373 n = s->mac_reg[TOTL];
374 if ((s->mac_reg[TOTL] += s->tx.size) < n)
375 s->mac_reg[TOTH]++;
376}
377
378static void
379process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
380{
381 uint32_t txd_lower = le32_to_cpu(dp->lower.data);
382 uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
383 unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
384 unsigned int msh = 0xfffff, hdr = 0;
385 uint64_t addr;
386 struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
387 struct e1000_tx *tp = &s->tx;
388
389 if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor
390 op = le32_to_cpu(xp->cmd_and_length);
391 tp->ipcss = xp->lower_setup.ip_fields.ipcss;
392 tp->ipcso = xp->lower_setup.ip_fields.ipcso;
393 tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);
394 tp->tucss = xp->upper_setup.tcp_fields.tucss;
395 tp->tucso = xp->upper_setup.tcp_fields.tucso;
396 tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);
397 tp->paylen = op & 0xfffff;
398 tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;
399 tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);
400 tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
401 tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
402 tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
403 tp->tso_frames = 0;
404 if (tp->tucso == 0) { // this is probably wrong
405 DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
406 tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
407 }
408 return;
balrog1b0009d2008-07-16 12:39:45 +0000409 } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
410 // data descriptor
balrog7c23b892008-02-03 02:20:18 +0000411 tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
balrog1b0009d2008-07-16 12:39:45 +0000412 tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
413 } else
414 // legacy descriptor
415 tp->cptse = 0;
balrog7c23b892008-02-03 02:20:18 +0000416
aliguori8f2e8d12008-11-21 16:25:17 +0000417 if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
418 (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
419 tp->vlan_needed = 1;
420 cpu_to_be16wu((uint16_t *)(tp->vlan_header),
421 le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
422 cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2),
423 le16_to_cpu(dp->upper.fields.special));
424 }
425
balrog7c23b892008-02-03 02:20:18 +0000426 addr = le64_to_cpu(dp->buffer_addr);
balrog1b0009d2008-07-16 12:39:45 +0000427 if (tp->tse && tp->cptse) {
balrog7c23b892008-02-03 02:20:18 +0000428 hdr = tp->hdr_len;
429 msh = hdr + tp->mss;
balrog1b0009d2008-07-16 12:39:45 +0000430 do {
431 bytes = split_size;
432 if (tp->size + bytes > msh)
433 bytes = msh - tp->size;
434 cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
435 if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
436 memmove(tp->header, tp->data, hdr);
437 tp->size = sz;
438 addr += bytes;
439 if (sz == msh) {
440 xmit_seg(s);
441 memmove(tp->data, tp->header, hdr);
442 tp->size = hdr;
443 }
444 } while (split_size -= bytes);
445 } else if (!tp->tse && tp->cptse) {
446 // context descriptor TSE is not set, while data descriptor TSE is set
447 DBGOUT(TXERR, "TCP segmentaion Error\n");
448 } else {
449 cpu_physical_memory_read(addr, tp->data + tp->size, split_size);
450 tp->size += split_size;
balrog7c23b892008-02-03 02:20:18 +0000451 }
balrog7c23b892008-02-03 02:20:18 +0000452
453 if (!(txd_lower & E1000_TXD_CMD_EOP))
454 return;
balrog1b0009d2008-07-16 12:39:45 +0000455 if (!(tp->tse && tp->cptse && tp->size < hdr))
balrog7c23b892008-02-03 02:20:18 +0000456 xmit_seg(s);
457 tp->tso_frames = 0;
458 tp->sum_needed = 0;
aliguori8f2e8d12008-11-21 16:25:17 +0000459 tp->vlan_needed = 0;
balrog7c23b892008-02-03 02:20:18 +0000460 tp->size = 0;
balrog1b0009d2008-07-16 12:39:45 +0000461 tp->cptse = 0;
balrog7c23b892008-02-03 02:20:18 +0000462}
463
464static uint32_t
465txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp)
466{
467 uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
468
469 if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))
470 return 0;
471 txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
472 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
473 dp->upper.data = cpu_to_le32(txd_upper);
474 cpu_physical_memory_write(base + ((char *)&dp->upper - (char *)dp),
475 (void *)&dp->upper, sizeof(dp->upper));
476 return E1000_ICR_TXDW;
477}
478
479static void
480start_xmit(E1000State *s)
481{
482 target_phys_addr_t base;
483 struct e1000_tx_desc desc;
484 uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
485
486 if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) {
487 DBGOUT(TX, "tx disabled\n");
488 return;
489 }
490
491 while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
492 base = ((uint64_t)s->mac_reg[TDBAH] << 32) + s->mac_reg[TDBAL] +
493 sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
494 cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
495
496 DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
ths61060752008-05-13 14:35:34 +0000497 (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
balrog7c23b892008-02-03 02:20:18 +0000498 desc.upper.data);
499
500 process_tx_desc(s, &desc);
501 cause |= txdesc_writeback(base, &desc);
502
503 if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])
504 s->mac_reg[TDH] = 0;
505 /*
506 * the following could happen only if guest sw assigns
507 * bogus values to TDT/TDLEN.
508 * there's nothing too intelligent we could do about this.
509 */
510 if (s->mac_reg[TDH] == tdh_start) {
511 DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
512 tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
513 break;
514 }
515 }
516 set_ics(s, 0, cause);
517}
518
519static int
520receive_filter(E1000State *s, const uint8_t *buf, int size)
521{
522 static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
523 static int mta_shift[] = {4, 3, 2, 0};
524 uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
525
aliguori8f2e8d12008-11-21 16:25:17 +0000526 if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
527 uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14));
528 uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) +
529 ((vid >> 5) & 0x7f));
530 if ((vfta & (1 << (vid & 0x1f))) == 0)
531 return 0;
532 }
533
balrog7c23b892008-02-03 02:20:18 +0000534 if (rctl & E1000_RCTL_UPE) // promiscuous
535 return 1;
536
537 if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast
538 return 1;
539
540 if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast))
541 return 1;
542
543 for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {
544 if (!(rp[1] & E1000_RAH_AV))
545 continue;
546 ra[0] = cpu_to_le32(rp[0]);
547 ra[1] = cpu_to_le32(rp[1]);
548 if (!memcmp(buf, (uint8_t *)ra, 6)) {
549 DBGOUT(RXFILTER,
550 "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
551 (int)(rp - s->mac_reg - RA)/2,
552 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
553 return 1;
554 }
555 }
556 DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",
557 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
558
559 f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
560 f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
561 if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f)))
562 return 1;
563 DBGOUT(RXFILTER,
564 "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",
565 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
566 (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,
567 s->mac_reg[MTA + (f >> 5)]);
568
569 return 0;
570}
571
aliguori99ed7e32009-01-08 19:45:50 +0000572static void
573e1000_set_link_status(VLANClientState *vc)
574{
575 E1000State *s = vc->opaque;
576 uint32_t old_status = s->mac_reg[STATUS];
577
578 if (vc->link_down)
579 s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
580 else
581 s->mac_reg[STATUS] |= E1000_STATUS_LU;
582
583 if (s->mac_reg[STATUS] != old_status)
584 set_ics(s, 0, E1000_ICR_LSC);
585}
586
balrog7c23b892008-02-03 02:20:18 +0000587static int
588e1000_can_receive(void *opaque)
589{
590 E1000State *s = opaque;
591
aliguori4105de62008-08-06 14:11:44 +0000592 return (s->mac_reg[RCTL] & E1000_RCTL_EN);
balrog7c23b892008-02-03 02:20:18 +0000593}
594
595static void
596e1000_receive(void *opaque, const uint8_t *buf, int size)
597{
598 E1000State *s = opaque;
599 struct e1000_rx_desc desc;
600 target_phys_addr_t base;
601 unsigned int n, rdt;
602 uint32_t rdh_start;
aliguori8f2e8d12008-11-21 16:25:17 +0000603 uint16_t vlan_special = 0;
604 uint8_t vlan_status = 0, vlan_offset = 0;
balrog7c23b892008-02-03 02:20:18 +0000605
606 if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
607 return;
608
609 if (size > s->rxbuf_size) {
610 DBGOUT(RX, "packet too large for buffers (%d > %d)\n", size,
611 s->rxbuf_size);
612 return;
613 }
614
615 if (!receive_filter(s, buf, size))
616 return;
617
aliguori8f2e8d12008-11-21 16:25:17 +0000618 if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
619 vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
620 memmove((void *)(buf + 4), buf, 12);
621 vlan_status = E1000_RXD_STAT_VP;
622 vlan_offset = 4;
623 size -= 4;
624 }
625
balrog7c23b892008-02-03 02:20:18 +0000626 rdh_start = s->mac_reg[RDH];
627 size += 4; // for the header
628 do {
629 if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
630 set_ics(s, 0, E1000_ICS_RXO);
631 return;
632 }
633 base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +
634 sizeof(desc) * s->mac_reg[RDH];
635 cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
aliguori8f2e8d12008-11-21 16:25:17 +0000636 desc.special = vlan_special;
637 desc.status |= (vlan_status | E1000_RXD_STAT_DD);
balrog7c23b892008-02-03 02:20:18 +0000638 if (desc.buffer_addr) {
639 cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
aliguori8f2e8d12008-11-21 16:25:17 +0000640 (void *)(buf + vlan_offset), size);
balrog7c23b892008-02-03 02:20:18 +0000641 desc.length = cpu_to_le16(size);
642 desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
643 } else // as per intel docs; skip descriptors with null buf addr
644 DBGOUT(RX, "Null RX descriptor!!\n");
645 cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));
646
647 if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
648 s->mac_reg[RDH] = 0;
649 s->check_rxov = 1;
650 /* see comment in start_xmit; same here */
651 if (s->mac_reg[RDH] == rdh_start) {
652 DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
653 rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
654 set_ics(s, 0, E1000_ICS_RXO);
655 return;
656 }
657 } while (desc.buffer_addr == 0);
658
659 s->mac_reg[GPRC]++;
660 s->mac_reg[TPR]++;
661 n = s->mac_reg[TORL];
662 if ((s->mac_reg[TORL] += size) < n)
663 s->mac_reg[TORH]++;
664
665 n = E1000_ICS_RXT0;
666 if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
667 rdt += s->mac_reg[RDLEN] / sizeof(desc);
aliguoribf16cc82009-03-20 16:13:47 +0000668 if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
669 s->rxbuf_min_shift)
balrog7c23b892008-02-03 02:20:18 +0000670 n |= E1000_ICS_RXDMT0;
671
672 set_ics(s, 0, n);
673}
674
675static uint32_t
676mac_readreg(E1000State *s, int index)
677{
678 return s->mac_reg[index];
679}
680
681static uint32_t
682mac_icr_read(E1000State *s, int index)
683{
684 uint32_t ret = s->mac_reg[ICR];
685
686 DBGOUT(INTERRUPT, "ICR read: %x\n", ret);
687 set_interrupt_cause(s, 0, 0);
688 return ret;
689}
690
691static uint32_t
692mac_read_clr4(E1000State *s, int index)
693{
694 uint32_t ret = s->mac_reg[index];
695
696 s->mac_reg[index] = 0;
697 return ret;
698}
699
700static uint32_t
701mac_read_clr8(E1000State *s, int index)
702{
703 uint32_t ret = s->mac_reg[index];
704
705 s->mac_reg[index] = 0;
706 s->mac_reg[index-1] = 0;
707 return ret;
708}
709
710static void
711mac_writereg(E1000State *s, int index, uint32_t val)
712{
713 s->mac_reg[index] = val;
714}
715
716static void
717set_rdt(E1000State *s, int index, uint32_t val)
718{
719 s->check_rxov = 0;
720 s->mac_reg[index] = val & 0xffff;
721}
722
723static void
724set_16bit(E1000State *s, int index, uint32_t val)
725{
726 s->mac_reg[index] = val & 0xffff;
727}
728
729static void
730set_dlen(E1000State *s, int index, uint32_t val)
731{
732 s->mac_reg[index] = val & 0xfff80;
733}
734
735static void
736set_tctl(E1000State *s, int index, uint32_t val)
737{
738 s->mac_reg[index] = val;
739 s->mac_reg[TDT] &= 0xffff;
740 start_xmit(s);
741}
742
743static void
744set_icr(E1000State *s, int index, uint32_t val)
745{
746 DBGOUT(INTERRUPT, "set_icr %x\n", val);
747 set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val);
748}
749
750static void
751set_imc(E1000State *s, int index, uint32_t val)
752{
753 s->mac_reg[IMS] &= ~val;
754 set_ics(s, 0, 0);
755}
756
757static void
758set_ims(E1000State *s, int index, uint32_t val)
759{
760 s->mac_reg[IMS] |= val;
761 set_ics(s, 0, 0);
762}
763
764#define getreg(x) [x] = mac_readreg
765static uint32_t (*macreg_readops[])(E1000State *, int) = {
766 getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL),
767 getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL),
768 getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS),
769 getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL),
aliguori8f2e8d12008-11-21 16:25:17 +0000770 getreg(RDH), getreg(RDT), getreg(VET),
balrog7c23b892008-02-03 02:20:18 +0000771
772 [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
773 [GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4,
774 [ICR] = mac_icr_read, [EECD] = get_eecd, [EERD] = flash_eerd_read,
775 [CRCERRS ... MPC] = &mac_readreg,
776 [RA ... RA+31] = &mac_readreg,
777 [MTA ... MTA+127] = &mac_readreg,
aliguori8f2e8d12008-11-21 16:25:17 +0000778 [VFTA ... VFTA+127] = &mac_readreg,
balrog7c23b892008-02-03 02:20:18 +0000779};
malcb1503cd2008-12-22 20:33:55 +0000780enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
balrog7c23b892008-02-03 02:20:18 +0000781
782#define putreg(x) [x] = mac_writereg
783static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
784 putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC),
785 putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH),
aliguori8f2e8d12008-11-21 16:25:17 +0000786 putreg(RDBAL), putreg(LEDCTL), putreg(CTRL), putreg(VET),
balrog7c23b892008-02-03 02:20:18 +0000787 [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl,
788 [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics,
789 [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
790 [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
791 [EECD] = set_eecd, [RCTL] = set_rx_control,
792 [RA ... RA+31] = &mac_writereg,
793 [MTA ... MTA+127] = &mac_writereg,
aliguori8f2e8d12008-11-21 16:25:17 +0000794 [VFTA ... VFTA+127] = &mac_writereg,
balrog7c23b892008-02-03 02:20:18 +0000795};
malcb1503cd2008-12-22 20:33:55 +0000796enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
balrog7c23b892008-02-03 02:20:18 +0000797
798static void
799e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
800{
801 E1000State *s = opaque;
pbrook8da3ff12008-12-01 18:59:50 +0000802 unsigned int index = (addr & 0x1ffff) >> 2;
balrog7c23b892008-02-03 02:20:18 +0000803
aurel326b59fc72008-03-13 19:18:26 +0000804#ifdef TARGET_WORDS_BIGENDIAN
805 val = bswap32(val);
806#endif
balrog7c23b892008-02-03 02:20:18 +0000807 if (index < NWRITEOPS && macreg_writeops[index])
aurel326b59fc72008-03-13 19:18:26 +0000808 macreg_writeops[index](s, index, val);
balrog7c23b892008-02-03 02:20:18 +0000809 else if (index < NREADOPS && macreg_readops[index])
810 DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
811 else
812 DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
813 index<<2, val);
814}
815
816static void
817e1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
818{
819 // emulate hw without byte enables: no RMW
820 e1000_mmio_writel(opaque, addr & ~3,
aurel326b59fc72008-03-13 19:18:26 +0000821 (val & 0xffff) << (8*(addr & 3)));
balrog7c23b892008-02-03 02:20:18 +0000822}
823
824static void
825e1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
826{
827 // emulate hw without byte enables: no RMW
828 e1000_mmio_writel(opaque, addr & ~3,
aurel326b59fc72008-03-13 19:18:26 +0000829 (val & 0xff) << (8*(addr & 3)));
balrog7c23b892008-02-03 02:20:18 +0000830}
831
832static uint32_t
833e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
834{
835 E1000State *s = opaque;
pbrook8da3ff12008-12-01 18:59:50 +0000836 unsigned int index = (addr & 0x1ffff) >> 2;
balrog7c23b892008-02-03 02:20:18 +0000837
838 if (index < NREADOPS && macreg_readops[index])
aurel326b59fc72008-03-13 19:18:26 +0000839 {
840 uint32_t val = macreg_readops[index](s, index);
841#ifdef TARGET_WORDS_BIGENDIAN
842 val = bswap32(val);
843#endif
844 return val;
845 }
balrog7c23b892008-02-03 02:20:18 +0000846 DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2);
847 return 0;
848}
849
850static uint32_t
851e1000_mmio_readb(void *opaque, target_phys_addr_t addr)
852{
aurel326b59fc72008-03-13 19:18:26 +0000853 return ((e1000_mmio_readl(opaque, addr & ~3)) >>
balrog7c23b892008-02-03 02:20:18 +0000854 (8 * (addr & 3))) & 0xff;
855}
856
857static uint32_t
858e1000_mmio_readw(void *opaque, target_phys_addr_t addr)
859{
aurel326b59fc72008-03-13 19:18:26 +0000860 return ((e1000_mmio_readl(opaque, addr & ~3)) >>
861 (8 * (addr & 3))) & 0xffff;
balrog7c23b892008-02-03 02:20:18 +0000862}
863
blueswir188b4e9d2008-10-02 18:24:21 +0000864static const int mac_regtosave[] = {
balrog7c23b892008-02-03 02:20:18 +0000865 CTRL, EECD, EERD, GPRC, GPTC, ICR, ICS, IMC, IMS,
866 LEDCTL, MANC, MDIC, MPC, PBA, RCTL, RDBAH, RDBAL, RDH,
867 RDLEN, RDT, STATUS, SWSM, TCTL, TDBAH, TDBAL, TDH, TDLEN,
868 TDT, TORH, TORL, TOTH, TOTL, TPR, TPT, TXDCTL, WUFC,
aliguori8f2e8d12008-11-21 16:25:17 +0000869 VET,
balrog7c23b892008-02-03 02:20:18 +0000870};
malcb1503cd2008-12-22 20:33:55 +0000871enum { MAC_NSAVE = ARRAY_SIZE(mac_regtosave) };
balrog7c23b892008-02-03 02:20:18 +0000872
blueswir188b4e9d2008-10-02 18:24:21 +0000873static const struct {
balrog7c23b892008-02-03 02:20:18 +0000874 int size;
875 int array0;
aliguori8f2e8d12008-11-21 16:25:17 +0000876} mac_regarraystosave[] = { {32, RA}, {128, MTA}, {128, VFTA} };
malcb1503cd2008-12-22 20:33:55 +0000877enum { MAC_NARRAYS = ARRAY_SIZE(mac_regarraystosave) };
balrog7c23b892008-02-03 02:20:18 +0000878
879static void
880nic_save(QEMUFile *f, void *opaque)
881{
882 E1000State *s = (E1000State *)opaque;
883 int i, j;
884
885 pci_device_save(&s->dev, f);
pbrook8da3ff12008-12-01 18:59:50 +0000886 qemu_put_be32(f, 0);
balrog7c23b892008-02-03 02:20:18 +0000887 qemu_put_be32s(f, &s->rxbuf_size);
888 qemu_put_be32s(f, &s->rxbuf_min_shift);
889 qemu_put_be32s(f, &s->eecd_state.val_in);
890 qemu_put_be16s(f, &s->eecd_state.bitnum_in);
891 qemu_put_be16s(f, &s->eecd_state.bitnum_out);
892 qemu_put_be16s(f, &s->eecd_state.reading);
893 qemu_put_be32s(f, &s->eecd_state.old_eecd);
894 qemu_put_8s(f, &s->tx.ipcss);
895 qemu_put_8s(f, &s->tx.ipcso);
896 qemu_put_be16s(f, &s->tx.ipcse);
897 qemu_put_8s(f, &s->tx.tucss);
898 qemu_put_8s(f, &s->tx.tucso);
899 qemu_put_be16s(f, &s->tx.tucse);
900 qemu_put_be32s(f, &s->tx.paylen);
901 qemu_put_8s(f, &s->tx.hdr_len);
902 qemu_put_be16s(f, &s->tx.mss);
903 qemu_put_be16s(f, &s->tx.size);
904 qemu_put_be16s(f, &s->tx.tso_frames);
905 qemu_put_8s(f, &s->tx.sum_needed);
blueswir1b6c4f712008-10-02 19:14:17 +0000906 qemu_put_s8s(f, &s->tx.ip);
907 qemu_put_s8s(f, &s->tx.tcp);
balrog7c23b892008-02-03 02:20:18 +0000908 qemu_put_buffer(f, s->tx.header, sizeof s->tx.header);
909 qemu_put_buffer(f, s->tx.data, sizeof s->tx.data);
910 for (i = 0; i < 64; i++)
911 qemu_put_be16s(f, s->eeprom_data + i);
912 for (i = 0; i < 0x20; i++)
913 qemu_put_be16s(f, s->phy_reg + i);
914 for (i = 0; i < MAC_NSAVE; i++)
915 qemu_put_be32s(f, s->mac_reg + mac_regtosave[i]);
916 for (i = 0; i < MAC_NARRAYS; i++)
917 for (j = 0; j < mac_regarraystosave[i].size; j++)
918 qemu_put_be32s(f,
919 s->mac_reg + mac_regarraystosave[i].array0 + j);
920}
921
922static int
923nic_load(QEMUFile *f, void *opaque, int version_id)
924{
925 E1000State *s = (E1000State *)opaque;
926 int i, j, ret;
927
928 if ((ret = pci_device_load(&s->dev, f)) < 0)
929 return ret;
ths18fdb1c2008-07-18 18:02:34 +0000930 if (version_id == 1)
blueswir1b6c4f712008-10-02 19:14:17 +0000931 qemu_get_sbe32s(f, &i); /* once some unused instance id */
pbrook8da3ff12008-12-01 18:59:50 +0000932 qemu_get_be32(f); /* Ignored. Was mmio_base. */
balrog7c23b892008-02-03 02:20:18 +0000933 qemu_get_be32s(f, &s->rxbuf_size);
934 qemu_get_be32s(f, &s->rxbuf_min_shift);
935 qemu_get_be32s(f, &s->eecd_state.val_in);
936 qemu_get_be16s(f, &s->eecd_state.bitnum_in);
937 qemu_get_be16s(f, &s->eecd_state.bitnum_out);
938 qemu_get_be16s(f, &s->eecd_state.reading);
939 qemu_get_be32s(f, &s->eecd_state.old_eecd);
940 qemu_get_8s(f, &s->tx.ipcss);
941 qemu_get_8s(f, &s->tx.ipcso);
942 qemu_get_be16s(f, &s->tx.ipcse);
943 qemu_get_8s(f, &s->tx.tucss);
944 qemu_get_8s(f, &s->tx.tucso);
945 qemu_get_be16s(f, &s->tx.tucse);
946 qemu_get_be32s(f, &s->tx.paylen);
947 qemu_get_8s(f, &s->tx.hdr_len);
948 qemu_get_be16s(f, &s->tx.mss);
949 qemu_get_be16s(f, &s->tx.size);
950 qemu_get_be16s(f, &s->tx.tso_frames);
951 qemu_get_8s(f, &s->tx.sum_needed);
blueswir1b6c4f712008-10-02 19:14:17 +0000952 qemu_get_s8s(f, &s->tx.ip);
953 qemu_get_s8s(f, &s->tx.tcp);
balrog7c23b892008-02-03 02:20:18 +0000954 qemu_get_buffer(f, s->tx.header, sizeof s->tx.header);
955 qemu_get_buffer(f, s->tx.data, sizeof s->tx.data);
956 for (i = 0; i < 64; i++)
957 qemu_get_be16s(f, s->eeprom_data + i);
958 for (i = 0; i < 0x20; i++)
959 qemu_get_be16s(f, s->phy_reg + i);
960 for (i = 0; i < MAC_NSAVE; i++)
961 qemu_get_be32s(f, s->mac_reg + mac_regtosave[i]);
962 for (i = 0; i < MAC_NARRAYS; i++)
963 for (j = 0; j < mac_regarraystosave[i].size; j++)
964 qemu_get_be32s(f,
965 s->mac_reg + mac_regarraystosave[i].array0 + j);
966 return 0;
967}
968
blueswir188b4e9d2008-10-02 18:24:21 +0000969static const uint16_t e1000_eeprom_template[64] = {
balrog7c23b892008-02-03 02:20:18 +0000970 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
971 0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
972 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700,
973 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706,
974 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff,
975 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
976 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
977 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
978};
979
blueswir188b4e9d2008-10-02 18:24:21 +0000980static const uint16_t phy_reg_init[] = {
balrog7c23b892008-02-03 02:20:18 +0000981 [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up
982 [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
983 [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
984 [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
985 [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
aurel32700f6e22008-03-28 22:31:22 +0000986 [M88E1000_PHY_SPEC_STATUS] = 0xac00,
balrog7c23b892008-02-03 02:20:18 +0000987};
988
blueswir188b4e9d2008-10-02 18:24:21 +0000989static const uint32_t mac_reg_init[] = {
balrog7c23b892008-02-03 02:20:18 +0000990 [PBA] = 0x00100030,
991 [LEDCTL] = 0x602,
992 [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
993 E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
994 [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
995 E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
996 E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
997 E1000_STATUS_LU,
998 [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
999 E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
1000 E1000_MANC_RMCP_EN,
1001};
1002
1003/* PCI interface */
1004
1005static CPUWriteMemoryFunc *e1000_mmio_write[] = {
1006 e1000_mmio_writeb, e1000_mmio_writew, e1000_mmio_writel
1007};
1008
1009static CPUReadMemoryFunc *e1000_mmio_read[] = {
1010 e1000_mmio_readb, e1000_mmio_readw, e1000_mmio_readl
1011};
1012
1013static void
1014e1000_mmio_map(PCIDevice *pci_dev, int region_num,
1015 uint32_t addr, uint32_t size, int type)
1016{
1017 E1000State *d = (E1000State *)pci_dev;
aliguorif65ed4c2008-12-09 20:09:57 +00001018 int i;
1019 const uint32_t excluded_regs[] = {
1020 E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
1021 E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
1022 };
1023
balrog7c23b892008-02-03 02:20:18 +00001024
1025 DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
1026
balrog7c23b892008-02-03 02:20:18 +00001027 cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
aliguorif65ed4c2008-12-09 20:09:57 +00001028 qemu_register_coalesced_mmio(addr, excluded_regs[0]);
1029
1030 for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
1031 qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4,
1032 excluded_regs[i + 1] -
1033 excluded_regs[i] - 4);
balrog7c23b892008-02-03 02:20:18 +00001034}
1035
aliguori4b09be82009-02-11 15:21:22 +00001036static int
1037pci_e1000_uninit(PCIDevice *dev)
1038{
1039 E1000State *d = (E1000State *) dev;
1040
1041 cpu_unregister_io_memory(d->mmio_index);
1042
1043 return 0;
1044}
1045
aliguori72da4202009-02-11 15:19:52 +00001046PCIDevice *
balrog7c23b892008-02-03 02:20:18 +00001047pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
1048{
1049 E1000State *d;
1050 uint8_t *pci_conf;
balrog7c23b892008-02-03 02:20:18 +00001051 uint16_t checksum = 0;
blueswir17ccfb2e2008-09-14 06:45:34 +00001052 static const char info_str[] = "e1000";
balrog7c23b892008-02-03 02:20:18 +00001053 int i;
1054
1055 d = (E1000State *)pci_register_device(bus, "e1000",
1056 sizeof(E1000State), devfn, NULL, NULL);
1057
1058 pci_conf = d->dev.config;
1059 memset(pci_conf, 0, 256);
1060
aliguorideb54392009-01-26 15:37:35 +00001061 pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
1062 pci_config_set_device_id(pci_conf, E1000_DEVID);
balrog7c23b892008-02-03 02:20:18 +00001063 *(uint16_t *)(pci_conf+0x04) = cpu_to_le16(0x0407);
1064 *(uint16_t *)(pci_conf+0x06) = cpu_to_le16(0x0010);
1065 pci_conf[0x08] = 0x03;
blueswir1173a5432009-02-01 19:26:20 +00001066 pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
balrog7c23b892008-02-03 02:20:18 +00001067 pci_conf[0x0c] = 0x10;
1068
1069 pci_conf[0x3d] = 1; // interrupt pin 0
1070
1071 d->mmio_index = cpu_register_io_memory(0, e1000_mmio_read,
1072 e1000_mmio_write, d);
1073
1074 pci_register_io_region((PCIDevice *)d, 0, PNPMMIO_SIZE,
1075 PCI_ADDRESS_SPACE_MEM, e1000_mmio_map);
1076
1077 pci_register_io_region((PCIDevice *)d, 1, IOPORT_SIZE,
1078 PCI_ADDRESS_SPACE_IO, ioport_map);
1079
balrog7c23b892008-02-03 02:20:18 +00001080 memmove(d->eeprom_data, e1000_eeprom_template,
1081 sizeof e1000_eeprom_template);
1082 for (i = 0; i < 3; i++)
1083 d->eeprom_data[i] = (nd->macaddr[2*i+1]<<8) | nd->macaddr[2*i];
1084 for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
1085 checksum += d->eeprom_data[i];
1086 checksum = (uint16_t) EEPROM_SUM - checksum;
1087 d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
1088
1089 memset(d->phy_reg, 0, sizeof d->phy_reg);
1090 memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
1091 memset(d->mac_reg, 0, sizeof d->mac_reg);
1092 memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
1093 d->rxbuf_min_shift = 1;
1094 memset(&d->tx, 0, sizeof d->tx);
1095
aliguori7a9f6e42009-01-07 17:48:51 +00001096 d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
aliguoribf38c1a2009-01-07 17:42:25 +00001097 e1000_receive, e1000_can_receive, d);
aliguori99ed7e32009-01-08 19:45:50 +00001098 d->vc->link_status_changed = e1000_set_link_status;
balrog7c23b892008-02-03 02:20:18 +00001099
aliguoriad067142009-04-17 17:10:56 +00001100 qemu_format_nic_info_str(d->vc, nd->macaddr);
balrog7c23b892008-02-03 02:20:18 +00001101
ths18fdb1c2008-07-18 18:02:34 +00001102 register_savevm(info_str, -1, 2, nic_save, nic_load, d);
aliguori4b09be82009-02-11 15:21:22 +00001103 d->dev.unregister = pci_e1000_uninit;
aliguori72da4202009-02-11 15:19:52 +00001104
1105 return (PCIDevice *)d;
balrog7c23b892008-02-03 02:20:18 +00001106}