diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/hw/xfree86/os-support/linux/lnx_pci.c | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/hw/xfree86/os-support/linux/lnx_pci.c')
-rw-r--r-- | xorg-server/hw/xfree86/os-support/linux/lnx_pci.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_pci.c b/xorg-server/hw/xfree86/os-support/linux/lnx_pci.c new file mode 100644 index 000000000..8eedfa49f --- /dev/null +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_pci.c @@ -0,0 +1,193 @@ + +#ifdef HAVE_XORG_CONFIG_H +#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" +#include "xf86Priv.h" +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" +#include "xf86Pci.h" +#include "Pci.h" + +#ifdef __sparc__ +#define PCIADDR_TYPE long long +#define PCIADDR_IGNORE_FMT "%*x" +#define PCIADDR_FMT "%llx" +#else +#define PCIADDR_TYPE long +#define PCIADDR_IGNORE_FMT "%*x" +#define PCIADDR_FMT "%lx" +#endif + +struct pci_dev { + unsigned int domain; + unsigned int bus; + unsigned int dev; + unsigned int fn; + PCIADDR_TYPE offset[7]; + PCIADDR_TYPE size[7]; + struct pci_dev *next; +}; + +struct pci_dev *xf86OSLinuxPCIDevs = NULL; +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 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; + + xf86OSLinuxNumPciDevs = 0; + + do { + res = fgets(c, 0x1ff, file); + if (res) { + tmp = xcalloc(sizeof(struct pci_dev),1); + 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, + &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); + return NULL; + } + if (ret) { + tmp->next = ret; + } + ret = tmp; + xf86OSLinuxNumPciDevs++; + } + } while (res); + fclose(file); + return ret; +} + +/* 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) +{ + unsigned int ndx; + struct pci_dev *device; + struct pci_device *dev; + + if (!xf86OSLinuxPCIDevs) { + xf86OSLinuxPCIDevs = xf86OSLinuxGetPciDevs(); + } + if (!xf86OSLinuxPCIDevs) { + return FALSE; + } + + for (device = xf86OSLinuxPCIDevs; device; device = device->next) { + dev = pci_device_find_by_slot(device->domain, device->bus, + device->dev, device->fn); + if (dev != NULL) { + /* ok now look through all the BAR values of this device */ + for (ndx=0; ndx<7; ndx++) { + uint32_t savePtr; + uint32_t flagMask; + + /* The ROM BAR isn't with the other BARs. + */ + const pciaddr_t offset = (ndx == 6) + ? (4 * 12) : (4 * ndx) + 16; + + pci_device_cfg_read_u32(dev, &savePtr, offset); + + /* Ignore unset base addresses. The kernel may have reported + * non-zero size and address even if they are disabled (e.g., + * disabled ROM BAR). + */ + if (savePtr == 0) + continue; + + /* Remove memory attribute bits, different for IO + * and memory ranges. + */ + flagMask = (savePtr & 0x1) ? ~0x3UL : ~0xFUL; + savePtr &= flagMask; + + /* find the index of the incoming base */ + if (base >= savePtr && base < (savePtr + device->size[ndx])) { + return (device->offset[ndx] & flagMask) + (base - savePtr); + } + } + } + } + + return 0; +} |