GT64XXX: fix endianness issues
PATCH 1/1 GT64XXX: fix endianness issues
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.
--- hw/gt64xxx.c | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-)
hw/gt64xxx.c +14 -5
@@ -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));
Signature · 8 lines
1.5.4.3 -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [email protected] | [email protected] `- people.debian.org/~aurel32 | www.aurel32.net