Bug #2373: SGI Altix platform support. (Shrijeet Mukherjee, Jesse Barnes,
Bjorn Helgaas, Egbert Eich.)
This commit is contained in:
parent
8565b6c0e2
commit
16c2499b8f
|
@ -124,7 +124,8 @@ extern int ffs(unsigned long);
|
||||||
|
|
||||||
# if !defined(__arm__)
|
# if !defined(__arm__)
|
||||||
# if !defined(__sparc__) && !defined(__arm32__) \
|
# 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 outb(unsigned short, unsigned char);
|
||||||
extern void outw(unsigned short, unsigned short);
|
extern void outw(unsigned short, unsigned short);
|
||||||
|
@ -162,7 +163,7 @@ extern unsigned short ldw_brx(volatile unsigned char *, int);
|
||||||
|
|
||||||
# ifndef NO_INLINE
|
# ifndef NO_INLINE
|
||||||
# ifdef __GNUC__
|
# 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
|
# ifdef linux
|
||||||
/* for Linux on Alpha, we use the LIBC _inx/_outx routines */
|
/* 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 outb
|
||||||
# undef outw
|
# undef outw
|
||||||
# undef outl
|
# 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__)
|
# elif defined(linux) && defined(__amd64__)
|
||||||
|
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
|
|
|
@ -1857,7 +1857,7 @@ xf86RegisterResources(int entityIndex, resList list, unsigned long access)
|
||||||
range.type = (range.type & ~ResAccMask) | (access & ResAccMask);
|
range.type = (range.type & ~ResAccMask) | (access & ResAccMask);
|
||||||
}
|
}
|
||||||
range.type &= ~ResEstimated; /* Not allowed for drivers */
|
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. */
|
/* On Alpha Linux, do not check for conflicts, trust the kernel. */
|
||||||
if (checkConflict(&range, Acc, entityIndex, SETUP,TRUE))
|
if (checkConflict(&range, Acc, entityIndex, SETUP,TRUE))
|
||||||
res = xf86AddResToList(res,&range,entityIndex);
|
res = xf86AddResToList(res,&range,entityIndex);
|
||||||
|
@ -2477,8 +2477,8 @@ xf86PostProbe(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
xf86FreeResList(acc);
|
xf86FreeResList(acc);
|
||||||
|
|
||||||
#if !(defined(__alpha__) && defined(linux)) && \
|
#if !(defined(__alpha__) && defined(linux)) && \
|
||||||
|
!(defined(__ia64__) && defined(linux)) && \
|
||||||
!(defined(__sparc64__) && defined(__OpenBSD__))
|
!(defined(__sparc64__) && defined(__OpenBSD__))
|
||||||
/*
|
/*
|
||||||
* No need to validate on Alpha Linux or OpenBSD/sparc64,
|
* No need to validate on Alpha Linux or OpenBSD/sparc64,
|
||||||
|
|
|
@ -1621,10 +1621,12 @@ getValidBIOSBase(PCITAG tag, int num)
|
||||||
m = m->next;
|
m = m->next;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if !defined(__ia64__) /* on ia64, trust the kernel, don't look for overlaps */
|
||||||
if (!xf86IsSubsetOf(range, m) ||
|
if (!xf86IsSubsetOf(range, m) ||
|
||||||
ChkConflict(&range, avoid, SETUP)
|
ChkConflict(&range, avoid, SETUP)
|
||||||
|| (mem && ChkConflict(&range, mem, SETUP)))
|
|| (mem && ChkConflict(&range, mem, SETUP)))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
xf86FreeResList(avoid);
|
xf86FreeResList(avoid);
|
||||||
|
|
|
@ -1093,12 +1093,12 @@ LOOKUP xfree86LookupTab[] = {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__ia64__)
|
#if defined(__ia64__)
|
||||||
SYMFUNC(_outw)
|
SYMFUNC(outw)
|
||||||
SYMFUNC(_outb)
|
SYMFUNC(outb)
|
||||||
SYMFUNC(_outl)
|
SYMFUNC(outl)
|
||||||
SYMFUNC(_inb)
|
SYMFUNC(inb)
|
||||||
SYMFUNC(_inw)
|
SYMFUNC(inw)
|
||||||
SYMFUNC(_inl)
|
SYMFUNC(inl)
|
||||||
#endif
|
#endif
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
SYMFUNC(outw)
|
SYMFUNC(outw)
|
||||||
|
|
|
@ -254,7 +254,6 @@
|
||||||
# if defined(linux)
|
# if defined(linux)
|
||||||
# define ARCH_PCI_INIT linuxPciInit
|
# define ARCH_PCI_INIT linuxPciInit
|
||||||
# define INCLUDE_XF86_MAP_PCI_MEM
|
# define INCLUDE_XF86_MAP_PCI_MEM
|
||||||
# define INCLUDE_XF86_NO_DOMAIN
|
|
||||||
# elif defined(FreeBSD)
|
# elif defined(FreeBSD)
|
||||||
# define ARCH_PCI_INIT freebsdPciInit
|
# define ARCH_PCI_INIT freebsdPciInit
|
||||||
# define INCLUDE_XF86_MAP_PCI_MEM
|
# define INCLUDE_XF86_MAP_PCI_MEM
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
static CARD32 linuxPciCfgRead(PCITAG tag, int off);
|
static CARD32 linuxPciCfgRead(PCITAG tag, int off);
|
||||||
static void linuxPciCfgWrite(PCITAG, int off, CARD32 val);
|
static void linuxPciCfgWrite(PCITAG, int off, CARD32 val);
|
||||||
static void linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits);
|
static void linuxPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits);
|
||||||
|
static ADDRESS linuxTransAddrBusToHost(PCITAG tag, PciAddrType type, ADDRESS addr);
|
||||||
#if defined(__powerpc__)
|
#if defined(__powerpc__)
|
||||||
static ADDRESS linuxPpcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS);
|
static ADDRESS linuxPpcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS);
|
||||||
static ADDRESS linuxPpcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS);
|
static ADDRESS linuxPpcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS);
|
||||||
|
@ -73,7 +74,7 @@ static pciBusFuncs_t linuxFuncs0 = {
|
||||||
/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr
|
/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr
|
||||||
#else
|
#else
|
||||||
/* pciAddrHostToBus */ pciAddrNOOP,
|
/* pciAddrHostToBus */ pciAddrNOOP,
|
||||||
/* pciAddrBusToHost */ pciAddrNOOP
|
/* pciAddrBusToHost */ linuxTransAddrBusToHost
|
||||||
#endif
|
#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__)
|
#if defined(__powerpc__)
|
||||||
|
|
||||||
#ifndef __NR_pciconfig_iobase
|
#ifndef __NR_pciconfig_iobase
|
||||||
|
@ -402,6 +423,9 @@ xf86GetPciDomain(PCITAG Tag)
|
||||||
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum)))
|
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum)))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if (pPCI->fakeDevice)
|
||||||
|
return 1; /* Domain 0 is reserved */
|
||||||
|
|
||||||
if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0)
|
if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -442,7 +466,7 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
|
||||||
if (Flags & VIDMEM_FRAMEBUFFER)
|
if (Flags & VIDMEM_FRAMEBUFFER)
|
||||||
mmapflags = MAP_SHARED | MAP_WRITECOMBINED;
|
mmapflags = MAP_SHARED | MAP_WRITECOMBINED;
|
||||||
else
|
else
|
||||||
mmapflags = MAP_SHARED | MAP_NONCACHED
|
mmapflags = MAP_SHARED | MAP_NONCACHED;
|
||||||
|
|
||||||
#else /* !__ia64__ */
|
#else /* !__ia64__ */
|
||||||
|
|
||||||
|
@ -467,7 +491,7 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
|
||||||
result = mmap(NULL, Size + Offset, prot, mmapflags, fd, realBase);
|
result = mmap(NULL, Size + Offset, prot, mmapflags, fd, realBase);
|
||||||
|
|
||||||
if (!result || ((pointer)result == MAP_FAILED))
|
if (!result || ((pointer)result == MAP_FAILED))
|
||||||
FatalError("linuxMapPci() mmap failure: %s\n", strerror(errno));
|
return NULL;
|
||||||
|
|
||||||
xf86MakeNewMapping(ScreenNum, Flags, realBase, Size + Offset, result);
|
xf86MakeNewMapping(ScreenNum, Flags, realBase, Size + Offset, result);
|
||||||
|
|
||||||
|
@ -480,38 +504,142 @@ linuxMapPci(int ScreenNum, int Flags, PCITAG Tag,
|
||||||
return NULL;
|
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
|
pointer
|
||||||
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
|
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
|
||||||
ADDRESS Base, unsigned long Size)
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return (pointer)((char *)DomainMmappedMem[domain] + Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_DOMAINS 257
|
/*
|
||||||
static pointer DomainMmappedIO[MAX_DOMAINS];
|
* xf86MapDomainIO - map I/O space in this domain
|
||||||
|
*
|
||||||
/* This has no means of returning failure, so all errors are fatal */
|
* 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
|
IOADDRESS
|
||||||
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
|
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
|
||||||
IOADDRESS Base, unsigned long Size)
|
IOADDRESS Base, unsigned long Size)
|
||||||
{
|
{
|
||||||
int domain = xf86GetPciDomain(Tag);
|
int domain = xf86GetPciDomain(Tag);
|
||||||
|
int fd;
|
||||||
|
|
||||||
if ((domain <= 0) || (domain >= MAX_DOMAINS))
|
if ((domain <= 0) || (domain >= MAX_DOMAINS))
|
||||||
FatalError("xf86MapDomainIO(): domain out of range\n");
|
FatalError("xf86MapDomainIO(): domain out of range\n");
|
||||||
|
|
||||||
|
if (DomainMmappedIO[domain])
|
||||||
|
return (IOADDRESS)DomainMmappedIO[domain] + Base;
|
||||||
|
|
||||||
/* Permanently map all of I/O space */
|
/* Permanently map all of I/O space */
|
||||||
if (!DomainMmappedIO[domain]) {
|
if ((fd = linuxOpenLegacy(Tag, "legacy_io")) < 0) {
|
||||||
DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag,
|
DomainMmappedIO[domain] = linuxMapPci(ScreenNum, Flags, Tag,
|
||||||
0, linuxGetIOSize(Tag),
|
0, linuxGetIOSize(Tag),
|
||||||
PCIIOC_MMAP_IS_IO);
|
PCIIOC_MMAP_IS_IO);
|
||||||
if (!DomainMmappedIO[domain])
|
/* ia64 can't mmap legacy IO port space */
|
||||||
FatalError("xf86MapDomainIO(): mmap() failure\n");
|
if (!DomainMmappedIO[domain])
|
||||||
|
return Base;
|
||||||
|
}
|
||||||
|
else { /* legacy_io file exists, encode fd */
|
||||||
|
DomainMmappedIO[domain] = (pointer)(fd << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (IOADDRESS)DomainMmappedIO[domain] + Base;
|
return (IOADDRESS)DomainMmappedIO[domain] + Base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xf86ReadDomainMemory - copy from domain memory into a caller supplied buffer
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
|
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;
|
unsigned long size;
|
||||||
int len, pagemask = getpagesize() - 1;
|
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 */
|
/* Ensure page boundaries */
|
||||||
offset = Base & ~pagemask;
|
offset = Base & ~pagemask;
|
||||||
size = ((Base + Len + pagemask) & ~pagemask) - offset;
|
size = ((Base + Len + pagemask) & ~pagemask) - offset;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "ia64Pci.h"
|
#include "ia64Pci.h"
|
||||||
|
@ -35,11 +36,24 @@
|
||||||
IA64Chipset OS_PROBE_PCI_CHIPSET(scanpciWrapperOpt flags)
|
IA64Chipset OS_PROBE_PCI_CHIPSET(scanpciWrapperOpt flags)
|
||||||
{
|
{
|
||||||
struct stat unused;
|
struct stat unused;
|
||||||
|
struct utsname utsName;
|
||||||
|
|
||||||
if (!stat("/proc/bus/mckinley/zx1",&unused)
|
if (!stat("/proc/bus/mckinley/zx1",&unused)
|
||||||
|| !stat("/proc/bus/mckinley/zx2",&unused))
|
|| !stat("/proc/bus/mckinley/zx2",&unused))
|
||||||
return ZX1_CHIPSET;
|
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;
|
return NONE_CHIPSET;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,3 +83,141 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return FALSE;
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -29,12 +29,165 @@
|
||||||
* This file contains the glue needed to support various IA-64 chipsets.
|
* 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 "460gxPCI.h"
|
||||||
#include "e8870PCI.h"
|
#include "e8870PCI.h"
|
||||||
#include "zx1PCI.h"
|
#include "zx1PCI.h"
|
||||||
|
#include "altixPCI.h"
|
||||||
#include "Pci.h"
|
#include "Pci.h"
|
||||||
#include "ia64Pci.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
|
void
|
||||||
ia64ScanPCIWrapper(scanpciWrapperOpt flags)
|
ia64ScanPCIWrapper(scanpciWrapperOpt flags)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +211,9 @@ ia64ScanPCIWrapper(scanpciWrapperOpt flags)
|
||||||
case ZX1_CHIPSET:
|
case ZX1_CHIPSET:
|
||||||
xf86PreScanZX1();
|
xf86PreScanZX1();
|
||||||
return;
|
return;
|
||||||
|
case ALTIX_CHIPSET:
|
||||||
|
xf86PreScanAltix();
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -74,6 +230,9 @@ ia64ScanPCIWrapper(scanpciWrapperOpt flags)
|
||||||
case ZX1_CHIPSET:
|
case ZX1_CHIPSET:
|
||||||
xf86PostScanZX1();
|
xf86PostScanZX1();
|
||||||
return;
|
return;
|
||||||
|
case ALTIX_CHIPSET:
|
||||||
|
xf86PostScanAltix();
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ typedef enum {
|
||||||
NONE_CHIPSET,
|
NONE_CHIPSET,
|
||||||
I460GX_CHIPSET,
|
I460GX_CHIPSET,
|
||||||
E8870_CHIPSET,
|
E8870_CHIPSET,
|
||||||
ZX1_CHIPSET
|
ZX1_CHIPSET,
|
||||||
|
ALTIX_CHIPSET
|
||||||
} IA64Chipset;
|
} IA64Chipset;
|
||||||
|
|
||||||
# ifdef OS_PROBE_PCI_CHIPSET
|
# ifdef OS_PROBE_PCI_CHIPSET
|
||||||
|
|
|
@ -256,6 +256,8 @@ resPtr xf86AccResFromOS(resPtr ret);
|
||||||
#endif /* NEED_OS_RAC_PROTOS */
|
#endif /* NEED_OS_RAC_PROTOS */
|
||||||
|
|
||||||
extern Bool xf86GetPciSizeFromOS(PCITAG tag, int indx, int* bits);
|
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 xf86MakeNewMapping(int, int, unsigned long, unsigned long, pointer);
|
||||||
extern void xf86InitVidMem(void);
|
extern void xf86InitVidMem(void);
|
||||||
|
|
Loading…
Reference in New Issue