diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/programs/Xserver/hw/xfree86/os-support/bus | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/bus')
21 files changed, 9254 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.c new file mode 100644 index 000000000..255dfa12f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.c @@ -0,0 +1,470 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.c,v 1.4 2003/08/29 21:08:06 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +/* + * This file contains the glue necessary for support of Intel's 460GX chipset. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "460gxPCI.h" +#include "xf86.h" +#include "Pci.h" + +/* 460GX register definitions */ +/* SAC at 0:10:0 */ +#define CBN 0x0040 +/* SAC at CBN:0:0 */ +#define DEVNPRES 0x0070 +/* SAC at CBN:1[0-7]:0 */ +#define BUSNO 0x0048 +#define SUBNO 0x0049 +#define VGASE 0x0080 +#define PCIS 0x0084 +#define IOR 0x008C +#define IORD 0x008E /* CBN:10:0 only */ +/* PXB at CBN:1[0-7]:1 */ +#define ERRCMD 0x0046 + +static int cbn_460gx = -1; +static CARD32 cbdevs_460gx = 0; +static CARD16 iord_460gx; +static int busno_460gx[8], subno_460gx[8]; +static CARD8 pcis_460gx[8], ior_460gx[8]; +static CARD8 has_err_460gx[8], err_460gx[8]; +static CARD8 iomap_460gx[16]; /* One for each 4k */ +static pciBusFuncs_t BusFuncs_460gx; + +static pciConfigPtr +Verify460GXBus(int bus) +{ + pciConfigPtr pPCI; + + if ((bus < 0) || (bus >= pciNumBuses) || + !pciBusInfo[bus] || !(pPCI = pciBusInfo[bus]->bridge) || + (pPCI->busnum != cbn_460gx) || (pPCI->funcnum != 0) || + (pPCI->devnum < 0x10) || (pPCI->devnum > 0x17)) + return NULL; + + return pPCI; +} + +/* + * This function is called to emulate the various settings in a P2P or CardBus + * bridge's control register using one of a 460GX's SAC host bridges. + */ +static CARD16 +Control460GXBridge(int bus, CARD16 mask, CARD16 value) +{ + pciConfigPtr pPCI; + PCITAG tag; + CARD16 current = 0; + CARD8 tmp; + + if ((pPCI = Verify460GXBus(bus))) { + /* Start with VGA enablement */ + tmp = pciReadByte(pPCI->tag, VGASE); + if (tmp & 0x01) { + current |= PCI_PCI_BRIDGE_VGA_EN; + if ((mask & PCI_PCI_BRIDGE_VGA_EN) && + !(value & PCI_PCI_BRIDGE_VGA_EN)) + pciWriteByte(pPCI->tag, VGASE, tmp & ~0x01); + } else { + if (mask & value & PCI_PCI_BRIDGE_VGA_EN) + pciWriteByte(pPCI->tag, VGASE, tmp | 0x01); + } + + /* Move on to master abort failure enablement */ + if (has_err_460gx[pPCI->devnum - 0x10]) { + tag = PCI_MAKE_TAG(pPCI->busnum, pPCI->devnum, pPCI->funcnum + 1); + tmp = pciReadByte(tag, ERRCMD); + if (tmp & 0x01) { + current |= PCI_PCI_BRIDGE_MASTER_ABORT_EN; + if ((mask & PCI_PCI_BRIDGE_MASTER_ABORT_EN) && + !(value & PCI_PCI_BRIDGE_MASTER_ABORT_EN)) + pciWriteByte(tag, ERRCMD, tmp & ~0x01); + } else { + if (mask & value & PCI_PCI_BRIDGE_MASTER_ABORT_EN) + pciWriteByte(tag, ERRCMD, tmp | 0x01); + } + } + + /* Put emulation of any other P2P bridge control here */ + } + + return (current & ~mask) | (value & mask); +} + +/* + * Retrieve various bus numbers representing the connections provided by 460GX + * host bridges. + */ +static void +Get460GXBridgeBuses(int bus, int *primary, int *secondary, int *subordinate) +{ + pciConfigPtr pPCI = Verify460GXBus(bus); + int i; + + /* The returned bus numbers are initialised by the caller */ + + if (!pPCI) + return; + + i = pPCI->devnum - 0x10; + + /* These are not modified, so no need to re-read them */ + if (primary) + *primary = pPCI->busnum; + if (secondary) + *secondary = busno_460gx[i]; + if (subordinate) + *subordinate = subno_460gx[i]; +} + +/* Retrieves a list of the resources routed to a host bridge's secondary bus */ +static void +Get460GXBridgeResources(int bus, + pointer *ppIoRes, + pointer *ppMemRes, + pointer *ppPmemRes) +{ + pciConfigPtr pPCI = Verify460GXBus(bus); + resRange range; + unsigned int i, j; + + if (ppIoRes) { + xf86FreeResList(*ppIoRes); + *ppIoRes = NULL; + + if (pPCI) { + for (i = 0; i <= 0x0F; i++) { + if (iomap_460gx[i] != pPCI->devnum) + continue; + + RANGE(range, i << 12, ((i + 1) << 12) - 1, + RANGE_TYPE(ResExcIoBlock, 0)); + *ppIoRes = xf86AddResToList(*ppIoRes, &range, -1); + } + } + } + + if (ppMemRes) { + xf86FreeResList(*ppMemRes); + *ppMemRes = NULL; + + if (pPCI) { + if (!(i = (pPCI->devnum - 0x10))) + j = 127; /* (4GB - 32M) / 32M */ + else + j = pcis_460gx[i - 1] & 0x7F; + + i = pcis_460gx[i] & 0x7F; + if (i < j) { + RANGE(range, i << 25, (j << 25) - 1, + RANGE_TYPE(ResExcMemBlock, 0)); + *ppMemRes = xf86AddResToList(*ppMemRes, &range, -1); + } + } + } + + if (ppPmemRes) { + xf86FreeResList(*ppPmemRes); + *ppPmemRes = NULL; + } +} + +/* + * This checks for, and validates, the presence of the 460GX chipset, and sets + * cbn_460gx to a positive value accordingly. This function returns TRUE if + * the chipset scan is to be stopped, or FALSE if the scan is to move on to the + * next chipset. + */ + +Bool +xorgProbe460GX(scanpciWrapperOpt flags) +{ + pciBusInfo_t *pBusInfo; + PCITAG tag; + + /* Bus zero should already be set up */ + if (!(pBusInfo = pciBusInfo[0])) { + cbn_460gx = -1; + return FALSE; + } + /* First look for a 460GX's primary host bridge */ + tag = PCI_MAKE_TAG(0, 0x10, 0); + if (pciReadLong(tag, PCI_ID_REG) == DEVID(VENDOR_INTEL, CHIP_460GX_SAC)) { + return TRUE; + } + + cbn_460gx = -1; + + return FALSE; +} + +void +xf86PreScan460GX(void) +{ + pciBusInfo_t *pBusInfo; + PCITAG tag; + CARD32 tmp; + int i, devno; + + if (!(pBusInfo = pciBusInfo[0])) + return; + + /* Get CBN (Chipset bus number) */ + tag = PCI_MAKE_TAG(0, 0x10, 0); + if (!(cbn_460gx = (unsigned int)pciReadByte(tag, CBN))) { + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + + if (pciNumBuses <= cbn_460gx) + pciNumBuses = cbn_460gx + 1; + + /* Set up bus CBN */ + if (!pciBusInfo[cbn_460gx]) { + pciBusInfo[cbn_460gx] = xnfalloc(sizeof(pciBusInfo_t)); + *pciBusInfo[cbn_460gx] = *pBusInfo; + } + + tag = PCI_MAKE_TAG(cbn_460gx, 0, 0); + if (pciReadLong(tag, PCI_ID_REG) != DEVID(VENDOR_INTEL, CHIP_460GX_SAC)) { + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + + /* + * Find out which CBN devices the firmware thinks are present. Of these, + * we are only interested in devices 0x10 through 0x17. + */ + cbdevs_460gx = pciReadLong(tag, DEVNPRES); + + for (i = 0, devno = 0x10; devno <= 0x17; i++, devno++) { + tag = PCI_MAKE_TAG(cbn_460gx, devno, 0); + if (pciReadLong(tag, PCI_ID_REG) != + DEVID(VENDOR_INTEL, CHIP_460GX_SAC)) { + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + + if (devno == 0x10) + iord_460gx = pciReadWord(tag, IORD); + + busno_460gx[i] = (unsigned int)pciReadByte(tag, BUSNO); + subno_460gx[i] = (unsigned int)pciReadByte(tag, SUBNO); + pcis_460gx[i] = pciReadByte(tag, PCIS); + ior_460gx[i] = pciReadByte(tag, IOR); + + has_err_460gx[i] = err_460gx[i] = 0; /* Insurance */ + + tag = PCI_MAKE_TAG(cbn_460gx, devno, 1); + tmp = pciReadLong(tag, PCI_ID_REG); + switch (tmp) { + case DEVID(VENDOR_INTEL, CHIP_460GX_PXB): + case DEVID(VENDOR_INTEL, CHIP_460GX_WXB): + if (cbdevs_460gx & (1 << devno)) { + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + + /* + * XXX I don't have WXB docs, but PCI register dumps indicate that + * the registers we are interested in are consistent with those of + * the PXB. + */ + err_460gx[i] = pciReadByte(tag, ERRCMD); + has_err_460gx[i] = 1; + break; + + case DEVID(VENDOR_INTEL, CHIP_460GX_GXB_1): + if (cbdevs_460gx & (1 << devno)) { + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + + /* + * XXX GXB isn't documented to have an ERRCMD register, nor any + * other means of failing master aborts. For now, assume master + * aborts are always allowed to complete normally. + */ + break; + + default: + if (((CARD16)(tmp + 1U) <= (CARD16)1U) && + (cbdevs_460gx & (1U << devno))) + break; + /* Sanity check failed */ + cbn_460gx = -1; + return; + } + } + + /* Allow master aborts to complete normally */ + for (i = 0, devno = 0x10; devno <= 0x17; i++, devno++) { + if (!(err_460gx[i] & 0x01)) + continue; + + pciWriteByte(PCI_MAKE_TAG(cbn_460gx, devno, 1), + ERRCMD, err_460gx[i] & ~0x01); + } + + /* + * The 460GX spec says that any access to buses higher than CBN will be + * master-aborted. It seems possible however that this is not the case in + * all 460GX implementations. For now, limit the bus scan to CBN, unless + * we have already found a higher bus number. + */ + for (i = 0; subno_460gx[i] < cbn_460gx; ) { + if (++i < 8) + continue; + + pciMaxBusNum = cbn_460gx + 1; + break; + } + + return; +} + +/* This does some 460GX-related processing after the PCI bus scan */ +void +xf86PostScan460GX(void) +{ + pciConfigPtr pPCI, *ppPCI; + pciBusInfo_t *pBusInfo; + int i, j, devno; + + if (cbn_460gx <= 0) + return; + + /* Set up our extra bus functions */ + BusFuncs_460gx = *(pciBusInfo[0]->funcs); + BusFuncs_460gx.pciControlBridge = Control460GXBridge; + BusFuncs_460gx.pciGetBridgeBuses = Get460GXBridgeBuses; + BusFuncs_460gx.pciGetBridgeResources = Get460GXBridgeResources; + + /* + * Mark all host bridges so that they are ignored by the upper-level + * xf86GetPciBridgeInfo() function. This marking is later clobbered by the + * tail end of xf86scanpci() for those bridges that actually have bus + * segments associated with them. + */ + ppPCI = xf86scanpci(0); /* Recursion is only apparent */ + while ((pPCI = *ppPCI++)) { + if ((pPCI->pci_base_class == PCI_CLASS_BRIDGE) && + (pPCI->pci_sub_class == PCI_SUBCLASS_BRIDGE_HOST)) + pPCI->businfo = HOST_NO_BUS; + } + + ppPCI = xf86scanpci(0); /* Recursion is only apparent */ + j = 0; + + /* + * Fix up CBN bus linkage. This is somewhat arbitrary. The bridge chosen + * for this must be a CBN device so that bus CBN can be recognised as the + * root segment. It also cannot be any of the bus expanders (devices + * CBN:0x10:0 through CBN:0x17:0 nor any of their functions). For now, we + * chose the SAC host bridge at CBN:0:0. + */ + pBusInfo = pciBusInfo[cbn_460gx]; + pBusInfo->bridge = pciBusInfo[0]->bridge; /* Just in case */ + while ((pPCI = *ppPCI++)) { + if (pPCI->busnum < cbn_460gx) + continue; + if (pPCI->busnum > cbn_460gx) + break; + if (pPCI->devnum < 0) + continue; + if (pPCI->devnum > 0) + break; + if (pPCI->funcnum < 0) + continue; + if (pPCI->funcnum > 0) + break; + + pBusInfo->bridge = pPCI; + pBusInfo->secondary = FALSE; + pBusInfo->primary_bus = cbn_460gx; + break; + } + + for (i = 0, devno = 0x10; devno <= 0x17; i++, devno++) { + /* Restore ERRCMD registers */ + if (err_460gx[i] & 0x01) + pciWriteByte(PCI_MAKE_TAG(cbn_460gx, devno, 1), + ERRCMD, err_460gx[i]); + + if (!(cbdevs_460gx & (1 << devno))) { + while ((pPCI = *ppPCI++)) { + if (pPCI->busnum < cbn_460gx) + continue; + if (pPCI->busnum > cbn_460gx) + break; + if (pPCI->devnum < devno) + continue; + if (pPCI->devnum > devno) + break; + if (pPCI->funcnum < 0) + continue; + if (pPCI->funcnum > 0) + break; + + if ((pBusInfo == pciBusInfo[busno_460gx[i]])) + break; + + /* Fix bus linkage */ + pBusInfo->bridge = pPCI; + pBusInfo->secondary = TRUE; + pBusInfo->primary_bus = cbn_460gx; + + /* Plug in chipset routines */ + pBusInfo->funcs = &BusFuncs_460gx; + break; + } + } + + /* Decode IOR registers */ + for(; j <= (ior_460gx[i] & 0x0F); j++) + iomap_460gx[j] = devno; + } + + /* The bottom 4k of I/O space is always routed to PCI0a */ + iomap_460gx[0] = 0x10; + + /* Decode IORD register */ + for (j = 1; j <= 0x0F; j++) + if (iord_460gx & (1 << j)) + iomap_460gx[j] = 0x10; +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.h new file mode 100644 index 000000000..65a19b2f0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.h @@ -0,0 +1,42 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/460gxPCI.h,v 1.1 2003/01/02 18:12:48 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef PCI_460GX_H +#define PCI_460GX_H 1 + +#include <X11/Xdefs.h> +#include <Pci.h> + +Bool xorgProbe460GX(scanpciWrapperOpt flags); +void xf86PreScan460GX(void); +void xf86PostScan460GX(void); + +#endif diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Imakefile b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Imakefile new file mode 100644 index 000000000..bae6ee7c2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Imakefile @@ -0,0 +1,165 @@ +XCOMM $XConsortium: Imakefile /main/16 1996/10/27 18:07:43 kaleb $ + + + + +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Imakefile,v 1.29tsi Exp $ + +#include <Server.tmpl> + +#if defined(LinuxArchitecture) && defined(AlphaArchitecture) + +XCOMM Alpha (Linux) PCI driver + +PCIDRVRSRC = axpPci.c +PCIDRVROBJ = axpPci.o + +#elif defined(LinuxArchitecture) && defined(SparcArchitecture) + +XCOMM Sparc SBUS driver and generic Linux PCI driver + +PCIDRVRSRC = sparcPci.c linuxPci.c +PCIDRVROBJ = sparcPci.o linuxPci.o +SBUSDRVSRC = Sbus.c +SBUSDRVOBJ = Sbus.o + +#elif defined(SunArchitecture) && defined(SparcArchitecture) + +XCOMM Sparc SBUS & PCI drivers + +PCIDRVRSRC = sparcPci.c +PCIDRVROBJ = sparcPci.o +SBUSDRVSRC = Sbus.c +SBUSDRVOBJ = Sbus.o + +#elif defined(LinuxArchitecture) && \ + (defined(PpcArchitecture) || \ + defined(Ppc64Architecture) || \ + defined(MipsArchitecture) || \ + defined(ia64Architecture) || \ + defined(Mc68020Architecture) || \ + defined(Arm32Architecture) || \ + defined(HPArchitecture) || \ + defined(s390Architecture) || \ + defined(SuperHArchitecture) || \ + defined(SuperHebArchitecture)) + +XCOMM generic linux PCI driver (using /proc/bus/pci, requires kernel 2.2) + +PCIDRVRSRC = linuxPci.c +PCIDRVROBJ = linuxPci.o + +#elif defined(OpenBSDArchitecture) && \ + (defined(PpcArchitecture) || \ + defined(AlphaArchitecture) || \ + defined(Sparc64Architecture)) + +XCOMM OpenBSD/alpha, OpenBSD/powerpc and OpenBSD/sparc64 + +PCIDRVRSRC = freebsdPci.c +PCIDRVROBJ = freebsdPci.o + +#elif defined(NetBSDArchitecture) && defined(PpcArchitecture) + +XCOMM NetBSD/powerpc + +PCIDRVRSRC = netbsdPci.c +PCIDRVROBJ = netbsdPci.o + +#elif defined(FreeBSDArchitecture) && defined(PpcArchitecture) + +XCOMM FreeBSD/PowerPC PCI driver (using /dev/pci) + +PCIDRVRSRC = freebsdPci.c +PCIDRVROBJ = freebsdPci.o + +#elif defined(PpcArchitecture) + +XCOMM PowerPC PCI drivers + +PCIDRVRSRC = ppcPci.c +PCIDRVROBJ = ppcPci.o + +#elif defined(LinuxArchitecture) && \ + (defined(i386Architecture) || defined(AMD64Architecture)) + +XCOMM ix86 PCI driver with OS fallback for Linux + +PCIDRVRSRC = ix86Pci.c linuxPci.c +PCIDRVROBJ = ix86Pci.o linuxPci.o + +#elif defined(KFreeBSDArchitecture) && \ + (defined(AlphaArchitecture) || defined(AMD64Architecture)) + +XCOMM generic FreeBSD PCI driver (using /dev/pci) + +PCIDRVRSRC = freebsdPci.c +PCIDRVROBJ = freebsdPci.o + +#elif defined(KFreeBSDArchitecture) && defined(Sparc64Architecture) + +XCOMM Sparc SBUS & PCI drivers + +PCIDRVRSRC = freebsdPci.c +PCIDRVROBJ = freebsdPci.o +SBUSDRVSRC = Sbus.c +SBUSDRVOBJ = Sbus.o + +#elif defined(NetBSDArchitecture) && defined(AlphaArchitecture) + +XCOMM Alpha (NetBSD) PCI driver + +PCIDRVRSRC = netbsdPci.c +PCIDRVROBJ = netbsdPci.o + +#elif defined(i386Architecture) || \ + defined(ia64Architecture) || \ + defined(AMD64Architecture) + +XCOMM ix86 PCI driver + +PCIDRVRSRC = ix86Pci.c +PCIDRVROBJ = ix86Pci.o +XCOMM PCIDRVRSRC = linuxPci.c +XCOMM PCIDRVROBJ = linuxPci.o + +#else +XCOMM no PCI driver -- shouldn't get here +#endif + +#if defined(SparcArchitecture) +# if !defined(SunArchitecture) +PCIARCHSRC = sparcPci.c +PCIARCHOBJ = sparcPci.o +# endif +#elif defined(ia64Architecture) +PCIARCHSRC = 460gxPCI.c e8870PCI.c zx1PCI.c altixPCI.c +PCIARCHOBJ = 460gxPCI.o e8870PCI.o zx1PCI.o altixPCI.o +#endif + +SRCS = Pci.c $(PCIDRVRSRC) $(SBUSDRVSRC) $(PCIARCHSRC) +OBJS = Pci.o $(PCIDRVROBJ) $(SBUSDRVOBJ) $(PCIARCHOBJ) + +INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86OSSRC) \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) + +NormalLibraryObjectRule() +SubdirLibraryRule($(OBJS)) + +/* + * egcs 1.1.2 as provided with some Linux distributions has an optimisation + * bug that results in bad code for this file. + */ +#if Egcs112Bug +SpecialCObjectRule(Pci,NullParameter,-O0) +#endif + +#if defined(SunArchitecture) && defined(SparcArchitecture) + +LFS_DEFINES = `getconf LFS_CFLAGS` + +SpecialCObjectRule(sparcPci,NullParameter,$(LFS_DEFINES)) + +#endif + +DependTarget() diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.c new file mode 100644 index 000000000..4e71eb614 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.c @@ -0,0 +1,1453 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c,v 1.82 2004/01/16 15:39:04 tsi Exp $ */ +/* + * Pci.c - New server PCI access functions + * + * The XFree86 server PCI access functions have been reimplemented as a + * framework that allows each supported platform/OS to have their own + * platform/OS specific pci driver. + * + * All of the public PCI access functions exported to the other parts of + * the server are declared in Pci.h and defined herein. These include: + * pciInit() - Initialize PCI access functions + * pciFindFirst() - Find a PCI device by dev/vend id + * pciFindNext() - Find another PCI device by dev/vend id + * pciReadLong() - Read a 32 bit value from a device's cfg space + * pciReadWord() - Read a 16 bit value from a device's cfg space + * pciReadByte() - Read an 8 bit value from a device's cfg space + * pciWriteLong() - Write a 32 bit value to a device's cfg space + * pciWriteWord() - Write a 16 bit value to a device's cfg space + * pciWriteByte() - Write an 8 bit value to a device's cfg space + * pciSetBitsLong() - Write a 32 bit value against a mask + * pciSetBitsByte() - Write an 8 bit value against a mask + * pciTag() - Return tag for a given PCI bus, device, & + * function + * pciBusAddrToHostAddr() - Convert a PCI address to a host address + * pciHostAddrToBusAddr() - Convert a host address to a PCI address + * pciGetBaseSize() - Returns the number of bits in a PCI base + * addr mapping + * xf86MapPciMem() - Like xf86MapVidMem() except function expects + * a PCI address and a PCITAG that identifies + * a PCI device + * xf86ReadPciBIOS() - Like xf86ReadBIOS() but can handle PCI/host + * address translation and BIOS decode enabling + * xf86scanpci() - Return info about all PCI devices + * xf86GetPciDomain() - Return domain number from a PCITAG + * xf86MapDomainMemory() - Like xf86MapPciMem() but can handle + * domain/host address translation + * xf86MapDomainIO() - Maps PCI I/O spaces + * xf86ReadDomainMemory() - Like xf86ReadPciBIOS() but can handle + * domain/host address translation + * + * The actual PCI backend driver is selected by the pciInit() function + * (see below) using either compile time definitions, run-time checks, + * or both. + * + * Certain generic functions are provided that make the implementation + * of certain well behaved platforms (e.g. those supporting PCI config + * mechanism 1 or some thing close to it) very easy. + * + * Less well behaved platforms/OS's can roll their own functions. + * + * To add support for another platform/OS, add a call to fooPciInit() within + * pciInit() below under the correct compile time definition or run-time + * conditional. + * + * The fooPciInit() procedure must do three things: + * 1) Initialize the pciBusTable[] for all primary PCI buses including + * the per domain PCI access functions (readLong, writeLong, + * addrBusToHost, and addrHostToBus). + * + * 2) Add entries to pciBusTable[] for configured secondary buses. This + * step may be skipped if a platform is using the generic findFirst/ + * findNext functions because these procedures will automatically + * discover and add secondary buses dynamically. + * + * 3) Overide default settings for global PCI access functions if + * required. These include pciFindFirstFP, pciFindNextFP, + * Of course, if you choose not to use one of the generic + * functions, you will need to provide a platform specifc replacement. + * + * 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. + * + * This software is derived from the original XFree86 PCI code + * which includes the following copyright notices as well: + * + * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org> + * + * 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 names of the above listed copyright holder(s) + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holder(s) make(s) no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + * + * This code is also based heavily on the code in FreeBSD-current, which was + * written by Wolfgang Stanglmeier, and contains the following copyright: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <errno.h> +#include <signal.h> +#include <X11/Xarch.h> +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" +#include "Pci.h" + +#define PCI_MFDEV_SUPPORT 1 /* Include PCI multifunction device support */ +#define PCI_BRIDGE_SUPPORT 1 /* Include support for PCI-to-PCI bridges */ + +/* + * Global data + */ +static int pciInitialized = 0; + +CARD32 pciDevid; /* Requested device/vendor ID (after mask) */ +CARD32 pciDevidMask; /* Bit mask applied (AND) before comparison */ + /* of real devid's with requested */ + +int pciBusNum; /* Bus Number of current device */ +int pciDevNum; /* Device number of current device */ +int pciFuncNum; /* Function number of current device */ +PCITAG pciDeviceTag; /* Tag for current device */ + +pciBusInfo_t *pciBusInfo[MAX_PCI_BUSES] = { NULL, }; +int pciNumBuses = 0; /* Actual number of PCI buses */ +int pciMaxBusNum = MAX_PCI_BUSES; +static Bool inProbe = FALSE; + +static pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, }; + +/* + * Platform specific PCI function pointers. + * + * NOTE: A platform/OS specific pci init procedure can override these defaults + * by setting them to the appropriate platform dependent functions. + */ +PCITAG (*pciFindFirstFP)(void) = pciGenFindFirst; +PCITAG (*pciFindNextFP)(void) = pciGenFindNext; + +/* + * pciInit - choose correct platform/OS specific PCI init routine + */ +void +pciInit() +{ + if (pciInitialized) + return; + + pciInitialized = 1; + + /* XXX */ +#if defined(DEBUGPCI) + if (DEBUGPCI >= xf86Verbose) + xf86Verbose = DEBUGPCI; +#endif + + ARCH_PCI_INIT(); +#if defined(ARCH_PCI_OS_INIT) + if (pciNumBuses <= 0) + ARCH_PCI_OS_INIT(); +#endif +} + +PCITAG +pciFindFirst(CARD32 id, CARD32 mask) +{ +#ifdef DEBUGPCI + ErrorF("pciFindFirst(0x%lx, 0x%lx), pciInit = %d\n", id, mask, pciInitialized); +#endif + pciInit(); + + pciDevid = id & mask; + pciDevidMask = mask; + + return((*pciFindFirstFP)()); +} + +PCITAG +pciFindNext(void) +{ +#ifdef DEBUGPCI + ErrorF("pciFindNext(), pciInit = %d\n", pciInitialized); +#endif + pciInit(); + + return((*pciFindNextFP)()); +} + +CARD32 +pciReadLong(PCITAG tag, int offset) +{ + int bus = PCI_BUS_FROM_TAG(tag); + +#ifdef DEBUGPCI + ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset); +#endif + pciInit(); + + if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciReadLong) { + CARD32 rv = (*pciBusInfo[bus]->funcs->pciReadLong)(tag, offset); + + PCITRACE(1, ("pciReadLong: tag=0x%x [b=%d,d=%d,f=%d] returns 0x%08x\n", + tag, bus, PCI_DEV_FROM_TAG(tag), PCI_FUNC_FROM_TAG(tag), rv)); + return(rv); + } + + return(PCI_NOT_FOUND); +} + +CARD16 +pciReadWord(PCITAG tag, int offset) +{ + CARD32 tmp; + int shift = (offset & 3) * 8; + int aligned_offset = offset & ~3; + int bus = PCI_BUS_FROM_TAG(tag); + + if (shift != 0 && shift != 16) + FatalError("pciReadWord: Alignment error: Cannot read 16 bits " + "at offset %d\n", offset); + + pciInit(); + + if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciReadWord) { + CARD32 rv = (*pciBusInfo[bus]->funcs->pciReadWord)(tag, offset); + + return(rv); + } else { + tmp = pciReadLong(tag, aligned_offset); + + return((CARD16)((tmp >> shift) & 0xffff)); + } +} + +CARD8 +pciReadByte(PCITAG tag, int offset) +{ + CARD32 tmp; + int shift = (offset & 3) * 8; + int aligned_offset = offset & ~3; + int bus = PCI_BUS_FROM_TAG(tag); + + pciInit(); + + if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciReadByte) { + CARD8 rv = (*pciBusInfo[bus]->funcs->pciReadByte)(tag, offset); + + return(rv); + } else { + tmp = pciReadLong(tag, aligned_offset); + + return((CARD8)((tmp >> shift) & 0xff)); + } +} + +void +pciWriteLong(PCITAG tag, int offset, CARD32 val) +{ + int bus = PCI_BUS_FROM_TAG(tag); + + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciWriteLong) + (*pciBusInfo[bus]->funcs->pciWriteLong)(tag, offset, val); +} + +void +pciWriteWord(PCITAG tag, int offset, CARD16 val) +{ + CARD32 tmp; + int aligned_offset = offset & ~3; + int shift = (offset & 3) * 8; + int bus = PCI_BUS_FROM_TAG(tag); + + if (shift != 0 && shift != 16) + FatalError("pciWriteWord: Alignment Error: Cannot read 16 bits " + "from offset %d\n", offset); + + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciWriteWord) { + (*pciBusInfo[bus]->funcs->pciWriteWord)(tag, offset, val); + } else { + tmp = pciReadLong(tag, aligned_offset); + + tmp &= ~(0xffffL << shift); + tmp |= (((CARD32)val) << shift); + + pciWriteLong(tag, aligned_offset, tmp); + } +} + +void +pciWriteByte(PCITAG tag, int offset, CARD8 val) +{ + CARD32 tmp; + int aligned_offset = offset & ~3; + int shift = (offset & 3) *8 ; + int bus = PCI_BUS_FROM_TAG(tag); + + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciWriteByte) { + (*pciBusInfo[bus]->funcs->pciWriteByte)(tag, offset, val); + } else { + + tmp = pciReadLong(tag, aligned_offset); + + tmp &= ~(0xffL << shift); + tmp |= (((CARD32)val) << shift); + + pciWriteLong(tag, aligned_offset, tmp); + } +} + +void +pciSetBitsLong(PCITAG tag, int offset, CARD32 mask, CARD32 val) +{ + int bus = PCI_BUS_FROM_TAG(tag); + +#ifdef DEBUGPCI + ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset); +#endif + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciSetBitsLong) { + (*pciBusInfo[bus]->funcs->pciSetBitsLong)(tag, offset, mask, val); + } +} + +void +pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val) +{ + CARD32 tmp_mask, tmp_val; + int aligned_offset = offset & ~3; + int shift = (offset & 3) *8 ; + + tmp_mask = mask << shift; + tmp_val = val << shift; + pciSetBitsLong(tag, aligned_offset, tmp_mask, tmp_val); +} + +ADDRESS +pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + int bus = PCI_BUS_FROM_TAG(tag); + + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciAddrBusToHost) + return (*pciBusInfo[bus]->funcs->pciAddrBusToHost)(tag, type, addr); + else + return(addr); +} + +ADDRESS +pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + int bus = PCI_BUS_FROM_TAG(tag); + + pciInit(); + + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciAddrHostToBus) + return (*pciBusInfo[bus]->funcs->pciAddrHostToBus)(tag, type, addr); + else + return(addr); +} + +/* + * pciGetBaseSize() returns the size of a PCI base address mapping in bits. + * The index identifies the base register: 0-5 are the six standard registers, + * and 6 is the ROM base register. If destructive is TRUE, it will write + * to the base address register to get an accurate result. Otherwise it + * makes a conservative guess based on the alignment of the already allocated + * address. If the result is accurate (ie, not an over-estimate), this is + * indicated by setting *min to TRUE (when min is non-NULL). This happens + * when either the destructive flag is set, the information is supplied by + * the OS if the OS supports this. + */ + +int +pciGetBaseSize(PCITAG tag, int index, Bool destructive, Bool *min) +{ + int offset; + CARD32 addr1; + CARD32 addr2; + CARD32 mask1; + CARD32 mask2; + int bits = 0; + + /* + * Eventually a function for this should be added to pciBusFuncs_t, but for + * now we'll just use a simple method based on the alignment of the already + * allocated address. + */ + + /* + * silently ignore bogus index values. Valid values are 0-6. 0-5 are + * the 6 base address registers, and 6 is the ROM base address register. + */ + if (index < 0 || index > 6) + return 0; + + pciInit(); + + if (xf86GetPciSizeFromOS(tag, index, &bits)) { + if (min) + *min = TRUE; + return bits; + } + + if (min) + *min = destructive; + + /* Get the PCI offset */ + if (index == 6) + offset = PCI_MAP_ROM_REG; + else + offset = PCI_MAP_REG_START + (index << 2); + + addr1 = pciReadLong(tag, offset); + /* + * Check if this is the second part of a 64 bit address. + * XXX need to check how endianness affects 64 bit addresses. + */ + if (index > 0 && index < 6) { + addr2 = pciReadLong(tag, offset - 4); + if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2)) + return 0; + } + + if (destructive) { + pciWriteLong(tag, offset, 0xffffffff); + mask1 = pciReadLong(tag, offset); + pciWriteLong(tag, offset, addr1); + } else { + mask1 = addr1; + } + + /* Check if this is the first part of a 64 bit address. */ + if (index < 5 && PCI_MAP_IS_MEM(mask1) && PCI_MAP_IS64BITMEM(mask1)) { + if (PCIGETMEMORY(mask1) == 0) { + addr2 = pciReadLong(tag, offset + 4); + if (destructive) { + pciWriteLong(tag, offset + 4, 0xffffffff); + mask2 = pciReadLong(tag, offset + 4); + pciWriteLong(tag, offset + 4, addr2); + } else { + mask2 = addr2; + } + if (mask2 == 0) + return 0; + bits = 32; + while ((mask2 & 1) == 0) { + bits++; + mask2 >>= 1; + } + if (bits > 32) + return bits; + } + } + if (index < 6) + if (PCI_MAP_IS_MEM(mask1)) + mask1 = PCIGETMEMORY(mask1); + else + mask1 = PCIGETIO(mask1); + else + mask1 = PCIGETROM(mask1); + if (mask1 == 0) + return 0; + bits = 0; + while ((mask1 & 1) == 0) { + bits++; + mask1 >>= 1; + } + /* I/O maps can be no larger than 8 bits */ + + if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8) + bits = 8; + /* ROM maps can be no larger than 24 bits */ + if (index == 6 && bits > 24) + bits = 24; + return bits; +} + +PCITAG +pciTag(int busnum, int devnum, int funcnum) +{ + return(PCI_MAKE_TAG(busnum,devnum,funcnum)); +} + +#if defined(PCI_MFDEV_SUPPORT) || defined(PowerMAX_OS) + +Bool +pciMfDev(int busnum, int devnum) +{ + PCITAG tag0, tag1; + CARD32 id0, id1, val; + + /* Detect a multi-function device that complies to the PCI 2.0 spec */ + + tag0 = PCI_MAKE_TAG(busnum, devnum, 0); + id0 = pciReadLong(tag0, PCI_ID_REG); + if ((CARD16)(id0 + 1) <= (CARD16)1UL) + return FALSE; + + val = pciReadLong(tag0, PCI_HEADER_MISC) & 0x00ff0000; + if ((val != 0x00ff0000) && (val & PCI_HEADER_MULTIFUNCTION)) + return TRUE; + + /* + * Now, to find non-compliant devices... + * If there is a valid ID for function 1 and the ID for func 0 and 1 + * are different, or the base0 values of func 0 and 1 are differend, + * then assume there is a multi-function device. + */ + tag1 = PCI_MAKE_TAG(busnum, devnum, 1); + id1 = pciReadLong(tag1, PCI_ID_REG); + if ((CARD16)(id1 + 1) <= (CARD16)1UL) + return FALSE; + + /* Vendor IDs should match */ + if ((id0 ^ id1) & 0x0000ffff) + return FALSE; + + if ((id0 != id1) || + /* Note the following test is valid for header types 0, 1 and 2 */ + (pciReadLong(tag0, PCI_MAP_REG_START) != + pciReadLong(tag1, PCI_MAP_REG_START))) + return TRUE; + + return FALSE; +} + +#endif + +/* + * Generic find/read/write functions + */ +PCITAG +pciGenFindNext(void) +{ + CARD32 devid, tmp; + int sec_bus, pri_bus; + static int previousBus = 0; + Bool speculativeProbe = FALSE; + unsigned char base_class, sub_class; + +#ifdef DEBUGPCI + ErrorF("pciGenFindNext\n"); +#endif + + for (;;) { + +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pciBusNum %d\n", pciBusNum); +#endif + if (pciBusNum == -1) { + /* + * Start at top of the order + */ + if (pciNumBuses <= 0) + return(PCI_NOT_FOUND); + + /* Skip ahead to the first bus defined by pciInit() */ + for (pciBusNum = 0; !pciBusInfo[pciBusNum]; ++pciBusNum); + pciFuncNum = 0; + pciDevNum = 0; + previousBus = pciBusNum; /* make sure previousBus exists */ + } else { +#ifdef PCI_MFDEV_SUPPORT +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pciFuncNum %d\n", pciFuncNum); +#endif + /* + * Somewhere in middle of order. Determine who's + * next up + */ + if (pciFuncNum == 0) { + /* + * Is current dev a multifunction device? + */ + if (!speculativeProbe && pciMfDev(pciBusNum, pciDevNum)) + /* Probe for other functions */ + pciFuncNum = 1; + else + /* + * No more functions this device. Next + * device please + */ + pciDevNum ++; + } else if (++pciFuncNum >= 8) { + /* No more functions for this device. Next device please */ + pciFuncNum = 0; + pciDevNum ++; + } +#else + pciDevNum ++; +#endif + if (pciDevNum >= 32 || + !pciBusInfo[pciBusNum] || + pciDevNum >= pciBusInfo[pciBusNum]->numDevices) { +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: next bus\n"); +#endif + /* + * No more devices for this bus. Next bus please + */ + if (speculativeProbe) { + NextSpeculativeBus: + xfree(pciBusInfo[pciBusNum]); + pciBusInfo[pciBusNum] = NULL; + speculativeProbe = FALSE; + } + + if (++pciBusNum >= pciMaxBusNum) { +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: out of buses\n"); +#endif + /* No more buses. All done for now */ + return(PCI_NOT_FOUND); + } + + pciDevNum = 0; + } + } + +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pciBusInfo[%d] = 0x%lx\n", pciBusNum, pciBusInfo[pciBusNum]); +#endif + if (!pciBusInfo[pciBusNum]) { + pciBusInfo[pciBusNum] = xnfalloc(sizeof(pciBusInfo_t)); + *pciBusInfo[pciBusNum] = *pciBusInfo[previousBus]; + + speculativeProbe = TRUE; + } + + /* + * At this point, pciBusNum, pciDevNum, and pciFuncNum have been + * advanced to the next device. Compute the tag, and read the + * device/vendor ID field. + */ +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: [%d, %d, %d]\n", pciBusNum, pciDevNum, pciFuncNum); +#endif + pciDeviceTag = PCI_MAKE_TAG(pciBusNum, pciDevNum, pciFuncNum); + inProbe = TRUE; + devid = pciReadLong(pciDeviceTag, PCI_ID_REG); + inProbe = FALSE; +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pciDeviceTag = 0x%lx, devid = 0x%lx\n", pciDeviceTag, devid); +#endif + if ((CARD16)(devid + 1U) <= (CARD16)1UL) + continue; /* Nobody home. Next device please */ + + /* + * Some devices mis-decode configuration cycles in such a way as to + * create phantom buses. + */ + if (speculativeProbe && (pciDevNum == 0) && (pciFuncNum == 0) && + (PCI_BUS_NO_DOMAIN(pciBusNum) > 0)) { + for (;;) { + if (++pciDevNum >= pciBusInfo[pciBusNum]->numDevices) + goto NextSpeculativeBus; + if (devid != + pciReadLong(PCI_MAKE_TAG(pciBusNum, pciDevNum, 0), + PCI_ID_REG)) + break; + } + + pciDevNum = 0; + } + + if (pciNumBuses <= pciBusNum) + pciNumBuses = pciBusNum + 1; + + speculativeProbe = FALSE; + previousBus = pciBusNum; + +#ifdef PCI_BRIDGE_SUPPORT + /* + * Before checking for a specific devid, look for enabled + * PCI to PCI bridge devices. If one is found, create and + * initialize a bus info record (if one does not already exist). + */ + tmp = pciReadLong(pciDeviceTag, PCI_CLASS_REG); + base_class = PCI_CLASS_EXTRACT(tmp); + sub_class = PCI_SUBCLASS_EXTRACT(tmp); + if ((base_class == PCI_CLASS_BRIDGE) && + ((sub_class == PCI_SUBCLASS_BRIDGE_PCI) || + (sub_class == PCI_SUBCLASS_BRIDGE_CARDBUS))) { + tmp = pciReadLong(pciDeviceTag, PCI_PCI_BRIDGE_BUS_REG); + sec_bus = PCI_SECONDARY_BUS_EXTRACT(tmp, pciDeviceTag); + pri_bus = PCI_PRIMARY_BUS_EXTRACT(tmp, pciDeviceTag); +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pri_bus %d sec_bus %d\n", + pri_bus, sec_bus); +#endif + if (pciBusNum != pri_bus) { + /* Some bridges do not implement the primary bus register */ + if ((PCI_BUS_NO_DOMAIN(pri_bus) != 0) || + (sub_class != PCI_SUBCLASS_BRIDGE_CARDBUS)) + xf86Msg(X_WARNING, + "pciGenFindNext: primary bus mismatch on PCI" + " bridge 0x%08lx (0x%02x, 0x%02x)\n", + pciDeviceTag, pciBusNum, pri_bus); + pri_bus = pciBusNum; + } + if ((pri_bus < sec_bus) && (sec_bus < pciMaxBusNum) && + pciBusInfo[pri_bus]) { + /* + * Found a secondary PCI bus + */ + if (!pciBusInfo[sec_bus]) { + pciBusInfo[sec_bus] = xnfalloc(sizeof(pciBusInfo_t)); + + /* Copy parents settings... */ + *pciBusInfo[sec_bus] = *pciBusInfo[pri_bus]; + } + + /* ...but not everything same as parent */ + pciBusInfo[sec_bus]->primary_bus = pri_bus; + pciBusInfo[sec_bus]->secondary = TRUE; + pciBusInfo[sec_bus]->numDevices = 32; + + if (pciNumBuses <= sec_bus) + pciNumBuses = sec_bus + 1; + } + } +#endif + + /* + * Does this device match the requested devid after + * applying mask? + */ +#ifdef DEBUGPCI + ErrorF("pciGenFindNext: pciDevidMask = 0x%lx, pciDevid = 0x%lx\n", pciDevidMask, pciDevid); +#endif + if ((devid & pciDevidMask) == pciDevid) + /* Yes - Return it. Otherwise, next device */ + return(pciDeviceTag); /* got a match */ + + } /* for */ + /*NOTREACHED*/ +} + +PCITAG +pciGenFindFirst(void) +{ + /* Reset PCI bus number to start from top */ + pciBusNum = -1; + + return pciGenFindNext(); +} + +CARD32 +pciByteSwap(CARD32 u) +{ +#if X_BYTE_ORDER == X_BIG_ENDIAN +# if defined(__powerpc__) && defined(PowerMAX_OS) + CARD32 tmp; + + __inst_stwbrx(u, &tmp, 0); + + return(tmp); + +# else /* !PowerMAX_OS */ + + return lswapl(u); + +# endif /* !PowerMAX_OS */ + +#else /* !BIG_ENDIAN */ + + return(u); + +#endif +} + +ADDRESS +pciAddrNOOP(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + return(addr); +} + +pciConfigPtr * +xf86scanpci(int flags) +{ + pciConfigPtr devp; + pciBusInfo_t *busp; + int idx = 0, i; + PCITAG tag; + static Bool done = FALSE; + + /* + * if we haven't found PCI devices checking for pci_devp may + * result in an endless recursion if platform/OS specific PCI + * bus probing code calls this function from with in it. + */ + if (done || pci_devp[0]) + return pci_devp; + + done = TRUE; + + pciInit(); + +#ifdef XF86SCANPCI_WRAPPER + XF86SCANPCI_WRAPPER(SCANPCI_INIT); +#endif + + tag = pciFindFirst(0,0); /* 0 mask means match any valid device */ + /* Check if no devices, return now */ + if (tag == PCI_NOT_FOUND) { +#ifdef XF86SCANPCI_WRAPPER + XF86SCANPCI_WRAPPER(SCANPCI_TERM); +#endif + return NULL; + } + +#ifdef DEBUGPCI + ErrorF("xf86scanpci: tag = 0x%lx\n", tag); +#endif +#ifndef OLD_FORMAT + xf86MsgVerb(X_INFO, 2, "PCI: PCI scan (all values are in hex)\n"); +#endif + + while (idx < MAX_PCI_DEVICES && tag != PCI_NOT_FOUND) { + devp = xcalloc(1, sizeof(pciDevice)); + if (!devp) { + xf86Msg(X_ERROR, + "xf86scanpci: Out of memory after %d devices!!\n", idx); + return (pciConfigPtr *)NULL; + } + + /* Identify pci device by bus, dev, func, and tag */ + devp->tag = tag; + devp->busnum = PCI_BUS_FROM_TAG(tag); + devp->devnum = PCI_DEV_FROM_TAG(tag); + devp->funcnum = PCI_FUNC_FROM_TAG(tag); + + /* Read config space for this device */ + for (i = 0; i < 17; i++) /* PCI hdr plus 1st dev spec dword */ + devp->cfgspc.dwords[i] = pciReadLong(tag, i * sizeof(CARD32)); + + /* Some broken devices don't implement this field... */ + if (devp->pci_header_type == 0xff) + devp->pci_header_type = 0; + + switch (devp->pci_header_type & 0x7f) { + case 0: + /* Get base address sizes for type 0 headers */ + for (i = 0; i < 7; i++) + devp->basesize[i] = + pciGetBaseSize(tag, i, FALSE, &devp->minBasesize); + break; + + case 1: + case 2: + /* Allow master aborts to complete normally on secondary buses */ + if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN)) + break; + pciWriteByte(tag, PCI_PCI_BRIDGE_CONTROL_REG, + devp->pci_bridge_control & + ~(PCI_PCI_BRIDGE_MASTER_ABORT_EN | + PCI_PCI_BRIDGE_SECONDARY_RESET)); + break; + + default: + break; + } + +#ifdef OLD_FORMAT + xf86MsgVerb(X_INFO, 2, "PCI: BusID 0x%.2x,0x%02x,0x%1x " + "ID 0x%04x,0x%04x Rev 0x%02x Class 0x%02x,0x%02x\n", + devp->busnum, devp->devnum, devp->funcnum, + devp->pci_vendor, devp->pci_device, devp->pci_rev_id, + devp->pci_base_class, devp->pci_sub_class); +#else + xf86MsgVerb(X_INFO, 2, "PCI: %.2x:%02x:%1x: chip %04x,%04x" + " card %04x,%04x rev %02x class %02x,%02x,%02x hdr %02x\n", + devp->busnum, devp->devnum, devp->funcnum, + devp->pci_vendor, devp->pci_device, + devp->pci_subsys_vendor, devp->pci_subsys_card, + devp->pci_rev_id, devp->pci_base_class, + devp->pci_sub_class, devp->pci_prog_if, + devp->pci_header_type); +#endif + + pci_devp[idx++] = devp; + tag = pciFindNext(); + +#ifdef DEBUGPCI + ErrorF("xf86scanpci: tag = pciFindNext = 0x%lx\n", tag); +#endif + } + + /* Restore modified data (in reverse order), and link buses */ + while (--idx >= 0) { + devp = pci_devp[idx]; + switch (devp->pci_header_type & 0x7f) { + case 0: + if ((devp->pci_base_class != PCI_CLASS_BRIDGE) || + (devp->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST)) + break; + pciBusInfo[devp->busnum]->bridge = devp; + pciBusInfo[devp->busnum]->primary_bus = devp->busnum; + break; + + case 1: + case 2: + i = PCI_SECONDARY_BUS_EXTRACT(devp->pci_pp_bus_register, devp->tag); + if (i > devp->busnum) { + if (pciBusInfo[i]) { + pciBusInfo[i]->bridge = devp; + /* + * The back link needs to be set here, and is unlikely to + * change. + */ + devp->businfo = pciBusInfo[i]; + } +#ifdef ARCH_PCI_PCI_BRIDGE + ARCH_PCI_PCI_BRIDGE(devp); +#endif + } + if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN)) + break; + pciWriteByte(devp->tag, PCI_PCI_BRIDGE_CONTROL_REG, + devp->pci_bridge_control & ~PCI_PCI_BRIDGE_SECONDARY_RESET); + break; + + default: + break; + } + } + +#ifdef XF86SCANPCI_WRAPPER + XF86SCANPCI_WRAPPER(SCANPCI_TERM); +#endif + + /* + * Lastly, link bridges to their secondary bus, after the architecture has + * had a chance to modify these assignments. + */ + for (idx = 0; idx < pciNumBuses; idx++) { + if (!(busp = pciBusInfo[idx]) || !(devp = busp->bridge)) + continue; + devp->businfo = busp; + } + +#ifndef OLD_FORMAT + xf86MsgVerb(X_INFO, 2, "PCI: End of PCI scan\n"); +#endif + + return pci_devp; +} + +CARD32 +pciCheckForBrokenBase(PCITAG Tag,int basereg) +{ + pciWriteLong(Tag, PCI_MAP_REG_START + (basereg << 2), 0xffffffff); + return pciReadLong(Tag, PCI_MAP_REG_START + (basereg << 2)); +} + +#if defined(INCLUDE_XF86_MAP_PCI_MEM) + +pointer +xf86MapPciMem(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base, + unsigned long Size) +{ + ADDRESS hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM,Base); + pointer base; + CARD32 save = 0; + + /* + * If there are possible read side-effects, disable memory while + * doing the mapping. + */ + if (Flags & VIDMEM_READSIDEEFFECT) { + save = pciReadLong(Tag, PCI_CMD_STAT_REG); + pciWriteLong(Tag, PCI_CMD_STAT_REG, + save & ~PCI_CMD_MEM_ENABLE); + } + base = xf86MapDomainMemory(ScreenNum, Flags, Tag, hostbase, Size); + if (!base) { + FatalError("xf86MapPciMem: Could not mmap PCI memory " + "[base=0x%lx,hostbase=0x%lx,size=%lx] (%s)\n", + Base, hostbase, Size, strerror(errno)); + } + /* + * If read side-effects, do whatever might be needed to prevent + * unintended reads, then restore PCI_CMD_STAT_REG. + */ + if (Flags & VIDMEM_READSIDEEFFECT) { + xf86MapReadSideEffects(ScreenNum, Flags, base, Size); + pciWriteLong(Tag, PCI_CMD_STAT_REG, save); + } + return((pointer)base); +} + +static int +handlePciBIOS(PCITAG Tag, int basereg, + int (*func)(PCITAG, CARD8*, ADDRESS, pointer), + pointer args) +{ + CARD32 romsave = 0; + int i; + romBaseSource b_reg; + ADDRESS hostbase; + CARD8 tmp[64]; + int ret = 0; + + romsave = pciReadLong(Tag, PCI_MAP_ROM_REG); + + for (i = ROM_BASE_PRESET; i <= ROM_BASE_FIND; i++) { + memType savebase = 0, newbase, romaddr; + + switch (i) { + case ROM_BASE_PRESET: + /* Does the driver have a preference? */ + if (basereg > ROM_BASE_PRESET && basereg <= ROM_BASE_FIND) + b_reg = basereg; + else + b_reg = ++i; + break; + case ROM_BASE_FIND: + /* + * If we have something that looks like a valid address + * in romsave, it's probably not going to help to try + * to guess a new address and reprogram it. + */ + if (PCIGETROM(romsave)) { + pciWriteLong(Tag, PCI_MAP_ROM_REG, PCI_MAP_ROM_ADDRESS_MASK); + if (romsave != pciReadLong(Tag, PCI_MAP_ROM_REG)) { + pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave); + continue; + } + } + default: + b_reg = i; + } + + if (!(newbase = getValidBIOSBase(Tag, b_reg))) + continue; /* no valid address found */ + + romaddr = PCIGETROM(newbase); + + /* if we use a mem base save it and move it out of the way */ + if (b_reg >= 0 && b_reg <= 5) { + savebase = pciReadLong(Tag, PCI_MAP_REG_START+(b_reg<<2)); + xf86MsgVerb(X_INFO,5,"xf86ReadPciBios: modifying membase[%i]" + " for device %i:%i:%i\n", basereg, + (int)PCI_BUS_FROM_TAG(Tag), (int)PCI_DEV_FROM_TAG(Tag), + (int)PCI_FUNC_FROM_TAG(Tag)); + pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2), + (CARD32)~0); + } + /* Set ROM base address and enable ROM address decoding */ + pciWriteLong(Tag, PCI_MAP_ROM_REG, romaddr + | PCI_MAP_ROM_DECODE_ENABLE); + + hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM, PCIGETROM(romaddr)); + + if ((xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp) != + sizeof(tmp)) || + (tmp[0] != 0x55) || (tmp[1] != 0xaa) || !tmp[2] ) { + /* Restore the base registers if they were changed. */ + pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave); + if (savebase) pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2), + (CARD32) savebase); + + /* No BIOS found: try another address */ + continue; + } + + ret = (*func)(Tag, tmp, hostbase, args); + + /* Restore the base register if it was changed. */ + if (savebase) pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2), + (CARD32) savebase); + /* Restore ROM address decoding */ + pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave); + + return ret; + } + /* Restore ROM address decoding */ + pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave); + return 0; +} + +typedef struct { + unsigned long Offset; + int Len; + unsigned char *Buf; + PciBiosType BiosType; +} readBios, *readBiosPtr; + +static int +readPciBios(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer args) +{ + unsigned int image_length = 0; + readBiosPtr rd = args; + int ret; + + /* We found a PCI BIOS Image. Now we look for the correct type */ + while ((tmp[0] == 0x55) && (tmp[1] == 0xAA)) { + unsigned short data_off = tmp[0x18] | (tmp[0x19] << 8); + unsigned char data[0x18]; + unsigned char type; + + if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data) + != sizeof(data)) || + (data[0] != 'P') || + (data[1] != 'C') || + (data[2] != 'I') || + (data[3] != 'R')) + break; + type = data[0x14]; +#ifdef PRINT_PCI + ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type); +#endif + if (type != rd->BiosType) { /* not correct image: find next one */ + unsigned char indicator = data[0x15]; + unsigned int i_length; + if (indicator & 0x80) /* last image */ + break; + i_length = (data[0x10] | (data[0x11] << 8)) << 9; +#ifdef PRINT_PCI + ErrorF("data image length: 0x%x, ind: 0x%x\n", + image_length, indicator); +#endif + hostbase += i_length; + if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp) + != sizeof(tmp)) + break; + continue; + } + /* OK, we have a PCI BIOS Image of the correct type */ + + if (rd->BiosType == PCI_BIOS_PC) + image_length = tmp[2] << 9; + else + image_length = (data[0x10] | (data[0x11] << 8)) << 9; +#ifdef PRINT_PCI + ErrorF("BIOS length: 0x%x\n", image_length); +#endif + break; + } + + ret = 0; + if (image_length) { + + /* + * if no length is given return the full lenght, + * Offset 0. Beware: Area pointed to by Buf must + * be large enough! + */ + if (rd->Len == 0) { + rd->Len = image_length; + rd->Offset = 0; + } + if ((rd->Offset) > (image_length)) { + xf86Msg(X_WARNING,"xf86ReadPciBios: requesting data past " + "end of BIOS %li > %i\n",(rd->Offset) , (image_length)); + } else { + if ((rd->Offset + rd->Len) > (image_length)) { + rd->Len = (image_length) - rd->Offset; + xf86MsgVerb(X_INFO,3,"Truncating PCI BIOS Length to %i\n",rd->Len); + } + } + + /* Read BIOS */ + ret = xf86ReadDomainMemory(Tag, hostbase + rd->Offset, rd->Len, rd->Buf); + } + + return ret; +} + +static int +getPciBIOSTypes(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer arg) +{ + int n = 0; + PciBiosType *Buf = arg; + + /* We found a PCI BIOS Image. Now we collect the types type */ + do { + unsigned short data_off = tmp[0x18] | (tmp[0x19] << 8); + unsigned char data[0x16]; + unsigned int i_length; + + if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data) + != sizeof(data)) || + (data[0] != 'P') || + (data[1] != 'C') || + (data[2] != 'I') || + (data[3] != 'R')) + break; + + if (data[0x14] >= PCI_BIOS_OTHER) + *Buf++ = PCI_BIOS_OTHER; + else + *Buf++ = data[0x14]; + + n++; + if (data[0x15] & 0x80) /* last image */ + break; +#ifdef PRINT_PCI + ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type); +#endif + i_length = (data[0x10] | (data[0x11] << 8)) << 9; +#ifdef PRINT_PCI + ErrorF("data image length: 0x%x, ind: 0x%x\n", + image_length, indicator); +#endif + hostbase += i_length; + if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp) + != sizeof(tmp)) + break; + continue; + } while ((tmp[0] == 0x55) && (tmp[1] == 0xAA)); + return n; +} + +typedef CARD32 (*ReadProcPtr)(PCITAG, int); +typedef void (*WriteProcPtr)(PCITAG, int, CARD32); + +static int +HandlePciBios(PCITAG Tag, int basereg, + int (*func)(PCITAG, CARD8*, ADDRESS, pointer), + pointer ptr) +{ + int n, num; + CARD32 Acc1, Acc2; + PCITAG *pTag; + int i; + + n = handlePciBIOS(Tag,basereg,func,ptr); + if (n) + return n; + + num = pciTestMultiDeviceCard(PCI_BUS_FROM_TAG(Tag), + PCI_DEV_FROM_TAG(Tag), + PCI_FUNC_FROM_TAG(Tag),&pTag); + + if (!num) return 0; + +#define PCI_ENA (PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE) + Acc1 = pciReadLong(Tag, PCI_CMD_STAT_REG); + pciWriteLong(Tag, PCI_CMD_STAT_REG, (Acc1 & ~PCI_ENA)); + + for (i = 0; i < num; i++) { + Acc2 = pciReadLong(pTag[i], PCI_CMD_STAT_REG); + pciWriteLong(pTag[i], PCI_CMD_STAT_REG, (Acc2 | PCI_ENA)); + + n = handlePciBIOS(pTag[i],0,func,ptr); + + pciWriteLong(pTag[i], PCI_CMD_STAT_REG, Acc2); + if (n) + break; + } + pciWriteLong(Tag, PCI_CMD_STAT_REG, Acc1); + return n; +} + +int +xf86ReadPciBIOS(unsigned long Offset, PCITAG Tag, int basereg, + unsigned char *Buf, int Len) +{ + return xf86ReadPciBIOSByType(Offset, Tag, basereg, Buf, Len, PCI_BIOS_PC); +} + +int +xf86ReadPciBIOSByType(unsigned long Offset, PCITAG Tag, int basereg, + unsigned char *Buf, int Len, PciBiosType Type) +{ + + readBios rb; + rb.Offset = Offset; + rb.Len = Len; + rb.Buf = Buf; + rb.BiosType = Type; + + return HandlePciBios(Tag, basereg, readPciBios, &rb); +} + +int +xf86GetAvailablePciBIOSTypes(PCITAG Tag, int basereg, PciBiosType *Buf) +{ + return HandlePciBios(Tag, basereg, getPciBIOSTypes, (pointer) Buf); +} + +#endif /* INCLUDE_XF86_MAP_PCI_MEM */ + +#ifdef INCLUDE_XF86_NO_DOMAIN + +int +xf86GetPciDomain(PCITAG Tag) +{ + return 0; +} + +pointer +xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size) +{ + return xf86MapVidMem(ScreenNum, Flags, Base, Size); +} + +IOADDRESS +xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, + IOADDRESS Base, unsigned long Size) +{ + return Base; +} + +int +xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) +{ + int ret, length, rlength; + + /* Read in 64kB chunks */ + ret = 0; + while ((length = Len) > 0) { + if (length > 0x010000) length = 0x010000; + rlength = xf86ReadBIOS(Base, 0, Buf, length); + if (rlength < 0) { + ret = rlength; + break; + } + ret += rlength; + if (rlength < length) break; + Base += rlength; + Buf += rlength; + Len -= rlength; + } + + return ret; +} + +#endif /* INCLUDE_XF86_NO_DOMAIN */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.h new file mode 100644 index 000000000..70293d3f4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Pci.h @@ -0,0 +1,449 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.h,v 1.45 2004/02/02 03:55:31 dawes Exp $ */ +/* + * 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. + * + * This file is derived in part from the original xf86_PCI.h that included + * following copyright message: + * + * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org> + * + * 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 names of the above listed copyright holder(s) + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holder(s) make(s) no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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 (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file has the private Pci definitions. The public ones are imported + * from xf86Pci.h. Drivers should not use this file. + */ +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _PCI_H +#define _PCI_H 1 + +#include <X11/Xarch.h> +#include <X11/Xfuncproto.h> +#include "xf86Pci.h" +#include "xf86PciInfo.h" + +/* + * Global Definitions + */ +#define MAX_PCI_DEVICES 128 /* Max number of devices accomodated */ + /* by xf86scanpci */ +#if defined(sun) && defined(SVR4) && defined(sparc) +# define MAX_PCI_BUSES 4096 /* Max number of PCI buses */ +#elif defined(__alpha__) && defined (linux) +# define MAX_PCI_DOMAINS 512 +# define PCI_DOM_MASK 0x01fful +# define MAX_PCI_BUSES (MAX_PCI_DOMAINS*256) /* 256 per domain */ +#else +# define MAX_PCI_BUSES 256 /* Max number of PCI buses */ +#endif + +#define DEVID(vendor, device) \ + ((CARD32)((PCI_##device << 16) | PCI_##vendor)) + +#ifndef PCI_DOM_MASK +# define PCI_DOM_MASK 0x0ffu +#endif +#define PCI_DOMBUS_MASK (((PCI_DOM_MASK) << 8) | 0x0ffu) + +/* + * "b" contains an optional domain number. + */ +#define PCI_MAKE_TAG(b,d,f) ((((b) & (PCI_DOMBUS_MASK)) << 16) | \ + (((d) & 0x00001fu) << 11) | \ + (((f) & 0x000007u) << 8)) + +#define PCI_MAKE_BUS(d,b) ((((d) & (PCI_DOM_MASK)) << 8) | ((b) & 0xffu)) + +#define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK)) +#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK)) +#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11) +#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8) + +#define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00u) >> 8) +#define PCI_BDEV_FROM_TAG(tag) ((tag) & 0x00fff800u) + +#define PCI_DOM_FROM_BUS(bus) (((bus) >> 8) & (PCI_DOM_MASK)) +#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu) +#define PCI_TAG_NO_DOMAIN(tag) ((tag) & 0x00ffff00u) + +/* + * Macros for bus numbers found in P2P headers. + */ +#define PCI_PRIMARY_BUS_EXTRACT(x, tag) \ + ((((x) & PCI_PRIMARY_BUS_MASK ) >> 0) | (PCI_DOM_FROM_TAG(tag) << 8)) +#define PCI_SECONDARY_BUS_EXTRACT(x, tag) \ + ((((x) & PCI_SECONDARY_BUS_MASK ) >> 8) | (PCI_DOM_FROM_TAG(tag) << 8)) +#define PCI_SUBORDINATE_BUS_EXTRACT(x, tag) \ + ((((x) & PCI_SUBORDINATE_BUS_MASK) >> 16) | (PCI_DOM_FROM_TAG(tag) << 8)) + +#define PCI_PRIMARY_BUS_INSERT(x, y) \ + (((x) & ~PCI_PRIMARY_BUS_MASK ) | (((y) & 0xffu) << 0)) +#define PCI_SECONDARY_BUS_INSERT(x, y) \ + (((x) & ~PCI_SECONDARY_BUS_MASK ) | (((y) & 0xffu) << 8)) +#define PCI_SUBORDINATE_BUS_INSERT(x, y) \ + (((x) & ~PCI_SUBORDINATE_BUS_MASK) | (((y) & 0xffu) << 16)) + +/* Ditto for CardBus bridges */ +#define PCI_CB_PRIMARY_BUS_EXTRACT(x, tag) \ + PCI_PRIMARY_BUS_EXTRACT(x, tag) +#define PCI_CB_CARDBUS_BUS_EXTRACT(x, tag) \ + PCI_SECONDARY_BUS_EXTRACT(x, tag) +#define PCI_CB_SUBORDINATE_BUS_EXTRACT(x, tag) \ + PCI_SUBORDINATE_BUS_EXTRACT(x, tag) + +#define PCI_CB_PRIMARY_BUS_INSERT(x, tag) \ + PCI_PRIMARY_BUS_INSERT(x, tag) +#define PCI_CB_CARDBUS_BUS_INSERT(x, tag) \ + PCI_SECONDARY_BUS_INSERT(x, tag) +#define PCI_CB_SUBORDINATE_BUS_INSERT(x, tag) \ + PCI_SUBORDINATE_BUS_INSERT(x, tag) + +#if X_BYTE_ORDER == X_BIG_ENDIAN +#define PCI_CPU(val) (((val >> 24) & 0x000000ff) | \ + ((val >> 8) & 0x0000ff00) | \ + ((val << 8) & 0x00ff0000) | \ + ((val << 24) & 0xff000000)) +#define PCI_CPU16(val) (((val >> 8) & 0x000000ff) | \ + ((val << 8) & 0x0000ff00)) +#else +#define PCI_CPU(val) (val) +#define PCI_CPU16(val) (val) +#endif + +/* + * Debug Macros/Definitions + */ +/* #define DEBUGPCI 2 */ /* Disable/enable trace in PCI code */ + +#if defined(DEBUGPCI) + +# define PCITRACE(lvl,printfargs) \ + if (lvl > xf86Verbose) { \ + ErrorF printfargs; \ + } + +#else /* !defined(DEBUGPCI) */ + +# define PCITRACE(lvl,printfargs) + +#endif /* !defined(DEBUGPCI) */ + +/* + * PCI Config mechanism definitions + */ +#define PCI_EN 0x80000000 + +#define PCI_CFGMECH1_ADDRESS_REG 0xCF8 +#define PCI_CFGMECH1_DATA_REG 0xCFC + +#define PCI_CFGMECH1_MAXDEV 32 + +/* + * Select architecture specific PCI init function + */ +#if defined(__alpha__) +# if defined(linux) +# define ARCH_PCI_INIT axpPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# elif defined(__FreeBSD__) || defined(__OpenBSD__) +# define ARCH_PCI_INIT freebsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# elif defined(__NetBSD__) +# define ARCH_PCI_INIT netbsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__arm__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__hppa__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__ia64__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# elif defined(FreeBSD) +# define ARCH_PCI_INIT freebsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +# define XF86SCANPCI_WRAPPER ia64ScanPCIWrapper +#elif defined(__i386__) || defined(i386) +# define ARCH_PCI_INIT ix86PciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# if defined(linux) +# define ARCH_PCI_OS_INIT linuxPciInit +# endif +#elif defined(__mc68000__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__mips__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__powerpc__) || defined(__powerpc64__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN /* Needs kernel work to remove */ +# elif defined(__FreeBSD__) || defined(__OpenBSD__) +# define ARCH_PCI_INIT freebsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# elif defined(__NetBSD__) +# define ARCH_PCI_INIT netbsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# elif defined(PowerMAX_OS) /* This port is broken */ +# define ARCH_PCI_INIT ppcPciInit +# else +# define ARCH_PCI_INIT ppcPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__s390__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__sh__) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +#elif defined(__sparc__) || defined(sparc) +# if defined(linux) +# define ARCH_PCI_INIT linuxPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# elif defined(sun) +# define ARCH_PCI_INIT sparcPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && defined(__sparc64__) +# define ARCH_PCI_INIT freebsdPciInit +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# endif +# if !defined(__FreeBSD__) +# define ARCH_PCI_PCI_BRIDGE sparcPciPciBridge +# endif +#elif defined(__amd64__) || defined(__amd64) +# if defined(__FreeBSD__) +# define ARCH_PCI_INIT freebsdPciInit +# else +# define ARCH_PCI_INIT ix86PciInit +# endif +# define INCLUDE_XF86_MAP_PCI_MEM +# define INCLUDE_XF86_NO_DOMAIN +# if defined(linux) +# define ARCH_PCI_OS_INIT linuxPciInit +# endif +#endif + +#ifndef ARCH_PCI_INIT +#error No PCI support available for this architecture/OS combination +#endif + +extern void ARCH_PCI_INIT(void); +#if defined(ARCH_PCI_OS_INIT) +extern void ARCH_PCI_OS_INIT(void); +#endif + +#if defined(ARCH_PCI_PCI_BRIDGE) +extern void ARCH_PCI_PCI_BRIDGE(pciConfigPtr pPCI); +#endif + +#if defined(XF86SCANPCI_WRAPPER) +typedef enum { + SCANPCI_INIT, + SCANPCI_TERM +} scanpciWrapperOpt; +extern void XF86SCANPCI_WRAPPER(scanpciWrapperOpt flags); +#endif + +/* + * Table of functions used to access a specific PCI bus domain + * (e.g. a primary PCI bus and all of its secondaries) + */ +typedef struct pci_bus_funcs { + CARD32 (*pciReadLong)(PCITAG, int); + void (*pciWriteLong)(PCITAG, int, CARD32); + void (*pciSetBitsLong)(PCITAG, int, CARD32, CARD32); + ADDRESS (*pciAddrHostToBus)(PCITAG, PciAddrType, ADDRESS); + ADDRESS (*pciAddrBusToHost)(PCITAG, PciAddrType, ADDRESS); + /* + * The next three are optional. If NULL, the corresponding function is + * to be performed generically. + */ + CARD16 (*pciControlBridge)(int, CARD16, CARD16); + void (*pciGetBridgeBuses)(int, int *, int *, int *); + /* Use pointer's to avoid #include recursion */ + void (*pciGetBridgeResources)(int, pointer *, pointer *, pointer *); + + /* These are optional and will be implemented using read long + * if not present. */ + CARD8 (*pciReadByte)(PCITAG, int); + void (*pciWriteByte)(PCITAG, int, CARD8); + CARD16 (*pciReadWord)(PCITAG, int); + void (*pciWriteWord)(PCITAG, int, CARD16); + +} pciBusFuncs_t, *pciBusFuncs_p; + +/* + * pciBusInfo_t - One structure per defined PCI bus + */ +typedef struct pci_bus_info { + unsigned char configMech; /* PCI config type to use */ + unsigned char numDevices; /* Range of valid devnums */ + unsigned char secondary; /* Boolean: bus is a secondary */ + int primary_bus; /* Parent bus */ +#ifdef PowerMAX_OS + unsigned long ppc_io_base; /* PowerPC I/O spc membase */ + unsigned long ppc_io_size; /* PowerPC I/O spc size */ +#endif + pciBusFuncs_p funcs; /* PCI access functions */ + void *pciBusPriv; /* Implementation private data */ + pciConfigPtr bridge; /* bridge that opens this bus */ +} pciBusInfo_t; + +#define HOST_NO_BUS ((pciBusInfo_t *)(-1)) + +/* configMech values */ +#define PCI_CFG_MECH_UNKNOWN 0 /* Not yet known */ +#define PCI_CFG_MECH_1 1 /* Most machines */ +#define PCI_CFG_MECH_2 2 /* Older PC's */ +#define PCI_CFG_MECH_OTHER 3 /* Something else */ + +/* Generic PCI service functions and helpers */ +PCITAG pciGenFindFirst(void); +PCITAG pciGenFindNext(void); +CARD32 pciCfgMech1Read(PCITAG tag, int offset); +void pciCfgMech1Write(PCITAG tag, int offset, CARD32 val); +void pciCfgMech1SetBits(PCITAG tag, int offset, CARD32 mask, + CARD32 val); +CARD32 pciByteSwap(CARD32); +Bool pciMfDev(int, int); +ADDRESS pciAddrNOOP(PCITAG tag, PciAddrType type, ADDRESS); + +extern PCITAG (*pciFindFirstFP)(void); +extern PCITAG (*pciFindNextFP)(void); + +extern CARD32 pciDevid; +extern CARD32 pciDevidMask; + +extern int pciMaxBusNum; + +extern int pciBusNum; +extern int pciDevNum; +extern int pciFuncNum; +extern PCITAG pciDeviceTag; + +extern pciBusInfo_t *pciBusInfo[]; + +#endif /* _PCI_H */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Sbus.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Sbus.c new file mode 100644 index 000000000..168bc669e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/Sbus.c @@ -0,0 +1,637 @@ +/* + * SBUS and OpenPROM access functions. + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Sbus.c,v 1.2tsi Exp $ */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#ifdef sun +#include <sys/utsname.h> +#endif +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#include "xf86sbusBus.h" +#include "xf86Sbus.h" + +int promRootNode; + +static int promFd = -1; +static int promCurrentNode; +static int promOpenCount = 0; +static int promP1275 = -1; +#define MAX_PROP 128 +#define MAX_VAL (4096-128-4) +static struct openpromio *promOpio; + +sbusDevicePtr *xf86SbusInfo = NULL; + +struct sbus_devtable sbusDeviceTable[] = { + { SBUS_DEVICE_BW2, FBTYPE_SUN2BW, "bwtwo", "Sun Monochrome (bwtwo)" }, + { SBUS_DEVICE_CG2, FBTYPE_SUN2COLOR, "cgtwo", "Sun Color2 (cgtwo)" }, + { SBUS_DEVICE_CG3, FBTYPE_SUN3COLOR, "cgthree", "Sun Color3 (cgthree)" }, + { SBUS_DEVICE_CG4, FBTYPE_SUN4COLOR, "cgfour", "Sun Color4 (cgfour)" }, + { SBUS_DEVICE_CG6, FBTYPE_SUNFAST_COLOR, "cgsix", "Sun GX" }, + { SBUS_DEVICE_CG8, FBTYPE_MEMCOLOR, "cgeight", "Sun CG8/RasterOps" }, + { SBUS_DEVICE_CG12, FBTYPE_SUNGP3, "cgtwelve", "Sun GS (cgtwelve)" }, + { SBUS_DEVICE_CG14, FBTYPE_MDICOLOR, "cgfourteen", "Sun SX" }, + { SBUS_DEVICE_GT, FBTYPE_SUNGT, "gt", "Sun Graphics Tower" }, + { SBUS_DEVICE_MGX, -1, "mgx", "Quantum 3D MGXplus" }, + { SBUS_DEVICE_LEO, FBTYPE_SUNLEO, "leo", "Sun ZX or Turbo ZX" }, + { SBUS_DEVICE_TCX, FBTYPE_TCXCOLOR, "tcx", "Sun TCX" }, + { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "ffb", "Sun FFB" }, + { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "afb", "Sun Elite3D" }, + { 0, 0, NULL } +}; + +int +promGetSibling(int node) +{ + promOpio->oprom_size = sizeof(int); + + if (node == -1) return 0; + *(int *)promOpio->oprom_array = node; + if (ioctl(promFd, OPROMNEXT, promOpio) < 0) + return 0; + promCurrentNode = *(int *)promOpio->oprom_array; + return *(int *)promOpio->oprom_array; +} + +int +promGetChild(int node) +{ + promOpio->oprom_size = sizeof(int); + + if (!node || node == -1) return 0; + *(int *)promOpio->oprom_array = node; + if (ioctl(promFd, OPROMCHILD, promOpio) < 0) + return 0; + promCurrentNode = *(int *)promOpio->oprom_array; + return *(int *)promOpio->oprom_array; +} + +char * +promGetProperty(const char *prop, int *lenp) +{ + promOpio->oprom_size = MAX_VAL; + + strcpy(promOpio->oprom_array, prop); + if (ioctl(promFd, OPROMGETPROP, promOpio) < 0) + return 0; + if (lenp) *lenp = promOpio->oprom_size; + return promOpio->oprom_array; +} + +int +promGetBool(const char *prop) +{ + promOpio->oprom_size = 0; + + *(int *)promOpio->oprom_array = 0; + for (;;) { + promOpio->oprom_size = MAX_PROP; + if (ioctl(promFd, OPROMNXTPROP, promOpio) < 0) + return 0; + if (!promOpio->oprom_size) + return 0; + if (!strcmp(promOpio->oprom_array, prop)) + return 1; + } +} + +#define PROM_NODE_SIBLING 0x01 +#define PROM_NODE_PREF 0x02 +#define PROM_NODE_SBUS 0x04 +#define PROM_NODE_EBUS 0x08 +#define PROM_NODE_PCI 0x10 + +static int +promSetNode(sbusPromNodePtr pnode) +{ + int node; + + if (!pnode->node || pnode->node == -1) + return -1; + if (pnode->cookie[0] & PROM_NODE_SIBLING) + node = promGetSibling(pnode->cookie[1]); + else + node = promGetChild(pnode->cookie[1]); + if (pnode->node != node) + return -1; + return 0; +} + +static void +promIsP1275(void) +{ +#ifdef linux + FILE *f; + char buffer[1024]; + + if (promP1275 != -1) + return; + promP1275 = 0; + f = fopen("/proc/cpuinfo","r"); + if (!f) return; + while (fgets(buffer, 1024, f) != NULL) + if (!strncmp (buffer, "type", 4) && strstr (buffer, "sun4u")) { + promP1275 = 1; + break; + } + fclose(f); +#elif defined(sun) + struct utsname buffer; + + if ((uname(&buffer) >= 0) && !strcmp(buffer.machine, "sun4u")) + promP1275 = TRUE; + else + promP1275 = FALSE; +#elif defined(__FreeBSD__) + promP1275 = TRUE; +#else +#error Missing promIsP1275() function for this OS +#endif +} + +void +sparcPromClose(void) +{ + if (promOpenCount > 1) { + promOpenCount--; + return; + } + if (promFd != -1) { + close(promFd); + promFd = -1; + } + if (promOpio) { + xfree(promOpio); + promOpio = NULL; + } + promOpenCount = 0; +} + +int +sparcPromInit(void) +{ + if (promOpenCount) { + promOpenCount++; + return 0; + } + promFd = open("/dev/openprom", O_RDONLY, 0); + if (promFd == -1) + return -1; + promOpio = (struct openpromio *)xalloc(4096); + if (!promOpio) { + sparcPromClose(); + return -1; + } + promRootNode = promGetSibling(0); + if (!promRootNode) { + sparcPromClose(); + return -1; + } + promIsP1275(); + promOpenCount++; + + return 0; +} + +char * +sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp) +{ + if (promSetNode(pnode)) + return NULL; + return promGetProperty(prop, lenp); +} + +int +sparcPromGetBool(sbusPromNodePtr pnode, const char *prop) +{ + if (promSetNode(pnode)) + return 0; + return promGetBool(prop); +} + +static void +promWalkAssignNodes(int node, int oldnode, int flags, sbusDevicePtr *devicePtrs) +{ + int nextnode; + int len, sbus = flags & PROM_NODE_SBUS; + char *prop; + int devId, i, j; + sbusPromNode pNode, pNode2; + + prop = promGetProperty("device_type", &len); + if (prop && (len > 0)) do { + if (!strcmp(prop, "display")) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + break; + while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') + prop++; + for (i = 0; sbusDeviceTable[i].devId; i++) + if (!strcmp(prop, sbusDeviceTable[i].promName)) + break; + devId = sbusDeviceTable[i].devId; + if (!devId) + break; + if (!sbus) { + if (devId == SBUS_DEVICE_FFB) { + /* + * All /SUNW,ffb outside of SBUS tree come before all + * /SUNW,afb outside of SBUS tree in Linux. + */ + if (!strcmp(prop, "afb")) + flags |= PROM_NODE_PREF; + } else if (devId != SBUS_DEVICE_CG14) + break; + } + for (i = 0; i < 32; i++) { + if (!devicePtrs[i] || devicePtrs[i]->devId != devId) + continue; + if (devicePtrs[i]->node.node) { + if ((devicePtrs[i]->node.cookie[0] & ~PROM_NODE_SIBLING) <= + (flags & ~PROM_NODE_SIBLING)) + continue; + for (j = i + 1, pNode = devicePtrs[i]->node; j < 32; j++) { + if (!devicePtrs[j] || devicePtrs[j]->devId != devId) + continue; + pNode2 = devicePtrs[j]->node; + devicePtrs[j]->node = pNode; + pNode = pNode2; + } + } + devicePtrs[i]->node.node = node; + devicePtrs[i]->node.cookie[0] = flags; + devicePtrs[i]->node.cookie[1] = oldnode; + break; + } + break; + } + } while (0); + + prop = promGetProperty("name", &len); + if (prop && len > 0) { + if (!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) + sbus = PROM_NODE_SBUS; + } + + nextnode = promGetChild(node); + if (nextnode) + promWalkAssignNodes(nextnode, node, sbus, devicePtrs); + + nextnode = promGetSibling(node); + if (nextnode) + promWalkAssignNodes(nextnode, node, PROM_NODE_SIBLING | sbus, devicePtrs); +} + +void +sparcPromAssignNodes(void) +{ + sbusDevicePtr psdp, *psdpp; + int n, holes = 0, i, j; + FILE *f; + sbusDevicePtr devicePtrs[32]; + + (void)memset(devicePtrs, 0, sizeof(devicePtrs)); + for (psdpp = xf86SbusInfo, n = 0; (psdp = *psdpp); psdpp++, n++) { + if (psdp->fbNum != n) + holes = 1; + devicePtrs[psdp->fbNum] = psdp; + } + if (holes && (f = fopen("/proc/fb", "r")) != NULL) { + /* We could not open one of fb devices, check /proc/fb to see what + * were the types of the cards missed. */ + char buffer[64]; + int fbNum, devId; + static struct { + int devId; + char *prefix; + } procFbPrefixes[] = { + { SBUS_DEVICE_BW2, "BWtwo" }, + { SBUS_DEVICE_CG14, "CGfourteen" }, + { SBUS_DEVICE_CG6, "CGsix" }, + { SBUS_DEVICE_CG3, "CGthree" }, + { SBUS_DEVICE_FFB, "Creator" }, + { SBUS_DEVICE_FFB, "Elite 3D" }, + { SBUS_DEVICE_LEO, "Leo" }, + { SBUS_DEVICE_TCX, "TCX" }, + { 0, NULL }, + }; + + while (fscanf(f, "%d %63s\n", &fbNum, buffer) == 2) { + for (i = 0; procFbPrefixes[i].devId; i++) + if (! strncmp(procFbPrefixes[i].prefix, buffer, + strlen(procFbPrefixes[i].prefix))) + break; + devId = procFbPrefixes[i].devId; + if (! devId) continue; + if (devicePtrs[fbNum]) { + if (devicePtrs[fbNum]->devId != devId) + xf86ErrorF("Inconsistent /proc/fb with FBIOGATTR\n"); + } else if (!devicePtrs[fbNum]) { + devicePtrs[fbNum] = psdp = xnfcalloc(sizeof (sbusDevice), 1); + psdp->devId = devId; + psdp->fbNum = fbNum; + psdp->fd = -2; + } + } + fclose(f); + } + promGetSibling(0); + promWalkAssignNodes(promRootNode, 0, PROM_NODE_PREF, devicePtrs); + for (i = 0, j = 0; i < 32; i++) + if (devicePtrs[i] && devicePtrs[i]->fbNum == -1) + j++; + xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (n + j + 1)); + for (i = 0, psdpp = xf86SbusInfo; i < 32; i++) + if (devicePtrs[i]) { + if (devicePtrs[i]->fbNum == -1) { + memmove(psdpp + 1, psdpp, sizeof(psdpp) * (n + 1)); + *psdpp = devicePtrs[i]; + } else + n--; + } +} + +static char * +promGetReg(int type) +{ + char *prop; + int len; + static char regstr[40]; + + regstr[0] = 0; + prop = promGetProperty("reg", &len); + if (prop && len >= 4) { + unsigned int *reg = (unsigned int *)prop; + if (!promP1275 || (type == PROM_NODE_SBUS) || (type == PROM_NODE_EBUS)) + sprintf (regstr, "@%x,%x", reg[0], reg[1]); + else if (type == PROM_NODE_PCI) { + if ((reg[0] >> 8) & 7) + sprintf (regstr, "@%x,%x", (reg[0] >> 11) & 0x1f, (reg[0] >> 8) & 7); + else + sprintf (regstr, "@%x", (reg[0] >> 11) & 0x1f); + } else if (len == 4) + sprintf (regstr, "@%x", reg[0]); + else { + unsigned int regs[2]; + + /* Things get more complicated on UPA. If upa-portid exists, + then address is @upa-portid,second-int-in-reg, otherwise + it is @first-int-in-reg/16,second-int-in-reg (well, probably + upa-portid always exists, but just to be safe). */ + memcpy (regs, reg, sizeof(regs)); + prop = promGetProperty("upa-portid", &len); + if (prop && len == 4) { + reg = (unsigned int *)prop; + sprintf (regstr, "@%x,%x", reg[0], regs[1]); + } else + sprintf (regstr, "@%x,%x", regs[0] >> 4, regs[1]); + } + } + return regstr; +} + +static int +promWalkNode2Pathname(char *path, int parent, int node, int searchNode, int type) +{ + int nextnode; + int len, ntype = type; + char *prop, *p; + + prop = promGetProperty("name", &len); + *path = '/'; + if (!prop || len <= 0) + return 0; + if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) + ntype = PROM_NODE_SBUS; + else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) + ntype = PROM_NODE_EBUS; + else if (!strcmp(prop, "pci") && !type) + ntype = PROM_NODE_PCI; + strcpy (path + 1, prop); + p = promGetReg(type); + if (*p) + strcat (path, p); + if (node == searchNode) + return 1; + nextnode = promGetChild(node); + if (nextnode && + promWalkNode2Pathname(strchr(path, 0), node, nextnode, searchNode, ntype)) + return 1; + nextnode = promGetSibling(node); + if (nextnode && + promWalkNode2Pathname(path, parent, nextnode, searchNode, type)) + return 1; + return 0; +} + +char * +sparcPromNode2Pathname(sbusPromNodePtr pnode) +{ + char *ret; + + if (!pnode->node) return NULL; + ret = xalloc(4096); + if (!ret) return NULL; + if (promWalkNode2Pathname(ret, promRootNode, promGetChild(promRootNode), pnode->node, 0)) + return ret; + xfree(ret); + return NULL; +} + +static int +promWalkPathname2Node(char *name, char *regstr, int parent, int type) +{ + int len, node, ret; + char *prop, *p; + + for (;;) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + return 0; + if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) + type = PROM_NODE_SBUS; + else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) + type = PROM_NODE_EBUS; + else if (!strcmp(prop, "pci") && !type) + type = PROM_NODE_PCI; + for (node = promGetChild(parent); node; node = promGetSibling(node)) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + continue; + if (*name && strcmp(name, prop)) + continue; + if (*regstr) { + p = promGetReg(type); + if (! *p || strcmp(p + 1, regstr)) + continue; + } + break; + } + if (!node) { + for (node = promGetChild(parent); node; node = promGetSibling(node)) { + ret = promWalkPathname2Node(name, regstr, node, type); + if (ret) return ret; + } + return 0; + } + name = strchr(regstr, 0) + 1; + if (! *name) + return node; + p = strchr(name, '/'); + if (p) + *p = 0; + else + p = strchr(name, 0); + regstr = strchr(name, '@'); + if (regstr) + *regstr++ = 0; + else + regstr = p; + if (name == regstr) + return 0; + parent = node; + } +} + +int +sparcPromPathname2Node(const char *pathName) +{ + int i; + char *name, *regstr, *p; + + i = strlen(pathName); + name = xalloc(i + 2); + if (! name) return 0; + strcpy (name, pathName); + name [i + 1] = 0; + if (name[0] != '/') + return 0; + p = strchr(name + 1, '/'); + if (p) + *p = 0; + else + p = strchr(name, 0); + regstr = strchr(name, '@'); + if (regstr) + *regstr++ = 0; + else + regstr = p; + if (name + 1 == regstr) + return 0; + promGetSibling(0); + i = promWalkPathname2Node(name + 1, regstr, promRootNode, 0); + xfree(name); + return i; +} + +pointer +xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset, unsigned long size) +{ + pointer ret; + unsigned long pagemask = xf86getpagesize() - 1; + unsigned long off = offset & ~pagemask; + unsigned long len = ((offset + size + pagemask) & ~pagemask) - off; + + if (psdp->fd == -1) { + psdp->fd = open(psdp->device, O_RDWR); + if (psdp->fd == -1) + return NULL; + } else if (psdp->fd < 0) + return NULL; + + ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, + psdp->fd, off); + if (ret == (pointer) -1) { + ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, + psdp->fd, off); + } + if (ret == (pointer) -1) + return NULL; + + return (char *)ret + (offset - off); +} + +void +xf86UnmapSbusMem(sbusDevicePtr psdp, pointer addr, unsigned long size) +{ + unsigned long mask = xf86getpagesize() - 1; + unsigned long base = (unsigned long)addr & ~mask; + unsigned long len = (((unsigned long)addr + size + mask) & ~mask) - base; + + munmap ((pointer)base, len); +} + +/* Tell OS that we are driving the HW cursor ourselves. */ +void +xf86SbusHideOsHwCursor(sbusDevicePtr psdp) +{ + struct fbcursor fbcursor; + unsigned char zeros[8]; + + memset(&fbcursor, 0, sizeof(fbcursor)); + memset(&zeros, 0, sizeof(zeros)); + fbcursor.cmap.count = 2; + fbcursor.cmap.red = zeros; + fbcursor.cmap.green = zeros; + fbcursor.cmap.blue = zeros; + fbcursor.image = (char *)zeros; + fbcursor.mask = (char *)zeros; + fbcursor.size.x = 32; + fbcursor.size.y = 1; + fbcursor.set = FB_CUR_SETALL; + ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); +} + +/* Set HW cursor colormap. */ +void +xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg) +{ + struct fbcursor fbcursor; + unsigned char red[2], green[2], blue[2]; + + memset(&fbcursor, 0, sizeof(fbcursor)); + red[0] = bg >> 16; + green[0] = bg >> 8; + blue[0] = bg; + red[1] = fg >> 16; + green[1] = fg >> 8; + blue[1] = fg; + fbcursor.cmap.count = 2; + fbcursor.cmap.red = red; + fbcursor.cmap.green = green; + fbcursor.cmap.blue = blue; + fbcursor.set = FB_CUR_SETCMAP; + ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c new file mode 100644 index 000000000..010f6619a --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c @@ -0,0 +1,120 @@ +/* + * This file contains the glue necessary for support of SGI's Altix chipset. + */ +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdio.h> +#include <unistd.h> +#include "altixPCI.h" +#include "xf86.h" +#include "Pci.h" + +/* + * get_dev_on_bus - Return the first device we find on segnum, busnum + * + * Walk all the PCI devices and return the first one found on segnum, busnum. + * There may be a better way to do this in some xf86* function I don't know + * about. + */ +static pciDevice *get_dev_on_bus(unsigned int segnum, unsigned int busnum) +{ + pciDevice **pdev = xf86scanpci(0); + int i; + + for (i = 0; pdev[i] != NULL; i++) + if (PCI_DOM_FROM_TAG(pdev[i]->tag) == segnum && + pdev[i]->busnum == busnum) + return pdev[i]; + /* Should never get here... */ + ErrorF("No PCI device found on %04x:%02x??", segnum, busnum); + return NULL; +} + +/* + * get_bridge_info - fill in the bridge info for bus_info based on pdev + * + * Find the parent bus for pdev if it exists, otherwise assume pdev *is* + * the parent bus. We need this on Altix because our bridges are transparent. + */ +static void get_bridge_info(pciBusInfo_t *bus_info, pciDevice *pdev) +{ + unsigned int parent_segnum, segnum = PCI_DOM_FROM_TAG(pdev->tag); + unsigned int parent_busnum, busnum = pdev->busnum; + char bridge_path[] = "/sys/class/pci_bus/0000:00/bridge"; + char bridge_target[] = "../../../devices/pci0000:00"; + + /* Path to this device's bridge */ + sprintf(bridge_path, "/sys/class/pci_bus/%04x:%02x/bridge", segnum, + busnum); + + if (readlink(bridge_path, bridge_target, strlen(bridge_target)) < 0) { + perror("failed to dereference bridge link"); + ErrorF("failed to dereference bridge link, aborting\n"); + exit(-1); + } + + sscanf(bridge_target, "../../../devices/pci%04x:%02x", &parent_segnum, + &parent_busnum); + + /* + * If there's no bridge or the bridge points to the device, use + * pdev as the bridge + */ + if (segnum == parent_segnum && busnum == parent_busnum) { + bus_info->bridge = pdev; + bus_info->secondary = FALSE; + bus_info->primary_bus = busnum; + } else { + bus_info->bridge = get_dev_on_bus(parent_segnum, + parent_busnum); + bus_info->secondary = TRUE; + bus_info->primary_bus = parent_busnum; + } + pdev->businfo = bus_info; + pdev->pci_base_class = PCI_CLASS_DISPLAY; + pdev->pci_sub_class = PCI_SUBCLASS_PREHISTORIC_VGA; +} + +void xf86PreScanAltix(void) +{ + /* Nothing to see here... */ +} + +void xf86PostScanAltix(void) +{ + pciConfigPtr *pdev; + pciBusInfo_t *bus_info; + int prevBusNum, curBusNum, idx; + + /* + * Altix PCI bridges are invisible to userspace, so we make each device + * look like it's its own bridge unless it actually has a parent (as in + * the case of PCI to PCI bridges). + */ + bus_info = pciBusInfo[0]; + pdev = xf86scanpci(0); + prevBusNum = curBusNum = pdev[0]->busnum; + bus_info = pciBusInfo[curBusNum]; + bus_info->bridge = pdev[0]; + bus_info->secondary = FALSE; + bus_info->primary_bus = curBusNum; + + /* Walk all the PCI devices, assigning their bridge info */ + for (idx = 0; pdev[idx] != NULL; idx++) { + if (pdev[idx]->busnum == prevBusNum) + continue; /* Already fixed up this bus */ + + curBusNum = pdev[idx]->busnum; + bus_info = pciBusInfo[curBusNum]; + + /* + * Fill in bus_info for pdev. The bridge field will either + * be pdev[idx] or a device on the parent bus. + */ + get_bridge_info(bus_info, pdev[idx]); + prevBusNum = curBusNum; + } + return; +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.h new file mode 100644 index 000000000..2a738f362 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.h @@ -0,0 +1,20 @@ +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef PCI_ALTIX_H +#define PCI_ALTIX_H 1 + +#include <X11/Xdefs.h> +#include <Pci.h> + +Bool xorgProbeAltix(scanpciWrapperOpt flags); +void xf86PreScanAltix(void); +void xf86PostScanAltix(void); + +/* Some defines for PCI */ +#define VENDOR_SGI 0x10A9 +#define CHIP_TIO_CA 0x1010 +#define CHIP_PIC_PCI 0x1011 + +#endif diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/axpPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/axpPci.c new file mode 100644 index 000000000..08c7fbd39 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/axpPci.c @@ -0,0 +1,478 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/axpPci.c,v 1.14 2002/12/11 02:44:28 dawes Exp $ */ +/* + * 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 + +#include <stdio.h> +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "Pci.h" + +#include <asm/unistd.h> +#include "../linux/lnx.h" /* for _iobase */ + +/* + * Alpha/Linux platform specific PCI access functions + */ +static CARD32 axpPciCfgRead(PCITAG tag, int off); +static void axpPciCfgWrite(PCITAG, int off, CARD32 val); +static void axpPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits); + +static pciBusFuncs_t axpFuncs0 = { +/* pciReadLong */ axpPciCfgRead, +/* pciWriteLong */ axpPciCfgWrite, +/* pciSetBitsLong */ axpPciCfgSetBits, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +typedef struct _axpDomainRec { + int domain, hose; + int root_bus; + unsigned long dense_io, sparse_io; + unsigned long dense_mem, sparse_mem; + IOADDRESS mapped_io; +} axpDomainRec, *axpDomainPtr; + +#define MAX_DOMAINS (MAX_PCI_BUSES / 256) +static axpDomainPtr xf86DomainInfo[MAX_DOMAINS] = { NULL, }; +static int pciNumDomains = 0; + +/* + * For debug, domain assignment can start downward from a fixed base + * (instead of up from 0) by defining FORCE_HIGH_DOMAINS. This allows + * debug of large domain numbers and sparse domain numbering on systems + * which don't have as many hoses. + */ +#if 0 +# define FORCE_HIGH_DOMAINS MAX_DOMAINS /* assign domains downward from here */ +#endif + +/* + * If FORCE_HIGH_DOMAINS is set, make sure it's not larger than the + * max domain + */ +#if defined(FORCE_HIGH_DOMAINS) && (FORCE_HIGH_DOMAINS > MAX_DOMAINS) +# undef FORCE_HIGH_DOMAINS +# define FORCE_HIGH_DOMAINS MAX_DOMAINS +#endif + +static int +axpSetupDomains(void) +{ + axpDomainRec axpDomain; + int numDomains = 0; + int hose; + +#ifndef INCLUDE_XF86_NO_DOMAIN + +#ifdef FORCE_HIGH_DOMAINS + xf86Msg(X_WARNING, + "DEBUG OPTION FORCE_HIGH_DOMAINS in use - DRI will *NOT* work\n"); + numDomains = FORCE_HIGH_DOMAINS; +#endif + + /* + * Since each hose has a different address space, hoses are a perfect + * overlay for domains, so set up one domain for each hose present + * in the system. We have to loop through all possible hoses because + * some systems allow sparse I/O controllers. + */ + for(hose = 0; hose < MAX_DOMAINS; hose++) { + axpDomain.root_bus = _iobase(IOBASE_ROOT_BUS, hose, -1, -1); + if (axpDomain.root_bus < 0) continue; + + axpDomain.hose = hose; + +#ifndef FORCE_HIGH_DOMAINS + + axpDomain.domain = axpDomain.hose = hose; + numDomains = axpDomain.domain + 1; + +#else /* FORCE_HIGH_DOMAINS */ + + axpDomain.domain = numDomains - hose - 1; + + xf86Msg(X_WARNING, + "FORCE_HIGH_DOMAINS - assigned hose %d to domain %d\n", + axpDomain.hose, axpDomain.domain); + +#endif /* FORCE_HIGH_DOMAINS */ + + axpDomain.dense_io = _iobase(IOBASE_DENSE_IO, hose, -1, -1); + axpDomain.sparse_io = _iobase(IOBASE_SPARSE_IO, hose, -1, -1); + axpDomain.mapped_io = 0; + axpDomain.dense_mem = _iobase(IOBASE_DENSE_MEM, hose, -1, -1); + axpDomain.sparse_mem = _iobase(IOBASE_SPARSE_MEM, hose, -1, -1); + + xf86DomainInfo[axpDomain.domain] = xnfalloc(sizeof(axpDomainRec)); + *(xf86DomainInfo[axpDomain.domain]) = axpDomain; + + /* + * For now, only allow a single domain (hose) on sparse i/o systems. + * + * Allowing multiple domains on sparse systems would require: + * 1) either + * a) revamping the sparse video mapping code to allow + * for multiple unrelated address regions + * -- OR -- + * b) implementing sparse mapping directly in + * xf86MapDomainMemory + * 2) revaming read/write sparse routines to correctly handle + * the solution to 1) + * 3) implementing a sparse I/O system (mapping, inX/outX) + * independent of glibc, since the glibc version only + * supports hose 0 + */ + if (axpDomain.sparse_io) { + if (_iobase(IOBASE_ROOT_BUS, hose + 1, -1, -1) >= 0) { + /* + * It's a sparse i/o system with (at least) one more hose, + * show a message indicating that video is constrained to + * hose 0 + */ + xf86Msg(X_INFO, + "Sparse I/O system - constraining video to hose 0\n"); + } + break; + } + } + +#else /* INCLUDE_XF86_NO_DOMAIN */ + + /* + * domain support is not included, so just set up a single domain (0) + * to represent the first hose so that axpPciInit will still have + * be able to set up the root bus + */ + xf86DomainInfo[0] = xnfalloc(sizeof(axpDomainRec)); + *(xf86DomainInfo[0]) = axpDomain; + numDomains = 1; + +#endif /* INCLUDE_XF86_NO_DOMAIN */ + + return numDomains; +} + +void +axpPciInit() +{ + axpDomainPtr pDomain; + int domain, bus; + + pciNumDomains = axpSetupDomains(); + + for(domain = 0; domain < pciNumDomains; domain++) { + if (!(pDomain = xf86DomainInfo[domain])) continue; + + /* + * Since any bridged buses will be behind a probed pci-pci bridge, + * only set up the root bus for each domain (hose) and the bridged + * buses will be set up as they are found. + */ + bus = PCI_MAKE_BUS(domain, 0); + pciBusInfo[bus] = xnfalloc(sizeof(pciBusInfo_t)); + (void)memset(pciBusInfo[bus], 0, sizeof(pciBusInfo_t)); + + pciBusInfo[bus]->configMech = PCI_CFG_MECH_OTHER; + pciBusInfo[bus]->numDevices = 32; + pciBusInfo[bus]->funcs = &axpFuncs0; + pciBusInfo[bus]->pciBusPriv = pDomain; + + pciNumBuses = bus + 1; + } + + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; +} + +/* + * Alpha/Linux PCI configuration space access routines + */ +static int +axpPciBusFromTag(PCITAG tag) +{ + pciBusInfo_t *pBusInfo; + axpDomainPtr pDomain; + int bus, dfn; + + bus = PCI_BUS_FROM_TAG(tag); + if ((bus >= pciNumBuses) + || !(pBusInfo = pciBusInfo[bus]) + || !(pDomain = pBusInfo->pciBusPriv) + || (pDomain->domain != PCI_DOM_FROM_TAG(tag))) return -1; + + bus = PCI_BUS_NO_DOMAIN(bus) + pDomain->root_bus; + dfn = PCI_DFN_FROM_TAG(tag); + if (_iobase(IOBASE_HOSE, -1, bus, dfn) != pDomain->hose) return -1; + + return bus; +} + +static CARD32 +axpPciCfgRead(PCITAG tag, int off) +{ + int bus, dfn; + CARD32 val = 0xffffffff; + + if ((bus = axpPciBusFromTag(tag)) >= 0) { + dfn = PCI_DFN_FROM_TAG(tag); + + syscall(__NR_pciconfig_read, bus, dfn, off, 4, &val); + } + return(val); +} + +static void +axpPciCfgWrite(PCITAG tag, int off, CARD32 val) +{ + int bus, dfn; + + if ((bus = axpPciBusFromTag(tag)) >= 0) { + dfn = PCI_DFN_FROM_TAG(tag); + syscall(__NR_pciconfig_write, bus, dfn, off, 4, &val); + } +} + +static void +axpPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits) +{ + int bus, dfn; + CARD32 val = 0xffffffff; + + if ((bus = axpPciBusFromTag(tag)) >= 0) { + dfn = PCI_DFN_FROM_TAG(tag); + + syscall(__NR_pciconfig_read, bus, dfn, off, 4, &val); + val = (val & ~mask) | (bits & mask); + syscall(__NR_pciconfig_write, bus, dfn, off, 4, &val); + } +} + +#ifndef INCLUDE_XF86_NO_DOMAIN + +/* + * Alpha/Linux addressing domain support + */ + +int +xf86GetPciDomain(PCITAG Tag) +{ + return PCI_DOM_FROM_TAG(Tag); +} + +pointer +xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size) +{ + axpDomainPtr pDomain; + int domain = PCI_DOM_FROM_TAG(Tag); + + if ((domain < 0) || (domain >= pciNumDomains) || + !(pDomain = xf86DomainInfo[domain])) + FatalError("%s called with invalid parameters\n", __FUNCTION__); + + /* + * xf86MapVidMem already does what we need, but remember to subtract + * _bus_base() (the physical dense memory root of hose 0) since + * xf86MapVidMem is expecting an offset relative to _bus_base() rather + * than an actual physical address. + */ + return xf86MapVidMem(ScreenNum, Flags, + pDomain->dense_mem + Base - _bus_base(), Size); +} + +IOADDRESS +xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, + IOADDRESS Base, unsigned long Size) +{ + axpDomainPtr pDomain; + int domain = PCI_DOM_FROM_TAG(Tag); + + if ((domain < 0) || (domain >= pciNumDomains) || + !(pDomain = xf86DomainInfo[domain])) + FatalError("%s called with invalid parameters\n", __FUNCTION__); + + /* + * Use glibc inx/outx routines for sparse I/O, so just return the + * base [this is ok since we also constrain sparse I/O systems to + * a single domain in axpSetupDomains()] + */ + if (pDomain->sparse_io) return Base; + + /* + * I/O addresses on Alpha are really just different physical memory + * addresses that the system corelogic turns into I/O commands on the + * bus, so just use xf86MapVidMem to map I/O as well, but remember + * to subtract _bus_base() (the physical dense memory root of hose 0) + * since xf86MapVidMem is expecting an offset relative to _bus_base() + * rather than an actual physical address. + * + * Map the entire I/O space (64kB) at once and only once. + */ + if (!pDomain->mapped_io) + pDomain->mapped_io = (IOADDRESS)xf86MapVidMem(ScreenNum, Flags, + pDomain->dense_io - _bus_base(), + 0x10000); + + return pDomain->mapped_io + Base; +} + +int +xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) +{ + static unsigned long pagemask = 0; + unsigned char *MappedAddr; + unsigned long MapSize; + ADDRESS MapBase; + int i; + + if (!pagemask) pagemask = xf86getpagesize() - 1; + + /* Ensure page boundaries */ + MapBase = Base & ~pagemask; + MapSize = ((Base + Len + pagemask) & ~pagemask) - MapBase; + + /* + * VIDMEM_MMIO in order to get sparse mapping on sparse memory systems + * so we can use mmio functions to read (that way we can really get byte + * at a time reads on dense memory systems with byte/word instructions. + */ + MappedAddr = xf86MapDomainMemory(-1, VIDMEM_READONLY | VIDMEM_MMIO, + Tag, MapBase, MapSize); + + for (i = 0; i < Len; i++) { + *Buf++ = xf86ReadMmio8(MappedAddr, Base - MapBase + i); + } + + xf86UnMapVidMem(-1, MappedAddr, MapSize); + return Len; +} + +resPtr +xf86PciBusAccWindowsFromOS(void) +{ + resPtr pRes = NULL; + resRange range; + int domain; + + for(domain = 0; domain < pciNumDomains; domain++) { + if (!xf86DomainInfo[domain]) continue; + + RANGE(range, 0, 0xffffffffUL, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0, 0x0000ffffUL, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + } + + return pRes; +} + +resPtr +xf86BusAccWindowsFromOS(void) +{ + return xf86PciBusAccWindowsFromOS(); +} + +resPtr +xf86AccResFromOS(resPtr pRes) +{ + resRange range; + int domain; + + for(domain = 0; domain < pciNumDomains; domain++) { + if (!xf86DomainInfo[domain]) continue; + + /* + * Fallback is to claim the following areas: + * + * 0x000c0000 - 0x000effff location of VGA and other extensions ROMS + */ + + RANGE(range, 0x000c0000, 0x000effff, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + /* + * Fallback would be to claim well known ports in the 0x0 - 0x3ff + * range along with their sparse I/O aliases, but that's too + * imprecise. Instead claim a bare minimum here. + */ + RANGE(range, 0x00000000, 0x000000ff, + RANGE_TYPE(ResExcIoBlock, domain)); /* For mainboard */ + pRes = xf86AddResToList(pRes, &range, -1); + + /* + * At minimum, the top and bottom resources must be claimed, so that + * resources that are (or appear to be) unallocated can be relocated. + */ + RANGE(range, 0x00000000, 0x00000000, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, 0xffffffff, 0xffffffff, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); +/* RANGE(range, 0x00000000, 0x00000000, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); */ + RANGE(range, 0xffffffff, 0xffffffff, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + } + + return pRes; +} + +#endif /* !INCLUDE_XF86_NO_DOMAIN */ + diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.c new file mode 100644 index 000000000..65b0c0474 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.c @@ -0,0 +1,64 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.c,v 1.2 2003/07/17 15:08:22 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +/* + * This file contains the glue necessary for support of Intel's E8870 chipset. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "e8870PCI.h" +#include "xf86.h" +#include "Pci.h" + +Bool +xorgProbeE8870(scanpciWrapperOpt flags) +{ + PCITAG tag; + + /* Look for an E8870's Hub interface */ + tag = PCI_MAKE_TAG(0, 0x1E, 0); + if (pciReadLong(tag, PCI_ID_REG) == DEVID(VENDOR_INTEL, CHIP_82801_P2P)) + return TRUE; + + return FALSE; +} + +void +xf86PreScanE8870(void) +{ + /* XXX Fill me in... */ + return; +} + +void +xf86PostScanE8870(void) +{ + /* XXX Fill me in... */ +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.h new file mode 100644 index 000000000..9efa0ed6d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.h @@ -0,0 +1,42 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/e8870PCI.h,v 1.1 2003/02/23 20:26:49 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef PCI_E8870_H +#define PCI_E8870_H 1 + +#include <X11/Xdefs.h> +#include <Pci.h> + +Bool xorgProbeE8870(scanpciWrapperOpt flags); +void xf86PreScanE8870(void); +void xf86PostScanE8870(void); + +#endif diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/freebsdPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/freebsdPci.c new file mode 100644 index 000000000..f6d6f8a6d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/freebsdPci.c @@ -0,0 +1,171 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/freebsdPci.c,v 1.4 2002/07/24 19:06:52 tsi Exp $ */ +/* + * 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 + +#include <stdio.h> +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "Pci.h" + +#include <sys/pciio.h> + +/* + * freebsd platform specific PCI access functions -- using /dev/pci + * needs kernel version 2.2.x + */ +static CARD32 freebsdPciCfgRead(PCITAG tag, int off); +static void freebsdPciCfgWrite(PCITAG, int off, CARD32 val); +static void freebsdPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits); + +static pciBusFuncs_t freebsdFuncs0 = { +/* pciReadLong */ freebsdPciCfgRead, +/* pciWriteLong */ freebsdPciCfgWrite, +/* pciSetBitsLong */ freebsdPciCfgSetBits, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +static pciBusInfo_t freebsdPci0 = { +/* configMech */ PCI_CFG_MECH_OTHER, +/* numDevices */ 32, +/* secondary */ FALSE, +/* primary_bus */ 0, +#ifdef PowerMAX_OS +/* ppc_io_base */ 0, +/* ppc_io_size */ 0, +#endif +/* funcs */ &freebsdFuncs0, +/* pciBusPriv */ NULL, +/* bridge */ NULL +}; + +#if !defined(__OpenBSD__) && !defined(__FreeBSD__) +#if X_BYTE_ORDER == X_BIG_ENDIAN +#ifdef __sparc__ +#ifndef ASI_PL +#define ASI_PL 0x88 +#endif +#define PCI_CPU(val) ({ \ +int __ret; \ +__asm__ __volatile__("lduwa [%1] %2, %0" : "=r" (__ret) : "r" (&val), "i" (ASI_PL)); \ +__ret; \ +}) +#else +#define PCI_CPU(val) (((val >> 24) & 0x000000ff) | \ + ((val >> 8) & 0x0000ff00) | \ + ((val << 8) & 0x00ff0000) | \ + ((val << 24) & 0xff000000)) +#endif +#else +#define PCI_CPU(val) (val) +#endif +#else /* ! OpenBSD */ +/* OpenBSD has already the bytes in the right order + for all architectures */ +#define PCI_CPU(val) (val) +#endif + + +#define BUS(tag) (((tag)>>16)&0xff) +#define DFN(tag) (((tag)>>8)&0xff) + +static int pciFd = -1; + +void +freebsdPciInit() +{ + pciFd = open("/dev/pci", O_RDWR); + if (pciFd < 0) + return; + + pciNumBuses = 1; + pciBusInfo[0] = &freebsdPci0; + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; +} + +static CARD32 +freebsdPciCfgRead(PCITAG tag, int off) +{ + struct pci_io io; + int error; + io.pi_sel.pc_bus = BUS(tag); + io.pi_sel.pc_dev = DFN(tag) >> 3; + io.pi_sel.pc_func = DFN(tag) & 7; + io.pi_reg = off; + io.pi_width = 4; + error = ioctl(pciFd, PCIOCREAD, &io); + if (error) + return ~0; + return PCI_CPU(io.pi_data); +} + +static void +freebsdPciCfgWrite(PCITAG tag, int off, CARD32 val) +{ + struct pci_io io; + io.pi_sel.pc_bus = BUS(tag); + io.pi_sel.pc_dev = DFN(tag) >> 3; + io.pi_sel.pc_func = DFN(tag) & 7; + io.pi_reg = off; + io.pi_width = 4; + io.pi_data = PCI_CPU(val); + ioctl(pciFd, PCIOCWRITE, &io); +} + +static void +freebsdPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits) +{ + CARD32 val = freebsdPciCfgRead(tag, off); + val = (val & ~mask) | (bits & mask); + freebsdPciCfgWrite(tag, off, val); +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ix86Pci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ix86Pci.c new file mode 100644 index 000000000..6e2b650d1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ix86Pci.c @@ -0,0 +1,704 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/ix86Pci.c,v 1.25 2003/09/24 02:43:34 dawes Exp $ */ +/* + * ix86Pci.c - x86 PCI driver + * + * The XFree86 server PCI access functions have been reimplemented as a + * framework that allows each supported platform/OS to have their own + * platform/OS specific PCI driver. + * + * Most of the code of these functions was simply lifted from the + * Intel architecture specifric portion of the original Xfree86 + * PCI code in hw/xfree86/common_hw/xf86_PCI.C... + * + * 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. + * + * This software is derived from the original XFree86 PCI code + * which includes the following copyright notices as well: + * + * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org> + * + * 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 names of the above listed copyright holder(s) + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holder(s) make(s) no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + * + * This code is also based heavily on the code in FreeBSD-current, which was + * written by Wolfgang Stanglmeier, and contains the following copyright: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdio.h> +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "Pci.h" + +#ifdef PC98 +#define outb(port,data) _outb(port,data) +#define outl(port,data) _outl(port,data) +#define inb(port) _inb(port) +#define inl(port) _inl(port) +#endif + +#define PCI_CFGMECH2_ENABLE_REG 0xCF8 +#ifdef PC98 +#define PCI_CFGMECH2_FORWARD_REG 0xCF9 +#else +#define PCI_CFGMECH2_FORWARD_REG 0xCFA +#endif + +#define PCI_CFGMECH2_MAXDEV 16 + +#define PCI_ADDR_FROM_TAG_CFG1(tag,reg) (PCI_EN | tag | (reg & 0xfc)) +#define PCI_FORWARD_FROM_TAG(tag) PCI_BUS_FROM_TAG(tag) +#define PCI_ENABLE_FROM_TAG(tag) (0xf0 | (((tag) & 0x00000700) >> 7)) +#define PCI_ADDR_FROM_TAG_CFG2(tag,reg) (0xc000 | (((tag) & 0x0000f800) >> 3) \ + | (reg & 0xfc)) + +/* + * Intel x86 platform specific PCI access functions + */ +static CARD32 ix86PciReadLongSetup(PCITAG tag, int off); +static void ix86PciWriteLongSetup(PCITAG, int off, CARD32 val); +static void ix86PciSetBitsLongSetup(PCITAG, int off, CARD32 mask, CARD32 val); +static CARD32 ix86PciReadLongCFG1(PCITAG tag, int off); +static void ix86PciWriteLongCFG1(PCITAG, int off, CARD32 val); +static void ix86PciSetBitsLongCFG1(PCITAG, int off, CARD32 mask, CARD32 val); +static CARD32 ix86PciReadLongCFG2(PCITAG tag, int off); +static void ix86PciWriteLongCFG2(PCITAG, int off, CARD32 val); +static void ix86PciSetBitsLongCFG2(PCITAG, int off, CARD32 mask, CARD32 val); + +static pciBusFuncs_t ix86Funcs0 = { +/* pciReadLong */ ix86PciReadLongSetup, +/* pciWriteLong */ ix86PciWriteLongSetup, +/* pciSetBitsLong */ ix86PciSetBitsLongSetup, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +static pciBusFuncs_t ix86Funcs1 = { +/* pciReadLong */ ix86PciReadLongCFG1, +/* pciWriteLong */ ix86PciWriteLongCFG1, +/* pciSetBitsLong */ ix86PciSetBitsLongCFG1, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +static pciBusFuncs_t ix86Funcs2 = { +/* pciReadLong */ ix86PciReadLongCFG2, +/* pciWriteLong */ ix86PciWriteLongCFG2, +/* pciSetBitsLong */ ix86PciSetBitsLongCFG2, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +static pciBusInfo_t ix86Pci0 = { +/* configMech */ PCI_CFG_MECH_UNKNOWN, /* Set by ix86PciInit() */ +/* numDevices */ 0, /* Set by ix86PciInit() */ +/* secondary */ FALSE, +/* primary_bus */ 0, +#ifdef PowerMAX_OS +/* ppc_io_base */ 0, +/* ppc_io_size */ 0, +#endif +/* funcs */ &ix86Funcs0, /* Set by ix86PciInit() */ +/* pciBusPriv */ NULL, +/* bridge */ NULL +}; + +static Bool +ix86PciBusCheck(void) +{ + PCITAG tag; + CARD32 id, class; + CARD8 device; + + for (device = 0; device < ix86Pci0.numDevices; device++) { + tag = PCI_MAKE_TAG(0, device, 0); + id = (*ix86Pci0.funcs->pciReadLong)(tag, PCI_ID_REG); + + if ((CARD16)(id + 1U) <= (CARD16)1UL) + continue; + + /* The rest of this is inspired by the Linux kernel */ + class = (*ix86Pci0.funcs->pciReadLong)(tag, PCI_CLASS_REG); + + /* Ignore revision id and programming interface */ + switch (class >> 16) { + case (PCI_CLASS_PREHISTORIC << 8) | PCI_SUBCLASS_PREHISTORIC_MISC: + /* Check for vendors of known buggy chipsets */ + id &= 0x0000ffff; + if ((id == PCI_VENDOR_INTEL) || (id == PCI_VENDOR_COMPAQ)) + return TRUE; + continue; + + case (PCI_CLASS_PREHISTORIC << 8) | PCI_SUBCLASS_PREHISTORIC_VGA: + case (PCI_CLASS_DISPLAY << 8) | PCI_SUBCLASS_DISPLAY_VGA: + case (PCI_CLASS_BRIDGE << 8) | PCI_SUBCLASS_BRIDGE_HOST: + return TRUE; + + default: + break; + } + } + return FALSE; +} + +static +void ix86PciSelectCfgmech(void) +{ + static Bool beenhere = FALSE; + CARD32 mode1Res1 = 0, mode1Res2 = 0, oldVal1 = 0; + CARD8 mode2Res1 = 0, mode2Res2 = 0, oldVal2 = 0; + int stages = 0; + + if (beenhere) + return; /* Been there, done that */ + + beenhere = TRUE; + + /* + * Determine if motherboard chipset supports PCI Config Mech 1 or 2 + * We rely on xf86Info.pciFlags to tell which mechanisms to try.... + */ + switch (xf86Info.pciFlags) { + + case PCIOsConfig: +#ifdef ARCH_PCI_OS_INIT + return; +#endif + + case PCIProbe1: + if (!xf86EnableIO()) + return; + + xf86MsgVerb(X_INFO, 2, + "PCI: Probing config type using method 1\n"); + oldVal1 = inl(PCI_CFGMECH1_ADDRESS_REG); + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("Checking config type 1:\n" + "\tinitial value of MODE1_ADDR_REG is 0x%08x\n", oldVal1); + ErrorF("\tChecking that all bits in mask 0x7f000000 are clear\n"); + } +#endif + + /* Assuming config type 1 to start with */ + if ((oldVal1 & 0x7f000000) == 0) { + + stages |= 0x01; + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tValue indicates possibly config type 1\n"); + ErrorF("\tWriting 32-bit value 0x%08x to MODE1_ADDR_REG\n", PCI_EN); +#if 0 + ErrorF("\tWriting 8-bit value 0x00 to MODE1_ADDR_REG + 3\n"); +#endif + } +#endif + + ix86Pci0.configMech = PCI_CFG_MECH_1; + ix86Pci0.numDevices = PCI_CFGMECH1_MAXDEV; + ix86Pci0.funcs = &ix86Funcs1; + + outl(PCI_CFGMECH1_ADDRESS_REG, PCI_EN); + +#if 0 + /* + * This seems to cause some Neptune-based PCI machines to switch + * from config type 1 to config type 2 + */ + outb(PCI_CFGMECH1_ADDRESS_REG + 3, 0); +#endif + mode1Res1 = inl(PCI_CFGMECH1_ADDRESS_REG); + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tValue read back from MODE1_ADDR_REG is 0x%08x\n", + mode1Res1); + ErrorF("\tRestoring original contents of MODE1_ADDR_REG\n"); + } +#endif + + outl(PCI_CFGMECH1_ADDRESS_REG, oldVal1); + + if (mode1Res1) { + + stages |= 0x02; + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tValue read back is non-zero, and indicates possible" + " config type 1\n"); + } +#endif + + if (ix86PciBusCheck()) { + +#ifdef DEBUGPCI + if (xf86Verbose > 2) + ErrorF("\tBus check Confirms this: "); +#endif + + xf86MsgVerb(X_INFO, 2, "PCI: Config type is 1\n"); + xf86MsgVerb(X_INFO, 3, + "PCI: stages = 0x%02x, oldVal1 = 0x%08lx, mode1Res1" + " = 0x%08lx\n", stages, (unsigned long)oldVal1, + (unsigned long)mode1Res1); + return; + } + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tBus check fails to confirm this, continuing type 1" + " check ...\n"); + } +#endif + + } + + stages |= 0x04; + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tWriting 0xff000001 to MODE1_ADDR_REG\n"); + } +#endif + outl(PCI_CFGMECH1_ADDRESS_REG, 0xff000001); + mode1Res2 = inl(PCI_CFGMECH1_ADDRESS_REG); + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tValue read back from MODE1_ADDR_REG is 0x%08x\n", + mode1Res2); + ErrorF("\tRestoring original contents of MODE1_ADDR_REG\n"); + } +#endif + + outl(PCI_CFGMECH1_ADDRESS_REG, oldVal1); + + if ((mode1Res2 & 0x80000001) == 0x80000000) { + + stages |= 0x08; + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tValue read back has only the msb set\n" + "\tThis indicates possible config type 1\n"); + } +#endif + + if (ix86PciBusCheck()) { + +#ifdef DEBUGPCI + if (xf86Verbose > 2) + ErrorF("\tBus check Confirms this: "); +#endif + + xf86MsgVerb(X_INFO, 2, "PCI: Config type is 1\n"); + xf86MsgVerb(X_INFO, 3, + "PCI: stages = 0x%02x, oldVal1 = 0x%08lx,\n" + "\tmode1Res1 = 0x%08lx, mode1Res2 = 0x%08lx\n", + stages, (unsigned long)oldVal1, + (unsigned long)mode1Res1, (unsigned long)mode1Res2); + return; + } + +#ifdef DEBUGPCI + if (xf86Verbose > 2) { + ErrorF("\tBus check fails to confirm this.\n"); + } +#endif + + } + } + + xf86MsgVerb(X_INFO, 3, "PCI: Standard check for type 1 failed.\n"); + xf86MsgVerb(X_INFO, 3, "PCI: stages = 0x%02x, oldVal1 = 0x%08lx,\n" + "\tmode1Res1 = 0x%08lx, mode1Res2 = 0x%08lx\n", + stages, (unsigned long)oldVal1, (unsigned long)mode1Res1, + (unsigned long)mode1Res2); + + /* Try config type 2 */ + oldVal2 = inb(PCI_CFGMECH2_ENABLE_REG); + if ((oldVal2 & 0xf0) == 0) { + ix86Pci0.configMech = PCI_CFG_MECH_2; + ix86Pci0.numDevices = PCI_CFGMECH2_MAXDEV; + ix86Pci0.funcs = &ix86Funcs2; + + outb(PCI_CFGMECH2_ENABLE_REG, 0x0e); + mode2Res1 = inb(PCI_CFGMECH2_ENABLE_REG); + outb(PCI_CFGMECH2_ENABLE_REG, oldVal2); + + if (mode2Res1 == 0x0e) { + if (ix86PciBusCheck()) { + xf86MsgVerb(X_INFO, 2, "PCI: Config type is 2\n"); + return; + } + } + } + break; /* } */ + + case PCIProbe2: /* { */ + if (!xf86EnableIO()) + return; + + /* The scanpci-style detection method */ + + xf86MsgVerb(X_INFO, 2, "PCI: Probing config type using method 2\n"); + + outb(PCI_CFGMECH2_ENABLE_REG, 0x00); + outb(PCI_CFGMECH2_FORWARD_REG, 0x00); + mode2Res1 = inb(PCI_CFGMECH2_ENABLE_REG); + mode2Res2 = inb(PCI_CFGMECH2_FORWARD_REG); + + if (mode2Res1 == 0 && mode2Res2 == 0) { + xf86MsgVerb(X_INFO, 2, "PCI: Config type is 2\n"); + ix86Pci0.configMech = PCI_CFG_MECH_2; + ix86Pci0.numDevices = PCI_CFGMECH2_MAXDEV; + ix86Pci0.funcs = &ix86Funcs2; + return; + } + + oldVal1 = inl(PCI_CFGMECH1_ADDRESS_REG); + outl(PCI_CFGMECH1_ADDRESS_REG, PCI_EN); + mode1Res1 = inl(PCI_CFGMECH1_ADDRESS_REG); + outl(PCI_CFGMECH1_ADDRESS_REG, oldVal1); + if (mode1Res1 == PCI_EN) { + xf86MsgVerb(X_INFO, 2, "PCI: Config type is 1\n"); + ix86Pci0.configMech = PCI_CFG_MECH_1; + ix86Pci0.numDevices = PCI_CFGMECH1_MAXDEV; + ix86Pci0.funcs = &ix86Funcs1; + return; + } + break; /* } */ + + case PCIForceConfig1: + if (!xf86EnableIO()) + return; + + xf86MsgVerb(X_INFO, 2, "PCI: Forcing config type 1\n"); + + ix86Pci0.configMech = PCI_CFG_MECH_1; + ix86Pci0.numDevices = PCI_CFGMECH1_MAXDEV; + ix86Pci0.funcs = &ix86Funcs1; + return; + + case PCIForceConfig2: + if (!xf86EnableIO()) + return; + + xf86MsgVerb(X_INFO, 2, "PCI: Forcing config type 2\n"); + + ix86Pci0.configMech = PCI_CFG_MECH_2; + ix86Pci0.numDevices = PCI_CFGMECH2_MAXDEV; + ix86Pci0.funcs = &ix86Funcs2; + return; + + case PCIForceNone: + break; + } + + /* No PCI found */ + ix86Pci0.configMech = PCI_CFG_MECH_UNKNOWN; + xf86MsgVerb(X_INFO, 2, "PCI: No PCI bus found or probed for\n"); +} + +#if 0 +static pciTagRec +ix86PcibusTag(CARD8 bus, CARD8 cardnum, CARD8 func) +{ + pciTagRec tag; + + tag.cfg1 = 0; + + if (func > 7 || cardnum >= pciBusInfo[bus]->numDevices) + return tag; + + switch (ix86Pci0.configMech) { + case PCI_CFG_MECH_1: + tag.cfg1 = PCI_EN | ((CARD32)bus << 16) | + ((CARD32)cardnum << 11) | + ((CARD32)func << 8); + break; + + case PCI_CFG_MECH_2: + tag.cfg2.port = 0xc000 | ((CARD16)cardnum << 8); + tag.cfg2.enable = 0xf0 | (func << 1); + tag.cfg2.forward = bus; + break; + } + + return tag; +} +#endif + +static CARD32 +ix86PciReadLongSetup(PCITAG Tag, int reg) +{ + ix86PciSelectCfgmech(); + return (*ix86Pci0.funcs->pciReadLong)(Tag,reg); +} + +static CARD32 +ix86PciReadLongCFG1(PCITAG Tag, int reg) +{ + CARD32 addr, data = 0; + +#ifdef DEBUGPCI + ErrorF("ix86PciReadLong 0x%lx, %d\n", Tag, reg); +#endif + + addr = PCI_ADDR_FROM_TAG_CFG1(Tag,reg); + outl(PCI_CFGMECH1_ADDRESS_REG, addr); + data = inl(PCI_CFGMECH1_DATA_REG); + outl(PCI_CFGMECH1_ADDRESS_REG, 0); + +#ifdef DEBUGPCI + ErrorF("ix86PciReadLong 0x%lx\n", data); +#endif + + return data; +} + +static CARD32 +ix86PciReadLongCFG2(PCITAG Tag, int reg) +{ + CARD32 addr, data = 0; + CARD8 forward, enable; + +#ifdef DEBUGPCI + ErrorF("ix86PciReadLong 0x%lx, %d\n", Tag, reg); +#endif + + forward = PCI_FORWARD_FROM_TAG(Tag); + enable = PCI_ENABLE_FROM_TAG(Tag); + addr = PCI_ADDR_FROM_TAG_CFG2(Tag,reg); + + outb(PCI_CFGMECH2_ENABLE_REG, enable); + outb(PCI_CFGMECH2_FORWARD_REG, forward); + data = inl((CARD16)addr); + outb(PCI_CFGMECH2_ENABLE_REG, 0); + outb(PCI_CFGMECH2_FORWARD_REG, 0); + +#ifdef DEBUGPCI + ErrorF("ix86PciReadLong 0x%lx\n", data); +#endif + + return data; +} + +static void +ix86PciWriteLongSetup(PCITAG Tag, int reg, CARD32 data) +{ + ix86PciSelectCfgmech(); + (*ix86Pci0.funcs->pciWriteLong)(Tag,reg,data); +} + +static void +ix86PciWriteLongCFG1(PCITAG Tag, int reg, CARD32 data) +{ + CARD32 addr; + + addr = PCI_ADDR_FROM_TAG_CFG1(Tag,reg); + outl(PCI_CFGMECH1_ADDRESS_REG, addr); + outl(PCI_CFGMECH1_DATA_REG, data); + outl(PCI_CFGMECH1_ADDRESS_REG, 0); +} + +static void +ix86PciWriteLongCFG2(PCITAG Tag, int reg, CARD32 data) +{ + CARD32 addr; + CARD8 forward, enable; + + forward = PCI_FORWARD_FROM_TAG(Tag); + enable = PCI_ENABLE_FROM_TAG(Tag); + addr = PCI_ADDR_FROM_TAG_CFG2(Tag,reg); + + outb(PCI_CFGMECH2_ENABLE_REG, enable); + outb(PCI_CFGMECH2_FORWARD_REG, forward); + outl((CARD16)addr, data); + outb(PCI_CFGMECH2_ENABLE_REG, 0); + outb(PCI_CFGMECH2_FORWARD_REG, 0); +} + +static void +ix86PciSetBitsLongSetup(PCITAG Tag, int reg, CARD32 mask, CARD32 val) +{ + ix86PciSelectCfgmech(); + (*ix86Pci0.funcs->pciSetBitsLong)(Tag,reg,mask,val); +} + +static void +ix86PciSetBitsLongCFG1(PCITAG Tag, int reg, CARD32 mask, CARD32 val) +{ + CARD32 addr, data = 0; + +#ifdef DEBUGPCI + ErrorF("ix86PciSetBitsLong 0x%lx, %d\n", Tag, reg); +#endif + + addr = PCI_ADDR_FROM_TAG_CFG1(Tag,reg); + outl(PCI_CFGMECH1_ADDRESS_REG, addr); + data = inl(PCI_CFGMECH1_DATA_REG); + data = (data & ~mask) | (val & mask); + outl(PCI_CFGMECH1_DATA_REG, data); + outl(PCI_CFGMECH1_ADDRESS_REG, 0); +} + +static void +ix86PciSetBitsLongCFG2(PCITAG Tag, int reg, CARD32 mask, CARD32 val) +{ + CARD32 addr, data = 0; + CARD8 enable, forward; + +#ifdef DEBUGPCI + ErrorF("ix86PciSetBitsLong 0x%lx, %d\n", Tag, reg); +#endif + + forward = PCI_FORWARD_FROM_TAG(Tag); + enable = PCI_ENABLE_FROM_TAG(Tag); + addr = PCI_ADDR_FROM_TAG_CFG2(Tag,reg); + + outb(PCI_CFGMECH2_ENABLE_REG, enable); + outb(PCI_CFGMECH2_FORWARD_REG, forward); + data = inl((CARD16)addr); + data = (data & ~mask) | (val & mask); + outl((CARD16)addr, data); + outb(PCI_CFGMECH2_ENABLE_REG, 0); + outb(PCI_CFGMECH2_FORWARD_REG, 0); +} + +void +ix86PciInit() +{ + /* Initialize pciBusInfo[] array and function pointers */ + pciNumBuses = 1; + pciBusInfo[0] = &ix86Pci0; + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; + + /* Make sure that there is a PCI bus present. */ + ix86PciSelectCfgmech(); + if (ix86Pci0.configMech == PCI_CFG_MECH_UNKNOWN) { + pciNumBuses = 0; + pciBusInfo[0] = NULL; + } +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c new file mode 100644 index 000000000..40fb4604b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c @@ -0,0 +1,894 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c,v 1.9 2002/09/24 16:14:16 tsi Exp $ */ +/* + * 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 + +#include <stdio.h> +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "Pci.h" + +/* + * linux platform specific PCI access functions -- using /proc/bus/pci + * needs kernel version 2.2.x + */ +static CARD32 linuxPciCfgRead(PCITAG tag, int off); +static void linuxPciCfgWrite(PCITAG, int off, CARD32 val); +static void linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits); +static ADDRESS linuxTransAddrBusToHost(PCITAG tag, PciAddrType type, ADDRESS addr); +#if defined(__powerpc__) +static ADDRESS linuxPpcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS); +static ADDRESS linuxPpcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS); +#endif + +static CARD8 linuxPciCfgReadByte(PCITAG tag, int off); +static void linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val); +static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); +static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); + +static pciBusFuncs_t linuxFuncs0 = { +/* pciReadLong */ linuxPciCfgRead, +/* pciWriteLong */ linuxPciCfgWrite, +/* pciSetBitsLong */ linuxPciCfgSetBits, +#if defined(__powerpc__) +/* pciAddrHostToBus */ linuxPpcHostAddrToBusAddr, +/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr, +#else +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ linuxTransAddrBusToHost, +#endif + +/* pciControlBridge */ NULL, +/* pciGetBridgeBuses */ NULL, +/* pciGetBridgeResources */ NULL, + +/* pciReadByte */ linuxPciCfgReadByte, +/* pciWriteByte */ linuxPciCfgWriteByte, + +/* pciReadWord */ linuxPciCfgReadWord, +/* pciWriteWord */ linuxPciCfgWriteWord, +}; + +static pciBusInfo_t linuxPci0 = { +/* configMech */ PCI_CFG_MECH_OTHER, +/* numDevices */ 32, +/* secondary */ FALSE, +/* primary_bus */ 0, +#ifdef PowerMAX_OS +/* ppc_io_base */ 0, +/* ppc_io_size */ 0, +#endif +/* funcs */ &linuxFuncs0, +/* pciBusPriv */ NULL, +/* bridge */ NULL +}; + +void +linuxPciInit() +{ + struct stat st; + if ((xf86Info.pciFlags == PCIForceNone) || + (-1 == stat("/proc/bus/pci", &st))) { + /* when using this as default for all linux architectures, + we'll need a fallback for 2.0 kernels here */ + return; + } + pciNumBuses = 1; + pciBusInfo[0] = &linuxPci0; + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; +} + +static int +linuxPciOpenFile(PCITAG tag, Bool write) +{ + static int lbus,ldev,lfunc,fd = -1,is_write = 0; + int bus, dev, func; + char file[32]; + struct stat ignored; + + bus = PCI_BUS_FROM_TAG(tag); + dev = PCI_DEV_FROM_TAG(tag); + func = PCI_FUNC_FROM_TAG(tag); + if (fd == -1 || (write && (!is_write)) + || bus != lbus || dev != ldev || func != lfunc) { + if (fd != -1) + close(fd); + if (bus < 256) { + sprintf(file,"/proc/bus/pci/%02x",bus); + if (stat(file, &ignored) < 0) + sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x", + bus, dev, func); + else + sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", + bus, dev, func); + } else { + sprintf(file,"/proc/bus/pci/%04x",bus); + if (stat(file, &ignored) < 0) + sprintf(file, "/proc/bus/pci/0000:%04x/%02x.%1x", + bus, dev, func); + else + sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", + bus, dev, func); + } + if (write) { + fd = open(file,O_RDWR); + if (fd != -1) is_write = TRUE; + } else switch (is_write) { + case TRUE: + fd = open(file,O_RDWR); + if (fd > -1) + break; + default: + fd = open(file,O_RDONLY); + is_write = FALSE; + } + + lbus = bus; + ldev = dev; + lfunc = func; + } + return fd; +} + +static CARD32 +linuxPciCfgRead(PCITAG tag, int off) +{ + int fd; + CARD32 val = 0xffffffff; + + if (-1 != (fd = linuxPciOpenFile(tag,FALSE))) { + lseek(fd,off,SEEK_SET); + read(fd,&val,4); + } + return PCI_CPU(val); +} + +static void +linuxPciCfgWrite(PCITAG tag, int off, CARD32 val) +{ + int fd; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd,off,SEEK_SET); + val = PCI_CPU(val); + write(fd,&val,4); + } +} + +static void +linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits) +{ + int fd; + CARD32 val = 0xffffffff; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd,off,SEEK_SET); + read(fd,&val,4); + val = PCI_CPU(val); + val = (val & ~mask) | (bits & mask); + val = PCI_CPU(val); + lseek(fd,off,SEEK_SET); + write(fd,&val,4); + } +} + +/* + * This function will convert a BAR address into a host address + * suitable for passing into the mmap function of a /proc/bus + * device. + */ +ADDRESS linuxTransAddrBusToHost(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + ADDRESS ret = xf86GetOSOffsetFromPCI(tag, PCI_MEM|PCI_IO, addr); + + if (ret) + return ret; + + /* + * if it is not a BAR address, it must be legacy, (or wrong) + * return it as is.. + */ + return addr; +} + + +#if defined(__powerpc__) + +#ifndef __NR_pciconfig_iobase +#define __NR_pciconfig_iobase 200 +#endif + +static ADDRESS +linuxPpcBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + if (type == PCI_MEM) + { + ADDRESS membase = syscall(__NR_pciconfig_iobase, 1, + PCI_BUS_FROM_TAG(tag), PCI_DFN_FROM_TAG(tag)); + return (addr + membase); + } + else if (type == PCI_IO) + { + ADDRESS iobase = syscall(__NR_pciconfig_iobase, 2, + PCI_BUS_FROM_TAG(tag), PCI_DFN_FROM_TAG(tag)); + return (addr + iobase); + } + else return addr; +} + +static ADDRESS +linuxPpcHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + if (type == PCI_MEM) + { + ADDRESS membase = syscall(__NR_pciconfig_iobase, 1, + PCI_BUS_FROM_TAG(tag), PCI_DFN_FROM_TAG(tag)); + return (addr - membase); + } + else if (type == PCI_IO) + { + ADDRESS iobase = syscall(__NR_pciconfig_iobase, 2, + PCI_BUS_FROM_TAG(tag), PCI_DFN_FROM_TAG(tag)); + return (addr - iobase); + } + else return addr; +} + +#endif /* __powerpc__ */ + +static CARD8 +linuxPciCfgReadByte(PCITAG tag, int off) +{ + int fd; + CARD8 val = 0xff; + + if (-1 != (fd = linuxPciOpenFile(tag,FALSE))) { + lseek(fd,off,SEEK_SET); + read(fd,&val,1); + } + + return val; +} + +static void +linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val) +{ + int fd; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd,off,SEEK_SET); + write(fd, &val, 1); + } +} + +static CARD16 +linuxPciCfgReadWord(PCITAG tag, int off) +{ + int fd; + CARD16 val = 0xff; + + if (-1 != (fd = linuxPciOpenFile(tag,FALSE))) { + lseek(fd, off, SEEK_SET); + read(fd, &val, 2); + } + + return PCI_CPU16(val); +} + +static void +linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val) +{ + int fd; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd, off, SEEK_SET); + val = PCI_CPU16(val); + write(fd, &val, 2); + } +} + +#ifndef INCLUDE_XF86_NO_DOMAIN + +/* + * Compiling the following simply requires the presence of <linux/pci.c>. + * Actually running this is another matter altogether... + * + * This scheme requires that the kernel allow mmap()'ing of a host bridge's I/O + * and memory spaces through its /proc/bus/pci/BUS/DFN entry. Which one is + * determined by a prior ioctl(). + * + * For the sparc64 port, this means 2.4.12 or later. For ppc, this + * functionality is almost, but not quite there yet. Alpha and other kernel + * ports to multi-domain architectures still need to implement this. + * + * This scheme is also predicated on the use of an IOADDRESS compatible type to + * designate I/O addresses. Although IOADDRESS is defined as an unsigned + * integral type, it is actually the virtual address of, i.e. a pointer to, the + * I/O port to access. And so, the inX/outX macros in "compiler.h" need to be + * #define'd appropriately (as is done on SPARC's). + * + * Another requirement to port this scheme to another multi-domain architecture + * is to add the appropriate entries in the pciControllerSizes array below. + * + * TO DO: Address the deleterious reaction some host bridges have to master + * aborts. This is already done for secondary PCI buses, but not yet + * for accesses to primary buses (except for the SPARC port, where + * master aborts are avoided during PCI scans). + */ + +#include <linux/pci.h> + +#ifndef PCIIOC_BASE /* Ioctls for /proc/bus/pci/X/Y nodes. */ +#define PCIIOC_BASE ('P' << 24 | 'C' << 16 | 'I' << 8) + +/* Get controller for PCI device. */ +#define PCIIOC_CONTROLLER (PCIIOC_BASE | 0x00) +/* Set mmap state to I/O space. */ +#define PCIIOC_MMAP_IS_IO (PCIIOC_BASE | 0x01) +/* Set mmap state to MEM space. */ +#define PCIIOC_MMAP_IS_MEM (PCIIOC_BASE | 0x02) +/* Enable/disable write-combining. */ +#define PCIIOC_WRITE_COMBINE (PCIIOC_BASE | 0x03) + +#endif + +/* This probably shouldn't be Linux-specific */ +static pciConfigPtr +xf86GetPciHostConfigFromTag(PCITAG Tag) +{ + int bus = PCI_BUS_FROM_TAG(Tag); + pciBusInfo_t *pBusInfo; + + while ((bus < pciNumBuses) && (pBusInfo = pciBusInfo[bus])) { + if (bus == pBusInfo->primary_bus) + return pBusInfo->bridge; + bus = pBusInfo->primary_bus; + } + + return NULL; /* Bad data */ +} + +/* + * This is ugly, but until I can extract this information from the kernel, + * it'll have to do. The default I/O space size is 64K, and 4G for memory. + * Anything else needs to go in this table. (PowerPC folk take note.) + * + * Note that Linux/SPARC userland is 32-bit, so 4G overflows to zero here. + * + * Please keep this table in ascending vendor/device order. + */ +static struct pciSizes { + unsigned short vendor, device; + unsigned long io_size, mem_size; +} pciControllerSizes[] = { + { + PCI_VENDOR_SUN, PCI_CHIP_PSYCHO, + 1U << 16, 1U << 31 + }, + { + PCI_VENDOR_SUN, PCI_CHIP_SCHIZO, + 1U << 24, 1U << 31 /* ??? */ + }, + { + PCI_VENDOR_SUN, PCI_CHIP_SABRE, + 1U << 24, (unsigned long)(1ULL << 32) + }, + { + PCI_VENDOR_SUN, PCI_CHIP_HUMMINGBIRD, + 1U << 24, (unsigned long)(1ULL << 32) + } +}; +#define NUM_SIZES (sizeof(pciControllerSizes) / sizeof(pciControllerSizes[0])) + +static unsigned long +linuxGetIOSize(PCITAG Tag) +{ + pciConfigPtr pPCI; + int i; + + /* Find host bridge */ + if ((pPCI = xf86GetPciHostConfigFromTag(Tag))) { + /* Look up vendor/device */ + for (i = 0; i < NUM_SIZES; i++) { + if (pPCI->pci_vendor > pciControllerSizes[i].vendor) + continue; + if (pPCI->pci_vendor < pciControllerSizes[i].vendor) + break; + if (pPCI->pci_device > pciControllerSizes[i].device) + continue; + if (pPCI->pci_device < pciControllerSizes[i].device) + break; + return pciControllerSizes[i].io_size; + } + } + + return 1U << 16; /* Default to 64K */ +} + +static void +linuxGetSizes(PCITAG Tag, unsigned long *io_size, unsigned long *mem_size) +{ + pciConfigPtr pPCI; + int i; + + *io_size = (1U << 16); /* Default to 64K */ + *mem_size = (unsigned long)(1ULL << 32); /* Default to 4G */ + + /* Find host bridge */ + if ((pPCI = xf86GetPciHostConfigFromTag(Tag))) { + /* Look up vendor/device */ + for (i = 0; i < NUM_SIZES; i++) { + if (pPCI->pci_vendor > pciControllerSizes[i].vendor) + continue; + if (pPCI->pci_vendor < pciControllerSizes[i].vendor) + break; + if (pPCI->pci_device > pciControllerSizes[i].device) + continue; + if (pPCI->pci_device < pciControllerSizes[i].device) + break; + *io_size = pciControllerSizes[i].io_size; + *mem_size = pciControllerSizes[i].mem_size; + break; + } + } +} + +int +xf86GetPciDomain(PCITAG Tag) +{ + pciConfigPtr pPCI; + int fd, result; + + pPCI = xf86GetPciHostConfigFromTag(Tag); + + if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) + return result; + + if (!pPCI || pPCI->fakeDevice) + return 1; /* Domain 0 is reserved */ + + if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) + return 0; + + if ((result = ioctl(fd, PCIIOC_CONTROLLER, 0)) < 0) + return 0; + + return result + 1; /* Domain 0 is reserved */ +} + +static pointer +linuxMapPci(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size, int mmap_ioctl) +{ + do { + pciConfigPtr pPCI; + unsigned char *result; + ADDRESS realBase, Offset; + int fd, mmapflags, prot; + + xf86InitVidMem(); + + pPCI = xf86GetPciHostConfigFromTag(Tag); + + if (((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) || + (ioctl(fd, mmap_ioctl, 0) < 0)) + break; + +/* Note: IA-64 doesn't compile this and doesn't need to */ +#ifdef __ia64__ + +# ifndef MAP_WRITECOMBINED +# define MAP_WRITECOMBINED 0x00010000 +# endif +# ifndef MAP_NONCACHED +# define MAP_NONCACHED 0x00020000 +# endif + + if (Flags & VIDMEM_FRAMEBUFFER) + mmapflags = MAP_SHARED | MAP_WRITECOMBINED; + else + mmapflags = MAP_SHARED | MAP_NONCACHED; + +#else /* !__ia64__ */ + + mmapflags = (Flags & VIDMEM_FRAMEBUFFER) / VIDMEM_FRAMEBUFFER; + + if (ioctl(fd, PCIIOC_WRITE_COMBINE, mmapflags) < 0) + break; + + mmapflags = MAP_SHARED; + +#endif /* ?__ia64__ */ + + /* Align to page boundary */ + realBase = Base & ~(getpagesize() - 1); + Offset = Base - realBase; + + if (Flags & VIDMEM_READONLY) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + + result = mmap(NULL, Size + Offset, prot, mmapflags, fd, realBase); + + if (!result || ((pointer)result == MAP_FAILED)) + return NULL; + + xf86MakeNewMapping(ScreenNum, Flags, realBase, Size + Offset, result); + + return result + Offset; + } while (0); + + if (mmap_ioctl == PCIIOC_MMAP_IS_MEM) + return xf86MapVidMem(ScreenNum, Flags, Base, Size); + + return NULL; +} + +#define MAX_DOMAINS 257 +static pointer DomainMmappedIO[MAX_DOMAINS]; +static pointer DomainMmappedMem[MAX_DOMAINS]; + +static int +linuxOpenLegacy(PCITAG Tag, char *name) +{ +#define PREFIX "/sys/class/pci_bus/%04x:%02x/%s" + char *path; + int domain, bus; + pciBusInfo_t *pBusInfo; + pciConfigPtr bridge = NULL; + int fd; + + path = xalloc(strlen(PREFIX) + strlen(name)); + if (!path) + return -1; + + for (;;) { + domain = xf86GetPciDomain(Tag); + bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); + + /* Domain 0 is reserved -- see xf86GetPciDomain() */ + if ((domain <= 0) || (domain >= MAX_DOMAINS)) + FatalError("linuxOpenLegacy(): domain out of range\n"); + + sprintf(path, PREFIX, domain - 1, bus, name); + fd = open(path, O_RDWR); + if (fd >= 0) { + xfree(path); + return fd; + } + + pBusInfo = pciBusInfo[bus]; + if (!pBusInfo || (bridge == pBusInfo->bridge) || + !(bridge = pBusInfo->bridge)) { + xfree(path); + return -1; + } + + Tag = bridge->tag; + } + + xfree(path); + return fd; +} + +/* + * xf86MapDomainMemory - memory map PCI domain memory + * + * This routine maps the memory region in the domain specified by Tag and + * returns a pointer to it. The pointer is saved for future use if it's in + * the legacy ISA memory space (memory in a domain between 0 and 1MB). + */ +pointer +xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size) +{ + int domain = xf86GetPciDomain(Tag); + int fd; + + /* + * We use /proc/bus/pci on non-legacy addresses or if the Linux sysfs + * legacy_mem interface is unavailable. + */ + if (Base > 1024*1024) + return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, + PCIIOC_MMAP_IS_MEM); + + if ((fd = linuxOpenLegacy(Tag, "legacy_mem")) < 0) + return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, + PCIIOC_MMAP_IS_MEM); + + + /* If we haven't already mapped this legacy space, try to. */ + if (!DomainMmappedMem[domain]) { + DomainMmappedMem[domain] = mmap(NULL, 1024*1024, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0); + if (DomainMmappedMem[domain] == MAP_FAILED) { + close(fd); + perror("mmap failure"); + FatalError("xf86MapDomainMem(): mmap() failure\n"); + } + } + + close(fd); + return (pointer)((char *)DomainMmappedMem[domain] + Base); +} + +/* + * xf86MapDomainIO - map I/O space in this domain + * + * Each domain has a legacy ISA I/O space. This routine will try to + * map it using the Linux sysfs legacy_io interface. If that fails, + * it'll fall back to using /proc/bus/pci. + * + * If the legacy_io interface *does* exist, the file descriptor (fd below) + * will be saved in the DomainMmappedIO array in the upper bits of the + * pointer. Callers will do I/O with small port numbers (<64k values), so + * the platform I/O code can extract the port number and the fd, lseek to + * the port number in the legacy_io file, and issue the read or write. + * + * This has no means of returning failure, so all errors are fatal + */ +IOADDRESS +xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, + IOADDRESS Base, unsigned long Size) +{ + int domain = xf86GetPciDomain(Tag); + int fd; + + if ((domain <= 0) || (domain >= MAX_DOMAINS)) + FatalError("xf86MapDomainIO(): domain out of range\n"); + + if (DomainMmappedIO[domain]) + return (IOADDRESS)DomainMmappedIO[domain] + Base; + + /* Permanently map all of I/O space */ + if ((fd = linuxOpenLegacy(Tag, "legacy_io")) < 0) { + DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag, + 0, linuxGetIOSize(Tag), + PCIIOC_MMAP_IS_IO); + /* ia64 can't mmap legacy IO port space */ + if (!DomainMmappedIO[domain]) + return Base; + } + else { /* legacy_io file exists, encode fd */ + DomainMmappedIO[domain] = (pointer)(fd << 24); + } + + return (IOADDRESS)DomainMmappedIO[domain] + Base; +} + +/* + * xf86ReadDomainMemory - copy from domain memory into a caller supplied buffer + */ +int +xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) +{ + unsigned char *ptr, *src; + ADDRESS offset; + unsigned long size; + int len, pagemask = getpagesize() - 1; + + unsigned int i, dom, bus, dev, func; + unsigned int fd; + char file[256]; + struct stat st; + + dom = PCI_DOM_FROM_TAG(Tag); + bus = PCI_BUS_FROM_TAG(Tag); + dev = PCI_DEV_FROM_TAG(Tag); + func = PCI_FUNC_FROM_TAG(Tag); + sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", + dom, bus, dom, bus, dev, func); + + /* + * If the caller wants the ROM and the sysfs rom interface exists, + * try to use it instead of reading it from /proc/bus/pci. + */ + if (((Base & 0xfffff) == 0xC0000) && (stat(file, &st) == 0)) { + if ((fd = open(file, O_RDWR))) + Base = 0x0; + + /* enable the ROM first */ + write(fd, "1", 2); + lseek(fd, 0, SEEK_SET); + + /* copy the ROM until we hit Len, EOF or read error */ + for (i = 0; i < Len && read(fd, Buf, 1) > 0; Buf++, i++) + ; + + write(fd, "0", 2); + close(fd); + + return Len; + } + + /* Ensure page boundaries */ + offset = Base & ~pagemask; + size = ((Base + Len + pagemask) & ~pagemask) - offset; + + ptr = xf86MapDomainMemory(-1, VIDMEM_READONLY, Tag, offset, size); + + if (!ptr) + return -1; + + /* Using memcpy() here can hang the system */ + src = ptr + (Base - offset); + for (len = Len; len-- > 0;) + *Buf++ = *src++; + + xf86UnMapVidMem(-1, ptr, size); + + return Len; +} + +resPtr +xf86BusAccWindowsFromOS(void) +{ + pciConfigPtr *ppPCI, pPCI; + resPtr pRes = NULL; + resRange range; + unsigned long io_size, mem_size; + int domain; + + if ((ppPCI = xf86scanpci(0))) { + for (; (pPCI = *ppPCI); ppPCI++) { + if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) || + (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST)) + continue; + + domain = xf86GetPciDomain(pPCI->tag); + linuxGetSizes(pPCI->tag, &io_size, &mem_size); + + RANGE(range, 0, (ADDRESS)(mem_size - 1), + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0, (IOADDRESS)(io_size - 1), + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + if (domain <= 0) + break; + } + } + + return pRes; +} + +resPtr +xf86PciBusAccWindowsFromOS(void) +{ + pciConfigPtr *ppPCI, pPCI; + resPtr pRes = NULL; + resRange range; + unsigned long io_size, mem_size; + int domain; + + if ((ppPCI = xf86scanpci(0))) { + for (; (pPCI = *ppPCI); ppPCI++) { + if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) || + (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST)) + continue; + + domain = xf86GetPciDomain(pPCI->tag); + linuxGetSizes(pPCI->tag, &io_size, &mem_size); + + RANGE(range, 0, (ADDRESS)(mem_size - 1), + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0, (IOADDRESS)(io_size - 1), + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + if (domain <= 0) + break; + } + } + + return pRes; +} + + +resPtr +xf86AccResFromOS(resPtr pRes) +{ + pciConfigPtr *ppPCI, pPCI; + resRange range; + unsigned long io_size, mem_size; + int domain; + + if ((ppPCI = xf86scanpci(0))) { + for (; (pPCI = *ppPCI); ppPCI++) { + if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) || + (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST)) + continue; + + domain = xf86GetPciDomain(pPCI->tag); + linuxGetSizes(pPCI->tag, &io_size, &mem_size); + + /* + * At minimum, the top and bottom resources must be claimed, so + * that resources that are (or appear to be) unallocated can be + * relocated. + */ + RANGE(range, 0x00000000u, 0x0009ffffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, 0x000c0000u, 0x000effffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, 0x000f0000u, 0x000fffffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, (ADDRESS)(mem_size - 1), (ADDRESS)(mem_size - 1), + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0x00000000u, 0x00000000u, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, (IOADDRESS)(io_size - 1), (IOADDRESS)(io_size - 1), + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + if (domain <= 0) + break; + } + } + + return pRes; +} + +#endif /* !INCLUDE_XF86_NO_DOMAIN */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/netbsdPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/netbsdPci.c new file mode 100644 index 000000000..7dbbfdec7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/netbsdPci.c @@ -0,0 +1,132 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/netbsdPci.c,v 1.4 2003/08/24 17:37:04 dawes Exp $ */ +/* + * Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project + * shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written + * authorization from the XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <dev/pci/pciio.h> + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86OSpriv.h" + +#include "Pci.h" + +static CARD32 netbsdPciConfRead(PCITAG, int); +static void netbsdPciConfWrite(PCITAG, int, CARD32); +static void netbsdPciSetBits(PCITAG, int, CARD32, CARD32); + +static int devpci = -1; + +static pciBusFuncs_t netbsdFuncs0 = { +/* pciReadLong */ netbsdPciConfRead, +/* pciWriteLong */ netbsdPciConfWrite, +/* pciSetBitsLong */ netbsdPciSetBits, +/* pciAddrHostToBus */ pciAddrNOOP, +/* pciAddrBusToHost */ pciAddrNOOP +}; + +static pciBusInfo_t netbsdPci0 = { +/* configMech */ PCI_CFG_MECH_OTHER, +/* numDevices */ 32, +/* secondary */ FALSE, +/* primary_bus */ 0, +/* funcs */ &netbsdFuncs0, +/* pciBusPriv */ NULL, +/* bridge */ NULL +}; + +void +netbsdPciInit() +{ + struct pciio_businfo pci_businfo; + + devpci = open("/dev/pci0", O_RDWR); + if (devpci == -1) + FatalError("netbsdPciInit: can't open /dev/pci0\n"); + + pciNumBuses = 1; + pciBusInfo[0] = &netbsdPci0; + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; + /* use businfo to get the number of devs */ + if (ioctl(devpci, PCI_IOC_BUSINFO, &pci_businfo) != 0) + FatalError("netbsdPciInit: not a PCI bus device"); + netbsdPci0.numDevices = pci_businfo.maxdevs; +} + +static CARD32 +netbsdPciConfRead(PCITAG tag, int reg) +{ + struct pciio_bdf_cfgreg bdfr; + + bdfr.bus = PCI_BUS_FROM_TAG(tag); + bdfr.device = PCI_DEV_FROM_TAG(tag); + bdfr.function = PCI_FUNC_FROM_TAG(tag); + bdfr.cfgreg.reg = reg; + + if (ioctl(devpci, PCI_IOC_BDF_CFGREAD, &bdfr) == -1) + FatalError("netbsdPciConfRead: failed on %d/%d/%d\n", + bdfr.bus, bdfr.device, bdfr.function); + + return (bdfr.cfgreg.val); +} + +static void +netbsdPciConfWrite(PCITAG tag, int reg, CARD32 val) +{ + struct pciio_bdf_cfgreg bdfr; + + bdfr.bus = PCI_BUS_FROM_TAG(tag); + bdfr.device = PCI_DEV_FROM_TAG(tag); + bdfr.function = PCI_FUNC_FROM_TAG(tag); + bdfr.cfgreg.reg = reg; + bdfr.cfgreg.val = val; + + if (ioctl(devpci, PCI_IOC_BDF_CFGWRITE, &bdfr) == -1) + FatalError("netbsdPciConfWrite: failed on %d/%d/%d\n", + bdfr.bus, bdfr.device, bdfr.function); +} + +static void +netbsdPciSetBits(PCITAG tag, int reg, CARD32 mask, CARD32 bits) +{ + CARD32 val; + + val = netbsdPciConfRead(tag, reg); + val = (val & ~mask) | (bits & mask); + netbsdPciConfWrite(tag, reg, val); +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ppcPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ppcPci.c new file mode 100644 index 000000000..7a438af67 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/ppcPci.c @@ -0,0 +1,311 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/ppcPci.c,v 1.8 2002/07/24 19:06:52 tsi Exp $ */ +/* + * 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 + +#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); + motoppcPciInit(); + +#endif +} + +#if defined(PowerMAX_OS) + +/* + * 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); + + +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 +motoppcPciInit() +{ + pciNumBuses = 1; + pciBusInfo[0] = &motoppcPci0; + pciFindFirstFP = pciGenFindFirst; + pciFindNextFP = pciGenFindNext; + + if (!xf86EnableIO()) + FatalError("motoppcPciInit: EnableIO failed\n"); + + 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 */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/sparcPci.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/sparcPci.c new file mode 100644 index 000000000..48e10ede4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/sparcPci.c @@ -0,0 +1,1052 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/sparcPci.c,v 1.14 2003/08/24 17:37:04 dawes Exp $ */ +/* + * Copyright (C) 2001-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "Pci.h" +#include "xf86sbusBus.h" + +#if defined(sun) + +extern char *apertureDevName; +static int apertureFd = -1; + +/* + * A version of xf86MapVidMem() that allows for 64-bit displacements (but not + * sizes). Areas thus mapped can be unmapped by xf86UnMapVidMem(). + */ +static pointer +sparcMapAperture(int iScreen, int Flags, + unsigned long long Base, unsigned long Size) +{ + pointer result; + static int lastFlags = 0; + + /* Assume both Base & Size are multiples of the page size */ + + if ((apertureFd < 0) || (Flags != lastFlags)) { + if (apertureFd >= 0) + close(apertureFd); + lastFlags = Flags; + apertureFd = open(apertureDevName, + (Flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); + if (apertureFd < 0) + FatalError("sparcMapAperture: open failure: %s\n", + strerror(errno)); + } + + result = mmap(NULL, Size, + (Flags & VIDMEM_READONLY) ? + PROT_READ : (PROT_READ | PROT_WRITE), + MAP_SHARED, apertureFd, (off_t)Base); + + if (result == MAP_FAILED) + FatalError("sparcMapAperture: mmap failure: %s\n", strerror(errno)); + + return result; +} + +/* + * Platform-specific bus privates. + */ +typedef struct _sparcDomainRec { + unsigned long long io_addr, io_size; + unsigned long long mem_addr, mem_size; + pointer pci, io; + int bus_min, bus_max; + unsigned char dfn_mask[256 / 8]; +} sparcDomainRec, *sparcDomainPtr; + +#define SetBitInMap(bit, map) \ + do { \ + int _bit = (bit); \ + (map)[_bit >> 3] |= 1 << (_bit & 7); \ + } while (0) + +#define IsBitSetInMap(bit, map) \ + ((map)[(bit) >> 3] & (1 << ((bit) & 7))) + +/* + * Domain 0 is reserved for the one that represents the system as a whole, i.e. + * the one without any resource relocations. + */ +#define MAX_DOMAINS (MAX_PCI_BUSES / 256) +static sparcDomainPtr xf86DomainInfo[MAX_DOMAINS]; +static int pciNumDomains = 1; + +/* Variables that are assigned this must be declared volatile */ +#define PciReg(base, tag, off, type) \ + *(volatile type *)(pointer)((char *)(base) + \ + (PCI_TAG_NO_DOMAIN(tag) | (off))) + +/* Generic SPARC PCI access functions */ +static CARD32 +sparcPciCfgRead32(PCITAG tag, int off) +{ + pciBusInfo_t *pBusInfo; + sparcDomainPtr pDomain; + volatile CARD32 result = (CARD32)(-1); /* Must be volatile */ + int bus; + + if ((off >= 0) && (off <= 252) && !(off & 3) && + ((bus = PCI_BUS_FROM_TAG(tag)) < pciNumBuses) && + (pBusInfo = pciBusInfo[bus]) && (pDomain = pBusInfo->pciBusPriv) && + (bus >= pDomain->bus_min) && (bus < pDomain->bus_max) && + ((bus > pDomain->bus_min) || + IsBitSetInMap(PCI_DFN_FROM_TAG(tag), pDomain->dfn_mask))) { + result = PciReg(pDomain->pci, tag, off, CARD32); + + result = PCI_CPU(result); + } + + return result; +} + +static void +sparcPciCfgWrite32(PCITAG tag, int off, CARD32 val) +{ + pciBusInfo_t *pBusInfo; + sparcDomainPtr pDomain; + int bus; + + if ((off < 0) || (off > 252) || (off & 3) || + ((bus = PCI_BUS_FROM_TAG(tag)) >= pciNumBuses) || + !(pBusInfo = pciBusInfo[bus]) || !(pDomain = pBusInfo->pciBusPriv) || + (bus < pDomain->bus_min) || (bus >= pDomain->bus_max) || + ((bus == pDomain->bus_min) && + !IsBitSetInMap(PCI_DFN_FROM_TAG(tag), pDomain->dfn_mask))) + return; + + val = PCI_CPU(val); + PciReg(pDomain->pci, tag, off, CARD32) = val; +} + +static void +sparcPciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits) +{ + CARD32 PciVal; + + PciVal = sparcPciCfgRead32(tag, off); + PciVal &= ~mask; + PciVal |= bits; + sparcPciCfgWrite32(tag, off, PciVal); +} + +static pciBusFuncs_t sparcPCIFunctions = +{ + sparcPciCfgRead32, + sparcPciCfgWrite32, + sparcPciCfgSetBits32, + pciAddrNOOP, + pciAddrNOOP +}; + +/* + * Sabre-specific versions of the above because of its peculiar access size + * requirements. + */ +static CARD32 +sabrePciCfgRead32(PCITAG tag, int off) +{ + pciBusInfo_t *pBusInfo; + sparcDomainPtr pDomain; + volatile CARD32 result; /* Must be volatile */ + int bus; + + if (PCI_BDEV_FROM_TAG(tag)) + return sparcPciCfgRead32(tag, off); + + if (PCI_FUNC_FROM_TAG(tag) || (off < 0) || (off > 252) || (off & 3) || + ((bus = PCI_BUS_FROM_TAG(tag)) >= pciNumBuses) || + !(pBusInfo = pciBusInfo[bus]) || !(pDomain = pBusInfo->pciBusPriv) || + (bus != pDomain->bus_min)) + return (CARD32)(-1); + + if (off < 8) { + result = (PciReg(pDomain->pci, tag, off, CARD16) << 16) | + PciReg(pDomain->pci, tag, off + 2, CARD16); + return PCI_CPU(result); + } + + result = (PciReg(pDomain->pci, tag, off + 3, CARD8) << 24) | + (PciReg(pDomain->pci, tag, off + 2, CARD8) << 16) | + (PciReg(pDomain->pci, tag, off + 1, CARD8) << 8) | + (PciReg(pDomain->pci, tag, off , CARD8) ); + return result; +} + +static void +sabrePciCfgWrite32(PCITAG tag, int off, CARD32 val) +{ + pciBusInfo_t *pBusInfo; + sparcDomainPtr pDomain; + int bus; + + if (PCI_BDEV_FROM_TAG(tag)) + sparcPciCfgWrite32(tag, off, val); + else if (!PCI_FUNC_FROM_TAG(tag) && + (off >= 0) && (off <= 252) && !(off & 3) && + ((bus = PCI_BUS_FROM_TAG(tag)) < pciNumBuses) && + (pBusInfo = pciBusInfo[bus]) && + (pDomain = pBusInfo->pciBusPriv) && + (bus == pDomain->bus_min)) { + if (off < 8) { + val = PCI_CPU(val); + PciReg(pDomain->pci, tag, off , CARD16) = val >> 16; + PciReg(pDomain->pci, tag, off + 2, CARD16) = val; + } else { + PciReg(pDomain->pci, tag, off , CARD8) = val; + PciReg(pDomain->pci, tag, off + 1, CARD8) = val >> 8; + PciReg(pDomain->pci, tag, off + 2, CARD8) = val >> 16; + PciReg(pDomain->pci, tag, off + 3, CARD8) = val >> 24; + } + } +} + +static void +sabrePciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits) +{ + CARD32 PciVal; + + PciVal = sabrePciCfgRead32(tag, off); + PciVal &= ~mask; + PciVal |= bits; + sabrePciCfgWrite32(tag, off, PciVal); +} + +static pciBusFuncs_t sabrePCIFunctions = +{ + sabrePciCfgRead32, + sabrePciCfgWrite32, + sabrePciCfgSetBits32, + pciAddrNOOP, + pciAddrNOOP +}; + +static int pagemask; + +/* Scan PROM for all PCI host bridges in the system */ +void +sparcPciInit(void) +{ + int node, node2; + + if (!xf86LinearVidMem()) + return; + + apertureFd = open(apertureDevName, O_RDWR); + if (apertureFd < 0) { + xf86Msg(X_ERROR, + "sparcPciInit: open failure: %s\n", strerror(errno)); + return; + } + + sparcPromInit(); + pagemask = xf86getpagesize() - 1; + + for (node = promGetChild(promRootNode); + node; + node = promGetSibling(node)) { + unsigned long long pci_addr; + sparcDomainRec domain; + sparcDomainPtr pDomain; + pciBusFuncs_p pFunctions; + char *prop_val; + int prop_len, bus; + + prop_val = promGetProperty("name", &prop_len); + /* Some PROMs include the trailing null; some don't */ + if (!prop_val || (prop_len < 3) || (prop_len > 4) || + strcmp(prop_val, "pci")) + continue; + + prop_val = promGetProperty("model", &prop_len); + if (!prop_val || (prop_len <= 0)) { + prop_val = promGetProperty("compatible", &prop_len); + if (!prop_val || (prop_len <= 0)) + continue; + } + + pFunctions = &sparcPCIFunctions; + (void)memset(&domain, 0, sizeof(domain)); + + if (!strncmp("SUNW,sabre", prop_val, prop_len) || + !strncmp("pci108e,a000", prop_val, prop_len) || + !strncmp("pci108e,a001", prop_val, prop_len)) { + /* + * There can only be one "Sabre" bridge in a system. It provides + * PCI configuration space, a 24-bit I/O space and a 32-bit memory + * space, all three of which are at fixed physical CPU addresses. + */ + static Bool sabre_seen = FALSE; + + xf86Msg(X_INFO, + "Sabre or Hummingbird PCI host bridge found (\"%s\")\n", + prop_val); + + /* There can only be one Sabre */ + if (sabre_seen) + continue; + sabre_seen = TRUE; + + /* Get "bus-range" property */ + prop_val = promGetProperty("bus-range", &prop_len); + if (!prop_val || (prop_len != 8) || + (((unsigned int *)prop_val)[0]) || + (((unsigned int *)prop_val)[1] >= 256)) + continue; + + pci_addr = 0x01fe01000000ull; + domain.io_addr = 0x01fe02000000ull; + domain.io_size = 0x000001000000ull; + domain.mem_addr = 0x01ff00000000ull; + domain.mem_size = 0x000100000000ull; + domain.bus_min = 0; /* Always */ + domain.bus_max = ((int *)prop_val)[1]; + + pFunctions = &sabrePCIFunctions; + } else + if (!strncmp("SUNW,psycho", prop_val, prop_len) || + !strncmp("pci108e,8000", prop_val, prop_len)) { + /* + * A "Psycho" host bridge provides two PCI interfaces, each with + * its own 16-bit I/O and 31-bit memory spaces. Both share the + * same PCI configuration space. Here, they are assigned separate + * domain numbers to prevent unintentional I/O and/or memory + * resource conflicts. + */ + xf86Msg(X_INFO, + "Psycho PCI host bridge found (\"%s\")\n", prop_val); + + /* Get "bus-range" property */ + prop_val = promGetProperty("bus-range", &prop_len); + if (!prop_val || (prop_len != 8) || + (((unsigned int *)prop_val)[1] >= 256) || + (((unsigned int *)prop_val)[0] > ((unsigned int *)prop_val)[1])) + continue; + + domain.bus_min = ((int *)prop_val)[0]; + domain.bus_max = ((int *)prop_val)[1]; + + /* Get "ranges" property */ + prop_val = promGetProperty("ranges", &prop_len); + if (!prop_val || (prop_len != 112) || + prop_val[0] || (prop_val[28] != 0x01u) || + (prop_val[56] != 0x02u) || (prop_val[84] != 0x03u) || + (((unsigned int *)prop_val)[4] != 0x01000000u) || + ((unsigned int *)prop_val)[5] || + ((unsigned int *)prop_val)[12] || + (((unsigned int *)prop_val)[13] != 0x00010000u) || + ((unsigned int *)prop_val)[19] || + (((unsigned int *)prop_val)[20] != 0x80000000u) || + ((((unsigned int *)prop_val)[11] & ~0x00010000u) != + 0x02000000u) || + (((unsigned int *)prop_val)[18] & ~0x80000000u) || + (((unsigned int *)prop_val)[3] != + ((unsigned int *)prop_val)[10]) || + (((unsigned int *)prop_val)[17] != + ((unsigned int *)prop_val)[24]) || + (((unsigned int *)prop_val)[18] != + ((unsigned int *)prop_val)[25]) || + (((unsigned int *)prop_val)[19] != + ((unsigned int *)prop_val)[26]) || + (((unsigned int *)prop_val)[20] != + ((unsigned int *)prop_val)[27])) + continue; + + /* Use memcpy() to avoid alignment issues */ + (void)memcpy(&pci_addr, prop_val + 12, + sizeof(pci_addr)); + (void)memcpy(&domain.io_addr, prop_val + 40, + sizeof(domain.io_addr)); + (void)memcpy(&domain.mem_addr, prop_val + 68, + sizeof(domain.mem_addr)); + + domain.io_size = 0x000000010000ull; + domain.mem_size = 0x000080000000ull; + } else + if (!strncmp("SUNW,schizo", prop_val, prop_len) || + !strncmp("pci108e,8001", prop_val, prop_len)) { + /* + * I have no docs on the "Schizo", but judging from the Linux + * kernel, it also provides two PCI domains. Each PCI + * configuration space is the usual 16M in size, followed by a + * variable-length I/O space. Each domain also provides a + * variable-length memory space. The kernel seems to think the I/O + * spaces are 16M long, and the memory spaces, 2G, but these + * assumptions are actually only present in source code comments. + * Sun has, however, confirmed to me the validity of these + * assumptions. + */ + volatile unsigned long long mem_match, mem_mask, io_match, io_mask; + unsigned long Offset; + pointer pSchizo; + + xf86Msg(X_INFO, + "Schizo PCI host bridge found (\"%s\")\n", prop_val); + + /* Get "bus-range" property */ + prop_val = promGetProperty("bus-range", &prop_len); + if (!prop_val || (prop_len != 8) || + (((unsigned int *)prop_val)[1] >= 256) || + (((unsigned int *)prop_val)[0] > ((unsigned int *)prop_val)[1])) + continue; + + domain.bus_min = ((int *)prop_val)[0]; + domain.bus_max = ((int *)prop_val)[1]; + + /* Get "reg" property */ + prop_val = promGetProperty("reg", &prop_len); + if (!prop_val || (prop_len != 48)) + continue; + + /* Temporarily map some of Schizo's registers */ + pSchizo = sparcMapAperture(-1, VIDMEM_MMIO, + ((unsigned long long *)prop_val)[2] - 0x000000010000ull, + 0x00010000ul); + + /* Determine where PCI config, I/O and memory spaces reside */ + if ((((unsigned long long *)prop_val)[0] & 0x000000700000ull) == + 0x000000600000ull) + Offset = 0x0040; + else + Offset = 0x0060; + + mem_match = PciReg(pSchizo, 0, Offset, unsigned long long); + mem_mask = PciReg(pSchizo, 0, Offset + 8, unsigned long long); + io_match = PciReg(pSchizo, 0, Offset + 16, unsigned long long); + io_mask = PciReg(pSchizo, 0, Offset + 24, unsigned long long); + + /* Unmap Schizo registers */ + xf86UnMapVidMem(-1, pSchizo, 0x00010000ul); + + /* Calculate sizes */ + mem_mask = (((mem_mask - 1) ^ mem_mask) >> 1) + 1; + io_mask = (((io_mask - 1) ^ io_mask ) >> 1) + 1; + + if (io_mask <= 0x000001000000ull) /* Nothing left for I/O */ + continue; + + domain.mem_addr = mem_match & ~0x8000000000000000ull; + domain.mem_size = mem_mask; + pci_addr = io_match & ~0x8000000000000000ull; + domain.io_addr = pci_addr + 0x0000000001000000ull; + domain.io_size = io_mask - 0x0000000001000000ull; + } else { + xf86Msg(X_WARNING, "Unknown PCI host bridge: \"%s\"\n", prop_val); + continue; + } + + /* Only map as much PCI configuration as we need */ + domain.pci = (char *)sparcMapAperture(-1, VIDMEM_MMIO, + pci_addr + PCI_MAKE_TAG(domain.bus_min, 0, 0), + PCI_MAKE_TAG(domain.bus_max - domain.bus_min + 1, 0, 0)) - + PCI_MAKE_TAG(domain.bus_min, 0, 0); + + /* Allocate a domain record */ + pDomain = xnfalloc(sizeof(sparcDomainRec)); + *pDomain = domain; + + /* + * Allocate and prime pciBusInfo records. These are allocated one at a + * time because those for empty buses are eventually released. + */ + bus = pDomain->bus_min = + PCI_MAKE_BUS(pciNumDomains, domain.bus_min); + pciNumBuses = pDomain->bus_max = + PCI_MAKE_BUS(pciNumDomains, domain.bus_max) + 1; + + pciBusInfo[bus] = xnfcalloc(1, sizeof(pciBusInfo_t)); + pciBusInfo[bus]->configMech = PCI_CFG_MECH_OTHER; + pciBusInfo[bus]->numDevices = 32; + pciBusInfo[bus]->funcs = pFunctions; + pciBusInfo[bus]->pciBusPriv = pDomain; + while (++bus < pciNumBuses) { + pciBusInfo[bus] = xnfalloc(sizeof(pciBusInfo_t)); + *(pciBusInfo[bus]) = *(pciBusInfo[bus - 1]); + pciBusInfo[bus]->funcs = &sparcPCIFunctions; + } + + /* Next domain, please... */ + xf86DomainInfo[pciNumDomains++] = pDomain; + + /* + * OK, enough of the straight-forward stuff. Time to deal with some + * brokenness... + * + * The PCI specs require that when a bus transaction remains unclaimed + * for too long, the master entity on that bus is to cancel the + * transaction it issued or passed on with a master abort. Two + * outcomes are possible: + * + * - the master abort can be treated as an error that is propogated + * back through the bus tree to the entity that ultimately originated + * the transaction; or + * - the transaction can be allowed to complete normally, which means + * that writes are ignored and reads return all ones. + * + * In the first case, if the CPU happens to be at the tail end of the + * tree path through one of its host bridges, it will be told there is + * a hardware mal-function, despite being generated by software. + * + * For a software function (be it firmware, OS or userland application) + * to determine how a PCI bus tree is populated, it must be able to + * detect when master aborts occur. Obviously, PCI discovery is much + * simpler when master aborts are allowed to complete normally. + * + * Unfortunately, a number of non-Intel PCI implementations have chosen + * to treat master aborts as severe errors. The net effect is to + * cripple PCI discovery algorithms in userland. + * + * On SPARCs, master aborts cause a number of different behaviours, + * including delivering a signal to the userland application, rebooting + * the system, "dropping down" to firmware, or, worst of all, bus + * lockouts. Even in the first case, the SIGBUS signal that is + * eventually generated isn't delivered in a timely enough fashion to + * allow an application to reliably detect the master abort that + * ultimately caused it. + * + * This can be somewhat mitigated. On all architectures, master aborts + * that occur on secondary buses can be forced to complete normally + * because the PCI-to-PCI bridges that serve them are governed by an + * industry-wide specification. (This is just another way of saying + * that whatever justification there might be for erroring out master + * aborts is deemed by the industry as insufficient to generate more + * PCI non-compliance than there already is...) + * + * This leaves us with master aborts that occur on primary buses. + * There is no specification for host-to-PCI bridges. Bridges used in + * SPARCs can be told to ignore all PCI errors, but not specifically + * master aborts. Not only is this too coarse-grained, but + * master-aborted read transactions on the primary bus end up returning + * garbage rather than all ones. + * + * I have elected to work around this the only way I can think of doing + * so right now. The following scans an additional PROM level and + * builds a device/function map for the primary bus. I can only hope + * this PROM information represents all devices on the primary bus, + * rather than only a subset of them. + * + * Master aborts are useful in other ways too, that are not addressed + * here. These include determining whether or not a domain provides + * VGA, or if a PCI device actually implements PCI disablement. + * + * --- TSI @ UQV 2001.09.19 + */ + for (node2 = promGetChild(node); + node2; + node2 = promGetSibling(node2)) { + /* Get "reg" property */ + prop_val = promGetProperty("reg", &prop_len); + if (!prop_val || (prop_len % 20)) + continue; + + /* + * It's unnecessary to scan the entire "reg" property, but I'll do + * so anyway. + */ + prop_len /= 20; + for (; prop_len--; prop_val += 20) + SetBitInMap(PCI_DFN_FROM_TAG(*(PCITAG *)prop_val), + pDomain->dfn_mask); + } + + /* Assume the host bridge is device 0, function 0 on its bus */ + SetBitInMap(0, pDomain->dfn_mask); + } + + sparcPromClose(); + + close(apertureFd); + apertureFd = -1; +} + +#ifndef INCLUDE_XF86_NO_DOMAIN + +int +xf86GetPciDomain(PCITAG Tag) +{ + return PCI_DOM_FROM_TAG(Tag); +} + +pointer +xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size) +{ + sparcDomainPtr pDomain; + pointer result; + int domain = PCI_DOM_FROM_TAG(Tag); + + if ((domain <= 0) || (domain >= pciNumDomains) || + !(pDomain = xf86DomainInfo[domain]) || + (((unsigned long long)Base + (unsigned long long)Size) > + pDomain->mem_size)) + FatalError("xf86MapDomainMemory() called with invalid parameters.\n"); + + result = sparcMapAperture(ScreenNum, Flags, pDomain->mem_addr + Base, Size); + + if (apertureFd >= 0) { + close(apertureFd); + apertureFd = -1; + } + + return result; +} + +IOADDRESS +xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, + IOADDRESS Base, unsigned long Size) +{ + sparcDomainPtr pDomain; + int domain = PCI_DOM_FROM_TAG(Tag); + + if ((domain <= 0) || (domain >= pciNumDomains) || + !(pDomain = xf86DomainInfo[domain]) || + (((unsigned long long)Base + (unsigned long long)Size) > + pDomain->io_size)) + FatalError("xf86MapDomainIO() called with invalid parameters.\n"); + + /* Permanently map all of I/O space */ + if (!pDomain->io) { + pDomain->io = sparcMapAperture(ScreenNum, Flags, + pDomain->io_addr, pDomain->io_size); + + if (apertureFd >= 0) { + close(apertureFd); + apertureFd = -1; + } + } + + return (IOADDRESS)pDomain->io + Base; +} + +int +xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) +{ + unsigned char *ptr, *src; + ADDRESS offset; + unsigned long size; + int len; + + /* Ensure page boundaries */ + offset = Base & ~pagemask; + size = ((Base + Len + pagemask) & ~pagemask) - offset; + + ptr = xf86MapDomainMemory(-1, VIDMEM_READONLY, Tag, offset, size); + + /* Using memcpy() here hangs the system */ + src = ptr + (Base - offset); + for (len = Len; len-- > 0;) + *Buf++ = *src++; + + xf86UnMapVidMem(-1, ptr, size); + + return Len; +} + +resPtr +xf86BusAccWindowsFromOS(void) +{ + sparcDomainPtr pDomain; + resPtr pRes = NULL; + resRange range; + int domain; + + for (domain = 1; domain < pciNumDomains; domain++) { + if (!(pDomain = xf86DomainInfo[domain])) + continue; + + RANGE(range, 0, pDomain->mem_size - 1, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0, pDomain->io_size - 1, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + } + + return pRes; +} + +resPtr +xf86PciBusAccWindowsFromOS(void) +{ + sparcDomainPtr pDomain; + resPtr pRes = NULL; + resRange range; + int domain; + + for (domain = 1; domain < pciNumDomains; domain++) { + if (!(pDomain = xf86DomainInfo[domain])) + continue; + + RANGE(range, 0, pDomain->mem_size - 1, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0, pDomain->io_size - 1, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + } + + return pRes; +} + +resPtr +xf86AccResFromOS(resPtr pRes) +{ + sparcDomainPtr pDomain; + resRange range; + int domain; + + for (domain = 1; domain < pciNumDomains; domain++) { + if (!(pDomain = xf86DomainInfo[domain])) + continue; + + /* + * At minimum, the top and bottom resources must be claimed, so that + * resources that are (or appear to be) unallocated can be relocated. + */ + RANGE(range, 0x00000000u, 0x0009ffffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, 0x000c0000u, 0x000effffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, 0x000f0000u, 0x000fffffu, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, pDomain->mem_size - 1, pDomain->mem_size - 1, + RANGE_TYPE(ResExcMemBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + + RANGE(range, 0x00000000u, 0x00000000u, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + RANGE(range, pDomain->io_size - 1, pDomain->io_size - 1, + RANGE_TYPE(ResExcIoBlock, domain)); + pRes = xf86AddResToList(pRes, &range, -1); + } + + return pRes; +} + +#endif /* !INCLUDE_XF86_NO_DOMAIN */ + +#endif /* defined(sun) */ + +#if defined(ARCH_PCI_PCI_BRIDGE) + +/* Definitions specific to Sun's APB P2P bridge (a.k.a. Simba) */ +#define APB_IO_ADDRESS_MAP 0xDE +#define APB_MEM_ADDRESS_MAP 0xDF + +/* + * Simba's can only occur on bus 0. Furthermore, Simba's must have a non-zero + * device/function number because the Sabre interface they must connect to + * occupies the 0:0:0 slot. Also, there can be only one Sabre interface in the + * system, and therefore, only one Simba function can route any particular + * resource. Thus, it is appropriate to use a single set of static variables + * to hold the tag of the Simba function routing a VGA resource range at any + * one time, and to test these variables for non-zero to determine whether or + * not the Sabre would master-abort a VGA access (and kill the system). + * + * The trick is to determine when it is safe to re-route VGA, because doing so + * re-routes much more. + */ +static PCITAG simbavgaIOTag = 0, simbavgaMemTag = 0; +static Bool simbavgaRoutingAllow = TRUE; + +/* + * Scan the bus subtree rooted at 'bus' for a non-display device that might be + * decoding the bottom 2 MB of I/O space and/or the bottom 512 MB of memory + * space. Reset simbavgaRoutingAllow if such a device is found. + * + * XXX For now, this is very conservative and should be made less so as the + * need arises. + */ +static void +simbaCheckBus(CARD16 pcicommand, int bus) +{ + pciConfigPtr pPCI, *ppPCI = xf86scanpci(0); + + while ((pPCI = *ppPCI++)) { + if (pPCI->busnum < bus) + continue; + if (pPCI->busnum > bus) + break; + + /* XXX Assume all devices respect PCI disablement */ + if (!(pcicommand & pPCI->pci_command)) + continue; + + /* XXX This doesn't deal with mis-advertised classes */ + switch (pPCI->pci_base_class) { + case PCI_CLASS_PREHISTORIC: + if (pPCI->pci_sub_class == PCI_SUBCLASS_PREHISTORIC_VGA) + continue; /* Ignore VGA */ + break; + + case PCI_CLASS_DISPLAY: + continue; + + case PCI_CLASS_BRIDGE: + switch (pPCI->pci_sub_class) { + case PCI_SUBCLASS_BRIDGE_PCI: + case PCI_SUBCLASS_BRIDGE_CARDBUS: + /* Scan secondary bus */ + /* XXX First check bridge routing? */ + simbaCheckBus(pcicommand & pPCI->pci_command, + PCI_SECONDARY_BUS_EXTRACT(pPCI->pci_pp_bus_register, + pPCI->tag)); + if (!simbavgaRoutingAllow) + return; + + default: + break; + } + + default: + break; + } + + /* + * XXX We could check the device's bases here, but PCI doesn't limit + * the device's decoding to them. + */ + + simbavgaRoutingAllow = FALSE; + break; + } +} + +static pciConfigPtr +simbaVerifyBus(int bus) +{ + pciConfigPtr pPCI; + if ((bus < 0) || (bus >= pciNumBuses) || + !pciBusInfo[bus] || !(pPCI = pciBusInfo[bus]->bridge) || + (pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA))) + return NULL; + + return pPCI; +} + +static CARD16 +simbaControlBridge(int bus, CARD16 mask, CARD16 value) +{ + pciConfigPtr pPCI; + CARD16 current = 0, tmp; + CARD8 iomap, memmap; + + if ((pPCI = simbaVerifyBus(bus))) { + /* + * The Simba does not implement VGA enablement as described in the P2P + * spec. It does however route I/O and memory in large enough chunks + * so that we can determine were VGA resources would be routed + * (including ISA VGA I/O aliases). We can allow changes to that + * routing only under certain circumstances. + */ + iomap = pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP); + memmap = pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP); + if (iomap & memmap & 0x01) { + current |= PCI_PCI_BRIDGE_VGA_EN; + if ((mask & PCI_PCI_BRIDGE_VGA_EN) && + !(value & PCI_PCI_BRIDGE_VGA_EN)) { + if (!simbavgaRoutingAllow) { + xf86MsgVerb(X_WARNING, 3, "Attempt to disable VGA routing" + " through Simba at %x:%x:%x disallowed.\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum); + value |= PCI_PCI_BRIDGE_VGA_EN; + } else { + pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP, + iomap & ~0x01); + pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP, + memmap & ~0x01); + simbavgaIOTag = simbavgaMemTag = 0; + } + } + } else { + if (mask & value & PCI_PCI_BRIDGE_VGA_EN) { + if (!simbavgaRoutingAllow) { + xf86MsgVerb(X_WARNING, 3, "Attempt to enable VGA routing" + " through Simba at %x:%x:%x disallowed.\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum); + value &= ~PCI_PCI_BRIDGE_VGA_EN; + } else { + if (pPCI->tag != simbavgaIOTag) { + if (simbavgaIOTag) { + tmp = pciReadByte(simbavgaIOTag, + APB_IO_ADDRESS_MAP); + pciWriteByte(simbavgaIOTag, APB_IO_ADDRESS_MAP, + tmp & ~0x01); + } + + pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP, + iomap | 0x01); + simbavgaIOTag = pPCI->tag; + } + + if (pPCI->tag != simbavgaMemTag) { + if (simbavgaMemTag) { + tmp = pciReadByte(simbavgaMemTag, + APB_MEM_ADDRESS_MAP); + pciWriteByte(simbavgaMemTag, APB_MEM_ADDRESS_MAP, + tmp & ~0x01); + } + + pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP, + memmap | 0x01); + simbavgaMemTag = pPCI->tag; + } + } + } + } + + /* Move on to master abort failure enablement (as per P2P spec) */ + tmp = pciReadWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG); + current |= tmp; + if (tmp & PCI_PCI_BRIDGE_MASTER_ABORT_EN) { + if ((mask & PCI_PCI_BRIDGE_MASTER_ABORT_EN) && + !(value & PCI_PCI_BRIDGE_MASTER_ABORT_EN)) + pciWriteWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG, + tmp & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN); + } else { + if (mask & value & PCI_PCI_BRIDGE_MASTER_ABORT_EN) + pciWriteWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG, + tmp | PCI_PCI_BRIDGE_MASTER_ABORT_EN); + } + + /* Insert emulation of other P2P controls here */ + } + + return (current & ~mask) | (value & mask); +} + +static void +simbaGetBridgeResources(int bus, + pointer *ppIoRes, + pointer *ppMemRes, + pointer *ppPmemRes) +{ + pciConfigPtr pPCI = simbaVerifyBus(bus); + resRange range; + int i; + + if (!pPCI) + return; + + if (ppIoRes) { + xf86FreeResList(*ppIoRes); + *ppIoRes = NULL; + + if (pPCI->pci_command & PCI_CMD_IO_ENABLE) { + unsigned char iomap = pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP); + if (simbavgaRoutingAllow) + iomap |= 0x01; + for (i = 0; i < 8; i++) { + if (iomap & (1 << i)) { + RANGE(range, i << 21, ((i + 1) << 21) - 1, + RANGE_TYPE(ResExcIoBlock, + xf86GetPciDomain(pPCI->tag))); + *ppIoRes = xf86AddResToList(*ppIoRes, &range, -1); + } + } + } + } + + if (ppMemRes) { + xf86FreeResList(*ppMemRes); + *ppMemRes = NULL; + + if (pPCI->pci_command & PCI_CMD_MEM_ENABLE) { + unsigned char memmap = pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP); + if (simbavgaRoutingAllow) + memmap |= 0x01; + for (i = 0; i < 8; i++) { + if (memmap & (1 << i)) { + RANGE(range, i << 29, ((i + 1) << 29) - 1, + RANGE_TYPE(ResExcMemBlock, + xf86GetPciDomain(pPCI->tag))); + *ppMemRes = xf86AddResToList(*ppMemRes, &range, -1); + } + } + } + } + + if (ppPmemRes) { + xf86FreeResList(*ppPmemRes); + *ppPmemRes = NULL; + } +} + +void ARCH_PCI_PCI_BRIDGE(pciConfigPtr pPCI) +{ + static pciBusFuncs_t simbaBusFuncs; + pciBusInfo_t *pBusInfo; + CARD16 pcicommand; + + if (pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA)) + return; + + pBusInfo = pPCI->businfo; + + simbaBusFuncs = *(pBusInfo->funcs); + simbaBusFuncs.pciControlBridge = simbaControlBridge; + simbaBusFuncs.pciGetBridgeResources = simbaGetBridgeResources; + + pBusInfo->funcs = &simbaBusFuncs; + + if (!simbavgaRoutingAllow) + return; + + pcicommand = 0; + + if (pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP) & 0x01) { + pcicommand |= PCI_CMD_IO_ENABLE; + simbavgaIOTag = pPCI->tag; + } + + if (pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP) & 0x01) { + pcicommand |= PCI_CMD_MEM_ENABLE; + simbavgaMemTag = pPCI->tag; + } + + if (!pcicommand) + return; + + simbaCheckBus(pcicommand, + PCI_SECONDARY_BUS_EXTRACT(pPCI->pci_pp_bus_register, pPCI->tag)); +} + +#endif /* defined(ARCH_PCI_PCI_BRIDGE) */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h new file mode 100644 index 000000000..a8b7ef492 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h @@ -0,0 +1,807 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h,v 1.39 2003/08/24 17:37:05 dawes Exp $ */ +/* + * 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. + * + * This file is derived in part from the original xf86_PCI.h that included + * following copyright message: + * + * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org> + * + * 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 names of the above listed copyright holder(s) + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holder(s) make(s) no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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 (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file contains just the public interface to the PCI code. + * Drivers should use this file rather than Pci.h. + */ + +#ifndef _XF86PCI_H +#define _XF86PCI_H 1 +#include <X11/Xarch.h> +#include <X11/Xfuncproto.h> +#include "misc.h" + +#define PCI_NOT_FOUND 0xFFFFFFFFU + +/* + * PCI cfg space definitions (e.g. stuff right out of the PCI spec) + */ + +/* Device identification register */ +#define PCI_ID_REG 0x00 + +/* Command and status register */ +#define PCI_CMD_STAT_REG 0x04 +#define PCI_CMD_BASE_REG 0x10 +#define PCI_CMD_BIOS_REG 0x30 +#define PCI_CMD_MASK 0xffff +#define PCI_CMD_IO_ENABLE 0x01 +#define PCI_CMD_MEM_ENABLE 0x02 +#define PCI_CMD_MASTER_ENABLE 0x04 +#define PCI_CMD_SPECIAL_ENABLE 0x08 +#define PCI_CMD_INVALIDATE_ENABLE 0x10 +#define PCI_CMD_PALETTE_ENABLE 0x20 +#define PCI_CMD_PARITY_ENABLE 0x40 +#define PCI_CMD_STEPPING_ENABLE 0x80 +#define PCI_CMD_SERR_ENABLE 0x100 +#define PCI_CMD_BACKTOBACK_ENABLE 0x200 +#define PCI_CMD_BIOS_ENABLE 0x01 + +/* base class */ +#define PCI_CLASS_REG 0x08 +#define PCI_CLASS_MASK 0xff000000 +#define PCI_CLASS_SHIFT 24 +#define PCI_CLASS_EXTRACT(x) \ + (((x) & PCI_CLASS_MASK) >> PCI_CLASS_SHIFT) + +/* base class values */ +#define PCI_CLASS_PREHISTORIC 0x00 +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_MULTIMEDIA 0x04 +#define PCI_CLASS_MEMORY 0x05 +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_COMMUNICATIONS 0x07 +#define PCI_CLASS_SYSPERIPH 0x08 +#define PCI_CLASS_INPUT 0x09 +#define PCI_CLASS_DOCKING 0x0a +#define PCI_CLASS_PROCESSOR 0x0b +#define PCI_CLASS_SERIALBUS 0x0c +#define PCI_CLASS_WIRELESS 0x0d +#define PCI_CLASS_I2O 0x0e +#define PCI_CLASS_SATELLITE 0x0f +#define PCI_CLASS_CRYPT 0x10 +#define PCI_CLASS_DATA_ACQUISTION 0x11 +#define PCI_CLASS_UNDEFINED 0xff + +/* sub class */ +#define PCI_SUBCLASS_MASK 0x00ff0000 +#define PCI_SUBCLASS_SHIFT 16 +#define PCI_SUBCLASS_EXTRACT(x) \ + (((x) & PCI_SUBCLASS_MASK) >> PCI_SUBCLASS_SHIFT) + +/* Sub class values */ +/* 0x00 prehistoric subclasses */ +#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00 +#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01 + +/* 0x01 mass storage subclasses */ +#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x01 +#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x03 +#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x80 + +/* 0x02 network subclasses */ +#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00 +#define PCI_SUBCLASS_NETWORK_TOKENRING 0x01 +#define PCI_SUBCLASS_NETWORK_FDDI 0x02 +#define PCI_SUBCLASS_NETWORK_MISC 0x80 + +/* 0x03 display subclasses */ +#define PCI_SUBCLASS_DISPLAY_VGA 0x00 +#define PCI_SUBCLASS_DISPLAY_XGA 0x01 +#define PCI_SUBCLASS_DISPLAY_MISC 0x80 + +/* 0x04 multimedia subclasses */ +#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00 +#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01 +#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x80 + +/* 0x05 memory subclasses */ +#define PCI_SUBCLASS_MEMORY_RAM 0x00 +#define PCI_SUBCLASS_MEMORY_FLASH 0x01 +#define PCI_SUBCLASS_MEMORY_MISC 0x80 + +/* 0x06 bridge subclasses */ +#define PCI_SUBCLASS_BRIDGE_HOST 0x00 +#define PCI_SUBCLASS_BRIDGE_ISA 0x01 +#define PCI_SUBCLASS_BRIDGE_EISA 0x02 +#define PCI_SUBCLASS_BRIDGE_MC 0x03 +#define PCI_SUBCLASS_BRIDGE_PCI 0x04 +#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05 +#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06 +#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07 +#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08 +#define PCI_SUBCLASS_BRIDGE_MISC 0x80 +#define PCI_IF_BRIDGE_PCI_SUBTRACTIVE 0x01 + +/* 0x07 communications controller subclasses */ +#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00 +#define PCI_SUBCLASS_COMMUNICATIONS_PARALLEL 0x01 +#define PCI_SUBCLASS_COMMUNICATIONS_MULTISERIAL 0x02 +#define PCI_SUBCLASS_COMMUNICATIONS_MODEM 0x03 +#define PCI_SUBCLASS_COMMUNICATIONS_MISC 0x80 + +/* 0x08 generic system peripherals subclasses */ +#define PCI_SUBCLASS_SYSPERIPH_PIC 0x00 +#define PCI_SUBCLASS_SYSPERIPH_DMA 0x01 +#define PCI_SUBCLASS_SYSPERIPH_TIMER 0x02 +#define PCI_SUBCLASS_SYSPERIPH_RTC 0x03 +#define PCI_SUBCLASS_SYSPERIPH_HOTPCI 0x04 +#define PCI_SUBCLASS_SYSPERIPH_MISC 0x80 + +/* 0x09 input device subclasses */ +#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00 +#define PCI_SUBCLASS_INPUT_DIGITIZER 0x01 +#define PCI_SUBCLASS_INPUT_MOUSE 0x02 +#define PCI_SUBCLASS_INPUT_SCANNER 0x03 +#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04 +#define PCI_SUBCLASS_INPUT_MISC 0x80 + +/* 0x0a docking station subclasses */ +#define PCI_SUBCLASS_DOCKING_GENERIC 0x00 +#define PCI_SUBCLASS_DOCKING_MISC 0x80 + +/* 0x0b processor subclasses */ +#define PCI_SUBCLASS_PROCESSOR_386 0x00 +#define PCI_SUBCLASS_PROCESSOR_486 0x01 +#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02 +#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10 +#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20 +#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30 +#define PCI_SUBCLASS_PROCESSOR_COPROC 0x40 + +/* 0x0c serial bus controller subclasses */ +#define PCI_SUBCLASS_SERIAL_FIREWIRE 0x00 +#define PCI_SUBCLASS_SERIAL_ACCESS 0x01 +#define PCI_SUBCLASS_SERIAL_SSA 0x02 +#define PCI_SUBCLASS_SERIAL_USB 0x03 +#define PCI_SUBCLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_SUBCLASS_SERIAL_SMBUS 0x05 + +/* 0x0d wireless controller subclasses */ +#define PCI_SUBCLASS_WIRELESS_IRDA 0x00 +#define PCI_SUBCLASS_WIRELESS_CONSUMER_IR 0x01 +#define PCI_SUBCLASS_WIRELESS_RF 0x02 +#define PCI_SUBCLASS_WIRELESS_MISC 0x80 + +/* 0x0e intelligent I/O controller subclasses */ +#define PCI_SUBCLASS_I2O_I2O 0x00 + +/* 0x0f satellite communications controller subclasses */ +#define PCI_SUBCLASS_SATELLITE_TV 0x01 +#define PCI_SUBCLASS_SATELLITE_AUDIO 0x02 +#define PCI_SUBCLASS_SATELLITE_VOICE 0x03 +#define PCI_SUBCLASS_SATELLITE_DATA 0x04 + +/* 0x10 encryption/decryption controller subclasses */ +#define PCI_SUBCLASS_CRYPT_NET_COMPUTING 0x00 +#define PCI_SUBCLASS_CRYPT_ENTERTAINMENT 0x10 +#define PCI_SUBCLASS_CRYPT_MISC 0x80 + +/* 0x11 data acquisition and signal processing controller subclasses */ +#define PCI_SUBCLASS_DATAACQ_DPIO 0x00 +#define PCI_SUBCLASS_DATAACQ_MISC 0x80 + + +/* Header */ +#define PCI_HEADER_MISC 0x0c +#define PCI_HEADER_MULTIFUNCTION 0x00800000 + +/* Interrupt configration register */ +#define PCI_INTERRUPT_REG 0x3c +#define PCI_INTERRUPT_PIN_MASK 0x0000ff00 +#define PCI_INTERRUPT_PIN_EXTRACT(x) \ + ((((x) & PCI_INTERRUPT_PIN_MASK) >> 8) & 0xff) +#define PCI_INTERRUPT_PIN_NONE 0x00 +#define PCI_INTERRUPT_PIN_A 0x01 +#define PCI_INTERRUPT_PIN_B 0x02 +#define PCI_INTERRUPT_PIN_C 0x03 +#define PCI_INTERRUPT_PIN_D 0x04 + +#define PCI_INTERRUPT_LINE_MASK 0x000000ff +#define PCI_INTERRUPT_LINE_EXTRACT(x) \ + ((((x) & PCI_INTERRUPT_LINE_MASK) >> 0) & 0xff) +#define PCI_INTERRUPT_LINE_INSERT(x,v) \ + (((x) & ~PCI_INTERRUPT_LINE_MASK) | ((v) << 0)) + +/* Base registers */ +#define PCI_MAP_REG_START 0x10 +#define PCI_MAP_REG_END 0x28 +#define PCI_MAP_ROM_REG 0x30 + +#define PCI_MAP_MEMORY 0x00000000 +#define PCI_MAP_IO 0x00000001 + +#define PCI_MAP_MEMORY_TYPE 0x00000007 +#define PCI_MAP_IO_TYPE 0x00000003 + +#define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000 +#define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002 +#define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004 +#define PCI_MAP_MEMORY_TYPE_MASK 0x00000006 +#define PCI_MAP_MEMORY_CACHABLE 0x00000008 +#define PCI_MAP_MEMORY_ATTR_MASK 0x0000000e +#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0 + +#define PCI_MAP_IO_ATTR_MASK 0x00000003 + +#define PCI_MAP_IS_IO(b) ((b) & PCI_MAP_IO) +#define PCI_MAP_IS_MEM(b) (!PCI_MAP_IS_IO(b)) + +#define PCI_MAP_IS64BITMEM(b) \ + (((b) & PCI_MAP_MEMORY_TYPE) == PCI_MAP_MEMORY_TYPE_64BIT) + +#define PCIGETMEMORY(b) ((b) & PCI_MAP_MEMORY_ADDRESS_MASK) +#define PCIGETMEMORY64HIGH(b) (*((CARD32*)&(b) + 1)) +#define PCIGETMEMORY64(b) \ + (PCIGETMEMORY(b) | ((CARD64)PCIGETMEMORY64HIGH(b) << 32)) + +#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc + +#define PCIGETIO(b) ((b) & PCI_MAP_IO_ADDRESS_MASK) + +#define PCI_MAP_ROM_DECODE_ENABLE 0x00000001 +#define PCI_MAP_ROM_ADDRESS_MASK 0xfffff800 + +#define PCIGETROM(b) ((b) & PCI_MAP_ROM_ADDRESS_MASK) + +/* PCI-PCI bridge mapping registers */ +#define PCI_PCI_BRIDGE_BUS_REG 0x18 +#define PCI_SUBORDINATE_BUS_MASK 0x00ff0000 +#define PCI_SECONDARY_BUS_MASK 0x0000ff00 +#define PCI_PRIMARY_BUS_MASK 0x000000ff + +#define PCI_PCI_BRIDGE_IO_REG 0x1c +#define PCI_PCI_BRIDGE_MEM_REG 0x20 +#define PCI_PCI_BRIDGE_PMEM_REG 0x24 + +#define PCI_PPB_IOBASE_EXTRACT(x) (((x) << 8) & 0xFF00) +#define PCI_PPB_IOLIMIT_EXTRACT(x) (((x) << 0) & 0xFF00) + +#define PCI_PPB_MEMBASE_EXTRACT(x) (((x) << 16) & 0xFFFF0000) +#define PCI_PPB_MEMLIMIT_EXTRACT(x) (((x) << 0) & 0xFFFF0000) + +#define PCI_PCI_BRIDGE_CONTROL_REG 0x3E +#define PCI_PCI_BRIDGE_PARITY_EN 0x01 +#define PCI_PCI_BRIDGE_SERR_EN 0x02 +#define PCI_PCI_BRIDGE_ISA_EN 0x04 +#define PCI_PCI_BRIDGE_VGA_EN 0x08 +#define PCI_PCI_BRIDGE_MASTER_ABORT_EN 0x20 +#define PCI_PCI_BRIDGE_SECONDARY_RESET 0x40 +#define PCI_PCI_BRIDGE_FAST_B2B_EN 0x80 +/* header type 2 extensions */ +#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ +#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 +#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 + +#define PCI_CB_SEC_STATUS_REG 0x16 /* Secondary status */ +#define PCI_CB_PRIMARY_BUS_REG 0x18 /* PCI bus number */ +#define PCI_CB_CARD_BUS_REG 0x19 /* CardBus bus number */ +#define PCI_CB_SUBORDINATE_BUS_REG 0x1a /* Subordinate bus number */ +#define PCI_CB_LATENCY_TIMER_REG 0x1b /* CardBus latency timer */ +#define PCI_CB_MEM_BASE_0_REG 0x1c +#define PCI_CB_MEM_LIMIT_0_REG 0x20 +#define PCI_CB_MEM_BASE_1_REG 0x24 +#define PCI_CB_MEM_LIMIT_1_REG 0x28 +#define PCI_CB_IO_BASE_0_REG 0x2c +#define PCI_CB_IO_LIMIT_0_REG 0x30 +#define PCI_CB_IO_BASE_1_REG 0x34 +#define PCI_CB_IO_LIMIT_1_REG 0x38 +#define PCI_CB_BRIDGE_CONTROL_REG 0x3E + +#define PCI_CB_IO_RANGE_MASK ~0x03 +#define PCI_CB_IOBASE(x) (x & PCI_CB_IO_RANGE_MASK) +#define PCI_CB_IOLIMIT(x) ((x & PCI_CB_IO_RANGE_MASK) + 3) + +/* Subsystem identification register */ +#define PCI_SUBSYSTEM_ID_REG 0x2c + +/* User defined cfg space regs */ +#define PCI_REG_USERCONFIG 0x40 +#define PCI_OPTION_REG 0x40 + +/* + * Typedefs, etc... + */ + +/* Primitive Types */ +typedef unsigned long ADDRESS; /* Memory/PCI address */ +typedef unsigned long IOADDRESS; /* Must be large enough for a pointer */ +typedef unsigned long PCITAG; + +/* + * PCI configuration space + */ +typedef struct pci_cfg_regs { + /* start of official PCI config space header */ + union { /* Offset 0x0 - 0x3 */ + CARD32 device_vendor; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 device; + CARD16 vendor; +#else + CARD16 vendor; + CARD16 device; +#endif + } dv; + } dv_id; + + union { /* Offset 0x4 - 0x8 */ + CARD32 status_command; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 status; + CARD16 command; +#else + CARD16 command; + CARD16 status; +#endif + } sc; + } stat_cmd; + + union { /* Offset 0x8 - 0xb */ + CARD32 class_revision; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD8 base_class; + CARD8 sub_class; + CARD8 prog_if; + CARD8 rev_id; +#else + CARD8 rev_id; + CARD8 prog_if; + CARD8 sub_class; + CARD8 base_class; +#endif + } cr; + } class_rev; + + union { /* Offset 0xc - 0xf */ + CARD32 bist_header_latency_cache; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD8 bist; + CARD8 header_type; + CARD8 latency_timer; + CARD8 cache_line_size; +#else + CARD8 cache_line_size; + CARD8 latency_timer; + CARD8 header_type; + CARD8 bist; +#endif + } bhlc; + } bhlc; + union { /* Offset 0x10 - 0x3b */ + struct { /* header type 2 */ + CARD32 cg_rsrvd1; /* 0x10 */ +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 secondary_status; /* 0x16 */ + CARD16 cg_rsrvd2; /* 0x14 */ + + union { + CARD32 cg_bus_reg; + struct { + CARD8 latency_timer; /* 0x1b */ + CARD8 subordinate_bus_number; /* 0x1a */ + CARD8 cardbus_bus_number; /* 0x19 */ + CARD8 primary_bus_number; /* 0x18 */ + } cgbr; + } cgbr; +#else + CARD16 cg_rsrvd2; /* 0x14 */ + CARD16 secondary_status; /* 0x16 */ + + union { + CARD32 cg_bus_reg; + struct { + CARD8 primary_bus_number; /* 0x18 */ + CARD8 cardbus_bus_number; /* 0x19 */ + CARD8 subordinate_bus_number; /* 0x1a */ + CARD8 latency_timer; /* 0x1b */ + } cgbr; + } cgbr; +#endif + CARD32 mem_base0; /* 0x1c */ + CARD32 mem_limit0; /* 0x20 */ + CARD32 mem_base1; /* 0x24 */ + CARD32 mem_limit1; /* 0x28 */ + CARD32 io_base0; /* 0x2c */ + CARD32 io_limit0; /* 0x30 */ + CARD32 io_base1; /* 0x34 */ + CARD32 io_limit1; /* 0x38 */ + } cg; + struct { + union { /* Offset 0x10 - 0x27 */ + struct { /* header type 0 */ + CARD32 dv_base0; + CARD32 dv_base1; + CARD32 dv_base2; + CARD32 dv_base3; + CARD32 dv_base4; + CARD32 dv_base5; + } dv; + struct { /* header type 1 */ + CARD32 bg_rsrvd[2]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + union { + CARD32 pp_bus_reg; + struct { + CARD8 secondary_latency_timer; + CARD8 subordinate_bus_number; + CARD8 secondary_bus_number; + CARD8 primary_bus_number; + } ppbr; + } ppbr; + + CARD16 secondary_status; + CARD8 io_limit; + CARD8 io_base; + + CARD16 mem_limit; + CARD16 mem_base; + + CARD16 prefetch_mem_limit; + CARD16 prefetch_mem_base; +#else + union { + CARD32 pp_bus_reg; + struct { + CARD8 primary_bus_number; + CARD8 secondary_bus_number; + CARD8 subordinate_bus_number; + CARD8 secondary_latency_timer; + } ppbr; + } ppbr; + + CARD8 io_base; + CARD8 io_limit; + CARD16 secondary_status; + + CARD16 mem_base; + CARD16 mem_limit; + + CARD16 prefetch_mem_base; + CARD16 prefetch_mem_limit; +#endif + } bg; + } bc; + union { /* Offset 0x28 - 0x2b */ + CARD32 rsvd1; + CARD32 pftch_umem_base; + CARD32 cardbus_cis_ptr; + } um_c_cis; + union { /* Offset 0x2c - 0x2f */ + CARD32 subsys_card_vendor; + CARD32 pftch_umem_limit; + CARD32 rsvd2; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 subsys_card; + CARD16 subsys_vendor; +#else + CARD16 subsys_vendor; + CARD16 subsys_card; +#endif + } ssys; + } um_ssys_id; + union { /* Offset 0x30 - 0x33 */ + CARD32 baserom; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 io_ulimit; + CARD16 io_ubase; +#else + CARD16 io_ubase; + CARD16 io_ulimit; +#endif + } b_u_io; + } uio_rom; + struct { + CARD32 rsvd3; /* Offset 0x34 - 0x37 */ + CARD32 rsvd4; /* Offset 0x38 - 0x3b */ + } rsvd; + } cd; + } cx; + union { /* Offset 0x3c - 0x3f */ + union { /* header type 0 */ + CARD32 max_min_ipin_iline; + struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD8 max_lat; + CARD8 min_gnt; + CARD8 int_pin; + CARD8 int_line; +#else + CARD8 int_line; + CARD8 int_pin; + CARD8 min_gnt; + CARD8 max_lat; +#endif + } mmii; + } mmii; + struct { /* header type 1 */ +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD16 bridge_control; /* upper 8 bits reserved */ + CARD8 rsvd2; + CARD8 rsvd1; +#else + CARD8 rsvd1; + CARD8 rsvd2; + CARD16 bridge_control; /* upper 8 bits reserved */ +#endif + } bctrl; + } bm; + union { /* Offset 0x40 - 0xff */ + CARD32 dwords[48]; + CARD8 bytes[192]; + } devspf; +} pciCfgRegs; + +typedef union pci_cfg_spc { + pciCfgRegs regs; + CARD32 dwords[256/sizeof(CARD32)]; + CARD8 bytes[256/sizeof(CARD8)]; +} pciCfgSpc; + +/* + * Data structure returned by xf86scanpci including contents of + * PCI config space header + */ +typedef struct pci_device { + PCITAG tag; + int busnum; + int devnum; + int funcnum; + pciCfgSpc cfgspc; + int basesize[7]; /* number of bits in base addr allocations */ + Bool minBasesize; + CARD32 listed_class; + pointer businfo; /* pointer to secondary's bus info structure */ + Bool fakeDevice; /* Device added by system chipset support */ +} pciDevice, *pciConfigPtr; + +typedef enum { + PCI_MEM, + PCI_MEM_SIZE, + PCI_MEM_SPARSE_BASE, + PCI_MEM_SPARSE_MASK, + PCI_IO, + PCI_IO_SIZE, + PCI_IO_SPARSE_BASE, + PCI_IO_SPARSE_MASK +} PciAddrType; + +#define pci_device_vendor cfgspc.regs.dv_id.device_vendor +#define pci_vendor cfgspc.regs.dv_id.dv.vendor +#define pci_device cfgspc.regs.dv_id.dv.device +#define pci_status_command cfgspc.regs.stat_cmd.status_command +#define pci_command cfgspc.regs.stat_cmd.sc.command +#define pci_status cfgspc.regs.stat_cmd.sc.status +#define pci_class_revision cfgspc.regs.class_rev.class_revision +#define pci_rev_id cfgspc.regs.class_rev.cr.rev_id +#define pci_prog_if cfgspc.regs.class_rev.cr.prog_if +#define pci_sub_class cfgspc.regs.class_rev.cr.sub_class +#define pci_base_class cfgspc.regs.class_rev.cr.base_class +#define pci_bist_header_latency_cache cfgspc.regs.bhlc.bist_header_latency_cache +#define pci_cache_line_size cfgspc.regs.bhlc.bhlc.cache_line_size +#define pci_latency_timer cfgspc.regs.bhlc.bhlc.latency_timer +#define pci_header_type cfgspc.regs.bhlc.bhlc.header_type +#define pci_bist cfgspc.regs.bhlc.bhlc.bist +#define pci_cb_secondary_status cfgspc.regs.cx.cg.secondary_status +#define pci_cb_bus_register cfgspc.regs.cx.cg.cgbr.cg_bus_reg +#define pci_cb_primary_bus_number cfgspc.regs.cx.cg.cgbr.cgbr.primary_bus_number +#define pci_cb_cardbus_bus_number cfgspc.regs.cx.cg.cgbr.cgbr.cardbus_bus_number +#define pci_cb_subordinate_bus_number cfgspc.regs.cx.cg.cgbr.cgbr.subordinate_bus_number +#define pci_cb_latency_timer cfgspc.regs.cx.cg.cgbr.cgbr.latency_timer +#define pci_cb_membase0 cfgspc.regs.cx.cg.mem_base0 +#define pci_cb_memlimit0 cfgspc.regs.cx.cg.mem_limit0 +#define pci_cb_membase1 cfgspc.regs.cx.cg.mem_base1 +#define pci_cb_memlimit1 cfgspc.regs.cx.cg.mem_limit1 +#define pci_cb_iobase0 cfgspc.regs.cx.cg.io_base0 +#define pci_cb_iolimit0 cfgspc.regs.cx.cg.io_limit0 +#define pci_cb_iobase1 cfgspc.regs.cx.cg.io_base1 +#define pci_cb_iolimit1 cfgspc.regs.cx.cg.io_limit1 +#define pci_base0 cfgspc.regs.cx.cd.bc.dv.dv_base0 +#define pci_base1 cfgspc.regs.cx.cd.bc.dv.dv_base1 +#define pci_base2 cfgspc.regs.cx.cd.bc.dv.dv_base2 +#define pci_base3 cfgspc.regs.cx.cd.bc.dv.dv_base3 +#define pci_base4 cfgspc.regs.cx.cd.bc.dv.dv_base4 +#define pci_base5 cfgspc.regs.cx.cd.bc.dv.dv_base5 +#define pci_cardbus_cis_ptr cfgspc.regs.cx.cd.umem_c_cis.cardbus_cis_ptr +#define pci_subsys_card_vendor cfgspc.regs.cx.cd.um_ssys_id.subsys_card_vendor +#define pci_subsys_vendor cfgspc.regs.cx.cd.um_ssys_id.ssys.subsys_vendor +#define pci_subsys_card cfgspc.regs.cx.cd.um_ssys_id.ssys.subsys_card +#define pci_baserom cfgspc.regs.cx.cd.uio_rom.baserom +#define pci_pp_bus_register cfgspc.regs.cx.cd.bc.bg.ppbr.pp_bus_reg +#define pci_primary_bus_number cfgspc.regs.cx.cd.bc.bg.ppbr.ppbr.primary_bus_number +#define pci_secondary_bus_number cfgspc.regs.cx.cd.bc.bg.ppbr.ppbr.secondary_bus_number +#define pci_subordinate_bus_number cfgspc.regs.cx.cd.bc.bg.ppbr.ppbr.subordinate_bus_number +#define pci_secondary_latency_timer cfgspc.regs.cx.cd.bc.bg.ppbr.ppbr.secondary_latency_timer +#define pci_io_base cfgspc.regs.cx.cd.bc.bg.io_base +#define pci_io_limit cfgspc.regs.cx.cd.bc.bg.io_limit +#define pci_secondary_status cfgspc.regs.cx.cd.bc.bg.secondary_status +#define pci_mem_base cfgspc.regs.cx.cd.bc.bg.mem_base +#define pci_mem_limit cfgspc.regs.cx.cd.bc.bg.mem_limit +#define pci_prefetch_mem_base cfgspc.regs.cx.cd.bc.bg.prefetch_mem_base +#define pci_prefetch_mem_limit cfgspc.regs.cx.cd.bc.bg.prefetch_mem_limit +#define pci_rsvd1 cfgspc.regs.cx.cd.um_c_cis.rsvd1 +#define pci_rsvd2 cfgspc.regs.cx.cd.um_ssys_id.rsvd2 +#define pci_prefetch_upper_mem_base cfgspc.regs.cx.cd.um_c_cis.pftch_umem_base +#define pci_prefetch_upper_mem_limit cfgspc.regs.cx.cd.um_ssys_id.pftch_umem_limit +#define pci_upper_io_base cfgspc.regs.cx.cd.uio_rom.b_u_io.io_ubase +#define pci_upper_io_limit cfgspc.regs.cx.cd.uio_rom.b_u_io.io_ulimit +#define pci_int_line cfgspc.regs.bm.mmii.mmii.int_line +#define pci_int_pin cfgspc.regs.bm.mmii.mmii.int_pin +#define pci_min_gnt cfgspc.regs.bm.mmii.mmii.min_gnt +#define pci_max_lat cfgspc.regs.bm.mmii.mmii.max_lat +#define pci_max_min_ipin_iline cfgspc.regs.bm.mmii.max_min_ipin_iline +#define pci_bridge_control cfgspc.regs.bm.bctrl.bridge_control +#define pci_user_config cfgspc.regs.devspf.dwords[0] +#define pci_user_config_0 cfgspc.regs.devspf.bytes[0] +#define pci_user_config_1 cfgspc.regs.devspf.bytes[1] +#define pci_user_config_2 cfgspc.regs.devspf.bytes[2] +#define pci_user_config_3 cfgspc.regs.devspf.bytes[3] + +typedef enum { + PCI_BIOS_PC = 0, + PCI_BIOS_OPEN_FIRMARE, + PCI_BIOS_HP_PA_RISC, + PCI_BIOS_OTHER +} PciBiosType; + +/* Public PCI access functions */ +void pciInit(void); +PCITAG pciFindFirst(CARD32 id, CARD32 mask); +PCITAG pciFindNext(void); +CARD32 pciReadLong(PCITAG tag, int offset); +CARD16 pciReadWord(PCITAG tag, int offset); +CARD8 pciReadByte(PCITAG tag, int offset); +void pciWriteLong(PCITAG tag, int offset, CARD32 val); +void pciWriteWord(PCITAG tag, int offset, CARD16 val); +void pciWriteByte(PCITAG tag, int offset, CARD8 val); +void pciSetBitsLong(PCITAG tag, int offset, CARD32 mask, CARD32 val); +void pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val); +ADDRESS pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr); +ADDRESS pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr); +PCITAG pciTag(int busnum, int devnum, int funcnum); +int pciGetBaseSize(PCITAG tag, int indx, Bool destructive, Bool *min); +CARD32 pciCheckForBrokenBase(PCITAG tag,int basereg); +pointer xf86MapPciMem(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size); +int xf86ReadPciBIOS(unsigned long Offset, PCITAG Tag, int basereg, + unsigned char *Buf, int Len); +int xf86ReadPciBIOSByType(unsigned long Offset, PCITAG Tag, + int basereg, unsigned char *Buf, + int Len, PciBiosType Type); +int xf86GetAvailablePciBIOSTypes(PCITAG Tag, int basereg, + PciBiosType *Buf); +pciConfigPtr *xf86scanpci(int flags); + +extern int pciNumBuses; + +/* Domain access functions. Some of these probably shouldn't be public */ +int xf86GetPciDomain(PCITAG tag); +pointer xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, + ADDRESS Base, unsigned long Size); +IOADDRESS xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, + IOADDRESS Base, unsigned long Size); +int xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, + unsigned char *Buf); + +typedef enum { + ROM_BASE_PRESET = -2, + ROM_BASE_BIOS, + ROM_BASE_MEM0 = 0, + ROM_BASE_MEM1, + ROM_BASE_MEM2, + ROM_BASE_MEM3, + ROM_BASE_MEM4, + ROM_BASE_MEM5, + ROM_BASE_FIND +} romBaseSource; + +#endif /* _XF86PCI_H */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Sbus.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Sbus.h new file mode 100644 index 000000000..21b05cba4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/xf86Sbus.h @@ -0,0 +1,70 @@ +/* + * Platform specific SBUS and OpenPROM access declarations. + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/xf86Sbus.h,v 1.3 2001/04/20 17:02:43 tsi Exp $ */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _XF86_SBUS_H +#define _XF86_SBUS_H + +#if defined(linux) +#include <asm/types.h> +#include <linux/fb.h> +#include <asm/fbio.h> +#include <asm/openpromio.h> +#elif defined(SVR4) +#include <sys/fbio.h> +#include <sys/openpromio.h> +#elif defined(__OpenBSD__) && defined(__sparc64__) +/* XXX */ +#elif defined(CSRG_BASED) +#if defined(__FreeBSD__) +#include <sys/types.h> +#include <sys/fbio.h> +#include <dev/ofw/openpromio.h> +#else +#include <machine/fbio.h> +#endif +#else +#include <sun/fbio.h> +#endif + +#ifndef FBTYPE_SUNGP3 +#define FBTYPE_SUNGP3 -1 +#endif +#ifndef FBTYPE_MDICOLOR +#define FBTYPE_MDICOLOR -1 +#endif +#ifndef FBTYPE_SUNLEO +#define FBTYPE_SUNLEO -1 +#endif +#ifndef FBTYPE_TCXCOLOR +#define FBTYPE_TCXCOLOR -1 +#endif +#ifndef FBTYPE_CREATOR +#define FBTYPE_CREATOR -1 +#endif + +#endif /* _XF86_SBUS_H */ diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c new file mode 100644 index 000000000..3d219c86f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c @@ -0,0 +1,1133 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c,v 1.8 2004/01/16 15:39:38 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +/* + * This file contains the glue necessary for support of HP's ZX1 chipset. + * Keep in mind that this chipset is used in both Itanium2 and PA-RISC + * architectures. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "zx1PCI.h" +#include "xf86.h" +#include "xf86_OSlib.h" +#include "Pci.h" + +#define MIO_BASE 0xFED00000UL /* mio register base */ +#define MIO_SIZE 0x00002000UL /* 8k, minimum */ + +/* ZX1 mio register definitions */ +#define MIO_FUNCTION0 0x0000U + +#define MODULE_INFO 0x0100U +#define STATUS_CONTROL 0x0108U +#define DILLON_PRESENT 0x02UL + +#define LMMIO_DIR_BASE0 0x0300U +#define LMMIO_DIR_MASK0 0x0308U +#define LMMIO_DIR_ROUTE0 0x0310U +#define LMMIO_DIR_BASE1 0x0318U +#define LMMIO_DIR_MASK1 0x0320U +#define LMMIO_DIR_ROUTE1 0x0328U +#define LMMIO_DIR_BASE2 0x0330U +#define LMMIO_DIR_MASK2 0x0338U +#define LMMIO_DIR_ROUTE2 0x0340U +#define LMMIO_DIR_BASE3 0x0348U +#define LMMIO_DIR_MASK3 0x0350U +#define LMMIO_DIR_ROUTE3 0x0358U +#define LMMIO_DIST_BASE 0x0360U +#define LMMIO_DIST_MASK 0x0368U +#define LMMIO_DIST_ROUTE 0x0370U +#define GMMIO_DIST_BASE 0x0378U +#define PORT_DISABLE 0x02UL +#define MAP_TO_LMMIO 0x04UL +#define GMMIO_DIST_MASK 0x0380U +#define GMMIO_DIST_ROUTE 0x0388U +#define IOS_DIST_BASE 0x0390U +#define IOS_DIST_MASK 0x0398U +#define IOS_DIST_ROUTE 0x03A0U +#define ROPE_CONFIG_BASE 0x03A8U +#define VGA_ROUTE 0x03B0U +#define VGA_ENABLE 0x8000000000000000UL +#define VGA_LIGHT 0x4000000000000000UL + +#define IOS_DIR_BASE 0x03C0U +#define IOS_DIR_MASK 0x03C8U +#define IOS_DIR_ROUTE 0x03D0U +#define IOS_BASE 0x03D8U + +#define MIO_FUNCTION1 0x1000U + +#define ROPE_CONFIG 0x1040U +#define ROPE_D0 0x0100UL +#define ROPE_D2 0x0200UL +#define ROPE_D4 0x0400UL +#define ROPE_D6 0x0800UL +#define ROPE_Q0 0x1000UL +#define ROPE_Q4 0x2000UL + +#define LBA_PORT0_CNTRL 0x1200U +#define LBA_PORT1_CNTRL 0x1208U +#define LBA_PORT2_CNTRL 0x1210U +#define LBA_PORT3_CNTRL 0x1218U +#define LBA_PORT4_CNTRL 0x1220U +#define LBA_PORT5_CNTRL 0x1228U +#define LBA_PORT6_CNTRL 0x1230U +#define LBA_PORT7_CNTRL 0x1238U +#define LBA_RESET_FUNCTION 0x0000000001UL +#define LBA_CLEAR_ERROR 0x0000000010UL +#define LBA_HARD_FAIL 0x0000000040UL +#define LBA_RESET_COMPLETE 0x0100000000UL + +#define ROPE_PAGE_CONTROL 0x1418U + +/* + * Total ioa configuration space size is actually 128k, but we only need the + * first 64k. + */ +#define IOA_SIZE 0x00010000UL + +/* ZX1 ioa register definitions */ +#define IOA_CONFIG_ADDR 0x0040U +#define IOA_CONFIG_DATA 0x0048U + +#define IOA_SECONDARY_BUS 0x0058U +#define IOA_SUBORDINATE_BUS 0x0059U + +#define IOA_CONTROL 0x0108U +#define IOA_RESET_FUNCTION 0x0000000001UL +#define IOA_FORWARD_VGA 0x0000000008UL +#define IOA_CLEAR_ERROR 0x0000000010UL +#define IOA_HARD_FAIL 0x0000000040UL +#define IOA_RESET_COMPLETE 0x0100000000UL + +#define IOA_LMMIO_BASE 0x0200U +#define IOA_LMMIO_MASK 0x0208U +#define IOA_GMMIO_BASE 0x0210U +#define IOA_GMMIO_MASK 0x0218U +#define IOA_WLMMIO_BASE 0x0220U +#define IOA_WLMMIO_MASK 0x0228U +#define IOA_WGMMIO_BASE 0x0230U +#define IOA_WGMMIO_MASK 0x0238U +#define IOA_IOS_BASE 0x0240U +#define IOA_IOS_MASK 0x0248U +#define IOA_ELMMIO_BASE 0x0250U +#define IOA_ELMMIO_MASK 0x0258U +#define IOA_EIOS_BASE 0x0260U +#define IOA_EIOS_MASK 0x0268U +#define IOA_GLOBAL_MASK 0x0270U +#define IOA_SLAVE_CONTROL 0x0278U +#define IOA_VGA_PEER_ENABLE 0x2000UL +#define IOA_MSI_BASE 0x0280U +#define IOA_MSI_MASK 0x0288U + +#define IOA_DMA_BASE 0x02B0U +#define IOA_DMA_MASK 0x02B8U + +#define IOA_ERROR_CONFIG 0x0680U +#define IOA_ERROR_PIOWRITE 0x0001UL +#define IOA_ERROR_PIOREAD 0x0002UL +#define IOA_ERROR_DMAWRITE 0x0004UL +#define IOA_ERROR_DMAREAD 0x0008UL +#define IOA_ERROR_CONFIG_MASTER 0x0010UL +#define IOA_ERROR_SMART 0x0020UL +#define IOA_ERROR_FATAL_SERR 0x0040UL +#define IOA_ERROR_ASSERT_SERR 0x0080UL +/* ? 0x0100UL */ +#define IOA_ERROR_LOOPBACK 0x0200UL +#define IOA_ERROR_CONFIG_TARGET 0x0400UL +#define IOA_ERROR_IO_MASTER 0x0800UL +#define IOA_ERROR_IO_TARGET 0x1000UL +#define IOA_ERROR_MEM_MASTER 0x2000UL +#define IOA_ERROR_MEM_TARGET 0x4000UL +#define IOA_ERROR_HF_IO_FATAL 0x8000UL + +#define RANGE_ENABLE 0x01UL /* In various base registers */ + +#define IO_MASK ((1UL << 16) - 1UL) +#define LMMIO_MASK ((1UL << 32) - 1UL) +#ifdef __ia64__ +#define GMMIO_MASK ((1UL << 44) - 1UL) +#else /* PA-RISC */ +#define GMMIO_MASK ((1UL << 40) - 1UL) +#endif + +#define PDH_START 0xFF000000UL +#define PDH_LAST 0xFFFFFFFFUL + +static CARD8 *pZX1mio = NULL, + *pZX1ioa = NULL; + +/* Per-rope data */ +static INT8 zx1_ropemap[8]; +static CARD32 zx1_pciids[8]; +static CARD64 zx1_lbacntl[8]; +static int zx1_busno[8], zx1_subno[8]; + +/* Array of Booleans for non-empty buses */ +static INT8 zx1_busnmpt[MAX_PCI_BUSES]; + +static pciBusFuncs_t zx1BusFuncs; +static int zx1_fakebus = -1; +static Bool zx1_hasvga = FALSE; + +static pointer pZX1IoRes[8], pZX1MemRes[8]; /* Rope resources */ + +/* Non-PCI configuration space access macros */ +#define MIO_BYTE(offset) \ + (*(volatile CARD8 *)(pointer)(pZX1mio + (offset))) +#define MIO_WORD(offset) \ + (*(volatile CARD16 *)(pointer)(pZX1mio + (offset))) +#define MIO_LONG(offset) \ + (*(volatile CARD32 *)(pointer)(pZX1mio + (offset))) +#define MIO_QUAD(offset) \ + (*(volatile CARD64 *)(pointer)(pZX1mio + (offset))) +#define IOA_BYTE(ioa, offset) \ + (*(volatile CARD8 *)(pointer)(pZX1ioa + ((offset) + ((ioa) << 13)))) +#define IOA_WORD(ioa, offset) \ + (*(volatile CARD16 *)(pointer)(pZX1ioa + ((offset) + ((ioa) << 13)))) +#define IOA_LONG(ioa, offset) \ + (*(volatile CARD32 *)(pointer)(pZX1ioa + ((offset) + ((ioa) << 13)))) +#define IOA_QUAD(ioa, offset) \ + (*(volatile CARD64 *)(pointer)(pZX1ioa + ((offset) + ((ioa) << 13)))) + +/* Range definitions */ +#define MAX_RANGE 16 +static CARD64 bot[MAX_RANGE], top[MAX_RANGE], msk[MAX_RANGE], siz[MAX_RANGE]; +static INT8 *pDecode[MAX_RANGE]; +static int nRange = 0; + +/* Track a resource range and assign a granularity to it */ +static void +SetRange(CARD64 base, CARD64 last, CARD8 width) +{ + int i; + + bot[nRange] = base; + top[nRange] = last; + msk[nRange] = (CARD64)(-1L); + if (base) + msk[nRange] &= (base ^ (base - 1UL)) >> 1; + if (last + 1UL) + msk[nRange] &= (last ^ (last + 1UL)) >> 1; + if (width < 64) + msk[nRange] &= (1UL << width) - 1UL; + + /* Look for overlapping ranges */ + for (i = 0; i < nRange; i++) { + if ((bot[i] > top[i]) || + (top[nRange] < bot[i]) || + (top[i] < bot[nRange])) + continue; + + /* Merge in overlapping range */ + if (bot[nRange] > bot[i]) + bot[nRange] = bot[i]; + if (top[nRange] < top[i]) + top[nRange] = top[i]; + + /* Assign finer granularity */ + msk[nRange] &= msk[i]; + bot[i] = 1UL; + top[i] = 0; + } + + nRange++; +} + +/* Lookup granularity associated with the range containing 'base' */ +static int +GetRange(CARD64 base) +{ + int i; + + for (i = 0; i < nRange; i++) { + if ((bot[i] > top[i]) || + (base < bot[i]) || + (base > top[i])) + continue; + + if (pDecode[i]) + break; + + /* Allocate decoding array */ + msk[i]++; + siz[i] = ((top[i] - bot[i] + 1UL) / msk[i]) + 1UL; + pDecode[i] = xnfalloc(siz[i]); + (void)memset(pDecode[i], -1, siz[i]); + break; + } + + return i; +} + +/* + * Verify that 'bus' is a rope's secondary bus and return the pciConfigPtr of + * the associated fake PCI-to-PCI bridge. + */ +static pciConfigPtr +VerifyZX1Bus(int bus) +{ + pciConfigPtr pPCI; + + if ((bus < 0) || (bus >= pciNumBuses) || + !pciBusInfo[bus] || !(pPCI = pciBusInfo[bus]->bridge) || + (pPCI->busnum != zx1_fakebus) || (pPCI->funcnum != 0) || + (pPCI->devnum < 0x10) || (pPCI->devnum > 0x17)) + return NULL; + + return pPCI; +} + +/* + * This function is called to emulate the various settings in a P2P or CardBus + * bridge's control register on a ZX1-based system. + */ +static CARD16 +ControlZX1Bridge(int bus, CARD16 mask, CARD16 value) +{ + pciConfigPtr pPCI; + CARD64 tmp1, tmp2, tmp3, ropenum; + CARD16 current = 0; + + if ((pPCI = VerifyZX1Bus(bus))) { + ropenum = pPCI->devnum & 0x07; + + /* + * Start with VGA enablement. This preserves the "VGA-lite" bit + * in mio's VGA_ROUTE register, and the VPE bit in each ioa's + * SLAVE_CONTROL register. + */ + tmp1 = MIO_QUAD(VGA_ROUTE); + tmp2 = IOA_QUAD(ropenum, IOA_CONTROL) & + ~(IOA_RESET_FUNCTION | IOA_CLEAR_ERROR); + if ((tmp1 & VGA_ENABLE) && ((tmp1 & 0x07UL) == ropenum)) { + current |= PCI_PCI_BRIDGE_VGA_EN; + if ((mask & PCI_PCI_BRIDGE_VGA_EN) && + !(value & PCI_PCI_BRIDGE_VGA_EN)) { + MIO_QUAD(VGA_ROUTE) = tmp1 & ~VGA_ENABLE; + tmp2 &= ~IOA_FORWARD_VGA; + IOA_QUAD(ropenum, IOA_CONTROL) = tmp2; + } + } else if (mask & value & PCI_PCI_BRIDGE_VGA_EN) { + if (!zx1_hasvga) { + xf86MsgVerb(X_WARNING, 3, + "HP ZX1: Attempt to enable VGA routing to bus %d" + " through rope %ld disallowed\n", bus, ropenum); + value &= ~PCI_PCI_BRIDGE_VGA_EN; + } else { + if (tmp1 & VGA_ENABLE) { + /* + * VGA is routed somewhere else. Disable it. + */ + MIO_QUAD(VGA_ROUTE) = 0UL; + tmp3 = IOA_QUAD(tmp1 & 0x07UL, IOA_CONTROL); + if (tmp3 & IOA_FORWARD_VGA) + IOA_QUAD(tmp1 & 0x07UL, IOA_CONTROL) = tmp3 & + ~(IOA_RESET_FUNCTION | IOA_FORWARD_VGA | + IOA_CLEAR_ERROR); + } + if (!(tmp2 & IOA_FORWARD_VGA)) { + tmp2 |= IOA_FORWARD_VGA; + IOA_QUAD(ropenum, IOA_CONTROL) = tmp2; + } + tmp1 = (tmp1 & ~0x07UL) | ropenum | VGA_ENABLE; + MIO_QUAD(VGA_ROUTE) = tmp1; + } + } + + /* Move on to master abort failure enablement */ + tmp1 = MIO_QUAD((ropenum << 3) + LBA_PORT0_CNTRL) & + ~(LBA_RESET_FUNCTION | LBA_CLEAR_ERROR); + if ((tmp1 & LBA_HARD_FAIL) || (tmp2 & IOA_HARD_FAIL)) { + current |= PCI_PCI_BRIDGE_MASTER_ABORT_EN; + if ((mask & PCI_PCI_BRIDGE_MASTER_ABORT_EN) && + !(value & PCI_PCI_BRIDGE_MASTER_ABORT_EN)) { + if (tmp1 & LBA_HARD_FAIL) + MIO_QUAD((ropenum << 3) + LBA_PORT0_CNTRL) = + tmp1 & ~LBA_HARD_FAIL; + if (tmp2 & IOA_HARD_FAIL) { + tmp2 &= ~IOA_HARD_FAIL; + IOA_QUAD(ropenum, IOA_CONTROL) = tmp2; + } + } + } else { + if (mask & value & PCI_PCI_BRIDGE_MASTER_ABORT_EN) { + if (!(tmp1 & LBA_HARD_FAIL)) + MIO_QUAD((ropenum << 3) + LBA_PORT0_CNTRL) = + tmp1 | LBA_HARD_FAIL; + if (!(tmp2 & IOA_HARD_FAIL)) { + tmp2 |= IOA_HARD_FAIL; + IOA_QUAD(ropenum, IOA_CONTROL) = tmp2; + } + } + } + + /* Put emulation of any other P2P bridge control here */ + } + + return (current & ~mask) | (value & mask); +} + +/* Retrieves a list of the resources routed to a rope's secondary bus */ +static void +GetZX1BridgeResources(int bus, + pointer *ppIoRes, + pointer *ppMemRes, + pointer *ppPmemRes) +{ + pciConfigPtr pPCI = VerifyZX1Bus(bus); + + if (ppIoRes) { + xf86FreeResList(*ppIoRes); + *ppIoRes = + pPCI ? xf86DupResList(pZX1IoRes[pPCI->devnum & 0x07]) : NULL; + } + + if (ppMemRes) { + xf86FreeResList(*ppMemRes); + *ppMemRes = + pPCI ? xf86DupResList(pZX1MemRes[pPCI->devnum & 0x07]) : NULL; + } + + if (ppPmemRes) { + xf86FreeResList(*ppPmemRes); + *ppPmemRes = NULL; + } +} + +/* The fake bus */ +static CARD32 +zx1FakeReadLong(PCITAG tag, int offset) +{ + FatalError("zx1FakeReadLong(0x%lX, 0x%X) called\n", + (unsigned long)tag, offset); +} + +static void +zx1FakeWriteLong(PCITAG tag, int offset, CARD32 val) +{ + FatalError("zx1FakeWriteLong(0x%lX, 0x%X, 0x%08X) called\n", + (unsigned long)tag, offset, val); +} + +static void +zx1FakeSetBits(PCITAG tag, int offset, CARD32 mask, CARD32 bits) +{ + CARD32 val; + + val = zx1FakeReadLong(tag, offset); + val &= ~mask; + val |= bits; + zx1FakeWriteLong(tag, offset, val); +} + +static pciBusFuncs_t zx1FakeBusFuncs = { + zx1FakeReadLong, + zx1FakeWriteLong, + zx1FakeSetBits +}; + +static pciBusInfo_t zx1FakeBus = { + 0, /* configMech -- copied from bus 0 */ + 0, /* numDevices -- copied from bus 0 */ + FALSE, /* secondary */ + 0, /* primary_bus -- dynamically set */ +#ifdef PowerMAX_OS + 0, /* ppc_io_base -- ignored */ + 0, /* ppc_io_size -- ignored */ +#endif + &zx1FakeBusFuncs, /* funcs */ + NULL, /* pciBusPriv -- none */ + NULL, /* bridge -- dynamically set */ +}; + +void +xf86PreScanZX1(void) +{ + resRange range; + unsigned long mapSize = xf86getpagesize(); + unsigned long tmp, base, ioaaddr; + unsigned long flagsd, based, lastd, maskd, routed; + unsigned long flags0, base0, last0, mask0, route0; + unsigned long flags1, base1, last1, mask1, route1; + unsigned long flags2, base2, last2, mask2, route2; + unsigned long flags3, base3, last3, mask3, route3; + unsigned long flagsg, baseg, lastg, maskg, routeg; + unsigned long flagsl, basel, lastl; + int i, rope; + + /* Map mio registers (minimum 8k) */ + if (mapSize < MIO_SIZE) + mapSize = MIO_SIZE; + + if (!(pZX1mio = xf86MapVidMem(-1, VIDMEM_MMIO, MIO_BASE, mapSize))) + return; + + /* Look for ZX1's SBA and IOC */ + if (((MIO_LONG(MIO_FUNCTION0 + PCI_ID_REG) != + DEVID(VENDOR_HP, CHIP_ZX1_SBA)) || + (MIO_LONG(MIO_FUNCTION1 + PCI_ID_REG) != + DEVID(VENDOR_HP, CHIP_ZX1_IOC))) && + ((MIO_LONG(MIO_FUNCTION0 + PCI_ID_REG) != + DEVID(VENDOR_HP, CHIP_ZX2_SBA)) || + (MIO_LONG(MIO_FUNCTION1 + PCI_ID_REG) != + DEVID(VENDOR_HP, CHIP_ZX2_IOC)))) { + xf86UnMapVidMem(-1, pZX1mio, mapSize); + pZX1mio = NULL; + return; + } + + /* Map rope configuration space */ + ioaaddr = MIO_QUAD(ROPE_CONFIG_BASE); + if (!(ioaaddr & RANGE_ENABLE) || /* No ropes */ + ((ioaaddr = ioaaddr & ~RANGE_ENABLE) & 0x01FFFFUL) || /* Not aligned */ + !(pZX1ioa = xf86MapVidMem(-1, VIDMEM_MMIO, ioaaddr, IOA_SIZE))) { + xf86UnMapVidMem(-1, pZX1mio, mapSize); + pZX1mio = NULL; + return; + } + + for (i = 0; i < 8; i++) { + zx1_ropemap[i] = i; + zx1_lbacntl[i] = 0; + xf86FreeResList(pZX1IoRes[i]); + xf86FreeResList(pZX1MemRes[i]); + pZX1IoRes[i] = pZX1MemRes[i] = NULL; + } + + /* + * Determine which of 8 possible ropes exist in the system. This is done + * by looking at their "coupling" to generate a list of candidates, + * whittling this list down by factoring in ROPE_PAGE_CONTROL register + * contents, then poking each candidate's configuration space to determine + * its existence. + */ + tmp = MIO_QUAD(ROPE_CONFIG); + if (tmp & ROPE_D0) + zx1_ropemap[1] = 0; + if (tmp & ROPE_D2) + zx1_ropemap[3] = 2; + if (tmp & ROPE_D4) + zx1_ropemap[5] = 4; + if (tmp & ROPE_D6) + zx1_ropemap[7] = 6; + if (tmp & ROPE_Q0) + zx1_ropemap[1] = zx1_ropemap[2] = zx1_ropemap[3] = 0; + if (tmp & ROPE_Q4) + zx1_ropemap[5] = zx1_ropemap[6] = zx1_ropemap[7] = 4; + + /* + * zx2 should allow better probing support via hard-fails, so no need to + * use the ROPE_PAGE_CONTROL register. Also, zx2 always has ropes 3 & 7 + * active regardless of bundling. + */ + if (MIO_LONG(MIO_FUNCTION0 + PCI_ID_REG) != + DEVID(VENDOR_HP, CHIP_ZX2_SBA)) { + + tmp = MIO_QUAD(ROPE_PAGE_CONTROL); + for (i = 0; i < 8; i++, tmp >>= 8) + if (!(CARD8)tmp) + zx1_ropemap[i] = -1; + } else { + zx1_ropemap[3] = 3; + zx1_ropemap[7] = 7; + } + + for (i = 0; i < 8; ) { + if (zx1_ropemap[i] == i) { + + /* Prevent hard-fails */ + zx1_lbacntl[i] = MIO_QUAD((i << 3) + LBA_PORT0_CNTRL) & + ~(LBA_RESET_FUNCTION | LBA_CLEAR_ERROR); + if (zx1_lbacntl[i] & LBA_HARD_FAIL) + MIO_QUAD((i << 3) + LBA_PORT0_CNTRL) = + zx1_lbacntl[i] & ~LBA_HARD_FAIL; + + /* Poke for an ioa */ + zx1_pciids[i] = IOA_LONG(i, PCI_ID_REG); + switch (zx1_pciids[i]) { + case DEVID(VENDOR_HP, CHIP_ELROY): + case DEVID(VENDOR_HP, CHIP_ZX1_LBA): /* Mercury */ + case DEVID(VENDOR_HP, CHIP_ZX1_AGP8): /* QuickSilver */ + case DEVID(VENDOR_HP, CHIP_ZX2_LBA): + /* Expected vendor/device IDs */ + zx1_busno[i] = + (unsigned int)IOA_BYTE(i, IOA_SECONDARY_BUS); + zx1_subno[i] = + (unsigned int)IOA_BYTE(i, IOA_SUBORDINATE_BUS); + break; + + default: + if ((CARD16)(zx1_pciids[i] + 1U) > (CARD16)1U) + xf86MsgVerb(X_NOTICE, 0, + "HP ZX1: Unexpected vendor/device id 0x%08X" + " on rope %d\n", zx1_pciids[i], i); + /* Nobody home, or not the "right" kind of rope guest */ + + /* + * Restore hard-fail setting. For "active" ropes, this is done + * later. + */ + if (zx1_lbacntl[i] & LBA_HARD_FAIL) { + MIO_QUAD((i << 3) + LBA_PORT0_CNTRL) = zx1_lbacntl[i]; + zx1_lbacntl[i] = 0; + } + + /* Ignore this rope and its couplings */ + do { + zx1_ropemap[i++] = -1; + } while ((i < 8) && (zx1_ropemap[i] < i)); + continue; /* Avoid over-incrementing 'i' */ + } + } + i++; + } + + /* Determine if VGA is currently routed */ + tmp = MIO_QUAD(VGA_ROUTE); + if (tmp & VGA_ENABLE) + zx1_hasvga = TRUE; + + /* + * Decode mio resource "coarse" routing (i.e. ignoring VGA). Due to the + * rather unusual flexibility of this chipset, this is done in a number of + * stages. For each of I/O and memory, first decode the relevant registers + * to generate ranges with an associated granularity. Overlapping ranges + * are merged into a larger range with the finer granularity. Each + * original range is then more thoroughly decoded using the granularity + * associated with the merged range that contains it. The result is then + * converted into resource lists for the common layer. + * + * Note that this doesn't care whether or not read-only bits are actually + * set as documented, nor that mask bits are contiguous. This does, + * however, factor in upper limits on I/O, LMMIO anf GMMIO addresses, and + * thus assumes high-order address bits are ignored rather than decoded. + * For example, an I/O address of 0x76543210 will be treated as 0x3210 + * rather than considered out-of-range. In part, this handling is a + * consequence of the fact that high-order mask bits are zeroes instead of + * ones. + */ + + flagsd = 0; based = 0; lastd = 0; maskd = 0; routed = 0; + flags0 = 0; base0 = 0; last0 = 0; mask0 = 0; route0 = 0; + flags1 = 0; base1 = 0; last1 = 0; mask1 = 0; route1 = 0; + flags2 = 0; base2 = 0; last2 = 0; mask2 = 0; route2 = 0; + flags3 = 0; base3 = 0; last3 = 0; mask3 = 0; route3 = 0; + flagsg = 0; baseg = 0; lastg = 0; maskg = 0; routeg = 0; + flagsl = 0; basel = 0; lastl = 0; + + if ((tmp = MIO_QUAD(IOS_DIST_BASE)) & RANGE_ENABLE) { + flagsd = RANGE_ENABLE; + maskd = MIO_QUAD(IOS_DIST_MASK); + based = tmp & maskd & (~RANGE_ENABLE & IO_MASK); + lastd = based | (~maskd & IO_MASK); + routed = MIO_QUAD(IOS_DIST_ROUTE) >> 58; + SetRange(based, lastd, routed); + } + + if ((tmp = MIO_QUAD(IOS_DIR_BASE)) & RANGE_ENABLE) { + flags0 = RANGE_ENABLE; + mask0 = MIO_QUAD(IOS_DIR_MASK); + base0 = tmp & mask0 & (~RANGE_ENABLE & IO_MASK); + last0 = base0 | (~mask0 & IO_MASK); + route0 = MIO_QUAD(IOS_DIR_ROUTE) & 0x07U; + SetRange(base0, last0, 64); + } + + if (flagsd) { + i = GetRange(based); + for (tmp = based; tmp <= lastd; tmp += msk[i]) { + if ((tmp & maskd) == based) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[(tmp >> routed) & 0x07U]; + } + } + + flagsd = 0; + } + + if (flags0) { + i = GetRange(base0); + for (tmp = base0; tmp <= last0; tmp += msk[i]) { + if ((tmp & mask0) == base0) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[route0]; + } + } + + flags0 = 0; + } + + for (i = 0; i < nRange; i++) { + if (!pDecode[i]) + continue; + + rope = pDecode[i][0]; + for (base = tmp = 0; ++tmp < siz[i]; ) { + if (rope == pDecode[i][tmp]) + continue; + + if (rope >= 0) { + RANGE(range, (base * msk[i]) + bot[i], + (tmp * msk[i]) + bot[i] - 1UL, + RANGE_TYPE(ResExcIoBlock, 0)); + pZX1IoRes[rope] = + xf86AddResToList(pZX1IoRes[rope], &range, -1); + } + + base = tmp; + rope = pDecode[i][base]; + } + + xfree(pDecode[i]); + pDecode[i] = NULL; + } + + nRange = 0; + + /* + * Move on to CPU memory access decoding. For now, don't tell the common + * layer about CPU memory ranges that are either relocated to 0 or + * translated into PCI I/O. + */ + + SetRange(MIO_BASE, MIO_BASE + MIO_SIZE - 1UL, 64); /* mio */ + SetRange(ioaaddr, ioaaddr + ((IOA_SIZE << 1) - 1UL), 64); /* ioa */ + SetRange(PDH_START, PDH_LAST, 64); /* PDH */ + + SetRange(MIO_BASE, LMMIO_MASK, 64); /* Completeness */ + + if ((tmp = MIO_QUAD(LMMIO_DIST_BASE)) & RANGE_ENABLE) { + flagsd = RANGE_ENABLE; + maskd = MIO_QUAD(LMMIO_DIST_MASK); + based = tmp & maskd & (~RANGE_ENABLE & LMMIO_MASK); + lastd = based | (~maskd & LMMIO_MASK); + routed = MIO_QUAD(LMMIO_DIST_ROUTE) >> 58; + SetRange(based, lastd, routed); + } + + if ((tmp = MIO_QUAD(LMMIO_DIR_BASE0)) & RANGE_ENABLE) { + flags0 = RANGE_ENABLE; + mask0 = MIO_QUAD(LMMIO_DIR_MASK0); + base0 = tmp & mask0 & (~RANGE_ENABLE & LMMIO_MASK); + last0 = base0 | (~mask0 & LMMIO_MASK); + route0 = MIO_QUAD(LMMIO_DIR_ROUTE0) & 0x07U; + SetRange(base0, last0, 64); + } + + if ((tmp = MIO_QUAD(LMMIO_DIR_BASE1)) & RANGE_ENABLE) { + flags1 = RANGE_ENABLE; + mask1 = MIO_QUAD(LMMIO_DIR_MASK1); + base1 = tmp & mask1 & (~RANGE_ENABLE & LMMIO_MASK); + last1 = base1 | (~mask1 & LMMIO_MASK); + route1 = MIO_QUAD(LMMIO_DIR_ROUTE1) & 0x07U; + SetRange(base1, last1, 64); + } + + if ((tmp = MIO_QUAD(LMMIO_DIR_BASE2)) & RANGE_ENABLE) { + flags2 = RANGE_ENABLE; + mask2 = MIO_QUAD(LMMIO_DIR_MASK2); + base2 = tmp & mask2 & (~RANGE_ENABLE & LMMIO_MASK); + last2 = base2 | (~mask2 & LMMIO_MASK); + route2 = MIO_QUAD(LMMIO_DIR_ROUTE2) & 0x07U; + SetRange(base2, last2, 64); + } + + if ((tmp = MIO_QUAD(LMMIO_DIR_BASE3)) & RANGE_ENABLE) { + flags3 = RANGE_ENABLE; + mask3 = MIO_QUAD(LMMIO_DIR_MASK3); + base3 = tmp & mask3 & (~RANGE_ENABLE & LMMIO_MASK); + last3 = base3 | (~mask3 & LMMIO_MASK); + route3 = MIO_QUAD(LMMIO_DIR_ROUTE3) & 0x07U; + SetRange(base3, last3, 64); + } + + if ((tmp = MIO_QUAD(GMMIO_DIST_BASE)) & RANGE_ENABLE) { + flagsg = tmp & (RANGE_ENABLE | PORT_DISABLE | MAP_TO_LMMIO); + maskg = MIO_QUAD(GMMIO_DIST_MASK); + baseg = tmp & maskg & + (~(RANGE_ENABLE | PORT_DISABLE | MAP_TO_LMMIO) & GMMIO_MASK); + lastg = baseg | (~maskg & GMMIO_MASK); + tmp = routeg = MIO_QUAD(GMMIO_DIST_ROUTE) >> 58; + if (!(flagsg & (PORT_DISABLE & MAP_TO_LMMIO)) && (tmp > 26)) + tmp = 26; + SetRange(baseg, lastg, tmp); + } + + if ((tmp = MIO_QUAD(IOS_BASE)) & RANGE_ENABLE) { + flagsl = RANGE_ENABLE; + basel = tmp & (~RANGE_ENABLE & GMMIO_MASK); + lastl = basel | 0x001FFFFFUL; + SetRange(basel, lastl, 64); + } + + if (flagsd) { + i = GetRange(based); + for (tmp = based; tmp <= lastd; tmp += msk[i]) { + if ((tmp & maskd) == based) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[(tmp >> routed) & 0x07U]; + } + } + + flagsd = 0; + } + + /* LMMIO distributed range does not address anything beyond 0xFED00000 */ + i = GetRange(MIO_BASE); + for (tmp = MIO_BASE; tmp <= LMMIO_MASK; tmp += msk[i]) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = -1; + } + + /* Dillon space can sometimes be redirected to rope 0 */ + tmp = MIO_QUAD(STATUS_CONTROL); + if (!(tmp & DILLON_PRESENT)) { + i = GetRange(PDH_START); + for (tmp = PDH_START; tmp <= PDH_LAST; tmp += msk[i]) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[0]; + } + } + + if (flagsg) { + unsigned long mask = (0x07UL << routeg) | maskg; + + i = GetRange(baseg); + for (tmp = baseg; tmp <= lastg; tmp += msk[i]) { + if ((tmp & maskg) == baseg) { + base = (tmp - bot[i]) / msk[i]; + + if ((flagsg & MAP_TO_LMMIO) || + (!(flagsg & PORT_DISABLE) && + (tmp <= ((tmp & mask) | 0x03FFFFFFUL)))) { + pDecode[i][base] = -1; + } else { + pDecode[i][base] = zx1_ropemap[(tmp >> routeg) & 0x07U]; + } + } + } + + flagsg = 0; + } + + if (flagsl) { + i = GetRange(basel); + for (tmp = basel; tmp <= lastl; tmp += msk[i]) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = -1; + } + + flagsl = 0; + } + + /* For now, assume directed LMMIO ranges don't overlap with each other */ + if (flags0) { + i = GetRange(base0); + for (tmp = base0; tmp <= last0; tmp += msk[i]) { + if ((tmp & mask0) == base0) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[route0]; + } + } + + flags0 = 0; + } + + if (flags1) { + i = GetRange(base1); + for (tmp = base1; tmp <= last1; tmp += msk[i]) { + if ((tmp & mask1) == base1) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[route1]; + } + } + + flags1 = 0; + } + + if (flags2) { + i = GetRange(base2); + for (tmp = base2; tmp <= last2; tmp += msk[i]) { + if ((tmp & mask2) == base2) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[route2]; + } + } + + flags2 = 0; + } + + if (flags3) { + i = GetRange(base3); + for (tmp = base3; tmp <= last3; tmp += msk[i]) { + if ((tmp & mask3) == base3) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = zx1_ropemap[route3]; + } + } + + flags3 = 0; + } + + /* Claim iao config area */ + i = GetRange(ioaaddr); + for (tmp = ioaaddr; tmp < ioaaddr + (IOA_SIZE << 1); tmp += msk[i]) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = -1; + } + + /* Claim mio config area */ + i = GetRange(MIO_BASE); + for (tmp = MIO_BASE; tmp < (MIO_BASE + MIO_SIZE); tmp += msk[i]) { + base = (tmp - bot[i]) / msk[i]; + pDecode[i][base] = -1; + } + + for (i = 0; i < nRange; i++) { + if (!pDecode[i]) + continue; + + rope = pDecode[i][0]; + for (base = tmp = 0; ++tmp < siz[i]; ) { + if (rope == pDecode[i][tmp]) + continue; + + if (rope >= 0) { + RANGE(range, (base * msk[i]) + bot[i], + (tmp * msk[i]) + bot[i] - 1UL, + RANGE_TYPE(ResExcMemBlock, 0)); + pZX1MemRes[rope] = + xf86AddResToList(pZX1MemRes[rope], &range, -1); + } + + base = tmp; + rope = pDecode[i][base]; + } + + xfree(pDecode[i]); + pDecode[i] = NULL; + } + + nRange = 0; + + return; +} + +/* This is called to finalise the results of a PCI bus scan */ +void +xf86PostScanZX1(void) +{ + pciConfigPtr pPCI, *ppPCI, *ppPCI2; + pciBusInfo_t *pBusInfo; + int i, idx; + + if (!pZX1mio) + return; + + (void)memset(zx1_busnmpt, FALSE, sizeof(zx1_busnmpt)); + pBusInfo = pciBusInfo[0]; + + /* + * Certain 2.4 & 2.5 Linux kernels add fake PCI devices. Remove them to + * prevent any possible interference with our PCI validation. + * + * Also, if VGA isn't routed on server entry, determine if VGA routing + * needs to be enabled while the server is running. + */ + idx = 0; + ppPCI = ppPCI2 = xf86scanpci(0); /* Recursion is only apparent */ + while ((pPCI = *ppPCI2++)) { + switch (pPCI->pci_device_vendor) { + case DEVID(VENDOR_HP, CHIP_ELROY): + case DEVID(VENDOR_HP, CHIP_ZX1_SBA): /* Pluto function 0 */ + case DEVID(VENDOR_HP, CHIP_ZX1_IOC): /* Pluto function 1 */ + case DEVID(VENDOR_HP, CHIP_ZX1_LBA): /* Mercury */ + case DEVID(VENDOR_HP, CHIP_ZX1_AGP8): /* QuickSilver */ + case DEVID(VENDOR_HP, CHIP_ZX2_SBA): + case DEVID(VENDOR_HP, CHIP_ZX2_IOC): + case DEVID(VENDOR_HP, CHIP_ZX2_LBA): + xfree(pPCI); /* Remove it */ + continue; + + default: + *ppPCI++ = pPCI; + idx++; + + zx1_busnmpt[pPCI->busnum] = TRUE; + + if (zx1_hasvga) + continue; + + switch (pPCI->pci_base_class) { + case PCI_CLASS_PREHISTORIC: + if (pPCI->pci_sub_class == PCI_SUBCLASS_PREHISTORIC_VGA) + break; + continue; + + case PCI_CLASS_DISPLAY: + if (pPCI->pci_sub_class == PCI_SUBCLASS_DISPLAY_VGA) + break; + continue; + + default: + continue; + } + + zx1_hasvga = TRUE; + continue; + } + } + + /* + * Restore hard-fail settings and figure out the actual secondary and + * subordinate bus numbers. + */ + for (i = 0; i < 8; i++) { + if (zx1_ropemap[i] != i) + continue; + + if (zx1_lbacntl[i] & LBA_HARD_FAIL) + MIO_QUAD((i << 3) + LBA_PORT0_CNTRL) = zx1_lbacntl[i]; + + while ((zx1_busno[i] < zx1_subno[i]) && !pciBusInfo[zx1_subno[i]]) + zx1_subno[i]--; + + if (zx1_fakebus <= zx1_subno[i]) + zx1_fakebus = zx1_subno[i] + 1; + + while (!zx1_busnmpt[zx1_busno[i]]) { + if (zx1_busno[i]) /* Info for bus zero is in static storage */ + xfree(pciBusInfo[zx1_busno[i]]); + pciBusInfo[zx1_busno[i]++] = NULL; + if (zx1_busno[i] > zx1_subno[i]) + break; + } + } + + if (zx1_fakebus >= pciNumBuses) { + if (zx1_fakebus >= pciMaxBusNum) + FatalError("HP ZX1: No room for fake PCI bus\n"); + pciNumBuses = zx1_fakebus + 1; + } + + /* Set up our extra bus functions */ + zx1BusFuncs = *(pBusInfo->funcs); + zx1BusFuncs.pciControlBridge = ControlZX1Bridge; + zx1BusFuncs.pciGetBridgeResources = GetZX1BridgeResources; + + /* Set up our own fake bus to act as the root segment */ + zx1FakeBus.configMech = pBusInfo->configMech; + zx1FakeBus.numDevices = pBusInfo->numDevices; + zx1FakeBus.primary_bus = zx1_fakebus; + pciBusInfo[zx1_fakebus] = &zx1FakeBus; + + /* Add the fake bus' host bridge */ + if (++idx >= MAX_PCI_DEVICES) + FatalError("HP ZX1: No room for fake Host-to-PCI bridge\n"); + *ppPCI++ = zx1FakeBus.bridge = pPCI = xnfcalloc(1, sizeof(pciDevice)); + pPCI->tag = PCI_MAKE_TAG(zx1_fakebus, 0, 0); + pPCI->busnum = zx1_fakebus; + /* pPCI->devnum = pPCI->funcnum = 0; */ + pPCI->pci_device_vendor = DEVID(VENDOR_HP, CHIP_ZX1_SBA); + pPCI->pci_base_class = PCI_CLASS_BRIDGE; + /* pPCI->pci_sub_class = PCI_SUBCLASS_BRIDGE_HOST; */ + pPCI->fakeDevice = TRUE; + +#ifdef OLD_FORMAT + xf86MsgVerb(X_INFO, 2, "PCI: BusID 0x%.2x,0x%02x,0x%1x " + "ID 0x%04x,0x%04x Rev 0x%02x Class 0x%02x,0x%02x\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum, + pPCI->pci_vendor, pPCI->pci_device, pPCI->pci_rev_id, + pPCI->pci_base_class, pPCI->pci_sub_class); +#else + xf86MsgVerb(X_INFO, 2, "PCI: %.2x:%02x:%1x: chip %04x,%04x" + " card %04x,%04x rev %02x class %02x,%02x,%02x hdr %02x\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum, + pPCI->pci_vendor, pPCI->pci_device, + pPCI->pci_subsys_vendor, pPCI->pci_subsys_card, + pPCI->pci_rev_id, pPCI->pci_base_class, + pPCI->pci_sub_class, pPCI->pci_prog_if, + pPCI->pci_header_type); +#endif + + /* Add a fake PCI-to-PCI bridge to represent each active rope */ + for (i = 0; i < 8; i++) { + if ((zx1_ropemap[i] != i) || (zx1_busno[i] > zx1_subno[i]) || + !(pBusInfo = pciBusInfo[zx1_busno[i]])) + continue; + + if (++idx >= MAX_PCI_DEVICES) + FatalError("HP ZX1: No room for fake PCI-to-PCI bridge\n"); + *ppPCI++ = pPCI = xnfcalloc(1, sizeof(pciDevice)); + pPCI->busnum = zx1_fakebus; + pPCI->devnum = i | 0x10; + /* pPCI->funcnum = 0; */ + pPCI->tag = PCI_MAKE_TAG(zx1_fakebus, pPCI->devnum, 0); + pPCI->pci_device_vendor = zx1_pciids[i]; + pPCI->pci_base_class = PCI_CLASS_BRIDGE; + pPCI->pci_sub_class = PCI_SUBCLASS_BRIDGE_PCI; + pPCI->pci_header_type = 1; + pPCI->pci_primary_bus_number = zx1_fakebus; + pPCI->pci_secondary_bus_number = zx1_busno[i]; + pPCI->pci_subordinate_bus_number = zx1_subno[i]; + pPCI->fakeDevice = TRUE; + + pBusInfo->bridge = pPCI; + pBusInfo->secondary = TRUE; + pBusInfo->primary_bus = zx1_fakebus; + + /* Plug in chipset routines */ + pBusInfo->funcs = &zx1BusFuncs; + + /* Set bridge control register for scanpci utility */ + pPCI->pci_bridge_control = ControlZX1Bridge(zx1_busno[i], 0, 0); + +#ifdef OLD_FORMAT + xf86MsgVerb(X_INFO, 2, "PCI: BusID 0x%.2x,0x%02x,0x%1x " + "ID 0x%04x,0x%04x Rev 0x%02x Class 0x%02x,0x%02x\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum, + pPCI->pci_vendor, pPCI->pci_device, pPCI->pci_rev_id, + pPCI->pci_base_class, pPCI->pci_sub_class); +#else + xf86MsgVerb(X_INFO, 2, "PCI: %.2x:%02x:%1x: chip %04x,%04x" + " card %04x,%04x rev %02x class %02x,%02x,%02x hdr %02x\n", + pPCI->busnum, pPCI->devnum, pPCI->funcnum, + pPCI->pci_vendor, pPCI->pci_device, + pPCI->pci_subsys_vendor, pPCI->pci_subsys_card, + pPCI->pci_rev_id, pPCI->pci_base_class, + pPCI->pci_sub_class, pPCI->pci_prog_if, + pPCI->pci_header_type); +#endif + } + + *ppPCI = NULL; /* Terminate array */ +} diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.h b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.h new file mode 100644 index 000000000..2795b4459 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.h @@ -0,0 +1,40 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.h,v 1.1 2003/02/23 20:26:49 tsi Exp $ */ +/* + * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef PCI_ZX1_H +#define PCI_ZX1_H 1 + +#include <X11/Xdefs.h> + +void xf86PreScanZX1(void); +void xf86PostScanZX1(void); + +#endif |