atipreinit.c revision 32b578d3
1/*
2 * Copyright 1999 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
30#include "ati.h"
31#include "atiadjust.h"
32#include "atiaudio.h"
33#include "atibus.h"
34#include "atichip.h"
35#include "aticursor.h"
36#include "atidac.h"
37#include "atidsp.h"
38#include "atii2c.h"
39#include "atiload.h"
40#include "atilock.h"
41#include "atimach64.h"
42#include "atimach64accel.h"
43#include "atimach64io.h"
44#include "atimach64probe.h"
45#include "atimode.h"
46#include "atioption.h"
47#include "atipreinit.h"
48#include "atiprint.h"
49#include "atiprobe.h"
50#include "atividmem.h"
51#include "atiwonderio.h"
52#include "atixv.h"
53
54#include "vbe.h"
55#include "xf86RAC.h"
56
57/*
58 * FreeScreen handles the clean-up.
59 */
60static Bool
61Mach64GetRec(ScrnInfoPtr pScrn)
62{
63    if (!pScrn->driverPrivate) {
64        pScrn->driverPrivate = xnfcalloc(sizeof(ATIRec), 1);
65        memset(pScrn->driverPrivate, 0, sizeof(ATIRec));
66    }
67
68    return TRUE;
69}
70
71/*
72 * ATIReportMemory --
73 *
74 * This function reports on the amount and type of video memory found.
75 */
76static void
77ATIReportMemory
78(
79    ScrnInfoPtr pScreenInfo,
80    ATIPtr      pATI,
81    const char *MemoryTypeName
82)
83{
84    char Buffer[128], *Message;
85
86    Message = Buffer +
87        snprintf(Buffer, SizeOf(Buffer), "%d kB of %s detected",
88            pATI->VideoRAM, MemoryTypeName);
89
90    if (pATI->VideoRAM > pScreenInfo->videoRam)
91    {
92        Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
93            " (using %d kB)", pScreenInfo->videoRam);
94    }
95    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
96}
97
98static const int videoRamSizes[] =
99    {512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024};
100static const rgb   defaultWeight = {0, 0, 0};
101static const Gamma defaultGamma  = {0.0, 0.0, 0.0};
102
103/*
104 * ATIPrintNoiseIfRequested --
105 *
106 * This function formats debugging information on the server's stderr when
107 * requested by the user through the server's verbosity setting.
108 */
109static void
110ATIPrintNoiseIfRequested
111(
112    ATIPtr       pATI,
113    CARD8       *BIOS,
114    unsigned int BIOSSize
115)
116{
117    if (xf86GetVerbosity() <= 3)
118        return;
119
120    if (BIOSSize > 0)
121        ATIPrintBIOS(BIOS, BIOSSize);
122    xf86ErrorFVerb(4, "\n On server entry:\n");
123    ATIPrintRegisters(pATI);
124}
125
126#define BIOS_SIZE    0x00010000U     /* 64kB */
127#define BIOSByte(_n) ((CARD8)(BIOS[_n]))
128#define BIOSWord(_n) ((CARD16)(BIOS[_n] |                \
129                               (BIOS[(_n) + 1] << 8)))
130
131/*
132 * For Mach64 adapters, pick up, from the BIOS, the type of programmable
133 * clock generator (if any), and various information about it.
134 */
135static void
136ati_bios_clock
137(
138    ScrnInfoPtr  pScreenInfo,
139    ATIPtr       pATI,
140    CARD8       *BIOS,
141    unsigned int ClockTable,
142    GDevPtr      pGDev
143)
144{
145    CARD16 ClockDac;
146
147    if (ClockTable > 0)
148    {
149        pATI->ProgrammableClock = BIOSByte(ClockTable);
150        pATI->ClockNumberToProgramme = BIOSByte(ClockTable + 0x06U);
151        pATI->refclk = BIOSWord(ClockTable + 0x08U);
152        pATI->refclk *= 10000;
153    }
154    else
155    {
156        /*
157         * Compensate for BIOS absence.  Note that the reference
158         * frequency has already been set by option processing.
159         */
160        if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
161        {
162            pATI->ProgrammableClock = ATI_CLOCK_INTERNAL;
163        }
164        else switch (pATI->DAC)
165        {
166            case ATI_DAC_STG1703:
167                pATI->ProgrammableClock = ATI_CLOCK_STG1703;
168                break;
169
170            case ATI_DAC_CH8398:
171                pATI->ProgrammableClock = ATI_CLOCK_CH8398;
172                break;
173
174            case ATI_DAC_ATT20C408:
175                pATI->ProgrammableClock = ATI_CLOCK_ATT20C408;
176                break;
177
178            case ATI_DAC_IBMRGB514:
179                pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
180                break;
181
182            default:        /* Provisional */
183                pATI->ProgrammableClock = ATI_CLOCK_ICS2595;
184                break;
185        }
186
187        /* This should be safe for all generators except IBM's RGB514 */
188        pATI->ClockNumberToProgramme = 3;
189    }
190
191    pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_FIXED];
192
193    if ((pATI->ProgrammableClock > ATI_CLOCK_FIXED) &&
194        (pATI->ProgrammableClock < ATI_CLOCK_MAX))
195    {
196        /*
197         * Graphics PRO TURBO 1600's are unusual in that an ICS2595 is used
198         * to generate clocks for VGA modes, and an IBM RGB514 is used for
199         * accelerator modes.
200         */
201        if ((pATI->ProgrammableClock == ATI_CLOCK_ICS2595) &&
202            (pATI->DAC == ATI_DAC_IBMRGB514))
203            pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
204
205        pATI->ClockDescriptor = ATIClockDescriptors[pATI->ProgrammableClock];
206    }
207
208    ClockDac = pATI->DAC;
209    switch (pATI->ProgrammableClock)
210    {
211        case ATI_CLOCK_ICS2595:
212            /*
213             * Pick up reference divider (43 or 46) appropriate to the chip
214             * revision level.
215             */
216            if (ClockTable > 0)
217                pATI->ClockDescriptor.MinM =
218                pATI->ClockDescriptor.MaxM = BIOSWord(ClockTable + 0x0AU);
219            else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-0"))
220                pATI->ClockDescriptor.MinM =
221                pATI->ClockDescriptor.MaxM = 43;
222            else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-1"))
223                pATI->ClockDescriptor.MinM =
224                pATI->ClockDescriptor.MaxM = 46;
225            else
226                pATI->ProgrammableClock = ATI_CLOCK_UNKNOWN;
227            break;
228
229        case ATI_CLOCK_STG1703:
230            /* This one's also a RAMDAC */
231            ClockDac = ATI_DAC_STG1703;
232            break;
233
234        case ATI_CLOCK_CH8398:
235            /* This one's also a RAMDAC */
236            ClockDac = ATI_DAC_CH8398;
237            break;
238
239        case ATI_CLOCK_INTERNAL:
240            /*
241             * The reference divider has already been programmed by BIOS
242             * initialisation.  Because, there is only one reference
243             * divider for all generated frequencies (including MCLK), it
244             * cannot be changed without reprogramming all clocks every
245             * time one of them needs a different reference divider.
246             *
247             * Besides, it's not a good idea to change the reference
248             * divider.  BIOS initialisation sets it to a value that
249             * effectively prevents generating frequencies beyond the
250             * graphics controller's tolerance.
251             */
252            pATI->ClockDescriptor.MinM =
253            pATI->ClockDescriptor.MaxM = ATIMach64GetPLLReg(PLL_REF_DIV);
254
255            /* The DAC is also integrated */
256            if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL)
257                ClockDac = ATI_DAC_INTERNAL;
258
259            break;
260
261        case ATI_CLOCK_ATT20C408:
262            /* This one's also a RAMDAC */
263            ClockDac = ATI_DAC_ATT20C408;
264            break;
265
266        case ATI_CLOCK_IBMRGB514:
267            /* This one's also a RAMDAC */
268            ClockDac = ATI_DAC_IBMRGB514;
269            pATI->ClockNumberToProgramme = 7;
270            break;
271
272        default:
273            break;
274    }
275
276    /*
277     * We now have up to two indications of what RAMDAC the adapter uses.
278     * They should be the same.  The following test and corresponding
279     * action are under construction.
280     */
281    if (pATI->DAC != ClockDac)
282    {
283        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
284                   "Mach64 RAMDAC probe discrepancy detected:\n"
285                   "  DAC=0x%02X;  ClockDac=0x%02X.\n",
286                   pATI->DAC, ClockDac);
287
288        if (pATI->DAC == ATI_DAC_IBMRGB514)
289        {
290            pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
291            pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_IBMRGB514];
292            pATI->ClockNumberToProgramme = 7;
293        }
294        else
295        {
296            pATI->DAC = ClockDac;   /* For now */
297        }
298    }
299
300    switch (pATI->refclk / 100000)
301    {
302        case 143:
303            pATI->ReferenceNumerator = 157500;
304            pATI->ReferenceDenominator = 11;
305            break;
306
307        case 286:
308            pATI->ReferenceNumerator = 315000;
309            pATI->ReferenceDenominator = 11;
310            break;
311
312        default:
313            pATI->ReferenceNumerator = pATI->refclk / 1000;
314            pATI->ReferenceDenominator = 1;
315            break;
316    }
317}
318
319/*
320 * Pick up multimedia information, which will be at different
321 * displacements depending on table revision.
322 */
323static void
324ati_bios_mmedia
325(
326    ScrnInfoPtr  pScreenInfo,
327    ATIPtr       pATI,
328    CARD8       *BIOS,
329    unsigned int VideoTable,
330    unsigned int HardwareTable
331)
332{
333    pATI->Audio = ATI_AUDIO_NONE;
334
335    if (VideoTable > 0)
336    {
337        switch (BIOSByte(VideoTable - 0x02U))
338        {
339            case 0x00U:
340                pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
341
342                /*
343                 * XXX  The VideoTable[1] byte is known to have been
344                 *      omitted in LTPro and Mobility BIOS'es.  Any others?
345                 */
346                switch (pATI->Chip)
347                {
348                    case ATI_CHIP_264LTPRO:
349                    case ATI_CHIP_MOBILITY:
350                        pATI->Decoder = BIOSByte(VideoTable + 0x01U) & 0x07U;
351                        pATI->Audio = BIOSByte(VideoTable + 0x02U) & 0x0FU;
352                        break;
353
354                    default:
355                        pATI->Decoder = BIOSByte(VideoTable + 0x02U) & 0x07U;
356                        pATI->Audio = BIOSByte(VideoTable + 0x03U) & 0x0FU;
357                        break;
358                }
359
360                break;
361
362            case 0x01U:
363                pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
364                pATI->Audio = BIOSByte(VideoTable + 0x01U) & 0x0FU;
365                pATI->Decoder = BIOSByte(VideoTable + 0x05U) & 0x0FU;
366                break;
367
368            default:
369                break;
370        }
371    }
372
373    if (HardwareTable > 0)
374    {
375        pATI->I2CType = BIOSByte(HardwareTable + 0x06U) & 0x0FU;
376    }
377}
378
379/*
380 * Determine panel dimensions and model.
381 */
382static void
383ati_bios_panel_info
384(
385    ScrnInfoPtr  pScreenInfo,
386    ATIPtr       pATI,
387    CARD8       *BIOS,
388    unsigned int BIOSSize,
389    unsigned int LCDTable
390)
391{
392    unsigned int LCDPanelInfo = 0;
393    char         Buffer[128];
394    int          i, j;
395
396    if (LCDTable > 0)
397    {
398        LCDPanelInfo = BIOSWord(LCDTable + 0x0AU);
399        if (((LCDPanelInfo + 0x1DU) > BIOSSize) ||
400            ((BIOSByte(LCDPanelInfo) != pATI->LCDPanelID) &&
401             (pATI->LCDPanelID || (BIOSByte(LCDPanelInfo) > 0x1FU) ||
402              (pATI->Chip <= ATI_CHIP_264LTPRO))))
403            LCDPanelInfo = 0;
404    }
405
406    if (!LCDPanelInfo)
407    {
408        /*
409         * Scan BIOS for panel info table.
410         */
411        for (i = 0;  i <= (int)(BIOSSize - 0x1DU);  i++)
412        {
413            /* Look for panel ID ... */
414            if ((BIOSByte(i) != pATI->LCDPanelID) &&
415                (pATI->LCDPanelID || (BIOSByte(i) > 0x1FU) ||
416                 (pATI->Chip <= ATI_CHIP_264LTPRO)))
417                continue;
418
419            /* ... followed by 24-byte panel model name ... */
420            for (j = 0;  j < 24;  j++)
421            {
422                if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU)
423                {
424                    i += j;
425                    goto NextBIOSByte;
426                }
427            }
428
429            /* ... verify panel width ... */
430            if (pATI->LCDHorizontal &&
431                (pATI->LCDHorizontal != BIOSWord(i + 0x19U)))
432                continue;
433
434            /* ... and verify panel height */
435            if (pATI->LCDVertical &&
436                (pATI->LCDVertical != BIOSWord(i + 0x1BU)))
437                continue;
438
439            if (LCDPanelInfo)
440            {
441                /*
442                 * More than one possibility, but don't care if all
443                 * tables describe panels of the same size.
444                 */
445                if ((BIOSByte(LCDPanelInfo + 0x19U) ==
446                     BIOSByte(i + 0x19U)) &&
447                    (BIOSByte(LCDPanelInfo + 0x1AU) ==
448                     BIOSByte(i + 0x1AU)) &&
449                    (BIOSByte(LCDPanelInfo + 0x1BU) ==
450                     BIOSByte(i + 0x1BU)) &&
451                    (BIOSByte(LCDPanelInfo + 0x1CU) ==
452                     BIOSByte(i + 0x1CU)))
453                    continue;
454
455                LCDPanelInfo = 0;
456                break;
457            }
458
459            LCDPanelInfo = i;
460
461    NextBIOSByte:  ;
462        }
463    }
464
465    if (LCDPanelInfo > 0)
466    {
467        pATI->LCDPanelID = BIOSByte(LCDPanelInfo);
468        pATI->LCDHorizontal = BIOSWord(LCDPanelInfo + 0x19U);
469        pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU);
470    }
471
472    if (LCDPanelInfo)
473    {
474        for (i = 0;  i < 24;  i++)
475            Buffer[i] = BIOSByte(LCDPanelInfo + 1 + i);
476        for (;  --i >= 0;  )
477            if (Buffer[i] && Buffer[i] != ' ')
478            {
479                Buffer[i + 1] = '\0';
480                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
481                    "Panel model %s.\n", Buffer);
482                break;
483            }
484    }
485}
486
487/*
488 * ATIPreInit --
489 *
490 * This function is only called once per screen at the start of the first
491 * server generation.
492 */
493Bool
494ATIPreInit
495(
496    ScrnInfoPtr pScreenInfo,
497    int flags
498)
499{
500    CARD8            BIOS[BIOS_SIZE];
501    unsigned int     BIOSSize = 0;
502    unsigned int     ROMTable = 0, ClockTable = 0, FrequencyTable = 0;
503    unsigned int     LCDTable = 0, VideoTable = 0;
504    unsigned int     HardwareTable = 0;
505
506    char             Buffer[128], *Message;
507    ATIPtr           pATI;
508    GDevPtr          pGDev;
509    EntityInfoPtr    pEntity;
510    resPtr           pResources;
511    pciVideoPtr      pVideo;
512    DisplayModePtr   pMode;
513    CARD32           IOValue;
514    int              i, j;
515    int              Numerator, Denominator;
516    int              MinX, MinY;
517    ClockRange       ATIClockRange = {NULL, 0, 80000, -1, TRUE, TRUE, 1, 1, 0};
518    int              DefaultmaxClock = 0;
519    int              minPitch, maxPitch = 0xFFU, pitchInc, maxHeight = 0;
520    int              ApertureSize = 0x00010000U;
521    int              ModeType = M_T_BUILTIN;
522    LookupModeFlags  Strategy = LOOKUP_CLOSEST_CLOCK;
523    int              DefaultDepth;
524    Bool             PreInitSuccess = FALSE;
525
526#   define           pATIHW     (&pATI->OldHW)
527
528#ifndef AVOID_CPIO
529
530    xf86Int10InfoPtr pInt10Info = NULL;
531    vbeInfoPtr       pVBE = NULL;
532    pointer          pInt10Module, pDDCModule = NULL, pVBEModule = NULL;
533
534#endif /* AVOID_CPIO */
535
536    if (pScreenInfo->numEntities != 1)
537    {
538        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
539            "Logic error:  Number of attached entities not 1.\n");
540        return FALSE;
541    }
542
543    if (!Mach64GetRec(pScreenInfo))
544        return FALSE;
545
546    pATI = ATIPTR(pScreenInfo);
547
548    /* Register resources */
549    pEntity = xf86GetEntityInfo(pScreenInfo->entityList[0]);
550    pGDev = pEntity->device;
551    pResources = pEntity->resources;
552
553    pATI->iEntity = pEntity->index;
554    pATI->Chip = pEntity->chipset;
555    pVideo = xf86GetPciInfoForEntity(pATI->iEntity);
556
557    xfree(pEntity);
558
559    if (!pResources)
560        pResources = xf86RegisterResources(pATI->iEntity, NULL, ResShared);
561    if (pResources)
562    {
563        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
564            "Unable to register the following bus resources:\n");
565        xf86PrintResList(0, pResources);
566        xf86FreeResList(pResources);
567        return FALSE;
568    }
569
570    ConfiguredMonitor = NULL;
571    (void)memset(BIOS, 0, SizeOf(BIOS));
572
573    if (!(flags & PROBE_DETECT))
574    {
575        /* Set monitor */
576        pScreenInfo->monitor = pScreenInfo->confScreen->monitor;
577
578        /* Set depth, bpp, etc. */
579        if ((pATI->Chip < ATI_CHIP_264CT))
580        {
581            i = NoDepth24Support;       /* No support for >8bpp either */
582            DefaultDepth = 8;
583        }
584        else
585        {
586            i = Support24bppFb | Support32bppFb;
587            DefaultDepth = 0;
588        }
589
590        if (!xf86SetDepthBpp(pScreenInfo, DefaultDepth, 0, 0, i))
591            return FALSE;
592
593        for (j = 0;  ;  j++)
594        {
595            static const CARD8 AllowedDepthBpp[][2] =
596            {
597                { 8,  8},
598                {15, 16},
599                {16, 16},
600                {24, 24},
601                {24, 32}
602            };
603
604            if (j < NumberOf(AllowedDepthBpp))
605            {
606                if (pScreenInfo->depth > AllowedDepthBpp[j][0])
607                    continue;
608
609                if (pScreenInfo->depth == AllowedDepthBpp[j][0])
610                {
611                    if (pScreenInfo->bitsPerPixel > AllowedDepthBpp[j][1])
612                        continue;
613
614                    if (pScreenInfo->bitsPerPixel == AllowedDepthBpp[j][1])
615                        break;
616                }
617            }
618
619            xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
620                "Driver does not support depth %d at fbbpp %d.\n",
621                pScreenInfo->depth, pScreenInfo->bitsPerPixel);
622            return FALSE;
623        }
624
625        xf86PrintDepthBpp(pScreenInfo);
626
627        if ((i == NoDepth24Support) && (pScreenInfo->depth > 8))
628        {
629            xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
630                "Depth %d is not supported through this adapter.\n",
631                pScreenInfo->depth);
632            return FALSE;
633        }
634
635        /* Pick up XF86Config options */
636        ATIProcessOptions(pScreenInfo, pATI);
637    }
638
639    if (!ATIMach64ProbeIO(pVideo, pATI))
640        return FALSE;
641
642    ATIClaimBusSlot(pGDev->active, pATI);
643
644#ifndef AVOID_CPIO
645
646#ifdef TV_OUT
647
648    pATI->pVBE = NULL;
649    pATI->pInt10 = NULL;
650
651#endif /* TV_OUT */
652
653    /*
654     * If there is an ix86-style BIOS, ensure its initialisation entry point
655     * has been executed, and retrieve DDC and VBE information from it.
656     */
657    if (!(pInt10Module = xf86LoadSubModule(pScreenInfo, "int10")))
658    {
659        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
660            "Unable to load int10 module.\n");
661    }
662    else if (!(pInt10Info = xf86InitInt10(pATI->iEntity)))
663    {
664        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
665             "Unable to initialise int10 interface.\n");
666    }
667    else
668    {
669        if (!(pDDCModule = xf86LoadSubModule(pScreenInfo, "ddc")))
670        {
671            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
672                "Unable to load ddc module.\n");
673        }
674        else
675        if (!(pVBEModule = xf86LoadSubModule(pScreenInfo, "vbe")))
676        {
677            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
678                "Unable to load vbe module.\n");
679        }
680        else
681        {
682            if ((pVBE = VBEInit(pInt10Info, pATI->iEntity)))
683            {
684                ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule);
685            }
686        }
687
688        if (!(flags & PROBE_DETECT))
689        {
690            /* Validate, then make a private copy of, the initialised BIOS */
691            CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4);
692
693            if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2])
694            {
695                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
696                    "Unable to correctly retrieve adapter BIOS.\n");
697            }
698            else
699            {
700                BIOSSize = pBIOS[2] << 9;
701                if (BIOSSize > BIOS_SIZE)
702                    BIOSSize = BIOS_SIZE;
703                (void)memcpy(BIOS, pBIOS, BIOSSize);
704            }
705        }
706    }
707
708#ifndef TV_OUT
709    /* De-activate VBE */
710    vbeFree(pVBE);
711    xf86UnloadSubModule(pVBEModule);
712
713    /* De-activate int10 */
714    xf86FreeInt10(pInt10Info);
715    xf86UnloadSubModule(pInt10Module);
716#else
717    pATI->pInt10 = pInt10Info;
718    pATI->pVBE = pVBE;
719    pVBE = NULL;
720    pInt10Info = NULL;
721#endif /* TV_OUT */
722
723    if (ConfiguredMonitor && !(flags & PROBE_DETECT))
724    {
725        xf86PrintEDID(ConfiguredMonitor);
726        xf86SetDDCproperties(pScreenInfo, ConfiguredMonitor);
727    }
728
729    /* DDC module is no longer needed at this point */
730    xf86UnloadSubModule(pDDCModule);
731
732#endif /* AVOID_CPIO */
733
734    if (flags & PROBE_DETECT)
735    {
736        return TRUE;
737    }
738
739#ifndef AVOID_CPIO
740
741    /* I/O bases might no longer be valid after BIOS initialisation */
742    {
743        if (pATI->CPIODecoding == BLOCK_IO)
744            pATI->CPIOBase = PCI_REGION_BASE(pVideo, 1, REGION_IO);
745
746        pATI->MMIOInLinear = FALSE;
747
748        /* Set MMIO address from PCI configuration space, if available */
749        if ((pATI->Block0Base = PCI_REGION_BASE(pVideo, 2, REGION_MEM)))
750        {
751            pATI->Block0Base += 0x0400U;
752        }
753    }
754
755#endif /* AVOID_CPIO */
756
757#ifdef AVOID_CPIO
758
759    pScreenInfo->racMemFlags =
760        RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
761
762#else /* AVOID_CPIO */
763
764    pScreenInfo->racIoFlags =
765        RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
766    pScreenInfo->racMemFlags = RAC_FB | RAC_CURSOR;
767
768#endif /* AVOID_CPIO */
769
770    /* Finish private area initialisation */
771    pATI->nFIFOEntries = 16;                    /* For now */
772
773    /* Finish probing the adapter */
774    {
775        /*
776         * For MMIO register access, the MMIO address is computed when probing
777         * and there are no BIOS calls. This mapping should always succeed.
778         *
779         * For CPIO register access, the MMIO address is computed above in the
780         * presence of an auxiliary aperture. Otherwise, it is set to zero and
781         * gets computed when we read the linear aperture configuration. This
782         * mapping is either irrelevant or a no-op.
783         */
784        if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
785            return FALSE;
786
787#ifdef AVOID_CPIO
788
789            if (!pATI->pBlock[0])
790            {
791                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
792                    "Unable to mmap() adapter registers.\n");
793                return FALSE;
794            }
795
796#endif /* AVOID_CPIO */
797
798            /*
799             * Verify register access by comparing against the CONFIG_CHIP_ID
800             * value saved by adapter detection.
801             */
802            if (pATI->config_chip_id != inr(CONFIG_CHIP_ID))
803            {
804                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
805                    "Adapter registers not mapped correctly.\n");
806                ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
807                return FALSE;
808            }
809
810            pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
811            if (!(pATIHW->crtc_gen_cntl & CRTC_EN) &&
812                (pATI->Chip >= ATI_CHIP_264CT))
813            {
814                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
815                    "Adapter has not been initialised.\n");
816                goto bail_locked;
817            }
818
819#ifdef AVOID_CPIO
820
821            if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
822            {
823                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
824                    "Adapters found to be in VGA mode on server entry are not"
825                    " supported by the MMIO-only version of this driver.\n");
826                goto bail_locked;
827            }
828
829#endif /* AVOID_CPIO */
830
831            pATIHW->mem_cntl = inr(MEM_CNTL);
832            if (pATI->Chip < ATI_CHIP_264VTB)
833            {
834                IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE);
835                pATI->VideoRAM = videoRamSizes[IOValue];
836            }
837            else
838            {
839                pATI->nFIFOEntries =            /* Don't care */
840                    (unsigned int)(-1) >> 1;
841
842                IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZEB);
843                if (IOValue < 8)
844                    pATI->VideoRAM = (IOValue + 1) * 512;
845                else if (IOValue < 12)
846                    pATI->VideoRAM = (IOValue - 3) * 1024;
847                else
848                    pATI->VideoRAM = (IOValue - 7) * 2048;
849            }
850
851            IOValue = inr(CONFIG_STATUS64_0);
852            if (pATI->Chip >= ATI_CHIP_264CT)
853            {
854                pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T);
855            }
856            else
857            {
858                pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE);
859            }
860
861            pATI->LCDPanelID = -1;
862
863            if (pATI->Chip >= ATI_CHIP_264CT)
864            {
865                /* Get LCD panel id */
866                if (pATI->Chip == ATI_CHIP_264LT)
867                {
868                    pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
869
870                    pATIHW->horz_stretching = inr(HORZ_STRETCHING);
871                    pATIHW->vert_stretching = inr(VERT_STRETCHING);
872                    pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
873                }
874                else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
875                         (pATI->Chip == ATI_CHIP_264XL) ||
876                         (pATI->Chip == ATI_CHIP_MOBILITY))
877                {
878                    pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
879
880                    pATIHW->lcd_index = inr(LCD_INDEX);
881                    pATIHW->horz_stretching =
882                        ATIMach64GetLCDReg(LCD_HORZ_STRETCHING);
883                    pATI->LCDHorizontal =
884                        GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE);
885                    if (pATI->LCDHorizontal)
886                    {
887                        if (pATI->LCDHorizontal == MaxBits(HORZ_PANEL_SIZE))
888                            pATI->LCDHorizontal = 0;
889                        else
890                            pATI->LCDHorizontal =
891                                (pATI->LCDHorizontal + 1) << 3;
892                    }
893                    pATIHW->ext_vert_stretch =
894                        ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH);
895                    pATI->LCDVertical =
896                        GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE);
897                    if (pATI->LCDVertical)
898                    {
899                        if (pATI->LCDVertical == MaxBits(VERT_PANEL_SIZE))
900                            pATI->LCDVertical = 0;
901                        else
902                            pATI->LCDVertical++;
903                    }
904                    pATIHW->vert_stretching =
905                        ATIMach64GetLCDReg(LCD_VERT_STRETCHING);
906                    pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
907                    outr(LCD_INDEX, pATIHW->lcd_index);
908                }
909
910                /*
911                 * Don't bother with panel support if it hasn't been previously
912                 * enabled.
913                 */
914                if ((pATI->LCDPanelID >= 0) &&
915                    !(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
916                    !(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
917                    !(pATIHW->lcd_gen_ctrl & LCD_ON))
918                {
919                    /*
920                     * At this point, if an XL or Mobility BIOS hasn't set
921                     * panel dimensions, then there is no panel.  Otherwise,
922                     * keep any panel disabled to allow for modes greater than
923                     * the panel's dimensions.
924                     */
925                    if ((pATI->Chip >= ATI_CHIP_264XL) &&
926                        (!pATI->LCDHorizontal || !pATI->LCDVertical))
927                        pATI->LCDPanelID = -1;
928                    else
929                        pATI->OptionPanelDisplay = FALSE;
930                }
931            }
932
933            /* Get DAC type */
934            pATI->DAC = GetBits(inr(DAC_CNTL), DAC_TYPE);
935
936            if (pATI->Chip < ATI_CHIP_264CT)
937            {
938                /* Factor in what the BIOS says the DAC is */
939                pATI->DAC = ATI_DAC(pATI->DAC,
940                    GetBits(inr(SCRATCH_REG1), BIOS_INIT_DAC_SUBTYPE));
941            }
942
943            /*
944             * RAMDAC types 0 & 1 for Mach64's are different than those for
945             * Mach32's.
946             */
947            if (pATI->DAC < ATI_DAC_ATI68875)
948                pATI->DAC += ATI_DAC_INTERNAL;
949    }
950
951    {
952        ROMTable = BIOSWord(0x48U);
953        if ((ROMTable < 0x0002U) ||
954            (BIOSWord(ROMTable - 0x02U) < 0x0012U) ||
955            ((ROMTable + BIOSWord(ROMTable - 0x02U)) > BIOSSize))
956            ROMTable = 0;
957
958        if (ROMTable > 0)
959        {
960            ClockTable = BIOSWord(ROMTable + 0x10U);
961            if ((ClockTable + 0x20U) > BIOSSize)
962                ClockTable = 0;
963
964            if (BIOSWord(ROMTable - 0x02U) >= 0x0048U)
965            {
966                VideoTable = BIOSWord(ROMTable + 0x46U);
967                if ((VideoTable < 0x08U) ||
968                    (BIOSByte(VideoTable - 0x01U) < 0x08U) ||
969                    (BIOSByte(VideoTable - 0x02U) > 0x01U) ||
970                    ((VideoTable + BIOSByte(VideoTable - 0x01U)) > BIOSSize))
971                    VideoTable = 0;
972            }
973
974            if (BIOSWord(ROMTable - 0x02U) >= 0x004AU)
975            {
976                HardwareTable = BIOSWord(ROMTable + 0x48U);
977                if (((HardwareTable + 0x08U) > BIOSSize) ||
978                    (memcmp(BIOS + HardwareTable, "$ATI", 4) != 0))
979                    HardwareTable = 0;
980            }
981        }
982
983        ati_bios_clock(pScreenInfo, pATI, BIOS, ClockTable, pGDev);
984
985        ati_bios_mmedia(pScreenInfo, pATI, BIOS, VideoTable, HardwareTable);
986
987        if (pATI->LCDPanelID >= 0)
988        {
989            LCDTable = BIOSWord(0x78U);
990            if ((LCDTable + BIOSByte(LCDTable + 5)) > BIOSSize)
991                LCDTable = 0;
992
993            ati_bios_panel_info(pScreenInfo, pATI, BIOS, BIOSSize, LCDTable);
994        }
995
996        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
997            "BIOS Data:  BIOSSize=0x%04X, ROMTable=0x%04X.\n",
998            BIOSSize, ROMTable);
999        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
1000            "BIOS Data:  ClockTable=0x%04X, FrequencyTable=0x%04X.\n",
1001            ClockTable, FrequencyTable);
1002        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
1003            "BIOS Data:  LCDTable=0x%04X.\n",
1004            LCDTable);
1005        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
1006            "BIOS Data:  VideoTable=0x%04X, HardwareTable=0x%04X.\n",
1007            VideoTable, HardwareTable);
1008        xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
1009            "BIOS Data:  I2CType=0x%02X, Tuner=0x%02X, Decoder=0x%02X,"
1010            " Audio=0x%02X.\n",
1011            pATI->I2CType, pATI->Tuner, pATI->Decoder, pATI->Audio);
1012    }
1013
1014    ATIUnlock(pATI);            /* Unlock registers */
1015
1016    /* Report what was found */
1017    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1018        "%s graphics controller detected.\n",
1019        xf86TokenToString(Mach64Chipsets, pATI->Chip));
1020
1021    {
1022        Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X",
1023            pATI->ChipType);
1024        if (!(pATI->ChipType & ~(CHIP_CODE_0 | CHIP_CODE_1)))
1025            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
1026                " (%c%c)",
1027                GetBits(pATI->ChipType, CHIP_CODE_1) + 0x41U,
1028                GetBits(pATI->ChipType, CHIP_CODE_0) + 0x41U);
1029        else if ((pATI->ChipType & 0x4040U) == 0x4040U)
1030            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
1031                " \"%c%c\"",
1032                GetByte(pATI->ChipType, 1), GetByte(pATI->ChipType, 0));
1033        if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chip != ATI_CHIP_Mach64))
1034            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
1035                ", version %d, foundry %s",
1036                pATI->ChipVersion, ATIFoundryNames[pATI->ChipFoundry]);
1037        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1038            "%s, class %d, revision 0x%02X.\n",
1039            Buffer, pATI->ChipClass, pATI->ChipRevision);
1040    }
1041
1042    {
1043        Message = Buffer + snprintf(Buffer, SizeOf(Buffer),
1044            "%s bus interface detected", ATIBusNames[pATI->BusType]);
1045
1046#ifndef AVOID_CPIO
1047
1048        {
1049            Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
1050                ";  %s I/O base is 0x%04lX",
1051                (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block",
1052                pATI->CPIOBase);
1053        }
1054
1055#endif /* AVOID_CPIO */
1056
1057        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
1058    }
1059
1060#ifndef AVOID_CPIO
1061
1062    if (pATI->CPIO_VGAWonder)
1063        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1064            "VGA Wonder registers at I/O port 0x%04lX.\n",
1065            pATI->CPIO_VGAWonder);
1066
1067#endif /* AVOID_CPIO */
1068
1069    xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1070        "ATI Mach64 adapter detected.\n");
1071
1072    if (pATI->Chip >= ATI_CHIP_264GT)
1073        xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
1074            "For information on using the multimedia capabilities\n\tof this"
1075            " adapter, please see http://gatos.sf.net.\n");
1076
1077    if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
1078    {
1079        xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1080            "Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU);
1081    }
1082    else
1083    {
1084        const SymTabRec *DAC;
1085
1086        for (DAC = ATIDACDescriptors;  ;  DAC++)
1087        {
1088            if (pATI->DAC == DAC->token)
1089            {
1090                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1091                    "%s RAMDAC detected.\n", DAC->name);
1092                break;
1093            }
1094
1095            if (pATI->DAC < DAC->token)
1096            {
1097                xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
1098                    "Unknown RAMDAC type 0x%02X detected.\n", pATI->DAC);
1099                break;
1100            }
1101        }
1102    }
1103
1104    if (!xf86LinearVidMem())
1105    {
1106        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1107            "A linear aperture is not available.\n");
1108        goto bail;
1109    }
1110
1111    /*
1112     * Set colour weights.
1113     */
1114
1115    if (pATI->Chip < ATI_CHIP_264CT)
1116        pScreenInfo->rgbBits = 6;
1117    else
1118        pScreenInfo->rgbBits = 8;
1119    pATI->rgbBits = pScreenInfo->rgbBits;
1120    if (!xf86SetWeight(pScreenInfo, defaultWeight, defaultWeight))
1121        goto bail;
1122
1123    if ((pScreenInfo->depth > 8) &&
1124        ((pScreenInfo->weight.red != pScreenInfo->weight.blue) ||
1125         (pScreenInfo->weight.red != (CARD32)(pScreenInfo->depth / 3)) ||
1126         ((CARD32)pScreenInfo->depth != (pScreenInfo->weight.red +
1127                                         pScreenInfo->weight.green +
1128                                         pScreenInfo->weight.blue))))
1129    {
1130        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1131            "Driver does not support weight %d%d%d for depth %d.\n",
1132            (int)pScreenInfo->weight.red, (int)pScreenInfo->weight.green,
1133            (int)pScreenInfo->weight.blue, pScreenInfo->depth);
1134        goto bail;
1135    }
1136
1137    /*
1138     * Set default visual.
1139     */
1140
1141    if (!xf86SetDefaultVisual(pScreenInfo, -1))
1142        goto bail;
1143
1144    if ((pScreenInfo->depth > 8) &&
1145        (((pScreenInfo->defaultVisual | DynamicClass) != DirectColor) ||
1146         ((pScreenInfo->defaultVisual == DirectColor) &&
1147          (pATI->DAC == ATI_DAC_INTERNAL))))
1148    {
1149        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1150            "Driver does not support default visual %s for depth %d.\n",
1151            xf86GetVisualName(pScreenInfo->defaultVisual),
1152            pScreenInfo->depth);
1153        goto bail;
1154    }
1155
1156    /*
1157     * Set colour gamma.
1158     */
1159
1160    if (!xf86SetGamma(pScreenInfo, defaultGamma))
1161        goto bail;
1162
1163    pATI->depth = pScreenInfo->depth;
1164    pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
1165    pATI->weight = pScreenInfo->weight;
1166    pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
1167
1168    /*
1169     * Determine which CRT controller to use for video modes.
1170     */
1171
1172    {
1173        pATI->NewHW.crtc = ATI_CRTC_MACH64;
1174
1175        xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1176            "Using Mach64 accelerator CRTC.\n");
1177
1178#ifndef AVOID_CPIO
1179
1180        if (pATI->VGAAdapter)
1181        {
1182            /*
1183             * No need for VGA I/O resources during operating state (but they
1184             * are still decoded).
1185             */
1186            pResources =
1187                xf86SetOperatingState(resVgaIo, pATI->iEntity, ResUnusedOpr);
1188            if (pResources)
1189            {
1190                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
1191                    "Logic error setting operating state for VGA I/O.\n");
1192                xf86FreeResList(pResources);
1193            }
1194
1195            if (pATI->CPIO_VGAWonder)
1196            {
1197                pResources = xf86SetOperatingState(pATI->VGAWonderResources,
1198                    pATI->iEntity, ResUnusedOpr);
1199                if (pResources)
1200                {
1201                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
1202                        "Logic error setting operating state for"
1203                        " VGAWonder I/O.\n");
1204                    xf86FreeResList(pResources);
1205                }
1206            }
1207        }
1208
1209#endif /* AVOID_CPIO */
1210
1211    }
1212
1213    /*
1214     * Decide between the CRT and the panel.
1215     */
1216    if (pATI->LCDPanelID >= 0)
1217    {
1218        if (!pATI->OptionPanelDisplay)
1219        {
1220            xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
1221                "Using CRT interface and disabling digital flat panel.\n");
1222        }
1223        else
1224        {
1225            unsigned HDisplay, VDisplay;
1226            CARD8 ClockMask, PostMask;
1227
1228            /*
1229             * Determine porch data.  This groks the mode on entry to extract
1230             * the width and position of its sync and blanking pulses, and
1231             * considers any overscan as part of the displayed area, given that
1232             * the overscan is also stretched.
1233             *
1234             * This also attempts to determine panel dimensions but cannot do
1235             * so for one that is "auto-stretched".
1236             */
1237
1238            if (pATI->Chip == ATI_CHIP_264LT)
1239            {
1240                pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
1241
1242                /* Set up to read non-shadow registers */
1243                if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
1244                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
1245            }
1246            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
1247                        (pATI->Chip == ATI_CHIP_264XL) ||
1248                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
1249            {
1250                pATIHW->lcd_index = inr(LCD_INDEX);
1251                pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL);
1252                pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
1253
1254                /* Set up to read non-shadow registers */
1255                if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
1256                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
1257                        pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
1258            }
1259
1260#ifndef AVOID_CPIO
1261
1262            if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
1263            {
1264                unsigned HBlankStart, HSyncStart, HSyncEnd, HBlankEnd, HTotal;
1265                unsigned VBlankStart, VSyncStart, VSyncEnd, VBlankEnd, VTotal;
1266
1267                pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2;
1268
1269                pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
1270                pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
1271                pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
1272                pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
1273                pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
1274                pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
1275                pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
1276
1277                pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
1278                pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
1279                pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
1280                pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
1281
1282                /* Switch to shadow registers */
1283                if (pATI->Chip == ATI_CHIP_264LT)
1284                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
1285                else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
1286                            (pATI->Chip == ATI_CHIP_264XL) ||
1287                            (pATI->Chip == ATI_CHIP_MOBILITY)) */
1288                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
1289                        pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
1290
1291                pATIHW->shadow_vga[2] =
1292                    GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
1293                pATIHW->shadow_vga[3] =
1294                    GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
1295                pATIHW->shadow_vga[5] =
1296                    GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
1297                pATIHW->shadow_vga[7] =
1298                    GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
1299                pATIHW->shadow_vga[9] =
1300                    GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
1301                pATIHW->shadow_vga[21] =
1302                    GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
1303                pATIHW->shadow_vga[22] =
1304                    GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
1305
1306                pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
1307                pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
1308                pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
1309                pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
1310
1311                /*
1312                 * HSyncStart and HSyncEnd should equal their shadow
1313                 * counterparts.  Otherwise, due to a chip bug, the panel might
1314                 * not sync, regardless of which register set is used to drive
1315                 * the panel.  There are certain combinations of register
1316                 * values where the panel does in fact sync, but it remains
1317                 * impossible to accurately determine the horizontal sync pulse
1318                 * timing actually seen by the panel.
1319                 *
1320                 * Note that this hardware bug does not affect the CRT output.
1321                 */
1322                if (((pATIHW->crtc_h_sync_strt_wid ^
1323                      pATIHW->shadow_h_sync_strt_wid) &
1324                     (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
1325                      CRTC_H_SYNC_WID)))
1326                {
1327                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
1328                        "Invalid horizontal sync pulse timing detected in mode"
1329                        " on server entry.\n");
1330
1331                    /* Don't trust input timing */
1332                    pATI->OptionLCDSync = TRUE;
1333                    ModeType = 0;
1334                }
1335
1336                /* Merge in shadow registers as appropriate */
1337                if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
1338                {
1339                    pATIHW->crt[2] = pATIHW->shadow_vga[2];
1340                    pATIHW->crt[3] = pATIHW->shadow_vga[3];
1341                    pATIHW->crt[5] = pATIHW->shadow_vga[5];
1342
1343                    /* XXX Does this apply to VGA?  If so, what about the LT? */
1344                    if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
1345                        !(pATIHW->config_panel & DONT_SHADOW_HEND))
1346                    {
1347                        pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
1348                        pATIHW->crtc_h_total_disp |=
1349                            pATIHW->shadow_h_total_disp & CRTC_H_DISP;
1350                    }
1351
1352                    pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
1353                    pATIHW->crtc_h_total_disp |=
1354                        pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
1355                    pATIHW->crtc_h_sync_strt_wid =
1356                        pATIHW->shadow_h_sync_strt_wid;
1357
1358                    /* XXX Does this apply to VGA? */
1359                    if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
1360                    {
1361                        pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
1362                        pATIHW->crtc_v_total_disp |=
1363                            pATIHW->shadow_v_total_disp & CRTC_V_DISP;
1364                    }
1365
1366                    if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
1367                    {
1368                        pATIHW->crt[7] = pATIHW->shadow_vga[7];
1369                        pATIHW->crt[9] = pATIHW->shadow_vga[9];
1370                        pATIHW->crt[21] = pATIHW->shadow_vga[21];
1371                        pATIHW->crt[22] = pATIHW->shadow_vga[22];
1372
1373                        pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
1374                        pATIHW->crtc_v_total_disp |=
1375                            pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
1376                    }
1377                }
1378
1379                if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
1380                    pATIHW->crtc_v_sync_strt_wid =
1381                        pATIHW->shadow_v_sync_strt_wid;
1382
1383                /*
1384                 * Decipher input timing.  This is complicated by the fact that
1385                 * the full width of all timing parameters, except for the
1386                 * blanking pulses, is only available through the accelerator
1387                 * registers, not the VGA ones.  Blanking pulse boundaries must
1388                 * then be interpolated.
1389                 *
1390                 * Note that, in VGA mode, the accelerator's sync width fields
1391                 * are actually end positions, not widths.
1392                 */
1393                HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP);
1394                HSyncStart =
1395                    (GetBits(pATIHW->crtc_h_sync_strt_wid,
1396                        CRTC_H_SYNC_STRT_HI) *
1397                     (MaxBits(CRTC_H_SYNC_STRT) + 1)) |
1398                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT);
1399                HSyncEnd = (HSyncStart & ~MaxBits(CRTC_H_SYNC_WID)) |
1400                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
1401                if (HSyncStart >= HSyncEnd)
1402                    HSyncEnd += MaxBits(CRTC_H_SYNC_WID) + 1;
1403                HTotal = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL);
1404
1405                HBlankStart = (HDisplay & ~0xFFU) | pATIHW->crt[2];
1406                if (HDisplay > HBlankStart)
1407                    HBlankStart += 0x0100U;
1408                HBlankEnd = (HSyncEnd & ~0x3FU) |
1409                    ((pATIHW->crt[5] >> 2) & 0x20U) |
1410                    (pATIHW->crt[3] & 0x1FU);
1411                if (HSyncEnd > (HBlankEnd + 1))
1412                    HBlankEnd += 0x40U;
1413
1414                VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP);
1415                VSyncStart =
1416                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT);
1417                VSyncEnd = (VSyncStart & ~MaxBits(CRTC_V_SYNC_END_VGA)) |
1418                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_END_VGA);
1419                if (VSyncStart > VSyncEnd)
1420                    VSyncEnd += MaxBits(CRTC_V_SYNC_END_VGA) + 1;
1421                VTotal = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL);
1422
1423                VBlankStart = (VDisplay & ~0x03FFU) |
1424                   ((pATIHW->crt[9] << 4) & 0x0200U) |
1425                   ((pATIHW->crt[7] << 5) & 0x0100U) | pATIHW->crt[21];
1426                if (VDisplay > VBlankStart)
1427                   VBlankStart += 0x0400U;
1428                VBlankEnd = (VSyncEnd & ~0x00FFU) | pATIHW->crt[22];
1429                if (VSyncEnd > (VBlankEnd + 1))
1430                   VBlankEnd += 0x0100U;
1431
1432                pATI->LCDHBlankWidth = HBlankEnd - HBlankStart;
1433                pATI->LCDHSyncStart = HSyncStart - HBlankStart;
1434                pATI->LCDHSyncWidth = HSyncEnd - HSyncStart;
1435
1436                pATI->LCDVBlankWidth = VBlankEnd - VBlankStart;
1437                pATI->LCDVSyncStart = VSyncStart - VBlankStart;
1438                pATI->LCDVSyncWidth = VSyncEnd - VSyncStart;
1439
1440                HDisplay = HTotal + 5 - pATI->LCDHBlankWidth;
1441                VDisplay = VTotal + 2 - pATI->LCDVBlankWidth;
1442            }
1443            else
1444
1445#endif /* AVOID_CPIO */
1446
1447            {
1448                pATIHW->clock = inr(CLOCK_CNTL) & 0x03U;
1449
1450                pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
1451                pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
1452                pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
1453                pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
1454                pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
1455                pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
1456
1457                /* Switch to shadow registers */
1458                if (pATI->Chip == ATI_CHIP_264LT)
1459                    outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
1460                else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
1461                            (pATI->Chip == ATI_CHIP_264XL) ||
1462                            (pATI->Chip == ATI_CHIP_MOBILITY)) */
1463                    ATIMach64PutLCDReg(LCD_GEN_CNTL,
1464                        pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
1465
1466                /* Oddly enough, there are no shadow overscan registers */
1467                pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
1468                pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
1469                pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
1470                pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
1471
1472                /*
1473                 * HSyncStart and HSyncEnd should equal their shadow
1474                 * counterparts.  Otherwise, due to a chip bug, the panel might
1475                 * not sync, regardless of which register set is used to drive
1476                 * the panel.  There are certain combinations of register
1477                 * values where the panel does in fact sync, but it remains
1478                 * impossible to accurately determine the horizontal sync pulse
1479                 * timing actually seen by the panel.
1480                 *
1481                 * Note that this hardware bug does not affect the CRT output.
1482                 */
1483                if (((pATIHW->crtc_h_sync_strt_wid ^
1484                      pATIHW->shadow_h_sync_strt_wid) &
1485                     (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
1486                      CRTC_H_SYNC_WID)))
1487                {
1488                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
1489                        "Invalid horizontal sync pulse timing detected in mode"
1490                        " on server entry.\n");
1491
1492                    /* Don't trust input timing */
1493                    pATI->OptionLCDSync = TRUE;
1494                    ModeType = 0;
1495                }
1496
1497                /* Merge in shadow registers as appropriate */
1498                if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
1499                {
1500                    /* XXX What about the LT? */
1501                    if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
1502                        !(pATIHW->config_panel & DONT_SHADOW_HEND))
1503                    {
1504                        pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
1505                        pATIHW->crtc_h_total_disp |=
1506                            pATIHW->shadow_h_total_disp & CRTC_H_DISP;
1507                    }
1508
1509                    pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
1510                    pATIHW->crtc_h_total_disp |=
1511                        pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
1512                    pATIHW->crtc_h_sync_strt_wid =
1513                        pATIHW->shadow_h_sync_strt_wid;
1514
1515                    if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
1516                    {
1517                        pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
1518                        pATIHW->crtc_v_total_disp |=
1519                            pATIHW->shadow_v_total_disp & CRTC_V_DISP;
1520                    }
1521
1522                    if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
1523                    {
1524                        pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
1525                        pATIHW->crtc_v_total_disp |=
1526                            pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
1527                    }
1528                }
1529
1530                if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
1531                    pATIHW->crtc_v_sync_strt_wid =
1532                        pATIHW->shadow_v_sync_strt_wid;
1533
1534                /* Decipher input timing */
1535                HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) +
1536                    GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) +
1537                    GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT);
1538                VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP) +
1539                    GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_TOP) +
1540                    GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_BOTTOM);
1541
1542                pATI->LCDHSyncStart =
1543                    (GetBits(pATIHW->crtc_h_sync_strt_wid,
1544                        CRTC_H_SYNC_STRT_HI) *
1545                     (MaxBits(CRTC_H_SYNC_STRT) + 1)) +
1546                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT) -
1547                    HDisplay;
1548                pATI->LCDHSyncWidth =
1549                    GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
1550                pATI->LCDHBlankWidth =
1551                    GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL) -
1552                    HDisplay;
1553                pATI->LCDVSyncStart =
1554                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT) -
1555                    VDisplay;
1556                pATI->LCDVSyncWidth =
1557                    GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID);
1558                pATI->LCDVBlankWidth =
1559                    GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL) -
1560                    VDisplay;
1561
1562                HDisplay++;
1563                VDisplay++;
1564            }
1565
1566            /* Restore LCD registers */
1567            if (pATI->Chip == ATI_CHIP_264LT)
1568            {
1569                outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl);
1570            }
1571            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
1572                        (pATI->Chip == ATI_CHIP_264XL) ||
1573                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
1574            {
1575                ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl);
1576                outr(LCD_INDEX, pATIHW->lcd_index);
1577            }
1578
1579            HDisplay <<= 3;
1580            pATI->LCDHSyncStart <<= 3;
1581            pATI->LCDHSyncWidth <<= 3;
1582            pATI->LCDHBlankWidth <<= 3;
1583
1584            /* Calculate panel dimensions implied by the input timing */
1585            if ((pATIHW->horz_stretching &
1586                 (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) ==
1587                HORZ_STRETCH_EN)
1588            {
1589                if (pATIHW->horz_stretching & HORZ_STRETCH_MODE)
1590                {
1591                    if (pATIHW->horz_stretching & HORZ_STRETCH_BLEND)
1592                    {
1593                        HDisplay =
1594                            (HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) /
1595                            GetBits(pATIHW->horz_stretching,
1596                                HORZ_STRETCH_BLEND);
1597                    }
1598                }
1599                else if (((pATIHW->horz_stretching & HORZ_STRETCH_LOOP) >
1600                          HORZ_STRETCH_LOOP15) ||
1601                         (pATIHW->horz_stretching &
1602                          SetBits(1, HORZ_STRETCH_RATIO)))
1603                {
1604                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
1605                        "Ignoring invalid horizontal stretch ratio in mode on"
1606                        " server entry.\n");
1607                }
1608                else
1609                {
1610                    IOValue =
1611                        GetBits(pATIHW->horz_stretching, HORZ_STRETCH_RATIO);
1612
1613                    switch (GetBits(pATIHW->horz_stretching,
1614                                    HORZ_STRETCH_LOOP))
1615                    {
1616                        case GetBits(HORZ_STRETCH_LOOP09, HORZ_STRETCH_LOOP):
1617                            i = 9;
1618                            IOValue &= (1 << 9) - 1;
1619                            break;
1620
1621                        case GetBits(HORZ_STRETCH_LOOP11, HORZ_STRETCH_LOOP):
1622                            i = 11;
1623                            IOValue &= (1 << 11) - 1;
1624                            break;
1625
1626                        case GetBits(HORZ_STRETCH_LOOP12, HORZ_STRETCH_LOOP):
1627                            i = 12;
1628                            IOValue &= (1 << 12) - 1;
1629                            break;
1630
1631                        case GetBits(HORZ_STRETCH_LOOP14, HORZ_STRETCH_LOOP):
1632                            i = 14;
1633                            IOValue &= (1 << 14) - 1;
1634                            break;
1635
1636                        case GetBits(HORZ_STRETCH_LOOP15, HORZ_STRETCH_LOOP):
1637                        default:    /* Muffle compiler */
1638                            i = 15;
1639                            IOValue &= (1 << 15) - 1;
1640                            break;
1641                    }
1642
1643                    if (IOValue)
1644                    {
1645                        /* Count the number of bits in IOValue */
1646                        j = (IOValue >> 1) & 0x36DBU;
1647                        j = IOValue - j - ((j >> 1) & 0x36DBU);
1648                        j = ((j + (j >> 3)) & 0x71C7U) % 0x3FU;
1649
1650                        HDisplay = (HDisplay * i) / j;
1651                    }
1652                }
1653            }
1654
1655            if ((pATIHW->vert_stretching & VERT_STRETCH_EN) &&
1656                !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
1657            {
1658                if ((pATIHW->vert_stretching & VERT_STRETCH_USE0) ||
1659                    (VDisplay <= 350))
1660                    IOValue =
1661                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO0);
1662                else if (VDisplay <= 400)
1663                    IOValue =
1664                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO1);
1665                else if ((VDisplay <= 480) ||
1666                         !(pATIHW->ext_vert_stretch & VERT_STRETCH_RATIO3))
1667                    IOValue =
1668                        GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO2);
1669                else
1670                    IOValue =
1671                        GetBits(pATIHW->ext_vert_stretch, VERT_STRETCH_RATIO3);
1672
1673                if (IOValue)
1674                    VDisplay =
1675                        (VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) /
1676                        IOValue;
1677            }
1678
1679            /* Match calculated dimensions to probed dimensions */
1680            if (!pATI->LCDHorizontal)
1681            {
1682                if ((pATIHW->horz_stretching &
1683                     (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
1684                     (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
1685                    pATI->LCDHorizontal = HDisplay;
1686            }
1687            else if (pATI->LCDHorizontal != (int)HDisplay)
1688            {
1689                if ((pATIHW->horz_stretching &
1690                    (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
1691                    (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
1692                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4,
1693                        "Inconsistent panel horizontal dimension:"
1694                        "  %d and %d.\n", pATI->LCDHorizontal, HDisplay);
1695                HDisplay = pATI->LCDHorizontal;
1696            }
1697
1698            if (!pATI->LCDVertical)
1699            {
1700                if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
1701                    !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
1702                    pATI->LCDVertical = VDisplay;
1703            }
1704            else if (pATI->LCDVertical != (int)VDisplay)
1705            {
1706                if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
1707                    !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
1708                    xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4,
1709                        "Inconsistent panel vertical dimension:  %d and %d.\n",
1710                        pATI->LCDVertical, VDisplay);
1711                VDisplay = pATI->LCDVertical;
1712            }
1713
1714            if (!pATI->LCDHorizontal || !pATI->LCDVertical)
1715            {
1716                if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
1717                    xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1718                        "Unable to determine dimensions of panel (ID %d).\n",
1719                        pATI->LCDPanelID);
1720                else
1721                    xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1722                        "Unable to determine dimensions of panel.\n");
1723
1724                goto bail;
1725            }
1726
1727            /* If the mode on entry wasn't stretched, adjust timings */
1728            if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
1729                (pATI->LCDHorizontal > (int)HDisplay))
1730            {
1731                HDisplay = pATI->LCDHorizontal - HDisplay;
1732                if (pATI->LCDHSyncStart >= HDisplay)
1733                    pATI->LCDHSyncStart -= HDisplay;
1734                else
1735                    pATI->LCDHSyncStart = 0;
1736                pATI->LCDHBlankWidth -= HDisplay;
1737                HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth;
1738                if (pATI->LCDHBlankWidth < HDisplay)
1739                    pATI->LCDHBlankWidth = HDisplay;
1740            }
1741
1742            if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
1743                (pATI->LCDVertical > (int)VDisplay))
1744            {
1745                VDisplay = pATI->LCDVertical - VDisplay;
1746                if (pATI->LCDVSyncStart >= VDisplay)
1747                    pATI->LCDVSyncStart -= VDisplay;
1748                else
1749                    pATI->LCDVSyncStart = 0;
1750                pATI->LCDVBlankWidth -= VDisplay;
1751                VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth;
1752                if (pATI->LCDVBlankWidth < VDisplay)
1753                    pATI->LCDVBlankWidth = VDisplay;
1754            }
1755
1756            if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
1757                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1758                    "%dx%d panel (ID %d) detected.\n",
1759                    pATI->LCDHorizontal, pATI->LCDVertical, pATI->LCDPanelID);
1760            else
1761                xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1762                    "%dx%d panel detected.\n",
1763                    pATI->LCDHorizontal, pATI->LCDVertical);
1764
1765            /*
1766             * Determine panel clock.  This must be done after option
1767             * processing so that the adapter's reference frequency is always
1768             * available.
1769             *
1770             * Get post divider.  A GCC bug has caused the following expression
1771             * to be broken down into its individual components.
1772             */
1773            ClockMask = PLL_VCLK0_XDIV << pATIHW->clock;
1774            PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2);
1775            i = GetBits(ATIMach64GetPLLReg(PLL_XCLK_CNTL), ClockMask);
1776            i *= MaxBits(PLL_VCLK0_POST_DIV) + 1;
1777            i |= GetBits(ATIMach64GetPLLReg(PLL_VCLK_POST_DIV), PostMask);
1778
1779            /* Calculate clock of mode on entry */
1780            Numerator = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) *
1781                pATI->ReferenceNumerator;
1782            Denominator = pATI->ClockDescriptor.MinM *
1783                pATI->ReferenceDenominator *
1784                pATI->ClockDescriptor.PostDividers[i];
1785            pATI->LCDClock = ATIDivide(Numerator, Denominator, 1, 0);
1786
1787            xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
1788                "Panel clock is %.3f MHz.\n",
1789                (double)(pATI->LCDClock) / 1000.0);
1790
1791            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1792                "Using digital flat panel interface%s.\n",
1793                pATI->OptionCRTDisplay ?
1794                    " to display on both CRT and panel" : "");
1795        }
1796    }
1797
1798    /*
1799     * Finish detecting video RAM size.
1800     */
1801    pScreenInfo->videoRam = pATI->VideoRAM;
1802
1803    {
1804        {
1805            /* Get adapter's linear aperture configuration */
1806            pATIHW->config_cntl = inr(CONFIG_CNTL);
1807            pATI->LinearBase =
1808                GetBits(pATIHW->config_cntl, CFG_MEM_AP_LOC) << 22;
1809            if ((pATIHW->config_cntl & CFG_MEM_AP_SIZE) != CFG_MEM_AP_SIZE)
1810            {
1811                pATI->LinearSize =
1812                    GetBits(pATIHW->config_cntl, CFG_MEM_AP_SIZE) << 22;
1813
1814                /*
1815                 * Linear aperture could have been disabled (but still
1816                 * assigned) by BIOS initialisation.
1817                 */
1818                if (pATI->LinearBase && !pATI->LinearSize)
1819                {
1820                    if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
1821                        (pATI->VideoRAM < 4096))
1822                        pATI->LinearSize = 4 * 1024 * 1024;
1823                    else
1824                        pATI->LinearSize = 8 * 1024 * 1024;
1825                }
1826            }
1827
1828            if (pATI->LinearBase && pATI->LinearSize)
1829            {
1830                int AcceleratorVideoRAM = 0, ServerVideoRAM;
1831
1832#ifndef AVOID_CPIO
1833
1834                /*
1835                 * Unless specified in PCI configuration space, set MMIO
1836                 * address to tail end of linear aperture.
1837                 */
1838                if (!pATI->Block0Base)
1839                {
1840                    pATI->Block0Base =
1841                        pATI->LinearBase + pATI->LinearSize - 0x00000400U;
1842                    pATI->MMIOInLinear = TRUE;
1843                }
1844
1845#endif /* AVOID_CPIO */
1846
1847                AcceleratorVideoRAM = pATI->LinearSize >> 10;
1848
1849                /*
1850                 * Account for MMIO area at the tail end of the linear
1851                 * aperture, if it is needed or if it cannot be disabled.
1852                 */
1853                if (pATI->MMIOInLinear || (pATI->Chip < ATI_CHIP_264VTB))
1854                    AcceleratorVideoRAM -= 2;
1855
1856                ServerVideoRAM = pATI->VideoRAM;
1857
1858                if (pATI->Cursor > ATI_CURSOR_SOFTWARE)
1859                {
1860                    /*
1861                     * Allocate a 1 kB cursor image area at the top of the
1862                     * little-endian aperture, just before any MMIO area that
1863                     * might also be there.
1864                     */
1865                    if (ServerVideoRAM > AcceleratorVideoRAM)
1866                        ServerVideoRAM = AcceleratorVideoRAM;
1867
1868                    ServerVideoRAM--;
1869                    pATI->CursorOffset = ServerVideoRAM << 10;
1870                    pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset;
1871
1872                    xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1873                        "Storing hardware cursor image at 0x%08lX.\n",
1874                        pATI->CursorBase);
1875                }
1876
1877                {
1878                    CARD32 PageSize = getpagesize() >> 10;
1879
1880#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1881
1882                    /*
1883                     * MMIO areas must be mmap()'ed separately to avoid write
1884                     * combining them.  Thus, they might not end up still
1885                     * adjacent with the little-endian linear aperture after
1886                     * mmap()'ing.  So, round down the linear aperture size to
1887                     * avoid an overlap.  Any hardware cursor image area might
1888                     * not end up being write combined, but this seems
1889                     * preferable to further reducing the video memory size
1890                     * advertised to the server.
1891                     *
1892                     * XXX Ideally this should be dealt with in the os-support
1893                     *     layer, i.e., it should be possible to reset a
1894                     *     subarea's write combining after it has been
1895                     *     mmap()'ed, but doing so currently causes the removal
1896                     *     of write combining for the entire aperture.
1897                     */
1898                    if (pATI->MMIOInLinear)
1899                        AcceleratorVideoRAM -= AcceleratorVideoRAM % PageSize;
1900
1901#else /* if X_BYTE_ORDER != X_LITTLE_ENDIAN */
1902
1903                    /*
1904                     * Big-endian apertures are 8 MB higher and don't contain
1905                     * an MMIO area.
1906                     */
1907                    pATI->LinearBase += 0x00800000U;
1908                    AcceleratorVideoRAM = pATI->LinearSize >> 10;
1909
1910#endif /* X_BYTE_ORDER */
1911
1912                    if (ServerVideoRAM > AcceleratorVideoRAM)
1913                        ServerVideoRAM = AcceleratorVideoRAM;
1914                    else if (AcceleratorVideoRAM > pATI->VideoRAM)
1915                        AcceleratorVideoRAM = pATI->VideoRAM;
1916
1917                    PageSize--;
1918                    AcceleratorVideoRAM =
1919                        (AcceleratorVideoRAM + PageSize) & ~PageSize;
1920
1921                    xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1922                        "Using %d MB linear aperture at 0x%08lX.\n",
1923                        pATI->LinearSize >> 20, pATI->LinearBase);
1924
1925                    /* Only mmap what is needed */
1926                    ApertureSize = pATI->LinearSize =
1927                        AcceleratorVideoRAM << 10;
1928                }
1929
1930                if (ServerVideoRAM < pATI->VideoRAM)
1931                {
1932                    pScreenInfo->videoRam = ServerVideoRAM;
1933                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
1934                        "Virtual resolutions will be limited to %d kB\n due to"
1935                        " linear aperture size and/or placement of hardware"
1936                        " cursor image area.\n",
1937                        ServerVideoRAM);
1938                }
1939            }
1940        }
1941
1942        if (!pATI->LinearBase || !pATI->LinearSize)
1943        {
1944                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1945                    "Linear aperture not available.\n");
1946                goto bail;
1947        }
1948
1949        if (pATI->Block0Base)
1950        {
1951            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1952                "Using Block 0 MMIO aperture at 0x%08lX.\n", pATI->Block0Base);
1953
1954            /* Set Block1 MMIO address if supported */
1955            if (pATI->Chip >= ATI_CHIP_264VT)
1956            {
1957                pATI->Block1Base = pATI->Block0Base - 0x00000400U;
1958                xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1959                    "Using Block 1 MMIO aperture at 0x%08lX.\n",
1960                    pATI->Block1Base);
1961            }
1962        }
1963    }
1964
1965#ifndef AVOID_CPIO
1966
1967        if (pATI->VGAAdapter)
1968        {
1969            /*
1970             * Free VGA memory aperture during operating state (but it is still
1971             * decoded).
1972             */
1973            pResources = xf86SetOperatingState(resVgaMem, pATI->iEntity,
1974                ResUnusedOpr);
1975            if (pResources)
1976            {
1977                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
1978                    "Logic error setting operating state for VGA memory"
1979                    " aperture.\n");
1980                xf86FreeResList(pResources);
1981            }
1982        }
1983
1984#endif /* AVOID_CPIO */
1985
1986    /*
1987     * Remap apertures.  Must lock and re-unlock around this in case the
1988     * remapping fails.
1989     */
1990    ATILock(pATI);
1991    ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
1992    if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
1993        return FALSE;
1994
1995    ATIUnlock(pATI);
1996
1997    if (pATI->OptionAccel)
1998    {
1999            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
2000                "MMIO write caching %sabled.\n",
2001                pATI->OptionMMIOCache ? "en" : "dis");
2002    }
2003
2004    {
2005        if (pATI->Chip >= ATI_CHIP_264CT)
2006            ATIReportMemory(pScreenInfo, pATI,
2007                ATIMemoryTypeNames_264xT[pATI->MemoryType]);
2008        else if (pATI->Chip == ATI_CHIP_88800CX)
2009            ATIReportMemory(pScreenInfo, pATI,
2010                ATIMemoryTypeNames_88800CX[pATI->MemoryType]);
2011        else
2012            ATIReportMemory(pScreenInfo, pATI,
2013                ATIMemoryTypeNames_Mach[pATI->MemoryType]);
2014    }
2015
2016    /*
2017     * Finish banking setup.  This needs to be fixed to not assume the mode on
2018     * entry is a VGA mode.  XXX
2019     */
2020
2021#ifndef AVOID_CPIO
2022
2023    if (!pATI->VGAAdapter)
2024    {
2025        pATI->NewHW.SetBank = ATIx8800SetBank;
2026        pATI->NewHW.nPlane = 0;
2027
2028        pATIHW->crtc = pATI->NewHW.crtc;
2029
2030        pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
2031    }
2032    else
2033    {
2034        Bool ext_disp_en = (pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN);
2035        Bool vga_ap_en = (pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN);
2036        Bool vga_color_256 = (GetReg(SEQX, 0x04U) & 0x08U);
2037
2038        pATI->NewHW.SetBank = ATIMach64SetBankPacked;
2039        pATI->NewHW.nPlane = 1;
2040
2041        pATIHW->crtc = ATI_CRTC_VGA;
2042
2043        if (ext_disp_en)
2044            pATIHW->crtc = ATI_CRTC_MACH64;
2045
2046        if ((pATIHW->crtc != ATI_CRTC_VGA) || vga_color_256)
2047            pATIHW->nPlane = 1;
2048        else
2049            pATIHW->nPlane = 4;
2050
2051        /* VideoRAM is a multiple of 512kB and BankSize is 64kB */
2052        pATIHW->nBank = pATI->VideoRAM / (pATIHW->nPlane * 0x40U);
2053
2054        if ((pATIHW->crtc == ATI_CRTC_VGA) && !vga_ap_en)
2055        {
2056            pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
2057            pATIHW->nBank = 1;
2058        }
2059        else if (pATIHW->nPlane == 1)
2060        {
2061            pATIHW->SetBank = ATIMach64SetBankPacked;
2062        }
2063        else
2064        {
2065            pATIHW->SetBank = ATIMach64SetBankPlanar;
2066        }
2067    }
2068
2069#else /* AVOID_CPIO */
2070
2071    {
2072        pATIHW->crtc = pATI->NewHW.crtc;
2073    }
2074
2075#endif /* AVOID_CPIO */
2076
2077    if (pATI->OptionShadowFB)
2078    {
2079        /* Until ShadowFB becomes a true screen wrapper, if it ever does... */
2080
2081        if (pATI->OptionAccel)
2082        {
2083            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
2084                "Cannot shadow an accelerated frame buffer.\n");
2085            pATI->OptionShadowFB = FALSE;
2086        }
2087        else
2088        {
2089            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
2090                "Using shadow frame buffer.\n");
2091        }
2092    }
2093
2094    /* 264VT-B's and later have DSP registers */
2095    if ((pATI->Chip >= ATI_CHIP_264VTB) &&
2096        !ATIDSPPreInit(pScreenInfo->scrnIndex, pATI))
2097        goto bail;
2098
2099    /*
2100     * Determine minClock and maxClock.  For adapters with supported
2101     * programmable clock generators, start with an absolute maximum.
2102     */
2103    if (pATI->ClockDescriptor.MaxN > 0)
2104    {
2105        Numerator = pATI->ClockDescriptor.MaxN * pATI->ReferenceNumerator;
2106        Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator *
2107            pATI->ClockDescriptor.PostDividers[0];
2108
2109        /*
2110         * An integrated PLL behaves as though the reference frequency were
2111         * doubled.  It also does not appear to care about the colour depth.
2112         */
2113        if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
2114            Numerator <<= 1;
2115
2116        ATIClockRange.maxClock = (Numerator / (Denominator * 1000)) * 1000;
2117
2118        Numerator = pATI->ClockDescriptor.MinN * pATI->ReferenceNumerator;
2119        Denominator = pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator *
2120            pATI->ClockDescriptor.PostDividers[pATI->ClockDescriptor.NumD - 1];
2121
2122        if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
2123            Numerator <<= 1;
2124
2125        ATIClockRange.minClock = (Numerator / (Denominator * 1000)) * 1000;
2126
2127        if (pATI->XCLKFeedbackDivider)
2128        {
2129            /* Possibly reduce maxClock due to memory bandwidth */
2130            Numerator = pATI->XCLKFeedbackDivider * 2 *
2131                pATI->ReferenceNumerator;
2132            Denominator = pATI->ClockDescriptor.MinM *
2133                pATI->XCLKReferenceDivider * pATI->ReferenceDenominator;
2134
2135            {
2136                Denominator *= pATI->bitsPerPixel / 4;
2137            }
2138
2139            i = (6 - 2) - pATI->XCLKPostDivider;
2140
2141            i = (ATIDivide(Numerator, Denominator, i, -1) / 1000) * 1000;
2142            if (i < ATIClockRange.maxClock)
2143                ATIClockRange.maxClock = i;
2144        }
2145    }
2146
2147    /*
2148     * Assume an internal DAC can handle whatever frequency the internal PLL
2149     * can produce (with the reference divider set by BIOS initialisation), but
2150     * default maxClock to a lower chip-specific default.
2151     */
2152    if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
2153    {
2154        int DacSpeed;
2155        switch (pATI->bitsPerPixel)
2156        {
2157            case 15:
2158            case 16:
2159                DacSpeed = pGDev->dacSpeeds[DAC_BPP16];
2160                break;
2161
2162            case 24:
2163                DacSpeed = pGDev->dacSpeeds[DAC_BPP24];
2164                break;
2165
2166            case 32:
2167                DacSpeed = pGDev->dacSpeeds[DAC_BPP32];
2168                break;
2169
2170            default:
2171                DacSpeed = 0;
2172                break;
2173        }
2174        if (!DacSpeed)
2175            DacSpeed = pGDev->dacSpeeds[DAC_BPP8];
2176        if (DacSpeed < ATIClockRange.maxClock)
2177        {
2178            DefaultmaxClock = 135000;
2179
2180            if (pATI->depth > 8)
2181                DefaultmaxClock = 80000;
2182
2183            if ((pATI->Chip >= ATI_CHIP_264VTB) &&
2184                (pATI->Chip != ATI_CHIP_Mach64))
2185            {
2186                if ((pATI->Chip >= ATI_CHIP_264VT4) &&
2187                    (pATI->Chip != ATI_CHIP_264LTPRO))
2188                    DefaultmaxClock = 230000;
2189                else if (pATI->Chip >= ATI_CHIP_264VT3)
2190                    DefaultmaxClock = 200000;
2191                else
2192                    DefaultmaxClock = 170000;
2193            }
2194            if (DacSpeed > DefaultmaxClock)
2195                ATIClockRange.maxClock = DacSpeed;
2196            else if (DefaultmaxClock < ATIClockRange.maxClock)
2197                ATIClockRange.maxClock = DefaultmaxClock;
2198        }
2199    }
2200    else
2201    {
2202        switch(pATI->DAC)
2203        {
2204            case ATI_DAC_STG1700:
2205            case ATI_DAC_STG1702:
2206            case ATI_DAC_STG1703:
2207                DefaultmaxClock = 110000;
2208                break;
2209
2210            case ATI_DAC_IBMRGB514:
2211                pATI->maxClock = 220000;
2212                {
2213                    DefaultmaxClock = 220000;
2214                }
2215                break;
2216
2217            default:
2218
2219#ifndef AVOID_CPIO
2220
2221                if (pATI->CPIO_VGAWonder && (pATI->VideoRAM < 1024))
2222                {
2223                    DefaultmaxClock =
2224                        (GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000;
2225                }
2226                else
2227
2228#endif /* AVOID_CPIO */
2229
2230                {
2231                    DefaultmaxClock = 80000;
2232                }
2233
2234                break;
2235        }
2236
2237        if (DefaultmaxClock < ATIClockRange.maxClock)
2238            ATIClockRange.maxClock = DefaultmaxClock;
2239    }
2240
2241    /*
2242     * Determine available pixel clock frequencies.
2243     */
2244
2245    if ((pATI->ProgrammableClock <= ATI_CLOCK_FIXED) ||
2246        (pATI->ProgrammableClock >= ATI_CLOCK_MAX))
2247    {
2248        xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
2249            "Unsupported or non-programmable clock generator.\n");
2250        goto bail;
2251    }
2252
2253    ATIClockPreInit(pScreenInfo, pATI);
2254    Strategy = LOOKUP_BEST_REFRESH;
2255
2256    /*
2257     * Mode validation.
2258     */
2259
2260    if (pATI->Chip >= ATI_CHIP_264CT)
2261    {
2262        minPitch = 8;
2263    }
2264    else
2265    {
2266        minPitch = 16;
2267    }
2268
2269    pitchInc = minPitch * pATI->bitsPerPixel;
2270
2271    pScreenInfo->maxHValue = (MaxBits(CRTC_H_TOTAL) + 1) << 3;
2272
2273    if (pATI->Chip < ATI_CHIP_264VT)
2274    {
2275        /*
2276         * ATI finally fixed accelerated doublescanning in the 264VT
2277         * and later.  On 88800's, the bit is documented to exist, but
2278         * only doubles the vertical timings.  On the 264CT and 264ET,
2279         * the bit is ignored.
2280         */
2281        ATIClockRange.doubleScanAllowed = FALSE;
2282
2283        /* CRTC_H_TOTAL is one bit narrower */
2284        pScreenInfo->maxHValue >>= 1;
2285    }
2286
2287    pScreenInfo->maxVValue = MaxBits(CRTC_V_TOTAL) + 1;
2288
2289    maxPitch = minPitch * MaxBits(CRTC_PITCH);
2290
2291    if (pATI->OptionAccel)
2292    {
2293        /*
2294         * Set engine restrictions on coordinate space.  Use maxPitch for the
2295         * horizontal and maxHeight for the vertical.
2296         */
2297        if (maxPitch > (ATIMach64MaxX / pATI->XModifier))
2298            maxPitch = ATIMach64MaxX / pATI->XModifier;
2299
2300        maxHeight = ATIMach64MaxY;
2301
2302        /*
2303         * For SGRAM & WRAM adapters, the display engine limits the pitch to
2304         * multiples of 64 bytes.
2305         */
2306        if ((pATI->Chip >= ATI_CHIP_264CT) &&
2307            ((pATI->Chip >= ATI_CHIP_264VTB) ||
2308             (pATI->MemoryType >= MEM_264_SGRAM)))
2309            pitchInc = pATI->XModifier * (64 * 8);
2310    }
2311
2312    if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
2313    {
2314        /*
2315         * Given LCD modes are more tightly controlled than CRT modes, allow
2316         * the user the option of not specifying a panel's horizontal sync
2317         * and/or vertical refresh tolerances.
2318         */
2319        Strategy |= LOOKUP_OPTIONAL_TOLERANCES;
2320
2321        if (ModeType == M_T_BUILTIN)
2322        {
2323            /*
2324             * Add a mode to the end of the monitor's list for the panel's
2325             * native resolution.
2326             */
2327            pMode = (DisplayModePtr)xnfcalloc(1, SizeOf(DisplayModeRec));
2328            pMode->name = "Native panel mode";
2329            pMode->type = M_T_BUILTIN;
2330            pMode->Clock = pATI->LCDClock;
2331            pMode->HDisplay = pATI->LCDHorizontal;
2332            pMode->VDisplay = pATI->LCDVertical;
2333
2334            /*
2335             * These timings are bogus, but enough to survive sync tolerance
2336             * checks.
2337             */
2338            pMode->HSyncStart = pMode->HDisplay;
2339            pMode->HSyncEnd = pMode->HSyncStart + minPitch;
2340            pMode->HTotal = pMode->HSyncEnd + minPitch;
2341            pMode->VSyncStart = pMode->VDisplay;
2342            pMode->VSyncEnd = pMode->VSyncStart + 1;
2343            pMode->VTotal = pMode->VSyncEnd + 1;
2344
2345            pMode->CrtcHDisplay = pMode->HDisplay;
2346            pMode->CrtcHBlankStart = pMode->HDisplay;
2347            pMode->CrtcHSyncStart = pMode->HSyncStart;
2348            pMode->CrtcHSyncEnd = pMode->HSyncEnd;
2349            pMode->CrtcHBlankEnd = pMode->HTotal;
2350            pMode->CrtcHTotal = pMode->HTotal;
2351
2352            pMode->CrtcVDisplay = pMode->VDisplay;
2353            pMode->CrtcVBlankStart = pMode->VDisplay;
2354            pMode->CrtcVSyncStart = pMode->VSyncStart;
2355            pMode->CrtcVSyncEnd = pMode->VSyncEnd;
2356            pMode->CrtcVBlankEnd = pMode->VTotal;
2357            pMode->CrtcVTotal = pMode->VTotal;
2358
2359            if (!pScreenInfo->monitor->Modes)
2360            {
2361                pScreenInfo->monitor->Modes = pMode;
2362            }
2363            else
2364            {
2365                pScreenInfo->monitor->Last->next = pMode;
2366                pMode->prev = pScreenInfo->monitor->Last;
2367            }
2368
2369            pScreenInfo->monitor->Last = pMode;
2370        }
2371
2372        /*
2373         * Defeat Xconfigurator brain damage.  Ignore all HorizSync and
2374         * VertRefresh specifications.  For now, this does not take
2375         * SYNC_TOLERANCE into account.
2376         */
2377        if (pScreenInfo->monitor->nHsync > 0)
2378        {
2379            double hsync = (double)pATI->LCDClock /
2380                           (pATI->LCDHorizontal + pATI->LCDHBlankWidth);
2381
2382            for (i = 0;  ;  i++)
2383            {
2384                if (i >= pScreenInfo->monitor->nHsync)
2385                {
2386                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
2387                        "Conflicting XF86Config HorizSync specification(s)"
2388                        " ignored.\n");
2389                    break;
2390                }
2391
2392                if ((hsync >= pScreenInfo->monitor->hsync[i].lo) &&
2393                    (hsync <= pScreenInfo->monitor->hsync[i].hi))
2394                {
2395                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
2396                        "Extraneous XF86Config HorizSync specification(s)"
2397                        " ignored.\n");
2398                    break;
2399                }
2400            }
2401
2402            pScreenInfo->monitor->nHsync = 0;
2403        }
2404
2405        if (pScreenInfo->monitor->nVrefresh > 0)
2406        {
2407            double vrefresh = ((double)pATI->LCDClock * 1000.0) /
2408                              ((pATI->LCDHorizontal + pATI->LCDHBlankWidth) *
2409                               (pATI->LCDVertical + pATI->LCDVBlankWidth));
2410
2411            for (i = 0;  ;  i++)
2412            {
2413                if (i >= pScreenInfo->monitor->nVrefresh)
2414                {
2415                    xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
2416                        "Conflicting XF86Config VertRefresh specification(s)"
2417                        " ignored.\n");
2418                    break;
2419                }
2420
2421                if ((vrefresh >= pScreenInfo->monitor->vrefresh[i].lo) &&
2422                    (vrefresh <= pScreenInfo->monitor->vrefresh[i].hi))
2423                {
2424                    xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
2425                        "Extraneous XF86Config VertRefresh specification(s)"
2426                        " ignored.\n");
2427                    break;
2428                }
2429            }
2430
2431            pScreenInfo->monitor->nVrefresh = 0;
2432        }
2433    }
2434
2435    i = xf86ValidateModes(pScreenInfo,
2436            pScreenInfo->monitor->Modes, pScreenInfo->display->modes,
2437            &ATIClockRange, NULL, minPitch, maxPitch,
2438            pitchInc, 0, maxHeight,
2439            pScreenInfo->display->virtualX, pScreenInfo->display->virtualY,
2440            ApertureSize, Strategy);
2441    if (i <= 0)
2442        goto bail;
2443
2444    /* Remove invalid modes */
2445    xf86PruneDriverModes(pScreenInfo);
2446
2447    /* Set current mode to the first in the list */
2448    pScreenInfo->currentMode = pScreenInfo->modes;
2449
2450    /* Print mode list */
2451    xf86PrintModes(pScreenInfo);
2452
2453    /* Set display resolution */
2454    xf86SetDpi(pScreenInfo, 0, 0);
2455
2456    /* Load required modules */
2457    if (!ATILoadModules(pScreenInfo, pATI))
2458        goto bail;
2459
2460    pATI->displayWidth = pScreenInfo->displayWidth;
2461
2462    /* Initialise for panning */
2463    ATIAdjustPreInit(pATI);
2464
2465    /*
2466     * Warn about modes that are too small, or not aligned, to scroll to the
2467     * bottom right corner of the virtual screen.
2468     */
2469    MinX = pScreenInfo->virtualX - pATI->AdjustMaxX;
2470    MinY = pScreenInfo->virtualY - pATI->AdjustMaxY;
2471
2472    pMode = pScreenInfo->modes;
2473    do
2474    {
2475        if ((pMode->VDisplay <= MinY) &&
2476            ((pMode->VDisplay < MinY) || (pMode->HDisplay < MinX)))
2477            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
2478                "Mode \"%s\" too small to scroll to bottom right corner of"
2479                " virtual resolution.\n", pMode->name);
2480        else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc)
2481            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
2482                "Mode \"%s\" cannot scroll to bottom right corner of virtual"
2483                " resolution.\n Horizontal dimension not a multiple of %ld.\n",
2484                pMode->name, ~pATI->AdjustMask + 1);
2485    } while ((pMode = pMode->next) != pScreenInfo->modes);
2486
2487    /* Initialise XVideo extension support */
2488    ATIXVPreInit(pATI);
2489
2490    /* Initialise CRTC code */
2491    ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
2492
2493    /* Set up for I2C */
2494    ATII2CPreInit(pScreenInfo, pATI);
2495
2496    if (!pScreenInfo->chipset || !*pScreenInfo->chipset)
2497        pScreenInfo->chipset = "mach64";
2498
2499    PreInitSuccess = TRUE;
2500
2501bail:
2502    ATILock(pATI);
2503
2504bail_locked:
2505    ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
2506    ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
2507
2508    return PreInitSuccess;
2509}
2510