xserver/hw/xorg/os-support/bus Makefile.am, NONE, 1.1 Pci.c, NONE, 1.1 Pci.h, NONE, 1.1 Sbus.c, NONE, 1.1 freebsdPci.c, NONE, 1.1 ix86Pci.c, NONE, 1.1 linuxPci.c, NONE, 1.1 netbsdPci.c, NONE, 1.1 xf86Pci.h, NONE, 1.1 xf86Sbus.h, NONE, 1.1

Daniel Stone xserver-commit at pdx.freedesktop.org
Sun Apr 25 23:52:19 EST 2004


Committed by: daniel

Update of /cvs/xserver/xserver/hw/xorg/os-support/bus
In directory pdx:/tmp/cvs-serv17025/hw/xorg/os-support/bus

Added Files:
	Makefile.am Pci.c Pci.h Sbus.c freebsdPci.c ix86Pci.c 
	linuxPci.c netbsdPci.c xf86Pci.h xf86Sbus.h 
Log Message:
Xizzle is dead, long live Xorg.

Re-import the DDX from X11R6.7, complete with automakey goodness, and do the
requisite configure.ac, et al, updates; also import the XKB extension from the
6.7 DIX.

Currently it'll link and then hang solid in RADEONInitAccel(), or the next
function if you enable NoAccel.


--- NEW FILE: Makefile.am ---
lib_LIBRARIES = libxorgbus.a
ARCH_SOURCES = 
if XORG_BUS_SBUS
	ARCH_SOURCES = Sbus.c
endif
PCI_SOURCES = $(XORG_OS)Pci.c ix86Pci.c
libxorgbus_a_SOURCES = Pci.c $(PCI_SOURCES) $(ARCH_SOURCES)
INCLUDES = $(XORG_INCS)
AM_CFLAGS = $(XORG_CFLAGS)

--- NEW FILE: Pci.c ---
/* $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
[...1439 lines suppressed...]
    /* 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 */

--- NEW FILE: Pci.h ---
/* $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 at 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.
 */
#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 64	/* 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))
#else
#define PCI_CPU(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
#  define INCLUDE_XF86_NO_DOMAIN
# 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__)
# 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(__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__)
# 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__)
# 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 *);
} 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 */

--- NEW FILE: Sbus.c ---
/*
 * SBUS and OpenPROM access functions.
 *
 * Copyright (C) 2000 Jakub Jelinek (jakub at 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 $ */

#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);
}

--- NEW FILE: freebsdPci.c ---
/* $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.
 */

#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);
}

--- NEW FILE: ix86Pci.c ---
/* $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 at 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 at 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).
 */

#include <stdio.h>
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.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 PCIProbe1: /* { */

      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: /* { */

      /* 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:

      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:

      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 PCIOsConfig:
	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;
    }
}

--- NEW FILE: linuxPci.c ---
/* $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.
 */

#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 pciBusFuncs_t linuxFuncs0 = {
/* pciReadLong      */	linuxPciCfgRead,
/* pciWriteLong     */	linuxPciCfgWrite,
/* pciSetBitsLong   */	linuxPciCfgSetBits,
/* pciAddrHostToBus */	pciAddrNOOP,
/* pciAddrBusToHost */	pciAddrNOOP
};

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)
{
	static int	lbus,ldev,lfunc,fd = -1;
	int		bus, dev, func;
	char		file[32];

	bus  = PCI_BUS_FROM_TAG(tag);
	dev  = PCI_DEV_FROM_TAG(tag);
	func = PCI_FUNC_FROM_TAG(tag);
	if (fd == -1 || bus != lbus || dev != ldev || func != lfunc) {
		if (fd != -1)
			close(fd);
		if (bus < 256)
			sprintf(file, "/proc/bus/pci/%02x/%02x.%1x",
				bus, dev, func);
		else
			sprintf(file, "/proc/bus/pci/%04x/%02x.%1x",
				bus, dev, func);
		fd = open(file,O_RDWR);
		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))) {
		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))) {
		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))) {
		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);
	}
}

#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 ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0)) < 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)) < 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))
	    FatalError("linuxMapPci() mmap failure:  %s\n", strerror(errno));

	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;
}

pointer
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
		    ADDRESS Base, unsigned long Size)
{
    return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, PCIIOC_MMAP_IS_MEM);
}

#define MAX_DOMAINS 257
static pointer DomainMmappedIO[MAX_DOMAINS];

/* 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);

    if ((domain <= 0) || (domain >= MAX_DOMAINS))
	FatalError("xf86MapDomainIO():  domain out of range\n");

    /* Permanently map all of I/O space */
    if (!DomainMmappedIO[domain]) {
	DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag,
					      0, linuxGetIOSize(Tag),
					      PCIIOC_MMAP_IS_IO);
	if (!DomainMmappedIO[domain])
	    FatalError("xf86MapDomainIO():  mmap() failure\n");
    }

    return (IOADDRESS)DomainMmappedIO[domain] + Base;
}

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;

    /* 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 */

--- NEW FILE: netbsdPci.c ---
/* $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.
 */

#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);
}

--- NEW FILE: xf86Pci.h ---
/* $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 at 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_MASK) == 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 */

--- NEW FILE: xf86Sbus.h ---
/*
 * Platform specific SBUS and OpenPROM access declarations.
 *
 * Copyright (C) 2000 Jakub Jelinek (jakub at 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 $ */

#ifndef _XF86_SBUS_H
#define _XF86_SBUS_H

#if defined(linux)
#include <asm/types.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 */




More information about the xserver-commit mailing list