From 84b35d18d0b84909f7216fc6a7487ffa72bd3f18 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 24 Sep 2010 10:10:29 +0000 Subject: xserver xkbcomp libxcb pixman git update 24/9/2010 --- xorg-server/hw/xfree86/os-support/bus/Makefile.am | 51 +- xorg-server/hw/xfree86/os-support/bus/Pci.c | 11 - xorg-server/hw/xfree86/os-support/bus/Pci.h | 5 - xorg-server/hw/xfree86/os-support/bus/linuxPci.c | 904 ++++++++++----------- .../hw/xfree86/os-support/linux/lnx_video.c | 5 +- 5 files changed, 478 insertions(+), 498 deletions(-) (limited to 'xorg-server/hw/xfree86/os-support') diff --git a/xorg-server/hw/xfree86/os-support/bus/Makefile.am b/xorg-server/hw/xfree86/os-support/bus/Makefile.am index 92a519bcc..41d8875fb 100644 --- a/xorg-server/hw/xfree86/os-support/bus/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/bus/Makefile.am @@ -1,26 +1,25 @@ -noinst_LTLIBRARIES = libbus.la -sdk_HEADERS = xf86Pci.h - -PCI_SOURCES = - -if XORG_BUS_LINUXPCI -PCI_SOURCES += linuxPci.c -endif - -if XORG_BUS_BSDPCI -PCI_SOURCES += bsd_pci.c -endif - -if XORG_BUS_SPARC -PLATFORM_SOURCES = Sbus.c -sdk_HEADERS += xf86Sbus.h -endif - -libbus_la_SOURCES = Pci.c Pci.h $(PCI_SOURCES) $(PLATFORM_PCI_SOURCES) \ - $(PLATFORM_SOURCES) - -INCLUDES = $(XORG_INCS) - -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) - -EXTRA_DIST = $(sdk_HEADERS) +noinst_LTLIBRARIES = libbus.la +sdk_HEADERS = xf86Pci.h + +PCI_SOURCES = Pci.c Pci.h + +if XORG_BUS_LINUXPCI +PCI_SOURCES += linuxPci.c +endif + +if XORG_BUS_BSDPCI +PCI_SOURCES += bsd_pci.c +endif + +if XORG_BUS_SPARC +PLATFORM_SOURCES = Sbus.c +sdk_HEADERS += xf86Sbus.h +endif + +libbus_la_SOURCES = $(PCI_SOURCES) $(PLATFORM_SOURCES) + +INCLUDES = $(XORG_INCS) + +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) + +EXTRA_DIST = $(sdk_HEADERS) diff --git a/xorg-server/hw/xfree86/os-support/bus/Pci.c b/xorg-server/hw/xfree86/os-support/bus/Pci.c index 7151cc885..8da149d16 100644 --- a/xorg-server/hw/xfree86/os-support/bus/Pci.c +++ b/xorg-server/hw/xfree86/os-support/bus/Pci.c @@ -124,19 +124,8 @@ #include #endif -#include -#include -#include "compiler.h" -#include "xf86.h" -#include "xf86Priv.h" -#define XF86_OS_PRIVS -#include "xf86_OSproc.h" #include "Pci.h" -#include - -/* Global data */ - PCITAG pciTag(int busnum, int devnum, int funcnum) { diff --git a/xorg-server/hw/xfree86/os-support/bus/Pci.h b/xorg-server/hw/xfree86/os-support/bus/Pci.h index 618dd3783..fb0ad41f6 100644 --- a/xorg-server/hw/xfree86/os-support/bus/Pci.h +++ b/xorg-server/hw/xfree86/os-support/bus/Pci.h @@ -133,11 +133,6 @@ #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_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) diff --git a/xorg-server/hw/xfree86/os-support/bus/linuxPci.c b/xorg-server/hw/xfree86/os-support/bus/linuxPci.c index 289315ebc..77f724bf1 100644 --- a/xorg-server/hw/xfree86/os-support/bus/linuxPci.c +++ b/xorg-server/hw/xfree86/os-support/bus/linuxPci.c @@ -1,454 +1,450 @@ -/* - * 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 -#endif - -#include -#include "compiler.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "Pci.h" -#include - -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 . - * 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 - -#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]; -} - +/* + * 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 +#endif + +#include +#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 . + * 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 + +#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]; +} + diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c index a515b4080..8aa2506a9 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c @@ -61,6 +61,7 @@ static Bool ExtendedEnabled = FALSE; !defined(__mc68000__) && \ !defined(__sparc__) && \ !defined(__mips__) && \ + !defined(__nds32__) && \ !defined(__arm__) /* @@ -519,7 +520,7 @@ xf86EnableIO(void) #endif } close(fd); -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) && !defined(__nds32__) if (ioperm(0, 1024, 1) || iopl(3)) { if (errno == ENODEV) ErrorF("xf86EnableIOPorts: no I/O ports found\n"); @@ -546,7 +547,7 @@ xf86DisableIO(void) #if defined(__powerpc__) munmap(ioBase, 0x20000); ioBase = NULL; -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) && !defined(__nds32__) iopl(0); ioperm(0, 1024, 0); #endif -- cgit v1.2.3