1 /*
2 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of Marc Aurele La France not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. Marc Aurele La France makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as-is" without express or implied warranty.
13 *
14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdint.h>
30
31 #include "ati.h"
32 #include "atibus.h"
33 #include "atichip.h"
34 #include "atimach64io.h"
35 #include "atimach64version.h"
36 #include "atiprobe.h"
37 #include "atividmem.h"
38 #include "atiwonderio.h"
39
40 #ifndef AVOID_CPIO
41
42 /*
43 * ATIVGAWonderProbe --
44 *
45 * This function determines if ATI extended VGA registers can be accessed
46 * through the I/O port specified by pATI->CPIO_VGAWonder. If not, the
47 * function resets pATI->CPIO_VGAWonder to zero.
48 */
49 static void
ATIVGAWonderProbe(pciVideoPtr pVideo,ATIPtr pATI)50 ATIVGAWonderProbe
51 (
52 pciVideoPtr pVideo,
53 ATIPtr pATI
54 )
55 {
56 CARD8 IOValue1, IOValue2, IOValue3, IOValue4, IOValue5, IOValue6;
57
58 if (!pATI->OptionProbeSparse)
59 {
60 xf86Msg(X_WARNING,
61 MACH64_NAME ": Expected VGA Wonder capability at I/O port"
62 " 0x%04lX will not be probed\n"
63 "set option \"probe_sparse\" to force probing.\n",
64 pATI->CPIO_VGAWonder);
65
66 pATI->CPIO_VGAWonder = 0;
67 return;
68 }
69
70 if (pVideo && !xf86IsPrimaryPci(pVideo) &&
71 (pATI->Chip <= ATI_CHIP_88800GXD))
72 {
73 /* Set up extended VGA register addressing */
74 PutReg(GRAX, 0x50U, GetByte(pATI->CPIO_VGAWonder, 0));
75 PutReg(GRAX, 0x51U, GetByte(pATI->CPIO_VGAWonder, 1) | 0x80U);
76 }
77 /*
78 * Register 0xBB is used by the BIOS to keep track of various
79 * things (monitor type, etc.). Except for 18800-x's, register
80 * 0xBC must be zero and causes the adapter to enter a test mode
81 * when written to with a non-zero value.
82 */
83 IOValue1 = inb(pATI->CPIO_VGAWonder);
84 IOValue2 = ATIGetExtReg(IOValue1);
85 IOValue3 = ATIGetExtReg(0xBBU);
86 ATIPutExtReg(0xBBU, IOValue3 ^ 0xAAU);
87 IOValue4 = ATIGetExtReg(0xBBU);
88 ATIPutExtReg(0xBBU, IOValue3 ^ 0x55U);
89 IOValue5 = ATIGetExtReg(0xBBU);
90 ATIPutExtReg(0xBBU, IOValue3);
91 IOValue6 = ATIGetExtReg(0xBCU);
92 ATIPutExtReg(IOValue1, IOValue2);
93
94 if ((IOValue4 == (IOValue3 ^ 0xAAU)) &&
95 (IOValue5 == (IOValue3 ^ 0x55U)) &&
96 (IOValue6 == 0))
97 {
98 xf86MsgVerb(X_INFO, 3,
99 MACH64_NAME ": VGA Wonder at I/O port 0x%04lX detected.\n",
100 pATI->CPIO_VGAWonder);
101 }
102 else
103 {
104 xf86Msg(X_WARNING,
105 MACH64_NAME ": Expected VGA Wonder capability at I/O port"
106 " 0x%04lX was not detected.\n", pATI->CPIO_VGAWonder);
107 pATI->CPIO_VGAWonder = 0;
108 }
109 }
110
111 #endif /* AVOID_CPIO */
112
113 /*
114 * ATIMach64Detect --
115 *
116 * This function determines if a Mach64 is detectable at a particular base
117 * address.
118 */
119 static Bool
ATIMach64Detect(ATIPtr pATI,const CARD16 ChipType,const ATIChipType Chip)120 ATIMach64Detect
121 (
122 ATIPtr pATI,
123 const CARD16 ChipType,
124 const ATIChipType Chip
125 )
126 {
127 CARD32 IOValue, bus_cntl, gen_test_cntl;
128 Bool DetectSuccess = FALSE;
129
130 (void)ATIMapApertures(-1, pATI); /* Ignore errors */
131
132 #ifdef AVOID_CPIO
133
134 if (!pATI->pBlock[0])
135 {
136 ATIUnmapApertures(-1, pATI);
137 return FALSE;
138 }
139
140 #endif /* AVOID_CPIO */
141
142 /* Make sure any Mach64 is not in some weird state */
143 bus_cntl = inr(BUS_CNTL);
144 if (Chip < ATI_CHIP_264VTB)
145 outr(BUS_CNTL,
146 (bus_cntl & ~(BUS_HOST_ERR_INT_EN | BUS_FIFO_ERR_INT_EN)) |
147 (BUS_HOST_ERR_INT | BUS_FIFO_ERR_INT));
148 else if (Chip < ATI_CHIP_264VT4)
149 outr(BUS_CNTL, (bus_cntl & ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT);
150
151 gen_test_cntl = inr(GEN_TEST_CNTL);
152 IOValue = gen_test_cntl &
153 (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN);
154 outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
155 outr(GEN_TEST_CNTL, IOValue);
156 outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
157
158 /* See if a Mach64 answers */
159 IOValue = inr(SCRATCH_REG0);
160
161 /* Test odd bits */
162 outr(SCRATCH_REG0, 0x55555555U);
163 if (inr(SCRATCH_REG0) == 0x55555555U)
164 {
165 /* Test even bits */
166 outr(SCRATCH_REG0, 0xAAAAAAAAU);
167 if (inr(SCRATCH_REG0) == 0xAAAAAAAAU)
168 {
169 /*
170 * *Something* has a R/W 32-bit register at this address. Try to
171 * make sure it's a Mach64. The following assumes that ATI will
172 * not be producing any more adapters that do not register
173 * themselves in PCI configuration space.
174 */
175 ATIMach64ChipID(pATI, ChipType);
176 if ((pATI->Chip != ATI_CHIP_Mach64) ||
177 (pATI->CPIODecoding == BLOCK_IO))
178 DetectSuccess = TRUE;
179 }
180 }
181
182 /* Restore clobbered register value */
183 outr(SCRATCH_REG0, IOValue);
184
185 /* If no Mach64 was detected, return now */
186 if (!DetectSuccess)
187 {
188 outr(GEN_TEST_CNTL, gen_test_cntl);
189 outr(BUS_CNTL, bus_cntl);
190 ATIUnmapApertures(-1, pATI);
191 return FALSE;
192 }
193
194 ATIUnmapApertures(-1, pATI);
195 return TRUE;
196 }
197
198 #ifdef AVOID_CPIO
199
200 /*
201 * ATIMach64Probe --
202 *
203 * This function looks for a Mach64 at a particular MMIO address and returns an
204 * ATIRec if one is found.
205 */
206 static ATIPtr
ATIMach64Probe(ATIPtr pATI,pciVideoPtr pVideo,const ATIChipType Chip)207 ATIMach64Probe
208 (
209 ATIPtr pATI,
210 pciVideoPtr pVideo,
211 const ATIChipType Chip
212 )
213 {
214 CARD16 ChipType = PCI_DEV_DEVICE_ID(pVideo);
215
216 pATI->MMIOInLinear = FALSE;
217
218 /*
219 * Probe through auxiliary MMIO aperture if one exists. Because such
220 * apertures can be enabled/disabled only through PCI, this probes no
221 * further.
222 */
223 if ((PCI_REGION_SIZE(pVideo, 2) >= (1 << 12)) &&
224 (pATI->Block0Base = PCI_REGION_BASE(pVideo, 2, REGION_MEM)))
225 {
226 pATI->Block0Base += 0x00000400U;
227 if (ATIMach64Detect(pATI, ChipType, Chip))
228 return pATI;
229
230 return NULL;
231 }
232
233 /*
234 * Probe through the primary MMIO aperture that exists at the tail end
235 * of the linear aperture. Test for both 8MB and 4MB linear apertures.
236 */
237 if ((PCI_REGION_SIZE(pVideo, 0) >= (1 << 22)) &&
238 (pATI->Block0Base = PCI_REGION_BASE(pVideo, 0, REGION_MEM)))
239 {
240 pATI->MMIOInLinear = TRUE;
241
242 pATI->Block0Base += 0x007FFC00U;
243 if ((PCI_REGION_SIZE(pVideo, 0) >= (1 << 23)) &&
244 ATIMach64Detect(pATI, ChipType, Chip))
245 return pATI;
246
247 pATI->Block0Base -= 0x00400000U;
248 if (ATIMach64Detect(pATI, ChipType, Chip))
249 return pATI;
250 }
251
252 return NULL;
253 }
254
255 #else /* AVOID_CPIO */
256
257 /*
258 * ATIMach64Probe --
259 *
260 * This function looks for a Mach64 at a particular PIO address and returns an
261 * ATIRec if one is found.
262 */
263 static ATIPtr
ATIMach64Probe(ATIPtr pATI,pciVideoPtr pVideo,const ATIChipType Chip)264 ATIMach64Probe
265 (
266 ATIPtr pATI,
267 pciVideoPtr pVideo,
268 const ATIChipType Chip
269 )
270 {
271 CARD32 IOValue;
272 CARD16 ChipType = PCI_DEV_DEVICE_ID(pVideo);
273
274 if ((pATI->CPIODecoding == BLOCK_IO) &&
275 (PCI_REGION_SIZE(pVideo, 1) < (1 << 8)))
276 return NULL;
277
278 if (!ATIMach64Detect(pATI, ChipType, Chip))
279 {
280 return NULL;
281 }
282
283 /*
284 * Determine VGA capability. VGA can always be enabled on integrated
285 * controllers. For the GX/CX, it's a board strap.
286 */
287 if (pATI->Chip >= ATI_CHIP_264CT)
288 {
289 pATI->VGAAdapter = TRUE;
290 }
291 else
292 {
293 IOValue = inr(CONFIG_STATUS64_0);
294 pATI->BusType = GetBits(IOValue, CFG_BUS_TYPE);
295 IOValue &= (CFG_VGA_EN | CFG_CHIP_EN);
296 if (pATI->Chip == ATI_CHIP_88800CX)
297 IOValue |= CFG_VGA_EN;
298 if (IOValue == (CFG_VGA_EN | CFG_CHIP_EN))
299 {
300 pATI->VGAAdapter = TRUE;
301 pATI->CPIO_VGAWonder = 0x01CEU;
302 }
303 }
304
305 return pATI;
306 }
307
308 static void
ATIAssignVGA(pciVideoPtr pVideo,ATIPtr pATI)309 ATIAssignVGA
310 (
311 pciVideoPtr pVideo,
312 ATIPtr pATI
313 )
314 {
315 if (pATI->CPIO_VGAWonder)
316 {
317 ATIVGAWonderProbe(pVideo, pATI);
318 if (!pATI->CPIO_VGAWonder)
319 {
320 /*
321 * Some adapters are reputed to append ATI extended VGA registers
322 * to the VGA Graphics controller registers. In particular, 0x01CE
323 * cannot, in general, be used in a PCI environment due to routing
324 * of I/O through the bus tree.
325 */
326 pATI->CPIO_VGAWonder = GRAX;
327 ATIVGAWonderProbe(pVideo, pATI);
328 }
329 }
330 }
331
332 /*
333 * ATIFindVGA --
334 *
335 * This function determines if a VGA associated with an ATI PCI adapter is
336 * shareable.
337 */
338 static void
ATIFindVGA(pciVideoPtr pVideo,ATIPtr pATI)339 ATIFindVGA
340 (
341 pciVideoPtr pVideo,
342 ATIPtr pATI
343 )
344 {
345 /*
346 * An ATI PCI adapter has been detected at this point, and its VGA, if
347 * any, is shareable. Ensure the VGA isn't in sleep mode.
348 */
349 outb(GENENA, 0x16U);
350 outb(GENVS, 0x01U);
351 outb(GENENA, 0x0EU);
352
353 ATIAssignVGA(pVideo, pATI);
354 }
355
356 #endif /* AVOID_CPIO */
357
358 /*
359 * ATIMach64ProbeIO --
360 *
361 * This function determines the IO method and IO base of the ATI PCI adapter.
362 */
363 Bool
ATIMach64ProbeIO(pciVideoPtr pVideo,ATIPtr pATI)364 ATIMach64ProbeIO
365 (
366 pciVideoPtr pVideo,
367 ATIPtr pATI
368 )
369 {
370 /* Next, look for sparse I/O Mach64's */
371 if (!PCI_REGION_SIZE(pVideo, 1))
372 {
373
374 #ifndef AVOID_CPIO
375
376 static const unsigned long Mach64SparseIOBases[] = {
377 0x02ECU,
378 0x01CCU,
379 0x01C8U
380 };
381 uint32_t PciReg;
382 uint32_t j;
383
384 #ifndef XSERVER_LIBPCIACCESS
385 pciConfigPtr pPCI = pVideo->thisCard;
386
387 if (pPCI == NULL)
388 return FALSE;
389 #endif
390
391 PCI_READ_LONG(pVideo, &PciReg, PCI_REG_USERCONFIG);
392 j = PciReg & 0x03U;
393
394 if (j == 0x03U)
395 {
396 xf86Msg(X_WARNING, MACH64_NAME ": "
397 "PCI Mach64 in slot %d:%d:%d cannot be enabled\n"
398 "because it has neither a block, nor a sparse, I/O base.\n",
399 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo));
400
401 return FALSE;
402 }
403
404 /* Possibly fix block I/O indicator */
405 if (PciReg & 0x00000004U)
406 {
407 PciReg &= ~0x00000004U;
408 PCI_WRITE_LONG(pVideo, PciReg, PCI_REG_USERCONFIG);
409 }
410
411 /* FIXME:
412 * Should not probe at sparse I/O bases which have been registered to
413 * other PCI devices. The old ATIProbe() would scan the PCI space and
414 * build a list of registered I/O ports. If there was a conflict
415 * between a mach64 sparse I/O base and a registered I/0 port, probing
416 * that port was not allowed...
417 *
418 * We just add an option and let the user decide, this will not work
419 * with "X -configure" though...
420 */
421 if (!pATI->OptionProbeSparse)
422 {
423 xf86Msg(X_WARNING, MACH64_NAME ": "
424 "PCI Mach64 in slot %d:%d:%d will not be probed\n"
425 "set option \"probe_sparse\" to force sparse I/O probing.\n",
426 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo));
427
428 return FALSE;
429 }
430
431 pATI->CPIOBase = Mach64SparseIOBases[j];
432 pATI->CPIODecoding = SPARSE_IO;
433 pATI->PCIInfo = pVideo;
434
435 #else /* AVOID_CPIO */
436
437 /* The adapter's CPIO base is of little concern here */
438 pATI->CPIOBase = 0;
439 pATI->CPIODecoding = SPARSE_IO;
440 pATI->PCIInfo = pVideo;
441
442 #endif /* AVOID_CPIO */
443
444 }
445
446 /* Lastly, look for block I/O devices */
447 if (PCI_REGION_SIZE(pVideo, 1))
448 {
449 pATI->CPIOBase = PCI_REGION_BASE(pVideo, 1, REGION_IO);
450 pATI->CPIODecoding = BLOCK_IO;
451 pATI->PCIInfo = pVideo;
452 }
453
454 if (!ATIMach64Probe(pATI, pVideo, pATI->Chip))
455 {
456 xf86Msg(X_WARNING, MACH64_NAME ": "
457 "Mach64 in slot %d:%d:%d could not be detected!\n",
458 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo));
459
460 return FALSE;
461 }
462
463 xf86Msg(X_INFO, MACH64_NAME ": "
464 "Mach64 in slot %d:%d:%d detected.\n",
465 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo));
466
467 #ifndef AVOID_CPIO
468
469 if (pATI->VGAAdapter)
470 ATIFindVGA(pVideo, pATI);
471
472 #endif /* AVOID_CPIO */
473
474 return TRUE;
475 }
476