@@ -44,7 +44,6 @@ typedef struct ISANE2000State {
static NetClientInfo net_ne2000_isa_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = ne2000_can_receive,
.receive = ne2000_receive,
};
@@ -165,15 +165,6 @@ static int ne2000_buffer_full(NE2000State *s)
return 0;
}
-int ne2000_can_receive(NetClientState *nc)
-{
- NE2000State *s = qemu_get_nic_opaque(nc);
-
- if (s->cmd & E8390_STOP)
- return 1;
- return !ne2000_buffer_full(s);
-}
-
#define MIN_BUF_SIZE 60
ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
@@ -190,8 +181,12 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
printf("NE2000: received len=%d\n", size);
#endif
- if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
+ if (s->cmd & E8390_STOP) {
return -1;
+ }
+ if (ne2000_buffer_full(s)) {
+ return 0;
+ }
/* XXX: check this */
if (s->rxcr & 0x10) {
@@ -277,6 +272,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
int offset, page, index;
+ bool try_flush = false;
addr &= 0xf;
#ifdef DEBUG_NE2000
@@ -309,19 +305,25 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->cmd &= ~E8390_TRANS;
ne2000_update_irq(s);
}
+ } else {
+ try_flush = true;
}
+
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_STARTPG:
s->start = val << 8;
+ try_flush = true;
break;
case EN0_STOPPG:
s->stop = val << 8;
+ try_flush = true;
break;
case EN0_BOUNDARY:
s->boundary = val;
+ try_flush = true;
break;
case EN0_IMR:
s->imr = val;
@@ -363,12 +365,16 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
case EN1_CURPAG:
s->curpag = val;
+ try_flush = true;
break;
case EN1_MULT ... EN1_MULT + 7:
s->mult[offset - EN1_MULT] = val;
break;
}
}
+ if (try_flush && !ne2000_buffer_full(s)) {
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ }
}
static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
@@ -705,7 +711,6 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
static NetClientInfo net_ne2000_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = ne2000_can_receive,
.receive = ne2000_receive,
};
This moves the behavior of ne2000_can_receive to ne2000_receive. The logic is when the NIC is stopped we drop the packet, when the buffer is full we queue it and try flush later. ne2000_buffer_full is determined by s->curpag, s->boundary, s->start and s->stop. Add a flush in ne2000_ioport_write as they are all updated there, except the advancing of s->curpag in ne2000_receive where ne2000_buffer_full is already false. Signed-off-by: Fam Zheng <famz@redhat.com> --- hw/net/ne2000-isa.c | 1 - hw/net/ne2000.c | 27 ++++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-)