@@ -60,6 +60,13 @@
#define CTRL_P 0x2
#define CTRL_S 0x1
+typedef struct XlnxXpsEthLitePort
+{
+ struct {
+ uint32_t rx_ctrl;
+ } reg;
+} XlnxXpsEthLitePort;
+
#define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite"
OBJECT_DECLARE_SIMPLE_TYPE(XlnxXpsEthLite, XILINX_ETHLITE)
@@ -77,6 +84,7 @@ struct XlnxXpsEthLite
unsigned int port_index; /* dual port RAM index */
UnimplementedDeviceState mdio;
+ XlnxXpsEthLitePort port[2];
uint32_t regs[R_MAX];
};
@@ -100,10 +108,18 @@ static void *txbuf_ptr(XlnxXpsEthLite *s, unsigned port_index)
return &s->regs[rxbase + R_TX_BUF0];
}
+static void *rxbuf_ptr(XlnxXpsEthLite *s, unsigned port_index)
+{
+ unsigned int rxbase = port_index * (0x800 / 4);
+
+ return &s->regs[rxbase + R_RX_BUF0];
+}
+
static uint64_t
eth_read(void *opaque, hwaddr addr, unsigned int size)
{
XlnxXpsEthLite *s = opaque;
+ unsigned port_index = addr_to_port_index(addr);
uint32_t r = 0;
addr >>= 2;
@@ -115,9 +131,12 @@ eth_read(void *opaque, hwaddr addr, unsigned int size)
case R_TX_LEN1:
case R_TX_CTRL1:
case R_TX_CTRL0:
+ r = s->regs[addr];
+ break;
+
case R_RX_CTRL1:
case R_RX_CTRL0:
- r = s->regs[addr];
+ r = s->port[port_index].reg.rx_ctrl;
break;
default:
@@ -167,7 +186,9 @@ eth_write(void *opaque, hwaddr addr,
if (!(value & CTRL_S)) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
- /* fall through */
+ s->port[port_index].reg.rx_ctrl = value;
+ break;
+
case R_TX_LEN0:
case R_TX_LEN1:
case R_TX_GIE0:
@@ -197,22 +218,21 @@ static const MemoryRegionOps eth_ops = {
static bool eth_can_rx(NetClientState *nc)
{
XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
- unsigned int rxbase = s->port_index * (0x800 / 4);
- return !(s->regs[rxbase + R_RX_CTRL0] & CTRL_S);
+ return !(s->port[s->port_index].reg.rx_ctrl & CTRL_S);
}
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
{
XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
- unsigned int rxbase = s->port_index * (0x800 / 4);
+ unsigned int port_index = s->port_index;
/* DA filter. */
if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
return size;
- if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) {
- trace_ethlite_pkt_lost(s->regs[R_RX_CTRL0]);
+ if (s->port[port_index].reg.rx_ctrl & CTRL_S) {
+ trace_ethlite_pkt_lost(s->port[port_index].reg.rx_ctrl);
return -1;
}
@@ -220,10 +240,10 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
trace_ethlite_pkt_size_too_big(size);
return -1;
}
- memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
+ memcpy(rxbuf_ptr(s, port_index), buf, size);
- s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
- if (s->regs[R_RX_CTRL0] & CTRL_I) {
+ s->port[port_index].reg.rx_ctrl |= CTRL_S;
+ if (s->port[port_index].reg.rx_ctrl & CTRL_I) {
eth_pulse_irq(s);
}