|
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 495-509
xf86GetPciDomain(PCITAG Tag)
Link Here
|
| 495 |
return result; |
541 |
return result; |
| 496 |
|
542 |
|
| 497 |
if (!pPCI || pPCI->fakeDevice) |
543 |
if (!pPCI || pPCI->fakeDevice) |
| 498 |
return 1; /* Domain 0 is reserved */ |
544 |
return 0; |
| 499 |
|
545 |
|
| 500 |
if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) |
546 |
if ((fd = linuxPciOpenFile(pPCI ? pPCI->tag : 0,FALSE)) < 0) |
| 501 |
return 0; |
547 |
return -1; |
| 502 |
|
548 |
|
| 503 |
if ((result = ioctl(fd, PCIIOC_CONTROLLER, 0)) < 0) |
549 |
if ((result = ioctl(fd, PCIIOC_CONTROLLER, 0)) < 0) |
| 504 |
return 0; |
550 |
return -1; |
| 505 |
|
551 |
|
| 506 |
return result + 1; /* Domain 0 is reserved */ |
552 |
return result; |
| 507 |
} |
553 |
} |
| 508 |
|
554 |
|
| 509 |
static pointer |
555 |
static pointer |
|
Lines 575-581
linuxMapPci(int ScreenNum, int Flags, PC
Link Here
|
| 575 |
return NULL; |
621 |
return NULL; |
| 576 |
} |
622 |
} |
| 577 |
|
623 |
|
| 578 |
#define MAX_DOMAINS 257 |
624 |
#define MAX_DOMAINS 256 |
| 579 |
static pointer DomainMmappedIO[MAX_DOMAINS]; |
625 |
static pointer DomainMmappedIO[MAX_DOMAINS]; |
| 580 |
static pointer DomainMmappedMem[MAX_DOMAINS]; |
626 |
static pointer DomainMmappedMem[MAX_DOMAINS]; |
| 581 |
|
627 |
|
|
Lines 597-607
linuxOpenLegacy(PCITAG Tag, char *name)
Link Here
|
| 597 |
domain = xf86GetPciDomain(Tag); |
643 |
domain = xf86GetPciDomain(Tag); |
| 598 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
644 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 599 |
|
645 |
|
| 600 |
/* Domain 0 is reserved -- see xf86GetPciDomain() */ |
646 |
if ((domain < 0) || (domain >= MAX_DOMAINS)) |
| 601 |
if ((domain <= 0) || (domain >= MAX_DOMAINS)) |
|
|
| 602 |
FatalError("linuxOpenLegacy(): domain out of range\n"); |
647 |
FatalError("linuxOpenLegacy(): domain out of range\n"); |
| 603 |
|
648 |
|
| 604 |
sprintf(path, PREFIX, domain - 1, bus, name); |
649 |
sprintf(path, PREFIX, domain, bus, name); |
| 605 |
fd = open(path, O_RDWR); |
650 |
fd = open(path, O_RDWR); |
| 606 |
if (fd >= 0) { |
651 |
if (fd >= 0) { |
| 607 |
xfree(path); |
652 |
xfree(path); |
|
Lines 686-692
xf86MapDomainIO(int ScreenNum, int Flags
Link Here
|
| 686 |
int domain = xf86GetPciDomain(Tag); |
731 |
int domain = xf86GetPciDomain(Tag); |
| 687 |
int fd; |
732 |
int fd; |
| 688 |
|
733 |
|
| 689 |
if ((domain <= 0) || (domain >= MAX_DOMAINS)) |
734 |
if ((domain < 0) || (domain >= MAX_DOMAINS)) |
| 690 |
FatalError("xf86MapDomainIO(): domain out of range\n"); |
735 |
FatalError("xf86MapDomainIO(): domain out of range\n"); |
| 691 |
|
736 |
|
| 692 |
if (DomainMmappedIO[domain]) |
737 |
if (DomainMmappedIO[domain]) |
|
Lines 725-731
xf86ReadDomainMemory(PCITAG Tag, ADDRESS
Link Here
|
| 725 |
struct stat st; |
770 |
struct stat st; |
| 726 |
|
771 |
|
| 727 |
dom = PCI_DOM_FROM_TAG(Tag); |
772 |
dom = PCI_DOM_FROM_TAG(Tag); |
| 728 |
bus = PCI_BUS_FROM_TAG(Tag); |
773 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 729 |
dev = PCI_DEV_FROM_TAG(Tag); |
774 |
dev = PCI_DEV_FROM_TAG(Tag); |
| 730 |
func = PCI_FUNC_FROM_TAG(Tag); |
775 |
func = PCI_FUNC_FROM_TAG(Tag); |
| 731 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
776 |
sprintf(file, "/sys/devices/pci%04x:%02x/%04x:%02x:%02x.%1x/rom", |
|
Lines 798-804
xf86BusAccWindowsFromOS(void)
Link Here
|
| 798 |
RANGE_TYPE(ResExcIoBlock, domain)); |
843 |
RANGE_TYPE(ResExcIoBlock, domain)); |
| 799 |
pRes = xf86AddResToList(pRes, &range, -1); |
844 |
pRes = xf86AddResToList(pRes, &range, -1); |
| 800 |
|
845 |
|
| 801 |
if (domain <= 0) |
846 |
if (domain < 0) |
| 802 |
break; |
847 |
break; |
| 803 |
} |
848 |
} |
| 804 |
} |
849 |
} |
|
Lines 832-838
xf86PciBusAccWindowsFromOS(void)
Link Here
|
| 832 |
RANGE_TYPE(ResExcIoBlock, domain)); |
877 |
RANGE_TYPE(ResExcIoBlock, domain)); |
| 833 |
pRes = xf86AddResToList(pRes, &range, -1); |
878 |
pRes = xf86AddResToList(pRes, &range, -1); |
| 834 |
|
879 |
|
| 835 |
if (domain <= 0) |
880 |
if (domain < 0) |
| 836 |
break; |
881 |
break; |
| 837 |
} |
882 |
} |
| 838 |
} |
883 |
} |
|
Lines 884-890
xf86AccResFromOS(resPtr pRes)
Link Here
|
| 884 |
RANGE_TYPE(ResExcIoBlock, domain)); |
929 |
RANGE_TYPE(ResExcIoBlock, domain)); |
| 885 |
pRes = xf86AddResToList(pRes, &range, -1); |
930 |
pRes = xf86AddResToList(pRes, &range, -1); |
| 886 |
|
931 |
|
| 887 |
if (domain <= 0) |
932 |
if (domain < 0) |
| 888 |
break; |
933 |
break; |
| 889 |
} |
934 |
} |
| 890 |
} |
935 |
} |
|
Lines 904-910
int linuxPciHandleBIOS(PCITAG Tag, int b
Link Here
|
| 904 |
int sofar = 0; |
949 |
int sofar = 0; |
| 905 |
|
950 |
|
| 906 |
dom = PCI_DOM_FROM_TAG(Tag); |
951 |
dom = PCI_DOM_FROM_TAG(Tag); |
| 907 |
bus = PCI_BUS_FROM_TAG(Tag); |
952 |
bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(Tag)); |
| 908 |
dev = PCI_DEV_FROM_TAG(Tag); |
953 |
dev = PCI_DEV_FROM_TAG(Tag); |
| 909 |
func = PCI_FUNC_FROM_TAG(Tag); |
954 |
func = PCI_FUNC_FROM_TAG(Tag); |
| 910 |
sprintf(file, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/rom", |
955 |
sprintf(file, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/rom", |
|
Lines 934-936
int linuxPciHandleBIOS(PCITAG Tag, int b
Link Here
|
| 934 |
} |
979 |
} |
| 935 |
return 0; |
980 |
return 0; |
| 936 |
} |
981 |
} |
|
|
982 |
|
| 983 |
#ifdef __ia64__ |
| 984 |
static PCITAG ia64linuxPciFindFirst(void); |
| 985 |
static PCITAG ia64linuxPciFindNext(void); |
| 986 |
|
| 987 |
void |
| 988 |
ia64linuxPciInit() |
| 989 |
{ |
| 990 |
struct stat st; |
| 991 |
|
| 992 |
linuxPciInit(); |
| 993 |
|
| 994 |
if (!stat("/proc/sgi_sn/licenseID", &st) && pciNumBuses) { |
| 995 |
/* Be a little paranoid here and only use this code for Altix systems. |
| 996 |
* It is generic, so it should work on any system, but depends on |
| 997 |
* /proc/bus/pci entries for each domain/bus combination. Altix is |
| 998 |
* guaranteed a recent enough kernel to have them. |
| 999 |
*/ |
| 1000 |
pciFindFirstFP = ia64linuxPciFindFirst; |
| 1001 |
pciFindNextFP = ia64linuxPciFindNext; |
| 1002 |
} |
| 1003 |
} |
| 1004 |
|
| 1005 |
static DIR *busdomdir; |
| 1006 |
static DIR *devdir; |
| 1007 |
|
| 1008 |
static PCITAG |
| 1009 |
ia64linuxPciFindFirst(void) |
| 1010 |
{ |
| 1011 |
busdomdir = opendir("/proc/bus/pci"); |
| 1012 |
devdir = NULL; |
| 1013 |
|
| 1014 |
return ia64linuxPciFindNext(); |
| 1015 |
} |
| 1016 |
|
| 1017 |
static struct dirent *getnextbus(int *domain, int *bus) |
| 1018 |
{ |
| 1019 |
struct dirent *entry; |
| 1020 |
int dombus; |
| 1021 |
|
| 1022 |
for (;;) { |
| 1023 |
entry = readdir(busdomdir); |
| 1024 |
if (entry == NULL) { |
| 1025 |
*domain = 0; |
| 1026 |
*bus = 0; |
| 1027 |
closedir(busdomdir); |
| 1028 |
return NULL; |
| 1029 |
} |
| 1030 |
if (sscanf(entry->d_name, "%04x:%02x", domain, bus) != 2) |
| 1031 |
continue; |
| 1032 |
dombus = PCI_MAKE_BUS(*domain, *bus); |
| 1033 |
|
| 1034 |
if (pciNumBuses <= dombus) |
| 1035 |
pciNumBuses = dombus + 1; |
| 1036 |
if (!pciBusInfo[dombus]) { |
| 1037 |
pciBusInfo[dombus] = xnfalloc(sizeof(pciBusInfo_t)); |
| 1038 |
*pciBusInfo[dombus] = *pciBusInfo[0]; |
| 1039 |
} |
| 1040 |
|
| 1041 |
return entry; |
| 1042 |
} |
| 1043 |
} |
| 1044 |
|
| 1045 |
static PCITAG |
| 1046 |
ia64linuxPciFindNext(void) |
| 1047 |
{ |
| 1048 |
struct dirent *entry; |
| 1049 |
char file[40]; |
| 1050 |
static int bus, dev, func, domain; |
| 1051 |
PCITAG pciDeviceTag; |
| 1052 |
CARD32 devid; |
| 1053 |
|
| 1054 |
for (;;) { |
| 1055 |
if (devdir == NULL) { |
| 1056 |
entry = getnextbus(&domain, &bus); |
| 1057 |
if (!entry) |
| 1058 |
return PCI_NOT_FOUND; |
| 1059 |
snprintf(file, 40, "/proc/bus/pci/%s", entry->d_name); |
| 1060 |
devdir = opendir(file); |
| 1061 |
if (!devdir) |
| 1062 |
return PCI_NOT_FOUND; |
| 1063 |
|
| 1064 |
} |
| 1065 |
|
| 1066 |
entry = readdir(devdir); |
| 1067 |
|
| 1068 |
if (entry == NULL) { |
| 1069 |
closedir(devdir); |
| 1070 |
devdir = NULL; |
| 1071 |
continue; |
| 1072 |
} |
| 1073 |
|
| 1074 |
if (sscanf(entry->d_name, "%02x . %01x", &dev, &func) == 2) { |
| 1075 |
pciDeviceTag = PCI_MAKE_TAG(PCI_MAKE_BUS(domain, bus), dev, func); |
| 1076 |
devid = pciReadLong(pciDeviceTag, PCI_ID_REG); |
| 1077 |
if ((devid & pciDevidMask) == pciDevid) |
| 1078 |
/* Yes - Return it. Otherwise, next device */ |
| 1079 |
return pciDeviceTag; |
| 1080 |
} |
| 1081 |
} |
| 1082 |
} |
| 1083 |
#endif |
| 1084 |
|