2 * Copyright (C) 2002-2003 The XFree86 Project, Inc. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * 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 THE
17 * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * Except as contained in this notice, the name of the XFree86 Project shall
22 * not be used in advertising or otherwise to promote the sale, use or other
23 * dealings in this Software without prior written authorization from the
28 * This file contains the glue necessary for support of Intel's 460GX chipset.
31 #ifdef HAVE_XORG_CONFIG_H
32 #include <xorg-config.h>
39 /* 460GX register definitions */
43 #define DEVNPRES 0x0070
44 /* SAC at CBN:1[0-7]:0 */
50 #define IORD 0x008E /* CBN:10:0 only */
51 /* PXB at CBN:1[0-7]:1 */
54 static int cbn_460gx
= -1;
55 static CARD32 cbdevs_460gx
= 0;
56 static CARD16 iord_460gx
;
57 static int busno_460gx
[8], subno_460gx
[8];
58 static CARD8 pcis_460gx
[8], ior_460gx
[8];
59 static CARD8 has_err_460gx
[8], err_460gx
[8];
60 static CARD8 iomap_460gx
[16]; /* One for each 4k */
61 static pciBusFuncs_t BusFuncs_460gx
;
64 Verify460GXBus(int bus
)
68 if ((bus
< 0) || (bus
>= pciNumBuses
) ||
69 !pciBusInfo
[bus
] || !(pPCI
= pciBusInfo
[bus
]->bridge
) ||
70 (pPCI
->busnum
!= cbn_460gx
) || (pPCI
->funcnum
!= 0) ||
71 (pPCI
->devnum
< 0x10) || (pPCI
->devnum
> 0x17))
78 * This function is called to emulate the various settings in a P2P or CardBus
79 * bridge's control register using one of a 460GX's SAC host bridges.
82 Control460GXBridge(int bus
, CARD16 mask
, CARD16 value
)
89 if ((pPCI
= Verify460GXBus(bus
))) {
90 /* Start with VGA enablement */
91 tmp
= pciReadByte(pPCI
->tag
, VGASE
);
93 current
|= PCI_PCI_BRIDGE_VGA_EN
;
94 if ((mask
& PCI_PCI_BRIDGE_VGA_EN
) &&
95 !(value
& PCI_PCI_BRIDGE_VGA_EN
))
96 pciWriteByte(pPCI
->tag
, VGASE
, tmp
& ~0x01);
98 if (mask
& value
& PCI_PCI_BRIDGE_VGA_EN
)
99 pciWriteByte(pPCI
->tag
, VGASE
, tmp
| 0x01);
102 /* Move on to master abort failure enablement */
103 if (has_err_460gx
[pPCI
->devnum
- 0x10]) {
104 tag
= PCI_MAKE_TAG(pPCI
->busnum
, pPCI
->devnum
, pPCI
->funcnum
+ 1);
105 tmp
= pciReadByte(tag
, ERRCMD
);
107 current
|= PCI_PCI_BRIDGE_MASTER_ABORT_EN
;
108 if ((mask
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
) &&
109 !(value
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
))
110 pciWriteByte(tag
, ERRCMD
, tmp
& ~0x01);
112 if (mask
& value
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
)
113 pciWriteByte(tag
, ERRCMD
, tmp
| 0x01);
117 /* Put emulation of any other P2P bridge control here */
120 return (current
& ~mask
) | (value
& mask
);
124 * Retrieve various bus numbers representing the connections provided by 460GX
128 Get460GXBridgeBuses(int bus
, int *primary
, int *secondary
, int *subordinate
)
130 pciConfigPtr pPCI
= Verify460GXBus(bus
);
133 /* The returned bus numbers are initialised by the caller */
138 i
= pPCI
->devnum
- 0x10;
140 /* These are not modified, so no need to re-read them */
142 *primary
= pPCI
->busnum
;
144 *secondary
= busno_460gx
[i
];
146 *subordinate
= subno_460gx
[i
];
149 /* Retrieves a list of the resources routed to a host bridge's secondary bus */
151 Get460GXBridgeResources(int bus
,
156 pciConfigPtr pPCI
= Verify460GXBus(bus
);
161 xf86FreeResList(*ppIoRes
);
165 for (i
= 0; i
<= 0x0F; i
++) {
166 if (iomap_460gx
[i
] != pPCI
->devnum
)
169 RANGE(range
, i
<< 12, ((i
+ 1) << 12) - 1,
170 RANGE_TYPE(ResExcIoBlock
, 0));
171 *ppIoRes
= xf86AddResToList(*ppIoRes
, &range
, -1);
177 xf86FreeResList(*ppMemRes
);
181 if (!(i
= (pPCI
->devnum
- 0x10)))
182 j
= 127; /* (4GB - 32M) / 32M */
184 j
= pcis_460gx
[i
- 1] & 0x7F;
186 i
= pcis_460gx
[i
] & 0x7F;
188 RANGE(range
, i
<< 25, (j
<< 25) - 1,
189 RANGE_TYPE(ResExcMemBlock
, 0));
190 *ppMemRes
= xf86AddResToList(*ppMemRes
, &range
, -1);
196 xf86FreeResList(*ppPmemRes
);
202 * This checks for, and validates, the presence of the 460GX chipset, and sets
203 * cbn_460gx to a positive value accordingly. This function returns TRUE if
204 * the chipset scan is to be stopped, or FALSE if the scan is to move on to the
209 xorgProbe460GX(scanpciWrapperOpt flags
)
211 pciBusInfo_t
*pBusInfo
;
214 /* Bus zero should already be set up */
215 if (!(pBusInfo
= pciBusInfo
[0])) {
219 /* First look for a 460GX's primary host bridge */
220 tag
= PCI_MAKE_TAG(0, 0x10, 0);
221 if (pciReadLong(tag
, PCI_ID_REG
) == DEVID(VENDOR_INTEL
, CHIP_460GX_SAC
)) {
231 xf86PreScan460GX(void)
233 pciBusInfo_t
*pBusInfo
;
238 if (!(pBusInfo
= pciBusInfo
[0]))
241 /* Get CBN (Chipset bus number) */
242 tag
= PCI_MAKE_TAG(0, 0x10, 0);
243 if (!(cbn_460gx
= (unsigned int)pciReadByte(tag
, CBN
))) {
244 /* Sanity check failed */
249 if (pciNumBuses
<= cbn_460gx
)
250 pciNumBuses
= cbn_460gx
+ 1;
253 if (!pciBusInfo
[cbn_460gx
]) {
254 pciBusInfo
[cbn_460gx
] = xnfalloc(sizeof(pciBusInfo_t
));
255 *pciBusInfo
[cbn_460gx
] = *pBusInfo
;
258 tag
= PCI_MAKE_TAG(cbn_460gx
, 0, 0);
259 if (pciReadLong(tag
, PCI_ID_REG
) != DEVID(VENDOR_INTEL
, CHIP_460GX_SAC
)) {
260 /* Sanity check failed */
266 * Find out which CBN devices the firmware thinks are present. Of these,
267 * we are only interested in devices 0x10 through 0x17.
269 cbdevs_460gx
= pciReadLong(tag
, DEVNPRES
);
271 for (i
= 0, devno
= 0x10; devno
<= 0x17; i
++, devno
++) {
272 tag
= PCI_MAKE_TAG(cbn_460gx
, devno
, 0);
273 if (pciReadLong(tag
, PCI_ID_REG
) !=
274 DEVID(VENDOR_INTEL
, CHIP_460GX_SAC
)) {
275 /* Sanity check failed */
281 iord_460gx
= pciReadWord(tag
, IORD
);
283 busno_460gx
[i
] = (unsigned int)pciReadByte(tag
, BUSNO
);
284 subno_460gx
[i
] = (unsigned int)pciReadByte(tag
, SUBNO
);
285 pcis_460gx
[i
] = pciReadByte(tag
, PCIS
);
286 ior_460gx
[i
] = pciReadByte(tag
, IOR
);
288 has_err_460gx
[i
] = err_460gx
[i
] = 0; /* Insurance */
290 tag
= PCI_MAKE_TAG(cbn_460gx
, devno
, 1);
291 tmp
= pciReadLong(tag
, PCI_ID_REG
);
293 case DEVID(VENDOR_INTEL
, CHIP_460GX_PXB
):
294 case DEVID(VENDOR_INTEL
, CHIP_460GX_WXB
):
295 if (cbdevs_460gx
& (1 << devno
)) {
296 /* Sanity check failed */
302 * XXX I don't have WXB docs, but PCI register dumps indicate that
303 * the registers we are interested in are consistent with those of
306 err_460gx
[i
] = pciReadByte(tag
, ERRCMD
);
307 has_err_460gx
[i
] = 1;
310 case DEVID(VENDOR_INTEL
, CHIP_460GX_GXB_1
):
311 if (cbdevs_460gx
& (1 << devno
)) {
312 /* Sanity check failed */
318 * XXX GXB isn't documented to have an ERRCMD register, nor any
319 * other means of failing master aborts. For now, assume master
320 * aborts are always allowed to complete normally.
325 if (((CARD16
)(tmp
+ 1U) <= (CARD16
)1U) &&
326 (cbdevs_460gx
& (1U << devno
)))
328 /* Sanity check failed */
334 /* Allow master aborts to complete normally */
335 for (i
= 0, devno
= 0x10; devno
<= 0x17; i
++, devno
++) {
336 if (!(err_460gx
[i
] & 0x01))
339 pciWriteByte(PCI_MAKE_TAG(cbn_460gx
, devno
, 1),
340 ERRCMD
, err_460gx
[i
] & ~0x01);
344 * The 460GX spec says that any access to buses higher than CBN will be
345 * master-aborted. It seems possible however that this is not the case in
346 * all 460GX implementations. For now, limit the bus scan to CBN, unless
347 * we have already found a higher bus number.
349 for (i
= 0; subno_460gx
[i
] < cbn_460gx
; ) {
353 pciMaxBusNum
= cbn_460gx
+ 1;
360 /* This does some 460GX-related processing after the PCI bus scan */
362 xf86PostScan460GX(void)
364 pciConfigPtr pPCI
, *ppPCI
;
365 pciBusInfo_t
*pBusInfo
;
371 /* Set up our extra bus functions */
372 BusFuncs_460gx
= *(pciBusInfo
[0]->funcs
);
373 BusFuncs_460gx
.pciControlBridge
= Control460GXBridge
;
374 BusFuncs_460gx
.pciGetBridgeBuses
= Get460GXBridgeBuses
;
375 BusFuncs_460gx
.pciGetBridgeResources
= Get460GXBridgeResources
;
378 * Mark all host bridges so that they are ignored by the upper-level
379 * xf86GetPciBridgeInfo() function. This marking is later clobbered by the
380 * tail end of xf86scanpci() for those bridges that actually have bus
381 * segments associated with them.
383 ppPCI
= xf86scanpci(0); /* Recursion is only apparent */
384 while ((pPCI
= *ppPCI
++)) {
385 if ((pPCI
->pci_base_class
== PCI_CLASS_BRIDGE
) &&
386 (pPCI
->pci_sub_class
== PCI_SUBCLASS_BRIDGE_HOST
))
387 pPCI
->businfo
= HOST_NO_BUS
;
390 ppPCI
= xf86scanpci(0); /* Recursion is only apparent */
394 * Fix up CBN bus linkage. This is somewhat arbitrary. The bridge chosen
395 * for this must be a CBN device so that bus CBN can be recognised as the
396 * root segment. It also cannot be any of the bus expanders (devices
397 * CBN:0x10:0 through CBN:0x17:0 nor any of their functions). For now, we
398 * chose the SAC host bridge at CBN:0:0.
400 pBusInfo
= pciBusInfo
[cbn_460gx
];
401 pBusInfo
->bridge
= pciBusInfo
[0]->bridge
; /* Just in case */
402 while ((pPCI
= *ppPCI
++)) {
403 if (pPCI
->busnum
< cbn_460gx
)
405 if (pPCI
->busnum
> cbn_460gx
)
407 if (pPCI
->devnum
< 0)
409 if (pPCI
->devnum
> 0)
411 if (pPCI
->funcnum
< 0)
413 if (pPCI
->funcnum
> 0)
416 pBusInfo
->bridge
= pPCI
;
417 pBusInfo
->secondary
= FALSE
;
418 pBusInfo
->primary_bus
= cbn_460gx
;
422 for (i
= 0, devno
= 0x10; devno
<= 0x17; i
++, devno
++) {
423 /* Restore ERRCMD registers */
424 if (err_460gx
[i
] & 0x01)
425 pciWriteByte(PCI_MAKE_TAG(cbn_460gx
, devno
, 1),
426 ERRCMD
, err_460gx
[i
]);
428 if (!(cbdevs_460gx
& (1 << devno
))) {
429 while ((pPCI
= *ppPCI
++)) {
430 if (pPCI
->busnum
< cbn_460gx
)
432 if (pPCI
->busnum
> cbn_460gx
)
434 if (pPCI
->devnum
< devno
)
436 if (pPCI
->devnum
> devno
)
438 if (pPCI
->funcnum
< 0)
440 if (pPCI
->funcnum
> 0)
443 if ((pBusInfo
== pciBusInfo
[busno_460gx
[i
]]))
446 /* Fix bus linkage */
447 pBusInfo
->bridge
= pPCI
;
448 pBusInfo
->secondary
= TRUE
;
449 pBusInfo
->primary_bus
= cbn_460gx
;
451 /* Plug in chipset routines */
452 pBusInfo
->funcs
= &BusFuncs_460gx
;
457 /* Decode IOR registers */
458 for(; j
<= (ior_460gx
[i
] & 0x0F); j
++)
459 iomap_460gx
[j
] = devno
;
462 /* The bottom 4k of I/O space is always routed to PCI0a */
463 iomap_460gx
[0] = 0x10;
465 /* Decode IORD register */
466 for (j
= 1; j
<= 0x0F; j
++)
467 if (iord_460gx
& (1 << j
))
468 iomap_460gx
[j
] = 0x10;