From 5b0c98fcb7ac006bd8efe0e0fecba52c43a9d028 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 29 Jan 2020 20:27:49 +1100 Subject: [PATCH] dp8393x: Update LLFA and CRDA registers from rx descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the algorithm given in the National Semiconductor DP83932C datasheet in section 3.4.7: At the next reception, the SONIC re-reads the last RXpkt.link field, and updates its CRDA register to point to the next descriptor. The chip is designed to allow the host to provide a new list of descriptors in this way. Signed-off-by: Finn Thain Tested-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Jason Wang --- hw/net/dp8393x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index ed57f5f326..960462397e 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -786,12 +786,13 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf, address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width; address_space_read(&s->as, address, MEMTXATTRS_UNSPECIFIED, s->data, size); - if (dp8393x_get(s, width, 0) & SONIC_DESC_EOL) { + s->regs[SONIC_LLFA] = dp8393x_get(s, width, 0); + if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) { /* Still EOL ; stop reception */ return -1; - } else { - s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA]; } + /* Link has been updated by host */ + s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA]; } /* Save current position */ @@ -840,7 +841,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf, MEMTXATTRS_UNSPECIFIED, s->data, size); - /* Move to next descriptor */ + /* Check link field */ size = sizeof(uint16_t) * width; address_space_read(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width, @@ -856,6 +857,8 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf, dp8393x_put(s, width, 0, 0); address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED, s->data, size); + + /* Move to next descriptor */ s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA]; s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX; s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);