summary refs log tree commit diff stats
path: root/hw/net/dp8393x.c
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2020-01-29 20:27:49 +1100
committerJason Wang <jasowang@redhat.com>2020-03-03 18:04:47 +0800
commitea2270279bc2e1635cb6e909e22e17e630198773 (patch)
treef0c5d377e158f39ce9211a2fc0465b772020a335 /hw/net/dp8393x.c
parentbae112b80c9c42cea21ee7623c283668c3451c2e (diff)
downloadfocaccia-qemu-ea2270279bc2e1635cb6e909e22e17e630198773.tar.gz
focaccia-qemu-ea2270279bc2e1635cb6e909e22e17e630198773.zip
dp8393x: Use long-word-aligned RRA pointers in 32-bit mode
Section 3.4.1 of the datasheet says,

    The alignment of the RRA is confined to either word or long word
    boundaries, depending upon the data width mode. In 16-bit mode,
    the RRA must be aligned to a word boundary (A0 is always zero)
    and in 32-bit mode, the RRA is aligned to a long word boundary
    (A0 and A1 are always zero).

This constraint has been implemented for 16-bit mode; implement it
for 32-bit mode too.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Tested-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'hw/net/dp8393x.c')
-rw-r--r--hw/net/dp8393x.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 63293411db..d8bf248bc6 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -665,12 +665,16 @@ static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
                 qemu_flush_queued_packets(qemu_get_queue(s->nic));
             }
             break;
-        /* Ignore least significant bit */
+        /* The guest is required to store aligned pointers here */
         case SONIC_RSA:
         case SONIC_REA:
         case SONIC_RRP:
         case SONIC_RWP:
-            s->regs[reg] = val & 0xfffe;
+            if (s->regs[SONIC_DCR] & SONIC_DCR_DW) {
+                s->regs[reg] = val & 0xfffc;
+            } else {
+                s->regs[reg] = val & 0xfffe;
+            }
             break;
         /* Invert written value for some registers */
         case SONIC_CRCT: