summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@nwnk.net>2005-04-22 16:49:22 +0000
committerAdam Jackson <ajax@nwnk.net>2005-04-22 16:49:22 +0000
commit16c2499b8f5c2405e36c7d5a922bb0b150df1762 (patch)
tree6ebb8f9a66e56163700086906b8144049f32dbea
parent8565b6c0e2851cc3f194ba72d3db02a4e2976528 (diff)
Bug #2373: SGI Altix platform support. (Shrijeet Mukherjee, Jesse Barnes,
Bjorn Helgaas, Egbert Eich.)
-rw-r--r--hw/xfree86/common/compiler.h18
-rw-r--r--hw/xfree86/common/xf86Bus.c4
-rw-r--r--hw/xfree86/common/xf86pciBus.c2
-rw-r--r--hw/xfree86/loader/xf86sym.c12
-rw-r--r--hw/xfree86/os-support/bus/Pci.h1
-rw-r--r--hw/xfree86/os-support/bus/linuxPci.c190
-rw-r--r--hw/xfree86/os-support/linux/lnx_ia64.c14
-rw-r--r--hw/xfree86/os-support/linux/lnx_pci.c138
-rw-r--r--hw/xfree86/os-support/shared/ia64Pci.c159
-rw-r--r--hw/xfree86/os-support/shared/ia64Pci.h3
-rw-r--r--hw/xfree86/os-support/xf86_OSproc.h2
11 files changed, 513 insertions, 30 deletions
diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index 31b1ea37c..aca769722 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -124,7 +124,8 @@ extern int ffs(unsigned long);
# 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 @@ extern unsigned short ldw_brx(volatile unsigned char *, int);
# 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 @@ __ustw (unsigned long r5, unsigned short * r11)
# 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 <inttypes.h>
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 7c3db0262..9abd81ee8 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -1857,7 +1857,7 @@ xf86RegisterResources(int entityIndex, resList list, unsigned long access)
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 @@ xf86PostProbe(void)
#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 b81c91759..ee22056d6 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 ec0436125..12c3a07e6 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -1093,12 +1093,12 @@ LOOKUP xfree86LookupTab[] = {
#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 41ef3f866..4359a0856 100644
--- a/hw/xfree86/os-support/bus/Pci.h
+++ b/hw/xfree86/os-support/bus/Pci.h
@@ -254,7 +254,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
diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c
index 1f5e649db..32e11e4eb 100644
--- a/hw/xfree86/os-support/bus/linuxPci.c
+++ b/hw/xfree86/os-support/bus/linuxPci.c
@@ -59,6 +59,7 @@
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 @@ static pciBusFuncs_t linuxFuncs0 = {
/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr
#else
/* pciAddrHostToBus */ pciAddrNOOP,
-/* pciAddrBusToHost */ pciAddrNOOP
+/* pciAddrBusToHost */ linuxTransAddrBusToHost
#endif
};
@@ -201,6 +202,26 @@ linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits)
}
}
+/*
+ * 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 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
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 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
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 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
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 Base, int Len, unsigned char *Buf)
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 8d0976a36..06f2be777 100644
--- a/hw/xfree86/os-support/linux/lnx_ia64.c
+++ b/hw/xfree86/os-support/linux/lnx_ia64.c
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/utsname.h>
#include <unistd.h>
#include "ia64Pci.h"
@@ -35,11 +36,24 @@
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 074a9d7f7..25404b02b 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 index, int* bits)
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 d0046a7f2..30a062276 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 <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/pci.h>
+
+#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 @@ ia64ScanPCIWrapper(scanpciWrapperOpt flags)
case ZX1_CHIPSET:
xf86PreScanZX1();
return;
+ case ALTIX_CHIPSET:
+ xf86PreScanAltix();
+ return;
default:
return;
}
@@ -74,6 +230,9 @@ ia64ScanPCIWrapper(scanpciWrapperOpt flags)
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 1ee2fc091..bc4777dbb 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 688f647a3..f50c00ea3 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);