Added linux 2.6 compatible domain aware device scanning code.

Additional scanning code uses the /sys interface of 2.6 kernels.
Cleaned up the use of tags and already split domain/bus/dev/fn.
This commit is contained in:
Matthias Hopf 2006-11-02 15:42:03 +01:00
parent 6319f7d713
commit 5afc6c1a14
3 changed files with 67 additions and 13 deletions

View File

@ -20,6 +20,8 @@
* pciSetBitsByte() - Write an 8 bit value against a mask
* pciTag() - Return tag for a given PCI bus, device, &
* function
* pciDomTag() - Return tag for a given PCI domain, bus,
* device & function
* pciBusAddrToHostAddr() - Convert a PCI address to a host address
* pciHostAddrToBusAddr() - Convert a host address to a PCI address
* pciGetBaseSize() - Returns the number of bits in a PCI base
@ -614,6 +616,12 @@ pciTag(int busnum, int devnum, int funcnum)
return(PCI_MAKE_TAG(busnum,devnum,funcnum));
}
_X_EXPORT PCITAG
pciDomTag(int domnum, int busnum, int devnum, int funcnum)
{
return(PCI_MAKE_TAG(PCI_MAKE_BUS(domnum,busnum),devnum,funcnum));
}
#if defined(PCI_MFDEV_SUPPORT)
Bool

View File

@ -766,6 +766,7 @@ void pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val);
ADDRESS pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr);
ADDRESS pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr);
PCITAG pciTag(int busnum, int devnum, int funcnum);
PCITAG pciDomTag(int domnum, int busnum, int devnum, int funcnum);
int pciGetBaseSize(PCITAG tag, int indx, Bool destructive, Bool *min);
CARD32 pciCheckForBrokenBase(PCITAG tag,int basereg);
pointer xf86MapPciMem(int ScreenNum, int Flags, PCITAG Tag,

View File

@ -3,7 +3,9 @@
#include <xorg-config.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <dirent.h>
#include <X11/X.h>
#include "os.h"
#include "xf86.h"
@ -25,8 +27,10 @@
int lnxPciInit(void);
struct pci_dev {
unsigned int domain;
unsigned int bus;
unsigned int devfn;
unsigned int dev;
unsigned int fn;
PCIADDR_TYPE offset[7];
PCIADDR_TYPE size[7];
struct pci_dev *next;
@ -38,10 +42,53 @@ int xf86OSLinuxNumPciDevs = 0;
static struct pci_dev *xf86OSLinuxGetPciDevs(void) {
char c[0x200];
FILE *file = NULL;
DIR *dir;
struct dirent *dirent;
struct pci_dev *tmp, *ret = NULL;
unsigned int num;
unsigned int i, num, devfn;
unsigned PCIADDR_TYPE begin, end;
char *res;
/* Try 2.6 devices first, with domain support */
if ( (dir = opendir ("/sys/bus/pci/devices")) ) {
xf86OSLinuxNumPciDevs = 0;
while ( (dirent = readdir (dir)) ) {
unsigned int domain, bus, dev, fn;
if (sscanf (dirent->d_name, "%04x:%02x:%02x.%01x",
&domain, &bus, &dev, &fn) == 4) {
tmp = xcalloc (sizeof(struct pci_dev), 1);
tmp->domain = domain;
tmp->bus = bus;
tmp->dev = dev;
tmp->fn = fn;
sprintf (c, "/sys/bus/pci/devices/%12s/resource",
dirent->d_name);
i = 0;
if ( (file = fopen (c, "r")) ) {
while (i < 7 && fgets (c, 0x200, file)) {
if (sscanf (c, PCIADDR_FMT " " PCIADDR_FMT " "
PCIADDR_IGNORE_FMT, &begin, &end) == 2) {
tmp->offset[i] = begin;
tmp->size[i] = begin ? end-begin+1 : 0;
i++;
}
}
fclose (file);
}
if (i > 0) {
tmp->next = ret;
ret = tmp;
xf86OSLinuxNumPciDevs++;
} else
xfree (tmp);
}
}
closedir (dir);
}
if (ret)
return ret;
file = fopen("/proc/bus/pci/devices", "r");
if (!file) return NULL;
@ -70,9 +117,11 @@ static struct pci_dev *xf86OSLinuxGetPciDevs(void) {
"\t" PCIADDR_FMT
"\t" PCIADDR_FMT
"\t" PCIADDR_FMT,
&tmp->bus,&tmp->devfn,&tmp->offset[0],&tmp->offset[1],&tmp->offset[2],&tmp->offset[3],
&tmp->bus,&devfn,&tmp->offset[0],&tmp->offset[1],&tmp->offset[2],&tmp->offset[3],
&tmp->offset[4],&tmp->offset[5],&tmp->offset[6], &tmp->size[0], &tmp->size[1], &tmp->size[2],
&tmp->size[3], &tmp->size[4], &tmp->size[5], &tmp->size[6]);
tmp->dev = devfn >> 3;
tmp->fn = devfn & 0x7;
if (num != 16) { /* apparantly not 2.3 style */
xfree(tmp);
fclose(file);
@ -114,10 +163,8 @@ xf86GetPciSizeFromOS(PCITAG tag, int index, int* bits)
return FALSE;
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
dev = device->devfn >> 3;
fn = device->devfn & 0x7;
if (tag == pciTag(device->bus,dev,fn)) {
*bits = 0;
if (tag == pciDomTag (device->domain, device->bus,
device->dev, device->fn)) {
if (device->size[index] != 0) {
Size = device->size[index] - ((PCIADDR_TYPE) 1);
while (Size & ((PCIADDR_TYPE) 0x01)) {
@ -151,9 +198,8 @@ xf86GetPciOffsetFromOS(PCITAG tag, int index, unsigned long* bases)
return FALSE;
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
dev = device->devfn >> 3;
fn = device->devfn & 0x7;
if (tag == pciTag(device->bus,dev,fn)) {
if (tag == pciDomTag (device->domain, device->bus,
device->dev, device->fn)) {
/* return the offset for the index requested */
*bases = device->offset[index];
return TRUE;
@ -179,9 +225,8 @@ xf86GetOSOffsetFromPCI(PCITAG tag, int space, unsigned long base)
}
for (device = xf86OSLinuxPCIDevs; device; device = device->next) {
dev = device->devfn >> 3;
fn = device->devfn & 0x7;
if (tag == pciTag(device->bus, dev, fn)) {
if (tag == pciDomTag (device->domain, device->bus,
device->dev, device->fn)) {
/* ok now look through all the BAR values of this device */
pciConfigPtr pDev = xf86GetPciConfigFromTag(tag);