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 "xf86Priv.h"
|
||||||
#include "xf86_OSlib.h"
|
#include "xf86_OSlib.h"
|
||||||
#include "Pci.h"
|
#include "Pci.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* linux platform specific PCI access functions -- using /proc/bus/pci
|
* 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 CARD16 linuxPciCfgReadWord(PCITAG tag, int off);
|
||||||
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val);
|
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val);
|
||||||
static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len);
|
static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len);
|
||||||
|
static Bool linuxDomainSupport(void);
|
||||||
|
|
||||||
static pciBusFuncs_t linuxFuncs0 = {
|
static pciBusFuncs_t linuxFuncs0 = {
|
||||||
/* pciReadLong */ linuxPciCfgRead,
|
/* pciReadLong */ linuxPciCfgRead,
|
||||||
|
@ -116,6 +118,8 @@ static pciBusInfo_t linuxPci0 = {
|
||||||
/* from lnx_pci.c. */
|
/* from lnx_pci.c. */
|
||||||
extern int lnxPciInit(void);
|
extern int lnxPciInit(void);
|
||||||
|
|
||||||
|
static Bool domain_support = FALSE;
|
||||||
|
|
||||||
void
|
void
|
||||||
linuxPciInit()
|
linuxPciInit()
|
||||||
{
|
{
|
||||||
|
@ -126,6 +130,9 @@ linuxPciInit()
|
||||||
we'll need a fallback for 2.0 kernels here */
|
we'll need a fallback for 2.0 kernels here */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifndef INCLUDE_XF86_NO_DOMAIN
|
||||||
|
domain_support = linuxDomainSupport();
|
||||||
|
#endif
|
||||||
pciNumBuses = 1;
|
pciNumBuses = 1;
|
||||||
pciBusInfo[0] = &linuxPci0;
|
pciBusInfo[0] = &linuxPci0;
|
||||||
pciFindFirstFP = pciGenFindFirst;
|
pciFindFirstFP = pciGenFindFirst;
|
||||||
|
@ -137,13 +144,14 @@ linuxPciInit()
|
||||||
static int
|
static int
|
||||||
linuxPciOpenFile(PCITAG tag, Bool write)
|
linuxPciOpenFile(PCITAG tag, Bool write)
|
||||||
{
|
{
|
||||||
static int lbus,ldev,lfunc,fd = -1,is_write = 0;
|
static int ldomain, lbus,ldev,lfunc,fd = -1,is_write = 0;
|
||||||
int bus, dev, func;
|
int domain, bus, dev, func;
|
||||||
char file[64];
|
char file[64];
|
||||||
struct stat ignored;
|
struct stat ignored;
|
||||||
static int is26 = -1;
|
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);
|
dev = PCI_DEV_FROM_TAG(tag);
|
||||||
func = PCI_FUNC_FROM_TAG(tag);
|
func = PCI_FUNC_FROM_TAG(tag);
|
||||||
if (is26 == -1) {
|
if (is26 == -1) {
|
||||||
|
@ -153,30 +161,41 @@ linuxPciOpenFile(PCITAG tag, Bool write)
|
||||||
is26 = 1;
|
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) {
|
|| bus != lbus || dev != ldev || func != lfunc) {
|
||||||
if (fd != -1)
|
if (fd != -1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
if (is26)
|
if (is26)
|
||||||
sprintf(file,"/sys/bus/pci/devices/0000:%02x:%02x.%01x/config",
|
sprintf(file,"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config",
|
||||||
bus, dev, func);
|
domain, bus, dev, func);
|
||||||
else {
|
else {
|
||||||
if (bus < 256) {
|
if (bus < 256) {
|
||||||
sprintf(file,"/proc/bus/pci/%02x",bus);
|
sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus);
|
||||||
if (stat(file, &ignored) < 0)
|
if (stat(file, &ignored) < 0) {
|
||||||
sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x",
|
if (domain == 0)
|
||||||
bus, dev, func);
|
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x",
|
||||||
else
|
bus, dev, func);
|
||||||
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x",
|
else
|
||||||
bus, dev, func);
|
goto bail;
|
||||||
|
} else
|
||||||
|
sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x",
|
||||||
|
domain, bus, dev, func);
|
||||||
} else {
|
} else {
|
||||||
sprintf(file,"/proc/bus/pci/%04x",bus);
|
sprintf(file, "/proc/bus/pci/%04x:%04x", domain, bus);
|
||||||
if (stat(file, &ignored) < 0)
|
if (stat(file, &ignored) < 0) {
|
||||||
sprintf(file, "/proc/bus/pci/0000:%04x/%02x.%1x",
|
if (domain == 0)
|
||||||
bus, dev, func);
|
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x",
|
||||||
else
|
bus, dev, func);
|
||||||
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x",
|
else
|
||||||
bus, dev, func);
|
goto bail;
|
||||||
|
} else
|
||||||
|
sprintf(file, "/proc/bus/pci/%04x:%04x/%02x.%1x",
|
||||||
|
domain, bus, dev, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (write) {
|
if (write) {
|
||||||
|
@ -191,7 +210,8 @@ linuxPciOpenFile(PCITAG tag, Bool write)
|
||||||
fd = open(file,O_RDONLY);
|
fd = open(file,O_RDONLY);
|
||||||
is_write = FALSE;
|
is_write = FALSE;
|
||||||
}
|
}
|
||||||
|
bail:
|
||||||
|
ldomain = domain;
|
||||||
lbus = bus;
|
lbus = bus;
|
||||||
ldev = dev;
|
ldev = dev;
|
||||||
lfunc = func;
|
lfunc = func;
|
||||||
|
@ -489,6 +509,32 @@ linuxGetSizes(PCITAG Tag, unsigned long *io_size, unsigned long *mem_size)
|
||||||
*mem_size = sizes->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
|
_X_EXPORT int
|
||||||
xf86GetPciDomain(PCITAG Tag)
|
xf86GetPciDomain(PCITAG Tag)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue