diff options
Diffstat (limited to 'xorg-server/hw/xfree86/os-support/bus/linuxPci.c')
-rw-r--r-- | xorg-server/hw/xfree86/os-support/bus/linuxPci.c | 450 |
1 files changed, 0 insertions, 450 deletions
diff --git a/xorg-server/hw/xfree86/os-support/bus/linuxPci.c b/xorg-server/hw/xfree86/os-support/bus/linuxPci.c deleted file mode 100644 index 77f724bf1..000000000 --- a/xorg-server/hw/xfree86/os-support/bus/linuxPci.c +++ /dev/null @@ -1,450 +0,0 @@ -/*
- * Copyright 1998 by Concurrent Computer Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Concurrent Computer
- * Corporation not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Concurrent Computer Corporation makes no representations
- * about the suitability of this software for any purpose. It is
- * provided "as is" without express or implied warranty.
- *
- * CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
- * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Copyright 1998 by Metro Link Incorporated
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Metro Link
- * Incorporated not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Metro Link Incorporated makes no representations
- * about the suitability of this software for any purpose. It is
- * provided "as is" without express or implied warranty.
- *
- * METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
- * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <stdio.h>
-#include "xf86_OSlib.h"
-#include "Pci.h"
-
-static const struct pci_id_match match_host_bridge = {
- PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
- (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_HOST << 8),
- 0x0000ffff00, 0
-};
-
-#define MAX_DOMAINS 257
-static pointer DomainMmappedIO[MAX_DOMAINS];
-
-void
-linuxPciInit(void)
-{
- memset(DomainMmappedIO, 0, sizeof(DomainMmappedIO));
-}
-
-/**
- * \bug
- * The generation of the procfs file name for the domain != 0 case may not be
- * correct.
- */
-static int
-linuxPciOpenFile(struct pci_device *dev, Bool write)
-{
- static struct pci_device *last_dev = NULL;
- static int fd = -1,is_write = 0;
- char file[64];
- struct stat ignored;
- static int is26 = -1;
-
- if (dev == NULL) {
- return -1;
- }
-
- if (is26 == -1) {
- is26 = (stat("/sys/bus/pci", &ignored) < 0) ? 0 : 1;
- }
-
- if (fd == -1 || (write && (!is_write)) || (last_dev != dev)) {
- if (fd != -1) {
- close(fd);
- fd = -1;
- }
-
- if (is26) {
- sprintf(file,"/sys/bus/pci/devices/%04u:%02x:%02x.%01x/config",
- dev->domain, dev->bus, dev->dev, dev->func);
- } else {
- if (dev->domain == 0) {
- sprintf(file,"/proc/bus/pci/%02x", dev->bus);
- if (stat(file, &ignored) < 0) {
- sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x",
- dev->bus, dev->dev, dev->func);
- } else {
- sprintf(file, "/proc/bus/pci/%02x/%02x.%1x",
- dev->bus, dev->dev, dev->func);
- }
- } else {
- sprintf(file,"/proc/bus/pci/%02x%02x", dev->domain, dev->bus);
- if (stat(file, &ignored) < 0) {
- sprintf(file, "/proc/bus/pci/%04x:%04x/%02x.%1x",
- dev->domain, dev->bus, dev->dev, dev->func);
- } else {
- sprintf(file, "/proc/bus/pci/%02x%02x/%02x.%1x",
- dev->domain, dev->bus, dev->dev, dev->func);
- }
- }
- }
-
- if (write) {
- fd = open(file,O_RDWR);
- if (fd != -1) is_write = TRUE;
- } else {
- switch (is_write) {
- case TRUE:
- fd = open(file,O_RDWR);
- if (fd > -1)
- break;
- default:
- fd = open(file,O_RDONLY);
- is_write = FALSE;
- }
- }
-
- last_dev = dev;
- }
-
- return fd;
-}
-
-/*
- * 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 struct pci_device *
-get_parent_bridge(struct pci_device *dev)
-{
- struct pci_id_match bridge_match = {
- PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
- (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_PCI << 8),
- 0
- };
- struct pci_device *bridge;
- struct pci_device_iterator *iter;
-
- if (dev == NULL) {
- return NULL;
- }
-
- iter = pci_id_match_iterator_create(& bridge_match);
- if (iter == NULL) {
- return NULL;
- }
-
- while ((bridge = pci_device_next(iter)) != NULL) {
- if (bridge->domain == dev->domain) {
- const struct pci_bridge_info *info =
- pci_device_get_bridge_info(bridge);
-
- if (info != NULL) {
- if (info->secondary_bus == dev->bus) {
- break;
- }
- }
- }
- }
-
- pci_iterator_destroy(iter);
-
- return bridge;
-}
-
-/*
- * 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 const 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 const struct pciSizes *
-linuxGetSizesStruct(const struct pci_device *dev)
-{
- static const struct pciSizes default_size = {
- 0, 0, 1U << 16, (unsigned long)(1ULL << 32)
- };
- int i;
-
- /* Look up vendor/device */
- if (dev != NULL) {
- for (i = 0; i < NUM_SIZES; i++) {
- if ((dev->vendor_id == pciControllerSizes[i].vendor)
- && (dev->device_id == pciControllerSizes[i].device)) {
- return & pciControllerSizes[i];
- }
- }
- }
-
- /* Default to 64KB I/O and 4GB memory. */
- return & default_size;
-}
-
-static __inline__ unsigned long
-linuxGetIOSize(const struct pci_device *dev)
-{
- const struct pciSizes * const sizes = linuxGetSizesStruct(dev);
- return sizes->io_size;
-}
-
-static pointer
-linuxMapPci(int ScreenNum, int Flags, struct pci_device *dev,
- ADDRESS Base, unsigned long Size, int mmap_ioctl)
-{
- /* Align to page boundary */
- const ADDRESS realBase = Base & ~(getpagesize() - 1);
- const ADDRESS Offset = Base - realBase;
-
- do {
- unsigned char *result;
- int fd, mmapflags, prot;
-
- xf86InitVidMem();
-
- /* If dev is NULL, linuxPciOpenFile will return -1, and this routine
- * will fail gracefully.
- */
- prot = ((Flags & VIDMEM_READONLY) == 0);
- if (((fd = linuxPciOpenFile(dev, prot)) < 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__ */
-
-
- if (Flags & VIDMEM_READONLY)
- prot = PROT_READ;
- else
- prot = PROT_READ | PROT_WRITE;
-
- result = mmap(NULL, Size + Offset, prot, mmapflags, fd, realBase);
-
- if (!result || ((pointer)result == MAP_FAILED))
- return NULL;
-
- xf86MakeNewMapping(ScreenNum, Flags, realBase, Size + Offset, result);
-
- return result + Offset;
- } while (0);
-
- if (mmap_ioctl == PCIIOC_MMAP_IS_MEM)
- return xf86MapVidMem(ScreenNum, Flags, Base, Size);
-
- return NULL;
-}
-
-static int
-linuxOpenLegacy(struct pci_device *dev, char *name)
-{
- static const char PREFIX[] = "/sys/class/pci_bus/%04x:%02x/%s";
- char path[sizeof(PREFIX) + 10];
- int fd = -1;
-
- while (dev != NULL) {
- snprintf(path, sizeof(path) - 1, PREFIX, dev->domain, dev->bus, name);
- fd = open(path, O_RDWR);
- if (fd >= 0) {
- return fd;
- }
-
- dev = get_parent_bridge(dev);
- }
-
- return fd;
-}
-
-/*
- * xf86MapDomainMemory - memory map PCI domain memory
- *
- * This routine maps the memory region in the domain specified by Tag and
- * returns a pointer to it. The pointer is saved for future use if it's in
- * the legacy ISA memory space (memory in a domain between 0 and 1MB).
- */
-pointer
-xf86MapDomainMemory(int ScreenNum, int Flags, struct pci_device *dev,
- ADDRESS Base, unsigned long Size)
-{
- int fd = -1;
- pointer addr;
-
- /*
- * We use /proc/bus/pci on non-legacy addresses or if the Linux sysfs
- * legacy_mem interface is unavailable.
- */
- if ((Base > 1024*1024) || ((fd = linuxOpenLegacy(dev, "legacy_mem")) < 0))
- return linuxMapPci(ScreenNum, Flags, dev, Base, Size,
- PCIIOC_MMAP_IS_MEM);
- else
- addr = mmap(NULL, Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, Base);
-
- if (fd >= 0)
- close(fd);
- if (addr == NULL || addr == MAP_FAILED) {
- perror("mmap failure");
- FatalError("xf86MapDomainMem(): mmap() failure\n");
- }
- return addr;
-}
-
-/**
- * Map I/O space in this domain
- *
- * Each domain has a legacy ISA I/O space. This routine will try to
- * map it using the Linux sysfs legacy_io interface. If that fails,
- * it'll fall back to using /proc/bus/pci.
- *
- * If the legacy_io interface \b does exist, the file descriptor (\c fd below)
- * will be saved in the \c DomainMmappedIO array in the upper bits of the
- * pointer. Callers will do I/O with small port numbers (<64k values), so
- * the platform I/O code can extract the port number and the \c fd, \c lseek
- * to the port number in the legacy_io file, and issue the read or write.
- *
- * This has no means of returning failure, so all errors are fatal
- */
-IOADDRESS
-xf86MapLegacyIO(struct pci_device *dev)
-{
- const int domain = dev->domain;
- struct pci_device *bridge = get_parent_bridge(dev);
- int fd;
-
- if (domain >= MAX_DOMAINS)
- FatalError("xf86MapLegacyIO(): domain out of range\n");
-
- if (DomainMmappedIO[domain] == NULL) {
- /* Permanently map all of I/O space */
- fd = linuxOpenLegacy(bridge, "legacy_io");
- if (fd < 0) {
- DomainMmappedIO[domain] = linuxMapPci(-1, VIDMEM_MMIO, bridge,
- 0, linuxGetIOSize(bridge),
- PCIIOC_MMAP_IS_IO);
- }
- else { /* legacy_io file exists, encode fd */
- DomainMmappedIO[domain] = (pointer)(intptr_t)(fd << 24);
- }
- }
-
- return (IOADDRESS)DomainMmappedIO[domain];
-}
-
|