xserver-multidpi/hw/xfree86/os-support/bus/ppcPci.c

312 lines
8.4 KiB
C
Raw Normal View History

/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/ppcPci.c,v 1.8 2002/07/24 19:06:52 tsi Exp $ */
2003-11-14 17:48:57 +01:00
/*
* ppcPci.c - PowerPC PCI access functions
*
* PCI driver functions supporting Motorola PowerPC platforms
* including Powerstack(RiscPC/RiscPC+), PowerStackII, MTX, and
* MVME 160x/260x/360x/460x VME boards
*
* Gary Barton
* Concurrent Computer Corporation
* garyb@gate.net
*
*/
/*
* Copyright 1998 by Concurrent Computer Corporation
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Concurrent Computer
* Corporation not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Concurrent Computer Corporation makes no representations
* about the suitability of this software for any purpose. It is
* provided "as is" without express or implied warranty.
*
* CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION BE
* LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Copyright 1998 by Metro Link Incorporated
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Metro Link
* Incorporated not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Metro Link Incorporated makes no representations
* about the suitability of this software for any purpose. It is
* provided "as is" without express or implied warranty.
*
* METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED BE
* LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
2003-11-14 17:48:57 +01:00
#include <stdio.h>
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "Pci.h"
#ifndef MAP_FAILED
#define MAP_FAILED (pointer)(-1)
#endif
void
ppcPciInit()
{
#if defined(PowerMAX_OS)
extern void pmaxPciInit(void);
pmaxPciInit();
#else
static void motoppcPciInit(void);
2003-11-14 17:48:57 +01:00
motoppcPciInit();
#endif
}
#if defined(PowerMAX_OS)
2003-11-14 17:48:57 +01:00
/*
* Motorola PowerPC platform support
*
* The following code should support the MVME 1600 & 2600 VME boards
* as well as the various PowerStack and RiscPC models. All of these
* machines support PCI config mechanism #1 and use the std config
* address and data regs locations:
* cfg address reg = 0xcf8 (PCI I/O)
* cfg data reg = 0xcfc (PCI I/O)
*
* The moto machines do have different address maps on either side
* of the PCI-host bridge though.
*/
static ADDRESS motoppcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS);
static ADDRESS motoppcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS);
static CARD32 pciCfgMech1Read(PCITAG tag, int offset);
static void pciCfgMech1Write(PCITAG tag, int offset, CARD32 val);
static void pciCfgMech1SetBits(PCITAG tag, int offset,
CARD32 mask, CARD32 val);
2003-11-14 17:48:57 +01:00
static pciBusFuncs_t motoppcFuncs0 = {
/* pciReadLong */ pciCfgMech1Read,
/* pciWriteLong */ pciCfgMech1Write,
/* pciSetBitsLong */ pciCfgMech1SetBits,
/* pciAddrHostToBus */ motoppcHostAddrToBusAddr,
/* pciAddrBusToHost */ motoppcBusAddrToHostAddr
};
static pciBusInfo_t motoppcPci0 = {
/* configMech */ PCI_CFG_MECH_1,
/* numDevices */ 32,
/* secondary */ FALSE,
/* primary_bus */ 0,
#ifdef PowerMAX_OS
/* ppc_io_base */ 0x80000000,
/* ppc_io_size */ 64 * 1024,
#endif
/* funcs */ &motoppcFuncs0,
/* pciBusPriv */ NULL,
/* bridge */ NULL
};
extern volatile unsigned char *ioBase;
static void
2003-11-14 17:48:57 +01:00
motoppcPciInit()
{
pciNumBuses = 1;
pciBusInfo[0] = &motoppcPci0;
pciFindFirstFP = pciGenFindFirst;
pciFindNextFP = pciGenFindNext;
if (!xf86EnableIO())
FatalError("motoppcPciInit: EnableIO failed\n");
2003-11-14 17:48:57 +01:00
if (ioBase == MAP_FAILED) {
ppcPciIoMap(0); /* Make inb/outb et al work for pci0 and its secondaries */
if (ioBase == MAP_FAILED) {
FatalError("motoppcPciInit: Cannot map pci0 I/O segment!!!\n");
/*NOTREACHED*/
}
}
}
extern unsigned long motoPciMemBase = 0;
#if defined(Lynx) && defined(__powerpc__)
extern unsigned long motoPciMemLen = 0x40000000;
#else
extern unsigned long motoPciMemLen = 0x3f000000;
#endif
extern unsigned long motoPciMemBaseCPU = 0xc0000000;
static ADDRESS
motoppcBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
{
unsigned long addr_l = (unsigned long)addr;
if (type == PCI_MEM) {
if (addr_l >= motoPciMemBase && addr_l < motoPciMemLen)
/*
* PCI memory space addresses [0-0x3effffff] are
* are seen at [0xc0000000,0xfeffffff] on moto host
*/
return((ADDRESS)((motoPciMemBaseCPU - motoPciMemBase) + addr_l));
else if (addr_l >= 0x80000000)
/*
* Moto host memory [0,0x7fffffff] is seen at
* [0x80000000,0xffffffff] on PCI bus
*/
return((ADDRESS)(addr_l & 0x7fffffff));
else
FatalError("motoppcBusAddrToHostAddr: PCI addr 0x%x is not accessible to host!!!\n",
addr_l);
} else
return addr;
/*NOTREACHED*/
}
static ADDRESS
motoppcHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
{
unsigned long addr_l = (unsigned long)addr;
if (type == PCI_MEM) {
if (addr_l < 0x80000000)
/*
* Moto host memory [0,0x7fffffff] is seen at
* [0x80000000,0xffffffff] on PCI bus
*/
return((ADDRESS)(0x80000000 | addr_l));
else if (addr_l >= motoPciMemBaseCPU && addr_l < motoPciMemBaseCPU + motoPciMemLen)
/*
* PCI memory space addresses [0-0x3effffff] are
* are seen at [0xc0000000,0xfeffffff] on moto host
*/
return((ADDRESS)(addr_l - (motoPciMemBaseCPU - motoPciMemBase)));
else
FatalError("motoppcHostAddrToBusAddr: Host addr 0x%x is not accessible to PCI!!!\n",
addr_l);
} else
return addr;
/*NOTREACHED*/
}
#if defined (__powerpc__)
static int buserr_detected;
static
void buserr(int sig)
{
buserr_detected = 1;
}
#endif
static CARD32
pciCfgMech1Read(PCITAG tag, int offset)
{
unsigned long rv = 0xffffffff;
#ifdef DEBUGPCI
ErrorF("pciCfgMech1Read(tag=%08x,offset=%08x)\n", tag, offset);
#endif
#if defined(__powerpc__)
signal(SIGBUS, buserr);
buserr_detected = 0;
#endif
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
rv = inl(0xCFC);
#if defined(__powerpc__)
signal(SIGBUS, SIG_DFL);
if (buserr_detected)
{
#ifdef DEBUGPCI
ErrorF("pciCfgMech1Read() BUS ERROR\n");
#endif
return(0xffffffff);
}
else
#endif
return(rv);
}
static void
pciCfgMech1Write(PCITAG tag, int offset, CARD32 val)
{
#ifdef DEBUGPCI
ErrorF("pciCfgMech1Write(tag=%08x,offset=%08x,val=%08x)\n",
tag, offset,val);
#endif
#if defined(__powerpc__)
signal(SIGBUS, SIG_IGN);
#endif
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
#if defined(Lynx) && defined(__powerpc__)
outb(0x80, 0x00); /* without this the next access fails
* on my Powerstack system when we use
* assembler inlines for outl */
#endif
outl(0xCFC, val);
#if defined(__powerpc__)
signal(SIGBUS, SIG_DFL);
#endif
}
static void
pciCfgMech1SetBits(PCITAG tag, int offset, CARD32 mask, CARD32 val)
{
unsigned long rv = 0xffffffff;
#if defined(__powerpc__)
signal(SIGBUS, buserr);
#endif
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
rv = inl(0xCFC);
rv = (rv & ~mask) | val;
outl(0xCFC, rv);
#if defined(__powerpc__)
signal(SIGBUS, SIG_DFL);
#endif
}
#endif /* PowerMAX_OS */