From 46901063e8edc82b67989f4e5eec39d17c67dc98 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 12:25:03 +0100 Subject: [PATCH 01/11] Build with -D_PC on ix86 only. --- hw/xfree86/int10/Makefile.am | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/int10/Makefile.am b/hw/xfree86/int10/Makefile.am index c059070ec4..3a18afb8aa 100644 --- a/hw/xfree86/int10/Makefile.am +++ b/hw/xfree86/int10/Makefile.am @@ -13,8 +13,12 @@ COMMON_SOURCES = \ xf86int10.c \ xf86int10module.c +if I386_VIDEO +I386_VIDEO_CFLAGS = -D_PC +endif + if INT10_VM86 -AM_CFLAGS = -D_PC -D_VM86_LINUX $(XORG_CFLAGS) $(EXTRA_CFLAGS) +AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_VM86_LINUX $(XORG_CFLAGS) $(EXTRA_CFLAGS) INCLUDES = $(XORG_INCS) libint10_la_SOURCES = \ $(COMMON_SOURCES) \ @@ -23,7 +27,8 @@ libint10_la_SOURCES = \ endif if INT10_X86EMU -AM_CFLAGS = -D_X86EMU -DNO_SYS_HEADERS -D_PC $(XORG_CFLAGS) $(EXTRA_CFLAGS) +AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_X86EMU -DNO_SYS_HEADERS \ + $(XORG_CFLAGS) $(EXTRA_CFLAGS) INCLUDES = $(XORG_INCS) -I$(srcdir)/../x86emu libint10_la_SOURCES = \ $(COMMON_SOURCES) \ @@ -33,7 +38,7 @@ libint10_la_SOURCES = \ endif if INT10_STUB -AM_CFLAGS = -D_PC -D_VM86_LINUX $(XORG_CFLAGS) $(EXTRA_CFLAGS) +AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_VM86_LINUX $(XORG_CFLAGS) $(EXTRA_CFLAGS) libint10_la_SOURCES = stub.c xf86int10module.c endif From f4dd2665b0f9aa9c00a5152c73bc72cb7514eeb5 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 12:36:12 +0100 Subject: [PATCH 02/11] Added missing domain stripping in already domain aware code. --- hw/xfree86/os-support/bus/linuxPci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index 7d220d08a7..bda265c539 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -731,7 +731,7 @@ xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf) 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", @@ -910,7 +910,7 @@ int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len) int sofar = 0; 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/bus/pci/devices/%04x:%02x:%02x.%1x/rom", From 6319f7d713971f70f06166480f069eca3bcace36 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Thu, 2 Nov 2006 12:50:52 +0100 Subject: [PATCH 03/11] Make int10 fully domain aware. --- hw/xfree86/int10/helper_exec.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/xfree86/int10/helper_exec.c b/hw/xfree86/int10/helper_exec.c index 734d847205..d80de89cc0 100644 --- a/hw/xfree86/int10/helper_exec.c +++ b/hw/xfree86/int10/helper_exec.c @@ -469,7 +469,6 @@ Mem_wl(CARD32 addr, CARD32 val) static CARD32 PciCfg1Addr = 0; -#define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00) #define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff) static int @@ -480,7 +479,7 @@ pciCfg1in(CARD16 addr, CARD32 *val) return 1; } if (addr == 0xCFC) { - *val = pciReadLong(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr)); + *val = pciReadLong(Int10Current->Tag, OFFSET(PciCfg1Addr)); return 1; } return 0; @@ -494,7 +493,7 @@ pciCfg1out(CARD16 addr, CARD32 val) return 1; } if (addr == 0xCFC) { - pciWriteLong(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr), val); + pciWriteLong(Int10Current->Tag, OFFSET(PciCfg1Addr), val); return 1; } return 0; @@ -512,7 +511,7 @@ pciCfg1inw(CARD16 addr, CARD16 *val) } if ((addr >= 0xCFC) && (addr <= 0xCFF)) { offset = addr - 0xCFC; - *val = pciReadWord(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr) + offset); + *val = pciReadWord(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset); return 1; } return 0; @@ -531,7 +530,7 @@ pciCfg1outw(CARD16 addr, CARD16 val) } if ((addr >= 0xCFC) && (addr <= 0xCFF)) { offset = addr - 0xCFC; - pciWriteWord(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr) + offset, val); + pciWriteWord(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset, val); return 1; } return 0; @@ -549,7 +548,7 @@ pciCfg1inb(CARD16 addr, CARD8 *val) } if ((addr >= 0xCFC) && (addr <= 0xCFF)) { offset = addr - 0xCFC; - *val = pciReadByte(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr) + offset); + *val = pciReadByte(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset); return 1; } return 0; @@ -568,7 +567,7 @@ pciCfg1outb(CARD16 addr, CARD8 val) } if ((addr >= 0xCFC) && (addr <= 0xCFF)) { offset = addr - 0xCFC; - pciWriteByte(TAG(PciCfg1Addr), OFFSET(PciCfg1Addr) + offset, val); + pciWriteByte(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset, val); return 1; } return 0; From 5afc6c1a14fea2966017493b045fa7209faeb8eb Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 15:42:03 +0100 Subject: [PATCH 04/11] Added linux 2.6 compatible domain aware device scanning code. Additional scanning code uses the /sys interface of 2.6 kernels. Cleaned up the use of tags and already split domain/bus/dev/fn. --- hw/xfree86/os-support/bus/Pci.c | 8 +++ hw/xfree86/os-support/bus/xf86Pci.h | 1 + hw/xfree86/os-support/linux/lnx_pci.c | 71 ++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/hw/xfree86/os-support/bus/Pci.c b/hw/xfree86/os-support/bus/Pci.c index ea6ac4ec08..b80371d83b 100644 --- a/hw/xfree86/os-support/bus/Pci.c +++ b/hw/xfree86/os-support/bus/Pci.c @@ -20,6 +20,8 @@ * pciSetBitsByte() - Write an 8 bit value against a mask * pciTag() - Return tag for a given PCI bus, device, & * function + * pciDomTag() - Return tag for a given PCI domain, bus, + * device & function * pciBusAddrToHostAddr() - Convert a PCI address to a host address * pciHostAddrToBusAddr() - Convert a host address to a PCI address * pciGetBaseSize() - Returns the number of bits in a PCI base @@ -614,6 +616,12 @@ pciTag(int busnum, int devnum, int funcnum) return(PCI_MAKE_TAG(busnum,devnum,funcnum)); } +_X_EXPORT PCITAG +pciDomTag(int domnum, int busnum, int devnum, int funcnum) +{ + return(PCI_MAKE_TAG(PCI_MAKE_BUS(domnum,busnum),devnum,funcnum)); +} + #if defined(PCI_MFDEV_SUPPORT) Bool diff --git a/hw/xfree86/os-support/bus/xf86Pci.h b/hw/xfree86/os-support/bus/xf86Pci.h index fdb88e832e..c444a0cd12 100644 --- a/hw/xfree86/os-support/bus/xf86Pci.h +++ b/hw/xfree86/os-support/bus/xf86Pci.h @@ -766,6 +766,7 @@ void pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val); ADDRESS pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr); ADDRESS pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr); PCITAG pciTag(int busnum, int devnum, int funcnum); +PCITAG pciDomTag(int domnum, 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, diff --git a/hw/xfree86/os-support/linux/lnx_pci.c b/hw/xfree86/os-support/linux/lnx_pci.c index a1dbc76046..aff6bb0ae6 100644 --- a/hw/xfree86/os-support/linux/lnx_pci.c +++ b/hw/xfree86/os-support/linux/lnx_pci.c @@ -3,7 +3,9 @@ #include #endif +#include #include +#include #include #include "os.h" #include "xf86.h" @@ -25,8 +27,10 @@ int lnxPciInit(void); struct pci_dev { + unsigned int domain; unsigned int bus; - unsigned int devfn; + unsigned int dev; + unsigned int fn; PCIADDR_TYPE offset[7]; PCIADDR_TYPE size[7]; struct pci_dev *next; @@ -38,10 +42,53 @@ int xf86OSLinuxNumPciDevs = 0; static struct pci_dev *xf86OSLinuxGetPciDevs(void) { char c[0x200]; FILE *file = NULL; + DIR *dir; + struct dirent *dirent; struct pci_dev *tmp, *ret = NULL; - unsigned int num; + unsigned int i, num, devfn; + unsigned PCIADDR_TYPE begin, end; char *res; + /* Try 2.6 devices first, with domain support */ + if ( (dir = opendir ("/sys/bus/pci/devices")) ) { + xf86OSLinuxNumPciDevs = 0; + while ( (dirent = readdir (dir)) ) { + unsigned int domain, bus, dev, fn; + if (sscanf (dirent->d_name, "%04x:%02x:%02x.%01x", + &domain, &bus, &dev, &fn) == 4) { + tmp = xcalloc (sizeof(struct pci_dev), 1); + tmp->domain = domain; + tmp->bus = bus; + tmp->dev = dev; + tmp->fn = fn; + sprintf (c, "/sys/bus/pci/devices/%12s/resource", + dirent->d_name); + i = 0; + if ( (file = fopen (c, "r")) ) { + while (i < 7 && fgets (c, 0x200, file)) { + if (sscanf (c, PCIADDR_FMT " " PCIADDR_FMT " " + PCIADDR_IGNORE_FMT, &begin, &end) == 2) { + tmp->offset[i] = begin; + tmp->size[i] = begin ? end-begin+1 : 0; + i++; + } + } + fclose (file); + } + if (i > 0) { + tmp->next = ret; + ret = tmp; + xf86OSLinuxNumPciDevs++; + } else + xfree (tmp); + } + } + closedir (dir); + } + + if (ret) + return ret; + file = fopen("/proc/bus/pci/devices", "r"); if (!file) return NULL; @@ -70,9 +117,11 @@ static struct pci_dev *xf86OSLinuxGetPciDevs(void) { "\t" PCIADDR_FMT "\t" PCIADDR_FMT "\t" PCIADDR_FMT, - &tmp->bus,&tmp->devfn,&tmp->offset[0],&tmp->offset[1],&tmp->offset[2],&tmp->offset[3], + &tmp->bus,&devfn,&tmp->offset[0],&tmp->offset[1],&tmp->offset[2],&tmp->offset[3], &tmp->offset[4],&tmp->offset[5],&tmp->offset[6], &tmp->size[0], &tmp->size[1], &tmp->size[2], &tmp->size[3], &tmp->size[4], &tmp->size[5], &tmp->size[6]); + tmp->dev = devfn >> 3; + tmp->fn = devfn & 0x7; if (num != 16) { /* apparantly not 2.3 style */ xfree(tmp); fclose(file); @@ -114,10 +163,8 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits) return FALSE; for (device = xf86OSLinuxPCIDevs; device; device = device->next) { - dev = device->devfn >> 3; - fn = device->devfn & 0x7; - if (tag == pciTag(device->bus,dev,fn)) { - *bits = 0; + if (tag == pciDomTag (device->domain, device->bus, + device->dev, device->fn)) { if (device->size[index] != 0) { Size = device->size[index] - ((PCIADDR_TYPE) 1); while (Size & ((PCIADDR_TYPE) 0x01)) { @@ -151,9 +198,8 @@ xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases) return FALSE; for (device = xf86OSLinuxPCIDevs; device; device = device->next) { - dev = device->devfn >> 3; - fn = device->devfn & 0x7; - if (tag == pciTag(device->bus,dev,fn)) { + if (tag == pciDomTag (device->domain, device->bus, + device->dev, device->fn)) { /* return the offset for the index requested */ *bases = device->offset[index]; return TRUE; @@ -179,9 +225,8 @@ xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base) } for (device = xf86OSLinuxPCIDevs; device; device = device->next) { - dev = device->devfn >> 3; - fn = device->devfn & 0x7; - if (tag == pciTag(device->bus, dev, fn)) { + if (tag == pciDomTag (device->domain, device->bus, + device->dev, device->fn)) { /* ok now look through all the BAR values of this device */ pciConfigPtr pDev = xf86GetPciConfigFromTag(tag); From 072c022e731c3aadf34096f16364e29df47280d2 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 17:58:19 +0100 Subject: [PATCH 05/11] Fix obviously wrong boundary checks + cleanup unused vars. Also disable compilation of code that is no longer used anywhere in the whole Xserver tree. --- hw/xfree86/os-support/linux/lnx_pci.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/os-support/linux/lnx_pci.c b/hw/xfree86/os-support/linux/lnx_pci.c index aff6bb0ae6..a957038997 100644 --- a/hw/xfree86/os-support/linux/lnx_pci.c +++ b/hw/xfree86/os-support/linux/lnx_pci.c @@ -149,11 +149,10 @@ int lnxPciInit(void) { Bool xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits) { - unsigned int dev, fn; signed PCIADDR_TYPE Size; struct pci_dev *device; - if (index > 7) + if (index >= 7) return FALSE; if (!xf86OSLinuxPCIDevs) { @@ -181,14 +180,14 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits) +#if 0 /* Query the kvirt address (64bit) of a BAR range from TAG */ Bool xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases) { - unsigned int dev, fn; struct pci_dev *device; - if (index > 7) + if (index >= 7) return FALSE; if (!xf86OSLinuxPCIDevs) { @@ -208,12 +207,12 @@ xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases) return FALSE; } +#endif /* 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) { - unsigned int dev, fn; unsigned int ndx; struct pci_dev *device; From 16c5043fc0c84b14323cd211c2645106455ac320 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 18:22:09 +0100 Subject: [PATCH 06/11] Fix 2 warnings. --- hw/xfree86/common/xf86pciBus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index b763042cc1..ae33568b84 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1398,7 +1398,7 @@ fixPciResource(int prt, memType alignment, pciVideoPtr pvp, unsigned long type) (*p_base) = H2B(tag,range.rBegin,type); #ifdef DEBUG ErrorF("New PCI res %i base: 0x%lx, size: 0x%lx, type %s\n", - res_n,(*p_base),(1 << (*p_size)), + res_n,(*p_base),(1L << (*p_size)), ((type & ResPhysMask) == ResMem) ? "Mem" : "Io"); #endif if (res_n != 0xff) { @@ -1577,8 +1577,8 @@ findPciRange(PCITAG tag, resPtr m, resPtr avoid, CARD32 size) return 0; } -pciVideoPtr -getPciVideoPtr(tag) +static pciVideoPtr +getPciVideoPtr(PCITAG tag) { int n = 0; From caaa113acf4144fd47a1ac93ca440d78d1983e54 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 18:38:45 +0100 Subject: [PATCH 07/11] Fixing domain support for ia64 ia64 specific functions + defines. Still uses /proc interface for some scaning code. Based on code from Egbert Eich . --- hw/xfree86/os-support/bus/Pci.h | 4 +- hw/xfree86/os-support/bus/linuxPci.c | 103 +++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/hw/xfree86/os-support/bus/Pci.h b/hw/xfree86/os-support/bus/Pci.h index 0f1af2086e..7cc882d363 100644 --- a/hw/xfree86/os-support/bus/Pci.h +++ b/hw/xfree86/os-support/bus/Pci.h @@ -119,7 +119,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 */ @@ -258,7 +258,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 diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index bda265c539..0f7fc470ce 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -940,3 +940,106 @@ int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len) } return 0; } + +#ifdef __ia64__ +static PCITAG ia64linuxPciFindFirst(void); +static PCITAG ia64linuxPciFindNext(void); + +void +ia64linuxPciInit() +{ + struct stat st; + + linuxPciInit(); + + if (!stat("/proc/sgi_sn/licenseID", &st) && pciNumBuses) { + /* 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. + */ + 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 + From 1d731fc54a2cf5d3f353d8ee1c7c4989df27f011 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 18:50:15 +0100 Subject: [PATCH 08/11] Add domain support to linuxPciOpenFile(). Loosely based on patch from David S. Miller See also bug #2368. --- hw/xfree86/os-support/bus/linuxPci.c | 90 +++++++++++++++++++++------- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index 0f7fc470ce..97d60f5999 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -54,6 +54,7 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" #include "Pci.h" +#include /* * linux platform specific PCI access functions -- using /proc/bus/pci @@ -73,6 +74,7 @@ static void linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val); static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len); +static Bool linuxDomainSupport(void); static pciBusFuncs_t linuxFuncs0 = { /* pciReadLong */ linuxPciCfgRead, @@ -116,6 +118,8 @@ static pciBusInfo_t linuxPci0 = { /* from lnx_pci.c. */ extern int lnxPciInit(void); +static Bool domain_support = FALSE; + void linuxPciInit() { @@ -126,6 +130,9 @@ linuxPciInit() we'll need a fallback for 2.0 kernels here */ return; } +#ifndef INCLUDE_XF86_NO_DOMAIN + domain_support = linuxDomainSupport(); +#endif pciNumBuses = 1; pciBusInfo[0] = &linuxPci0; pciFindFirstFP = pciGenFindFirst; @@ -137,13 +144,14 @@ linuxPciInit() 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[64]; struct stat ignored; static int is26 = -1; - 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 (is26 == -1) { @@ -153,30 +161,41 @@ linuxPciOpenFile(PCITAG tag, Bool write) is26 = 1; } - if (fd == -1 || (write && (!is_write)) + if (!domain_support && domain > 0) + return -1; + + if (fd == -1 || (write && (!is_write)) || domain != ldomain || bus != lbus || dev != ldev || func != lfunc) { - if (fd != -1) + if (fd != -1) { close(fd); + fd = -1; + } if (is26) - sprintf(file,"/sys/bus/pci/devices/0000:%02x:%02x.%01x/config", - bus, dev, func); + sprintf(file,"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config", + domain, bus, dev, func); else { if (bus < 256) { - sprintf(file,"/proc/bus/pci/%02x",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); + sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus); + if (stat(file, &ignored) < 0) { + if (domain == 0) + sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", + bus, dev, func); + else + goto bail; + } else + sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x", + domain, bus, dev, func); } else { - sprintf(file,"/proc/bus/pci/%04x",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); + sprintf(file, "/proc/bus/pci/%04x:%04x", domain, bus); + if (stat(file, &ignored) < 0) { + if (domain == 0) + sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", + bus, dev, func); + else + goto bail; + } else + sprintf(file, "/proc/bus/pci/%04x:%04x/%02x.%1x", + domain, bus, dev, func); } } if (write) { @@ -191,7 +210,8 @@ linuxPciOpenFile(PCITAG tag, Bool write) fd = open(file,O_RDONLY); is_write = FALSE; } - + bail: + ldomain = domain; lbus = bus; ldev = dev; lfunc = func; @@ -489,6 +509,32 @@ linuxGetSizes(PCITAG Tag, unsigned long *io_size, unsigned long *mem_size) *mem_size = sizes->mem_size; } +static Bool +linuxDomainSupport(void) +{ + DIR *dir; + struct dirent *dirent; + char *end; + + if (!(dir = opendir("/proc/bus/pci"))) + return FALSE; + while (1) { + if (!(dirent = readdir(dir))) + return FALSE; + strtol(dirent->d_name,&end,16); + /* entry of the form xx or xxxx : x=[0..f] no domain */ + if (*end == '\0') + return FALSE; + else if (*end == ':') { + /* ':' found immediately after: verify for xxxx:xx or xxxx:xxxx */ + strtol(end + 1,&end,16); + if (*end == '\0') + return TRUE; + } + } + return FALSE; +} + _X_EXPORT int xf86GetPciDomain(PCITAG Tag) { From d50fc413b39f52663b46084c28e81fc4933a7b49 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Thu, 2 Nov 2006 18:53:41 +0100 Subject: [PATCH 09/11] Fix device path in altixPCI.c to be domain aware. --- hw/xfree86/os-support/bus/altixPCI.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/os-support/bus/altixPCI.c b/hw/xfree86/os-support/bus/altixPCI.c index 010f6619a8..7a72ec6e7a 100644 --- a/hw/xfree86/os-support/bus/altixPCI.c +++ b/hw/xfree86/os-support/bus/altixPCI.c @@ -41,13 +41,14 @@ static pciDevice *get_dev_on_bus(unsigned int segnum, unsigned int busnum) 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 @@ static void get_bridge_info(pciBusInfo_t *bus_info, pciDevice *pdev) } 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 From c1828a8ff51c8db326c47e6710f4f42fab94fb6d Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Fri, 3 Nov 2006 18:32:48 +0100 Subject: [PATCH 10/11] Fixing mach64 driver bailing out on ia64 Mach64 driver bails out on ia64 because it cannot map device memory. It turns out that some bogus and unneeded code attempts to find the root bridge of the device and fails to do so proberly as there this host-to-pci bridge is not existant. This code has been around for years although it completely unclear what it had been intended for. Fixing this by eliminating the bogus code. --- hw/xfree86/os-support/bus/linuxPci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index 97d60f5999..afb38197fc 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -570,9 +570,7 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag, xf86InitVidMem(); - pPCI = xf86GetPciHostConfigFromTag(Tag); - - if (((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) || + if (((fd = linuxPciOpenFile(Tag ,FALSE)) < 0) || (ioctl(fd, mmap_ioctl, 0) < 0)) break; From bd0c829654903ca45543dfa59cda967c4fafd8ac Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 3 Nov 2006 18:54:06 +0100 Subject: [PATCH 11/11] Do not map full 0-1MB legacy range If we're mapping something in the "legacy range" (0-1Mb), we shouldn't expand the requested range to the entire 0-1Mb range. Typically this is for mapping the VGA frame buffer, and some platforms support mmap of the frame buffer but not the entire 0-1Mb range. For example, HP sx1000 and sx2000 ia64 platforms can have memory from 0-0x9ffff, VGA frame buffer from 0xa0000-0xbffff, and memory from 0xc0000-0xfffff. On these platforms, we can't map the entire 0-1Mb range with the same attribute because the memory only supports WB, while the frame buffer supports only UC. But an mmap of just the frame buffer should work fine. --- hw/xfree86/os-support/bus/linuxPci.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index afb38197fc..15fc2b8c7c 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -627,7 +627,6 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag, #define MAX_DOMAINS 257 static pointer DomainMmappedIO[MAX_DOMAINS]; -static pointer DomainMmappedMem[MAX_DOMAINS]; static int linuxOpenLegacy(PCITAG Tag, char *name) @@ -685,6 +684,7 @@ xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, { int domain = xf86GetPciDomain(Tag); int fd; + pointer addr; /* * We use /proc/bus/pci on non-legacy addresses or if the Linux sysfs @@ -698,20 +698,14 @@ xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, 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"); - } + addr = mmap(NULL, Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, Base); + if (addr == MAP_FAILED) { + close (fd); + perror("mmap failure"); + FatalError("xf86MapDomainMem(): mmap() failure\n"); } - close(fd); - return (pointer)((char *)DomainMmappedMem[domain] + Base); + return addr; } /*