programs/Xserver/hw/xfree86/int10/helper_exec.c | 4 programs/Xserver/hw/xfree86/os-support/bus/Pci.c | 10 + programs/Xserver/hw/xfree86/os-support/bus/Pci.h | 4 programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c | 9 - programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c | 136 +++++++++++++++-- programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h | 2 programs/Xserver/hw/xfree86/os-support/linux/lnx_pci.c | 81 +++++++++- 7 files changed, 220 insertions(+), 26 deletions(-) Index: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.h =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/bus/Pci.h 2005-11-09 14:13:04.587891937 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.h 2005-11-09 14:13:12.670780649 -0600 @@ -120,7 +120,7 @@ /* by xf86scanpci */ #if defined(sun) && defined(SVR4) && defined(sparc) # define MAX_PCI_BUSES 4096 /* Max number of PCI buses */ -#elif defined(__alpha__) && defined (linux) +#elif (defined(__alpha__) || defined(__ia64__)) && defined (linux) # define MAX_PCI_DOMAINS 512 # define PCI_DOM_MASK 0x01fful # define MAX_PCI_BUSES (MAX_PCI_DOMAINS*256) /* 256 per domain */ @@ -259,7 +259,7 @@ # endif #elif defined(__ia64__) # if defined(linux) -# define ARCH_PCI_INIT linuxPciInit +# define ARCH_PCI_INIT ia64linuxPciInit # define INCLUDE_XF86_MAP_PCI_MEM # elif defined(FreeBSD) # define ARCH_PCI_INIT freebsdPciInit Index: xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2005-11-09 14:13:04.599609099 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2005-11-09 17:32:12.212553207 -0600 @@ -55,6 +55,7 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" #include "Pci.h" +#include /* * linux platform specific PCI access functions -- using /proc/bus/pci @@ -130,34 +131,37 @@ static int linuxPciOpenFile(PCITAG tag, Bool write) { - static int lbus,ldev,lfunc,fd = -1,is_write = 0; - int bus, dev, func; + static int ldomain, lbus,ldev,lfunc,fd = -1,is_write = 0; + int domain, bus, dev, func; char file[32]; struct stat ignored; - bus = PCI_BUS_FROM_TAG(tag); + domain = PCI_DOM_FROM_TAG(tag); + bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)); dev = PCI_DEV_FROM_TAG(tag); func = PCI_FUNC_FROM_TAG(tag); - if (fd == -1 || (write && (!is_write)) - || bus != lbus || dev != ldev || func != lfunc) { + + if (fd == -1 || (write && (!is_write)) || bus != lbus + || dev != ldev || func != lfunc || domain != ldomain) { + if (fd != -1) close(fd); if (bus < 256) { - sprintf(file,"/proc/bus/pci/%02x",bus); + sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus); if (stat(file, &ignored) < 0) - sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x", - bus, dev, func); - else sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", bus, dev, func); + else + sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x", + domain, bus, dev, func); } else { - sprintf(file,"/proc/bus/pci/%04x",bus); + sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus); if (stat(file, &ignored) < 0) - sprintf(file, "/proc/bus/pci/0000:%04x/%02x.%1x", - bus, dev, func); - else sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", bus, dev, func); + else + sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x", + domain, bus, dev, func); } if (write) { fd = open(file,O_RDWR); @@ -171,7 +175,8 @@ fd = open(file,O_RDONLY); is_write = FALSE; } - + + ldomain = domain; lbus = bus; ldev = dev; lfunc = func; @@ -600,7 +605,7 @@ if ((domain <= 0) || (domain >= MAX_DOMAINS)) FatalError("linuxOpenLegacy(): domain out of range\n"); - sprintf(path, PREFIX, domain - 1, bus, name); + sprintf(path, PREFIX, domain, bus, name); fd = open(path, O_RDWR); if (fd >= 0) { xfree(path); @@ -724,7 +729,7 @@ struct stat st; dom = PCI_DOM_FROM_TAG(Tag); - bus = PCI_BUS_FROM_TAG(Tag); + bus = PCI_BUS_NO_DOMAIN(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", @@ -892,3 +897,112 @@ } #endif /* !INCLUDE_XF86_NO_DOMAIN */ + +#ifdef __ia64__ +static PCITAG ia64linuxPciFindFirst(void); +static PCITAG ia64linuxPciFindNext(void); + + +void +ia64linuxPciInit() +{ + struct stat st; + /* Be a little paranoid here and only use this code for Altix systems. + * It is generic, so it should work on any system, but depends on + * /proc/bus/pci entries for each domain/bus combination. Altix is + * guaranteed a recent enough kernel to have them. + */ + if (stat("/proc/sgi_sn/licenseID", &st)) { + return linuxPciInit(); + } + 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 = ia64linuxPciFindFirst; + pciFindNextFP = ia64linuxPciFindNext; +} + +static DIR *busdomdir; +static DIR *devdir; + +static PCITAG +ia64linuxPciFindFirst(void) +{ + busdomdir = opendir("/proc/bus/pci"); + devdir = NULL; + + return ia64linuxPciFindNext(); +} + +static struct dirent *getnextbus(int *domain, int *bus) +{ + struct dirent *entry; + int dombus; + + for (;;) { + entry = readdir(busdomdir); + if (entry == NULL) { + *domain = 0; + *bus = 0; + closedir(busdomdir); + return NULL; + } + if (sscanf(entry->d_name, "%04x:%02x", domain, bus) != 2) + continue; + dombus = PCI_MAKE_BUS(*domain, *bus); + + if (pciNumBuses <= dombus) + pciNumBuses = dombus + 1; + if (!pciBusInfo[dombus]) { + pciBusInfo[dombus] = xnfalloc(sizeof(pciBusInfo_t)); + *pciBusInfo[dombus] = *pciBusInfo[0]; + } + + return entry; + } +} + +static PCITAG +ia64linuxPciFindNext(void) +{ + struct dirent *entry; + char file[40]; + static int bus, dev, func, domain; + PCITAG pciDeviceTag; + CARD32 devid; + + for (;;) { + if (devdir == NULL) { + entry = getnextbus(&domain, &bus); + if (!entry) + return PCI_NOT_FOUND; + snprintf(file, 40, "/proc/bus/pci/%s", entry->d_name); + devdir = opendir(file); + if (!devdir) + return PCI_NOT_FOUND; + + } + + entry = readdir(devdir); + + if (entry == NULL) { + closedir(devdir); + devdir = NULL; + continue; + } + + if (sscanf(entry->d_name, "%02x . %01x", &dev, &func) == 2) { + pciDeviceTag = PCI_MAKE_TAG(PCI_MAKE_BUS(domain, bus), dev, func); + devid = pciReadLong(pciDeviceTag, PCI_ID_REG); + if ((devid & pciDevidMask) == pciDevid) + /* Yes - Return it. Otherwise, next device */ + return pciDeviceTag; + } + } +} +#endif Index: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_pci.c =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/linux/lnx_pci.c 2005-11-09 14:13:04.610349830 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_pci.c 2005-11-09 14:13:12.672733509 -0600 @@ -28,16 +28,41 @@ Bool xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits) { + FILE *file; char c[0x200]; char *res; - unsigned int bus, devfn, dev, fn; + unsigned int domain, bus, devfn, dev, fn; unsigned PCIADDR_TYPE size[7]; unsigned int num; signed PCIADDR_TYPE Size; + int resource; + unsigned PCIADDR_TYPE begin, end; if (index > 7) return FALSE; - + + pciInfoFromTag(tag, &domain, &bus, &dev, &fn); + + sprintf(c, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/resource", + domain, bus, domain, bus, dev, fn); + if (file = fopen(c, "r")) { + for (resource=0; resource != index; resource++) + fgets(c, 0x1ff, file); + res = fgets(c, 0x1ff, file); + num = sscanf(res, PCIADDR_FMT " " PCIADDR_FMT " " PCIADDR_IGNORE_FMT, + &begin, &end); + if (num == 2) { + Size = end - begin; + while (Size & ((PCIADDR_TYPE) 0x01)) { + Size = Size >> ((PCIADDR_TYPE) 1); + (*bits)++; + } + fclose(file); + return TRUE; + } + fclose(file); + } + if (!xf86OSLinuxPCIFile && \ !(xf86OSLinuxPCIFile = fopen("/proc/bus/pci/devices","r"))) return FALSE; @@ -99,13 +124,32 @@ FILE *file; char c[0x200]; char *res; - unsigned int bus, devfn, dev, fn; + unsigned int domain, bus, devfn, dev, fn; unsigned PCIADDR_TYPE offset[7]; unsigned int num; + int resource; if (index > 7) return FALSE; + pciInfoFromTag(tag, &domain, &bus, &dev, &fn); + + sprintf(c, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/resource", + domain, bus, domain, bus, dev, fn); + if (file = fopen(c, "r")) { + for (resource=0; resource != index; resource++) + fgets(c, 0x1ff, file); + res = fgets(c, 0x1ff, file); + num = sscanf(res, PCIADDR_FMT " " PCIADDR_IGNORE_FMT " " PCIADDR_IGNORE_FMT, + &offset[0]); + if (num == 1) { + *bases = offset[0]; + fclose(file); + return TRUE; + } + fclose(file); + } + if (!(file = fopen("/proc/bus/pci/devices","r"))) return FALSE; do { @@ -159,11 +203,40 @@ FILE *file; char c[0x200]; char *res; - unsigned int bus, devfn, dev, fn; + unsigned int domain, bus, devfn, dev, fn; unsigned PCIADDR_TYPE offset[7]; unsigned PCIADDR_TYPE size[7]; unsigned int num; unsigned int ndx; + unsigned PCIADDR_TYPE begin,end; + + pciInfoFromTag(tag, &domain, &bus, &dev, &fn); + + sprintf(c, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/resource", + domain, bus, domain, bus, dev, fn); + if (file = fopen(c, "r")) { + unsigned long savePtr; + for (ndx=0; ndx < 7; ndx++) { + res = fgets(c, 0x1ff, file); + if (!res) + break; + num = sscanf(res, PCIADDR_FMT " " PCIADDR_FMT " " PCIADDR_IGNORE_FMT, + &begin, &end); + if (num == 2) { + 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)); + if (base >= savePtr && base <= (savePtr + (end - begin))) { + fclose(file); + return ( ~(0xFUL) & (begin + (base - savePtr))); + } + } + } + fclose(file); + } if (!(file = fopen("/proc/bus/pci/devices","r"))) return 0; Index: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/bus/Pci.c 2005-11-09 14:13:04.578127636 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c 2005-11-09 14:13:12.673709939 -0600 @@ -597,6 +597,16 @@ return bits; } +void +pciInfoFromTag(PCITAG tag, int *domainnum, int *busnum, + int *devnum, int *funcnum) +{ + *domainnum = PCI_DOM_FROM_TAG(tag); + *busnum = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)); + *devnum = PCI_DEV_FROM_TAG(tag); + *funcnum = PCI_FUNC_FROM_TAG(tag); +} + PCITAG pciTag(int busnum, int devnum, int funcnum) { Index: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/int10/helper_exec.c 2005-11-09 14:13:04.532235419 -0600 +++ xc/programs/Xserver/hw/xfree86/int10/helper_exec.c 2005-11-09 14:13:12.673709939 -0600 @@ -478,7 +478,7 @@ return 1; } if (addr == 0xCFC) { - *val = pciReadLong(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr)); + *val = pciReadLong(Int10Current->Tag, OFFSET(PciCfg1Addr)); return 1; } return 0; @@ -492,7 +492,7 @@ return 1; } if (addr == 0xCFC) { - pciWriteLong(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr), val); + pciWriteLong(Int10Current->Tag, OFFSET(PciCfg1Addr),val); return 1; } return 0; Index: xc/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h 2005-11-09 14:13:04.600585529 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/xf86Pci.h 2005-11-09 14:13:12.674686369 -0600 @@ -768,6 +768,8 @@ ADDRESS pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr); ADDRESS pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr); PCITAG pciTag(int busnum, int devnum, int funcnum); +void pciInfoFromTag(PCITAG tag, int *domainnum, + 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, Index: xc/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c =================================================================== --- xc.orig/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c 2005-11-09 14:13:04.587891937 -0600 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c 2005-11-09 14:13:12.675662799 -0600 @@ -41,13 +41,14 @@ 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; + unsigned int parent_busnum, parent_nodombus, busnum = pdev->busnum; + unsigned int nodombus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(pdev->tag)); 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); + nodombus); if (readlink(bridge_path, bridge_target, strlen(bridge_target)) < 0) { perror("failed to dereference bridge link"); @@ -56,7 +57,9 @@ } sscanf(bridge_target, "../../../devices/pci%04x:%02x", &parent_segnum, - &parent_busnum); + &parent_nodombus); + + parent_busnum = PCI_MAKE_BUS(parent_segnum, parent_nodombus); /* * If there's no bridge or the bridge points to the device, use