From e5b8b0d4ba29fe1268ba049519a1b0cf8552a21a Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Fri, 19 Oct 2012 07:56:55 +0200 Subject: e1000: drop check_rxov, always treat RX ring with RDH == RDT as empty Real HW always treats RX ring with RDH == RDT as empty. Emulation is supposed to behave the same. Reported-by: Chris Webb Reported-by: Richard Davies Signed-off-by: Dmitry Fleytman Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/e1000.c b/hw/e1000.c index e4f1ffef74..ec32f591af 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -92,7 +92,6 @@ typedef struct E1000State_st { uint32_t rxbuf_size; uint32_t rxbuf_min_shift; - int check_rxov; struct e1000_tx { unsigned char header[256]; unsigned char vlan_header[4]; @@ -741,11 +740,11 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size) int bufs; /* Fast-path short packets */ if (total_size <= s->rxbuf_size) { - return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov; + return s->mac_reg[RDH] != s->mac_reg[RDT]; } if (s->mac_reg[RDH] < s->mac_reg[RDT]) { bufs = s->mac_reg[RDT] - s->mac_reg[RDH]; - } else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) { + } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) { bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + s->mac_reg[RDT] - s->mac_reg[RDH]; } else { @@ -848,7 +847,6 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) s->mac_reg[RDH] = 0; - s->check_rxov = 1; /* see comment in start_xmit; same here */ if (s->mac_reg[RDH] == rdh_start) { DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", @@ -925,7 +923,6 @@ mac_writereg(E1000State *s, int index, uint32_t val) static void set_rdt(E1000State *s, int index, uint32_t val) { - s->check_rxov = 0; s->mac_reg[index] = val & 0xffff; if (e1000_has_rxbufs(s, 1)) { qemu_flush_queued_packets(&s->nic->nc); -- cgit v1.2.3 From 372254c6e5c078fb13b236bb648d2b9b2b0c70f1 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 31 Oct 2012 14:15:39 -0400 Subject: e1000: pre-initialize RAH/RAL registers Some guest operating systems' drivers (Mac OS X in particular) fail to properly initialize the Receive Address registers (probably expecting them to be pre-initialized by an earlier component, such as a specific proprietary BIOS). This patch pre-initializes the RA registers, allowing OS X networking to function properly. Other guest operating systems are not affected, and free to (re)initialize these registers during boot. [According to the datasheet the Address Valid bits in the RA registers are cleared on PCI or software reset. This patch adds the NIC's MAC address and sets Address Valid on reset. So we diverge from real hardware behavior here. -- Stefan] Signed-off-by: Gabriel Somlo Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'hw') diff --git a/hw/e1000.c b/hw/e1000.c index ec32f591af..cb7e7e8366 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -265,6 +265,8 @@ rxbufsize(uint32_t v) static void e1000_reset(void *opaque) { E1000State *d = opaque; + uint8_t *macaddr = d->conf.macaddr.a; + int i; qemu_del_timer(d->autoneg_timer); memset(d->phy_reg, 0, sizeof d->phy_reg); @@ -277,6 +279,14 @@ static void e1000_reset(void *opaque) if (d->nic->nc.link_down) { e1000_link_down(d); } + + /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */ + d->mac_reg[RA] = 0; + d->mac_reg[RA + 1] = E1000_RAH_AV; + for (i = 0; i < 4; i++) { + d->mac_reg[RA] |= macaddr[i] << (8 * i); + d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0; + } } static void -- cgit v1.2.3