diff -u -r build-sgi/xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c build4/xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c --- build-sgi/xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2005-04-15 09:23:03.207875963 -0600 +++ build4/xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2005-04-15 09:30:50.700057736 -0600 @@ -422,7 +422,7 @@ result = mmap(NULL, Size + Offset, prot, mmapflags, fd, realBase); if (!result || ((pointer)result == MAP_FAILED)) - FatalError("linuxMapPci() mmap failure: %s\n", strerror(errno)); + return NULL; xf86MakeNewMapping(ScreenNum, Flags, realBase, Size + Offset, result); @@ -439,51 +439,74 @@ static pointer DomainMmappedIO[MAX_DOMAINS]; static pointer DomainMmappedMem[MAX_DOMAINS]; +static int +linuxOpenLegacy(PCITAG Tag, char *name) +{ +#define PREFIX "/sys/class/pci_bus/%04x:%02x/%s" + char *path; + int domain, bus; + pciBusInfo_t *pBusInfo; + pciConfigPtr bridge; + int fd; + + path = xalloc(strlen(PREFIX) + strlen(name)); + if (!path) + return -1; + + for (;;) { + domain = xf86GetPciDomain(Tag); + bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); + + /* Domain 0 is reserved -- see xf86GetPciDomain() */ + if ((domain <= 0) || (domain >= MAX_DOMAINS)) + FatalError("linuxOpenLegacy(): domain out of range\n"); + + sprintf(path, PREFIX, domain - 1, bus, name); + fd = open(path, O_RDWR); + if (fd >= 0) { + xfree(path); + return fd; + } + + pBusInfo = pciBusInfo[bus]; + if (!pBusInfo || (bridge == pBusInfo->bridge) || + !(bridge = pBusInfo->bridge)) { + xfree(path); + return -1; + } + + Tag = bridge->tag; + } + + xfree(path); + return fd; +} + pointer xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base, unsigned long Size) { - char path[38]; /* /sys/class/pci_bus/DDDD:BB/legacy_mem */ int domain = xf86GetPciDomain(Tag); - int bus = PCI_BUS_FROM_TAG(Tag); int fd; - struct stat st; - /* - * If we are running a new enough linux kernel (2.6.11+) - * then we can open the legacy space through the /sys interface - * this allows us to open the device and use a read/write/seek - * interface to read/write bytes into legacy space. - * - * We will use this interface for accesses to IO mapped regions - * on the graphics card and all vga accesses - */ - - /* Hack, need to deal with domains correctly */ - sprintf(path, "/sys/class/pci_bus/%04x:%02x/legacy_mem", 0, bus); - /* * if the /sys/...../legacy_mem structure is not supported in the * running linux kernel, switch to the previous method */ if ((Base > 1024*1024 /* 1MB since that is legacy space*/) || - (stat(path, &st) < 0)) + (fd = linuxOpenLegacy(Tag, "legacy_mem")) < 0) return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, PCIIOC_MMAP_IS_MEM); - if ((domain <= 0) || (domain >= MAX_DOMAINS)) - FatalError("xf86MapDomainMem(): domain out of range\n"); - /* Permanently map all of memory space */ if (!DomainMmappedMem[domain]) { - fd = open(path, O_RDWR); DomainMmappedMem[domain] = mmap(0, 1024*1024 /* 1MB, all of legacy space */, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - close(fd); if (!DomainMmappedMem[domain]) FatalError("xf86MapDomainMem(): mmap() failure\n"); } + close(fd); return (pointer)((char *)DomainMmappedMem[domain] + Base); } @@ -492,23 +515,24 @@ xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, IOADDRESS Base, unsigned long Size) { - char path[37]; /* /sys/class/pci_bus/DDDD:BB/legacy_io */ int domain = xf86GetPciDomain(Tag); - int bus = PCI_BUS_FROM_TAG(Tag); int fd; if ((domain <= 0) || (domain >= MAX_DOMAINS)) FatalError("xf86MapDomainIO(): domain out of range\n"); - /* Hack, need to deal with domains properly */ - sprintf(path, "/sys/class/pci_bus/%04x:%02x/legacy_io", 0, bus); - /* Permanently map all of I/O space */ if (!DomainMmappedIO[domain]) { - fd = open(path, O_RDWR); - if (fd == -1) - FatalError("xf86MapDomainIO(): open() failure\n"); - DomainMmappedIO[domain] = fd << 24; /* encode fd in address */ + if ((fd = linuxOpenLegacy(Tag, "legacy_io")) >= 0) { + DomainMmappedIO[domain] = fd << 24; /* encode fd in address */ + } else { + DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag, + 0, linuxGetIOSize(Tag), + PCIIOC_MMAP_IS_IO); + /* ia64 can't mmap legacy IO port space */ + if (!DomainMmappedIO[domain]) + return Base; + } } return (IOADDRESS)DomainMmappedIO[domain] + Base;