Author: mcayland Date: Mon Sep 2 15:45:56 2013 New Revision: 1225 URL: http://tracker.coreboot.org/trac/openbios/changeset/1225
Log: PPC: Fix PCI configuration space address access
This patch corrects two long-standing bugs with PPC PCI configuration space access. Firstly fix the calculation of PCI configuration space addresses by the PCI_ADDR macro; this was incorrectly using arch->cfg_base which is the mapped address and has nothing to do with the PCI configuration space address. Instead just set bit 31 to initiate a configuration cycle as per the PCI specification.
Secondly, fix pci_config_read32() and pci_config_write32() which were incorrectly adding the register offset to the PCI IO dataport address causing them to write into unknown address space for registers > 0. It appears that this only worked purely by coincidence with QEMU due to the way in which the configuration address was calculated for an oversized PCI configuration IO dataport MemoryRegion.
Reported-by: Hervé Poussineau hpoussin@reactos.org CC: Hervé Poussineau hpoussin@reactos.org CC: Andreas Färber afaerber@suse.de Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Modified: trunk/openbios-devel/include/arch/ppc/pci.h
Modified: trunk/openbios-devel/include/arch/ppc/pci.h ============================================================================== --- trunk/openbios-devel/include/arch/ppc/pci.h Sat Aug 24 22:00:36 2013 (r1224) +++ trunk/openbios-devel/include/arch/ppc/pci.h Mon Sep 2 15:45:56 2013 (r1225) @@ -12,7 +12,7 @@ /* PCI Configuration Mechanism #1 */
#define PCI_ADDR(bus, dev, fn) \ - ((pci_addr) (arch->cfg_base \ + ((pci_addr) (0x80000000u \ | (uint32_t) (bus) << 16 \ | (uint32_t) (dev) << 11 \ | (uint32_t) (fn) << 8)) @@ -41,7 +41,7 @@ { uint32_t res; out_le32((unsigned *)arch->cfg_addr, dev | reg); - res = in_le32((unsigned *)(arch->cfg_data + reg)); + res = in_le32((unsigned *)(arch->cfg_data)); return res; }
@@ -60,7 +60,7 @@ static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val) { out_le32((unsigned *)arch->cfg_addr, dev | reg); - out_le32((unsigned *)(arch->cfg_data + reg), val); + out_le32((unsigned *)(arch->cfg_data), val); } #else /* !PCI_CONFIG_1 */ #error PCI Configuration Mechanism is not specified or implemented