diff options
Diffstat (limited to 'hw/net/cadence_gem.c')
-rw-r--r-- | hw/net/cadence_gem.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index d4de8ad9f1..3943187572 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -300,6 +300,8 @@ #define DESC_1_RX_SOF 0x00004000 #define DESC_1_RX_EOF 0x00008000 +#define GEM_MODID_VALUE 0x00020118 + static inline unsigned tx_desc_get_buffer(unsigned *desc) { return desc[0]; @@ -481,14 +483,17 @@ static int gem_can_receive(NetClientState *nc) } for (i = 0; i < s->num_priority_queues; i++) { - if (rx_desc_get_ownership(s->rx_desc[i]) == 1) { - if (s->can_rx_state != 2) { - s->can_rx_state = 2; - DB_PRINT("can't receive - busy buffer descriptor (q%d) 0x%x\n", - i, s->rx_desc_addr[i]); - } - return 0; + if (rx_desc_get_ownership(s->rx_desc[i]) != 1) { + break; + } + }; + + if (i == s->num_priority_queues) { + if (s->can_rx_state != 2) { + s->can_rx_state = 2; + DB_PRINT("can't receive - all the buffer descriptors are busy\n"); } + return 0; } if (s->can_rx_state != 0) { @@ -506,7 +511,18 @@ static void gem_update_int_status(CadenceGEMState *s) { int i; - if ((s->num_priority_queues == 1) && s->regs[GEM_ISR]) { + if (!s->regs[GEM_ISR]) { + /* ISR isn't set, clear all the interrupts */ + for (i = 0; i < s->num_priority_queues; ++i) { + qemu_set_irq(s->irq[i], 0); + } + return; + } + + /* If we get here we know s->regs[GEM_ISR] is set, so we don't need to + * check it again. + */ + if (s->num_priority_queues == 1) { /* No priority queues, just trigger the interrupt */ DB_PRINT("asserting int.\n"); qemu_set_irq(s->irq[0], 1); @@ -790,8 +806,8 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) { DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]); /* read current descriptor */ - cpu_physical_memory_read(s->rx_desc_addr[0], - (uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0])); + cpu_physical_memory_read(s->rx_desc_addr[q], + (uint8_t *)s->rx_desc[q], sizeof(s->rx_desc[q])); /* Descriptor owned by software ? */ if (rx_desc_get_ownership(s->rx_desc[q]) == 1) { @@ -1209,7 +1225,7 @@ static void gem_reset(DeviceState *d) s->regs[GEM_TXPAUSE] = 0x0000ffff; s->regs[GEM_TXPARTIALSF] = 0x000003ff; s->regs[GEM_RXPARTIALSF] = 0x000003ff; - s->regs[GEM_MODID] = 0x00020118; + s->regs[GEM_MODID] = s->revision; s->regs[GEM_DESCONF] = 0x02500111; s->regs[GEM_DESCONF2] = 0x2ab13fff; s->regs[GEM_DESCONF5] = 0x002f2145; @@ -1271,7 +1287,6 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) { CadenceGEMState *s; uint32_t retval; - int i; s = (CadenceGEMState *)opaque; offset >>= 2; @@ -1282,9 +1297,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) switch (offset) { case GEM_ISR: DB_PRINT("lowering irqs on ISR read\n"); - for (i = 0; i < s->num_priority_queues; ++i) { - qemu_set_irq(s->irq[i], 0); - } + /* The interrupts get updated at the end of the function. */ break; case GEM_PHYMNTNC: if (retval & GEM_PHYMNTNC_OP_R) { @@ -1508,6 +1521,8 @@ static const VMStateDescription vmstate_cadence_gem = { static Property gem_properties[] = { DEFINE_NIC_PROPERTIES(CadenceGEMState, conf), + DEFINE_PROP_UINT32("revision", CadenceGEMState, revision, + GEM_MODID_VALUE), DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState, num_priority_queues, 1), DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState, |