|
@@ -34,6 +34,7 @@
|
|
|
#include "hw/sysbus.h"
|
|
|
#include "hw/irq.h"
|
|
|
#include "hw/qdev-properties.h"
|
|
|
+#include "hw/qdev-properties-system.h"
|
|
|
#include "hw/misc/unimp.h"
|
|
|
#include "net/net.h"
|
|
|
#include "trace.h"
|
|
@@ -85,6 +86,7 @@ struct XlnxXpsEthLite
|
|
|
{
|
|
|
SysBusDevice parent_obj;
|
|
|
|
|
|
+ EndianMode model_endianness;
|
|
|
MemoryRegion container;
|
|
|
qemu_irq irq;
|
|
|
NICState *nic;
|
|
@@ -183,10 +185,10 @@ static void port_tx_write(void *opaque, hwaddr addr, uint64_t value,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static const MemoryRegionOps eth_porttx_ops = {
|
|
|
+static const MemoryRegionOps eth_porttx_ops[2] = {
|
|
|
+ [0 ... 1] = {
|
|
|
.read = port_tx_read,
|
|
|
.write = port_tx_write,
|
|
|
- .endianness = DEVICE_NATIVE_ENDIAN,
|
|
|
.impl = {
|
|
|
.min_access_size = 4,
|
|
|
.max_access_size = 4,
|
|
@@ -195,6 +197,9 @@ static const MemoryRegionOps eth_porttx_ops = {
|
|
|
.min_access_size = 4,
|
|
|
.max_access_size = 4,
|
|
|
},
|
|
|
+ },
|
|
|
+ [0].endianness = DEVICE_LITTLE_ENDIAN,
|
|
|
+ [1].endianness = DEVICE_BIG_ENDIAN,
|
|
|
};
|
|
|
|
|
|
static uint64_t port_rx_read(void *opaque, hwaddr addr, unsigned int size)
|
|
@@ -232,10 +237,10 @@ static void port_rx_write(void *opaque, hwaddr addr, uint64_t value,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static const MemoryRegionOps eth_portrx_ops = {
|
|
|
+static const MemoryRegionOps eth_portrx_ops[2] = {
|
|
|
+ [0 ... 1] = {
|
|
|
.read = port_rx_read,
|
|
|
.write = port_rx_write,
|
|
|
- .endianness = DEVICE_NATIVE_ENDIAN,
|
|
|
.impl = {
|
|
|
.min_access_size = 4,
|
|
|
.max_access_size = 4,
|
|
@@ -244,6 +249,9 @@ static const MemoryRegionOps eth_portrx_ops = {
|
|
|
.min_access_size = 4,
|
|
|
.max_access_size = 4,
|
|
|
},
|
|
|
+ },
|
|
|
+ [0].endianness = DEVICE_LITTLE_ENDIAN,
|
|
|
+ [1].endianness = DEVICE_BIG_ENDIAN,
|
|
|
};
|
|
|
|
|
|
static bool eth_can_rx(NetClientState *nc)
|
|
@@ -300,6 +308,14 @@ static NetClientInfo net_xilinx_ethlite_info = {
|
|
|
static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
|
|
|
{
|
|
|
XlnxXpsEthLite *s = XILINX_ETHLITE(dev);
|
|
|
+ unsigned ops_index;
|
|
|
+
|
|
|
+ if (s->model_endianness == ENDIAN_MODE_UNSPECIFIED) {
|
|
|
+ error_setg(errp, TYPE_XILINX_ETHLITE " property 'endianness'"
|
|
|
+ " must be set to 'big' or 'little'");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ops_index = s->model_endianness == ENDIAN_MODE_BIG ? 1 : 0;
|
|
|
|
|
|
memory_region_init(&s->container, OBJECT(dev),
|
|
|
"xlnx.xps-ethernetlite", 0x2000);
|
|
@@ -328,7 +344,7 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
|
|
|
BUFSZ_MAX, &error_abort);
|
|
|
memory_region_add_subregion(&s->container, 0x0800 * i, &s->port[i].txbuf);
|
|
|
memory_region_init_io(&s->port[i].txio, OBJECT(dev),
|
|
|
- ð_porttx_ops, s,
|
|
|
+ ð_porttx_ops[ops_index], s,
|
|
|
i ? "ethlite.tx[1]io" : "ethlite.tx[0]io",
|
|
|
4 * TX_MAX);
|
|
|
memory_region_add_subregion(&s->container, i ? A_TX_BASE1 : A_TX_BASE0,
|
|
@@ -340,7 +356,7 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
|
|
|
memory_region_add_subregion(&s->container, 0x1000 + 0x0800 * i,
|
|
|
&s->port[i].rxbuf);
|
|
|
memory_region_init_io(&s->port[i].rxio, OBJECT(dev),
|
|
|
- ð_portrx_ops, s,
|
|
|
+ ð_portrx_ops[ops_index], s,
|
|
|
i ? "ethlite.rx[1]io" : "ethlite.rx[0]io",
|
|
|
4 * RX_MAX);
|
|
|
memory_region_add_subregion(&s->container, i ? A_RX_BASE1 : A_RX_BASE0,
|
|
@@ -363,6 +379,7 @@ static void xilinx_ethlite_init(Object *obj)
|
|
|
}
|
|
|
|
|
|
static const Property xilinx_ethlite_properties[] = {
|
|
|
+ DEFINE_PROP_ENDIAN_NODEFAULT("endianness", XlnxXpsEthLite, model_endianness),
|
|
|
DEFINE_PROP_UINT32("tx-ping-pong", XlnxXpsEthLite, c_tx_pingpong, 1),
|
|
|
DEFINE_PROP_UINT32("rx-ping-pong", XlnxXpsEthLite, c_rx_pingpong, 1),
|
|
|
DEFINE_NIC_PROPERTIES(XlnxXpsEthLite, conf),
|