#include "qemu/timer.h"
#include "net/net.h"
#include "net/eth.h"
-#include "hw/loader.h"
#include "sysemu/sysemu.h"
-#include "qemu/iov.h"
/* debug RTL8139 card */
//#define DEBUG_RTL8139 1
return size;
}
- int mcast_idx = compute_mcast_idx(buf);
+ int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
{
s->RxBufAddr = 0;
}
+static void rtl8139_reset_phy(RTL8139State *s)
+{
+ s->BasicModeStatus = 0x7809;
+ s->BasicModeStatus |= 0x0020; /* autonegotiation completed */
+ /* preserve link state */
+ s->BasicModeStatus |= qemu_get_queue(s->nic)->link_down ? 0 : 0x04;
+
+ s->NWayAdvert = 0x05e1; /* all modes, full duplex */
+ s->NWayLPAR = 0x05e1; /* all modes, full duplex */
+ s->NWayExpansion = 0x0001; /* autonegotiation supported */
+
+ s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
+}
+
static void rtl8139_reset(DeviceState *d)
{
RTL8139State *s = RTL8139(d);
s->Config3 = 0x1; /* fast back-to-back compatible */
s->Config5 = 0x0;
- s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
-
s->CpCmd = 0x0; /* reset C+ mode */
s->cplus_enabled = 0;
-
// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation
// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex
s->BasicModeCtrl = 0x1000; // autonegotiation
- s->BasicModeStatus = 0x7809;
- //s->BasicModeStatus |= 0x0040; /* UTP medium */
- s->BasicModeStatus |= 0x0020; /* autonegotiation completed */
- /* preserve link state */
- s->BasicModeStatus |= qemu_get_queue(s->nic)->link_down ? 0 : 0x04;
-
- s->NWayAdvert = 0x05e1; /* all modes, full duplex */
- s->NWayLPAR = 0x05e1; /* all modes, full duplex */
- s->NWayExpansion = 0x0001; /* autonegotiation supported */
+ rtl8139_reset_phy(s);
/* also reset timer and disable timer interrupt */
s->TCTR = 0;
DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val);
/* mask unwritable bits */
- uint32_t mask = 0x4cff;
+ uint32_t mask = 0xccff;
if (1 || !rtl8139_config_writable(s))
{
mask |= 0x0100;
}
+ if (val & 0x8000) {
+ /* Reset PHY */
+ rtl8139_reset_phy(s);
+ }
+
val = SET_MASKED(val, mask, s->BasicModeCtrl);
s->BasicModeCtrl = val;
{
int txcount = 0;
- while (rtl8139_cplus_transmit_one(s))
+ while (txcount < 64 && rtl8139_cplus_transmit_one(s))
{
++txcount;
}
/* */
-static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val)
-{
- rtl8139_io_writeb(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_mmio_writew(void *opaque, hwaddr addr, uint32_t val)
-{
- rtl8139_io_writew(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_mmio_writel(void *opaque, hwaddr addr, uint32_t val)
-{
- rtl8139_io_writel(opaque, addr & 0xFF, val);
-}
-
-static uint32_t rtl8139_mmio_readb(void *opaque, hwaddr addr)
-{
- return rtl8139_io_readb(opaque, addr & 0xFF);
-}
-
-static uint32_t rtl8139_mmio_readw(void *opaque, hwaddr addr)
-{
- uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF);
- return val;
-}
-
-static uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr)
-{
- uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF);
- return val;
-}
-
static int rtl8139_post_load(void *opaque, int version_id)
{
RTL8139State* s = opaque;
}
};
-static void rtl8139_pre_save(void *opaque)
+static int rtl8139_pre_save(void *opaque)
{
RTL8139State* s = opaque;
int64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* for migration to older versions */
s->TCTR = (current_time - s->TCTR_base) / PCI_PERIOD;
s->rtl8139_mmio_io_addr_dummy = 0;
+
+ return 0;
}
static const VMStateDescription vmstate_rtl8139 = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static const MemoryRegionOps rtl8139_mmio_ops = {
- .old_mmio = {
- .read = {
- rtl8139_mmio_readb,
- rtl8139_mmio_readw,
- rtl8139_mmio_readl,
- },
- .write = {
- rtl8139_mmio_writeb,
- rtl8139_mmio_writew,
- rtl8139_mmio_writel,
- },
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
static void rtl8139_timer(void *opaque)
{
RTL8139State *s = opaque;
memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s,
"rtl8139", 0x100);
- memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s,
- "rtl8139", 0x100);
+ memory_region_init_alias(&s->bar_mem, OBJECT(s), "rtl8139-mem", &s->bar_io,
+ 0, 0x100);
+
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
.instance_size = sizeof(RTL8139State),
.class_init = rtl8139_class_init,
.instance_init = rtl8139_instance_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+ },
};
static void rtl8139_register_types(void)