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:
parent
caaa113acf
commit
1d731fc54a
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user