Add domain support to linuxPciOpenFile().

Loosely based on patch from David S. Miller <davem@davemloft.net>
See also bug #2368.
This commit is contained in:
Matthias Hopf 2006-11-02 18:50:15 +01:00
parent caaa113acf
commit 1d731fc54a

View File

@ -54,6 +54,7 @@
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "Pci.h"
#include <dirent.h>
/*
* 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)
{