Apply this patch with `patch -R` to reverse altix support. diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h index 31b1ea3..aca7697 100644 --- a/hw/xfree86/common/compiler.h +++ b/hw/xfree86/common/compiler.h @@ -124,7 +124,8 @@ # if defined(NO_INLINE) || defined(DO_PR # if !defined(__arm__) # if !defined(__sparc__) && !defined(__arm32__) \ - && !(defined(__alpha__) && defined(linux)) + && !(defined(__alpha__) && defined(linux)) \ + && !(defined(__ia64__) && defined(linux)) \ extern void outb(unsigned short, unsigned char); extern void outw(unsigned short, unsigned short); @@ -162,7 +163,7 @@ # endif # ifndef NO_INLINE # ifdef __GNUC__ -# if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__alpha__) +# if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && (defined(__alpha__)) # ifdef linux /* for Linux on Alpha, we use the LIBC _inx/_outx routines */ @@ -494,11 +495,16 @@ # endif # undef outb # undef outw # undef outl +# undef inb +# undef inw +# undef inl +extern void outb(unsigned long port, unsigned char val); +extern void outw(unsigned long port, unsigned short val); +extern void outl(unsigned long port, unsigned int val); +extern unsigned int inb(unsigned long port); +extern unsigned int inw(unsigned long port); +extern unsigned int inl(unsigned long port); -# define outb(a,b) _outb(b,a) -# define outw(a,b) _outw(b,a) -# define outl(a,b) _outl(b,a) - # elif defined(linux) && defined(__amd64__) # include diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c index 7c3db02..9abd81e 100644 --- a/hw/xfree86/common/xf86Bus.c +++ b/hw/xfree86/common/xf86Bus.c @@ -1857,7 +1857,7 @@ xf86RegisterResources(int entityIndex, r range.type = (range.type & ~ResAccMask) | (access & ResAccMask); } range.type &= ~ResEstimated; /* Not allowed for drivers */ -#if !(defined(__alpha__) && defined(linux)) +#if !((defined(__alpha__) || (defined(__ia64__))) && defined(linux)) /* On Alpha Linux, do not check for conflicts, trust the kernel. */ if (checkConflict(&range, Acc, entityIndex, SETUP,TRUE)) res = xf86AddResToList(res,&range,entityIndex); @@ -2477,8 +2477,8 @@ #ifdef REDUCER #endif } xf86FreeResList(acc); - #if !(defined(__alpha__) && defined(linux)) && \ + !(defined(__ia64__) && defined(linux)) && \ !(defined(__sparc64__) && defined(__OpenBSD__)) /* * No need to validate on Alpha Linux or OpenBSD/sparc64, diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index b81c917..ee22056 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1621,10 +1621,12 @@ getValidBIOSBase(PCITAG tag, int num) m = m->next; } } else { +#if !defined(__ia64__) /* on ia64, trust the kernel, don't look for overlaps */ if (!xf86IsSubsetOf(range, m) || ChkConflict(&range, avoid, SETUP) || (mem && ChkConflict(&range, mem, SETUP))) ret = 0; +#endif } xf86FreeResList(avoid); diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c index ec04361..12c3a07 100644 --- a/hw/xfree86/loader/xf86sym.c +++ b/hw/xfree86/loader/xf86sym.c @@ -1093,12 +1093,12 @@ #if !defined(Lynx) #endif #endif #if defined(__ia64__) - SYMFUNC(_outw) - SYMFUNC(_outb) - SYMFUNC(_outl) - SYMFUNC(_inb) - SYMFUNC(_inw) - SYMFUNC(_inl) + SYMFUNC(outw) + SYMFUNC(outb) + SYMFUNC(outl) + SYMFUNC(inb) + SYMFUNC(inw) + SYMFUNC(inl) #endif #if defined(__arm__) SYMFUNC(outw) diff --git a/hw/xfree86/os-support/bus/Pci.h b/hw/xfree86/os-support/bus/Pci.h index 41ef3f8..4359a08 100644 --- a/hw/xfree86/os-support/bus/Pci.h +++ b/hw/xfree86/os-support/bus/Pci.h @@ -254,7 +254,6 @@ #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 diff --git a/hw/xfree86/os-support/bus/altixPCI.c b/hw/xfree86/os-support/bus/altixPCI.c new file mode 100644 index 0000000..c2c21d3 --- /dev/null +++ b/hw/xfree86/os-support/bus/altixPCI.c @@ -0,0 +1,116 @@ +/* + * This file contains the glue necessary for support of SGI's Altix chipset. + */ +#include +#include +#include "altixPCI.h" +#include "xf86.h" +#include "Pci.h" + +/* + * get_dev_on_bus - Return the first device we find on segnum, busnum + * + * Walk all the PCI devices and return the first one found on segnum, busnum. + * There may be a better way to do this in some xf86* function I don't know + * about. + */ +static pciDevice *get_dev_on_bus(unsigned int segnum, unsigned int busnum) +{ + pciDevice **pdev = xf86scanpci(0); + int i; + + for (i = 0; pdev[i] != NULL; i++) + if (PCI_DOM_FROM_TAG(pdev[i]->tag) == segnum && + pdev[i]->busnum == busnum) + return pdev[i]; + /* Should never get here... */ + ErrorF("No PCI device found on %04x:%02x??", segnum, busnum); + return NULL; +} + +/* + * get_bridge_info - fill in the bridge info for bus_info based on pdev + * + * Find the parent bus for pdev if it exists, otherwise assume pdev *is* + * the parent bus. We need this on Altix because our bridges are transparent. + */ +static void get_bridge_info(pciBusInfo_t *bus_info, pciDevice *pdev) +{ + unsigned int parent_segnum, segnum = PCI_DOM_FROM_TAG(pdev->tag); + unsigned int parent_busnum, busnum = pdev->busnum; + char bridge_path[] = "/sys/class/pci_bus/0000:00/bridge"; + char bridge_target[] = "../../../devices/pci0000:00"; + + /* Path to this device's bridge */ + sprintf(bridge_path, "/sys/class/pci_bus/%04x:%02x/bridge", segnum, + busnum); + + if (readlink(bridge_path, bridge_target, strlen(bridge_target)) < 0) { + perror("failed to dereference bridge link"); + ErrorF("failed to dereference bridge link, aborting\n"); + exit(-1); + } + + sscanf(bridge_target, "../../../devices/pci%04x:%02x", &parent_segnum, + &parent_busnum); + + /* + * If there's no bridge or the bridge points to the device, use + * pdev as the bridge + */ + if (segnum == parent_segnum && busnum == parent_busnum) { + bus_info->bridge = pdev; + bus_info->secondary = FALSE; + bus_info->primary_bus = busnum; + } else { + bus_info->bridge = get_dev_on_bus(parent_segnum, + parent_busnum); + bus_info->secondary = TRUE; + bus_info->primary_bus = parent_busnum; + } + pdev->businfo = bus_info; + pdev->pci_base_class = PCI_CLASS_DISPLAY; + pdev->pci_sub_class = PCI_SUBCLASS_PREHISTORIC_VGA; +} + +void xf86PreScanAltix(void) +{ + /* Nothing to see here... */ +} + +void xf86PostScanAltix(void) +{ + pciConfigPtr *pdev; + pciBusInfo_t *bus_info; + int prevBusNum, curBusNum, idx; + + /* + * Altix PCI bridges are invisible to userspace, so we make each device + * look like it's its own bridge unless it actually has a parent (as in + * the case of PCI to PCI bridges). + */ + bus_info = pciBusInfo[0]; + pdev = xf86scanpci(0); + prevBusNum = curBusNum = pdev[0]->busnum; + bus_info = pciBusInfo[curBusNum]; + bus_info->bridge = pdev[0]; + bus_info->secondary = FALSE; + bus_info->primary_bus = curBusNum; + + /* Walk all the PCI devices, assigning their bridge info */ + for (idx = 0; pdev[idx] != NULL; idx++) { + if (pdev[idx]->busnum == prevBusNum) + continue; /* Already fixed up this bus */ + + curBusNum = pdev[idx]->busnum; + bus_info = pciBusInfo[curBusNum]; + + /* + * Fill in bus_info for pdev. The bridge field will either + * be pdev[idx] or a device on the parent bus. + */ + get_bridge_info(bus_info, pdev[idx]); + prevBusNum = curBusNum; + } + return; +} diff --git a/hw/xfree86/os-support/bus/altixPCI.h b/hw/xfree86/os-support/bus/altixPCI.h new file mode 100644 index 0000000..1d449d5 --- /dev/null +++ b/hw/xfree86/os-support/bus/altixPCI.h @@ -0,0 +1,16 @@ +#ifndef PCI_ALTIX_H +#define PCI_ALTIX_H 1 + +#include +#include + +Bool xorgProbeAltix(scanpciWrapperOpt flags); +void xf86PreScanAltix(void); +void xf86PostScanAltix(void); + +/* Some defines for PCI */ +#define VENDOR_SGI 0x10A9 +#define CHIP_TIO_CA 0x1010 +#define CHIP_PIC_PCI 0x1011 + +#endif diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index 1f5e649..32e11e4 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -59,6 +59,7 @@ #include "Pci.h" static CARD32 linuxPciCfgRead(PCITAG tag, int off); static void linuxPciCfgWrite(PCITAG, int off, CARD32 val); static void linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits); +static ADDRESS linuxTransAddrBusToHost(PCITAG tag, PciAddrType type, ADDRESS addr); #if defined(__powerpc__) static ADDRESS linuxPpcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS); static ADDRESS linuxPpcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS); @@ -73,7 +74,7 @@ #if defined(__powerpc__) /* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr #else /* pciAddrHostToBus */ pciAddrNOOP, -/* pciAddrBusToHost */ pciAddrNOOP +/* pciAddrBusToHost */ linuxTransAddrBusToHost #endif }; @@ -201,6 +202,26 @@ linuxPciCfgSetBits(PCITAG tag, int off, } } +/* + * This function will convert a BAR address into a host address + * suitable for passing into the mmap function of a /proc/bus + * device. + */ +ADDRESS linuxTransAddrBusToHost(PCITAG tag, PciAddrType type, ADDRESS addr) +{ + ADDRESS ret = xf86GetOSOffsetFromPCI(tag, PCI_MEM|PCI_IO, addr); + + if (ret) + return ret; + + /* + * if it is not a BAR address, it must be legacy, (or wrong) + * return it as is.. + */ + return addr; +} + + #if defined(__powerpc__) #ifndef __NR_pciconfig_iobase @@ -402,6 +423,9 @@ xf86GetPciDomain(PCITAG Tag) if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) return result; + if (pPCI->fakeDevice) + return 1; /* Domain 0 is reserved */ + if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) return 0; @@ -442,7 +466,7 @@ # endif if (Flags & VIDMEM_FRAMEBUFFER) mmapflags = MAP_SHARED | MAP_WRITECOMBINED; else - mmapflags = MAP_SHARED | MAP_NONCACHED + mmapflags = MAP_SHARED | MAP_NONCACHED; #else /* !__ia64__ */ @@ -467,7 +491,7 @@ #endif /* ?__ia64__ */ 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); @@ -480,38 +504,142 @@ #endif /* ?__ia64__ */ return NULL; } +#define MAX_DOMAINS 257 +static pointer DomainMmappedIO[MAX_DOMAINS]; +static pointer DomainMmappedMem[MAX_DOMAINS]; + +static int +linuxOpenLegacy(PCITAG Tag, char *name) +{ +#define PREFIX "/sys/class/pci_bus/%04x:%02x/%s" + char *path; + int domain, bus; + pciBusInfo_t *pBusInfo; + pciConfigPtr bridge = NULL; + int fd; + + path = xalloc(strlen(PREFIX) + strlen(name)); + if (!path) + return -1; + + for (;;) { + domain = xf86GetPciDomain(Tag); + bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); + + /* Domain 0 is reserved -- see xf86GetPciDomain() */ + if ((domain <= 0) || (domain >= MAX_DOMAINS)) + FatalError("linuxOpenLegacy(): domain out of range\n"); + + sprintf(path, PREFIX, domain - 1, bus, name); + fd = open(path, O_RDWR); + if (fd >= 0) { + xfree(path); + return fd; + } + + pBusInfo = pciBusInfo[bus]; + if (!pBusInfo || (bridge == pBusInfo->bridge) || + !(bridge = pBusInfo->bridge)) { + xfree(path); + return -1; + } + + Tag = bridge->tag; + } + + xfree(path); + return fd; +} + +/* + * xf86MapDomainMemory - memory map PCI domain memory + * + * This routine maps the memory region in the domain specified by Tag and + * returns a pointer to it. The pointer is saved for future use if it's in + * the legacy ISA memory space (memory in a domain between 0 and 1MB). + */ pointer xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base, unsigned long Size) { - return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, PCIIOC_MMAP_IS_MEM); -} + int domain = xf86GetPciDomain(Tag); + int fd; + + /* + * We use /proc/bus/pci on non-legacy addresses or if the Linux sysfs + * legacy_mem interface is unavailable. + */ + if (Base > 1024*1024) + return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, + PCIIOC_MMAP_IS_MEM); + + if ((fd = linuxOpenLegacy(Tag, "legacy_mem")) < 0) + return linuxMapPci(ScreenNum, Flags, Tag, Base, Size, + PCIIOC_MMAP_IS_MEM); + + + /* If we haven't already mapped this legacy space, try to. */ + if (!DomainMmappedMem[domain]) { + DomainMmappedMem[domain] = mmap(NULL, 1024*1024, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0); + if (DomainMmappedMem[domain] == MAP_FAILED) { + close(fd); + perror("mmap failure"); + FatalError("xf86MapDomainMem(): mmap() failure\n"); + } + } -#define MAX_DOMAINS 257 -static pointer DomainMmappedIO[MAX_DOMAINS]; + close(fd); + return (pointer)((char *)DomainMmappedMem[domain] + Base); +} -/* This has no means of returning failure, so all errors are fatal */ +/* + * xf86MapDomainIO - map I/O space in this domain + * + * Each domain has a legacy ISA I/O space. This routine will try to + * map it using the Linux sysfs legacy_io interface. If that fails, + * it'll fall back to using /proc/bus/pci. + * + * If the legacy_io interface *does* exist, the file descriptor (fd below) + * will be saved in the DomainMmappedIO array in the upper bits of the + * pointer. Callers will do I/O with small port numbers (<64k values), so + * the platform I/O code can extract the port number and the fd, lseek to + * the port number in the legacy_io file, and issue the read or write. + * + * This has no means of returning failure, so all errors are fatal + */ IOADDRESS xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, IOADDRESS Base, unsigned long Size) { int domain = xf86GetPciDomain(Tag); + int fd; if ((domain <= 0) || (domain >= MAX_DOMAINS)) FatalError("xf86MapDomainIO(): domain out of range\n"); + if (DomainMmappedIO[domain]) + return (IOADDRESS)DomainMmappedIO[domain] + Base; + /* Permanently map all of I/O space */ - if (!DomainMmappedIO[domain]) { - DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag, - 0, linuxGetIOSize(Tag), - PCIIOC_MMAP_IS_IO); - if (!DomainMmappedIO[domain]) - FatalError("xf86MapDomainIO(): mmap() failure\n"); + if ((fd = linuxOpenLegacy(Tag, "legacy_io")) < 0) { + DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag, + 0, linuxGetIOSize(Tag), + PCIIOC_MMAP_IS_IO); + /* ia64 can't mmap legacy IO port space */ + if (!DomainMmappedIO[domain]) + return Base; + } + else { /* legacy_io file exists, encode fd */ + DomainMmappedIO[domain] = (pointer)(fd << 24); } return (IOADDRESS)DomainMmappedIO[domain] + Base; } +/* + * xf86ReadDomainMemory - copy from domain memory into a caller supplied buffer + */ int xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) { @@ -520,6 +648,40 @@ xf86ReadDomainMemory(PCITAG Tag, ADDRESS unsigned long size; int len, pagemask = getpagesize() - 1; + unsigned int i, dom, bus, dev, func; + unsigned int fd; + char file[256]; + struct stat st; + + dom = PCI_DOM_FROM_TAG(Tag); + bus = PCI_BUS_FROM_TAG(Tag); + dev = PCI_DEV_FROM_TAG(Tag); + func = PCI_FUNC_FROM_TAG(Tag); + sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", + dom, bus, dom, bus, dev, func); + + /* + * If the caller wants the ROM and the sysfs rom interface exists, + * try to use it instead of reading it from /proc/bus/pci. + */ + if (((Base & 0xfffff) == 0xC0000) && (stat(file, &st) == 0)) { + if ((fd = open(file, O_RDWR))) + Base = 0x0; + + /* enable the ROM first */ + write(fd, "1", 2); + lseek(fd, 0, SEEK_SET); + + /* copy the ROM until we hit Len, EOF or read error */ + for (i = 0; i < Len && read(fd, Buf, 1) > 0; Buf++, i++) + ; + + write(fd, "0", 2); + close(fd); + + return Len; + } + /* Ensure page boundaries */ offset = Base & ~pagemask; size = ((Base + Len + pagemask) & ~pagemask) - offset; diff --git a/hw/xfree86/os-support/linux/lnx_ia64.c b/hw/xfree86/os-support/linux/lnx_ia64.c index 8d0976a..06f2be7 100644 --- a/hw/xfree86/os-support/linux/lnx_ia64.c +++ b/hw/xfree86/os-support/linux/lnx_ia64.c @@ -26,6 +26,7 @@ #include #include +#include #include #include "ia64Pci.h" @@ -35,11 +36,24 @@ #if defined OS_PROBE_PCI_CHIPSET IA64Chipset OS_PROBE_PCI_CHIPSET(scanpciWrapperOpt flags) { struct stat unused; + struct utsname utsName; if (!stat("/proc/bus/mckinley/zx1",&unused) || !stat("/proc/bus/mckinley/zx2",&unused)) return ZX1_CHIPSET; + if (!stat("/proc/sgi_sn/licenseID", &unused)) { + /* + * We need a 2.6.11 or better kernel for Altix support + */ + uname(&utsName); + if (!strstr(utsName.release, "2.6.11")) { + ErrorF("Kernel 2.6.11 or better needed for Altix support\n"); + return NONE_CHIPSET; + } + return ALTIX_CHIPSET; + } + return NONE_CHIPSET; } #endif diff --git a/hw/xfree86/os-support/linux/lnx_pci.c b/hw/xfree86/os-support/linux/lnx_pci.c index 074a9d7..25404b0 100644 --- a/hw/xfree86/os-support/linux/lnx_pci.c +++ b/hw/xfree86/os-support/linux/lnx_pci.c @@ -83,3 +83,141 @@ xf86GetPciSizeFromOS(PCITAG tag, int ind fclose(file); return FALSE; } + + + +/* Query the kvirt address (64bit) of a BAR range from TAG */ +Bool +xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases) +{ + FILE *file; + char c[0x200]; + char *res; + unsigned int bus, devfn, dev, fn; + unsigned PCIADDR_TYPE offset[7]; + unsigned int num; + + if (index > 7) + return FALSE; + + if (!(file = fopen("/proc/bus/pci/devices","r"))) + return FALSE; + do { + res = fgets(c,0x1ff,file); + if (res) { + num = sscanf(res, + /*bus+dev vendorid deviceid irq */ + "%02x%02x\t%*04x%*04x\t%*x" + /* 7 PCI resource base addresses */ + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + /* 7 PCI resource sizes, and then optionally a driver name */ + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT + "\t" PCIADDR_IGNORE_FMT, + &bus,&devfn,&offset[0],&offset[1],&offset[2],&offset[3], + &offset[4],&offset[5],&offset[6]); + if (num != 9) { /* apparantly not 2.3 style */ + fclose(file); + return FALSE; + } + + dev = devfn >> 3; + fn = devfn & 0x7; + if (tag == pciTag(bus,dev,fn)) { + /* return the offset for the index requested */ + *bases = offset[index]; + fclose(file); + return TRUE; + } + } + } while (res); + + fclose(file); + return FALSE; +} + +/* Query the kvirt address (64bit) of a BAR range from size for a given TAG */ +unsigned long +xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base) +{ + FILE *file; + char c[0x200]; + char *res; + unsigned int bus, devfn, dev, fn; + unsigned PCIADDR_TYPE offset[7]; + unsigned PCIADDR_TYPE size[7]; + unsigned int num; + unsigned int ndx; + + if (!(file = fopen("/proc/bus/pci/devices","r"))) + return NULL; + do { + res = fgets(c,0x1ff,file); + if (res) { + num = sscanf(res, + /*bus+dev vendorid deviceid irq */ + "%02x%02x\t%*04x%*04x\t%*x" + /* 7 PCI resource base addresses */ + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + /* 7 PCI resource sizes, and then optionally a driver name */ + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT + "\t" PCIADDR_FMT, + &bus,&devfn,&offset[0],&offset[1],&offset[2],&offset[3], + &offset[4],&offset[5],&offset[6], &size[0], &size[1], &size[2], + &size[3], &size[4], &size[5], &size[6]); + if (num != 16) { /* apparantly not 2.3 style */ + fclose(file); + return NULL; + } + + dev = devfn >> 3; + fn = devfn & 0x7; + if (tag == pciTag(bus,dev,fn)) { + /* ok now look through all the BAR values of this device */ + for (ndx=0; ndx<7; ndx++) { + unsigned long savePtr; + /* + * remember to lop of the last 4bits of the BAR values as they are + * memory attributes + */ + if (ndx == 6) + savePtr = (0xFFFFFFF0) & + pciReadLong(tag, PCI_CMD_BIOS_REG); + else /* this the ROM bar */ + savePtr = (0xFFFFFFF0) & + pciReadLong(tag, PCI_CMD_BASE_REG + (0x4 * ndx)); + /* find the index of the incoming base */ + if (base >= savePtr && base <= (savePtr + size[ndx])) { + fclose(file); + return ( ~(0xFUL) & (offset[ndx] + (base - savePtr))); + } + } + } + } + } while (res); + + fclose(file); + return NULL; + +} diff --git a/hw/xfree86/os-support/shared/ia64Pci.c b/hw/xfree86/os-support/shared/ia64Pci.c index d0046a7..30a0622 100644 --- a/hw/xfree86/os-support/shared/ia64Pci.c +++ b/hw/xfree86/os-support/shared/ia64Pci.c @@ -29,12 +29,165 @@ * This file contains the glue needed to support various IA-64 chipsets. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compiler.h" #include "460gxPCI.h" #include "e8870PCI.h" #include "zx1PCI.h" +#include "altixPCI.h" #include "Pci.h" #include "ia64Pci.h" +/* + * We use special in/out routines here since Altix platforms require the + * use of the sysfs legacy_io interface. The legacy_io file maps to the I/O + * space of a given PCI domain; reads and writes are used to do port I/O. + * The file descriptor for the file is stored in the upper bits of the + * value passed in by the caller, and is created and populated by + * xf86MapDomainIO. + * + * If the legacy_io interface doesn't exist, we fall back to the glibc in/out + * routines, which are prefixed by an underscore (e.g. _outb). + */ +static int ia64_port_to_fd(unsigned long port) +{ + return (port >> 24) & 0xffffffff; +} + +void outb(unsigned long port, unsigned char val) +{ + int fd = ia64_port_to_fd(port); + + if (!fd) { + _outb(val, port & 0xffff); + goto out; + } + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + goto out; + } + if (write(fd, &val, 1) != 1) { + ErrorF("I/O write failed\n"); + goto out; + } + out: + return; +} + +void outw(unsigned long port, unsigned short val) +{ + int fd = ia64_port_to_fd(port); + + if (!fd) { + _outw(val, port & 0xffff); + goto out; + } + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + goto out; + } + if (write(fd, &val, 2) != 2) { + ErrorF("I/O write failed\n"); + goto out; + } + out: + return; +} + +void outl(unsigned long port, unsigned int val) +{ + int fd = ia64_port_to_fd(port); + + if (!fd) { + _outl(val, port & 0xffff); + goto out; + } + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + goto out; + } + if (write(fd, &val, 4) != 4) { + ErrorF("I/O write failed\n"); + goto out; + } + out: + return; +} + +unsigned int inb(unsigned long port) +{ + int fd = ia64_port_to_fd(port); + unsigned char val; + + if (!fd) + return _inb(port & 0xffff); + + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + val = -1; + goto out; + } + if (read(fd, &val, 1) != 1) { + ErrorF("I/O read failed\n"); + val = -1; + goto out; + } + out: + return val; +} + +unsigned int inw(unsigned long port) +{ + int fd = ia64_port_to_fd(port); + unsigned short val; + + if (!fd) + return _inw(port & 0xffff); + + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + val = -1; + goto out; + } + if (read(fd, &val, 2) != 2) { + ErrorF("I/O read failed\n"); + val = -1; + goto out; + } + out: + return val; +} + +unsigned int inl(unsigned long port) +{ + int fd = ia64_port_to_fd(port); + unsigned int val; + + if (!fd) + return _inl(port & 0xffff); + + if (lseek(fd, port & 0xffff, SEEK_SET) == -1) { + ErrorF("I/O lseek failed\n"); + val = -1; + goto out; + } + if (read(fd, &val, 4) != 4) { + ErrorF("I/O read failed\n"); + val = -1; + goto out; + } + out: + return val; +} + void ia64ScanPCIWrapper(scanpciWrapperOpt flags) { @@ -58,6 +211,9 @@ #ifdef OS_PROBE_PCI_CHIPSET case ZX1_CHIPSET: xf86PreScanZX1(); return; + case ALTIX_CHIPSET: + xf86PreScanAltix(); + return; default: return; } @@ -74,6 +230,9 @@ #endif case ZX1_CHIPSET: xf86PostScanZX1(); return; + case ALTIX_CHIPSET: + xf86PostScanAltix(); + return; default: return; } diff --git a/hw/xfree86/os-support/shared/ia64Pci.h b/hw/xfree86/os-support/shared/ia64Pci.h index 1ee2fc0..bc4777d 100644 --- a/hw/xfree86/os-support/shared/ia64Pci.h +++ b/hw/xfree86/os-support/shared/ia64Pci.h @@ -32,7 +32,8 @@ typedef enum { NONE_CHIPSET, I460GX_CHIPSET, E8870_CHIPSET, - ZX1_CHIPSET + ZX1_CHIPSET, + ALTIX_CHIPSET } IA64Chipset; # ifdef OS_PROBE_PCI_CHIPSET diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h index 688f647..f50c00e 100644 --- a/hw/xfree86/os-support/xf86_OSproc.h +++ b/hw/xfree86/os-support/xf86_OSproc.h @@ -256,6 +256,8 @@ resPtr xf86AccResFromOS(resPtr ret); #endif /* NEED_OS_RAC_PROTOS */ extern Bool xf86GetPciSizeFromOS(PCITAG tag, int indx, int* bits); +extern Bool xf86GetPciOffsetFromOS(PCITAG tag, int indx, unsigned long* bases); +extern unsigned long xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base); extern void xf86MakeNewMapping(int, int, unsigned long, unsigned long, pointer); extern void xf86InitVidMem(void);