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 */
49static void
50ATIVGAWonderProbe
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 */
119static Bool
120ATIMach64Detect
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 */
206static ATIPtr
207ATIMach64Probe
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	    (pATI->Block0Base != 0xfffff000))
226        {
227            pATI->Block0Base += 0x00000400U;
228            if (ATIMach64Detect(pATI, ChipType, Chip))
229                return pATI;
230
231            return NULL;
232        }
233
234        /*
235         * Probe through the primary MMIO aperture that exists at the tail end
236         * of the linear aperture.  Test for both 8MB and 4MB linear apertures.
237         */
238        if ((PCI_REGION_SIZE(pVideo, 0) >= (1 << 22)) &&
239            (pATI->Block0Base = PCI_REGION_BASE(pVideo, 0, REGION_MEM)))
240        {
241            pATI->MMIOInLinear = TRUE;
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 */
263static ATIPtr
264ATIMach64Probe
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
308static void
309ATIAssignVGA
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 */
338static void
339ATIFindVGA
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 */
363Bool
364ATIMach64ProbeIO
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