|
Lines 54-59
Link Here
|
| 54 |
#include "xf86Priv.h" |
54 |
#include "xf86Priv.h" |
| 55 |
#include "xf86_OSlib.h" |
55 |
#include "xf86_OSlib.h" |
| 56 |
#include "Pci.h" |
56 |
#include "Pci.h" |
|
|
57 |
#include <dirent.h> |
| 57 |
|
58 |
|
| 58 |
/* |
59 |
/* |
| 59 |
* linux platform specific PCI access functions -- using /proc/bus/pci |
60 |
* linux platform specific PCI access functions -- using /proc/bus/pci |
|
Lines 73-78
static void linuxPciCfgWriteByte(PCITAG
Link Here
|
| 73 |
static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); |
74 |
static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); |
| 74 |
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); |
75 |
static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); |
| 75 |
static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len); |
76 |
static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len); |
|
|
77 |
static Bool linuxDomainSupport(void); |
| 76 |
|
78 |
|
| 77 |
static pciBusFuncs_t linuxFuncs0 = { |
79 |
static pciBusFuncs_t linuxFuncs0 = { |
| 78 |
/* pciReadLong */ linuxPciCfgRead, |
80 |
/* pciReadLong */ linuxPciCfgRead, |
|
Lines 110-115
static pciBusInfo_t linuxPci0 = {
Link Here
|
| 110 |
/* from lnx_pci.c. */ |
112 |
/* from lnx_pci.c. */ |
| 111 |
extern int lnxPciInit(void); |
113 |
extern int lnxPciInit(void); |
| 112 |
|
114 |
|
|
|
115 |
static Bool domain_support = FALSE; |
| 116 |
|
| 113 |
void |
117 |
void |
| 114 |
linuxPciInit() |
118 |
linuxPciInit() |
| 115 |
{ |
119 |
{ |
|
Lines 120-125
linuxPciInit()
Link Here
|
| 120 |
we'll need a fallback for 2.0 kernels here */ |
124 |
we'll need a fallback for 2.0 kernels here */ |
| 121 |
return; |
125 |
return; |
| 122 |
} |
126 |
} |
|
|
127 |
#ifndef INCLUDE_XF86_NO_DOMAIN |
| 128 |
domain_support = linuxDomainSupport(); |
| 129 |
#endif |
| 123 |
pciNumBuses = 1; |
130 |
pciNumBuses = 1; |
| 124 |
pciBusInfo[0] = &linuxPci0; |
131 |
pciBusInfo[0] = &linuxPci0; |
| 125 |
pciFindFirstFP = pciGenFindFirst; |
132 |
pciFindFirstFP = pciGenFindFirst; |
|
Lines 131-143
linuxPciInit()
Link Here
|
| 131 |
static int |
138 |
static int |
| 132 |
linuxPciOpenFile(PCITAG tag, Bool write) |
139 |
linuxPciOpenFile(PCITAG tag, Bool write) |
| 133 |
{ |
140 |
{ |
| 134 |
static int lbus,ldev,lfunc,fd = -1,is_write = 0; |
141 |
static int ldomain, lbus,ldev,lfunc,fd = -1,is_write = 0; |
| 135 |
int bus, dev, func; |
142 |
int domain, bus, dev, func; |
| 136 |
char file[64]; |
143 |
char file[64]; |
| 137 |
struct stat ignored; |
144 |
struct stat ignored; |
| 138 |
static int is26 = -1; |
145 |
static int is26 = -1; |
| 139 |
|
146 |
|
| 140 |
bus = PCI_BUS_FROM_TAG(tag); |
147 |
domain = PCI_DOM_FROM_TAG(tag); |
|
|
148 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)); |
| 141 |
dev = PCI_DEV_FROM_TAG(tag); |
149 |
dev = PCI_DEV_FROM_TAG(tag); |
| 142 |
func = PCI_FUNC_FROM_TAG(tag); |
150 |
func = PCI_FUNC_FROM_TAG(tag); |
| 143 |
if (is26 == -1) { |
151 |
if (is26 == -1) { |
|
Lines 147-176
linuxPciOpenFile(PCITAG tag, Bool write)
Link Here
|
| 147 |
is26 = 1; |
155 |
is26 = 1; |
| 148 |
} |
156 |
} |
| 149 |
|
157 |
|
| 150 |
if (fd == -1 || (write && (!is_write)) |
158 |
if (!domain_support && domain > 0) |
|
|
159 |
return -1; |
| 160 |
|
| 161 |
if (fd == -1 || (write && (!is_write)) || domain != ldomain |
| 151 |
|| bus != lbus || dev != ldev || func != lfunc) { |
162 |
|| bus != lbus || dev != ldev || func != lfunc) { |
| 152 |
if (fd != -1) |
163 |
if (fd != -1) { |
| 153 |
close(fd); |
164 |
close(fd); |
|
|
165 |
fd = -1; |
| 166 |
} |
| 154 |
if (is26) |
167 |
if (is26) |
| 155 |
sprintf(file,"/sys/bus/pci/devices/0000:%02x:%02x.%01x/config", |
168 |
sprintf(file,"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config", |
| 156 |
bus, dev, func); |
169 |
domain, bus, dev, func); |
| 157 |
else { |
170 |
else { |
| 158 |
if (bus < 256) { |
171 |
if (bus < 256) { |
| 159 |
sprintf(file,"/proc/bus/pci/%02x",bus); |
172 |
sprintf(file, "/proc/bus/pci/%04x:%02x", domain, bus); |
| 160 |
if (stat(file, &ignored) < 0) |
173 |
if (stat(file, &ignored) < 0) { |
| 161 |
sprintf(file, "/proc/bus/pci/0000:%02x/%02x.%1x", |
174 |
if (domain == 0) |
| 162 |
bus, dev, func); |
175 |
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", |
| 163 |
else |
176 |
bus, dev, func); |
| 164 |
sprintf(file, "/proc/bus/pci/%02x/%02x.%1x", |
177 |
else |
| 165 |
bus, dev, func); |
178 |
goto bail; |
|
|
179 |
} else |
| 180 |
sprintf(file, "/proc/bus/pci/%04x:%02x/%02x.%1x", |
| 181 |
domain, bus, dev, func); |
| 166 |
} else { |
182 |
} else { |
| 167 |
sprintf(file,"/proc/bus/pci/%04x",bus); |
183 |
sprintf(file, "/proc/bus/pci/%04x:%04x", domain, bus); |
| 168 |
if (stat(file, &ignored) < 0) |
184 |
if (stat(file, &ignored) < 0) { |
| 169 |
sprintf(file, "/proc/bus/pci/0000:%04x/%02x.%1x", |
185 |
if (domain == 0) |
| 170 |
bus, dev, func); |
186 |
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", |
| 171 |
else |
187 |
bus, dev, func); |
| 172 |
sprintf(file, "/proc/bus/pci/%04x/%02x.%1x", |
188 |
else |
| 173 |
bus, dev, func); |
189 |
goto bail; |
|
|
190 |
} else |
| 191 |
sprintf(file, "/proc/bus/pci/%04x:%04x/%02x.%1x", |
| 192 |
domain, bus, dev, func); |
| 174 |
} |
193 |
} |
| 175 |
} |
194 |
} |
| 176 |
if (write) { |
195 |
if (write) { |
|
Lines 185-191
linuxPciOpenFile(PCITAG tag, Bool write)
Link Here
|
| 185 |
fd = open(file,O_RDONLY); |
204 |
fd = open(file,O_RDONLY); |
| 186 |
is_write = FALSE; |
205 |
is_write = FALSE; |
| 187 |
} |
206 |
} |
| 188 |
|
207 |
bail: |
|
|
208 |
ldomain = domain; |
| 189 |
lbus = bus; |
209 |
lbus = bus; |
| 190 |
ldev = dev; |
210 |
ldev = dev; |
| 191 |
lfunc = func; |
211 |
lfunc = func; |
|
Lines 483-488
linuxGetSizes(PCITAG Tag, unsigned long
Link Here
|
| 483 |
*mem_size = sizes->mem_size; |
503 |
*mem_size = sizes->mem_size; |
| 484 |
} |
504 |
} |
| 485 |
|
505 |
|
|
|
506 |
static Bool |
| 507 |
linuxDomainSupport(void) |
| 508 |
{ |
| 509 |
DIR *dir; |
| 510 |
struct dirent *dirent; |
| 511 |
char *end; |
| 512 |
|
| 513 |
if (!(dir = opendir("/proc/bus/pci"))) |
| 514 |
return FALSE; |
| 515 |
while (1) { |
| 516 |
if (!(dirent = readdir(dir))) |
| 517 |
return FALSE; |
| 518 |
strtol(dirent->d_name,&end,16); |
| 519 |
/* entry of the form xx or xxxx : x=[0..f] no domain */ |
| 520 |
if (*end == '\0') |
| 521 |
return FALSE; |
| 522 |
else if (*end == ':') { |
| 523 |
/* ':' found immediately after: verify for xxxx:xx or xxxx:xxxx */ |
| 524 |
strtol(end + 1,&end,16); |
| 525 |
if (*end == '\0') |
| 526 |
return TRUE; |
| 527 |
} |
| 528 |
} |
| 529 |
return FALSE; |
| 530 |
} |
| 531 |
|
| 486 |
_X_EXPORT int |
532 |
_X_EXPORT int |
| 487 |
xf86GetPciDomain(PCITAG Tag) |
533 |
xf86GetPciDomain(PCITAG Tag) |
| 488 |
{ |
534 |
{ |
|
Lines 492-498
xf86GetPciDomain(PCITAG Tag)
Link Here
|
| 492 |
pPCI = xf86GetPciHostConfigFromTag(Tag); |
538 |
pPCI = xf86GetPciHostConfigFromTag(Tag); |
| 493 |
|
539 |
|
| 494 |
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) |
540 |
if (pPCI && (result = PCI_DOM_FROM_BUS(pPCI->busnum))) |
| 495 |
return result; |
541 |
return result + 1; |
| 496 |
|
542 |
|
| 497 |
if (!pPCI || pPCI->fakeDevice) |
543 |
if (!pPCI || pPCI->fakeDevice) |
| 498 |
return 1; /* Domain 0 is reserved */ |
544 |
return 1; /* Domain 0 is reserved */ |
|
Lines 725-731
xf86ReadDomainMemory(PCITAG Tag, ADDRESS
Link Here
|
| 725 |
struct stat st; |
771 |
struct stat st; |
| 726 |
|
772 |
|
| 727 |
dom = PCI_DOM_FROM_TAG(Tag); |
773 |
dom = PCI_DOM_FROM_TAG(Tag); |
| 728 |
bus = PCI_BUS_FROM_TAG(Tag); |
774 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 729 |
dev = PCI_DEV_FROM_TAG(Tag); |
775 |
dev = PCI_DEV_FROM_TAG(Tag); |
| 730 |
func = PCI_FUNC_FROM_TAG(Tag); |
776 |
func = PCI_FUNC_FROM_TAG(Tag); |
| 731 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
777 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
|
Lines 906-912
int linuxPciHandleBIOS(PCITAG Tag, int b
Link Here
|
| 906 |
int sofar = 0; |
952 |
int sofar = 0; |
| 907 |
|
953 |
|
| 908 |
dom = PCI_DOM_FROM_TAG(Tag); |
954 |
dom = PCI_DOM_FROM_TAG(Tag); |
| 909 |
bus = PCI_BUS_FROM_TAG(Tag); |
955 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 910 |
dev = PCI_DEV_FROM_TAG(Tag); |
956 |
dev = PCI_DEV_FROM_TAG(Tag); |
| 911 |
func = PCI_FUNC_FROM_TAG(Tag); |
957 |
func = PCI_FUNC_FROM_TAG(Tag); |
| 912 |
sprintf(file, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/rom", |
958 |
sprintf(file, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/rom", |
|
Lines 936-938
int linuxPciHandleBIOS(PCITAG Tag, int b
Link Here
|
| 936 |
} |
982 |
} |
| 937 |
return 0; |
983 |
return 0; |
| 938 |
} |
984 |
} |
|
|
985 |
|
| 986 |
#ifdef __ia64__ |
| 987 |
static PCITAG ia64linuxPciFindFirst(void); |
| 988 |
static PCITAG ia64linuxPciFindNext(void); |
| 989 |
|
| 990 |
void |
| 991 |
ia64linuxPciInit() |
| 992 |
{ |
| 993 |
struct stat st; |
| 994 |
|
| 995 |
linuxPciInit(); |
| 996 |
|
| 997 |
if (!stat("/proc/sgi_sn/licenseID", &st) && pciNumBuses) { |
| 998 |
/* Be a little paranoid here and only use this code for Altix systems. |
| 999 |
* It is generic, so it should work on any system, but depends on |
| 1000 |
* /proc/bus/pci entries for each domain/bus combination. Altix is |
| 1001 |
* guaranteed a recent enough kernel to have them. |
| 1002 |
*/ |
| 1003 |
pciFindFirstFP = ia64linuxPciFindFirst; |
| 1004 |
pciFindNextFP = ia64linuxPciFindNext; |
| 1005 |
} |
| 1006 |
} |
| 1007 |
|
| 1008 |
static DIR *busdomdir; |
| 1009 |
static DIR *devdir; |
| 1010 |
|
| 1011 |
static PCITAG |
| 1012 |
ia64linuxPciFindFirst(void) |
| 1013 |
{ |
| 1014 |
busdomdir = opendir("/proc/bus/pci"); |
| 1015 |
devdir = NULL; |
| 1016 |
|
| 1017 |
return ia64linuxPciFindNext(); |
| 1018 |
} |
| 1019 |
|
| 1020 |
static struct dirent *getnextbus(int *domain, int *bus) |
| 1021 |
{ |
| 1022 |
struct dirent *entry; |
| 1023 |
int dombus; |
| 1024 |
|
| 1025 |
for (;;) { |
| 1026 |
entry = readdir(busdomdir); |
| 1027 |
if (entry == NULL) { |
| 1028 |
*domain = 0; |
| 1029 |
*bus = 0; |
| 1030 |
closedir(busdomdir); |
| 1031 |
return NULL; |
| 1032 |
} |
| 1033 |
if (sscanf(entry->d_name, "%04x:%02x", domain, bus) != 2) |
| 1034 |
continue; |
| 1035 |
dombus = PCI_MAKE_BUS(*domain, *bus); |
| 1036 |
|
| 1037 |
if (pciNumBuses <= dombus) |
| 1038 |
pciNumBuses = dombus + 1; |
| 1039 |
if (!pciBusInfo[dombus]) { |
| 1040 |
pciBusInfo[dombus] = xnfalloc(sizeof(pciBusInfo_t)); |
| 1041 |
*pciBusInfo[dombus] = *pciBusInfo[0]; |
| 1042 |
} |
| 1043 |
|
| 1044 |
return entry; |
| 1045 |
} |
| 1046 |
} |
| 1047 |
|
| 1048 |
static PCITAG |
| 1049 |
ia64linuxPciFindNext(void) |
| 1050 |
{ |
| 1051 |
struct dirent *entry; |
| 1052 |
char file[40]; |
| 1053 |
static int bus, dev, func, domain; |
| 1054 |
PCITAG pciDeviceTag; |
| 1055 |
CARD32 devid; |
| 1056 |
|
| 1057 |
for (;;) { |
| 1058 |
if (devdir == NULL) { |
| 1059 |
entry = getnextbus(&domain, &bus); |
| 1060 |
if (!entry) |
| 1061 |
return PCI_NOT_FOUND; |
| 1062 |
snprintf(file, 40, "/proc/bus/pci/%s", entry->d_name); |
| 1063 |
devdir = opendir(file); |
| 1064 |
if (!devdir) |
| 1065 |
return PCI_NOT_FOUND; |
| 1066 |
|
| 1067 |
} |
| 1068 |
|
| 1069 |
entry = readdir(devdir); |
| 1070 |
|
| 1071 |
if (entry == NULL) { |
| 1072 |
closedir(devdir); |
| 1073 |
devdir = NULL; |
| 1074 |
continue; |
| 1075 |
} |
| 1076 |
|
| 1077 |
if (sscanf(entry->d_name, "%02x . %01x", &dev, &func) == 2) { |
| 1078 |
pciDeviceTag = PCI_MAKE_TAG(PCI_MAKE_BUS(domain, bus), dev, func); |
| 1079 |
devid = pciReadLong(pciDeviceTag, PCI_ID_REG); |
| 1080 |
if ((devid & pciDevidMask) == pciDevid) |
| 1081 |
/* Yes - Return it. Otherwise, next device */ |
| 1082 |
return pciDeviceTag; |
| 1083 |
} |
| 1084 |
} |
| 1085 |
} |
| 1086 |
#endif |
| 1087 |
|