#include "qemu/log.h"
#include "net/net.h"
#include "net/checksum.h"
-#include "qapi/qmp/qerror.h"
#include "hw/stream.h"
r |= 1;
break;
case 17:
- /* Marvel PHY on many xilinx boards. */
+ /* Marvell PHY on many xilinx boards. */
r = 0x8000; /* 1000Mb */
break;
case 18:
phy->regs[regnum] = data;
break;
}
+
+ /* Unconditionally clear regs[BMCR][BMCR_RESET] */
+ phy->regs[0] &= ~0x8000;
}
static void
uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
uint32_t rxappsize;
+
+ /* Whether axienet_eth_rx_notify should flush incoming queue. */
+ bool need_flush;
};
static void axienet_rx_reset(XilinxAXIEnet *s)
break;
case R_MC:
- value &= ((1 < 7) - 1);
+ value &= ((1 << 7) - 1);
/* Enable the MII. */
if (value & MC_EN) {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static int eth_can_rx(NetClientState *nc)
+static int eth_can_rx(XilinxAXIEnet *s)
{
- XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
-
/* RX enabled? */
return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
}
s->rxpos += ret;
if (!s->rxsize) {
s->regs[R_IS] |= IS_RX_COMPLETE;
+ if (s->need_flush) {
+ s->need_flush = false;
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ }
}
}
enet_update_irq(s);
DENET(qemu_log("%s: %zd bytes\n", __func__, size));
+ if (!eth_can_rx(s)) {
+ s->need_flush = true;
+ return 0;
+ }
+
unicast = ~buf[0] & 0x1;
broadcast = memcmp(buf, sa_bcast, 6) == 0;
multicast = !unicast && !broadcast;
return size;
}
-static void eth_cleanup(NetClientState *nc)
-{
- /* FIXME. */
- XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
- g_free(s->rxmem);
- g_free(s);
-}
-
static size_t
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
{
static NetClientInfo net_xilinx_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = eth_can_rx,
.receive = eth_rx,
- .cleanup = eth_cleanup,
};
static void xilinx_enet_realize(DeviceState *dev, Error **errp)
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev);
XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(
&s->rx_control_dev);
- Error *local_errp = NULL;
+ Error *local_err = NULL;
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
- (Object **) &ds->enet, &local_errp);
+ (Object **) &ds->enet,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &local_err);
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
- (Object **) &cs->enet, &local_errp);
- if (local_errp) {
+ (Object **) &cs->enet,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &local_err);
+ if (local_err) {
goto xilinx_enet_realize_fail;
}
- object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_errp);
- object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_errp);
- if (local_errp) {
+ object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_err);
+ object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_err);
+ if (local_err) {
goto xilinx_enet_realize_fail;
}
xilinx_enet_realize_fail:
if (!*errp) {
- *errp = local_errp;
+ *errp = local_err;
}
}
{
XilinxAXIEnet *s = XILINX_AXI_ENET(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
- (Object **) &s->tx_data_dev, &errp);
- assert_no_error(errp);
+ (Object **) &s->tx_data_dev,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
object_property_add_link(obj, "axistream-control-connected",
TYPE_STREAM_SLAVE,
- (Object **) &s->tx_control_dev, &errp);
- assert_no_error(errp);
-
- object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM);
- object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_ENET_CONTROL_STREAM);
+ (Object **) &s->tx_control_dev,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
+
+ object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
+ TYPE_XILINX_AXI_ENET_DATA_STREAM);
+ object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev),
+ TYPE_XILINX_AXI_ENET_CONTROL_STREAM);
object_property_add_child(OBJECT(s), "axistream-connected-target",
- (Object *)&s->rx_data_dev, &errp);
- assert_no_error(errp);
+ (Object *)&s->rx_data_dev, &error_abort);
object_property_add_child(OBJECT(s), "axistream-control-connected-target",
- (Object *)&s->rx_control_dev, &errp);
- assert_no_error(errp);
+ (Object *)&s->rx_control_dev, &error_abort);
sysbus_init_irq(sbd, &s->irq);
- memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
+ memory_region_init_io(&s->iomem, OBJECT(s), &enet_ops, s, "enet", 0x40000);
sysbus_init_mmio(sbd, &s->iomem);
}