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