summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/beatnik')
-rw-r--r--bsps/powerpc/beatnik/pci/gt_pci_init.c270
-rw-r--r--bsps/powerpc/beatnik/pci/motload_fixup.c180
-rw-r--r--bsps/powerpc/beatnik/pci/pci_io_remap.c203
-rw-r--r--bsps/powerpc/beatnik/pci/pci_io_remap.h66
4 files changed, 719 insertions, 0 deletions
diff --git a/bsps/powerpc/beatnik/pci/gt_pci_init.c b/bsps/powerpc/beatnik/pci/gt_pci_init.c
new file mode 100644
index 0000000000..68d7467b22
--- /dev/null
+++ b/bsps/powerpc/beatnik/pci/gt_pci_init.c
@@ -0,0 +1,270 @@
+/* PCI configuration space access */
+
+/*
+ * Acknowledgements:
+ * Valuable information was obtained from the following drivers
+ * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc.
+ * linux: (C) MontaVista, Software, Inc; Chris Zankel, Mark A. Greer.
+ * rtems: (C) Brookhaven National Laboratory; K. Feng
+ */
+
+/*
+ * Original file header of libbsp/shared/pci.c where this file is based upon.
+ *
+ * Copyright (C) 1999 valette@crf.canon.fr
+ *
+ * This code is heavily inspired by the public specification of STREAM V2
+ * that can be found at :
+ *
+ * <http://www.chorus.com/Documentation/index.html> by following
+ * the STREAM API Specification Document link.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * Till Straumann, <strauman@slac.stanford.edu>, 1/2002
+ * - separated bridge detection code out of this file
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <libcpu/io.h>
+#include <bsp/pci.h>
+#include <rtems/bspIo.h>
+#include <stdint.h>
+
+/* set to max so we get early access to hose 0 */
+unsigned BSP_pci_hose1_bus_base = (unsigned)-1;
+
+#define MV64x60_PCI0_CONFIG_ADDR (BSP_MV64x60_BASE + 0xcf8)
+#define MV64x60_PCI0_CONFIG_DATA (BSP_MV64x60_BASE + 0xcfc)
+#define MV64x60_PCI1_CONFIG_ADDR (BSP_MV64x60_BASE + 0xc78)
+#define MV64x60_PCI1_CONFIG_DATA (BSP_MV64x60_BASE + 0xc7c)
+
+#define PCI_BUS2HOSE(bus) (bus<BSP_pci_hose1_bus_base?0:1)
+
+void detect_host_bridge(void)
+{
+
+}
+
+typedef struct {
+ volatile unsigned char *pci_config_addr;
+ volatile unsigned char *pci_config_data;
+} PciHoseCfg;
+
+static PciHoseCfg hoses[2] = {
+ {
+ pci_config_addr: (volatile unsigned char *)(MV64x60_PCI0_CONFIG_ADDR),
+ pci_config_data: (volatile unsigned char *)(MV64x60_PCI0_CONFIG_DATA),
+ },
+ {
+ pci_config_addr: (volatile unsigned char *)(MV64x60_PCI1_CONFIG_ADDR),
+ pci_config_data: (volatile unsigned char *)(MV64x60_PCI1_CONFIG_DATA),
+ }
+};
+
+#define pci hoses[hose]
+
+#define HOSE_PREAMBLE \
+ uint8_t hose; \
+ if (bus < BSP_pci_hose1_bus_base) { \
+ hose = 0; \
+ } else { \
+ hose = 1; \
+ bus -= BSP_pci_hose1_bus_base; \
+ }
+
+
+/* Sigh; we have to copy those out from the shared area... */
+static int
+indirect_pci_read_config_byte(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint8_t *val) {
+HOSE_PREAMBLE;
+ out_be32((volatile uint32_t *) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
+ *val = in_8(pci.pci_config_data + (offset&3));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_pci_read_config_word(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint16_t *val) {
+HOSE_PREAMBLE;
+ *val = 0xffff;
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
+ *val = in_le16((volatile uint16_t *)(pci.pci_config_data + (offset&3)));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_pci_read_config_dword(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint32_t *val) {
+HOSE_PREAMBLE;
+ *val = 0xffffffff;
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
+ *val = in_le32((volatile uint32_t *)pci.pci_config_data);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_pci_write_config_byte(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint8_t val) {
+HOSE_PREAMBLE;
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
+ out_8(pci.pci_config_data + (offset&3), val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_pci_write_config_word(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint16_t val) {
+HOSE_PREAMBLE;
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
+ out_le16((volatile uint16_t *)(pci.pci_config_data + (offset&3)), val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_pci_write_config_dword(unsigned char bus, unsigned char slot,
+ unsigned char function,
+ unsigned char offset, uint32_t val) {
+HOSE_PREAMBLE;
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
+ out_le32((volatile uint32_t *)pci.pci_config_data, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+const pci_config_access_functions pci_hosed_indirect_functions = {
+ indirect_pci_read_config_byte,
+ indirect_pci_read_config_word,
+ indirect_pci_read_config_dword,
+ indirect_pci_write_config_byte,
+ indirect_pci_write_config_word,
+ indirect_pci_write_config_dword
+};
+
+
+extern unsigned char ucMaxPCIBus; /* importing this is ugly */
+
+/* This is a very ugly hack. I don't want to change the shared
+ * code to support multiple hoses so we hide everything under
+ * the hood with horrible kludges for now. Sorry.
+ */
+void
+BSP_pci_initialize(void)
+{
+
+#if 0 /* These values are already set up for the shared/pci.c code */
+{
+extern pci_config_access_functions pci_indirect_functions;
+ /* by means of the PCI_CONFIG_ADDR/PCI_CONFIG_DATA macros (bsp.h) */
+ BSP_pci_configuration.pci_config_addr = hoses[0].pci_config_addr;
+ BSP_pci_configuration.pci_config_data = hoses[0].pci_config_data;
+ BSP_pci_configuration.pci_functions = &pci_indirect_functions;
+}
+#endif
+ /* initialize the first hose */
+ /* scan hose 0 and sets the maximum bus number */
+ pci_initialize();
+ /* remember the boundary */
+ BSP_pci_hose1_bus_base = pci_bus_count();
+ /* so far, so good -- now comes the cludgy part: */
+ /* hack/reset the bus count */
+ ucMaxPCIBus = 0;
+ /* scan hose 1 */
+ BSP_pci_configuration.pci_config_addr = hoses[1].pci_config_addr;
+ BSP_pci_configuration.pci_config_data = hoses[1].pci_config_data;
+ pci_initialize();
+ /* check for overflow of an unsigned char */
+ if ( BSP_pci_hose1_bus_base + pci_bus_count() > 255 ) {
+ rtems_panic("Too many PCI busses in the system");
+ }
+ /* readjust total number */
+ ucMaxPCIBus+=BSP_pci_hose1_bus_base;
+
+ /* install new access functions that can hide the hoses */
+ BSP_pci_configuration.pci_config_addr = (volatile unsigned char *)0xdeadbeef;
+ BSP_pci_configuration.pci_config_data = (volatile unsigned char *)0xdeadbeef;
+ BSP_pci_configuration.pci_functions = &pci_hosed_indirect_functions;
+}
+
+#define PCI_ERR_BITS 0xf900
+#define PCI_STATUS_OK(x) (!((x)&PCI_ERR_BITS))
+
+/* For now, just clear errors in the PCI status reg.
+ *
+ * Returns: (for diagnostic purposes)
+ * original settings (i.e. before applying the clearing
+ * sequence)
+ * (pci_status(hose_1)&0xff00) | ((pci_status(hose_2)>>8)&0xff)
+ */
+
+static unsigned long clear_hose_errors(int bus, int quiet)
+{
+unsigned long rval;
+uint16_t pcistat;
+int count;
+int hose = PCI_BUS2HOSE(bus);
+
+ /* read error status for info return */
+ pci_read_config_word(bus,0,0,PCI_STATUS,&pcistat);
+ rval = pcistat;
+
+ count=10;
+ do {
+ /* clear error reporting registers */
+
+ /* clear PCI status register */
+ pci_write_config_word(bus,0,0,PCI_STATUS, PCI_ERR_BITS);
+
+ /* read new status */
+ pci_read_config_word(bus,0,0,PCI_STATUS, &pcistat);
+
+ } while ( ! PCI_STATUS_OK(pcistat) && count-- );
+
+ if ( !PCI_STATUS_OK(rval) && !quiet) {
+ printk("Cleared PCI errors at discovery (hose %i): pci_stat was 0x%04lx\n", hose, rval);
+ }
+ if ( !PCI_STATUS_OK(pcistat) ) {
+ printk("Unable to clear PCI errors at discovery (hose %i) still 0x%04x after 10 attempts\n",hose, pcistat);
+ }
+ return rval;
+}
+
+unsigned short
+(*_BSP_clear_vmebridge_errors)(int) = 0;
+
+unsigned long
+_BSP_clear_hostbridge_errors(int enableMCP, int quiet)
+{
+unsigned long rval;
+
+ /* MCP is not connected */
+ if ( enableMCP )
+ return -1;
+
+ rval = (clear_hose_errors(0, quiet) & PCI_ERR_BITS)>>8;
+ rval |= clear_hose_errors(BSP_pci_hose1_bus_base, quiet) & PCI_ERR_BITS;
+
+ /* Tsi148 doesn't propagate VME bus errors to PCI status reg. */
+ if ( _BSP_clear_vmebridge_errors )
+ rval |= _BSP_clear_vmebridge_errors(quiet)<<16;
+
+ return rval;
+}
diff --git a/bsps/powerpc/beatnik/pci/motload_fixup.c b/bsps/powerpc/beatnik/pci/motload_fixup.c
new file mode 100644
index 0000000000..21d55916cb
--- /dev/null
+++ b/bsps/powerpc/beatnik/pci/motload_fixup.c
@@ -0,0 +1,180 @@
+/* remap the zero-based PCI IO spaces of both hoses to a single
+ * address space
+ *
+ * This must be called AFTER to BSP_pci_initialize()
+ */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+#include <rtems.h>
+#include <bsp.h>
+#include <libcpu/io.h>
+#include <bsp/pci.h>
+#include <bsp/irq.h>
+#include <rtems/bspIo.h>
+#include <bsp/gtreg.h>
+#include "pci_io_remap.h"
+
+static int
+fixup_irq_line(int bus, int slot, int fun, void *uarg)
+{
+unsigned char line;
+ pci_read_config_byte( bus, slot, fun, PCI_INTERRUPT_LINE, &line);
+ if ( line < BSP_IRQ_GPP_0 ) {
+ pci_write_config_byte( bus, slot, fun, PCI_INTERRUPT_LINE, line + BSP_IRQ_GPP_0 );
+ }
+
+ return 0;
+}
+
+void BSP_motload_pci_fixup(void)
+{
+uint32_t b0,b1,r0,r1,lim,dis;
+
+ /* MotLoad on the mvme5500 and mvme6100 configures the PCI
+ * busses nicely, i.e., the values read from the memory address
+ * space BARs by means of PCI config cycles directly reflect the
+ * CPU memory map. Thus, the presence of two hoses is already hidden.
+ *
+ * Unfortunately, all PCI I/O addresses are 'zero-based' i.e.,
+ * a hose-specific base address would have to be added to
+ * the values read from config space.
+ *
+ * We fix this here so I/O BARs also reflect the CPU memory map.
+ *
+ * Furthermore, the mvme5500 uses
+ * f000.0000
+ * ..f07f.ffff for PCI-0 / hose0
+ *
+ * and
+ *
+ * f080.0000
+ * ..f0ff.0000 for PCI-1 / hose 0
+ *
+ * whereas the mvme6100 does it the other way round...
+ */
+
+ b0 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Low_Decode) );
+ b1 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Low_Decode) );
+
+ r0 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap) );
+ r1 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap) );
+
+ switch ( BSP_getDiscoveryVersion(0) ) {
+ case MV_64360:
+ /* In case of the MV64360 the 'limit' is actually a 'size'!
+ * Disable by setting special bits in the 'BAR disable reg'.
+ */
+ dis = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL) );
+ /* disable PCI0 I/O and PCI1 I/O */
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis | (1<<9) | (1<<14) );
+ /* remap busses on hose 0; if the remap register was already set, assume
+ * that someone else [such as the bootloader] already performed the fixup
+ */
+ if ( (b0 & 0xffff) && 0 == (r0 & 0xffff) ) {
+ rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xffff)<<16 );
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xffff) );
+ }
+
+ /* remap busses on hose 1 */
+ if ( (b1 & 0xffff) && 0 == (r1 & 0xffff) ) {
+ rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xffff)<<16 );
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xffff) );
+ }
+
+ /* re-enable */
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis );
+ break;
+
+ case GT_64260_A:
+ case GT_64260_B:
+
+ if ( (b0 & 0xfff) && 0 == (r0 & 0xfff) ) { /* base are only 12 bits */
+ /* switch window off by setting the limit < base */
+ lim = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode) );
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), 0 );
+ /* remap busses on hose 0 */
+ rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xfff)<<20 );
+
+ /* BTW: it seems that writing the base register also copies the
+ * value into the 'remap' register automatically (??)
+ */
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xfff) );
+
+ /* re-enable */
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), lim );
+ }
+
+ if ( (b1 & 0xfff) && 0 == (r1 & 0xfff) ) { /* base are only 12 bits */
+ /* switch window off by setting the limit < base */
+ lim = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode) );
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), 0 );
+
+ /* remap busses on hose 1 */
+ rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xfff)<<20 );
+
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xfff) );
+
+ /* re-enable */
+ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), lim );
+ }
+ break;
+
+ default:
+ rtems_panic("Unknown discovery version; switch in file: "__FILE__" not implemented (yet)");
+ break; /* never get here */
+ }
+
+ /* Fixup the IRQ lines; the mvme6100 maps them nicely into our scheme, i.e., GPP
+ * interrupts start at 64 upwards
+ *
+ * The mvme5500 is apparently initialized differently :-(. GPP interrupts start at 0
+ * Since all PCI interrupts are wired to GPP we simply check for a value < 64 and
+ * reprogram the interrupt line register.
+ */
+ BSP_pciScan(0, fixup_irq_line, 0);
+}
+
+
diff --git a/bsps/powerpc/beatnik/pci/pci_io_remap.c b/bsps/powerpc/beatnik/pci/pci_io_remap.c
new file mode 100644
index 0000000000..56118d01d5
--- /dev/null
+++ b/bsps/powerpc/beatnik/pci/pci_io_remap.c
@@ -0,0 +1,203 @@
+/* Adjust a PCI bus range's I/O address space by adding an offset */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <bsp/pci.h>
+#include <stdint.h>
+#include "pci_io_remap.h"
+
+#ifndef PCI_MULTI_FUN
+#define PCI_MULTI_FUN 0x80
+#endif
+
+#ifndef PCI_HEADER_TYPE_MSK
+#define PCI_HEADER_TYPE_MSK 0x7f
+#endif
+
+/* Reconfigure all I/O base address registers for a range of PCI busses
+ * (from and including 'bus_from' up to and not including 'bus_to').
+ * adding an offset. This involves adjusting the base and limit registers
+ * of PCI-PCI bridges, too.
+ *
+ * RESTRICTIONS: 'offset' must be 4k aligned (PCI req.); no argument check
+ * on the bus numbers is done.
+ *
+ * RETURNS: 0 on success and a number > 0 indicating the number of
+ * non-32bit bridges found where the offset couldn't be added.
+ * Devices behind such a bridge are not accessible through I/O
+ * and should probably be switched off (not done by this code).
+ */
+int
+rtems_pci_io_remap(int bus_from, int bus_to, uint32_t offset)
+{
+ int rval = 0;
+ int bus, dev, fun, maxf;
+ int bar, numBars = 0;
+ uint8_t b;
+ uint16_t s;
+ uint32_t d;
+ unsigned int bas, lim;
+
+ if ( offset & ((1<<12)-1) ) {
+ rtems_panic("rtems_pci_io_remap(): offset must be 4k aligned");
+ return -1;
+ }
+
+
+ for ( bus=bus_from; bus < bus_to; bus++ ) {
+ for ( dev = 0; dev<PCI_MAX_DEVICES; dev++ ) {
+
+ maxf = 1;
+
+ for ( fun = 0; fun < maxf; fun++ ) {
+ pci_read_config_word( bus, dev, fun, PCI_VENDOR_ID, &s );
+ if ( 0xffff == s )
+ continue;
+
+ pci_read_config_byte( bus, dev, fun, PCI_HEADER_TYPE, &b );
+
+ /* readjust the max. function number to scan if this is a multi-function
+ * device.
+ */
+ if ( 0 == fun && (PCI_MULTI_FUN & b) )
+ maxf = PCI_MAX_FUNCTIONS;
+
+ /* Check the header type; panic if unknown.
+ * header type 0 has 6 bars, header type 1 (PCI-PCI bridge) has 2
+ */
+ b &= PCI_HEADER_TYPE_MSK;
+ switch ( b ) {
+ default:
+ printk("PCI header type %i (@%i/%i/%i)\n", b, bus, dev, fun);
+ rtems_panic("rtems_pci_io_remap(): unknown PCI header type");
+ return -1; /* keep compiler happy */
+
+ case PCI_HEADER_TYPE_CARDBUS:
+ printk("PCI header type %i (@%i/%i/%i)\n", b, bus, dev, fun);
+ rtems_panic("rtems_pci_io_remap(): don't know how to deal with Cardbus bridge");
+ return -1;
+
+ case PCI_HEADER_TYPE_NORMAL:
+ numBars = 6*4; /* loop below counts reg. offset in bytes */
+ break;
+
+ case PCI_HEADER_TYPE_BRIDGE:
+ numBars = 2*4; /* loop below counts reg. offset in bytes */
+ break;
+
+ }
+
+ for ( bar = 0; bar < numBars; bar+=4 ) {
+ pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0 + bar, &d );
+ if ( PCI_BASE_ADDRESS_SPACE_IO & d ) {
+ /* It's an I/O BAR; remap */
+ d &= PCI_BASE_ADDRESS_IO_MASK;
+ if ( d ) {
+ /* IO bar was configured; add offset */
+ d += offset;
+ pci_write_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0 + bar, d );
+ }
+ } else {
+ /* skip upper half of 64-bit window */
+ d &= PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+ if ( PCI_BASE_ADDRESS_MEM_TYPE_64 == d )
+ bar+=4;
+ }
+ }
+
+ /* Now it's time to deal with bridges */
+ if ( PCI_HEADER_TYPE_BRIDGE == b ) {
+ /* must adjust the limit registers */
+ pci_read_config_byte( bus, dev, fun, PCI_IO_LIMIT, &b );
+ pci_read_config_word( bus, dev, fun, PCI_IO_LIMIT_UPPER16, &s );
+ lim = (s<<16) + (( b & PCI_IO_RANGE_MASK ) << 8);
+ lim += offset;
+
+ pci_read_config_byte( bus, dev, fun, PCI_IO_BASE, &b );
+ pci_read_config_word( bus, dev, fun, PCI_IO_BASE_UPPER16, &s );
+ bas = (s<<16) + (( b & PCI_IO_RANGE_MASK ) << 8);
+ bas += offset;
+
+ b &= PCI_IO_RANGE_TYPE_MASK;
+ switch ( b ) {
+ default:
+ printk("Unknown IO range type 0x%x (@%i/%i/%i)\n", b, bus, dev, fun);
+ rtems_panic("rtems_pci_io_remap(): unknown IO range type");
+ return -1;
+
+ case PCI_IO_RANGE_TYPE_16:
+ if ( bas > 0xffff || lim > 0xffff ) {
+ printk("PCI I/O range type 1 (16bit) bridge (@%i/%i/%i) found:\n", bus, dev, fun);
+ printk("WARNING: base (0x%08x) or limit (0x%08x) exceed 16-bit;\n", bas, lim);
+ printk(" devices behind this bridge are NOT accessible!\n");
+
+ /* FIXME: should we disable devices behind this bridge ? */
+ bas = lim = 0;
+ }
+ break;
+
+ case PCI_IO_RANGE_TYPE_32:
+ break;
+ }
+
+ b = (uint8_t)((bas>>8) & PCI_IO_RANGE_MASK);
+ pci_write_config_byte( bus, dev, fun, PCI_IO_BASE, b );
+
+ s = (uint16_t)((bas>>16)&0xffff);
+ pci_write_config_word( bus, dev, fun, PCI_IO_BASE_UPPER16, s);
+
+ b = (uint8_t)((lim>>8) & PCI_IO_RANGE_MASK);
+ pci_write_config_byte( bus, dev, fun, PCI_IO_LIMIT, b );
+ s = (uint16_t)((lim>>16)&0xffff);
+ pci_write_config_word( bus, dev, fun, PCI_IO_LIMIT_UPPER16, s );
+ }
+ }
+ }
+ }
+ return rval;
+}
diff --git a/bsps/powerpc/beatnik/pci/pci_io_remap.h b/bsps/powerpc/beatnik/pci/pci_io_remap.h
new file mode 100644
index 0000000000..533519a2ae
--- /dev/null
+++ b/bsps/powerpc/beatnik/pci/pci_io_remap.h
@@ -0,0 +1,66 @@
+#ifndef RTEMS_PCI_IO_REMAP_H
+#define RTEMS_PCI_IO_REMAP_H
+/* Reconfigure all I/O base address registers for a range of PCI busses
+ * (from and including 'bus_from' up to and not including 'bus_to').
+ * adding an offset. This involves adjusting the base and limit registers
+ * of PCI-PCI bridges, too.
+ *
+ * RESTRICTIONS: 'offset' must be 4k aligned (PCI req.); no argument check
+ * on the bus numbers is done.
+ *
+ * RETURNS: 0 on success and a number > 0 indicating the number of
+ * non-32bit bridges found where the offset couldn't be added.
+ * Devices behind such a bridge are not accessible through I/O
+ * and should probably be switched off (not done by this code).
+ */
+
+int
+rtems_pci_io_remap(int bus_from, int bus_to, uint32_t offset);
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#endif
+