uint32_t rxbuf_size;
uint32_t rxbuf_min_shift;
- int check_rxov;
struct e1000_tx {
unsigned char header[256];
unsigned char vlan_header[4];
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);
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
s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
s->mac_reg[RCTL]);
+ qemu_flush_queued_packets(&s->nic->nc);
}
static void
}
static void
-e1000_set_link_status(VLANClientState *nc)
+e1000_set_link_status(NetClientState *nc)
{
E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
uint32_t old_status = s->mac_reg[STATUS];
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 {
}
static int
-e1000_can_receive(VLANClientState *nc)
+e1000_can_receive(NetClientState *nc)
{
E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
}
static ssize_t
-e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
+e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
struct e1000_rx_desc desc;
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",
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);
+ }
}
static void
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
static void
-e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
E1000State *s = opaque;
}
static uint64_t
-e1000_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size)
+e1000_mmio_read(void *opaque, hwaddr addr, unsigned size)
{
E1000State *s = opaque;
unsigned int index = (addr & 0x1ffff) >> 2;
},
};
-static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr,
+static uint64_t e1000_io_read(void *opaque, hwaddr addr,
unsigned size)
{
E1000State *s = opaque;
return 0;
}
-static void e1000_io_write(void *opaque, target_phys_addr_t addr,
+static void e1000_io_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
E1000State *s = opaque;
return version_id == 1;
}
+static int e1000_post_load(void *opaque, int version_id)
+{
+ E1000State *s = opaque;
+
+ /* nc.link_down can't be migrated, so infer link_down according
+ * to link status bit in mac_reg[STATUS] */
+ s->nic->nc.link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
+
+ return 0;
+}
+
static const VMStateDescription vmstate_e1000 = {
.name = "e1000",
.version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .post_load = e1000_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, E1000State),
VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */
}
static void
-e1000_cleanup(VLANClientState *nc)
+e1000_cleanup(NetClientState *nc)
{
E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
s->nic = NULL;
}
-static int
+static void
pci_e1000_uninit(PCIDevice *dev)
{
E1000State *d = DO_UPCAST(E1000State, dev, dev);
qemu_free_timer(d->autoneg_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
- qemu_del_vlan_client(&d->nic->nc);
- return 0;
+ qemu_del_net_client(&d->nic->nc);
}
static NetClientInfo net_e1000_info = {
- .type = NET_CLIENT_TYPE_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = e1000_can_receive,
.receive = e1000_receive,