Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / common / xf86pciBus.c
blob096b7899781d1974cfdbe896099c7a1d9d7a2eab
1 /*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
29 * This file contains the interfaces to the bus-specific code
31 #ifdef HAVE_XORG_CONFIG_H
32 #include <xorg-config.h>
33 #endif
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <X11/X.h>
39 #include "os.h"
40 #include "Pci.h"
41 #include "xf86.h"
42 #include "xf86Priv.h"
43 #include "xf86Resources.h"
45 /* Bus-specific headers */
46 #include "xf86PciData.h"
48 #include "xf86Bus.h"
50 #define XF86_OS_PRIVS
51 #define NEED_OS_RAC_PROTOS
52 #include "xf86_OSproc.h"
54 #include "xf86RAC.h"
56 /* Bus-specific globals */
57 Bool pciSlotClaimed = FALSE;
58 pciConfigPtr *xf86PciInfo = NULL; /* Full PCI probe info */
59 pciVideoPtr *xf86PciVideoInfo = NULL; /* PCI probe for video hw */
60 pciAccPtr * xf86PciAccInfo = NULL; /* PCI access related */
62 /* pcidata globals */
63 ScanPciSetupProcPtr xf86SetupPciIds = NULL;
64 ScanPciCloseProcPtr xf86ClosePciIds = NULL;
65 ScanPciFindByDeviceProcPtr xf86FindPciNamesByDevice = NULL;
66 ScanPciFindBySubsysProcPtr xf86FindPciNamesBySubsys = NULL;
68 static resPtr pciAvoidRes = NULL;
70 /* PCI buses */
71 static PciBusPtr xf86PciBus = NULL;
72 /* Bus-specific probe/sorting functions */
74 /* PCI classes that get included in xf86PciVideoInfo */
75 #define PCIINFOCLASSES(b,s) \
76 (((b) == PCI_CLASS_PREHISTORIC) || \
77 ((b) == PCI_CLASS_DISPLAY) || \
78 ((b) == PCI_CLASS_MULTIMEDIA && (s) == PCI_SUBCLASS_MULTIMEDIA_VIDEO) || \
79 ((b) == PCI_CLASS_PROCESSOR && (s) == PCI_SUBCLASS_PROCESSOR_COPROC))
82 * PCI classes that have messages printed always. The others are only
83 * have a message printed when the vendor/dev IDs are recognised.
85 #define PCIALWAYSPRINTCLASSES(b,s) \
86 (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \
87 ((b) == PCI_CLASS_DISPLAY) || \
88 ((b) == PCI_CLASS_MULTIMEDIA && (s) == PCI_SUBCLASS_MULTIMEDIA_VIDEO))
91 * PCI classes for which potentially destructive checking of the map sizes
92 * may be done. Any classes where this may be unsafe should be omitted
93 * from this list.
95 #define PCINONSYSTEMCLASSES(b,s) PCIALWAYSPRINTCLASSES(b,s)
97 /*
98 * PCI classes that use RAC
100 #define PCISHAREDIOCLASSES(b,s) \
101 (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \
102 ((b) == PCI_CLASS_DISPLAY && (s) == PCI_SUBCLASS_DISPLAY_VGA))
104 #define PCI_MEM32_LENGTH_MAX 0xFFFFFFFF
106 #define B2M(tag,base) pciBusAddrToHostAddr(tag,PCI_MEM,base)
107 #define B2I(tag,base) pciBusAddrToHostAddr(tag,PCI_IO,base)
108 #define B2H(tag,base,type) (((type & ResPhysMask) == ResMem) ? \
109 B2M(tag, base) : B2I(tag, base))
110 #define M2B(tag,base) pciHostAddrToBusAddr(tag,PCI_MEM,base)
111 #define I2B(tag,base) pciHostAddrToBusAddr(tag,PCI_IO,base)
112 #define H2B(tag,base,type) (((type & ResPhysMask) == ResMem) ? \
113 M2B(tag, base) : I2B(tag, base))
114 #define TAG(pvp) (pciTag(pvp->bus,pvp->device,pvp->func))
115 #define SIZE(size) ((1 << size) - 1)
116 #define PCI_SIZE(type,tag,size) (((type & ResPhysMask) == ResMem) \
117 ? pciBusAddrToHostAddr(tag,PCI_MEM_SIZE,size) \
118 : pciBusAddrToHostAddr(tag,PCI_IO_SIZE,size))
119 #define PCI_M_RANGE(range,tag,begin,end,type) \
121 RANGE(range, B2M(tag, begin), B2M(tag, end), \
122 RANGE_TYPE(type, xf86GetPciDomain(tag))); \
124 #define PCI_I_RANGE(range,tag,begin,end,type) \
126 RANGE(range, B2I(tag, begin), B2I(tag, end), \
127 RANGE_TYPE(type, xf86GetPciDomain(tag))); \
129 #define PCI_X_RANGE(range,tag,begin,end,type) \
130 { if ((type & ResPhysMask) == ResMem) PCI_M_RANGE(range,tag,begin,end,type); \
131 else PCI_I_RANGE(range,tag,begin,end,type); }
132 #define P_M_RANGE(range,tag,begin,size,type) \
133 PCI_M_RANGE(range,tag,begin,(begin + SIZE(size)),type)
134 #define P_I_RANGE(range,tag,begin,size,type) \
135 PCI_I_RANGE(range,tag,begin,(begin + SIZE(size)),type)
136 #define P_X_RANGE(range,tag,begin,size,type) \
137 { if ((type & ResPhysMask) == ResMem) P_M_RANGE(range,tag,begin,size,type); \
138 else P_I_RANGE(range,tag,begin,size,type); }
139 #define PV_M_RANGE(range,pvp,i,type) \
140 P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i],type)
141 #define PV_B_RANGE(range,pvp,type) \
142 P_M_RANGE(range,TAG(pvp),pvp->biosBase,pvp->biosSize,type)
143 #define PV_I_RANGE(range,pvp,i,type) \
144 P_I_RANGE(range,TAG(pvp),pvp->ioBase[i],pvp->size[i],type)
146 static void pciConvertListToHost(int bus, int dev, int func, resPtr list);
147 static PciBusPtr xf86GetPciBridgeInfo(void);
149 _X_EXPORT void
150 xf86FormatPciBusNumber(int busnum, char *buffer)
152 /* 'buffer' should be at least 8 characters long */
153 if (busnum < 256)
154 sprintf(buffer, "%d", busnum);
155 else
156 sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8);
159 static Bool
160 IsBaseUnassigned(CARD32 base)
162 CARD32 mask;
164 if (base & PCI_MAP_IO)
165 mask = ~PCI_MAP_IO_ATTR_MASK;
166 else
167 mask = ~PCI_MAP_MEMORY_ATTR_MASK;
169 base &= mask;
170 return (!base || (base == mask));
173 static Bool
174 IsBaseUnassigned64(CARD32 base0, CARD32 base1)
176 base0 &= ~PCI_MAP_MEMORY_ATTR_MASK;
177 base1 &= 0xffffffff;
179 return ((!base0 && !base1)
180 || ((base0 == ~PCI_MAP_MEMORY_ATTR_MASK)
181 && (base1 == 0xffffffff)));
184 static void
185 FindPCIVideoInfo(void)
187 pciConfigPtr pcrp, *pcrpp;
188 int i = 0, j, k;
189 int num = 0;
190 pciVideoPtr info;
191 int DoIsolateDeviceCheck = 0;
193 if (xf86IsolateDevice.bus || xf86IsolateDevice.device || xf86IsolateDevice.func)
194 DoIsolateDeviceCheck = 1;
195 pcrpp = xf86PciInfo = xf86scanpci(0);
198 if (pcrpp == NULL) {
199 xf86PciVideoInfo = NULL;
200 return;
202 xf86PciBus = xf86GetPciBridgeInfo();
204 while ((pcrp = pcrpp[i])) {
205 const int baseclass = pcrp->pci_base_class;
206 const int subclass = pcrp->pci_sub_class;
208 if ( PCIINFOCLASSES(baseclass, subclass) &&
209 (!DoIsolateDeviceCheck ||
210 (xf86IsolateDevice.bus == pcrp->busnum &&
211 xf86IsolateDevice.device == pcrp->devnum &&
212 xf86IsolateDevice.func == pcrp->funcnum)) ) {
213 num++;
214 xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo,
215 sizeof(pciVideoPtr) * (num + 1));
216 xf86PciVideoInfo[num] = NULL;
217 info = xf86PciVideoInfo[num - 1] = xnfalloc(sizeof(pciVideoRec));
218 info->validSize = FALSE;
219 info->vendor = pcrp->pci_vendor;
220 info->chipType = pcrp->pci_device;
221 info->chipRev = pcrp->pci_rev_id;
222 info->subsysVendor = pcrp->pci_subsys_vendor;
223 info->subsysCard = pcrp->pci_subsys_card;
224 info->bus = pcrp->busnum;
225 info->device = pcrp->devnum;
226 info->func = pcrp->funcnum;
227 info->class = baseclass;
228 info->subclass = pcrp->pci_sub_class;
229 info->interface = pcrp->pci_prog_if;
230 info->biosBase = PCIGETROM(pcrp->pci_baserom);
231 info->biosSize = pciGetBaseSize(pcrp->tag, 6, TRUE, NULL);
232 info->thisCard = pcrp;
233 info->validate = FALSE;
234 #ifdef INCLUDE_XF86_NO_DOMAIN
235 if ((PCISHAREDIOCLASSES(baseclass, subclass))
236 && (pcrp->pci_command & PCI_CMD_IO_ENABLE) &&
237 (pcrp->pci_prog_if == 0)) {
240 * Attempt to ensure that VGA is actually routed to this
241 * adapter on entry. This needs to be fixed when we finally
242 * grok host bridges (and multiple bus trees).
244 j = info->bus;
245 while (TRUE) {
246 PciBusPtr pBus = xf86PciBus;
247 while (pBus && j != pBus->secondary)
248 pBus = pBus->next;
249 if (!pBus || !(pBus->brcontrol & PCI_PCI_BRIDGE_VGA_EN))
250 break;
251 if (j == pBus->primary) {
252 if (primaryBus.type == BUS_NONE) {
253 /* assumption: primary adapter is always VGA */
254 primaryBus.type = BUS_PCI;
255 primaryBus.id.pci.bus = pcrp->busnum;
256 primaryBus.id.pci.device = pcrp->devnum;
257 primaryBus.id.pci.func = pcrp->funcnum;
258 } else if (primaryBus.type < BUS_last) {
259 xf86Msg(X_NOTICE,
260 "More than one primary device found\n");
261 primaryBus.type ^= (BusType)(-1);
263 break;
265 j = pBus->primary;
268 #endif
270 for (j = 0; j < 6; j++) {
271 info->memBase[j] = 0;
272 info->ioBase[j] = 0;
273 if (PCINONSYSTEMCLASSES(baseclass, subclass)) {
274 info->size[j] =
275 pciGetBaseSize(pcrp->tag, j, TRUE, &info->validSize);
276 pcrp->minBasesize = info->validSize;
277 } else {
278 info->size[j] = pcrp->basesize[j];
279 info->validSize = pcrp->minBasesize;
281 info->type[j] = 0;
284 if (PCINONSYSTEMCLASSES(baseclass, subclass)) {
286 * Check of a PCI base is unassigned. If so
287 * attempt to fix it. Validation will determine
288 * if the value was correct later on.
290 CARD32 *base = &pcrp->pci_base0;
292 for (j = 0; j < 6; j++) {
293 if (!PCI_MAP_IS64BITMEM(base[j])) {
294 if (info->size[j] && IsBaseUnassigned(base[j]))
295 base[j] = pciCheckForBrokenBase(pcrp->tag, j);
296 } else {
297 if (j == 5) /* bail out */
298 break;
299 if (info->size[j]
300 && IsBaseUnassigned64(base[j],base[j+1])) {
301 base[j] = pciCheckForBrokenBase(pcrp->tag, j);
302 j++;
303 base[j] = pciCheckForBrokenBase(pcrp->tag, j);
310 * 64-bit base addresses are checked for and avoided on 32-bit
311 * platforms.
313 for (j = 0; j < 6; ++j) {
314 CARD32 bar = (&pcrp->pci_base0)[j];
316 if (bar != 0) {
317 if (bar & PCI_MAP_IO) {
318 info->ioBase[j] = (memType)PCIGETIO(bar);
319 info->type[j] = bar & PCI_MAP_IO_ATTR_MASK;
320 } else {
321 info->type[j] = bar & PCI_MAP_MEMORY_ATTR_MASK;
322 info->memBase[j] = (memType)PCIGETMEMORY(bar);
323 if (PCI_MAP_IS64BITMEM(bar)) {
324 if (j == 5) {
325 xf86MsgVerb(X_WARNING, 0,
326 "****BAR5 specified as 64-bit wide, "
327 "which is not possible. "
328 "Ignoring BAR5.****\n");
329 info->memBase[j] = 0;
330 } else {
331 CARD32 bar_hi = PCIGETMEMORY64HIGH((&pcrp->pci_base0)[j]);
332 #if defined(LONG64) || defined(WORD64)
333 /* 64 bit architecture */
334 info->memBase[j] |=
335 (memType)bar_hi << 32;
336 #else
337 if (bar_hi != 0)
338 info->memBase[j] = 0;
339 #endif
340 ++j; /* Step over the next BAR */
347 i++;
350 /* If we haven't found a primary device try a different heuristic */
351 if (primaryBus.type == BUS_NONE && num) {
352 for (i = 0; i < num; i++) {
353 info = xf86PciVideoInfo[i];
354 pcrp = info->thisCard;
356 if ((pcrp->pci_command & PCI_CMD_MEM_ENABLE) &&
357 (num == 1 ||
358 ((info->class == PCI_CLASS_DISPLAY) &&
359 (info->subclass == PCI_SUBCLASS_DISPLAY_VGA)))) {
360 if (primaryBus.type == BUS_NONE) {
361 primaryBus.type = BUS_PCI;
362 primaryBus.id.pci.bus = pcrp->busnum;
363 primaryBus.id.pci.device = pcrp->devnum;
364 primaryBus.id.pci.func = pcrp->funcnum;
365 } else {
366 xf86Msg(X_NOTICE,
367 "More than one possible primary device found\n");
368 primaryBus.type ^= (BusType)(-1);
374 /* Print a summary of the video devices found */
375 for (k = 0; k < num; k++) {
376 const char *vendorname = NULL, *chipname = NULL;
377 const char *prim = " ";
378 char busnum[8];
379 Bool memdone = FALSE, iodone = FALSE;
381 i = 0;
382 info = xf86PciVideoInfo[k];
383 xf86FormatPciBusNumber(info->bus, busnum);
384 xf86FindPciNamesByDevice(info->vendor, info->chipType,
385 NOVENDOR, NOSUBSYS,
386 &vendorname, &chipname, NULL, NULL);
387 if ((!vendorname || !chipname) &&
388 !PCIALWAYSPRINTCLASSES(info->class, info->subclass))
389 continue;
390 if (xf86IsPrimaryPci(info))
391 prim = "*";
393 xf86Msg(X_PROBED, "PCI:%s(%s:%d:%d) ", prim, busnum, info->device,
394 info->func);
395 if (vendorname)
396 xf86ErrorF("%s ", vendorname);
397 else
398 xf86ErrorF("unknown vendor (0x%04x) ", info->vendor);
399 if (chipname)
400 xf86ErrorF("%s ", chipname);
401 else
402 xf86ErrorF("unknown chipset (0x%04x) ", info->chipType);
403 xf86ErrorF("rev %d", info->chipRev);
404 for (i = 0; i < 6; i++) {
405 if (info->memBase[i] &&
406 (info->memBase[i] < (memType)(-1 << info->size[i]))) {
407 if (!memdone) {
408 xf86ErrorF(", Mem @ ");
409 memdone = TRUE;
410 } else
411 xf86ErrorF(", ");
412 xf86ErrorF("0x%08lx/%d", info->memBase[i], info->size[i]);
415 for (i = 0; i < 6; i++) {
416 if (info->ioBase[i] &&
417 (info->ioBase[i] < (memType)(-1 << info->size[i]))) {
418 if (!iodone) {
419 xf86ErrorF(", I/O @ ");
420 iodone = TRUE;
421 } else
422 xf86ErrorF(", ");
423 xf86ErrorF("0x%04lx/%d", info->ioBase[i], info->size[i]);
426 if (info->biosBase &&
427 (info->biosBase < (memType)(-1 << info->biosSize)))
428 xf86ErrorF(", BIOS @ 0x%08lx/%d", info->biosBase, info->biosSize);
429 xf86ErrorF("\n");
434 * fixPciSizeInfo() -- fix pci size info by testing it destructively
435 * (if not already done), fix pciVideoInfo and entry in the resource
436 * list.
439 * Note: once we have OS support to read the sizes GetBaseSize() will
440 * have to be wrapped by the OS layer. fixPciSizeInfo() should also
441 * be wrapped by the OS layer to do nothing if the size is always
442 * returned correctly by GetBaseSize(). It should however set validate
443 * in pciVideoRec if validation is required. ValidatePci() also needs
444 * to be wrapped by the OS layer. This may do nothing if the OS has
445 * already taken care of validation. fixPciResource() may be moved to
446 * OS layer with minimal changes. Once the wrapping layer is in place
447 * the common level and drivers should not reference these functions
448 * directly but thru the OS layer.
451 static void
452 fixPciSizeInfo(int entityIndex)
454 pciVideoPtr pvp;
455 resPtr pAcc;
456 PCITAG tag;
457 int j;
459 if (! (pvp = xf86GetPciInfoForEntity(entityIndex))) return;
460 if (pvp->validSize) return;
462 tag = pciTag(pvp->bus,pvp->device,pvp->func);
464 for (j = 0; j < 6; j++) {
465 pAcc = Acc;
466 if (pvp->memBase[j])
467 while (pAcc) {
468 if (((pAcc->res_type & (ResPhysMask | ResBlock))
469 == (ResMem | ResBlock))
470 && (pAcc->block_begin == B2M(TAG(pvp),pvp->memBase[j]))
471 && (pAcc->block_end == B2M(TAG(pvp),pvp->memBase[j]
472 + SIZE(pvp->size[j])))) break;
473 pAcc = pAcc->next;
475 else if (pvp->ioBase[j])
476 while (pAcc) {
477 if (((pAcc->res_type & (ResPhysMask | ResBlock)) ==
478 (ResIo | ResBlock))
479 && (pAcc->block_begin == B2I(TAG(pvp),pvp->ioBase[j]))
480 && (pAcc->block_end == B2I(TAG(pvp),pvp->ioBase[j]
481 + SIZE(pvp->size[j])))) break;
482 pAcc = pAcc->next;
484 else continue;
485 pvp->size[j] = pciGetBaseSize(tag, j, TRUE, &pvp->validSize);
486 if (pAcc) {
487 pAcc->block_end = pvp->memBase[j] ?
488 B2M(TAG(pvp),pvp->memBase[j] + SIZE(pvp->size[j]))
489 : B2I(TAG(pvp),pvp->ioBase[j] + SIZE(pvp->size[j]));
490 pAcc->res_type &= ~ResEstimated;
491 pAcc->res_type |= ResBios;
494 if (pvp->biosBase) {
495 pAcc = Acc;
496 while (pAcc) {
497 if (((pAcc->res_type & (ResPhysMask | ResBlock)) ==
498 (ResMem | ResBlock))
499 && (pAcc->block_begin == B2M(TAG(pvp),pvp->biosBase))
500 && (pAcc->block_end == B2M(TAG(pvp),pvp->biosBase
501 + SIZE(pvp->biosSize)))) break;
502 pAcc = pAcc->next;
504 pvp->biosSize = pciGetBaseSize(tag, 6, TRUE, &pvp->validSize);
505 if (pAcc) {
506 pAcc->block_end = B2M(TAG(pvp),pvp->biosBase+SIZE(pvp->biosSize));
507 pAcc->res_type &= ~ResEstimated;
508 pAcc->res_type |= ResBios;
514 * IO enable/disable related routines for PCI
516 #define pArg ((pciArg*)arg)
517 #define SETBITS PCI_CMD_IO_ENABLE
518 static void
519 pciIoAccessEnable(void* arg)
521 #ifdef DEBUG
522 ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
523 #endif
524 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
525 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
528 static void
529 pciIoAccessDisable(void* arg)
531 #ifdef DEBUG
532 ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
533 #endif
534 pArg->ctrl &= ~SETBITS;
535 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
538 #undef SETBITS
539 #define SETBITS (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)
540 static void
541 pciIo_MemAccessEnable(void* arg)
543 #ifdef DEBUG
544 ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
545 #endif
546 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
547 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
550 static void
551 pciIo_MemAccessDisable(void* arg)
553 #ifdef DEBUG
554 ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
555 #endif
556 pArg->ctrl &= ~SETBITS;
557 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
560 #undef SETBITS
561 #define SETBITS (PCI_CMD_MEM_ENABLE)
562 static void
563 pciMemAccessEnable(void* arg)
565 #ifdef DEBUG
566 ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
567 #endif
568 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
569 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
572 static void
573 pciMemAccessDisable(void* arg)
575 #ifdef DEBUG
576 ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
577 #endif
578 pArg->ctrl &= ~SETBITS;
579 pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
581 #undef SETBITS
582 #undef pArg
585 /* move to OS layer */
586 #define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN)
587 static void
588 pciBusAccessEnable(BusAccPtr ptr)
590 PCITAG tag = ptr->busdep.pci.acc;
591 CARD16 ctrl;
593 #ifdef DEBUG
594 ErrorF("pciBusAccessEnable: bus=%d\n", ptr->busdep.pci.bus);
595 #endif
596 ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG);
597 if ((ctrl & MASKBITS) != PCI_PCI_BRIDGE_VGA_EN) {
598 ctrl = (ctrl | PCI_PCI_BRIDGE_VGA_EN) &
599 ~(PCI_PCI_BRIDGE_MASTER_ABORT_EN | PCI_PCI_BRIDGE_SECONDARY_RESET);
600 pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl);
604 /* move to OS layer */
605 static void
606 pciBusAccessDisable(BusAccPtr ptr)
608 PCITAG tag = ptr->busdep.pci.acc;
609 CARD16 ctrl;
611 #ifdef DEBUG
612 ErrorF("pciBusAccessDisable: bus=%d\n", ptr->busdep.pci.bus);
613 #endif
614 ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG);
615 if (ctrl & MASKBITS) {
616 ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET);
617 pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl);
620 #undef MASKBITS
622 /* move to OS layer */
623 static void
624 pciDrvBusAccessEnable(BusAccPtr ptr)
626 int bus = ptr->busdep.pci.bus;
628 #ifdef DEBUG
629 ErrorF("pciDrvBusAccessEnable: bus=%d\n", bus);
630 #endif
631 (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
632 PCI_PCI_BRIDGE_VGA_EN,
633 PCI_PCI_BRIDGE_VGA_EN);
636 /* move to OS layer */
637 static void
638 pciDrvBusAccessDisable(BusAccPtr ptr)
640 int bus = ptr->busdep.pci.bus;
642 #ifdef DEBUG
643 ErrorF("pciDrvBusAccessDisable: bus=%d\n", bus);
644 #endif
645 (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
646 PCI_PCI_BRIDGE_VGA_EN, 0);
650 static void
651 pciSetBusAccess(BusAccPtr ptr)
653 #ifdef DEBUG
654 ErrorF("pciSetBusAccess: route VGA to bus %d\n", ptr->busdep.pci.bus);
655 #endif
657 if (!ptr->primary && !ptr->current)
658 return;
660 if (ptr->current && ptr->current->disable_f)
661 (*ptr->current->disable_f)(ptr->current);
662 ptr->current = NULL;
664 /* walk down */
665 while (ptr->primary) { /* No enable for root bus */
666 if (ptr != ptr->primary->current) {
667 if (ptr->primary->current && ptr->primary->current->disable_f)
668 (*ptr->primary->current->disable_f)(ptr->primary->current);
669 if (ptr->enable_f)
670 (*ptr->enable_f)(ptr);
671 ptr->primary->current = ptr;
673 ptr = ptr->primary;
677 /* move to OS layer */
678 static void
679 savePciState(PCITAG tag, pciSavePtr ptr)
681 int i;
683 ptr->command = pciReadLong(tag, PCI_CMD_STAT_REG);
684 for (i=0; i < 6; i++)
685 ptr->base[i] = pciReadLong(tag, PCI_CMD_BASE_REG + i*4);
686 ptr->biosBase = pciReadLong(tag, PCI_CMD_BIOS_REG);
689 /* move to OS layer */
690 static void
691 restorePciState(PCITAG tag, pciSavePtr ptr)
693 int i;
695 /* disable card before setting anything */
696 pciSetBitsLong(tag, PCI_CMD_STAT_REG,
697 PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE , 0);
698 pciWriteLong(tag,PCI_CMD_BIOS_REG, ptr->biosBase);
699 for (i=0; i<6; i++)
700 pciWriteLong(tag, PCI_CMD_BASE_REG + i*4, ptr->base[i]);
701 pciWriteLong(tag, PCI_CMD_STAT_REG, ptr->command);
704 /* move to OS layer */
705 static void
706 savePciBusState(BusAccPtr ptr)
708 PCITAG tag = ptr->busdep.pci.acc;
710 ptr->busdep.pci.save.control =
711 pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG) &
712 ~PCI_PCI_BRIDGE_SECONDARY_RESET;
713 /* Allow master aborts to complete normally on non-root buses */
714 if (ptr->busdep.pci.save.control & PCI_PCI_BRIDGE_MASTER_ABORT_EN)
715 pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG,
716 ptr->busdep.pci.save.control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN);
719 /* move to OS layer */
720 #define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN)
721 static void
722 restorePciBusState(BusAccPtr ptr)
724 PCITAG tag = ptr->busdep.pci.acc;
725 CARD16 ctrl;
727 /* Only restore the bits we've changed (and don't cause resets) */
728 ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG);
729 if ((ctrl ^ ptr->busdep.pci.save.control) & MASKBITS) {
730 ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET);
731 ctrl |= ptr->busdep.pci.save.control & MASKBITS;
732 pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl);
735 #undef MASKBITS
737 /* move to OS layer */
738 static void
739 savePciDrvBusState(BusAccPtr ptr)
741 int bus = ptr->busdep.pci.bus;
743 ptr->busdep.pci.save.control =
744 (*pciBusInfo[bus]->funcs->pciControlBridge)(bus, 0, 0);
745 /* Allow master aborts to complete normally on this bus */
746 (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
747 PCI_PCI_BRIDGE_MASTER_ABORT_EN,
751 /* move to OS layer */
752 static void
753 restorePciDrvBusState(BusAccPtr ptr)
755 int bus = ptr->busdep.pci.bus;
757 (*pciBusInfo[bus]->funcs->pciControlBridge)(bus, (CARD16)(-1),
758 ptr->busdep.pci.save.control);
762 static void
763 disablePciBios(PCITAG tag)
765 pciSetBitsLong(tag, PCI_CMD_BIOS_REG, PCI_CMD_BIOS_ENABLE, 0);
768 /* ????? */
769 static void
770 correctPciSize(memType base, memType oldsize, memType newsize,
771 unsigned long type)
773 pciConfigPtr pcrp, *pcrpp;
774 pciVideoPtr pvp, *pvpp;
775 CARD32 *basep;
776 int i;
777 int old_bits = 0, new_bits = 0;
779 if (oldsize + 1) while (oldsize & 1) {
780 old_bits ++;
781 oldsize >>= 1;
783 if (newsize + 1) while (newsize & 1) {
784 new_bits ++;
785 newsize >>= 1;
788 for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
790 /* Only process devices with type 0 headers */
791 if ((pcrp->pci_header_type & 0x7f) != 0)
792 continue;
794 basep = &pcrp->pci_base0;
795 for (i = 0; i < 6; i++) {
796 if (basep[i] && (pcrp->basesize[i] == old_bits)) {
797 if ((((type & ResPhysMask) == ResIo) &&
798 PCI_MAP_IS_IO(basep[i]) &&
799 B2I(pcrp->tag,PCIGETIO(basep[i]) == base)) ||
800 (((type & ResPhysMask) == ResMem) &&
801 PCI_MAP_IS_MEM(basep[i]) &&
802 (((!PCI_MAP_IS64BITMEM(basep[i])) &&
803 (B2M(pcrp->tag,PCIGETMEMORY(basep[i])) == base))
804 #if defined(LONG64) || defined(WORD64)
806 (B2M(pcrp->tag,PCIGETMEMORY64(basep[i])) == base)
807 #else
809 (!basep[i+1]
810 && (B2M(pcrp->tag,PCIGETMEMORY(basep[i])) == base))
811 #endif
812 ))) {
813 pcrp->basesize[i] = new_bits;
814 break; /* to next device */
817 if (PCI_MAP_IS64BITMEM(basep[i])) i++;
821 if (xf86PciVideoInfo) {
822 for (pvpp = xf86PciVideoInfo, pvp = *pvpp; pvp; pvp = *(++pvpp)) {
824 for (i = 0; i < 6; i++) {
825 if (pvp->size[i] == old_bits) {
826 if ((((type & ResPhysMask) == ResIo) && pvp->ioBase[i]
827 && (B2I(TAG(pvp),pvp->ioBase[i]) == base)) ||
828 (((type & ResPhysMask) == ResMem) && pvp->memBase[i]
829 && (B2M(TAG(pvp),pvp->memBase[i]) == base))) {
830 pvp->size[i] = new_bits;
831 break; /* to next device */
839 /* ????? */
840 static void
841 removeOverlapsWithBridges(int busIndex, resPtr target)
843 PciBusPtr pbp;
844 resPtr tmp,bridgeRes = NULL;
845 resRange range;
847 if (!target)
848 return;
850 if (!ResCanOverlap(&target->val))
851 return;
853 range = target->val;
855 for (pbp=xf86PciBus; pbp; pbp = pbp->next) {
856 if (pbp->primary == busIndex) {
857 tmp = xf86DupResList(pbp->preferred_io);
858 bridgeRes = xf86JoinResLists(tmp,bridgeRes);
859 tmp = xf86DupResList(pbp->preferred_mem);
860 bridgeRes = xf86JoinResLists(tmp,bridgeRes);
861 tmp = xf86DupResList(pbp->preferred_pmem);
862 bridgeRes = xf86JoinResLists(tmp,bridgeRes);
866 RemoveOverlaps(target, bridgeRes, TRUE, TRUE);
867 if (range.rEnd > target->block_end) {
868 correctPciSize(range.rBegin, range.rEnd - range.rBegin,
869 target->block_end - target->block_begin,
870 target->res_type);
871 xf86MsgVerb(X_INFO, 3,
872 "PCI %s resource overlap reduced 0x%08lx from 0x%08lx to 0x%08lx\n",
873 ((target->res_type & ResPhysMask) == ResMem) ? "Memory" : "I/O",
874 range.rBegin, range.rEnd, target->block_end);
876 xf86FreeResList(bridgeRes);
879 /* ????? */
880 static void
881 xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes)
883 pciConfigPtr pcrp, *pcrpp;
884 pciVideoPtr pvp, *pvpp;
885 CARD32 *basep;
886 int i;
887 resPtr pRes, tmp;
888 resRange range;
889 long resMisc;
891 if (activeRes)
892 *activeRes = NULL;
893 if (inactiveRes)
894 *inactiveRes = NULL;
896 if (!activeRes || !inactiveRes || !xf86PciInfo)
897 return;
899 if (xf86PciVideoInfo)
900 for (pvpp = xf86PciVideoInfo, pvp = *pvpp; pvp; pvp = *(++pvpp)) {
901 resPtr *res;
903 if (PCINONSYSTEMCLASSES(pvp->class, pvp->subclass))
904 resMisc = ResBios;
905 else
906 resMisc = 0;
908 if (((pciConfigPtr)pvp->thisCard)->pci_command
909 & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE))
910 res = activeRes;
911 else
912 res = inactiveRes;
914 if (!pvp->validSize)
915 resMisc |= ResEstimated;
917 for (i = 0; i < 6; i++) {
918 if (pvp->ioBase[i] &&
919 (pvp->ioBase[i] < (memType)(-1 << pvp->size[i]))) {
920 PV_I_RANGE(range,pvp,i,ResExcIoBlock | resMisc);
921 tmp = xf86AddResToList(NULL, &range, -1);
922 removeOverlapsWithBridges(pvp->bus,tmp);
923 *res = xf86JoinResLists(tmp,*res);
924 } else if (pvp->memBase[i] &&
925 (pvp->memBase[i] < (memType)(-1 << pvp->size[i]))) {
926 PV_M_RANGE(range, pvp,i, ResExcMemBlock | resMisc);
927 tmp = xf86AddResToList(NULL, &range, -1);
928 removeOverlapsWithBridges(pvp->bus,tmp);
929 *res = xf86JoinResLists(tmp,*res);
932 /* FIXME!!!: Don't use BIOS resources for overlap
933 * checking but reserve them!
935 if (pvp->biosBase &&
936 (pvp->biosBase < (memType)(-1 << pvp->biosSize))) {
937 PV_B_RANGE(range, pvp, ResExcMemBlock | resMisc);
938 tmp = xf86AddResToList(NULL, &range, -1);
939 removeOverlapsWithBridges(pvp->bus,tmp);
940 *res = xf86JoinResLists(tmp,*res);
944 for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
945 resPtr *res;
946 const CARD8 baseclass = pcrp->pci_base_class;
947 const CARD8 subclass = pcrp->pci_sub_class;
950 if (PCIINFOCLASSES(baseclass, subclass))
951 continue;
953 /* Only process devices with type 0 headers */
954 if ((pcrp->pci_header_type & 0x7f) != 0)
955 continue;
957 if (!pcrp->minBasesize)
958 resMisc = ResEstimated;
959 else
960 resMisc = 0;
963 * Allow resources allocated to host bridges to overlap. Perhaps, this
964 * needs to be specific to AGP-capable chipsets. AGP "memory"
965 * sometimes gets allocated within the range routed to the AGP bus.
967 if ((baseclass == PCI_CLASS_BRIDGE) &&
968 (subclass == PCI_SUBCLASS_BRIDGE_HOST))
969 resMisc |= ResOverlap;
971 basep = &pcrp->pci_base0;
972 for (i = 0; i < 6; i++) {
973 if (basep[i]) {
974 if (PCI_MAP_IS_IO(basep[i])) {
975 if (pcrp->pci_command & PCI_CMD_IO_ENABLE)
976 res = activeRes;
977 else
978 res = inactiveRes;
979 P_I_RANGE(range, pcrp->tag, PCIGETIO(basep[i]),
980 pcrp->basesize[i], ResExcIoBlock | resMisc)
981 } else if (!PCI_MAP_IS64BITMEM(basep[i])) {
982 if (pcrp->pci_command & PCI_CMD_MEM_ENABLE)
983 res = activeRes;
984 else
985 res = inactiveRes;
986 P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i]),
987 pcrp->basesize[i], ResExcMemBlock | resMisc)
988 } else {
989 i++;
990 #if defined(LONG64) || defined(WORD64)
991 P_M_RANGE(range,pcrp->tag,PCIGETMEMORY64(basep[i - 1]),
992 pcrp->basesize[i - 1], ResExcMemBlock | resMisc)
993 #else
994 if (basep[i])
995 continue;
996 P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i - 1]),
997 pcrp->basesize[i - 1], ResExcMemBlock | resMisc)
998 #endif
999 if (pcrp->pci_command & PCI_CMD_MEM_ENABLE)
1000 res = activeRes;
1001 else
1002 res = inactiveRes;
1004 if (range.rBegin) { /* catch cases where PCI base is unset */
1005 tmp = xf86AddResToList(NULL, &range, -1);
1006 removeOverlapsWithBridges(pcrp->busnum,tmp);
1007 *res = xf86JoinResLists(tmp,*res);
1012 /* Ignore disabled non-video ROMs */
1013 if ((pcrp->pci_command & PCI_CMD_MEM_ENABLE) &&
1014 (pcrp->pci_baserom & PCI_MAP_ROM_DECODE_ENABLE)) {
1015 P_M_RANGE(range,pcrp->tag,PCIGETROM(pcrp->pci_baserom),
1016 pcrp->basesize[6], ResExcMemBlock | resMisc);
1017 if (range.rBegin) {
1018 tmp = xf86AddResToList(NULL, &range, -1);
1019 removeOverlapsWithBridges(pcrp->busnum, tmp);
1020 *activeRes = xf86JoinResLists(tmp, *activeRes);
1025 if (*activeRes) {
1026 xf86MsgVerb(X_INFO, 3, "Active PCI resource ranges:\n");
1027 xf86PrintResList(3, *activeRes);
1029 if (*inactiveRes) {
1030 xf86MsgVerb(X_INFO, 3, "Inactive PCI resource ranges:\n");
1031 xf86PrintResList(3, *inactiveRes);
1035 * Adjust ranges based on the assumption that there are no real
1036 * overlaps in the PCI base allocations. This assumption should be
1037 * reasonable in most cases. It may be possible to refine the
1038 * approximated PCI base sizes by considering bus mapping information
1039 * from PCI-PCI bridges.
1042 if (*activeRes) {
1043 /* Check for overlaps */
1044 for (pRes = *activeRes; pRes; pRes = pRes->next) {
1045 if (ResCanOverlap(&pRes->val)) {
1046 range = pRes->val;
1048 RemoveOverlaps(pRes, *activeRes, TRUE, TRUE);
1049 RemoveOverlaps(pRes, *inactiveRes, TRUE,
1050 (xf86Info.estimateSizesAggressively > 0));
1052 if (range.rEnd > pRes->block_end) {
1053 correctPciSize(range.rBegin, range.rEnd - range.rBegin,
1054 pRes->block_end - pRes->block_begin,
1055 pRes->res_type);
1056 xf86MsgVerb(X_INFO, 3,
1057 "PCI %s resource overlap reduced 0x%08lx"
1058 " from 0x%08lx to 0x%08lx\n",
1059 ((pRes->res_type & ResPhysMask) == ResMem) ?
1060 "Memory" : "I/O",
1061 range.rBegin, range.rEnd, pRes->block_end);
1065 xf86MsgVerb(X_INFO, 3,
1066 "Active PCI resource ranges after removing overlaps:\n");
1067 xf86PrintResList(3, *activeRes);
1070 if (*inactiveRes) {
1071 /* Check for overlaps */
1072 for (pRes = *inactiveRes; pRes; pRes = pRes->next) {
1073 if (ResCanOverlap(&pRes->val)) {
1074 range = pRes->val;
1076 RemoveOverlaps(pRes, *activeRes, TRUE,
1077 (xf86Info.estimateSizesAggressively > 1));
1078 RemoveOverlaps(pRes, *inactiveRes, TRUE,
1079 (xf86Info.estimateSizesAggressively > 1));
1081 if (range.rEnd > pRes->block_end) {
1082 correctPciSize(range.rBegin, range.rEnd - range.rBegin,
1083 pRes->block_end - pRes->block_begin,
1084 pRes->res_type);
1085 xf86MsgVerb(X_INFO, 3,
1086 "PCI %s resource overlap reduced 0x%08lx"
1087 " from 0x%08lx to 0x%08lx\n",
1088 ((pRes->res_type & ResPhysMask) == ResMem) ?
1089 "Memory" : "I/O",
1090 range.rBegin, range.rEnd, pRes->block_end);
1095 xf86MsgVerb(X_INFO, 3,
1096 "Inactive PCI resource ranges after removing overlaps:\n");
1097 xf86PrintResList(3, *inactiveRes);
1101 resPtr
1102 ResourceBrokerInitPci(resPtr *osRes)
1104 resPtr activeRes, inactiveRes;
1105 resPtr tmp;
1107 /* Get bus-specific system resources (PCI) */
1108 xf86GetPciRes(&activeRes, &inactiveRes);
1111 * Adjust OS-reported resource ranges based on the assumption that there
1112 * are no overlaps with the PCI base allocations. This should be a good
1113 * assumption because writes to PCI address space won't be routed directly
1114 * to host memory.
1117 for (tmp = *osRes; tmp; tmp = tmp->next)
1118 RemoveOverlaps(tmp, activeRes, FALSE, TRUE);
1120 xf86MsgVerb(X_INFO, 3, "OS-reported resource ranges after removing"
1121 " overlaps with PCI:\n");
1122 xf86PrintResList(3, *osRes);
1124 pciAvoidRes = xf86AddRangesToList(pciAvoidRes,PciAvoid,-1);
1125 for (tmp = pciAvoidRes; tmp; tmp = tmp->next)
1126 RemoveOverlaps(tmp, activeRes, FALSE, TRUE);
1127 tmp = xf86DupResList(*osRes);
1128 pciAvoidRes = xf86JoinResLists(pciAvoidRes,tmp);
1130 return (xf86JoinResLists(activeRes,inactiveRes));
1135 * PCI Resource modification
1137 static Bool
1138 fixPciResource(int prt, memType alignment, pciVideoPtr pvp, unsigned long type)
1140 int res_n;
1141 memType *p_base;
1142 int *p_size;
1143 unsigned char p_type;
1144 resPtr AccTmp = NULL;
1145 resPtr orgAcc = NULL;
1146 resPtr *pAcc = &AccTmp;
1147 resPtr avoid = NULL;
1148 resRange range;
1149 resPtr resSize = NULL;
1150 resPtr w_tmp, w = NULL, w_2nd = NULL;
1151 PCITAG tag;
1152 PciBusPtr pbp = xf86PciBus;
1153 pciConfigPtr pcp;
1154 resPtr tmp;
1156 if (!pvp) return FALSE;
1157 tag = pciTag(pvp->bus,pvp->device,pvp->func);
1158 pcp = pvp->thisCard;
1160 type &= ResAccMask;
1161 if (!type) type = ResShared;
1162 if (prt < 6) {
1163 if (pvp->memBase[prt]) {
1164 type |= ResMem;
1165 res_n = prt;
1166 p_base = &(pvp->memBase[res_n]);
1167 p_size = &(pvp->size[res_n]);
1168 p_type = pvp->type[res_n];
1169 if (!PCI_MAP_IS64BITMEM(pvp->type[res_n])) {
1170 PCI_M_RANGE(range,tag,0,0xffffffff,ResExcMemBlock);
1171 resSize = xf86AddResToList(resSize,&range,-1);
1173 } else if (pvp->ioBase[prt]){
1174 type |= ResIo;
1175 res_n = prt;
1176 p_base = &(pvp->ioBase[res_n]);
1177 p_size = &(pvp->size[res_n]);
1178 p_type = pvp->type[res_n];
1179 PCI_I_RANGE(range, tag, 0, 0xffffffff, ResExcIoBlock);
1180 resSize = xf86AddResToList(resSize, &range, -1);
1181 } else return FALSE;
1182 } else if (prt == 6) {
1183 type |= ResMem;
1184 res_n = 0xff; /* special flag for bios rom */
1185 p_base = &(pvp->biosBase);
1186 p_size = &(pvp->biosSize);
1187 /* XXX This should also include the PCI_MAP_MEMORY_TYPE_MASK part */
1188 p_type = 0;
1189 PCI_M_RANGE(range,tag,0,0xffffffff,ResExcMemBlock);
1190 resSize = xf86AddResToList(resSize,&range,-1);
1191 } else return FALSE;
1193 if (! *p_base) return FALSE;
1195 type |= (range.type & ResDomain) | ResBlock;
1197 /* setup avoid: PciAvoid is bus range: convert later */
1198 avoid = xf86DupResList(pciAvoidRes);
1200 while (pbp) {
1201 if (pbp->secondary == pvp->bus) {
1202 if ((type & ResPhysMask) == ResMem) {
1203 if (((p_type & PCI_MAP_MEMORY_CACHABLE)
1204 #if 0 /*EE*/
1205 || (res_n == 0xff)/* bios should also be prefetchable */
1206 #endif
1207 )) {
1208 if (pbp->preferred_pmem)
1209 w = xf86FindIntersectOfLists(pbp->preferred_pmem,
1210 ResRange);
1211 else if (pbp->pmem)
1212 w = xf86FindIntersectOfLists(pbp->pmem,ResRange);
1214 if (pbp->preferred_mem)
1215 w_2nd = xf86FindIntersectOfLists(pbp->preferred_mem,
1216 ResRange);
1217 else if (pbp->mem)
1218 w_2nd = xf86FindIntersectOfLists(pbp->mem,
1219 ResRange);
1220 } else {
1221 if (pbp->preferred_mem)
1222 w = xf86FindIntersectOfLists(pbp->preferred_mem,
1223 ResRange);
1224 else if (pbp->mem)
1225 w = xf86FindIntersectOfLists(pbp->mem,ResRange);
1227 } else {
1228 if (pbp->preferred_io)
1229 w = xf86FindIntersectOfLists(pbp->preferred_io,ResRange);
1230 if (pbp->io)
1231 w = xf86FindIntersectOfLists(pbp->io,ResRange);
1233 } else if (pbp->primary == pvp->bus) {
1234 if ((type & ResPhysMask) == ResMem) {
1235 tmp = xf86DupResList(pbp->preferred_pmem);
1236 avoid = xf86JoinResLists(avoid, tmp);
1237 tmp = xf86DupResList(pbp->preferred_mem);
1238 avoid = xf86JoinResLists(avoid, tmp);
1239 } else {
1240 tmp = xf86DupResList(pbp->preferred_io);
1241 avoid = xf86JoinResLists(avoid, tmp);
1244 pbp = pbp->next;
1247 /* convert bus based entries in avoid list to host base */
1248 pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
1250 if (!w)
1251 w = xf86DupResList(ResRange);
1252 xf86MsgVerb(X_INFO, 3, "window:\n");
1253 xf86PrintResList(3, w);
1254 xf86MsgVerb(X_INFO, 3, "resSize:\n");
1255 xf86PrintResList(3, resSize);
1257 if (resSize) {
1258 w_tmp = w;
1259 w = xf86FindIntersectOfLists(w,resSize);
1260 xf86FreeResList(w_tmp);
1261 if (w_2nd) {
1262 w_tmp = w_2nd;
1263 w_2nd = xf86FindIntersectOfLists(w_2nd,resSize);
1264 xf86FreeResList(w_tmp);
1266 xf86FreeResList(resSize);
1268 xf86MsgVerb(X_INFO, 3, "window fixed:\n");
1269 xf86PrintResList(3, w);
1271 if (!alignment)
1272 alignment = (1 << (*p_size)) - 1;
1274 /* Access list holds bios resources -- remove this one */
1275 #ifdef NOTYET
1276 AccTmp = xf86DupResList(Acc);
1277 while ((*pAcc)) {
1278 if ((((*pAcc)->res_type & (type & ~ResAccMask))
1279 == (type & ~ResAccMask))
1280 && ((*pAcc)->block_begin == (B2H(tag,(*p_base),type)))
1281 && ((*pAcc)->block_end == (B2H(tag,
1282 (*p_base)+SIZE(*p_size),type)))) {
1283 resPtr acc_tmp = (*pAcc)->next;
1284 xfree((*pAcc));
1285 (*pAcc) = acc_tmp;
1286 break;
1287 } else
1288 pAcc = &((*pAcc)->next);
1290 /* check if we really need to fix anything */
1291 P_X_RANGE(range,tag,(*p_base),(*p_base) + SIZE((*p_size)),type);
1292 if (!ChkConflict(&range,avoid,SETUP)
1293 && !ChkConflict(&range,AccTmp,SETUP)
1294 && ((B2H(tag,(*p_base),type) & PCI_SIZE(type,tag,alignment)
1295 == range->block_begin)
1296 && ((xf86IsSubsetOf(range,w)
1297 || (w_2nd && xf86IsSubsetOf(range,w_2n))))) {
1298 #ifdef DEBUG
1299 ErrorF("nothing to fix\n");
1300 #endif
1301 xf86FreeResList(AccTmp);
1302 xf86FreeResList(w);
1303 xf86FreeResList(w_2nd);
1304 xf86FreeResList(avoid);
1305 return TRUE;
1307 #ifdef DEBUG
1308 ErrorF("removing old resource\n");
1309 #endif
1310 orgAcc = Acc;
1311 Acc = AccTmp;
1312 #else
1313 orgAcc = xf86DupResList(Acc);
1314 pAcc = &Acc;
1315 while (*pAcc) {
1316 if ((((*pAcc)->res_type & (ResTypeMask|ResExtMask)) ==
1317 (type & ~ResAccMask))
1318 && ((*pAcc)->block_begin == B2H(tag,(*p_base),type))
1319 && ((*pAcc)->block_end == B2H(tag,(*p_base) + SIZE(*p_size),
1320 type))) {
1321 #ifdef DEBUG
1322 ErrorF("removing old resource\n");
1323 #endif
1324 tmp = *pAcc;
1325 *pAcc = (*pAcc)->next;
1326 tmp->next = NULL;
1327 xf86FreeResList(tmp);
1328 break;
1329 } else
1330 pAcc = &((*pAcc)->next);
1332 #endif
1334 #ifdef DEBUG
1335 ErrorF("base: 0x%lx alignment: 0x%lx host alignment: 0x%lx size[bit]: 0x%x\n",
1336 (*p_base),alignment,PCI_SIZE(type,tag,alignment),(*p_size));
1337 xf86MsgVerb(X_INFO, 3, "window:\n");
1338 xf86PrintResList(3, w);
1339 if (w_2nd)
1340 xf86MsgVerb(X_INFO, 3, "2nd window:\n");
1341 xf86PrintResList(3, w_2nd);
1342 xf86ErrorFVerb(3,"avoid:\n");
1343 xf86PrintResList(3,avoid);
1344 #endif
1345 w_tmp = w;
1346 while (w) {
1347 if ((type & ResTypeMask) == (w->res_type & ResTypeMask)) {
1348 #ifdef DEBUG
1349 ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w->block_begin,
1350 w->block_end);
1351 #endif
1352 range = xf86GetBlock(type,PCI_SIZE(type,tag,alignment + 1),
1353 w->block_begin, w->block_end,
1354 PCI_SIZE(type,tag,alignment),avoid);
1355 if (range.type != ResEnd)
1356 break;
1358 w = w->next;
1360 xf86FreeResList(w_tmp);
1361 /* if unsuccessful and memory prefetchable try non-prefetchable */
1362 if (range.type == ResEnd && w_2nd) {
1363 w_tmp = w_2nd;
1364 while (w_2nd) {
1365 if ((type & ResTypeMask) == (w_2nd->res_type & ResTypeMask)) {
1366 #ifdef DEBUG
1367 ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w_2nd->block_begin,
1368 w_2nd->block_end);
1369 #endif
1370 range = xf86GetBlock(type,PCI_SIZE(type,tag,alignment + 1),
1371 w_2nd->block_begin, w_2nd->block_end,
1372 PCI_SIZE(type,tag,alignment),avoid);
1373 if (range.type != ResEnd)
1374 break;
1376 w_2nd = w_2nd->next;
1378 xf86FreeResList(w_tmp);
1380 xf86FreeResList(avoid);
1382 if (range.type == ResEnd) {
1383 xf86MsgVerb(X_ERROR,3,"Cannot find a replacement memory range\n");
1384 xf86FreeResList(Acc);
1385 Acc = orgAcc;
1386 return FALSE;
1388 xf86FreeResList(orgAcc);
1389 #ifdef DEBUG
1390 ErrorF("begin: 0x%lx, end: 0x%lx\n",range.a,range.b);
1391 #endif
1393 (*p_size) = 0;
1394 while (alignment >> (*p_size))
1395 (*p_size)++;
1396 (*p_base) = H2B(tag,range.rBegin,type);
1397 #ifdef DEBUG
1398 ErrorF("New PCI res %i base: 0x%lx, size: 0x%lx, type %s\n",
1399 res_n,(*p_base),(1L << (*p_size)),
1400 ((type & ResPhysMask) == ResMem) ? "Mem" : "Io");
1401 #endif
1402 if (res_n != 0xff) {
1403 if ((type & ResPhysMask) == ResMem)
1404 pvp->memBase[prt] = range.rBegin;
1405 else
1406 pvp->ioBase[prt] = range.rBegin;
1407 ((CARD32 *)(&(pcp->pci_base0)))[res_n] =
1408 (CARD32)(*p_base) | (CARD32)(p_type);
1409 pciWriteLong(tag, PCI_CMD_BASE_REG + res_n * sizeof(CARD32),
1410 ((CARD32 *)(&(pcp->pci_base0)))[res_n]);
1411 if (PCI_MAP_IS64BITMEM(p_type)) {
1412 #if defined(LONG64) || defined(WORD64)
1413 ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] =
1414 (CARD32)(*p_base >> 32);
1415 pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32),
1416 ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1]);
1417 #else
1418 ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] = 0;
1419 pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32),
1421 #endif
1423 } else {
1424 pvp->biosBase = range.rBegin;
1425 pcp->pci_baserom = (pciReadLong(tag,PCI_CMD_BIOS_REG) & 0x01) |
1426 (CARD32)(*p_base);
1427 pciWriteLong(tag, PCI_CMD_BIOS_REG, pcp->pci_baserom);
1429 /* @@@ fake BIOS allocated resource */
1430 range.type |= ResBios;
1431 Acc = xf86AddResToList(Acc, &range,-1);
1433 return TRUE;
1437 _X_EXPORT Bool
1438 xf86FixPciResource(int entityIndex, int prt, memType alignment,
1439 unsigned long type)
1441 pciVideoPtr pvp = xf86GetPciInfoForEntity(entityIndex);
1442 return fixPciResource(prt, alignment, pvp, type);
1445 _X_EXPORT resPtr
1446 xf86ReallocatePciResources(int entityIndex, resPtr pRes)
1448 pciVideoPtr pvp = xf86GetPciInfoForEntity(entityIndex);
1449 resPtr pBad = NULL,pResTmp;
1450 unsigned int prt = 0;
1451 int i;
1453 if (!pvp) return pRes;
1455 while (pRes) {
1456 switch (pRes->res_type & ResPhysMask) {
1457 case ResMem:
1458 if (pRes->block_begin == B2M(TAG(pvp),pvp->biosBase) &&
1459 pRes->block_end == B2M(TAG(pvp),pvp->biosBase
1460 + SIZE(pvp->biosSize)))
1461 prt = 6;
1462 else for (i = 0 ; i < 6; i++)
1463 if ((pRes->block_begin == B2M(TAG(pvp),pvp->memBase[i]))
1464 && (pRes->block_end == B2M(TAG(pvp),pvp->memBase[i]
1465 + SIZE(pvp->size[i])))) {
1466 prt = i;
1467 break;
1469 break;
1470 case ResIo:
1471 for (i = 0 ; i < 6; i++)
1472 if (pRes->block_begin == B2I(TAG(pvp),pvp->ioBase[i])
1473 && pRes->block_end == B2I(TAG(pvp),pvp->ioBase[i]
1474 + SIZE(pvp->size[i]))) {
1475 prt = i;
1476 break;
1478 break;
1481 if (!prt) return pRes;
1483 pResTmp = pRes->next;
1484 if (! fixPciResource(prt, 0, pvp, pRes->res_type)) {
1485 pRes->next = pBad;
1486 pBad = pRes;
1487 } else
1488 xfree(pRes);
1490 pRes = pResTmp;
1492 return pBad;
1496 * BIOS releated
1498 static resPtr
1499 getOwnResources(pciVideoPtr pvp, resPtr mem)
1501 resRange range;
1502 int i;
1503 /* Make sure we don't conflict with our own mem resources */
1504 for (i = 0; i < 6; i++) {
1505 if (!pvp->memBase[i])
1506 continue;
1507 P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i],
1508 ResExcMemBlock);
1509 mem = xf86AddResToList(mem,&range,-1);
1511 return mem;
1514 static void
1515 getPciRangesForMapping(pciVideoPtr pvp, resPtr *map, resPtr *avoid)
1517 PciBusPtr pbp;
1518 resPtr tmp;
1520 *avoid = xf86DupResList(pciAvoidRes);
1522 pbp = xf86PciBus;
1523 while (pbp) {
1524 if (pbp->secondary == pvp->bus) {
1525 if (pbp->preferred_pmem)
1526 tmp = xf86DupResList(pbp->preferred_pmem);
1527 else
1528 tmp = xf86DupResList(pbp->pmem);
1529 *map = xf86JoinResLists(*map,tmp);
1530 if (pbp->preferred_mem)
1531 tmp = xf86DupResList(pbp->preferred_mem);
1532 else
1533 tmp = xf86DupResList(pbp->mem);
1534 *map = xf86JoinResLists(*map,tmp);
1535 tmp = *map;
1536 while (tmp) {
1537 tmp->block_end = min(tmp->block_end,PCI_MEM32_LENGTH_MAX);
1538 tmp = tmp->next;
1540 } else if ((pbp->primary == pvp->bus) &&
1541 (pbp->secondary >= 0) &&
1542 (pbp->primary != pbp->secondary)) {
1543 tmp = xf86DupResList(pbp->preferred_pmem);
1544 *avoid = xf86JoinResLists(*avoid, tmp);
1545 tmp = xf86DupResList(pbp->pmem);
1546 *avoid = xf86JoinResLists(*avoid, tmp);
1547 tmp = xf86DupResList(pbp->preferred_mem);
1548 *avoid = xf86JoinResLists(*avoid, tmp);
1549 tmp = xf86DupResList(pbp->mem);
1550 *avoid = xf86JoinResLists(*avoid, tmp);
1552 pbp = pbp->next;
1554 pciConvertListToHost(pvp->bus,pvp->device,pvp->func, *avoid);
1555 pciConvertListToHost(pvp->bus,pvp->device,pvp->func, *map);
1558 static memType
1559 findPciRange(PCITAG tag, resPtr m, resPtr avoid, CARD32 size)
1561 resRange range;
1562 CARD32 alignment = (1 << size) - 1;
1564 while (m) {
1565 range = xf86GetBlock(RANGE_TYPE(ResExcMemBlock, xf86GetPciDomain(tag)),
1566 PCI_SIZE(ResMem, tag, 1 << size),
1567 m->block_begin, m->block_end,
1568 PCI_SIZE(ResMem, tag, alignment),
1569 avoid);
1570 if (range.type != ResEnd) {
1571 return M2B(tag, range.rBase);
1573 m = m->next;
1575 return 0;
1578 static pciVideoPtr
1579 getPciVideoPtr(PCITAG tag)
1581 int n = 0;
1583 pciVideoPtr pvp = NULL;
1584 if (!xf86PciVideoInfo) return 0;
1586 while ((pvp = xf86PciVideoInfo[n++])) {
1587 if (pciTag(pvp->bus,pvp->device,pvp->func) == tag)
1588 return pvp;
1590 return NULL;
1593 memType
1594 getValidBIOSBase(PCITAG tag, int num)
1596 pciVideoPtr pvp = NULL;
1597 memType ret;
1598 CARD32 biosSize;
1599 resPtr mem = NULL;
1600 resPtr avoid = NULL, m = NULL;
1601 resRange range;
1603 pvp = getPciVideoPtr(tag);
1605 if (!pvp) return 0;
1607 biosSize = pvp->biosSize;
1609 if (biosSize > 24)
1610 biosSize = 24;
1612 switch ((romBaseSource)num) {
1613 case ROM_BASE_PRESET:
1614 return 0; /* This should not happen */
1615 case ROM_BASE_BIOS:
1616 /* In some cases the BIOS base register contains the size mask */
1617 if ((memType)(-1 << biosSize) == PCIGETROM(pvp->biosBase))
1618 return 0;
1619 mem = getOwnResources(pvp,mem);
1620 P_M_RANGE(range, tag, pvp->biosBase,biosSize,ResExcMemBlock);
1621 ret = pvp->biosBase;
1622 break;
1623 case ROM_BASE_MEM0:
1624 case ROM_BASE_MEM1:
1625 case ROM_BASE_MEM2:
1626 case ROM_BASE_MEM3:
1627 case ROM_BASE_MEM4:
1628 case ROM_BASE_MEM5:
1629 if (!pvp->memBase[num] || (pvp->size[num] < biosSize))
1630 return 0;
1631 P_M_RANGE(range, tag ,pvp->memBase[num],biosSize,
1632 ResExcMemBlock);
1633 ret = pvp->memBase[num];
1634 break;
1635 case ROM_BASE_FIND:
1636 ret = 0;
1637 break;
1638 default:
1639 return 0; /* This should not happen */
1642 /* Now find the ranges for validation */
1643 getPciRangesForMapping(pvp,&m,&avoid);
1645 if (!ret) {
1646 /* Return a possible window */
1647 ret = findPciRange(tag,m,avoid,biosSize);
1648 } else {
1649 #if !defined(__ia64__) /* on ia64, trust the kernel, don't look for overlaps */
1650 if (mem)
1651 pciConvertListToHost(pvp->bus,pvp->device,pvp->func, mem);
1652 if (!xf86IsSubsetOf(range, m) ||
1653 ChkConflict(&range, avoid, SETUP)
1654 || (mem && ChkConflict(&range, mem, SETUP)))
1655 ret = 0;
1656 #endif
1659 xf86FreeResList(avoid);
1660 xf86FreeResList(m);
1661 return ret;
1664 memType
1665 getEmptyPciRange(PCITAG tag, int base_reg)
1667 resPtr avoid = NULL, m = NULL;
1668 memType ret;
1670 pciVideoPtr pvp = getPciVideoPtr(tag);
1671 if (!pvp) return 0;
1672 getPciRangesForMapping(pvp,&m,&avoid);
1673 ret = findPciRange(tag,m,avoid,pvp->size[base_reg]);
1674 xf86FreeResList(avoid);
1675 xf86FreeResList(m);
1677 return ret;
1681 * xf86Bus.c interface
1684 void
1685 xf86PciProbe(void)
1688 * Initialise the pcidata entry points.
1690 xf86SetupPciIds = (ScanPciSetupProcPtr)LoaderSymbol("ScanPciSetupPciIds");
1691 xf86ClosePciIds = (ScanPciCloseProcPtr)LoaderSymbol("ScanPciClosePciIds");
1692 xf86FindPciNamesByDevice =
1693 (ScanPciFindByDeviceProcPtr)LoaderSymbol("ScanPciFindPciNamesByDevice");
1694 xf86FindPciNamesBySubsys =
1695 (ScanPciFindBySubsysProcPtr)LoaderSymbol("ScanPciFindPciNamesBySubsys");
1697 if (!xf86SetupPciIds())
1698 FatalError("xf86SetupPciIds() failed\n");
1700 FindPCIVideoInfo();
1703 static void alignBridgeRanges(PciBusPtr PciBusBase, PciBusPtr primary);
1705 static void
1706 printBridgeInfo(PciBusPtr PciBus)
1708 char primary[8], secondary[8], subordinate[8], brbus[8];
1710 xf86FormatPciBusNumber(PciBus->primary, primary);
1711 xf86FormatPciBusNumber(PciBus->secondary, secondary);
1712 xf86FormatPciBusNumber(PciBus->subordinate, subordinate);
1713 xf86FormatPciBusNumber(PciBus->brbus, brbus);
1715 xf86MsgVerb(X_INFO, 3, "Bus %s: bridge is at (%s:%d:%d), (%s,%s,%s),"
1716 " BCTRL: 0x%04x (VGA_EN is %s)\n",
1717 secondary, brbus, PciBus->brdev, PciBus->brfunc,
1718 primary, secondary, subordinate, PciBus->brcontrol,
1719 (PciBus->brcontrol & PCI_PCI_BRIDGE_VGA_EN) ?
1720 "set" : "cleared");
1721 if (PciBus->preferred_io) {
1722 xf86MsgVerb(X_INFO, 3,
1723 "Bus %s I/O range:\n", secondary);
1724 xf86PrintResList(3, PciBus->preferred_io);
1726 if (PciBus->preferred_mem) {
1727 xf86MsgVerb(X_INFO, 3,
1728 "Bus %s non-prefetchable memory range:\n", secondary);
1729 xf86PrintResList(3, PciBus->preferred_mem);
1731 if (PciBus->preferred_pmem) {
1732 xf86MsgVerb(X_INFO, 3,
1733 "Bus %s prefetchable memory range:\n", secondary);
1734 xf86PrintResList(3, PciBus->preferred_pmem);
1738 static PciBusPtr
1739 xf86GetPciBridgeInfo(void)
1741 const pciConfigPtr *pcrpp;
1742 pciConfigPtr pcrp;
1743 pciBusInfo_t *pBusInfo;
1744 resRange range;
1745 PciBusPtr PciBus, PciBusBase = NULL;
1746 PciBusPtr *pnPciBus = &PciBusBase;
1747 int MaxBus = 0;
1748 int i, domain;
1749 int primary, secondary, subordinate;
1750 memType base, limit;
1752 resPtr pciBusAccWindows = xf86PciBusAccWindowsFromOS();
1754 if (xf86PciInfo == NULL)
1755 return NULL;
1757 /* Add each bridge */
1758 for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *(++pcrpp)) {
1759 if (pcrp->busnum > MaxBus)
1760 MaxBus = pcrp->busnum;
1761 if ( pcrp->pci_base_class == PCI_CLASS_BRIDGE ) {
1762 const int sub_class = pcrp->pci_sub_class;
1764 domain = xf86GetPciDomain(pcrp->tag);
1766 switch (sub_class) {
1767 case PCI_SUBCLASS_BRIDGE_PCI:
1768 /* something fishy about the header? If so: just ignore! */
1769 if ((pcrp->pci_header_type & 0x7f) != 0x01) {
1770 xf86MsgVerb(X_WARNING, 3, "PCI-PCI bridge at %x:%x:%x has"
1771 " unexpected header: 0x%x",
1772 pcrp->busnum, pcrp->devnum,
1773 pcrp->funcnum, pcrp->pci_header_type);
1774 break;
1777 domain = pcrp->busnum & 0x0000FF00;
1778 primary = pcrp->busnum;
1779 secondary = domain | pcrp->pci_secondary_bus_number;
1780 subordinate = domain | pcrp->pci_subordinate_bus_number;
1782 /* Is this the correct bridge? If not, ignore it */
1783 pBusInfo = pcrp->businfo;
1784 if (pBusInfo && (pcrp != pBusInfo->bridge)) {
1785 xf86MsgVerb(X_WARNING, 3, "PCI bridge mismatch for bus %x:"
1786 " %x:%x:%x and %x:%x:%x\n", secondary,
1787 pcrp->busnum, pcrp->devnum, pcrp->funcnum,
1788 pBusInfo->bridge->busnum,
1789 pBusInfo->bridge->devnum,
1790 pBusInfo->bridge->funcnum);
1791 break;
1794 if (pBusInfo && pBusInfo->funcs->pciGetBridgeBuses)
1795 (*pBusInfo->funcs->pciGetBridgeBuses)(secondary,
1796 &primary,
1797 &secondary,
1798 &subordinate);
1800 if (!pcrp->fakeDevice && (primary >= secondary)) {
1801 xf86MsgVerb(X_WARNING, 3, "Misconfigured PCI bridge"
1802 " %x:%x:%x (%x,%x)\n",
1803 pcrp->busnum, pcrp->devnum, pcrp->funcnum,
1804 primary, secondary);
1805 break;
1808 *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
1809 pnPciBus = &PciBus->next;
1811 PciBus->primary = primary;
1812 PciBus->secondary = secondary;
1813 PciBus->subordinate = subordinate;
1815 PciBus->brbus = pcrp->busnum;
1816 PciBus->brdev = pcrp->devnum;
1817 PciBus->brfunc = pcrp->funcnum;
1819 PciBus->subclass = sub_class;
1821 /* The Intel bridges don't report as transparent
1822 but guess what they are - from Linux kernel - airlied */
1823 if ((pcrp->pci_vendor == PCI_VENDOR_INTEL) &&
1824 ((pcrp->pci_device & 0xff00) == 0x2400)) {
1825 xf86MsgVerb(X_INFO, 3, "Intel Bridge workaround enabled\n");
1826 PciBus->interface = PCI_IF_BRIDGE_PCI_SUBTRACTIVE;
1827 } else {
1828 PciBus->interface = pcrp->pci_prog_if;
1831 if (pBusInfo && pBusInfo->funcs->pciControlBridge)
1832 PciBus->brcontrol =
1833 (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
1834 else
1835 PciBus->brcontrol = pcrp->pci_bridge_control;
1837 if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
1838 (*pBusInfo->funcs->pciGetBridgeResources)(secondary,
1839 (pointer *)&PciBus->preferred_io,
1840 (pointer *)&PciBus->preferred_mem,
1841 (pointer *)&PciBus->preferred_pmem);
1842 break;
1845 if ((pcrp->pci_command & PCI_CMD_IO_ENABLE) &&
1846 (pcrp->pci_upper_io_base || pcrp->pci_io_base ||
1847 pcrp->pci_upper_io_limit || pcrp->pci_io_limit)) {
1848 base = (pcrp->pci_upper_io_base << 16) |
1849 ((pcrp->pci_io_base & 0xf0u) << 8);
1850 limit = (pcrp->pci_upper_io_limit << 16) |
1851 ((pcrp->pci_io_limit & 0xf0u) << 8) | 0x0fff;
1853 * Deal with bridge ISA mode (256 wide ranges spaced 1K
1854 * apart, but only in the first 64K).
1856 if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
1857 while ((base <= (CARD16)(-1)) && (base <= limit)) {
1858 PCI_I_RANGE(range, pcrp->tag,
1859 base, base + (CARD8)(-1),
1860 ResIo | ResBlock | ResExclusive);
1861 PciBus->preferred_io =
1862 xf86AddResToList(PciBus->preferred_io,
1863 &range, -1);
1864 base += 0x0400;
1867 if (base <= limit) {
1868 PCI_I_RANGE(range, pcrp->tag, base, limit,
1869 ResIo | ResBlock | ResExclusive);
1870 PciBus->preferred_io =
1871 xf86AddResToList(PciBus->preferred_io, &range, -1);
1874 if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) {
1876 * The P2P spec requires these next two, but some bridges
1877 * don't comply. Err on the side of caution, making the not
1878 * so bold assumption that no bridge would ever re-route the
1879 * bottom megabyte.
1881 if (pcrp->pci_mem_base || pcrp->pci_mem_limit) {
1882 base = pcrp->pci_mem_base & 0xfff0u;
1883 limit = pcrp->pci_mem_limit & 0xfff0u;
1884 if (base <= limit) {
1885 PCI_M_RANGE(range, pcrp->tag,
1886 base << 16, (limit << 16) | 0x0fffff,
1887 ResMem | ResBlock | ResExclusive);
1888 PciBus->preferred_mem =
1889 xf86AddResToList(PciBus->preferred_mem, &range, -1);
1893 if (pcrp->pci_prefetch_mem_base ||
1894 pcrp->pci_prefetch_mem_limit ||
1895 pcrp->pci_prefetch_upper_mem_base ||
1896 pcrp->pci_prefetch_upper_mem_limit) {
1897 base = pcrp->pci_prefetch_mem_base & 0xfff0u;
1898 limit = pcrp->pci_prefetch_mem_limit & 0xfff0u;
1899 #if defined(LONG64) || defined(WORD64)
1900 base |= (memType)pcrp->pci_prefetch_upper_mem_base << 16;
1901 limit |= (memType)pcrp->pci_prefetch_upper_mem_limit << 16;
1902 #endif
1903 if (base <= limit) {
1904 PCI_M_RANGE(range, pcrp->tag,
1905 base << 16, (limit << 16) | 0xfffff,
1906 ResMem | ResBlock | ResExclusive);
1907 PciBus->preferred_pmem =
1908 xf86AddResToList(PciBus->preferred_pmem,
1909 &range, -1);
1913 break;
1915 case PCI_SUBCLASS_BRIDGE_CARDBUS:
1916 /* something fishy about the header? If so: just ignore! */
1917 if ((pcrp->pci_header_type & 0x7f) != 0x02) {
1918 xf86MsgVerb(X_WARNING, 3, "PCI-CardBus bridge at %x:%x:%x"
1919 " has unexpected header: 0x%x",
1920 pcrp->busnum, pcrp->devnum,
1921 pcrp->funcnum, pcrp->pci_header_type);
1922 break;
1925 domain = pcrp->busnum & 0x0000FF00;
1926 primary = pcrp->busnum;
1927 secondary = domain | pcrp->pci_cb_cardbus_bus_number;
1928 subordinate = domain | pcrp->pci_subordinate_bus_number;
1930 /* Is this the correct bridge? If not, ignore it */
1931 pBusInfo = pcrp->businfo;
1932 if (pBusInfo && (pcrp != pBusInfo->bridge)) {
1933 xf86MsgVerb(X_WARNING, 3, "CardBus bridge mismatch for bus"
1934 " %x: %x:%x:%x and %x:%x:%x\n", secondary,
1935 pcrp->busnum, pcrp->devnum, pcrp->funcnum,
1936 pBusInfo->bridge->busnum,
1937 pBusInfo->bridge->devnum,
1938 pBusInfo->bridge->funcnum);
1939 break;
1942 if (pBusInfo && pBusInfo->funcs->pciGetBridgeBuses)
1943 (*pBusInfo->funcs->pciGetBridgeBuses)(secondary,
1944 &primary,
1945 &secondary,
1946 &subordinate);
1948 if (primary >= secondary) {
1949 if (pcrp->pci_cb_cardbus_bus_number != 0)
1950 xf86MsgVerb(X_WARNING, 3, "Misconfigured CardBus"
1951 " bridge %x:%x:%x (%x,%x)\n",
1952 pcrp->busnum, pcrp->devnum, pcrp->funcnum,
1953 primary, secondary);
1954 break;
1957 *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
1958 pnPciBus = &PciBus->next;
1960 PciBus->primary = primary;
1961 PciBus->secondary = secondary;
1962 PciBus->subordinate = subordinate;
1964 PciBus->brbus = pcrp->busnum;
1965 PciBus->brdev = pcrp->devnum;
1966 PciBus->brfunc = pcrp->funcnum;
1968 PciBus->subclass = sub_class;
1969 PciBus->interface = pcrp->pci_prog_if;
1971 if (pBusInfo && pBusInfo->funcs->pciControlBridge)
1972 PciBus->brcontrol =
1973 (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
1974 else
1975 PciBus->brcontrol = pcrp->pci_bridge_control;
1977 if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
1978 (*pBusInfo->funcs->pciGetBridgeResources)(secondary,
1979 (pointer *)&PciBus->preferred_io,
1980 (pointer *)&PciBus->preferred_mem,
1981 (pointer *)&PciBus->preferred_pmem);
1982 break;
1985 if (pcrp->pci_command & PCI_CMD_IO_ENABLE) {
1986 if (pcrp->pci_cb_iobase0) {
1987 base = PCI_CB_IOBASE(pcrp->pci_cb_iobase0);
1988 limit = PCI_CB_IOLIMIT(pcrp->pci_cb_iolimit0);
1991 * Deal with bridge ISA mode (256-wide ranges spaced 1K
1992 * apart (start to start), but only in the first 64K).
1994 if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
1995 while ((base <= (CARD16)(-1)) &&
1996 (base <= limit)) {
1997 PCI_I_RANGE(range, pcrp->tag,
1998 base, base + (CARD8)(-1),
1999 ResIo | ResBlock | ResExclusive);
2000 PciBus->preferred_io =
2001 xf86AddResToList(PciBus->preferred_io,
2002 &range, -1);
2003 base += 0x0400;
2007 if (base <= limit) {
2008 PCI_I_RANGE(range, pcrp->tag, base, limit,
2009 ResIo | ResBlock | ResExclusive);
2010 PciBus->preferred_io =
2011 xf86AddResToList(PciBus->preferred_io,
2012 &range, -1);
2016 if (pcrp->pci_cb_iobase1) {
2017 base = PCI_CB_IOBASE(pcrp->pci_cb_iobase1);
2018 limit = PCI_CB_IOLIMIT(pcrp->pci_cb_iolimit1);
2021 * Deal with bridge ISA mode (256-wide ranges spaced 1K
2022 * apart (start to start), but only in the first 64K).
2024 if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
2025 while ((base <= (CARD16)(-1)) &&
2026 (base <= limit)) {
2027 PCI_I_RANGE(range, pcrp->tag,
2028 base, base + (CARD8)(-1),
2029 ResIo | ResBlock | ResExclusive);
2030 PciBus->preferred_io =
2031 xf86AddResToList(PciBus->preferred_io,
2032 &range, -1);
2033 base += 0x0400;
2037 if (base <= limit) {
2038 PCI_I_RANGE(range, pcrp->tag, base, limit,
2039 ResIo | ResBlock | ResExclusive);
2040 PciBus->preferred_io =
2041 xf86AddResToList(PciBus->preferred_io,
2042 &range, -1);
2047 if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) {
2048 if ((pcrp->pci_cb_membase0) &&
2049 (pcrp->pci_cb_membase0 <= pcrp->pci_cb_memlimit0)) {
2050 PCI_M_RANGE(range, pcrp->tag,
2051 pcrp->pci_cb_membase0 & ~0x0fff,
2052 pcrp->pci_cb_memlimit0 | 0x0fff,
2053 ResMem | ResBlock | ResExclusive);
2054 if (pcrp->pci_bridge_control &
2055 PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)
2056 PciBus->preferred_pmem =
2057 xf86AddResToList(PciBus->preferred_pmem,
2058 &range, -1);
2059 else
2060 PciBus->preferred_mem =
2061 xf86AddResToList(PciBus->preferred_mem,
2062 &range, -1);
2064 if ((pcrp->pci_cb_membase1) &&
2065 (pcrp->pci_cb_membase1 <= pcrp->pci_cb_memlimit1)) {
2066 PCI_M_RANGE(range, pcrp->tag,
2067 pcrp->pci_cb_membase1 & ~0x0fff,
2068 pcrp->pci_cb_memlimit1 | 0x0fff,
2069 ResMem | ResBlock | ResExclusive);
2070 if (pcrp->pci_bridge_control &
2071 PCI_CB_BRIDGE_CTL_PREFETCH_MEM1)
2072 PciBus->preferred_pmem =
2073 xf86AddResToList(PciBus->preferred_pmem,
2074 &range, -1);
2075 else
2076 PciBus->preferred_mem =
2077 xf86AddResToList(PciBus->preferred_mem,
2078 &range, -1);
2082 break;
2084 case PCI_SUBCLASS_BRIDGE_ISA:
2085 case PCI_SUBCLASS_BRIDGE_EISA:
2086 case PCI_SUBCLASS_BRIDGE_MC:
2087 *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
2088 pnPciBus = &PciBus->next;
2089 PciBus->primary = pcrp->busnum;
2090 PciBus->secondary = PciBus->subordinate = -1;
2091 PciBus->brbus = pcrp->busnum;
2092 PciBus->brdev = pcrp->devnum;
2093 PciBus->brfunc = pcrp->funcnum;
2094 PciBus->subclass = sub_class;
2095 PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
2096 break;
2098 case PCI_SUBCLASS_BRIDGE_HOST:
2099 /* Is this the correct bridge? If not, ignore bus info */
2100 pBusInfo = pcrp->businfo;
2102 if (!pBusInfo || pBusInfo == HOST_NO_BUS)
2103 break;
2105 secondary = 0;
2106 /* Find "secondary" bus segment */
2107 while (pBusInfo != pciBusInfo[secondary])
2108 secondary++;
2109 if (pcrp != pBusInfo->bridge) {
2110 xf86MsgVerb(X_WARNING, 3, "Host bridge mismatch for"
2111 " bus %x: %x:%x:%x and %x:%x:%x\n",
2112 pBusInfo->primary_bus,
2113 pcrp->busnum, pcrp->devnum, pcrp->funcnum,
2114 pBusInfo->bridge->busnum,
2115 pBusInfo->bridge->devnum,
2116 pBusInfo->bridge->funcnum);
2117 pBusInfo = NULL;
2120 *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
2121 pnPciBus = &PciBus->next;
2124 PciBus->primary = PciBus->secondary = secondary;
2125 PciBus->subordinate = pciNumBuses - 1;
2127 if (pBusInfo->funcs->pciGetBridgeBuses)
2128 (*pBusInfo->funcs->pciGetBridgeBuses)
2129 (secondary,
2130 &PciBus->primary,
2131 &PciBus->secondary,
2132 &PciBus->subordinate);
2134 PciBus->brbus = pcrp->busnum;
2135 PciBus->brdev = pcrp->devnum;
2136 PciBus->brfunc = pcrp->funcnum;
2138 PciBus->subclass = sub_class;
2140 if (pBusInfo && pBusInfo->funcs->pciControlBridge)
2141 PciBus->brcontrol =
2142 (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
2143 else
2144 PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
2146 if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
2147 (*pBusInfo->funcs->pciGetBridgeResources)
2148 (secondary,
2149 (pointer *)&PciBus->preferred_io,
2150 (pointer *)&PciBus->preferred_mem,
2151 (pointer *)&PciBus->preferred_pmem);
2152 break;
2155 PciBus->preferred_io =
2156 xf86ExtractTypeFromList(pciBusAccWindows,
2157 RANGE_TYPE(ResIo, domain));
2158 PciBus->preferred_mem =
2159 xf86ExtractTypeFromList(pciBusAccWindows,
2160 RANGE_TYPE(ResMem, domain));
2161 PciBus->preferred_pmem =
2162 xf86ExtractTypeFromList(pciBusAccWindows,
2163 RANGE_TYPE(ResMem, domain));
2164 break;
2166 default:
2167 break;
2171 for (i = 0; i <= MaxBus; i++) { /* find PCI buses not attached to bridge */
2172 if (!pciBusInfo[i])
2173 continue;
2174 for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next)
2175 if (PciBus->secondary == i) break;
2176 if (!PciBus) { /* We assume it's behind a HOST-PCI bridge */
2178 * Find the 'smallest' free HOST-PCI bridge, where 'small' is in
2179 * the order of pciTag().
2181 PCITAG minTag = 0xFFFFFFFF, tag;
2182 PciBusPtr PciBusFound = NULL;
2183 for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next)
2184 if ((PciBus->subclass == PCI_SUBCLASS_BRIDGE_HOST) &&
2185 (PciBus->secondary == -1) &&
2186 ((tag = pciTag(PciBus->brbus,PciBus->brdev,PciBus->brfunc))
2187 < minTag) ) {
2188 minTag = tag;
2189 PciBusFound = PciBus;
2191 if (PciBusFound)
2192 PciBusFound->secondary = i;
2193 else { /* if nothing found it may not be visible: create new */
2194 /* Find a device on this bus */
2195 domain = 0;
2196 for (pcrpp = xf86PciInfo; (pcrp = *pcrpp); pcrpp++) {
2197 if (pcrp->busnum == i) {
2198 domain = xf86GetPciDomain(pcrp->tag);
2199 break;
2202 *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
2203 pnPciBus = &PciBus->next;
2204 PciBus->primary = PciBus->secondary = i;
2205 PciBus->subclass = PCI_SUBCLASS_BRIDGE_HOST;
2206 PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
2207 PciBus->preferred_io =
2208 xf86ExtractTypeFromList(pciBusAccWindows,
2209 RANGE_TYPE(ResIo, domain));
2210 PciBus->preferred_mem =
2211 xf86ExtractTypeFromList(pciBusAccWindows,
2212 RANGE_TYPE(ResMem, domain));
2213 PciBus->preferred_pmem =
2214 xf86ExtractTypeFromList(pciBusAccWindows,
2215 RANGE_TYPE(ResMem, domain));
2220 for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
2221 if (PciBus->primary == PciBus->secondary) {
2222 alignBridgeRanges(PciBusBase, PciBus);
2226 for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
2227 switch (PciBus->subclass) {
2228 case PCI_SUBCLASS_BRIDGE_PCI:
2229 if (PciBus->interface == PCI_IF_BRIDGE_PCI_SUBTRACTIVE)
2230 xf86MsgVerb(X_INFO, 3, "Subtractive PCI-to-PCI bridge:\n");
2231 else
2232 xf86MsgVerb(X_INFO, 3, "PCI-to-PCI bridge:\n");
2233 break;
2234 case PCI_SUBCLASS_BRIDGE_CARDBUS:
2235 xf86MsgVerb(X_INFO, 3, "PCI-to-CardBus bridge:\n");
2236 break;
2237 case PCI_SUBCLASS_BRIDGE_HOST:
2238 xf86MsgVerb(X_INFO, 3, "Host-to-PCI bridge:\n");
2239 break;
2240 case PCI_SUBCLASS_BRIDGE_ISA:
2241 xf86MsgVerb(X_INFO, 3, "PCI-to-ISA bridge:\n");
2242 break;
2243 case PCI_SUBCLASS_BRIDGE_EISA:
2244 xf86MsgVerb(X_INFO, 3, "PCI-to-EISA bridge:\n");
2245 break;
2246 case PCI_SUBCLASS_BRIDGE_MC:
2247 xf86MsgVerb(X_INFO, 3, "PCI-to-MCA bridge:\n");
2248 break;
2249 default:
2250 break;
2252 printBridgeInfo(PciBus);
2254 xf86FreeResList(pciBusAccWindows);
2255 return PciBusBase;
2258 static void
2259 alignBridgeRanges(PciBusPtr PciBusBase, PciBusPtr primary)
2261 PciBusPtr PciBus;
2263 for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
2264 if ((PciBus != primary) && (PciBus->primary != -1)
2265 && (PciBus->primary == primary->secondary)) {
2266 resPtr tmp;
2267 tmp = xf86FindIntersectOfLists(primary->preferred_io,
2268 PciBus->preferred_io);
2269 xf86FreeResList(PciBus->preferred_io);
2270 PciBus->preferred_io = tmp;
2271 tmp = xf86FindIntersectOfLists(primary->preferred_pmem,
2272 PciBus->preferred_pmem);
2273 xf86FreeResList(PciBus->preferred_pmem);
2274 PciBus->preferred_pmem = tmp;
2275 tmp = xf86FindIntersectOfLists(primary->preferred_mem,
2276 PciBus->preferred_mem);
2277 xf86FreeResList(PciBus->preferred_mem);
2278 PciBus->preferred_mem = tmp;
2280 /* Deal with subtractive decoding */
2281 switch (PciBus->subclass) {
2282 case PCI_SUBCLASS_BRIDGE_PCI:
2283 if (PciBus->interface != PCI_IF_BRIDGE_PCI_SUBTRACTIVE)
2284 break;
2285 /* Fall through */
2286 #if 0 /* Not yet */
2287 case PCI_SUBCLASS_BRIDGE_ISA:
2288 case PCI_SUBCLASS_BRIDGE_EISA:
2289 case PCI_SUBCLASS_BRIDGE_MC:
2290 #endif
2291 if (!(PciBus->io = primary->io))
2292 PciBus->io = primary->preferred_io;
2293 if (!(PciBus->mem = primary->mem))
2294 PciBus->mem = primary->preferred_mem;
2295 if (!(PciBus->pmem = primary->pmem))
2296 PciBus->pmem = primary->preferred_pmem;
2297 default:
2298 break;
2301 alignBridgeRanges(PciBusBase, PciBus);
2306 void
2307 ValidatePci(void)
2309 pciVideoPtr pvp, pvp1;
2310 PciBusPtr pbp;
2311 pciConfigPtr pcrp, *pcrpp;
2312 CARD32 *basep;
2313 resPtr Sys;
2314 resRange range;
2315 int n = 0, m, i;
2317 if (!xf86PciVideoInfo) return;
2320 * Mark all pciInfoRecs that need to be validated. These are
2321 * the ones which have been assigned to a screen.
2323 Sys = xf86DupResList(osRes);
2324 /* Only validate graphics devices in use */
2325 for (i=0; i<xf86NumScreens; i++) {
2326 for (m = 0; m < xf86Screens[i]->numEntities; m++)
2327 if ((pvp = xf86GetPciInfoForEntity(xf86Screens[i]->entityList[m])))
2328 pvp->validate = TRUE;
2332 * Collect all background PCI resources we need to validate against.
2333 * These are all resources which don't belong to PCINONSYSTEMCLASSES
2334 * and which have not been assigned to an entity.
2336 /* First get the PCIINFOCLASSES */
2337 m = 0;
2338 while ((pvp = xf86PciVideoInfo[m++])) {
2339 /* is it a PCINONSYSTEMCLASS? */
2340 if (PCINONSYSTEMCLASSES(pvp->class, pvp->subclass))
2341 continue;
2342 /* has it an Entity assigned to it? */
2343 for (i=0; i<xf86NumEntities; i++) {
2344 EntityPtr p = xf86Entities[i];
2345 if (p->busType != BUS_PCI)
2346 continue;
2347 if (p->pciBusId.bus == pvp->bus
2348 && p->pciBusId.device == pvp->device
2349 && p->pciBusId.func == pvp->func)
2350 break;
2352 if (i != xf86NumEntities) /* found an Entity for this one */
2353 continue;
2355 for (i = 0; i<6; i++) {
2356 if (pvp->ioBase[i]) {
2357 PV_I_RANGE(range,pvp,i,ResExcIoBlock);
2358 Sys = xf86AddResToList(Sys,&range,-1);
2359 } else if (pvp->memBase[i]) {
2360 PV_M_RANGE(range,pvp,i,ResExcMemBlock);
2361 Sys = xf86AddResToList(Sys,&range,-1);
2365 for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
2367 /* These were handled above */
2368 if (PCIINFOCLASSES(pcrp->pci_base_class, pcrp->pci_sub_class))
2369 continue;
2371 if ((pcrp->pci_header_type & 0x7f) ||
2372 !(pcrp->pci_command & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)))
2373 continue;
2375 basep = &pcrp->pci_base0;
2376 for (i = 0; i < 6; i++) {
2377 if (basep[i]) {
2378 if (PCI_MAP_IS_IO(basep[i])) {
2379 if (!(pcrp->pci_command & PCI_CMD_IO_ENABLE))
2380 continue;
2381 P_I_RANGE(range, pcrp->tag, PCIGETIO(basep[i]),
2382 pcrp->basesize[i], ResExcIoBlock)
2383 } else if (!PCI_MAP_IS64BITMEM(basep[i])) {
2384 if (!(pcrp->pci_command & PCI_CMD_MEM_ENABLE))
2385 continue;
2386 P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i]),
2387 pcrp->basesize[i], ResExcMemBlock)
2388 } else {
2389 i++;
2390 if (!(pcrp->pci_command & PCI_CMD_MEM_ENABLE))
2391 continue;
2392 #if defined(LONG64) || defined(WORD64)
2393 P_M_RANGE(range, pcrp->tag, PCIGETMEMORY64(basep[i-1]),
2394 pcrp->basesize[i-1], ResExcMemBlock)
2395 #else
2396 if (basep[i])
2397 continue;
2398 P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i-1]),
2399 pcrp->basesize[i-1], ResExcMemBlock)
2400 #endif
2402 Sys = xf86AddResToList(Sys, &range, -1);
2405 if ((pcrp->pci_baserom) &&
2406 (pcrp->pci_command & PCI_CMD_MEM_ENABLE) &&
2407 (pcrp->pci_baserom & PCI_MAP_ROM_DECODE_ENABLE)) {
2408 P_M_RANGE(range,pcrp->tag,PCIGETROM(pcrp->pci_baserom),
2409 pcrp->basesize[6],ResExcMemBlock);
2410 Sys = xf86AddResToList(Sys, &range, -1);
2413 #ifdef DEBUG
2414 xf86MsgVerb(X_INFO, 3,"Sys:\n");
2415 xf86PrintResList(3,Sys);
2416 #endif
2419 * The order the video devices are listed in is
2420 * just right: the lower buses come first.
2421 * This way we attempt to fix a conflict of
2422 * a lower bus device with a higher bus device
2423 * where we have more room to find different
2424 * resources.
2426 while ((pvp = xf86PciVideoInfo[n++])) {
2427 resPtr res_mp = NULL, res_m_io = NULL;
2428 resPtr NonSys;
2429 resPtr tmp, avoid = NULL;
2431 if (!pvp->validate) continue;
2432 NonSys = xf86DupResList(Sys);
2433 m = n;
2434 while ((pvp1 = xf86PciVideoInfo[m++])) {
2435 if (!pvp1->validate) continue;
2436 for (i = 0; i<6; i++) {
2437 if (pvp1->ioBase[i]) {
2438 PV_I_RANGE(range,pvp1,i,ResExcIoBlock);
2439 NonSys = xf86AddResToList(NonSys,&range,-1);
2440 } else if (pvp1->memBase[i]) {
2441 PV_M_RANGE(range,pvp1,i,ResExcMemBlock);
2442 NonSys = xf86AddResToList(NonSys,&range,-1);
2446 #ifdef DEBUG
2447 xf86MsgVerb(X_INFO, 3,"NonSys:\n");
2448 xf86PrintResList(3,NonSys);
2449 #endif
2450 pbp = xf86PciBus;
2451 while (pbp) {
2452 if (pbp->secondary == pvp->bus) {
2453 if (pbp->preferred_pmem) {
2454 /* keep prefetchable separate */
2455 res_mp =
2456 xf86FindIntersectOfLists(pbp->preferred_pmem, ResRange);
2458 if (pbp->pmem) {
2459 res_mp = xf86FindIntersectOfLists(pbp->pmem, ResRange);
2461 if (pbp->preferred_mem) {
2462 res_m_io =
2463 xf86FindIntersectOfLists(pbp->preferred_mem, ResRange);
2465 if (pbp->mem) {
2466 res_m_io = xf86FindIntersectOfLists(pbp->mem, ResRange);
2468 if (pbp->preferred_io) {
2469 res_m_io = xf86JoinResLists(res_m_io,
2470 xf86FindIntersectOfLists(pbp->preferred_io, ResRange));
2472 if (pbp->io) {
2473 res_m_io = xf86JoinResLists(res_m_io,
2474 xf86FindIntersectOfLists(pbp->preferred_io, ResRange));
2476 } else if ((pbp->primary == pvp->bus) &&
2477 (pbp->secondary >= 0) &&
2478 (pbp->primary != pbp->secondary)) {
2479 tmp = xf86DupResList(pbp->preferred_pmem);
2480 avoid = xf86JoinResLists(avoid, tmp);
2481 tmp = xf86DupResList(pbp->preferred_mem);
2482 avoid = xf86JoinResLists(avoid, tmp);
2483 tmp = xf86DupResList(pbp->preferred_io);
2484 avoid = xf86JoinResLists(avoid, tmp);
2486 pbp = pbp->next;
2488 if (res_m_io == NULL)
2489 res_m_io = xf86DupResList(ResRange);
2491 pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
2493 #ifdef DEBUG
2494 xf86MsgVerb(X_INFO, 3,"avoid:\n");
2495 xf86PrintResList(3,avoid);
2496 xf86MsgVerb(X_INFO, 3,"prefetchable Memory:\n");
2497 xf86PrintResList(3,res_mp);
2498 xf86MsgVerb(X_INFO, 3,"MEM/IO:\n");
2499 xf86PrintResList(3,res_m_io);
2500 #endif
2501 for (i = 0; i < 6; i++) {
2502 int j;
2503 resPtr own = NULL;
2504 for (j = i+1; j < 6; j++) {
2505 if (pvp->ioBase[j]) {
2506 PV_I_RANGE(range,pvp,j,ResExcIoBlock);
2507 own = xf86AddResToList(own,&range,-1);
2508 } else if (pvp->memBase[j]) {
2509 PV_M_RANGE(range,pvp,j,ResExcMemBlock);
2510 own = xf86AddResToList(own,&range,-1);
2513 #ifdef DEBUG
2514 xf86MsgVerb(X_INFO, 3, "own:\n");
2515 xf86PrintResList(3, own);
2516 #endif
2517 if (pvp->ioBase[i]) {
2518 PV_I_RANGE(range,pvp,i,ResExcIoBlock);
2519 if (xf86IsSubsetOf(range,res_m_io)
2520 && ! ChkConflict(&range,own,SETUP)
2521 && ! ChkConflict(&range,avoid,SETUP)
2522 && ! ChkConflict(&range,NonSys,SETUP)) {
2523 xf86FreeResList(own);
2524 continue;
2526 xf86MsgVerb(X_WARNING, 0,
2527 "****INVALID IO ALLOCATION**** b: 0x%lx e: 0x%lx "
2528 "correcting\a\n", range.rBegin,range.rEnd);
2529 #ifdef DEBUG
2530 sleep(2);
2531 #endif
2532 fixPciResource(i, 0, pvp, range.type);
2533 } else if (pvp->memBase[i]) {
2534 PV_M_RANGE(range,pvp,i,ResExcMemBlock);
2535 if (pvp->type[i] & PCI_MAP_MEMORY_CACHABLE) {
2536 if (xf86IsSubsetOf(range,res_mp)
2537 && ! ChkConflict(&range,own,SETUP)
2538 && ! ChkConflict(&range,avoid,SETUP)
2539 && ! ChkConflict(&range,NonSys,SETUP)) {
2540 xf86FreeResList(own);
2541 continue;
2544 if (xf86IsSubsetOf(range,res_m_io)
2545 && ! ChkConflict(&range,own,SETUP)
2546 && ! ChkConflict(&range,avoid,SETUP)
2547 && ! ChkConflict(&range,NonSys,SETUP)) {
2548 xf86FreeResList(own);
2549 continue;
2551 xf86MsgVerb(X_WARNING, 0,
2552 "****INVALID MEM ALLOCATION**** b: 0x%lx e: 0x%lx "
2553 "correcting\a\n", range.rBegin,range.rEnd);
2554 if (ChkConflict(&range,own,SETUP)) {
2555 xf86MsgVerb(X_INFO,3,"own\n");
2556 xf86PrintResList(3,own);
2558 if (ChkConflict(&range,avoid,SETUP)) {
2559 xf86MsgVerb(X_INFO,3,"avoid\n");
2560 xf86PrintResList(3,avoid);
2562 if (ChkConflict(&range,NonSys,SETUP)) {
2563 xf86MsgVerb(X_INFO,3,"NonSys\n");
2564 xf86PrintResList(3,NonSys);
2567 #ifdef DEBUG
2568 sleep(2);
2569 #endif
2570 fixPciResource(i, 0, pvp, range.type);
2572 xf86FreeResList(own);
2574 xf86FreeResList(avoid);
2575 xf86FreeResList(NonSys);
2576 xf86FreeResList(res_mp);
2577 xf86FreeResList(res_m_io);
2579 xf86FreeResList(Sys);
2582 resList
2583 GetImplicitPciResources(int entityIndex)
2585 pciVideoPtr pvp;
2586 int i;
2587 resList list = NULL;
2588 int num = 0;
2590 if (! (pvp = xf86GetPciInfoForEntity(entityIndex))) return NULL;
2592 for (i = 0; i < 6; i++) {
2593 if (pvp->ioBase[i]) {
2594 list = xnfrealloc(list,sizeof(resRange) * (++num));
2595 PV_I_RANGE(list[num - 1],pvp,i,ResShrIoBlock | ResBios);
2596 } else if (pvp->memBase[i]) {
2597 list = xnfrealloc(list,sizeof(resRange) * (++num));
2598 PV_M_RANGE(list[num - 1],pvp,i,ResShrMemBlock | ResBios);
2601 #if 0
2602 if (pvp->biosBase) {
2603 list = xnfrealloc(list,sizeof(resRange) * (++num));
2604 PV_B_RANGE(list[num - 1],pvp,ResShrMemBlock | ResBios);
2606 #endif
2607 list = xnfrealloc(list,sizeof(resRange) * (++num));
2608 list[num - 1].type = ResEnd;
2610 return list;
2613 void
2614 initPciState(void)
2616 int i = 0;
2617 int j = 0;
2618 pciVideoPtr pvp;
2619 pciAccPtr pcaccp;
2621 if (xf86PciAccInfo != NULL)
2622 return;
2624 if (xf86PciVideoInfo == NULL)
2625 return;
2627 while ((pvp = xf86PciVideoInfo[i]) != NULL) {
2628 i++;
2629 j++;
2630 xf86PciAccInfo = xnfrealloc(xf86PciAccInfo,
2631 sizeof(pciAccPtr) * (j + 1));
2632 xf86PciAccInfo[j] = NULL;
2633 pcaccp = xf86PciAccInfo[j - 1] = xnfalloc(sizeof(pciAccRec));
2634 pcaccp->busnum = pvp->bus;
2635 pcaccp->devnum = pvp->device;
2636 pcaccp->funcnum = pvp->func;
2637 pcaccp->arg.tag = pciTag(pvp->bus, pvp->device, pvp->func);
2638 pcaccp->ioAccess.AccessDisable = pciIoAccessDisable;
2639 pcaccp->ioAccess.AccessEnable = pciIoAccessEnable;
2640 pcaccp->ioAccess.arg = &pcaccp->arg;
2641 pcaccp->io_memAccess.AccessDisable = pciIo_MemAccessDisable;
2642 pcaccp->io_memAccess.AccessEnable = pciIo_MemAccessEnable;
2643 pcaccp->io_memAccess.arg = &pcaccp->arg;
2644 pcaccp->memAccess.AccessDisable = pciMemAccessDisable;
2645 pcaccp->memAccess.AccessEnable = pciMemAccessEnable;
2646 pcaccp->memAccess.arg = &pcaccp->arg;
2647 if (PCISHAREDIOCLASSES(pvp->class, pvp->subclass))
2648 pcaccp->ctrl = TRUE;
2649 else
2650 pcaccp->ctrl = FALSE;
2651 savePciState(pcaccp->arg.tag, &pcaccp->save);
2652 pcaccp->arg.ctrl = pcaccp->save.command;
2657 * initPciBusState() - fill out the BusAccRec for a PCI bus.
2658 * Theory: each bus is associated with one bridge connecting it
2659 * to its parent bus. The address of a bridge is therefore stored
2660 * in the BusAccRec of the bus it connects to. Each bus can
2661 * have several bridges connecting secondary buses to it. Only one
2662 * of these bridges can be open. Therefore the status of a bridge
2663 * associated with a bus is stored in the BusAccRec of the parent
2664 * the bridge connects to. The first member of the structure is
2665 * a pointer to a function that open access to this bus. This function
2666 * receives a pointer to the structure itself as argument. This
2667 * design should be common to BusAccRecs of any type of buses we
2668 * support. The remeinder of the structure is bus type specific.
2669 * In this case it contains a pointer to the structure of the
2670 * parent bus. Thus enabling access to a specific bus is simple:
2671 * 1. Close any bridge going to secondary buses.
2672 * 2. Climb down the ladder and enable any bridge on buses
2673 * on the path from the CPU to this bus.
2676 void
2677 initPciBusState(void)
2679 BusAccPtr pbap, pbap_tmp;
2680 PciBusPtr pbp = xf86PciBus;
2681 pciBusInfo_t *pBusInfo;
2683 while (pbp) {
2684 pbap = xnfcalloc(1,sizeof(BusAccRec));
2685 pbap->busdep.pci.bus = pbp->secondary;
2686 pbap->busdep.pci.primary_bus = pbp->primary;
2687 pbap->busdep_type = BUS_PCI;
2688 pbap->busdep.pci.acc = PCITAG_SPECIAL;
2690 if ((pbp->secondary >= 0) && (pbp->secondary < pciNumBuses) &&
2691 (pBusInfo = pciBusInfo[pbp->secondary]) &&
2692 pBusInfo->funcs->pciControlBridge) {
2693 pbap->type = BUS_PCI;
2694 pbap->save_f = savePciDrvBusState;
2695 pbap->restore_f = restorePciDrvBusState;
2696 pbap->set_f = pciSetBusAccess;
2697 pbap->enable_f = pciDrvBusAccessEnable;
2698 pbap->disable_f = pciDrvBusAccessDisable;
2699 savePciDrvBusState(pbap);
2700 } else switch (pbp->subclass) {
2701 case PCI_SUBCLASS_BRIDGE_HOST:
2702 pbap->type = BUS_PCI;
2703 pbap->set_f = pciSetBusAccess;
2704 break;
2705 case PCI_SUBCLASS_BRIDGE_PCI:
2706 case PCI_SUBCLASS_BRIDGE_CARDBUS:
2707 pbap->type = BUS_PCI;
2708 pbap->save_f = savePciBusState;
2709 pbap->restore_f = restorePciBusState;
2710 pbap->set_f = pciSetBusAccess;
2711 pbap->enable_f = pciBusAccessEnable;
2712 pbap->disable_f = pciBusAccessDisable;
2713 pbap->busdep.pci.acc = pciTag(pbp->brbus,pbp->brdev,pbp->brfunc);
2714 savePciBusState(pbap);
2715 break;
2716 case PCI_SUBCLASS_BRIDGE_ISA:
2717 case PCI_SUBCLASS_BRIDGE_EISA:
2718 case PCI_SUBCLASS_BRIDGE_MC:
2719 pbap->type = BUS_ISA;
2720 pbap->set_f = pciSetBusAccess;
2721 break;
2723 pbap->next = xf86BusAccInfo;
2724 xf86BusAccInfo = pbap;
2725 pbp = pbp->next;
2728 pbap = xf86BusAccInfo;
2730 while (pbap) {
2731 pbap->primary = NULL;
2732 if (pbap->busdep_type == BUS_PCI
2733 && pbap->busdep.pci.primary_bus > -1) {
2734 pbap_tmp = xf86BusAccInfo;
2735 while (pbap_tmp) {
2736 if (pbap_tmp->busdep_type == BUS_PCI &&
2737 pbap_tmp->busdep.pci.bus == pbap->busdep.pci.primary_bus) {
2738 /* Don't create loops */
2739 if (pbap == pbap_tmp)
2740 break;
2741 pbap->primary = pbap_tmp;
2742 break;
2744 pbap_tmp = pbap_tmp->next;
2747 pbap = pbap->next;
2751 void
2752 PciStateEnter(void)
2754 pciAccPtr paccp;
2755 int i = 0;
2757 if (xf86PciAccInfo == NULL)
2758 return;
2760 while ((paccp = xf86PciAccInfo[i]) != NULL) {
2761 i++;
2762 if (!paccp->ctrl)
2763 continue;
2764 savePciState(paccp->arg.tag, &paccp->save);
2765 restorePciState(paccp->arg.tag, &paccp->restore);
2766 paccp->arg.ctrl = paccp->restore.command;
2770 void
2771 PciBusStateEnter(void)
2773 BusAccPtr pbap = xf86BusAccInfo;
2775 while (pbap) {
2776 if (pbap->save_f)
2777 pbap->save_f(pbap);
2778 pbap = pbap->next;
2782 void
2783 PciStateLeave(void)
2785 pciAccPtr paccp;
2786 int i = 0;
2788 if (xf86PciAccInfo == NULL)
2789 return;
2791 while ((paccp = xf86PciAccInfo[i]) != NULL) {
2792 i++;
2793 if (!paccp->ctrl)
2794 continue;
2795 savePciState(paccp->arg.tag, &paccp->restore);
2796 restorePciState(paccp->arg.tag, &paccp->save);
2800 void
2801 PciBusStateLeave(void)
2803 BusAccPtr pbap = xf86BusAccInfo;
2805 while (pbap) {
2806 if (pbap->restore_f)
2807 pbap->restore_f(pbap);
2808 pbap = pbap->next;
2812 void
2813 DisablePciAccess(void)
2815 int i = 0;
2816 pciAccPtr paccp;
2817 if (xf86PciAccInfo == NULL)
2818 return;
2820 while ((paccp = xf86PciAccInfo[i]) != NULL) {
2821 i++;
2822 if (!paccp->ctrl) /* disable devices that are under control initially*/
2823 continue;
2824 pciIo_MemAccessDisable(paccp->io_memAccess.arg);
2828 void
2829 DisablePciBusAccess(void)
2831 BusAccPtr pbap = xf86BusAccInfo;
2833 while (pbap) {
2834 if (pbap->disable_f)
2835 pbap->disable_f(pbap);
2836 if (pbap->primary)
2837 pbap->primary->current = NULL;
2838 pbap = pbap->next;
2843 * Public functions
2846 _X_EXPORT Bool
2847 xf86IsPciDevPresent(int bus, int dev, int func)
2849 int i = 0;
2850 pciConfigPtr pcp;
2852 while ((pcp = xf86PciInfo[i]) != NULL) {
2853 if ((pcp->busnum == bus)
2854 && (pcp->devnum == dev)
2855 && (pcp->funcnum == func))
2856 return TRUE;
2857 i++;
2859 return FALSE;
2863 * If the slot requested is already in use, return -1.
2864 * Otherwise, claim the slot for the screen requesting it.
2867 _X_EXPORT int
2868 xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
2869 int chipset, GDevPtr dev, Bool active)
2871 EntityPtr p = NULL;
2872 pciAccPtr *ppaccp = xf86PciAccInfo;
2873 BusAccPtr pbap = xf86BusAccInfo;
2875 int num;
2877 if (xf86CheckPciSlot(bus, device, func)) {
2878 num = xf86AllocateEntity();
2879 p = xf86Entities[num];
2880 p->driver = drvp;
2881 p->chipset = chipset;
2882 p->busType = BUS_PCI;
2883 p->pciBusId.bus = bus;
2884 p->pciBusId.device = device;
2885 p->pciBusId.func = func;
2886 p->active = active;
2887 p->inUse = FALSE;
2888 if (dev)
2889 xf86AddDevToEntity(num, dev);
2890 /* Here we initialize the access structure */
2891 p->access = xnfcalloc(1,sizeof(EntityAccessRec));
2892 while (ppaccp && *ppaccp) {
2893 if ((*ppaccp)->busnum == bus
2894 && (*ppaccp)->devnum == device
2895 && (*ppaccp)->funcnum == func) {
2896 p->access->fallback = &(*ppaccp)->io_memAccess;
2897 p->access->pAccess = &(*ppaccp)->io_memAccess;
2898 (*ppaccp)->ctrl = TRUE; /* mark control if not already */
2899 break;
2901 ppaccp++;
2903 if (!ppaccp || !*ppaccp) {
2904 p->access->fallback = &AccessNULL;
2905 p->access->pAccess = &AccessNULL;
2908 p->busAcc = NULL;
2909 while (pbap) {
2910 if (pbap->type == BUS_PCI && pbap->busdep.pci.bus == bus)
2911 p->busAcc = pbap;
2912 pbap = pbap->next;
2914 fixPciSizeInfo(num);
2916 /* in case bios is enabled disable it */
2917 disablePciBios(pciTag(bus,device,func));
2918 pciSlotClaimed = TRUE;
2920 if (active) {
2921 /* Map in this domain's I/O space */
2922 p->domainIO = xf86MapDomainIO(-1, VIDMEM_MMIO,
2923 pciTag(bus, device, func), 0, 1);
2926 return num;
2927 } else
2928 return -1;
2932 * Get xf86PciVideoInfo for a driver.
2934 _X_EXPORT pciVideoPtr *
2935 xf86GetPciVideoInfo(void)
2937 return xf86PciVideoInfo;
2940 /* --- Used by ATI driver, but also more generally useful */
2943 * Get the full xf86scanpci data.
2945 _X_EXPORT pciConfigPtr *
2946 xf86GetPciConfigInfo(void)
2948 return xf86PciInfo;
2952 * Enable a device and route VGA to it. This is intended for a driver's
2953 * Probe(), before creating EntityRec's. Only one device can be thus enabled
2954 * at any one time, and should be disabled when the driver is done with it.
2956 * The following special calls are also available:
2958 * pvp == NULL && rt == NONE disable previously enabled device
2959 * pvp != NULL && rt == NONE ensure device is disabled
2960 * pvp == NULL && rt != NONE disable >all< subsequent calls to this function
2961 * (done from xf86PostProbe())
2962 * The last combination has been removed! To do this cleanly we have
2963 * to implement stages and need to test at each stage dependent function
2964 * if it is allowed to execute.
2966 * The device represented by pvp may not have been previously claimed.
2968 _X_EXPORT void
2969 xf86SetPciVideo(pciVideoPtr pvp, resType rt)
2971 static BusAccPtr pbap = NULL;
2972 static xf86AccessPtr pAcc = NULL;
2973 static Bool DoneProbes = FALSE;
2974 pciAccPtr pcaccp;
2975 int i;
2977 if (DoneProbes)
2978 return;
2980 /* Disable previous access */
2981 if (pAcc) {
2982 if (pAcc->AccessDisable)
2983 (*pAcc->AccessDisable)(pAcc->arg);
2984 pAcc = NULL;
2986 if (pbap) {
2987 while (pbap->primary) {
2988 if (pbap->disable_f)
2989 (*pbap->disable_f)(pbap);
2990 pbap->primary->current = NULL;
2991 pbap = pbap->primary;
2993 pbap = NULL;
2996 /* Check for xf86PostProbe's magic combo */
2997 if (!pvp) {
2998 if (rt != NONE)
2999 DoneProbes = TRUE;
3000 return;
3003 /* Validate device */
3004 if (!xf86PciVideoInfo || !xf86PciAccInfo || !xf86BusAccInfo)
3005 return;
3007 for (i = 0; pvp != xf86PciVideoInfo[i]; i++)
3008 if (!xf86PciVideoInfo[i])
3009 return;
3011 /* Ignore request for claimed adapters */
3012 if (!xf86CheckPciSlot(pvp->bus, pvp->device, pvp->func))
3013 return;
3015 /* Find pciAccRec structure */
3016 for (i = 0; ; i++) {
3017 if (!(pcaccp = xf86PciAccInfo[i]))
3018 return;
3019 if ((pvp->bus == pcaccp->busnum) &&
3020 (pvp->device == pcaccp->devnum) &&
3021 (pvp->func == pcaccp->funcnum))
3022 break;
3025 if (rt == NONE) {
3026 /* This is a call to ensure the adapter is disabled */
3027 if (pcaccp->io_memAccess.AccessDisable)
3028 (*pcaccp->io_memAccess.AccessDisable)(pcaccp->io_memAccess.arg);
3029 return;
3032 /* Find BusAccRec structure */
3033 for (pbap = xf86BusAccInfo; ; pbap = pbap->next) {
3034 if (!pbap)
3035 return;
3036 if (pvp->bus == pbap->busdep.pci.bus)
3037 break;
3040 /* Route VGA */
3041 if (pbap->set_f)
3042 (*pbap->set_f)(pbap);
3044 /* Enable device */
3045 switch (rt) {
3046 case IO:
3047 pAcc = &pcaccp->ioAccess;
3048 break;
3049 case MEM_IO:
3050 pAcc = &pcaccp->io_memAccess;
3051 break;
3052 case MEM:
3053 pAcc = &pcaccp->memAccess;
3054 break;
3055 default: /* no compiler noise */
3056 break;
3059 if (pAcc && pAcc->AccessEnable)
3060 (*pAcc->AccessEnable)(pAcc->arg);
3064 * Parse a BUS ID string, and return the PCI bus parameters if it was
3065 * in the correct format for a PCI bus id.
3068 _X_EXPORT Bool
3069 xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
3072 * The format is assumed to be "bus[@domain]:device[:func]", where domain,
3073 * bus, device and func are decimal integers. domain and func may be
3074 * omitted and assumed to be zero, although doing this isn't encouraged.
3077 char *p, *s, *d;
3078 const char *id;
3079 int i;
3081 if (StringToBusType(busID, &id) != BUS_PCI)
3082 return FALSE;
3084 s = xstrdup(id);
3085 p = strtok(s, ":");
3086 if (p == NULL || *p == 0) {
3087 xfree(s);
3088 return FALSE;
3090 d = strpbrk(p, "@");
3091 if (d != NULL) {
3092 *(d++) = 0;
3093 for (i = 0; d[i] != 0; i++) {
3094 if (!isdigit(d[i])) {
3095 xfree(s);
3096 return FALSE;
3100 for (i = 0; p[i] != 0; i++) {
3101 if (!isdigit(p[i])) {
3102 xfree(s);
3103 return FALSE;
3106 *bus = atoi(p);
3107 if (d != NULL && *d != 0)
3108 *bus += atoi(d) << 8;
3109 p = strtok(NULL, ":");
3110 if (p == NULL || *p == 0) {
3111 xfree(s);
3112 return FALSE;
3114 for (i = 0; p[i] != 0; i++) {
3115 if (!isdigit(p[i])) {
3116 xfree(s);
3117 return FALSE;
3120 *device = atoi(p);
3121 *func = 0;
3122 p = strtok(NULL, ":");
3123 if (p == NULL || *p == 0) {
3124 xfree(s);
3125 return TRUE;
3127 for (i = 0; p[i] != 0; i++) {
3128 if (!isdigit(p[i])) {
3129 xfree(s);
3130 return FALSE;
3133 *func = atoi(p);
3134 xfree(s);
3135 return TRUE;
3139 * Compare a BUS ID string with a PCI bus id. Return TRUE if they match.
3142 _X_EXPORT Bool
3143 xf86ComparePciBusString(const char *busID, int bus, int device, int func)
3145 int ibus, idevice, ifunc;
3147 if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
3148 return bus == ibus && device == idevice && func == ifunc;
3149 } else {
3150 return FALSE;
3155 * xf86IsPrimaryPci() -- return TRUE if primary device
3156 * is PCI and bus, dev and func numbers match.
3159 _X_EXPORT Bool
3160 xf86IsPrimaryPci(pciVideoPtr pPci)
3162 if (primaryBus.type != BUS_PCI) return FALSE;
3163 return (pPci->bus == primaryBus.id.pci.bus &&
3164 pPci->device == primaryBus.id.pci.device &&
3165 pPci->func == primaryBus.id.pci.func);
3169 * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
3171 _X_EXPORT pciVideoPtr
3172 xf86GetPciInfoForEntity(int entityIndex)
3174 pciVideoPtr *ppPci;
3175 EntityPtr p;
3177 if (entityIndex >= xf86NumEntities)
3178 return NULL;
3180 p = xf86Entities[entityIndex];
3181 if (p->busType != BUS_PCI)
3182 return NULL;
3184 for (ppPci = xf86PciVideoInfo; *ppPci != NULL; ppPci++) {
3185 if (p->pciBusId.bus == (*ppPci)->bus &&
3186 p->pciBusId.device == (*ppPci)->device &&
3187 p->pciBusId.func == (*ppPci)->func)
3188 return (*ppPci);
3190 return NULL;
3193 _X_EXPORT int
3194 xf86GetPciEntity(int bus, int dev, int func)
3196 int i;
3198 for (i = 0; i < xf86NumEntities; i++) {
3199 EntityPtr p = xf86Entities[i];
3200 if (p->busType != BUS_PCI) continue;
3202 if (p->pciBusId.bus == bus &&
3203 p->pciBusId.device == dev &&
3204 p->pciBusId.func == func)
3205 return i;
3207 return -1;
3211 * xf86CheckPciMemBase() checks that the memory base value matches one of the
3212 * PCI base address register values for the given PCI device.
3214 _X_EXPORT Bool
3215 xf86CheckPciMemBase(pciVideoPtr pPci, memType base)
3217 int i;
3219 for (i = 0; i < 6; i++)
3220 if (base == pPci->memBase[i])
3221 return TRUE;
3222 return FALSE;
3226 * Check if the slot requested is free. If it is already in use, return FALSE.
3229 _X_EXPORT Bool
3230 xf86CheckPciSlot(int bus, int device, int func)
3232 int i;
3233 EntityPtr p;
3235 for (i = 0; i < xf86NumEntities; i++) {
3236 p = xf86Entities[i];
3237 /* Check if this PCI slot is taken */
3238 if (p->busType == BUS_PCI && p->pciBusId.bus == bus &&
3239 p->pciBusId.device == device && p->pciBusId.func == func)
3240 return FALSE;
3243 return TRUE;
3248 * xf86FindPciVendorDevice() xf86FindPciClass(): These functions
3249 * are meant to be used by the pci bios emulation. Some bioses
3250 * need to see if there are _other_ chips of the same type around
3251 * so by setting pvp_exclude one pci device can be explicitely
3252 * _excluded if required.
3254 _X_EXPORT pciVideoPtr
3255 xf86FindPciDeviceVendor(CARD16 vendorID, CARD16 deviceID,
3256 char n, pciVideoPtr pvp_exclude)
3258 pciVideoPtr pvp, *ppvp;
3259 n++;
3261 for (ppvp = xf86PciVideoInfo, pvp =*ppvp; pvp ; pvp = *(++ppvp)) {
3262 if (pvp == pvp_exclude) continue;
3263 if ((pvp->vendor == vendorID) && (pvp->chipType == deviceID)) {
3264 if (!(--n)) break;
3267 return pvp;
3270 _X_EXPORT pciVideoPtr
3271 xf86FindPciClass(CARD8 intf, CARD8 subClass, CARD16 class,
3272 char n, pciVideoPtr pvp_exclude)
3274 pciVideoPtr pvp, *ppvp;
3275 n++;
3277 for (ppvp = xf86PciVideoInfo, pvp =*ppvp; pvp ; pvp = *(++ppvp)) {
3278 if (pvp == pvp_exclude) continue;
3279 if ((pvp->interface == intf) && (pvp->subclass == subClass)
3280 && (pvp->class == class)) {
3281 if (!(--n)) break;
3284 return pvp;
3288 * This attempts to detect a multi-device card and sets up a list
3289 * of pci tags of the devices of this card. On some of these
3290 * cards the BIOS is not visible from all chipsets. We therefore
3291 * need to use the BIOS from a chipset where it is visible.
3292 * We do the following heuristics:
3293 * If we detect only identical pci devices on a bus we assume it's
3294 * a multi-device card. This assumption isn't true always, however.
3295 * One might just use identical cards on a bus. We therefore don't
3296 * detect this situation when we set up the PCI video info. Instead
3297 * we wait until an attempt to read the BIOS fails.
3300 pciTestMultiDeviceCard(int bus, int dev, int func, PCITAG** pTag)
3302 pciConfigPtr *ppcrp = xf86PciInfo;
3303 pciConfigPtr pcrp = NULL;
3304 int i,j;
3305 Bool multicard = FALSE;
3306 Bool multifunc = FALSE;
3307 char str[256];
3308 char *str1;
3310 str1 = str;
3311 if (!pTag)
3312 return 0;
3314 *pTag = NULL;
3316 for (i=0; i < 8; i++) {
3317 j = 0;
3319 while (ppcrp[j]) {
3320 if (ppcrp[j]->busnum == bus && ppcrp[j]->funcnum == i) {
3321 pcrp = ppcrp[j];
3322 break;
3324 j++;
3327 if (!pcrp) return 0;
3330 * we check all functions here: since multifunc devices need
3331 * to implement func 0 we catch all devices on the bus when
3332 * i = 0
3334 if (pcrp->pci_header_type &0x80)
3335 multifunc = TRUE;
3337 j = 0;
3339 while (ppcrp[j]) {
3340 if (ppcrp[j]->busnum == bus && ppcrp[j]->funcnum == i
3341 && ppcrp[j]->devnum != pcrp->devnum) {
3342 /* don't test subsys ID here. It might be set by POST
3343 - however some cards might not have been POSTed */
3344 if (ppcrp[j]->pci_device_vendor != pcrp->pci_device_vendor
3345 || ppcrp[j]->pci_header_type != pcrp->pci_header_type )
3346 return 0;
3347 else
3348 multicard = TRUE;
3350 j++;
3352 if (!multifunc)
3353 break;
3356 if (!multicard)
3357 return 0;
3359 j = 0;
3360 i = 0;
3361 while (ppcrp[i]) {
3362 if (ppcrp[i]->busnum == bus && ppcrp[i]->funcnum == func) {
3363 str1 += sprintf(str1,"[%x:%x:%x]",ppcrp[i]->busnum,
3364 ppcrp[i]->devnum,ppcrp[i]->funcnum);
3365 *pTag = xnfrealloc(*pTag,sizeof(PCITAG) * (j + 1));
3366 (*pTag)[j++] = pciTag(ppcrp[i]->busnum,
3367 ppcrp[i]->devnum,ppcrp[i]->funcnum);
3369 i++;
3371 xf86MsgVerb(X_INFO,3,"Multi Device Card detected: %s\n",str);
3372 return j;
3375 static void
3376 pciTagConvertRange2Host(PCITAG tag, resRange *pRange)
3378 if (!(pRange->type & ResBus))
3379 return;
3381 switch(pRange->type & ResPhysMask) {
3382 case ResMem:
3383 switch(pRange->type & ResExtMask) {
3384 case ResBlock:
3385 pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rBegin);
3386 pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rEnd);
3387 break;
3388 case ResSparse:
3389 pRange->rBase = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_BASE,
3390 pRange->rBegin);
3391 pRange->rMask = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_MASK,
3392 pRange->rEnd);
3393 break;
3395 break;
3396 case ResIo:
3397 switch(pRange->type & ResExtMask) {
3398 case ResBlock:
3399 pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rBegin);
3400 pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rEnd);
3401 break;
3402 case ResSparse:
3403 pRange->rBase = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_BASE
3404 , pRange->rBegin);
3405 pRange->rMask = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_MASK
3406 , pRange->rEnd);
3407 break;
3409 break;
3412 /* Set domain number */
3413 pRange->type &= ~(ResDomain | ResBus);
3414 pRange->type |= xf86GetPciDomain(tag) << 24;
3417 static void
3418 pciConvertListToHost(int bus, int dev, int func, resPtr list)
3420 PCITAG tag = pciTag(bus,dev,func);
3421 while (list) {
3422 pciTagConvertRange2Host(tag, &list->val);
3423 list = list->next;
3427 static void
3428 updateAccessInfoStatusControlInfo(PCITAG tag, CARD32 ctrl)
3430 int i;
3432 if (!xf86PciAccInfo)
3433 return;
3435 for (i = 0; xf86PciAccInfo[i] != NULL; i++) {
3436 if (xf86PciAccInfo[i]->arg.tag == tag)
3437 xf86PciAccInfo[i]->arg.ctrl = ctrl;
3441 void
3442 pciConvertRange2Host(int entityIndex, resRange *pRange)
3444 PCITAG tag;
3445 pciVideoPtr pvp;
3447 pvp = xf86GetPciInfoForEntity(entityIndex);
3448 if (!pvp) return;
3449 tag = TAG(pvp);
3450 pciTagConvertRange2Host(tag, pRange);