The GT64XXX code has some endianness issues on big endian as shown by
lspci:
  00:00.0 Network and computing encryption device: Unknown device 2046:ab11 
(rev 06)
  00:0a.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA
  ...

The first device ID is obviously wrong.

This patch attempts to fix endianness issues:
- Byte swapping for internal GT64XXX registers is controlled by the bit
  12 of the Configuration Register and not by the PCI Internal Command
  register.
- The bit 0 of the PCI Internal Command register controls byte swapping
  for PCI access *except for the internal PCI device*, that is when both
  bus and device numbers are 0.

PCI access is now done directly via pci_data_read/write and not via
pci_host_data_readl/writel as the later functions assume that the host
always handle PCI data in its own endianness.

Signed-off-by: Aurelien Jarno <[EMAIL PROTECTED]>
---
 hw/gt64xxx.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 46d6a76..8e8adad 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -309,7 +309,7 @@ static void gt64120_writel (void *opaque, 
target_phys_addr_t addr,
     GT64120State *s = opaque;
     uint32_t saddr;
 
-    if (!(s->regs[GT_PCI0_CMD] & 1))
+    if (!(s->regs[GT_CPU] & 0x00001000))
         val = bswap32(val);
 
     saddr = (addr & 0xfff) >> 2;
@@ -530,7 +530,10 @@ static void gt64120_writel (void *opaque, 
target_phys_addr_t addr,
         s->pci->config_reg = val & 0x80fffffc;
         break;
     case GT_PCI0_CFGDATA:
-        pci_host_data_writel(s->pci, 0, val);
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+            val = bswap32(val);
+        if (s->pci->config_reg & (1u << 31))
+            pci_data_write(s->pci->bus, s->pci->config_reg, val, 4);
         break;
 
     /* Interrupts */
@@ -767,7 +770,12 @@ static uint32_t gt64120_readl (void *opaque,
         val = s->pci->config_reg;
         break;
     case GT_PCI0_CFGDATA:
-        val = pci_host_data_readl(s->pci, 0);
+        if (!(s->pci->config_reg & (1 << 31)))
+            val = 0xffffffff;
+        else
+            val = pci_data_read(s->pci->bus, s->pci->config_reg, 4);
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+            val = bswap32(val);
         break;
 
     case GT_PCI0_CMD:
@@ -840,7 +848,7 @@ static uint32_t gt64120_readl (void *opaque,
         break;
     }
 
-    if (!(s->regs[GT_PCI0_CMD] & 1))
+    if (!(s->regs[GT_CPU] & 0x00001000))
         val = bswap32(val);
 
     return val;
@@ -1069,7 +1077,6 @@ static void gt64120_reset(void *opaque)
     s->regs[GT_PCI1_CFGADDR]  = 0x00000000;
     s->regs[GT_PCI1_CFGDATA]  = 0x00000000;
     s->regs[GT_PCI0_CFGADDR]  = 0x00000000;
-    s->regs[GT_PCI0_CFGDATA]  = 0x00000000;
 
     /* Interrupt registers are all zeroed at reset */
 
@@ -1114,8 +1121,10 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 
     (void)&pci_host_data_writeb; /* avoid warning */
     (void)&pci_host_data_writew; /* avoid warning */
+    (void)&pci_host_data_writel; /* avoid warning */
     (void)&pci_host_data_readb; /* avoid warning */
     (void)&pci_host_data_readw; /* avoid warning */
+    (void)&pci_host_data_readl; /* avoid warning */
 
     s = qemu_mallocz(sizeof(GT64120State));
     s->pci = qemu_mallocz(sizeof(GT64120PCIState));
-- 
1.5.4.3


-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [EMAIL PROTECTED]         | [EMAIL PROTECTED]
   `-    people.debian.org/~aurel32 | www.aurel32.net


Reply via email to