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>
43 #include "xf86Resources.h"
45 /* Bus-specific headers */
46 #include "xf86PciData.h"
51 #define NEED_OS_RAC_PROTOS
52 #include "xf86_OSproc.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 */
63 ScanPciSetupProcPtr xf86SetupPciIds
= NULL
;
64 ScanPciCloseProcPtr xf86ClosePciIds
= NULL
;
65 ScanPciFindByDeviceProcPtr xf86FindPciNamesByDevice
= NULL
;
66 ScanPciFindBySubsysProcPtr xf86FindPciNamesBySubsys
= NULL
;
68 static resPtr pciAvoidRes
= NULL
;
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
95 #define PCINONSYSTEMCLASSES(b,s) PCIALWAYSPRINTCLASSES(b,s)
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);
150 xf86FormatPciBusNumber(int busnum
, char *buffer
)
152 /* 'buffer' should be at least 8 characters long */
154 sprintf(buffer
, "%d", busnum
);
156 sprintf(buffer
, "%d@%d", busnum
& 0x00ff, busnum
>> 8);
160 IsBaseUnassigned(CARD32 base
)
164 if (base
& PCI_MAP_IO
)
165 mask
= ~PCI_MAP_IO_ATTR_MASK
;
167 mask
= ~PCI_MAP_MEMORY_ATTR_MASK
;
170 return (!base
|| (base
== mask
));
174 IsBaseUnassigned64(CARD32 base0
, CARD32 base1
)
176 base0
&= ~PCI_MAP_MEMORY_ATTR_MASK
;
179 return ((!base0
&& !base1
)
180 || ((base0
== ~PCI_MAP_MEMORY_ATTR_MASK
)
181 && (base1
== 0xffffffff)));
185 FindPCIVideoInfo(void)
187 pciConfigPtr pcrp
, *pcrpp
;
191 int DoIsolateDeviceCheck
= 0;
193 if (xf86IsolateDevice
.bus
|| xf86IsolateDevice
.device
|| xf86IsolateDevice
.func
)
194 DoIsolateDeviceCheck
= 1;
195 pcrpp
= xf86PciInfo
= xf86scanpci(0);
199 xf86PciVideoInfo
= NULL
;
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
)) ) {
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).
246 PciBusPtr pBus
= xf86PciBus
;
247 while (pBus
&& j
!= pBus
->secondary
)
249 if (!pBus
|| !(pBus
->brcontrol
& PCI_PCI_BRIDGE_VGA_EN
))
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
) {
260 "More than one primary device found\n");
261 primaryBus
.type
^= (BusType
)(-1);
270 for (j
= 0; j
< 6; j
++) {
271 info
->memBase
[j
] = 0;
273 if (PCINONSYSTEMCLASSES(baseclass
, subclass
)) {
275 pciGetBaseSize(pcrp
->tag
, j
, TRUE
, &info
->validSize
);
276 pcrp
->minBasesize
= info
->validSize
;
278 info
->size
[j
] = pcrp
->basesize
[j
];
279 info
->validSize
= pcrp
->minBasesize
;
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
);
297 if (j
== 5) /* bail out */
300 && IsBaseUnassigned64(base
[j
],base
[j
+1])) {
301 base
[j
] = pciCheckForBrokenBase(pcrp
->tag
, j
);
303 base
[j
] = pciCheckForBrokenBase(pcrp
->tag
, j
);
310 * 64-bit base addresses are checked for and avoided on 32-bit
313 for (j
= 0; j
< 6; ++j
) {
314 CARD32 bar
= (&pcrp
->pci_base0
)[j
];
317 if (bar
& PCI_MAP_IO
) {
318 info
->ioBase
[j
] = (memType
)PCIGETIO(bar
);
319 info
->type
[j
] = bar
& PCI_MAP_IO_ATTR_MASK
;
321 info
->type
[j
] = bar
& PCI_MAP_MEMORY_ATTR_MASK
;
322 info
->memBase
[j
] = (memType
)PCIGETMEMORY(bar
);
323 if (PCI_MAP_IS64BITMEM(bar
)) {
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;
331 CARD32 bar_hi
= PCIGETMEMORY64HIGH((&pcrp
->pci_base0
)[j
]);
332 #if defined(LONG64) || defined(WORD64)
333 /* 64 bit architecture */
335 (memType
)bar_hi
<< 32;
338 info
->memBase
[j
] = 0;
340 ++j
; /* Step over the next BAR */
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
) &&
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
;
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
= " ";
379 Bool memdone
= FALSE
, iodone
= FALSE
;
382 info
= xf86PciVideoInfo
[k
];
383 xf86FormatPciBusNumber(info
->bus
, busnum
);
384 xf86FindPciNamesByDevice(info
->vendor
, info
->chipType
,
386 &vendorname
, &chipname
, NULL
, NULL
);
387 if ((!vendorname
|| !chipname
) &&
388 !PCIALWAYSPRINTCLASSES(info
->class, info
->subclass
))
390 if (xf86IsPrimaryPci(info
))
393 xf86Msg(X_PROBED
, "PCI:%s(%s:%d:%d) ", prim
, busnum
, info
->device
,
396 xf86ErrorF("%s ", vendorname
);
398 xf86ErrorF("unknown vendor (0x%04x) ", info
->vendor
);
400 xf86ErrorF("%s ", chipname
);
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
]))) {
408 xf86ErrorF(", Mem @ ");
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
]))) {
419 xf86ErrorF(", I/O @ ");
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
);
434 * fixPciSizeInfo() -- fix pci size info by testing it destructively
435 * (if not already done), fix pciVideoInfo and entry in the resource
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.
452 fixPciSizeInfo(int entityIndex
)
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
++) {
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;
475 else if (pvp
->ioBase
[j
])
477 if (((pAcc
->res_type
& (ResPhysMask
| 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;
485 pvp
->size
[j
] = pciGetBaseSize(tag
, j
, TRUE
, &pvp
->validSize
);
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
;
497 if (((pAcc
->res_type
& (ResPhysMask
| ResBlock
)) ==
499 && (pAcc
->block_begin
== B2M(TAG(pvp
),pvp
->biosBase
))
500 && (pAcc
->block_end
== B2M(TAG(pvp
),pvp
->biosBase
501 + SIZE(pvp
->biosSize
)))) break;
504 pvp
->biosSize
= pciGetBaseSize(tag
, 6, TRUE
, &pvp
->validSize
);
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
519 pciIoAccessEnable(void* arg
)
522 ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG
*)arg
);
524 pArg
->ctrl
|= SETBITS
| PCI_CMD_MASTER_ENABLE
;
525 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
529 pciIoAccessDisable(void* arg
)
532 ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG
*)arg
);
534 pArg
->ctrl
&= ~SETBITS
;
535 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
539 #define SETBITS (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)
541 pciIo_MemAccessEnable(void* arg
)
544 ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG
*)arg
);
546 pArg
->ctrl
|= SETBITS
| PCI_CMD_MASTER_ENABLE
;
547 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
551 pciIo_MemAccessDisable(void* arg
)
554 ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG
*)arg
);
556 pArg
->ctrl
&= ~SETBITS
;
557 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
561 #define SETBITS (PCI_CMD_MEM_ENABLE)
563 pciMemAccessEnable(void* arg
)
566 ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG
*)arg
);
568 pArg
->ctrl
|= SETBITS
| PCI_CMD_MASTER_ENABLE
;
569 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
573 pciMemAccessDisable(void* arg
)
576 ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG
*)arg
);
578 pArg
->ctrl
&= ~SETBITS
;
579 pciWriteLong(pArg
->tag
, PCI_CMD_STAT_REG
, pArg
->ctrl
);
585 /* move to OS layer */
586 #define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN)
588 pciBusAccessEnable(BusAccPtr ptr
)
590 PCITAG tag
= ptr
->busdep
.pci
.acc
;
594 ErrorF("pciBusAccessEnable: bus=%d\n", ptr
->busdep
.pci
.bus
);
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 */
606 pciBusAccessDisable(BusAccPtr ptr
)
608 PCITAG tag
= ptr
->busdep
.pci
.acc
;
612 ErrorF("pciBusAccessDisable: bus=%d\n", ptr
->busdep
.pci
.bus
);
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
);
622 /* move to OS layer */
624 pciDrvBusAccessEnable(BusAccPtr ptr
)
626 int bus
= ptr
->busdep
.pci
.bus
;
629 ErrorF("pciDrvBusAccessEnable: bus=%d\n", bus
);
631 (*pciBusInfo
[bus
]->funcs
->pciControlBridge
)(bus
,
632 PCI_PCI_BRIDGE_VGA_EN
,
633 PCI_PCI_BRIDGE_VGA_EN
);
636 /* move to OS layer */
638 pciDrvBusAccessDisable(BusAccPtr ptr
)
640 int bus
= ptr
->busdep
.pci
.bus
;
643 ErrorF("pciDrvBusAccessDisable: bus=%d\n", bus
);
645 (*pciBusInfo
[bus
]->funcs
->pciControlBridge
)(bus
,
646 PCI_PCI_BRIDGE_VGA_EN
, 0);
651 pciSetBusAccess(BusAccPtr ptr
)
654 ErrorF("pciSetBusAccess: route VGA to bus %d\n", ptr
->busdep
.pci
.bus
);
657 if (!ptr
->primary
&& !ptr
->current
)
660 if (ptr
->current
&& ptr
->current
->disable_f
)
661 (*ptr
->current
->disable_f
)(ptr
->current
);
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
);
670 (*ptr
->enable_f
)(ptr
);
671 ptr
->primary
->current
= ptr
;
677 /* move to OS layer */
679 savePciState(PCITAG tag
, pciSavePtr ptr
)
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 */
691 restorePciState(PCITAG tag
, pciSavePtr ptr
)
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
);
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 */
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)
722 restorePciBusState(BusAccPtr ptr
)
724 PCITAG tag
= ptr
->busdep
.pci
.acc
;
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
);
737 /* move to OS layer */
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 */
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
);
763 disablePciBios(PCITAG tag
)
765 pciSetBitsLong(tag
, PCI_CMD_BIOS_REG
, PCI_CMD_BIOS_ENABLE
, 0);
770 correctPciSize(memType base
, memType oldsize
, memType newsize
,
773 pciConfigPtr pcrp
, *pcrpp
;
774 pciVideoPtr pvp
, *pvpp
;
777 int old_bits
= 0, new_bits
= 0;
779 if (oldsize
+ 1) while (oldsize
& 1) {
783 if (newsize
+ 1) while (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)
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
)
810 && (B2M(pcrp
->tag
,PCIGETMEMORY(basep
[i
])) == base
))
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 */
841 removeOverlapsWithBridges(int busIndex
, resPtr target
)
844 resPtr tmp
,bridgeRes
= NULL
;
850 if (!ResCanOverlap(&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
,
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
);
881 xf86GetPciRes(resPtr
*activeRes
, resPtr
*inactiveRes
)
883 pciConfigPtr pcrp
, *pcrpp
;
884 pciVideoPtr pvp
, *pvpp
;
896 if (!activeRes
|| !inactiveRes
|| !xf86PciInfo
)
899 if (xf86PciVideoInfo
)
900 for (pvpp
= xf86PciVideoInfo
, pvp
= *pvpp
; pvp
; pvp
= *(++pvpp
)) {
903 if (PCINONSYSTEMCLASSES(pvp
->class, pvp
->subclass
))
908 if (((pciConfigPtr
)pvp
->thisCard
)->pci_command
909 & (PCI_CMD_IO_ENABLE
| PCI_CMD_MEM_ENABLE
))
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!
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
)) {
946 const CARD8 baseclass
= pcrp
->pci_base_class
;
947 const CARD8 subclass
= pcrp
->pci_sub_class
;
950 if (PCIINFOCLASSES(baseclass
, subclass
))
953 /* Only process devices with type 0 headers */
954 if ((pcrp
->pci_header_type
& 0x7f) != 0)
957 if (!pcrp
->minBasesize
)
958 resMisc
= ResEstimated
;
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
++) {
974 if (PCI_MAP_IS_IO(basep
[i
])) {
975 if (pcrp
->pci_command
& PCI_CMD_IO_ENABLE
)
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
)
986 P_M_RANGE(range
, pcrp
->tag
, PCIGETMEMORY(basep
[i
]),
987 pcrp
->basesize
[i
], ResExcMemBlock
| resMisc
)
990 #if defined(LONG64) || defined(WORD64)
991 P_M_RANGE(range
,pcrp
->tag
,PCIGETMEMORY64(basep
[i
- 1]),
992 pcrp
->basesize
[i
- 1], ResExcMemBlock
| resMisc
)
996 P_M_RANGE(range
, pcrp
->tag
, PCIGETMEMORY(basep
[i
- 1]),
997 pcrp
->basesize
[i
- 1], ResExcMemBlock
| resMisc
)
999 if (pcrp
->pci_command
& PCI_CMD_MEM_ENABLE
)
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
);
1018 tmp
= xf86AddResToList(NULL
, &range
, -1);
1019 removeOverlapsWithBridges(pcrp
->busnum
, tmp
);
1020 *activeRes
= xf86JoinResLists(tmp
, *activeRes
);
1026 xf86MsgVerb(X_INFO
, 3, "Active PCI resource ranges:\n");
1027 xf86PrintResList(3, *activeRes
);
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.
1043 /* Check for overlaps */
1044 for (pRes
= *activeRes
; pRes
; pRes
= pRes
->next
) {
1045 if (ResCanOverlap(&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
,
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
) ?
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
);
1071 /* Check for overlaps */
1072 for (pRes
= *inactiveRes
; pRes
; pRes
= pRes
->next
) {
1073 if (ResCanOverlap(&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
,
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
) ?
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
);
1102 ResourceBrokerInitPci(resPtr
*osRes
)
1104 resPtr activeRes
, inactiveRes
;
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
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
1138 fixPciResource(int prt
, memType alignment
, pciVideoPtr pvp
, unsigned long type
)
1143 unsigned char p_type
;
1144 resPtr AccTmp
= NULL
;
1145 resPtr orgAcc
= NULL
;
1146 resPtr
*pAcc
= &AccTmp
;
1147 resPtr avoid
= NULL
;
1149 resPtr resSize
= NULL
;
1150 resPtr w_tmp
, w
= NULL
, w_2nd
= NULL
;
1152 PciBusPtr pbp
= xf86PciBus
;
1156 if (!pvp
) return FALSE
;
1157 tag
= pciTag(pvp
->bus
,pvp
->device
,pvp
->func
);
1158 pcp
= pvp
->thisCard
;
1161 if (!type
) type
= ResShared
;
1163 if (pvp
->memBase
[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
]){
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) {
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 */
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
);
1201 if (pbp
->secondary
== pvp
->bus
) {
1202 if ((type
& ResPhysMask
) == ResMem
) {
1203 if (((p_type
& PCI_MAP_MEMORY_CACHABLE
)
1205 || (res_n
== 0xff)/* bios should also be prefetchable */
1208 if (pbp
->preferred_pmem
)
1209 w
= xf86FindIntersectOfLists(pbp
->preferred_pmem
,
1212 w
= xf86FindIntersectOfLists(pbp
->pmem
,ResRange
);
1214 if (pbp
->preferred_mem
)
1215 w_2nd
= xf86FindIntersectOfLists(pbp
->preferred_mem
,
1218 w_2nd
= xf86FindIntersectOfLists(pbp
->mem
,
1221 if (pbp
->preferred_mem
)
1222 w
= xf86FindIntersectOfLists(pbp
->preferred_mem
,
1225 w
= xf86FindIntersectOfLists(pbp
->mem
,ResRange
);
1228 if (pbp
->preferred_io
)
1229 w
= xf86FindIntersectOfLists(pbp
->preferred_io
,ResRange
);
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
);
1240 tmp
= xf86DupResList(pbp
->preferred_io
);
1241 avoid
= xf86JoinResLists(avoid
, tmp
);
1247 /* convert bus based entries in avoid list to host base */
1248 pciConvertListToHost(pvp
->bus
,pvp
->device
,pvp
->func
, avoid
);
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
);
1259 w
= xf86FindIntersectOfLists(w
,resSize
);
1260 xf86FreeResList(w_tmp
);
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
);
1272 alignment
= (1 << (*p_size
)) - 1;
1274 /* Access list holds bios resources -- remove this one */
1276 AccTmp
= xf86DupResList(Acc
);
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
;
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
))))) {
1299 ErrorF("nothing to fix\n");
1301 xf86FreeResList(AccTmp
);
1303 xf86FreeResList(w_2nd
);
1304 xf86FreeResList(avoid
);
1308 ErrorF("removing old resource\n");
1313 orgAcc
= xf86DupResList(Acc
);
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
),
1322 ErrorF("removing old resource\n");
1325 *pAcc
= (*pAcc
)->next
;
1327 xf86FreeResList(tmp
);
1330 pAcc
= &((*pAcc
)->next
);
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
);
1340 xf86MsgVerb(X_INFO
, 3, "2nd window:\n");
1341 xf86PrintResList(3, w_2nd
);
1342 xf86ErrorFVerb(3,"avoid:\n");
1343 xf86PrintResList(3,avoid
);
1347 if ((type
& ResTypeMask
) == (w
->res_type
& ResTypeMask
)) {
1349 ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w
->block_begin
,
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
)
1360 xf86FreeResList(w_tmp
);
1361 /* if unsuccessful and memory prefetchable try non-prefetchable */
1362 if (range
.type
== ResEnd
&& w_2nd
) {
1365 if ((type
& ResTypeMask
) == (w_2nd
->res_type
& ResTypeMask
)) {
1367 ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w_2nd
->block_begin
,
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
)
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
);
1388 xf86FreeResList(orgAcc
);
1390 ErrorF("begin: 0x%lx, end: 0x%lx\n",range
.a
,range
.b
);
1394 while (alignment
>> (*p_size
))
1396 (*p_base
) = H2B(tag
,range
.rBegin
,type
);
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");
1402 if (res_n
!= 0xff) {
1403 if ((type
& ResPhysMask
) == ResMem
)
1404 pvp
->memBase
[prt
] = range
.rBegin
;
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]);
1418 ((CARD32
*)(&(pcp
->pci_base0
)))[res_n
+ 1] = 0;
1419 pciWriteLong(tag
, PCI_CMD_BASE_REG
+ (res_n
+ 1) * sizeof(CARD32
),
1424 pvp
->biosBase
= range
.rBegin
;
1425 pcp
->pci_baserom
= (pciReadLong(tag
,PCI_CMD_BIOS_REG
) & 0x01) |
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);
1438 xf86FixPciResource(int entityIndex
, int prt
, memType alignment
,
1441 pciVideoPtr pvp
= xf86GetPciInfoForEntity(entityIndex
);
1442 return fixPciResource(prt
, alignment
, pvp
, type
);
1446 xf86ReallocatePciResources(int entityIndex
, resPtr pRes
)
1448 pciVideoPtr pvp
= xf86GetPciInfoForEntity(entityIndex
);
1449 resPtr pBad
= NULL
,pResTmp
;
1450 unsigned int prt
= 0;
1453 if (!pvp
) return pRes
;
1456 switch (pRes
->res_type
& ResPhysMask
) {
1458 if (pRes
->block_begin
== B2M(TAG(pvp
),pvp
->biosBase
) &&
1459 pRes
->block_end
== B2M(TAG(pvp
),pvp
->biosBase
1460 + SIZE(pvp
->biosSize
)))
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
])))) {
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
]))) {
1481 if (!prt
) return pRes
;
1483 pResTmp
= pRes
->next
;
1484 if (! fixPciResource(prt
, 0, pvp
, pRes
->res_type
)) {
1499 getOwnResources(pciVideoPtr pvp
, resPtr mem
)
1503 /* Make sure we don't conflict with our own mem resources */
1504 for (i
= 0; i
< 6; i
++) {
1505 if (!pvp
->memBase
[i
])
1507 P_M_RANGE(range
,TAG(pvp
),pvp
->memBase
[i
],pvp
->size
[i
],
1509 mem
= xf86AddResToList(mem
,&range
,-1);
1515 getPciRangesForMapping(pciVideoPtr pvp
, resPtr
*map
, resPtr
*avoid
)
1520 *avoid
= xf86DupResList(pciAvoidRes
);
1524 if (pbp
->secondary
== pvp
->bus
) {
1525 if (pbp
->preferred_pmem
)
1526 tmp
= xf86DupResList(pbp
->preferred_pmem
);
1528 tmp
= xf86DupResList(pbp
->pmem
);
1529 *map
= xf86JoinResLists(*map
,tmp
);
1530 if (pbp
->preferred_mem
)
1531 tmp
= xf86DupResList(pbp
->preferred_mem
);
1533 tmp
= xf86DupResList(pbp
->mem
);
1534 *map
= xf86JoinResLists(*map
,tmp
);
1537 tmp
->block_end
= min(tmp
->block_end
,PCI_MEM32_LENGTH_MAX
);
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
);
1554 pciConvertListToHost(pvp
->bus
,pvp
->device
,pvp
->func
, *avoid
);
1555 pciConvertListToHost(pvp
->bus
,pvp
->device
,pvp
->func
, *map
);
1559 findPciRange(PCITAG tag
, resPtr m
, resPtr avoid
, CARD32 size
)
1562 CARD32 alignment
= (1 << size
) - 1;
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
),
1570 if (range
.type
!= ResEnd
) {
1571 return M2B(tag
, range
.rBase
);
1579 getPciVideoPtr(PCITAG tag
)
1583 pciVideoPtr pvp
= NULL
;
1584 if (!xf86PciVideoInfo
) return 0;
1586 while ((pvp
= xf86PciVideoInfo
[n
++])) {
1587 if (pciTag(pvp
->bus
,pvp
->device
,pvp
->func
) == tag
)
1594 getValidBIOSBase(PCITAG tag
, int num
)
1596 pciVideoPtr pvp
= NULL
;
1600 resPtr avoid
= NULL
, m
= NULL
;
1603 pvp
= getPciVideoPtr(tag
);
1607 biosSize
= pvp
->biosSize
;
1612 switch ((romBaseSource
)num
) {
1613 case ROM_BASE_PRESET
:
1614 return 0; /* This should not happen */
1616 /* In some cases the BIOS base register contains the size mask */
1617 if ((memType
)(-1 << biosSize
) == PCIGETROM(pvp
->biosBase
))
1619 mem
= getOwnResources(pvp
,mem
);
1620 P_M_RANGE(range
, tag
, pvp
->biosBase
,biosSize
,ResExcMemBlock
);
1621 ret
= pvp
->biosBase
;
1629 if (!pvp
->memBase
[num
] || (pvp
->size
[num
] < biosSize
))
1631 P_M_RANGE(range
, tag
,pvp
->memBase
[num
],biosSize
,
1633 ret
= pvp
->memBase
[num
];
1639 return 0; /* This should not happen */
1642 /* Now find the ranges for validation */
1643 getPciRangesForMapping(pvp
,&m
,&avoid
);
1646 /* Return a possible window */
1647 ret
= findPciRange(tag
,m
,avoid
,biosSize
);
1649 #if !defined(__ia64__) /* on ia64, trust the kernel, don't look for overlaps */
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
)))
1659 xf86FreeResList(avoid
);
1665 getEmptyPciRange(PCITAG tag
, int base_reg
)
1667 resPtr avoid
= NULL
, m
= NULL
;
1670 pciVideoPtr pvp
= getPciVideoPtr(tag
);
1672 getPciRangesForMapping(pvp
,&m
,&avoid
);
1673 ret
= findPciRange(tag
,m
,avoid
,pvp
->size
[base_reg
]);
1674 xf86FreeResList(avoid
);
1681 * xf86Bus.c interface
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");
1703 static void alignBridgeRanges(PciBusPtr PciBusBase
, PciBusPtr primary
);
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
) ?
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
);
1739 xf86GetPciBridgeInfo(void)
1741 const pciConfigPtr
*pcrpp
;
1743 pciBusInfo_t
*pBusInfo
;
1745 PciBusPtr PciBus
, PciBusBase
= NULL
;
1746 PciBusPtr
*pnPciBus
= &PciBusBase
;
1749 int primary
, secondary
, subordinate
;
1750 memType base
, limit
;
1752 resPtr pciBusAccWindows
= xf86PciBusAccWindowsFromOS();
1754 if (xf86PciInfo
== 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
);
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
);
1794 if (pBusInfo
&& pBusInfo
->funcs
->pciGetBridgeBuses
)
1795 (*pBusInfo
->funcs
->pciGetBridgeBuses
)(secondary
,
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
);
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
;
1828 PciBus
->interface
= pcrp
->pci_prog_if
;
1831 if (pBusInfo
&& pBusInfo
->funcs
->pciControlBridge
)
1833 (*pBusInfo
->funcs
->pciControlBridge
)(secondary
, 0, 0);
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
);
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
,
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
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;
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
,
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
);
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
);
1942 if (pBusInfo
&& pBusInfo
->funcs
->pciGetBridgeBuses
)
1943 (*pBusInfo
->funcs
->pciGetBridgeBuses
)(secondary
,
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
);
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
)
1973 (*pBusInfo
->funcs
->pciControlBridge
)(secondary
, 0, 0);
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
);
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)) &&
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
,
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
,
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)) &&
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
,
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
,
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
,
2060 PciBus
->preferred_mem
=
2061 xf86AddResToList(PciBus
->preferred_mem
,
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
,
2076 PciBus
->preferred_mem
=
2077 xf86AddResToList(PciBus
->preferred_mem
,
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
;
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
)
2106 /* Find "secondary" bus segment */
2107 while (pBusInfo
!= pciBusInfo
[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
);
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
)
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
)
2142 (*pBusInfo
->funcs
->pciControlBridge
)(secondary
, 0, 0);
2144 PciBus
->brcontrol
= PCI_PCI_BRIDGE_VGA_EN
;
2146 if (pBusInfo
&& pBusInfo
->funcs
->pciGetBridgeResources
) {
2147 (*pBusInfo
->funcs
->pciGetBridgeResources
)
2149 (pointer
*)&PciBus
->preferred_io
,
2150 (pointer
*)&PciBus
->preferred_mem
,
2151 (pointer
*)&PciBus
->preferred_pmem
);
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
));
2171 for (i
= 0; i
<= MaxBus
; i
++) { /* find PCI buses not attached to bridge */
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
))
2189 PciBusFound
= PciBus
;
2192 PciBusFound
->secondary
= i
;
2193 else { /* if nothing found it may not be visible: create new */
2194 /* Find a device on this bus */
2196 for (pcrpp
= xf86PciInfo
; (pcrp
= *pcrpp
); pcrpp
++) {
2197 if (pcrp
->busnum
== i
) {
2198 domain
= xf86GetPciDomain(pcrp
->tag
);
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");
2232 xf86MsgVerb(X_INFO
, 3, "PCI-to-PCI bridge:\n");
2234 case PCI_SUBCLASS_BRIDGE_CARDBUS
:
2235 xf86MsgVerb(X_INFO
, 3, "PCI-to-CardBus bridge:\n");
2237 case PCI_SUBCLASS_BRIDGE_HOST
:
2238 xf86MsgVerb(X_INFO
, 3, "Host-to-PCI bridge:\n");
2240 case PCI_SUBCLASS_BRIDGE_ISA
:
2241 xf86MsgVerb(X_INFO
, 3, "PCI-to-ISA bridge:\n");
2243 case PCI_SUBCLASS_BRIDGE_EISA
:
2244 xf86MsgVerb(X_INFO
, 3, "PCI-to-EISA bridge:\n");
2246 case PCI_SUBCLASS_BRIDGE_MC
:
2247 xf86MsgVerb(X_INFO
, 3, "PCI-to-MCA bridge:\n");
2252 printBridgeInfo(PciBus
);
2254 xf86FreeResList(pciBusAccWindows
);
2259 alignBridgeRanges(PciBusPtr PciBusBase
, PciBusPtr primary
)
2263 for (PciBus
= PciBusBase
; PciBus
; PciBus
= PciBus
->next
) {
2264 if ((PciBus
!= primary
) && (PciBus
->primary
!= -1)
2265 && (PciBus
->primary
== primary
->secondary
)) {
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
)
2287 case PCI_SUBCLASS_BRIDGE_ISA
:
2288 case PCI_SUBCLASS_BRIDGE_EISA
:
2289 case PCI_SUBCLASS_BRIDGE_MC
:
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
;
2301 alignBridgeRanges(PciBusBase
, PciBus
);
2309 pciVideoPtr pvp
, pvp1
;
2311 pciConfigPtr pcrp
, *pcrpp
;
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 */
2338 while ((pvp
= xf86PciVideoInfo
[m
++])) {
2339 /* is it a PCINONSYSTEMCLASS? */
2340 if (PCINONSYSTEMCLASSES(pvp
->class, pvp
->subclass
))
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
)
2347 if (p
->pciBusId
.bus
== pvp
->bus
2348 && p
->pciBusId
.device
== pvp
->device
2349 && p
->pciBusId
.func
== pvp
->func
)
2352 if (i
!= xf86NumEntities
) /* found an Entity for this one */
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
))
2371 if ((pcrp
->pci_header_type
& 0x7f) ||
2372 !(pcrp
->pci_command
& (PCI_CMD_IO_ENABLE
| PCI_CMD_MEM_ENABLE
)))
2375 basep
= &pcrp
->pci_base0
;
2376 for (i
= 0; i
< 6; i
++) {
2378 if (PCI_MAP_IS_IO(basep
[i
])) {
2379 if (!(pcrp
->pci_command
& PCI_CMD_IO_ENABLE
))
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
))
2386 P_M_RANGE(range
, pcrp
->tag
, PCIGETMEMORY(basep
[i
]),
2387 pcrp
->basesize
[i
], ResExcMemBlock
)
2390 if (!(pcrp
->pci_command
& PCI_CMD_MEM_ENABLE
))
2392 #if defined(LONG64) || defined(WORD64)
2393 P_M_RANGE(range
, pcrp
->tag
, PCIGETMEMORY64(basep
[i
-1]),
2394 pcrp
->basesize
[i
-1], ResExcMemBlock
)
2398 P_M_RANGE(range
, pcrp
->tag
, PCIGETMEMORY(basep
[i
-1]),
2399 pcrp
->basesize
[i
-1], ResExcMemBlock
)
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);
2414 xf86MsgVerb(X_INFO
, 3,"Sys:\n");
2415 xf86PrintResList(3,Sys
);
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
2426 while ((pvp
= xf86PciVideoInfo
[n
++])) {
2427 resPtr res_mp
= NULL
, res_m_io
= NULL
;
2429 resPtr tmp
, avoid
= NULL
;
2431 if (!pvp
->validate
) continue;
2432 NonSys
= xf86DupResList(Sys
);
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);
2447 xf86MsgVerb(X_INFO
, 3,"NonSys:\n");
2448 xf86PrintResList(3,NonSys
);
2452 if (pbp
->secondary
== pvp
->bus
) {
2453 if (pbp
->preferred_pmem
) {
2454 /* keep prefetchable separate */
2456 xf86FindIntersectOfLists(pbp
->preferred_pmem
, ResRange
);
2459 res_mp
= xf86FindIntersectOfLists(pbp
->pmem
, ResRange
);
2461 if (pbp
->preferred_mem
) {
2463 xf86FindIntersectOfLists(pbp
->preferred_mem
, ResRange
);
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
));
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
);
2488 if (res_m_io
== NULL
)
2489 res_m_io
= xf86DupResList(ResRange
);
2491 pciConvertListToHost(pvp
->bus
,pvp
->device
,pvp
->func
, avoid
);
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
);
2501 for (i
= 0; i
< 6; i
++) {
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);
2514 xf86MsgVerb(X_INFO
, 3, "own:\n");
2515 xf86PrintResList(3, own
);
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
);
2526 xf86MsgVerb(X_WARNING
, 0,
2527 "****INVALID IO ALLOCATION**** b: 0x%lx e: 0x%lx "
2528 "correcting\a\n", range
.rBegin
,range
.rEnd
);
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
);
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
);
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
);
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
);
2583 GetImplicitPciResources(int entityIndex
)
2587 resList list
= NULL
;
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
);
2602 if (pvp
->biosBase
) {
2603 list
= xnfrealloc(list
,sizeof(resRange
) * (++num
));
2604 PV_B_RANGE(list
[num
- 1],pvp
,ResShrMemBlock
| ResBios
);
2607 list
= xnfrealloc(list
,sizeof(resRange
) * (++num
));
2608 list
[num
- 1].type
= ResEnd
;
2621 if (xf86PciAccInfo
!= NULL
)
2624 if (xf86PciVideoInfo
== NULL
)
2627 while ((pvp
= xf86PciVideoInfo
[i
]) != NULL
) {
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
;
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.
2677 initPciBusState(void)
2679 BusAccPtr pbap
, pbap_tmp
;
2680 PciBusPtr pbp
= xf86PciBus
;
2681 pciBusInfo_t
*pBusInfo
;
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
;
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
);
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
;
2723 pbap
->next
= xf86BusAccInfo
;
2724 xf86BusAccInfo
= pbap
;
2728 pbap
= xf86BusAccInfo
;
2731 pbap
->primary
= NULL
;
2732 if (pbap
->busdep_type
== BUS_PCI
2733 && pbap
->busdep
.pci
.primary_bus
> -1) {
2734 pbap_tmp
= xf86BusAccInfo
;
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
)
2741 pbap
->primary
= pbap_tmp
;
2744 pbap_tmp
= pbap_tmp
->next
;
2757 if (xf86PciAccInfo
== NULL
)
2760 while ((paccp
= xf86PciAccInfo
[i
]) != NULL
) {
2764 savePciState(paccp
->arg
.tag
, &paccp
->save
);
2765 restorePciState(paccp
->arg
.tag
, &paccp
->restore
);
2766 paccp
->arg
.ctrl
= paccp
->restore
.command
;
2771 PciBusStateEnter(void)
2773 BusAccPtr pbap
= xf86BusAccInfo
;
2788 if (xf86PciAccInfo
== NULL
)
2791 while ((paccp
= xf86PciAccInfo
[i
]) != NULL
) {
2795 savePciState(paccp
->arg
.tag
, &paccp
->restore
);
2796 restorePciState(paccp
->arg
.tag
, &paccp
->save
);
2801 PciBusStateLeave(void)
2803 BusAccPtr pbap
= xf86BusAccInfo
;
2806 if (pbap
->restore_f
)
2807 pbap
->restore_f(pbap
);
2813 DisablePciAccess(void)
2817 if (xf86PciAccInfo
== NULL
)
2820 while ((paccp
= xf86PciAccInfo
[i
]) != NULL
) {
2822 if (!paccp
->ctrl
) /* disable devices that are under control initially*/
2824 pciIo_MemAccessDisable(paccp
->io_memAccess
.arg
);
2829 DisablePciBusAccess(void)
2831 BusAccPtr pbap
= xf86BusAccInfo
;
2834 if (pbap
->disable_f
)
2835 pbap
->disable_f(pbap
);
2837 pbap
->primary
->current
= NULL
;
2847 xf86IsPciDevPresent(int bus
, int dev
, int func
)
2852 while ((pcp
= xf86PciInfo
[i
]) != NULL
) {
2853 if ((pcp
->busnum
== bus
)
2854 && (pcp
->devnum
== dev
)
2855 && (pcp
->funcnum
== func
))
2863 * If the slot requested is already in use, return -1.
2864 * Otherwise, claim the slot for the screen requesting it.
2868 xf86ClaimPciSlot(int bus
, int device
, int func
, DriverPtr drvp
,
2869 int chipset
, GDevPtr dev
, Bool active
)
2872 pciAccPtr
*ppaccp
= xf86PciAccInfo
;
2873 BusAccPtr pbap
= xf86BusAccInfo
;
2877 if (xf86CheckPciSlot(bus
, device
, func
)) {
2878 num
= xf86AllocateEntity();
2879 p
= xf86Entities
[num
];
2881 p
->chipset
= chipset
;
2882 p
->busType
= BUS_PCI
;
2883 p
->pciBusId
.bus
= bus
;
2884 p
->pciBusId
.device
= device
;
2885 p
->pciBusId
.func
= func
;
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 */
2903 if (!ppaccp
|| !*ppaccp
) {
2904 p
->access
->fallback
= &AccessNULL
;
2905 p
->access
->pAccess
= &AccessNULL
;
2910 if (pbap
->type
== BUS_PCI
&& pbap
->busdep
.pci
.bus
== bus
)
2914 fixPciSizeInfo(num
);
2916 /* in case bios is enabled disable it */
2917 disablePciBios(pciTag(bus
,device
,func
));
2918 pciSlotClaimed
= TRUE
;
2921 /* Map in this domain's I/O space */
2922 p
->domainIO
= xf86MapDomainIO(-1, VIDMEM_MMIO
,
2923 pciTag(bus
, device
, func
), 0, 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)
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.
2969 xf86SetPciVideo(pciVideoPtr pvp
, resType rt
)
2971 static BusAccPtr pbap
= NULL
;
2972 static xf86AccessPtr pAcc
= NULL
;
2973 static Bool DoneProbes
= FALSE
;
2980 /* Disable previous access */
2982 if (pAcc
->AccessDisable
)
2983 (*pAcc
->AccessDisable
)(pAcc
->arg
);
2987 while (pbap
->primary
) {
2988 if (pbap
->disable_f
)
2989 (*pbap
->disable_f
)(pbap
);
2990 pbap
->primary
->current
= NULL
;
2991 pbap
= pbap
->primary
;
2996 /* Check for xf86PostProbe's magic combo */
3003 /* Validate device */
3004 if (!xf86PciVideoInfo
|| !xf86PciAccInfo
|| !xf86BusAccInfo
)
3007 for (i
= 0; pvp
!= xf86PciVideoInfo
[i
]; i
++)
3008 if (!xf86PciVideoInfo
[i
])
3011 /* Ignore request for claimed adapters */
3012 if (!xf86CheckPciSlot(pvp
->bus
, pvp
->device
, pvp
->func
))
3015 /* Find pciAccRec structure */
3016 for (i
= 0; ; i
++) {
3017 if (!(pcaccp
= xf86PciAccInfo
[i
]))
3019 if ((pvp
->bus
== pcaccp
->busnum
) &&
3020 (pvp
->device
== pcaccp
->devnum
) &&
3021 (pvp
->func
== pcaccp
->funcnum
))
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
);
3032 /* Find BusAccRec structure */
3033 for (pbap
= xf86BusAccInfo
; ; pbap
= pbap
->next
) {
3036 if (pvp
->bus
== pbap
->busdep
.pci
.bus
)
3042 (*pbap
->set_f
)(pbap
);
3047 pAcc
= &pcaccp
->ioAccess
;
3050 pAcc
= &pcaccp
->io_memAccess
;
3053 pAcc
= &pcaccp
->memAccess
;
3055 default: /* no compiler noise */
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.
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.
3081 if (StringToBusType(busID
, &id
) != BUS_PCI
)
3086 if (p
== NULL
|| *p
== 0) {
3090 d
= strpbrk(p
, "@");
3093 for (i
= 0; d
[i
] != 0; i
++) {
3094 if (!isdigit(d
[i
])) {
3100 for (i
= 0; p
[i
] != 0; i
++) {
3101 if (!isdigit(p
[i
])) {
3107 if (d
!= NULL
&& *d
!= 0)
3108 *bus
+= atoi(d
) << 8;
3109 p
= strtok(NULL
, ":");
3110 if (p
== NULL
|| *p
== 0) {
3114 for (i
= 0; p
[i
] != 0; i
++) {
3115 if (!isdigit(p
[i
])) {
3122 p
= strtok(NULL
, ":");
3123 if (p
== NULL
|| *p
== 0) {
3127 for (i
= 0; p
[i
] != 0; i
++) {
3128 if (!isdigit(p
[i
])) {
3139 * Compare a BUS ID string with a PCI bus id. Return TRUE if they match.
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
;
3155 * xf86IsPrimaryPci() -- return TRUE if primary device
3156 * is PCI and bus, dev and func numbers match.
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
)
3177 if (entityIndex
>= xf86NumEntities
)
3180 p
= xf86Entities
[entityIndex
];
3181 if (p
->busType
!= BUS_PCI
)
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
)
3194 xf86GetPciEntity(int bus
, int dev
, int func
)
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
)
3211 * xf86CheckPciMemBase() checks that the memory base value matches one of the
3212 * PCI base address register values for the given PCI device.
3215 xf86CheckPciMemBase(pciVideoPtr pPci
, memType base
)
3219 for (i
= 0; i
< 6; i
++)
3220 if (base
== pPci
->memBase
[i
])
3226 * Check if the slot requested is free. If it is already in use, return FALSE.
3230 xf86CheckPciSlot(int bus
, int device
, int func
)
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
)
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
;
3261 for (ppvp
= xf86PciVideoInfo
, pvp
=*ppvp
; pvp
; pvp
= *(++ppvp
)) {
3262 if (pvp
== pvp_exclude
) continue;
3263 if ((pvp
->vendor
== vendorID
) && (pvp
->chipType
== deviceID
)) {
3270 _X_EXPORT pciVideoPtr
3271 xf86FindPciClass(CARD8 intf
, CARD8 subClass
, CARD16
class,
3272 char n
, pciVideoPtr pvp_exclude
)
3274 pciVideoPtr pvp
, *ppvp
;
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)) {
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
;
3305 Bool multicard
= FALSE
;
3306 Bool multifunc
= FALSE
;
3316 for (i
=0; i
< 8; i
++) {
3320 if (ppcrp
[j
]->busnum
== bus
&& ppcrp
[j
]->funcnum
== i
) {
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
3334 if (pcrp
->pci_header_type
&0x80)
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
)
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
);
3371 xf86MsgVerb(X_INFO
,3,"Multi Device Card detected: %s\n",str
);
3376 pciTagConvertRange2Host(PCITAG tag
, resRange
*pRange
)
3378 if (!(pRange
->type
& ResBus
))
3381 switch(pRange
->type
& ResPhysMask
) {
3383 switch(pRange
->type
& ResExtMask
) {
3385 pRange
->rBegin
= pciBusAddrToHostAddr(tag
,PCI_MEM
, pRange
->rBegin
);
3386 pRange
->rEnd
= pciBusAddrToHostAddr(tag
,PCI_MEM
, pRange
->rEnd
);
3389 pRange
->rBase
= pciBusAddrToHostAddr(tag
,PCI_MEM_SPARSE_BASE
,
3391 pRange
->rMask
= pciBusAddrToHostAddr(tag
,PCI_MEM_SPARSE_MASK
,
3397 switch(pRange
->type
& ResExtMask
) {
3399 pRange
->rBegin
= pciBusAddrToHostAddr(tag
,PCI_IO
, pRange
->rBegin
);
3400 pRange
->rEnd
= pciBusAddrToHostAddr(tag
,PCI_IO
, pRange
->rEnd
);
3403 pRange
->rBase
= pciBusAddrToHostAddr(tag
,PCI_IO_SPARSE_BASE
3405 pRange
->rMask
= pciBusAddrToHostAddr(tag
,PCI_IO_SPARSE_MASK
3412 /* Set domain number */
3413 pRange
->type
&= ~(ResDomain
| ResBus
);
3414 pRange
->type
|= xf86GetPciDomain(tag
) << 24;
3418 pciConvertListToHost(int bus
, int dev
, int func
, resPtr list
)
3420 PCITAG tag
= pciTag(bus
,dev
,func
);
3422 pciTagConvertRange2Host(tag
, &list
->val
);
3428 updateAccessInfoStatusControlInfo(PCITAG tag
, CARD32 ctrl
)
3432 if (!xf86PciAccInfo
)
3435 for (i
= 0; xf86PciAccInfo
[i
] != NULL
; i
++) {
3436 if (xf86PciAccInfo
[i
]->arg
.tag
== tag
)
3437 xf86PciAccInfo
[i
]->arg
.ctrl
= ctrl
;
3442 pciConvertRange2Host(int entityIndex
, resRange
*pRange
)
3447 pvp
= xf86GetPciInfoForEntity(entityIndex
);
3450 pciTagConvertRange2Host(tag
, pRange
);