Index: hw/xorg/common/compiler.h =================================================================== RCS file: /cvs/xserver/debrix/hw/xorg/common/compiler.h,v retrieving revision 1.3 diff -u -r1.3 compiler.h --- hw/xorg/common/compiler.h 10 Jun 2004 19:40:04 -0000 1.3 +++ hw/xorg/common/compiler.h 25 Jun 2004 14:42:23 -0000 @@ -465,10 +465,12 @@ # ifndef __INTEL_COMPILER # define mem_barrier() __asm__ __volatile__ ("mf" ::: "memory") # define write_mem_barrier() __asm__ __volatile__ ("mf" ::: "memory") +# define io_mem_barrier() __asm__ __volatile__ ("mf.a" ::: "memory") # else # include "ia64intrin.h" # define mem_barrier() __mf() # define write_mem_barrier() __mf() +# define io_mem_barrier() __mfa # endif /* @@ -491,14 +493,132 @@ __mf();\ __isrlz();\ } -# endif +# endif /* __INTEL_COMPILER */ + +/* + * It seems like the in/out routines in this file could be consolidated a bit + * and/or split into multiple, arch specific header files. + * + * Many also assume that the 'port' value passed in is an actual address, + * rather than relative to some 'IOBase' value. This means that callers + * have to be fixed up to get their own 'IOBase' (which will be PCI device + * specific), or the inX/outX routines need to be changed to take a PCI + * tag so that platforms can route the PIOs to the correct bus. + */ + # undef outb # undef outw # undef outl - -# define outb(a,b) _outb(b,a) -# define outw(a,b) _outw(b,a) -# define outl(a,b) _outl(b,a) + +/* + * Deal with outX on platforms where it's simply a store. + */ + +static inline unsigned int outb(unsigned long port, unsigned char val) +{ + volatile unsigned char *addr = (unsigned char *)port; + + *addr = val; + io_memory_barrier(); +} + +static inline unsigned int outw(unsigned long port, unsigned short val) +{ + volatile unsigned short *addr = (unsigned char *)port; + + *addr = val; + io_memory_barrier(); +} + +static inline unsigned int outl(unsigned long port, unsigned int val) +{ + volatile unsigned int *addr = (unsigned char *)port; + + *addr = val; + io_memory_barrier(); +} + +# undef inb +# undef inw +# undef inl + +/* + * Deal with master aborts on a really funky platform. The kernel will send + * a SIGBUS to applications that have mapped /proc/bus/pci/... when an I/O + * error, like a master abort, occurs. + * + * On ia64, an error caused by an uncached read may (and probably will) be + * reported to software *way* after the instruction that did the read. The + * only way to be sure that any errors that might occur have been flushed out + * is to use the value we get back in a statement that affects control flow. + * + * Note that on some platforms, an PIO read does *not* guarantee that DMA + * initiated prior to the PIO is complete. + */ +extern int ia64_io_error; + +static inline unsigned int inb(unsigned long port) +{ + unsigned int val; + + /* The SIGBUS handler will set this for us if an error occurs */ + ia64_io_error = 0; + + val = (unsigned int) (*((volatile unsigned char *)port)); + + /* Use val in an expression to flush out errors */ + if (val && ia64_io_error) + return -1; + + /* Double check for an error */ + if (ia64_io_error) + return -1; + + /* val was actually read from the hardware */ + return val; +} + +static inline unsigned int inw(unsigned long port) +{ + unsigned int val; + + /* The SIGBUS handler will set this for us if an error occurs */ + ia64_io_error = 0; + + val = (unsigned int) (*((volatile unsigned short *)port)); + + /* Use val in an expression to flush out errors */ + if (val && ia64_io_error) + return -1; + + /* Double check for an error */ + if (ia64_io_error) + return -1; + + /* val was actually read from the hardware */ + return val; +} + +static inline unsigned int inl(unsigned long port) +{ + unsigned int val; + + /* The SIGBUS handler will set this for us if an error occurs */ + ia64_io_error = 0; + + val = (unsigned int) (*((volatile unsigned int *)port)); + + /* Use val in an expression to flush out errors */ + if (val && ia64_io_error) + return -1; + + /* Double check for an error */ + if (ia64_io_error) + return -1; + + /* val was actually read from the hardware */ + return val; +} # elif defined(linux) && defined(__amd64__) Index: hw/xorg/os-support/bus/Pci.h =================================================================== RCS file: /cvs/xserver/debrix/hw/xorg/os-support/bus/Pci.h,v retrieving revision 1.3 diff -u -r1.3 Pci.h --- hw/xorg/os-support/bus/Pci.h 10 Jun 2004 19:40:52 -0000 1.3 +++ hw/xorg/os-support/bus/Pci.h 25 Jun 2004 14:42:23 -0000 @@ -257,7 +257,6 @@ # 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 Index: hw/xorg/os-support/bus/ia64Pci.c =================================================================== RCS file: /cvs/xserver/debrix/hw/xorg/os-support/bus/ia64Pci.c,v retrieving revision 1.2 diff -u -r1.2 ia64Pci.c --- hw/xorg/os-support/bus/ia64Pci.c 10 Jun 2004 19:40:52 -0000 1.2 +++ hw/xorg/os-support/bus/ia64Pci.c 25 Jun 2004 14:42:23 -0000 @@ -32,17 +32,37 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include "460gxPCI.h" #include "e8870PCI.h" #include "zx1PCI.h" #include "Pci.h" +/* Used by the in/out routines to check for master aborts */ +int ia64_io_error; + +void ia64SigBusHandler(int signo, siginfo_t *sinfo, void *unused) +{ + ia64_io_error = 1; +} + +void +ia64SigBusSetup(void) +{ + struct sigaction saction; + + saction.sa_sigaction = ia64SigBusHandler; + saction.sa_flags = SA_SIGINFO; + sigaction(SIGBUS, &saction, NULL); +} + void ia64ScanPCIWrapper(scanpciWrapperOpt flags) { if (flags == SCANPCI_INIT) { - + ia64SigBusSetup(); +#if 0 /* PCI configuration space probes should be done first */ if (xf86PreScan460GX()) return; @@ -50,13 +70,13 @@ return; if (xf86PreScanZX1()) return; - +#endif } else /* if (flags == SCANPCI_TERM) */ { - +#if 0 xf86PostScan460GX(); xf86PostScanE8870(); xf86PostScanZX1(); - +#endif } } Index: hw/xorg/os-support/bus/linuxPci.c =================================================================== RCS file: /cvs/xserver/debrix/hw/xorg/os-support/bus/linuxPci.c,v retrieving revision 1.3 diff -u -r1.3 linuxPci.c --- hw/xorg/os-support/bus/linuxPci.c 10 Jun 2004 19:40:52 -0000 1.3 +++ hw/xorg/os-support/bus/linuxPci.c 25 Jun 2004 14:42:23 -0000 @@ -327,7 +327,8 @@ if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) return result; - if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0)) < 0) + /* Open the bridge if present, otherwise try this device */ + if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : Tag)) < 0) return 0; if ((result = ioctl(fd, PCIIOC_CONTROLLER, 0)) < 0) @@ -350,7 +351,8 @@ pPCI = xf86GetPciHostConfigFromTag(Tag); - if (((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0)) < 0) || + /* Again, use the tag we were given if there's no parent bridge */ + if (((fd = linuxPciOpenFile(pPCI ? pPCI->tag : Tag)) < 0) || (ioctl(fd, mmap_ioctl, 0) < 0)) break;