>From f0f37cac74b87a55cf78cda2dd25de87915a186f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 12 Mar 2008 22:25:32 +0100 Subject: [PATCH] e1000: fix endianness issues This patch fixes endianness issues in the e1000 nic emulation, which currently only works on little endian hosts with little endian targets. Byte swapping does not depend on host endianness, so this patch remove the use of cpu_to_le32 and le32_to_cpu functions. It depends on the path from the CPU to the device, which is currently and *wrongly* implemented in Qemu as a byteswap on big endian targets. This patch does the same as in other devices emulation as all the currently implemented targets work with this implementation. I have tested it on both little and big endian targets (mipsel and mips) on both little and big endian hosts (amd64 and powerpc using a backported version of e1000.c on top of 0.9.1). Signed-off-by: Aurelien Jarno --- hw/e1000.c | 23 ++++++++++++++++------- 1 files changed, 16 insertions(+), 7 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 1c77afc..6e22ef9 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -720,8 +720,11 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) E1000State *s = opaque; unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif if (index < NWRITEOPS && macreg_writeops[index]) - macreg_writeops[index](s, index, le32_to_cpu(val)); + macreg_writeops[index](s, index, val); else if (index < NREADOPS && macreg_readops[index]) DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val); else @@ -734,7 +737,7 @@ e1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { // emulate hw without byte enables: no RMW e1000_mmio_writel(opaque, addr & ~3, - cpu_to_le32(le16_to_cpu(val & 0xffff) << (8*(addr & 3)))); + (val & 0xffff) << (8*(addr & 3))); } static void @@ -742,7 +745,7 @@ e1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { // emulate hw without byte enables: no RMW e1000_mmio_writel(opaque, addr & ~3, - cpu_to_le32((val & 0xff) << (8*(addr & 3)))); + (val & 0xff) << (8*(addr & 3))); } static uint32_t @@ -752,7 +755,13 @@ e1000_mmio_readl(void *opaque, target_phys_addr_t addr) unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2; if (index < NREADOPS && macreg_readops[index]) - return cpu_to_le32(macreg_readops[index](s, index)); + { + uint32_t val = macreg_readops[index](s, index); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + return val; + } DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2); return 0; } @@ -760,15 +769,15 @@ e1000_mmio_readl(void *opaque, target_phys_addr_t addr) static uint32_t e1000_mmio_readb(void *opaque, target_phys_addr_t addr) { - return (le32_to_cpu(e1000_mmio_readl(opaque, addr & ~3)) >> + return ((e1000_mmio_readl(opaque, addr & ~3)) >> (8 * (addr & 3))) & 0xff; } static uint32_t e1000_mmio_readw(void *opaque, target_phys_addr_t addr) { - return cpu_to_le16((le32_to_cpu(e1000_mmio_readl(opaque, addr & ~3)) >> - (8 * (addr & 3))) & 0xffff); + return ((e1000_mmio_readl(opaque, addr & ~3)) >> + (8 * (addr & 3))) & 0xffff; } int mac_regtosave[] = { -- 1.5.4.3