|
Lines 55-60
Link Here
|
| 55 |
#include "xf86Priv.h" |
55 |
#include "xf86Priv.h" |
| 56 |
#include "xf86_OSlib.h" |
56 |
#include "xf86_OSlib.h" |
| 57 |
#include "Pci.h" |
57 |
#include "Pci.h" |
|
|
58 |
#include <dirent.h> |
| 58 |
|
59 |
|
| 59 |
/* |
60 |
/* |
| 60 |
* linux platform specific PCI access functions -- using /proc/bus/pci |
61 |
* linux platform specific PCI access functions -- using /proc/bus/pci |
|
Lines 73-78
static CARD8 linuxPciCfgReadByte(PCITAG
Link Here
|
| 73 |
static void linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val); |
74 |
static void linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val); |
| 74 |
static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); |
75 |
static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); |
| 75 |
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); |
76 |
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); |
|
|
77 |
static Bool linuxDomainSupport(void); |
| 76 |
|
78 |
|
| 77 |
static pciBusFuncs_t linuxFuncs0 = { |
79 |
static pciBusFuncs_t linuxFuncs0 = { |
| 78 |
/* pciReadLong */ linuxPciCfgRead, |
80 |
/* pciReadLong */ linuxPciCfgRead, |
|
Lines 111-116
static pciBusInfo_t linuxPci0 = {
Link Here
|
| 111 |
/* bridge */ NULL |
113 |
/* bridge */ NULL |
| 112 |
}; |
114 |
}; |
| 113 |
|
115 |
|
|
|
116 |
static Bool domain_support = FALSE; |
| 117 |
|
| 114 |
void |
118 |
void |
| 115 |
linuxPciInit() |
119 |
linuxPciInit() |
| 116 |
{ |
120 |
{ |
|
Lines 121-163
linuxPciInit()
Link Here
|
| 121 |
we'll need a fallback for 2.0 kernels here */ |
125 |
we'll need a fallback for 2.0 kernels here */ |
| 122 |
return; |
126 |
return; |
| 123 |
} |
127 |
} |
|
|
128 |
|
| 129 |
#ifndef INCLUDE_XF86_NO_DOMAIN |
| 130 |
domain_support = linuxDomainSupport(); |
| 131 |
#endif |
| 124 |
pciNumBuses = 1; |
132 |
pciNumBuses = 1; |
| 125 |
pciBusInfo[0] = &linuxPci0; |
133 |
pciBusInfo[0] = &linuxPci0; |
| 126 |
pciFindFirstFP = pciGenFindFirst; |
134 |
pciFindFirstFP = pciGenFindFirst; |
| 127 |
pciFindNextFP = pciGenFindNext; |
135 |
pciFindNextFP = pciGenFindNext; |
|
|
136 |
|
| 137 |
return; |
| 128 |
} |
138 |
} |
| 129 |
|
139 |
|
| 130 |
static int |
140 |
static int |
| 131 |
linuxPciOpenFile(PCITAG tag, Bool write) |
141 |
linuxPciOpenFile(PCITAG tag, Bool write) |
| 132 |
{ |
142 |
{ |
| 133 |
static int lbus,ldev,lfunc,fd = -1,is_write = 0; |
143 |
static int ldomain, lbus,ldev,lfunc,fd = -1,is_write = 0; |
| 134 |
int bus, dev, func; |
144 |
int domain, bus, dev, func; |
| 135 |
char file[32]; |
145 |
char file[32]; |
| 136 |
struct stat ignored; |
146 |
struct stat ignored; |
| 137 |
|
147 |
|
| 138 |
bus = PCI_BUS_FROM_TAG(tag); |
148 |
domain = PCI_DOM_FROM_TAG(tag); |
|
|
149 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)); |
| 139 |
dev = PCI_DEV_FROM_TAG(tag); |
150 |
dev = PCI_DEV_FROM_TAG(tag); |
| 140 |
func = PCI_FUNC_FROM_TAG(tag); |
151 |
func = PCI_FUNC_FROM_TAG(tag); |
| 141 |
if (fd == -1 || (write && (!is_write)) |
152 |
|
| 142 |
|| bus != lbus || dev != ldev || func != lfunc) { |
153 |
if (!domain_support && domain > 0) |
| 143 |
if (fd != -1) |
154 |
return -1; |
|
|
155 |
|
| 156 |
if (fd == -1 || (write && (!is_write)) || bus != lbus |
| 157 |
|| dev != ldev || func != lfunc || domain != ldomain) { |
| 158 |
|
| 159 |
if (fd != -1) { |
| 144 |
close(fd); |
160 |
close(fd); |
|
|
161 |
fd = -1; |
| 162 |
} |
| 145 |
if (bus < 256) { |
163 |
if (bus < 256) { |
| 146 |
sprintf(file,"/proc/bus/pci/%02x",bus); |
164 |
sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus); |
| 147 |
if (stat(file, &ignored) < 0) |
165 |
if (stat(file, &ignored) < 0) { |
| 148 |
sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x", |
166 |
if (domain == 0) |
| 149 |
bus, dev, func); |
167 |
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", |
| 150 |
else |
168 |
bus, dev, func); |
| 151 |
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", |
169 |
else goto bail; |
| 152 |
bus, dev, func); |
170 |
} else |
|
|
171 |
sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x", |
| 172 |
domain, bus, dev, func); |
| 153 |
} else { |
173 |
} else { |
| 154 |
sprintf(file,"/proc/bus/pci/%04x",bus); |
174 |
sprintf(file, "/proc/bus/pci/%04x:%04x", domain, bus); |
| 155 |
if (stat(file, &ignored) < 0) |
175 |
if (stat(file, &ignored) < 0) { |
| 156 |
sprintf(file, "/proc/bus/pci/0000:%04x/%02x.%1x", |
176 |
if (domain == 0) |
| 157 |
bus, dev, func); |
177 |
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", |
| 158 |
else |
178 |
bus, dev, func); |
| 159 |
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", |
179 |
else goto bail; |
| 160 |
bus, dev, func); |
180 |
} else |
|
|
181 |
sprintf(file, "/proc/bus/pci/%04x:%04x/%02x.%1x", |
| 182 |
domain, bus, dev, func); |
| 161 |
} |
183 |
} |
| 162 |
if (write) { |
184 |
if (write) { |
| 163 |
fd = open(file,O_RDWR); |
185 |
fd = open(file,O_RDWR); |
|
Lines 171-177
linuxPciOpenFile(PCITAG tag, Bool write)
Link Here
|
| 171 |
fd = open(file,O_RDONLY); |
193 |
fd = open(file,O_RDONLY); |
| 172 |
is_write = FALSE; |
194 |
is_write = FALSE; |
| 173 |
} |
195 |
} |
| 174 |
|
196 |
bail: |
|
|
197 |
ldomain = domain; |
| 175 |
lbus = bus; |
198 |
lbus = bus; |
| 176 |
ldev = dev; |
199 |
ldev = dev; |
| 177 |
lfunc = func; |
200 |
lfunc = func; |
|
Lines 482-487
linuxGetSizes(PCITAG Tag, unsigned long
Link Here
|
| 482 |
} |
505 |
} |
| 483 |
} |
506 |
} |
| 484 |
|
507 |
|
|
|
508 |
static Bool |
| 509 |
linuxDomainSupport(void) |
| 510 |
{ |
| 511 |
DIR *dir; |
| 512 |
struct dirent *dirent; |
| 513 |
char *end; |
| 514 |
|
| 515 |
if (!(dir = opendir("/proc/bus/pci"))) |
| 516 |
return FALSE; |
| 517 |
while (1) { |
| 518 |
if (!(dirent = readdir(dir))) |
| 519 |
return FALSE; |
| 520 |
strtol(dirent->d_name,&end,16); |
| 521 |
/* entry of the form xx or xxxx : x=[0..f] no domain */ |
| 522 |
if (*end == '\0') |
| 523 |
return FALSE; |
| 524 |
else if (*end == ':') { |
| 525 |
/* ':' found immediately after: verify for xxxx:xx or xxxx:xxxx */ |
| 526 |
strtol(end + 1,&end,16); |
| 527 |
if (*end == '\0') |
| 528 |
return TRUE; |
| 529 |
} |
| 530 |
} |
| 531 |
return FALSE; |
| 532 |
} |
| 533 |
|
| 485 |
int |
534 |
int |
| 486 |
xf86GetPciDomain(PCITAG Tag) |
535 |
xf86GetPciDomain(PCITAG Tag) |
| 487 |
{ |
536 |
{ |
|
Lines 491-497
xf86GetPciDomain(PCITAG Tag)
Link Here
|
| 491 |
pPCI = xf86GetPciHostConfigFromTag(Tag); |
540 |
pPCI = xf86GetPciHostConfigFromTag(Tag); |
| 492 |
|
541 |
|
| 493 |
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) |
542 |
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) |
| 494 |
return result; |
543 |
return result + 1; |
| 495 |
|
544 |
|
| 496 |
if (!pPCI || pPCI->fakeDevice) |
545 |
if (!pPCI || pPCI->fakeDevice) |
| 497 |
return 1; /* Domain 0 is reserved */ |
546 |
return 1; /* Domain 0 is reserved */ |
|
Lines 724-730
xf86ReadDomainMemory(PCITAG Tag, ADDRESS
Link Here
|
| 724 |
struct stat st; |
773 |
struct stat st; |
| 725 |
|
774 |
|
| 726 |
dom = PCI_DOM_FROM_TAG(Tag); |
775 |
dom = PCI_DOM_FROM_TAG(Tag); |
| 727 |
bus = PCI_BUS_FROM_TAG(Tag); |
776 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 728 |
dev = PCI_DEV_FROM_TAG(Tag); |
777 |
dev = PCI_DEV_FROM_TAG(Tag); |
| 729 |
func = PCI_FUNC_FROM_TAG(Tag); |
778 |
func = PCI_FUNC_FROM_TAG(Tag); |
| 730 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
779 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
|
Lines 892-894
xf86AccResFromOS(resPtr pRes)
Link Here
|
| 892 |
} |
941 |
} |
| 893 |
|
942 |
|
| 894 |
#endif /* !INCLUDE_XF86_NO_DOMAIN */ |
943 |
#endif /* !INCLUDE_XF86_NO_DOMAIN */ |
|
|
944 |
|
| 945 |
#ifdef __ia64__ |
| 946 |
static PCITAG ia64linuxPciFindFirst(void); |
| 947 |
static PCITAG ia64linuxPciFindNext(void); |
| 948 |
|
| 949 |
void |
| 950 |
ia64linuxPciInit() |
| 951 |
{ |
| 952 |
struct stat st; |
| 953 |
|
| 954 |
linuxPciInit(); |
| 955 |
|
| 956 |
if (!stat("/proc/sgi_sn/licenseID", &st) && pciNumBuses) { |
| 957 |
/* Be a little paranoid here and only use this code for Altix systems. |
| 958 |
* It is generic, so it should work on any system, but depends on |
| 959 |
* /proc/bus/pci entries for each domain/bus combination. Altix is |
| 960 |
* guaranteed a recent enough kernel to have them. |
| 961 |
*/ |
| 962 |
pciFindFirstFP = ia64linuxPciFindFirst; |
| 963 |
pciFindNextFP = ia64linuxPciFindNext; |
| 964 |
} |
| 965 |
} |
| 966 |
|
| 967 |
static DIR *busdomdir; |
| 968 |
static DIR *devdir; |
| 969 |
|
| 970 |
static PCITAG |
| 971 |
ia64linuxPciFindFirst(void) |
| 972 |
{ |
| 973 |
busdomdir = opendir("/proc/bus/pci"); |
| 974 |
devdir = NULL; |
| 975 |
|
| 976 |
return ia64linuxPciFindNext(); |
| 977 |
} |
| 978 |
|
| 979 |
static struct dirent *getnextbus(int *domain, int *bus) |
| 980 |
{ |
| 981 |
struct dirent *entry; |
| 982 |
int dombus; |
| 983 |
|
| 984 |
for (;;) { |
| 985 |
entry = readdir(busdomdir); |
| 986 |
if (entry == NULL) { |
| 987 |
*domain = 0; |
| 988 |
*bus = 0; |
| 989 |
closedir(busdomdir); |
| 990 |
return NULL; |
| 991 |
} |
| 992 |
if (sscanf(entry->d_name, "%04x:%02x", domain, bus) != 2) |
| 993 |
continue; |
| 994 |
dombus = PCI_MAKE_BUS(*domain, *bus); |
| 995 |
|
| 996 |
if (pciNumBuses <= dombus) |
| 997 |
pciNumBuses = dombus + 1; |
| 998 |
if (!pciBusInfo[dombus]) { |
| 999 |
pciBusInfo[dombus] = xnfalloc(sizeof(pciBusInfo_t)); |
| 1000 |
*pciBusInfo[dombus] = *pciBusInfo[0]; |
| 1001 |
} |
| 1002 |
|
| 1003 |
return entry; |
| 1004 |
} |
| 1005 |
} |
| 1006 |
|
| 1007 |
static PCITAG |
| 1008 |
ia64linuxPciFindNext(void) |
| 1009 |
{ |
| 1010 |
struct dirent *entry; |
| 1011 |
char file[40]; |
| 1012 |
static int bus, dev, func, domain; |
| 1013 |
PCITAG pciDeviceTag; |
| 1014 |
CARD32 devid; |
| 1015 |
|
| 1016 |
for (;;) { |
| 1017 |
if (devdir == NULL) { |
| 1018 |
entry = getnextbus(&domain, &bus); |
| 1019 |
if (!entry) |
| 1020 |
return PCI_NOT_FOUND; |
| 1021 |
snprintf(file, 40, "/proc/bus/pci/%s", entry->d_name); |
| 1022 |
devdir = opendir(file); |
| 1023 |
if (!devdir) |
| 1024 |
return PCI_NOT_FOUND; |
| 1025 |
|
| 1026 |
} |
| 1027 |
|
| 1028 |
entry = readdir(devdir); |
| 1029 |
|
| 1030 |
if (entry == NULL) { |
| 1031 |
closedir(devdir); |
| 1032 |
devdir = NULL; |
| 1033 |
continue; |
| 1034 |
} |
| 1035 |
|
| 1036 |
if (sscanf(entry->d_name, "%02x . %01x", &dev, &func) == 2) { |
| 1037 |
pciDeviceTag = PCI_MAKE_TAG(PCI_MAKE_BUS(domain, bus), dev, func); |
| 1038 |
devid = pciReadLong(pciDeviceTag, PCI_ID_REG); |
| 1039 |
if ((devid & pciDevidMask) == pciDevid) |
| 1040 |
/* Yes - Return it. Otherwise, next device */ |
| 1041 |
return pciDeviceTag; |
| 1042 |
} |
| 1043 |
} |
| 1044 |
} |
| 1045 |
#endif |