#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
#include "qemu/iov.h"
+#include "qemu/range.h"
#include "e1000_regs.h"
{
s->mac_reg[STATUS] |= E1000_STATUS_LU;
s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+
+ /* E1000_STATUS_LU is tested by e1000_can_receive() */
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
static bool
is_vlan_packet(E1000State *s, const uint8_t *buf)
{
return (be16_to_cpup((uint16_t *)(buf + 12)) ==
- le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
+ le16_to_cpu(s->mac_reg[VET]));
}
static inline int
(tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
tp->vlan_needed = 1;
stw_be_p(tp->vlan_header,
- le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
+ le16_to_cpu(s->mac_reg[VET]));
stw_be_p(tp->vlan_header + 2,
le16_to_cpu(dp->upper.fields.special));
}
memmove(tp->data, tp->header, tp->hdr_len);
tp->size = tp->hdr_len;
}
- } while (split_size -= bytes);
+ split_size -= bytes;
+ } while (bytes && split_size);
} else if (!tp->tse && tp->cptse) {
// context descriptor TSE is not set, while data descriptor TSE is set
DBGOUT(TXERR, "TCP segmentation error\n");
E1000State *s = qemu_get_nic_opaque(nc);
return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
- (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+ (s->mac_reg[RCTL] & E1000_RCTL_EN) &&
+ (s->parent_obj.config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
+ e1000_has_rxbufs(s, 1);
}
static uint64_t rx_desc_base(E1000State *s)
.name = "e1000/mit_state",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = e1000_mit_state_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(mac_reg[RDTR], E1000State),
VMSTATE_UINT32(mac_reg[RADV], E1000State),
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_e1000_mit_state,
- .needed = e1000_mit_state_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_e1000_mit_state,
+ NULL
}
};
memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
}
-static void
-e1000_cleanup(NetClientState *nc)
-{
- E1000State *s = qemu_get_nic_opaque(nc);
-
- s->nic = NULL;
-}
-
static void
pci_e1000_uninit(PCIDevice *dev)
{
timer_free(d->autoneg_timer);
timer_del(d->mit_timer);
timer_free(d->mit_timer);
- memory_region_destroy(&d->mmio);
- memory_region_destroy(&d->io);
qemu_del_nic(d->nic);
}
.can_receive = e1000_can_receive,
.receive = e1000_receive,
.receive_iov = e1000_receive_iov,
- .cleanup = e1000_cleanup,
.link_status_changed = e1000_set_link_status,
};
-static int pci_e1000_init(PCIDevice *pci_dev)
+static void e1000_write_config(PCIDevice *pci_dev, uint32_t address,
+ uint32_t val, int len)
+{
+ E1000State *s = E1000(pci_dev);
+
+ pci_default_write_config(pci_dev, address, val, len);
+
+ if (range_covers_byte(address, len, PCI_COMMAND) &&
+ (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ }
+}
+
+
+static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
{
DeviceState *dev = DEVICE(pci_dev);
E1000State *d = E1000(pci_dev);
int i;
uint8_t *macaddr;
+ pci_dev->config_write = e1000_write_config;
+
pci_conf = pci_dev->config;
/* TODO: RST# value should be 0, PCI spec 6.2.4 */
qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
- add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
-
d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
-
- return 0;
}
static void qdev_e1000_reset(DeviceState *dev)
E1000BaseClass *e = E1000_DEVICE_CLASS(klass);
const E1000Info *info = data;
- k->init = pci_e1000_init;
+ k->realize = pci_e1000_realize;
k->exit = pci_e1000_uninit;
k->romfile = "efi-e1000.rom";
k->vendor_id = PCI_VENDOR_ID_INTEL;
dc->props = e1000_properties;
}
+static void e1000_instance_init(Object *obj)
+{
+ E1000State *n = E1000(obj);
+ device_add_bootindex_property(obj, &n->conf.bootindex,
+ "bootindex", "/ethernet-phy@0",
+ DEVICE(n), NULL);
+}
+
static const TypeInfo e1000_base_info = {
.name = TYPE_E1000_BASE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(E1000State),
+ .instance_init = e1000_instance_init,
.class_size = sizeof(E1000BaseClass),
.abstract = true,
};
type_info.parent = TYPE_E1000_BASE;
type_info.class_data = (void *)info;
type_info.class_init = e1000_class_init;
+ type_info.instance_init = e1000_instance_init;
type_register(&type_info);
}