tdfx_driver.c revision 02be438a
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#define USE_INT10 1
6#define USE_PCIVGAIO 1
7
8/**************************************************************************
9
10Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
11All Rights Reserved.
12
13Permission is hereby granted, free of charge, to any person obtaining a
14copy of this software and associated documentation files (the
15"Software"), to deal in the Software without restriction, including
16without limitation the rights to use, copy, modify, merge, publish,
17distribute, sub license, and/or sell copies of the Software, and to
18permit persons to whom the Software is furnished to do so, subject to
19the following conditions:
20
21The above copyright notice and this permission notice (including the
22next paragraph) shall be included in all copies or substantial portions
23of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
28IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
29ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
30TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33**************************************************************************/
34/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c,v 1.104tsi Exp $ */
35
36/*
37 * Authors:
38 *   Daryll Strauss <daryll@precisioninsight.com>
39 *
40 */
41
42/*
43 * This server does not support these XFree 4.0 features yet
44 * DDC2 (requires I2C)
45 * shadowFb (if requested or acceleration is off)
46 * Overlay planes
47 */
48
49/*
50 * These are X and server generic header files.
51 */
52#include "xf86.h"
53#include "xf86_OSproc.h"
54#include "xf86Resources.h"
55#include "xf86RAC.h"
56#include "vbe.h"
57#include "xf86cmap.h"
58
59/* If the driver uses port I/O directly, it needs: */
60
61#include "compiler.h"
62
63/* Drivers using the mi implementation of backing store need: */
64
65#include "mibstore.h"
66
67/* All drivers using the vgahw module need this */
68/* This driver needs to be modified to not use vgaHW for multihead operation */
69#include "vgaHW.h"
70
71/* Drivers using the mi SW cursor need: */
72
73#include "mipointer.h"
74
75/* Drivers using the mi colourmap code need: */
76
77#include "micmap.h"
78
79/* Required for line biases */
80#include "miline.h"
81
82#include "fb.h"
83
84/* !!! These need to be checked !!! */
85#if 0
86#define _XF86DGA_SERVER_
87#include <X11/extensions/xf86dgastr.h>
88#endif
89
90/* The driver's own header file: */
91
92#include "tdfx.h"
93
94#include "regionstr.h"
95#include "dixstruct.h"
96
97#include "xf86xv.h"
98#include <X11/extensions/Xv.h>
99
100#ifdef XF86DRI
101#include "dri.h"
102#endif
103
104/* Required Functions: */
105
106static const OptionInfoRec *	TDFXAvailableOptions(int chipid, int busid);
107/* Print a driver identifying message. */
108static void TDFXIdentify(int flags);
109
110/* Identify if there is any hardware present that I know how to drive. */
111static Bool TDFXProbe(DriverPtr drv, int flags);
112
113/* Process the config file and see if we have a valid configuration */
114static Bool TDFXPreInit(ScrnInfoPtr pScrn, int flags);
115
116/* Initialize a screen */
117static Bool TDFXScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
118
119/* Enter from a virtual terminal */
120static Bool TDFXEnterVT(int scrnIndex, int flags);
121
122/* Leave to a virtual terminal */
123static void TDFXLeaveVT(int scrnIndex, int flags);
124
125/* Close down each screen we initialized */
126static Bool TDFXCloseScreen(int scrnIndex, ScreenPtr pScreen);
127
128/* Change screensaver state */
129static Bool TDFXSaveScreen(ScreenPtr pScreen, int mode);
130
131/* Cleanup server private data */
132static void TDFXFreeScreen(int scrnIndex, int flags);
133
134/* Check if a mode is valid on the hardware */
135static ModeStatus TDFXValidMode(int scrnIndex, DisplayModePtr mode,
136				Bool verbose, int flags);
137
138static void TDFXBlockHandler(int, pointer, pointer, pointer);
139
140/* Switch to various Display Power Management System levels */
141static void TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn,
142					int PowerManagermentMode, int flags);
143
144_X_EXPORT DriverRec TDFX = {
145  TDFX_VERSION,
146  TDFX_DRIVER_NAME,
147  TDFXIdentify,
148  TDFXProbe,
149  TDFXAvailableOptions,
150  NULL,
151  0
152};
153
154/* Chipsets */
155static SymTabRec TDFXChipsets[] = {
156  { PCI_CHIP_BANSHEE, "3dfx Banshee"},
157  { PCI_CHIP_VOODOO3, "3dfx Voodoo3"},
158  { PCI_CHIP_VOODOO5, "3dfx Voodoo5"},
159  { -1, NULL }
160};
161
162static PciChipsets TDFXPciChipsets[] = {
163  { PCI_CHIP_BANSHEE, PCI_CHIP_BANSHEE, RES_SHARED_VGA },
164  { PCI_CHIP_VOODOO3, PCI_CHIP_VOODOO3, RES_SHARED_VGA },
165  { PCI_CHIP_VOODOO5, PCI_CHIP_VOODOO5, RES_SHARED_VGA },
166  { -1, -1, RES_UNDEFINED }
167};
168
169/* !!! Do we want an option for alternate clocking? !!! */
170
171typedef enum {
172  OPTION_NOACCEL,
173  OPTION_SW_CURSOR,
174  OPTION_USE_PIO,
175  OPTION_SHOWCACHE,
176  OPTION_VIDEO_KEY,
177  OPTION_NO_SLI,
178  OPTION_TEXTURED_VIDEO,
179  OPTION_DRI
180} TDFXOpts;
181
182static const OptionInfoRec TDFXOptions[] = {
183  { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
184  { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
185  { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE},
186  { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
187  { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE},
188  { OPTION_NO_SLI, "NoSLI", OPTV_BOOLEAN, {0}, FALSE},
189  { OPTION_TEXTURED_VIDEO, "TexturedVideo", OPTV_BOOLEAN, {1}, FALSE},
190  { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
191  { -1, NULL, OPTV_NONE, {0}, FALSE}
192};
193
194static const char *vgahwSymbols[] = {
195    "vgaHWEnable",
196    "vgaHWFreeHWRec",
197    "vgaHWGetHWRec",
198    "vgaHWGetIOBase",
199    "vgaHWGetIndex",
200    "vgaHWInit",
201    "vgaHWLock",
202    "vgaHWMapMem",
203    "vgaHWProtect",
204    "vgaHWRestore",
205    "vgaHWSave",
206    "vgaHWSeqReset",
207    "vgaHWUnlock",
208    0
209};
210
211static const char *ramdacSymbols[] = {
212    "xf86CreateCursorInfoRec",
213    "xf86InitCursor",
214    NULL
215};
216
217static const char *ddcSymbols[] = {
218    "xf86PrintEDID",
219    "xf86SetDDCproperties",
220    NULL
221};
222
223static const char *fbSymbols[] = {
224    "fbPictureInit",
225    "fbScreenInit",
226    NULL
227};
228
229static const char *xaaSymbols[] = {
230    "XAACreateInfoRec",
231    "XAADestroyInfoRec",
232    "XAAInit",
233    "XAAReverseBitOrder",
234    NULL
235};
236
237static const char *vbeSymbols[] = {
238    "VBEInit",
239    "vbeDoEDID",
240    "vbeFree",
241    NULL
242};
243
244static const char *int10Symbols[] = {
245    "xf86FreeInt10",
246    "xf86InitInt10",
247    NULL
248};
249
250#ifdef XF86DRI
251static const char *drmSymbols[] = {
252    "drmAddMap",
253    "drmFreeVersion",
254    "drmGetVersion",
255    NULL
256};
257
258static const char *driSymbols[] = {
259    "DRICloseScreen",
260    "DRICreateInfoRec",
261    "DRIDestroyInfoRec",
262    "DRIFinishScreenInit",
263    "DRIGetSAREAPrivate",
264    "DRILock",
265    "DRIMoveBuffersHelper",
266    "DRIQueryVersion",
267    "DRIScreenInit",
268    "DRIUnlock",
269    "GlxSetVisualConfigs",
270    "DRICreatePCIBusID",
271    NULL
272};
273
274#endif
275
276#ifdef XFree86LOADER
277
278static MODULESETUPPROTO(tdfxSetup);
279
280static XF86ModuleVersionInfo tdfxVersRec =
281{
282  "tdfx",
283  MODULEVENDORSTRING,
284  MODINFOSTRING1,
285  MODINFOSTRING2,
286  XORG_VERSION_CURRENT,
287  TDFX_MAJOR_VERSION, TDFX_MINOR_VERSION, TDFX_PATCHLEVEL,
288  ABI_CLASS_VIDEODRV,
289  ABI_VIDEODRV_VERSION,
290  MOD_CLASS_VIDEODRV,
291  {0,0,0,0}
292};
293
294_X_EXPORT XF86ModuleData tdfxModuleData = {&tdfxVersRec, tdfxSetup, 0};
295
296static pointer
297tdfxSetup(pointer module, pointer opts, int *errmaj, int *errmin)
298{
299    static Bool setupDone = FALSE;
300
301    /* This module should be loaded only once, but check to be sure. */
302
303    if (!setupDone) {
304	setupDone = TRUE;
305	xf86AddDriver(&TDFX, module, 0);
306
307	/*
308	 * Modules that this driver always requires may be loaded here
309	 * by calling LoadSubModule().
310	 */
311
312	/*
313	 * Tell the loader about symbols from other modules that this module
314	 * might refer to.
315	 */
316	LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
317			  ramdacSymbols, vbeSymbols, int10Symbols,
318#ifdef XF86DRI
319			  drmSymbols, driSymbols,
320#endif
321			  NULL);
322
323	/*
324	 * The return value must be non-NULL on success even though there
325	 * is no TearDownProc.
326	 */
327	return (pointer)1;
328    } else {
329	if (errmaj) *errmaj = LDR_ONCEONLY;
330	return NULL;
331    }
332}
333
334#endif
335
336/*
337 * TDFXGetRec and TDFXFreeRec --
338 *
339 * Private data for the driver is stored in the screen structure.
340 * These two functions create and destroy that private data.
341 *
342 */
343static Bool
344TDFXGetRec(ScrnInfoPtr pScrn) {
345  if (pScrn->driverPrivate) return TRUE;
346
347  pScrn->driverPrivate = xnfcalloc(sizeof(TDFXRec), 1);
348  return TRUE;
349}
350
351static void
352TDFXFreeRec(ScrnInfoPtr pScrn) {
353  if (!pScrn) return;
354  if (!pScrn->driverPrivate) return;
355  xfree(pScrn->driverPrivate);
356  pScrn->driverPrivate=0;
357}
358
359/*
360 * TDFXIdentify --
361 *
362 * Returns the string name for the driver based on the chipset. In this
363 * case it will always be an TDFX, so we can return a static string.
364 *
365 */
366static void
367TDFXIdentify(int flags) {
368  xf86PrintChipsets(TDFX_NAME, "Driver for 3dfx Banshee/Voodoo3 chipsets", TDFXChipsets);
369}
370
371static const OptionInfoRec *
372TDFXAvailableOptions(int chipid, int busid)
373{
374    return TDFXOptions;
375}
376
377static void
378TDFXProbeDDC(ScrnInfoPtr pScrn, int index)
379{
380    vbeInfoPtr pVbe;
381    if (xf86LoadSubModule(pScrn, "vbe"))
382    {
383	pVbe =  VBEInit(NULL,index);
384	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
385	vbeFree(pVbe);
386    }
387}
388
389/*
390 * TDFXProbe --
391 *
392 * Look through the PCI bus to find cards that are TDFX boards.
393 * Setup the dispatch table for the rest of the driver functions.
394 *
395 */
396static Bool
397TDFXProbe(DriverPtr drv, int flags) {
398  int i, numUsed, numDevSections, *usedChips;
399  GDevPtr *devSections;
400  Bool foundScreen = FALSE;
401
402  TDFXTRACE("TDFXProbe start\n");
403  /*
404   Find the config file Device sections that match this
405   driver, and return if there are none.
406   */
407  if ((numDevSections = xf86MatchDevice(TDFX_DRIVER_NAME, &devSections))<=0) {
408    return FALSE;
409  }
410
411  /*
412     Since these Probing is just checking the PCI data the server already
413     collected.
414  */
415  if (!xf86GetPciVideoInfo()) return FALSE;
416
417  numUsed = xf86MatchPciInstances(TDFX_NAME, PCI_VENDOR_3DFX,
418				  TDFXChipsets, TDFXPciChipsets,
419				  devSections, numDevSections,
420				  drv, &usedChips);
421
422  xfree(devSections);
423  if (numUsed<=0) return FALSE;
424
425  if (flags & PROBE_DETECT)
426    foundScreen = TRUE;
427  else for (i=0; i<numUsed; i++) {
428    ScrnInfoPtr pScrn;
429
430    /* Allocate new ScrnInfoRec and claim the slot */
431    pScrn = NULL;
432    if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
433			   TDFXPciChipsets, NULL, NULL, NULL, NULL, NULL))) {
434
435	pScrn->driverVersion = TDFX_VERSION;
436	pScrn->driverName = TDFX_DRIVER_NAME;
437	pScrn->name = TDFX_NAME;
438	pScrn->Probe = TDFXProbe;
439	pScrn->PreInit = TDFXPreInit;
440	pScrn->ScreenInit = TDFXScreenInit;
441	pScrn->SwitchMode = TDFXSwitchMode;
442	pScrn->AdjustFrame = TDFXAdjustFrame;
443	pScrn->EnterVT = TDFXEnterVT;
444	pScrn->LeaveVT = TDFXLeaveVT;
445	pScrn->FreeScreen = TDFXFreeScreen;
446	pScrn->ValidMode = TDFXValidMode;
447	foundScreen = TRUE;
448    }
449  }
450  xfree(usedChips);
451
452  return foundScreen;
453}
454
455static int
456TDFXCountRam(ScrnInfoPtr pScrn) {
457  TDFXPtr pTDFX;
458  int vmemSize;
459  int vmemType=-1; /* SDRAM or SGRAM */
460
461  pTDFX = TDFXPTR(pScrn);
462  TDFXTRACE("TDFXCountRam start\n");
463  vmemSize=0;
464  if (pTDFX->PIOBase[0]) {
465    CARD32
466      partSize,                 /* size of SGRAM chips in Mbits */
467      nChips,                   /* # chips of SDRAM/SGRAM */
468      banks,			/* Number of banks of chips */
469      dramInit0_strap,
470      dramInit1_strap,
471      dramInit1,
472      miscInit1;
473
474    /* determine memory type: SDRAM or SGRAM */
475    vmemType = MEM_TYPE_SGRAM;
476    dramInit1_strap = pTDFX->readLong(pTDFX, DRAMINIT1);
477    dramInit1_strap &= SST_MCTL_TYPE_SDRAM;
478    if (dramInit1_strap) vmemType = MEM_TYPE_SDRAM;
479
480    /* set memory interface delay values and enable refresh */
481    /* these apply to all RAM vendors */
482    dramInit1 = 0x0;
483    dramInit1 |= 2<<SST_SGRAM_OFLOP_DEL_ADJ_SHIFT;
484    dramInit1 |= SST_SGRAM_CLK_NODELAY;
485    dramInit1 |= SST_DRAM_REFRESH_EN;
486    dramInit1 |= (0x18 << SST_DRAM_REFRESH_VALUE_SHIFT) & SST_DRAM_REFRESH_VALUE;
487    dramInit1 &= ~SST_MCTL_TYPE_SDRAM;
488    dramInit1 |= dramInit1_strap;
489
490    /* Some information about the timing register (for later debugging) */
491    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
492               "DRAMINIT1 read 0x%x, programming 0x%lx (not Banshee)\n",
493	       pTDFX->readLong(pTDFX, DRAMINIT1), (unsigned long)dramInit1);
494
495    /*
496     * Here we don't whack the timing register on the Banshee boards as the
497     * BIOS has done a perfectly good job. As Banshee boards were made by
498     * different manufacturers we don't touch this, but carry on whacking it
499     * for Voodoo3 and Voodoo5 boards, as we've never had a problem with them.
500     * I guess this could be removed for all boards as we probably shouldn't
501     * be doing this to the V3/V5 boards too.
502     */
503    if (pTDFX->ChipType != PCI_CHIP_BANSHEE)
504    	pTDFX->writeLong(pTDFX, DRAMINIT1, dramInit1);
505
506    /* determine memory size from strapping pins (dramInit0 and dramInit1) */
507    dramInit0_strap = pTDFX->readLong(pTDFX, DRAMINIT0);
508
509    if (pTDFX->ChipType<=PCI_CHIP_VOODOO3) { /* Banshee/V3 */
510      if (vmemType == MEM_TYPE_SDRAM) {
511	vmemSize = 16;
512      } else {
513	nChips = ((dramInit0_strap & SST_SGRAM_NUM_CHIPSETS) == 0) ? 4 : 8;
514
515	if ( (dramInit0_strap & SST_SGRAM_TYPE) == SST_SGRAM_TYPE_8MBIT )  {
516	  partSize = 8;
517	} else if ( (dramInit0_strap & SST_SGRAM_TYPE) == SST_SGRAM_TYPE_16MBIT) {
518	  partSize = 16;
519	} else {
520	  ErrorF("Invalid sgram type = 0x%lx",
521		 (dramInit0_strap & SST_SGRAM_TYPE) << SST_SGRAM_TYPE_SHIFT );
522	  return 0;
523	}
524	vmemSize = (nChips * partSize) / 8;      /* in MBytes */
525      }
526    } else { /* V4, V5 */
527      nChips = ((dramInit0_strap & SST_SGRAM_NUM_CHIPSETS)==0) ? 4 : 8;
528      partSize=1<<((dramInit0_strap&0x38000000)>>28);
529      banks=((dramInit0_strap&BIT(30))==0) ? 2 : 4;
530      vmemSize=nChips*partSize*banks;
531    }
532    TDFXTRACEREG("dramInit0 = %lx dramInit1 = %lx\n",
533		(unsigned long)dramInit0_strap, (unsigned long)dramInit1_strap);
534    TDFXTRACEREG("MemConfig %d chips %ld size %ld total\n", (int)nChips,
535		(unsigned long)partSize, (unsigned long)vmemSize);
536
537    /*
538      disable block writes for SDRAM
539    */
540    miscInit1 = pTDFX->readLong(pTDFX, MISCINIT1);
541    if ( vmemType == MEM_TYPE_SDRAM ) {
542      miscInit1 |= SST_DISABLE_2D_BLOCK_WRITE;
543    }
544    miscInit1|=1;
545    pTDFX->writeLong(pTDFX, MISCINIT1, miscInit1);
546  }
547
548  /* return # of KBytes of board memory */
549  return vmemSize*1024;
550}
551
552#if 0
553static int TDFXCfgToSize(int cfg)
554{
555  if (cfg<4) return 0x8000000<<cfg;
556  return 0x4000000>>(cfg-4);
557}
558#endif
559
560static int TDFXSizeToCfg(int size)
561{
562  switch (size) {
563  case 0x40000000: return 3;
564  case 0x20000000: return 2;
565  case 0x10000000: return 1;
566  case 0x08000000: return 0;
567  case 0x04000000: return 4;
568  case 0x02000000: return 5;
569  case 0x01000000: return 6;
570  case 0x00800000: return 7;
571  case 0x00400000: return 8;
572  default:
573    return -1;
574  }
575}
576
577static void
578TDFXFindChips(ScrnInfoPtr pScrn, pciVideoPtr match)
579{
580  TDFXPtr pTDFX;
581  pciVideoPtr *ppPci;
582
583  pTDFX=TDFXPTR(pScrn);
584  pTDFX->numChips=0;
585  pTDFX->ChipType=match->chipType;
586  for (ppPci = xf86GetPciVideoInfo(); *ppPci != NULL; ppPci++) {
587    if ((*ppPci)->bus == match->bus &&
588	(*ppPci)->device == match->device) {
589      pTDFX->PciTag[pTDFX->numChips] = pciTag((*ppPci)->bus,
590					      (*ppPci)->device,
591					      (*ppPci)->func);
592      pTDFX->PIOBase[pTDFX->numChips] =
593	pScrn->domainIOBase + ((*ppPci)->ioBase[2] & 0xFFFFFFFCU);
594      pTDFX->numChips++;
595    }
596  }
597  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
598	"TDFXFindChips: found %d chip(s)\n", pTDFX->numChips);
599  /* Disable the secondary chips for now */
600  pTDFX->numChips=1;
601}
602
603static void
604TDFXInitChips(ScrnInfoPtr pScrn)
605{
606  TDFXPtr pTDFX;
607  int i;
608#if 0
609  int v;
610#endif
611  unsigned long cfgbits, initbits;
612  unsigned long mem0base, mem1base, mem0size, mem0bits, mem1size, mem1bits;
613
614  pTDFX=TDFXPTR(pScrn);
615  cfgbits=pciReadLong(pTDFX->PciTag[0], CFG_PCI_DECODE);
616  mem0base=pciReadLong(pTDFX->PciTag[0], CFG_MEM0BASE);
617  mem1base=pciReadLong(pTDFX->PciTag[0], CFG_MEM1BASE);
618  initbits=pciReadLong(pTDFX->PciTag[0], CFG_INIT_ENABLE);
619  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
620		"TDFXInitChips: numchips = %d\n", pTDFX->numChips);
621  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
622		"TDFXInitChips: cfgbits = 0x%08lx, initbits = 0x%08lx\n",
623		cfgbits, initbits);
624  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
625		"TDFXInitChips: mem0base = 0x%08lx, mem1base = 0x%08lx\n",
626		mem0base, mem1base);
627  mem0size=32*1024*1024; /* Registers are always 32MB */
628  mem1size=pScrn->videoRam*1024*2; /* Linear mapping is 2x memory */
629  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
630		"TDFXInitChips: mem0size = 0x%08lx, mem1size = 0x%08lx\n",
631		mem0size, mem1size);
632  mem0bits=TDFXSizeToCfg(mem0size);
633  mem1bits=TDFXSizeToCfg(mem1size)<<4;
634  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
635		"TDFXInitChips: mem0bits = 0x%08lx, mem1bits = 0x%08lx\n",
636		mem0bits, mem1bits);
637  cfgbits=(cfgbits&~(0xFF))|mem0bits|mem1bits;
638  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
639		"TDFXInitChips: cfgbits = 0x%08lx\n", cfgbits);
640  for (i=0; i<pTDFX->numChips; i++) {
641    initbits|=BIT(10);
642    pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, initbits);
643#if 0
644    v=pciReadWord(pTDFX->PciTag[i], CFG_PCI_COMMAND);
645    if (!i)
646      pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v|0x3);
647    else
648      pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v|0x2);
649#endif
650    pTDFX->MMIOAddr[i]=mem0base+i*mem0size;
651    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
652		"TDFXInitChips: MMIOAddr[%d] = 0x%08lx\n",
653		i, pTDFX->MMIOAddr[i]);
654    pciWriteLong(pTDFX->PciTag[i], CFG_MEM0BASE, pTDFX->MMIOAddr[i]);
655    pTDFX->MMIOAddr[i]&=0xFFFFFF00;
656    pTDFX->LinearAddr[i]=mem1base+i*mem1size;
657    pciWriteLong(pTDFX->PciTag[i], CFG_MEM1BASE, pTDFX->LinearAddr[i]);
658    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
659		"TDFXInitChips: LinearAddr[%d] = 0x%08lx\n",
660		i, pTDFX->LinearAddr[i]);
661    pTDFX->LinearAddr[i]&=0xFFFFFF00;
662    pciWriteLong(pTDFX->PciTag[i], CFG_PCI_DECODE, cfgbits);
663    initbits&=~BIT(10);
664    pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, initbits);
665  }
666}
667
668/*
669 * TDFXPreInit --
670 *
671 * Do initial setup of the board before we know what resolution we will
672 * be running at.
673 *
674 */
675static Bool
676TDFXPreInit(ScrnInfoPtr pScrn, int flags)
677{
678  TDFXPtr pTDFX;
679  ClockRangePtr clockRanges;
680  int i;
681  MessageType from;
682  int flags24;
683  rgb defaultWeight = {0, 0, 0};
684  pciVideoPtr match;
685  int availableMem;
686
687  TDFXTRACE("TDFXPreInit start\n");
688  if (pScrn->numEntities != 1) return FALSE;
689
690  /* Allocate driverPrivate */
691  if (!TDFXGetRec(pScrn)) {
692    return FALSE;
693  }
694
695  pTDFX = TDFXPTR(pScrn);
696
697  pTDFX->initDone=FALSE;
698  pTDFX->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
699
700  if (flags & PROBE_DETECT) {
701#if !defined(__powerpc__)
702    TDFXProbeDDC(pScrn, pTDFX->pEnt->index);
703    return TRUE;
704#else
705    return FALSE;
706#endif
707  }
708
709  if (pTDFX->pEnt->location.type != BUS_PCI) return FALSE;
710
711  /* The vgahw module should be loaded here when needed */
712  if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
713
714  xf86LoaderReqSymLists(vgahwSymbols, NULL);
715
716  /* Allocate a vgaHWRec */
717  if (!vgaHWGetHWRec(pScrn)) return FALSE;
718
719#if USE_INT10
720#if !defined(__powerpc__)
721  if (xf86LoadSubModule(pScrn, "int10")) {
722    xf86Int10InfoPtr pInt;
723
724    xf86LoaderReqSymLists(int10Symbols, NULL);
725    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
726               "Softbooting the board (through the int10 interface).\n");
727    pInt = xf86InitInt10(pTDFX->pEnt->index);
728    if (!pInt)
729    {
730      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
731                 "Softbooting the board failed.\n");
732    }
733    else
734    {
735      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
736                 "Softbooting the board succeeded.\n");
737      xf86FreeInt10(pInt);
738    }
739  }
740#endif
741#endif
742
743  match=pTDFX->PciInfo=xf86GetPciInfoForEntity(pTDFX->pEnt->index);
744  TDFXFindChips(pScrn, match);
745  pTDFX->Primary = xf86IsPrimaryPci(pTDFX->PciInfo);
746
747  if (xf86RegisterResources(pTDFX->pEnt->index, NULL, ResExclusive)) {
748      TDFXFreeRec(pScrn);
749      return FALSE;
750  }
751  /*
752   * We don't need VGA resources during OPERATING state. However I'm
753   * not sure if they are disabled.
754   */
755  xf86SetOperatingState(resVgaIo, pTDFX->pEnt->index, ResDisableOpr);
756
757  /* Is VGA memory disabled during OPERATING state? */
758  xf86SetOperatingState(resVgaMem, pTDFX->pEnt->index, ResUnusedOpr);
759    /*
760     * I'm sure we don't need to set these. All resources
761     * for these operations are exclusive.
762     */
763  if (pTDFX->usePIO) {
764      pScrn->racMemFlags = 0;
765      pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
766  } else
767      pScrn->racMemFlags = 0;
768
769  /* Set pScrn->monitor */
770  pScrn->monitor = pScrn->confScreen->monitor;
771
772  flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
773  if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
774    return FALSE;
775  } else {
776    switch (pScrn->depth) {
777    case 8:
778    case 16:
779    case 24:
780      break;
781    default:
782      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
783		 "Given depth (%d) is not supported by tdfx driver\n",
784		 pScrn->depth);
785      return FALSE;
786    }
787  }
788  xf86PrintDepthBpp(pScrn);
789
790  pScrn->rgbBits=8;
791  if (pScrn->depth>8) {
792    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
793      return FALSE;
794  }
795
796  if (!xf86SetDefaultVisual(pScrn, -1)) {
797    return FALSE;
798  } else {
799    /* We don't currently support DirectColor at > 8bpp */
800    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
801      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
802		 " (%s) is not supported at depth %d\n",
803		 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
804      return FALSE;
805    }
806  }
807
808  /* We use a programmable clock */
809  pScrn->progClock = TRUE;
810
811  pTDFX->cpp = pScrn->bitsPerPixel/8;
812
813  /* Process the options */
814  xf86CollectOptions(pScrn, NULL);
815  if (!(pTDFX->Options = xalloc(sizeof(TDFXOptions))))
816    return FALSE;
817  memcpy(pTDFX->Options, TDFXOptions, sizeof(TDFXOptions));
818  xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTDFX->Options);
819
820  /*
821   * Set the Chipset and ChipRev, allowing config file entries to
822   * override.
823   */
824  if (pTDFX->pEnt->device->chipset && *pTDFX->pEnt->device->chipset) {
825    pScrn->chipset = pTDFX->pEnt->device->chipset;
826    from = X_CONFIG;
827  } else if (pTDFX->pEnt->device->chipID >= 0) {
828    pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets, pTDFX->pEnt->device->chipID);
829    from = X_CONFIG;
830    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
831	       pTDFX->pEnt->device->chipID);
832  } else {
833    from = X_PROBED;
834    pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets, match->chipType);
835  }
836  if (pTDFX->pEnt->device->chipRev >= 0) {
837    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
838	       pTDFX->pEnt->device->chipRev);
839  }
840
841  xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
842
843  if (pTDFX->pEnt->device->MemBase != 0) {
844    pTDFX->LinearAddr[0] = pTDFX->pEnt->device->MemBase;
845    from = X_CONFIG;
846  } else {
847    if (match->memBase[1] != 0) {
848      pTDFX->LinearAddr[0] = match->memBase[1];
849      from = X_PROBED;
850    } else {
851      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
852		 "No valid FB address in PCI config space\n");
853      TDFXFreeRec(pScrn);
854      return FALSE;
855    }
856  }
857  xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
858	     (unsigned long)pTDFX->LinearAddr[0]);
859
860  if (pTDFX->pEnt->device->IOBase != 0) {
861    pTDFX->MMIOAddr[0] = pTDFX->pEnt->device->IOBase;
862    from = X_CONFIG;
863  } else {
864    if (match->memBase[0]) {
865      pTDFX->MMIOAddr[0] = match->memBase[0];
866      from = X_PROBED;
867    } else {
868      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
869		 "No valid MMIO address in PCI config space\n");
870      TDFXFreeRec(pScrn);
871      return FALSE;
872    }
873  }
874  xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at addr 0x%lX\n",
875	     (unsigned long)pTDFX->MMIOAddr[0]);
876
877  if (!match->ioBase[2]) {
878    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
879	       "No valid PIO address in PCI config space\n");
880    TDFXFreeRec(pScrn);
881    return FALSE;
882  }
883  xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PIO registers at addr 0x%lX\n",
884	     (unsigned long)pTDFX->PIOBase[0]);
885
886  /* We have to use PIO to probe, because we haven't mappend yet */
887  TDFXSetPIOAccess(pTDFX);
888
889  /* Calculate memory */
890  pScrn->videoRam = TDFXCountRam(pScrn);
891  from = X_PROBED;
892  if (pTDFX->pEnt->device->videoRam) {
893    pScrn->videoRam = pTDFX->pEnt->device->videoRam;
894    from = X_CONFIG;
895  }
896
897  TDFXInitChips(pScrn);
898
899  /* Multiple by two because tiled access requires more address space */
900  pTDFX->FbMapSize = pScrn->videoRam*1024*2;
901  xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte Mapping %ld kByte\n",
902	     pScrn->videoRam, pTDFX->FbMapSize/1024);
903
904  /* Since we can do gamma correction, we call xf86SetGamma */
905  {
906    Gamma zeros = {0.0, 0.0, 0.0};
907
908    if (!xf86SetGamma(pScrn, zeros)) {
909      return FALSE;
910    }
911  }
912
913  pTDFX->MaxClock = 0;
914  if (pTDFX->pEnt->device->dacSpeeds[0]) {
915    switch (pScrn->bitsPerPixel) {
916    case 8:
917      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP8];
918      break;
919    case 16:
920      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP16];
921      break;
922    case 24:
923      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP24];
924      break;
925    case 32:
926      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP32];
927      break;
928    }
929    if (!pTDFX->MaxClock)
930      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[0];
931    from = X_CONFIG;
932  } else {
933    switch (pTDFX->ChipType) {
934    case PCI_CHIP_BANSHEE:
935      pTDFX->MaxClock = 270000;
936      break;
937    case PCI_CHIP_VOODOO3:
938      switch(match->subsysCard) {
939      case PCI_CARD_VOODOO3_2000:
940	pTDFX->MaxClock = 300000;
941	break;
942      case PCI_CARD_VOODOO3_3000:
943	pTDFX->MaxClock = 350000;
944	break;
945      default:
946	pTDFX->MaxClock = 300000;
947	break;
948      }
949      break;
950    case PCI_CHIP_VOODOO5:
951      pTDFX->MaxClock = 350000;
952      break;
953    }
954  }
955  clockRanges = xnfcalloc(sizeof(ClockRange), 1);
956  clockRanges->next=NULL;
957  clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
958  clockRanges->maxClock=pTDFX->MaxClock;
959  clockRanges->clockIndex = -1;
960  switch (pTDFX->ChipType) {
961    case PCI_CHIP_BANSHEE:
962      clockRanges->interlaceAllowed = FALSE;
963      break;
964    case PCI_CHIP_VOODOO3:
965    case PCI_CHIP_VOODOO5:
966      clockRanges->interlaceAllowed = TRUE;
967      break;
968    default:
969      clockRanges->interlaceAllowed = FALSE;
970      break;
971  }
972  clockRanges->doubleScanAllowed = TRUE;
973
974  /*
975   * Max memory available for the framebuffer is the total less the
976   * HW cursor space and FIFO space.
977   */
978  availableMem = pScrn->videoRam - 4096 -
979		 (((255 <= CMDFIFO_PAGES) ? 255 : CMDFIFO_PAGES) << 12);
980
981  i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
982			pScrn->display->modes, clockRanges,
983			0, 320, 2048, 16*pScrn->bitsPerPixel,
984			200, 2047,
985			pScrn->display->virtualX, pScrn->display->virtualY,
986			availableMem, LOOKUP_BEST_REFRESH);
987
988  if (i==-1) {
989    TDFXFreeRec(pScrn);
990    return FALSE;
991  }
992
993  xf86PruneDriverModes(pScrn);
994
995  if (!i || !pScrn->modes) {
996    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
997    TDFXFreeRec(pScrn);
998    return FALSE;
999  }
1000
1001  xf86SetCrtcForModes(pScrn, 0);
1002
1003  pScrn->currentMode = pScrn->modes;
1004
1005  xf86PrintModes(pScrn);
1006
1007  xf86SetDpi(pScrn, 0, 0);
1008
1009  if (!xf86LoadSubModule(pScrn, "fb")) {
1010    TDFXFreeRec(pScrn);
1011    return FALSE;
1012  }
1013  xf86LoaderReqSymLists(fbSymbols, NULL);
1014
1015  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_NOACCEL, FALSE)) {
1016    if (!xf86LoadSubModule(pScrn, "xaa")) {
1017      TDFXFreeRec(pScrn);
1018      return FALSE;
1019    }
1020    xf86LoaderReqSymLists(xaaSymbols, NULL);
1021  }
1022
1023  if (!xf86GetOptValBool(pTDFX->Options, OPTION_SHOWCACHE, &(pTDFX->ShowCache))) {
1024    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache %s\n", pTDFX->ShowCache ? "Enabled" : "Disabled");
1025  } else {
1026    pTDFX->ShowCache = FALSE;
1027  }
1028
1029  if (xf86GetOptValBool(pTDFX->Options, OPTION_TEXTURED_VIDEO, &(pTDFX->TextureXvideo))) {
1030    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Texture Xvideo Adaptor %s\n", pTDFX->TextureXvideo ? "Enabled" : "Disabled");
1031  } else {
1032    pTDFX->TextureXvideo = FALSE;
1033  }
1034
1035  if (xf86GetOptValInteger(pTDFX->Options, OPTION_VIDEO_KEY, &(pTDFX->videoKey))) {
1036    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pTDFX->videoKey);
1037  } else {
1038    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key default 0x%x\n", pTDFX->videoKey = 0x1E);
1039  }
1040
1041  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
1042    if (!xf86LoadSubModule(pScrn, "ramdac")) {
1043      TDFXFreeRec(pScrn);
1044      return FALSE;
1045    }
1046    xf86LoaderReqSymLists(ramdacSymbols, NULL);
1047  }
1048
1049#if USE_INT10
1050#if !defined(__powerpc__)
1051  /* Load DDC if needed */
1052  /* This gives us DDC1 - we should be able to get DDC2B using i2c */
1053  if (!xf86LoadSubModule(pScrn, "ddc")) {
1054    TDFXFreeRec(pScrn);
1055    return FALSE;
1056  }
1057  xf86LoaderReqSymLists(ddcSymbols, NULL);
1058
1059  /* Initialize DDC1 if possible */
1060  if (xf86LoadSubModule(pScrn, "vbe")) {
1061      xf86MonPtr pMon;
1062      vbeInfoPtr pVbe = VBEInit(NULL,pTDFX->pEnt->index);
1063
1064      xf86LoaderReqSymLists(vbeSymbols, NULL);
1065      pMon = vbeDoEDID(pVbe, NULL);
1066      vbeFree(pVbe);
1067      xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
1068  }
1069#endif
1070#endif
1071
1072  if (xf86ReturnOptValBool(pTDFX->Options, OPTION_USE_PIO, FALSE)) {
1073    pTDFX->usePIO=TRUE;
1074  }
1075
1076#if X_BYTE_ORDER == X_BIG_ENDIAN
1077  pTDFX->ModeReg.miscinit0 = pTDFX->readLong(pTDFX, MISCINIT0);
1078  pTDFX->SavedReg.miscinit0 = pTDFX->ModeReg.miscinit0;
1079
1080  switch (pScrn->bitsPerPixel) {
1081  case 8:
1082    pTDFX->writeFifo = TDFXWriteFifo_8;
1083    pTDFX->ModeReg.miscinit0 &= ~BIT(30); /* LFB byte swizzle */
1084    pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
1085    break;
1086  case 15:
1087  case 16:
1088    pTDFX->writeFifo = TDFXWriteFifo_16;
1089    pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
1090    pTDFX->ModeReg.miscinit0 |= BIT(31); /* LFB word swizzle */
1091    break;
1092  case 24:
1093  case 32:
1094    pTDFX->writeFifo = TDFXWriteFifo_24;
1095    pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
1096    pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
1097    break;
1098  default:
1099    return FALSE;
1100    break;
1101  }
1102  pTDFX->writeLong(pTDFX, MISCINIT0, pTDFX->ModeReg.miscinit0);
1103#endif
1104
1105#ifdef XF86DRI
1106  /* Load the dri module if requested. */
1107  if (xf86ReturnOptValBool(pTDFX->Options, OPTION_DRI, FALSE)) {
1108    if (xf86LoadSubModule(pScrn, "dri")) {
1109      xf86LoaderReqSymLists(driSymbols, drmSymbols, NULL);
1110    }
1111  }
1112#endif
1113  return TRUE;
1114}
1115
1116static Bool
1117TDFXMapMem(ScrnInfoPtr pScrn)
1118{
1119  int mmioFlags, i;
1120  TDFXPtr pTDFX;
1121
1122  TDFXTRACE("TDFXMapMem start\n");
1123  pTDFX = TDFXPTR(pScrn);
1124
1125  mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
1126
1127  for (i=0; i<pTDFX->numChips; i++) {
1128    pTDFX->MMIOBase[i] = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
1129				       pTDFX->PciTag[i],
1130				       pTDFX->MMIOAddr[i],
1131				       TDFXIOMAPSIZE);
1132
1133    if (!pTDFX->MMIOBase[i]) return FALSE;
1134  }
1135
1136  pTDFX->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1137				pTDFX->PciTag[0],
1138				pTDFX->LinearAddr[0],
1139				pTDFX->FbMapSize);
1140  if (!pTDFX->FbBase) return FALSE;
1141
1142  return TRUE;
1143}
1144
1145static Bool
1146TDFXUnmapMem(ScrnInfoPtr pScrn)
1147{
1148  TDFXPtr pTDFX;
1149  int i;
1150
1151  TDFXTRACE("TDFXUnmapMem start\n");
1152  pTDFX = TDFXPTR(pScrn);
1153
1154  for (i=0; i<pTDFX->numChips; i++) {
1155    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->MMIOBase[i],
1156		    TDFXIOMAPSIZE);
1157    pTDFX->MMIOBase[i]=0;
1158  }
1159
1160  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->FbBase, pTDFX->FbMapSize);
1161  pTDFX->FbBase = 0;
1162  return TRUE;
1163}
1164
1165static void
1166PrintRegisters(ScrnInfoPtr pScrn, TDFXRegPtr regs)
1167{
1168#ifdef TRACE
1169  int i;
1170  TDFXPtr pTDFX;
1171  vgaHWPtr pHW = VGAHWPTR(pScrn);
1172  vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
1173
1174
1175  pTDFX = TDFXPTR(pScrn);
1176#if 1
1177  ErrorF("VGA Registers\n");
1178  ErrorF("MiscOutReg = %x versus %x\n", pHW->readMiscOut(pHW), pVga->MiscOutReg);
1179  ErrorF("EnableReg = %x\n", pHW->readEnable(pHW));
1180  for (i=0; i<25; i++) {
1181    int x;
1182    x = pHW->readCrtc(pHW, i);
1183    ErrorF("CRTC[%d]=%d versus %d\n", i, x, pVga->CRTC[i]);
1184  }
1185  for (i=0; i<21; i++) {
1186    ErrorF("Attribute[%d]=%d versus %d\n", i, pHW->readAttr(pHW, i), pVga->Attribute[i]);
1187  }
1188  for (i=0; i<9; i++) {
1189    ErrorF("Graphics[%d]=%d versus %d\n", i, pHW->readGr(pHW, i), pVga->Graphics[i]);
1190  }
1191  for (i=0; i<5; i++) {
1192    ErrorF("Sequencer[%d]=%d versus %d\n", i, pHW->readSeq(pHW, i), pVga->Sequencer[i]);
1193  }
1194#endif
1195#if 1
1196  ErrorF("Banshee Registers\n");
1197  ErrorF("VidCfg = %x versus %x\n",  pTDFX->readLong(pTDFX, VIDPROCCFG), regs->vidcfg);
1198  ErrorF("DACmode = %x versus %x\n", pTDFX->readLong(pTDFX, DACMODE), regs->dacmode);
1199  ErrorF("Vgainit0 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT0), regs->vgainit0);
1200  ErrorF("Vgainit1 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT1), regs->vgainit1);
1201  ErrorF("Miscinit0 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT0), regs->miscinit0);
1202  ErrorF("Miscinit1 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT1), regs->miscinit1);
1203  ErrorF("DramInit0 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT0));
1204  ErrorF("DramInit1 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT1));
1205  ErrorF("VidPLL = %x versus %x\n", pTDFX->readLong(pTDFX, PLLCTRL0), regs->vidpll);
1206  ErrorF("screensize = %x versus %x\n", pTDFX->readLong(pTDFX, VIDSCREENSIZE), regs->screensize);
1207  ErrorF("stride = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE), regs->stride);
1208  ErrorF("startaddr = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR), regs->startaddr);
1209  ErrorF("Input Status 0 = %x\n", pTDFX->readLong(pTDFX, 0xc2));
1210  ErrorF("Input Status 1 = %x\n", pTDFX->readLong(pTDFX, 0xda));
1211  ErrorF("2D Status = %x\n", pTDFX->readLong(pTDFX, SST_2D_OFFSET));
1212  ErrorF("3D Status = %x\n", pTDFX->readLong(pTDFX, SST_3D_OFFSET));
1213#endif
1214#endif
1215}
1216
1217/*
1218 * TDFXSave --
1219 *
1220 * This function saves the video state.  It reads all of the SVGA registers
1221 * into the vgaTDFXRec data structure.  There is in general no need to
1222 * mask out bits here - just read the registers.
1223 */
1224static void
1225DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg, Bool saveFonts)
1226{
1227  TDFXPtr pTDFX;
1228  vgaHWPtr hwp;
1229  int i, dummy, count;
1230
1231  TDFXTRACE("TDFXDoSave start\n");
1232  pTDFX = TDFXPTR(pScrn);
1233  hwp = VGAHWPTR(pScrn);
1234
1235  /*
1236   * This function will handle creating the data structure and filling
1237   * in the generic VGA portion.
1238   */
1239  if (saveFonts && pTDFX->Primary) {
1240    /* Enable legacy VGA to access font memory. */
1241    dummy = pTDFX->readLong(pTDFX, VGAINIT0);
1242    pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
1243    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS);
1244    pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
1245  } else
1246    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
1247
1248  tdfxReg->ExtVga[0] = hwp->readCrtc(hwp, 0x1a);
1249  tdfxReg->ExtVga[1] = hwp->readCrtc(hwp, 0x1b);
1250  tdfxReg->miscinit1=pTDFX->readLong(pTDFX, MISCINIT1);
1251  tdfxReg->vidcfg=pTDFX->readLong(pTDFX, VIDPROCCFG);
1252  tdfxReg->vidpll=pTDFX->readLong(pTDFX, PLLCTRL0);
1253  tdfxReg->dacmode=pTDFX->readLong(pTDFX, DACMODE);
1254  tdfxReg->screensize=pTDFX->readLong(pTDFX, VIDSCREENSIZE);
1255  tdfxReg->stride=pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE);
1256  tdfxReg->cursloc=pTDFX->readLong(pTDFX, HWCURPATADDR);
1257  tdfxReg->startaddr=pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR);
1258  tdfxReg->clip0min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MIN);
1259  tdfxReg->clip0max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MAX);
1260  tdfxReg->clip1min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MIN);
1261  tdfxReg->clip1max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MAX);
1262  tdfxReg->srcbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_SRCBASEADDR);
1263  tdfxReg->dstbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_DSTBASEADDR);
1264  for (i=0; i<512; i++) {
1265    count=0;
1266    do {
1267      TDFXWriteLongMMIO(pTDFX, DACADDR, i);
1268      dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
1269    } while (count++<100 && dummy!=i);
1270    tdfxReg->dactable[i]=TDFXReadLongMMIO(pTDFX, DACDATA);
1271  }
1272  PrintRegisters(pScrn, tdfxReg);
1273}
1274
1275static void
1276TDFXSave(ScrnInfoPtr pScrn)
1277{
1278  vgaHWPtr hwp;
1279  TDFXPtr pTDFX;
1280
1281  TDFXTRACE("TDFXSave start\n");
1282  hwp = VGAHWPTR(pScrn);
1283  pTDFX = TDFXPTR(pScrn);
1284  /* Make sure VGA functionality is enabled */
1285  pTDFX->SavedReg.vgainit0=pTDFX->readLong(pTDFX, VGAINIT0);
1286#if 0
1287  pTDFX->SavedReg.vgainit1=pTDFX->readLong(pTDFX, VGAINIT1);
1288#endif
1289  pTDFX->writeLong(pTDFX, VGAINIT0, pTDFX->ModeReg.vgainit0);
1290#if 0
1291  pTDFX->writeLong(pTDFX, VGAINIT1, pTDFX->ModeReg.vgainit1);
1292#endif
1293  vgaHWEnable(hwp);
1294
1295  DoSave(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
1296}
1297
1298static void
1299DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg,
1300	  Bool restoreFonts) {
1301  TDFXPtr pTDFX;
1302  vgaHWPtr hwp;
1303  int i, dummy, count;
1304
1305  TDFXTRACE("TDFXDoRestore start\n");
1306  pTDFX = TDFXPTR(pScrn);
1307  hwp = VGAHWPTR(pScrn);
1308
1309  pTDFX->sync(pScrn);
1310
1311  vgaHWProtect(pScrn, TRUE);
1312
1313  if (restoreFonts && pTDFX->Primary) {
1314    /* Enable legacy VGA to access font memory. */
1315    dummy = pTDFX->readLong(pTDFX, VGAINIT0);
1316    pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
1317    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
1318    pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
1319  } else
1320    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
1321
1322  hwp->writeCrtc(hwp, 0x1a, tdfxReg->ExtVga[0]);
1323  hwp->writeCrtc(hwp, 0x1b, tdfxReg->ExtVga[1]);
1324  pTDFX->writeLong(pTDFX, PLLCTRL0, tdfxReg->vidpll);
1325  pTDFX->writeLong(pTDFX, DACMODE, tdfxReg->dacmode);
1326  pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, tdfxReg->stride);
1327  pTDFX->writeLong(pTDFX, HWCURPATADDR, tdfxReg->cursloc);
1328  pTDFX->writeLong(pTDFX, VIDSCREENSIZE, tdfxReg->screensize);
1329  pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
1330  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MIN, tdfxReg->clip0min);
1331  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MAX, tdfxReg->clip0max);
1332  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MIN, tdfxReg->clip1min);
1333  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MAX, tdfxReg->clip1max);
1334#if X_BYTE_ORDER == X_BIG_ENDIAN
1335  pTDFX->writeLong(pTDFX, MISCINIT0, tdfxReg->miscinit0);
1336#endif
1337  pTDFX->writeLong(pTDFX, VIDPROCCFG, tdfxReg->vidcfg);
1338  TDFXWriteLongMMIO(pTDFX, SST_2D_SRCBASEADDR, tdfxReg->srcbaseaddr);
1339  TDFXWriteLongMMIO(pTDFX, SST_2D_DSTBASEADDR, tdfxReg->dstbaseaddr);
1340  for (i=0; i<512; i++) {
1341    count=0;
1342    do {
1343      TDFXWriteLongMMIO(pTDFX, DACADDR, i);
1344      dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
1345    } while (count++<100 && dummy!=i);
1346    count=0;
1347    do {
1348      TDFXWriteLongMMIO(pTDFX, DACDATA, tdfxReg->dactable[i]);
1349      dummy=TDFXReadLongMMIO(pTDFX, DACDATA);
1350    } while (count++<100 && dummy!=tdfxReg->dactable[i]);
1351  }
1352  pTDFX->writeLong(pTDFX, VGAINIT0, tdfxReg->vgainit0);
1353#if 0
1354  pTDFX->writeLong(pTDFX, VGAINIT1, tdfxReg->vgainit1);
1355  pTDFX->writeLong(pTDFX, MISCINIT1, tdfxReg->miscinit1);
1356#endif
1357  vgaHWProtect(pScrn, FALSE);
1358
1359  pTDFX->sync(pScrn);
1360  PrintRegisters(pScrn, tdfxReg);
1361}
1362
1363static void
1364TDFXRestore(ScrnInfoPtr pScrn) {
1365  vgaHWPtr hwp;
1366  TDFXPtr pTDFX;
1367
1368  TDFXTRACE("TDFXRestore start\n");
1369  hwp = VGAHWPTR(pScrn);
1370  pTDFX = TDFXPTR(pScrn);
1371
1372  DoRestore(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
1373}
1374
1375#define REFFREQ 14318.18
1376
1377static int
1378CalcPLL(int freq, int *f_out, int isBanshee) {
1379  int m, n, k, best_m, best_n, best_k, f_cur, best_error;
1380  int minm, maxm;
1381
1382  TDFXTRACE("CalcPLL start\n");
1383  best_error=freq;
1384  best_n=best_m=best_k=0;
1385  if (isBanshee) {
1386    minm=24;
1387    maxm=24;
1388  } else {
1389    minm=1;
1390    maxm=57; /* This used to be 64, alas it seems the last 8 (funny that ?)
1391              * values cause jittering at lower resolutions. I've not done
1392              * any calculations to what the adjustment affects clock ranges,
1393              * but I can still run at 1600x1200@75Hz */
1394  }
1395  for (n=1; n<256; n++) {
1396    f_cur=REFFREQ*(n+2);
1397    if (f_cur<freq) {
1398      f_cur=f_cur/3;
1399      if (freq-f_cur<best_error) {
1400	best_error=freq-f_cur;
1401	best_n=n;
1402	best_m=1;
1403	best_k=0;
1404	continue;
1405      }
1406    }
1407    for (m=minm; m<maxm; m++) {
1408      for (k=0; k<4; k++) {
1409	f_cur=REFFREQ*(n+2)/(m+2)/(1<<k);
1410	if (abs(f_cur-freq)<best_error) {
1411	  best_error=abs(f_cur-freq);
1412	  best_n=n;
1413	  best_m=m;
1414	  best_k=k;
1415	}
1416      }
1417    }
1418  }
1419  n=best_n;
1420  m=best_m;
1421  k=best_k;
1422  *f_out=REFFREQ*(n+2)/(m+2)/(1<<k);
1423  return (n<<8)|(m<<2)|k;
1424}
1425
1426static Bool
1427SetupVidPLL(ScrnInfoPtr pScrn, DisplayModePtr mode) {
1428  TDFXPtr pTDFX;
1429  TDFXRegPtr tdfxReg;
1430  int freq, f_out;
1431
1432  TDFXTRACE("SetupVidPLL start\n");
1433  pTDFX = TDFXPTR(pScrn);
1434  tdfxReg = &pTDFX->ModeReg;
1435  freq=mode->Clock;
1436  tdfxReg->dacmode&=~SST_DAC_MODE_2X;
1437  tdfxReg->vidcfg&=~SST_VIDEO_2X_MODE_EN;
1438  if (freq>TDFX2XCUTOFF) {
1439    if (freq>pTDFX->MaxClock) {
1440      ErrorF("Overclocked PLLs\n");
1441      freq=pTDFX->MaxClock;
1442    }
1443    tdfxReg->dacmode|=SST_DAC_MODE_2X;
1444    tdfxReg->vidcfg|=SST_VIDEO_2X_MODE_EN;
1445  }
1446  tdfxReg->vidpll=CalcPLL(freq, &f_out, 0);
1447  TDFXTRACEREG("Vid PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1448     tdfxReg->vidpll);
1449  return TRUE;
1450}
1451
1452#if 0
1453static Bool
1454SetupMemPLL(int freq) {
1455  TDFXPtr pTDFX;
1456  vgaTDFXPtr tdfxReg;
1457  int f_out;
1458
1459  TDFXTRACE("SetupMemPLL start\n");
1460  pTDFX=TDFXPTR();
1461  tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
1462  tdfxReg->mempll=CalcPLL(freq, &f_out);
1463  pTDFX->writeLong(pTDFX, PLLCTRL1, tdfxReg->mempll);
1464  TDFXTRACEREG("Mem PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1465     tdfxReg->mempll);
1466  return TRUE;
1467}
1468
1469static Bool
1470SetupGfxPLL(int freq) {
1471  TDFXPtr pTDFX;
1472  vgaTDFXPtr tdfxReg;
1473  int f_out;
1474
1475  TDFXTRACE("SetupGfxPLL start\n");
1476  pTDFX=TDFXPTR();
1477  tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
1478  if (pTDFX->chipType==PCI_CHIP_BANSHEE)
1479    tdfxReg->gfxpll=CalcPLL(freq, &f_out, 1);
1480  else
1481    tdfxReg->gfxpll=CalcPLL(freq, &f_out, 0);
1482  pTDFX->writeLong(pTDFX, PLLCTRL2, tdfxReg->gfxpll);
1483  TDFXTRACEREG("Gfx PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1484     tdfxReg->gfxpll);
1485  return TRUE;
1486}
1487#endif
1488
1489#if 0
1490static Bool
1491TDFXInitWithBIOSData(ScrnInfoPtr pScrn)
1492{
1493  TDFXPtr pTDFX;
1494  unsigned char *bios = NULL;
1495  int offset1, offset2;
1496  int i;
1497  CARD32 uint[9];
1498
1499  pTDFX=TDFXPTR(pScrn);
1500
1501  if (pTDFX->initDone)
1502    return TRUE;
1503
1504  if (pTDFX->Primary) {
1505    uint[0] = pTDFX->readLong(pTDFX, PCIINIT0);
1506    uint[1] = pTDFX->readLong(pTDFX, MISCINIT0);
1507    uint[2] = pTDFX->readLong(pTDFX, MISCINIT1);
1508    uint[3] = pTDFX->readLong(pTDFX, DRAMINIT0);
1509    uint[4] = pTDFX->readLong(pTDFX, DRAMINIT1);
1510    uint[5] = pTDFX->readLong(pTDFX, AGPINIT);
1511    uint[6] = pTDFX->readLong(pTDFX, PLLCTRL1);
1512    uint[7] = pTDFX->readLong(pTDFX, PLLCTRL2);
1513    for (i = 0; i < 8; i++) {
1514      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Primary UINT32[%d] is 0x%08lx\n", i, uint[i]);
1515    }
1516    return TRUE;
1517  }
1518
1519#define T_B_SIZE (64 * 1024)
1520  bios = xcalloc(T_B_SIZE, 1);
1521  if (!bios)
1522    return FALSE;
1523
1524  if (!xf86ReadPciBIOS(0, pTDFX->PciTag[0], 1, bios, T_B_SIZE)) {
1525#if 0
1526    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS read.\n");
1527    xfree(bios);
1528    return FALSE;
1529#endif
1530  }
1531
1532  if (bios[0] != 0x55 || bios[1] != 0xAA) {
1533    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS signature.\n");
1534    xfree(bios);
1535    return FALSE;
1536  }
1537
1538  offset1 = bios[0x50] | (bios[0x51] << 8);
1539  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 1 is (0x%04x)\n", offset1);
1540  offset2 = bios[offset1] | (bios[offset1 + 1] << 8);
1541  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 2 is (0x%04x)\n", offset2);
1542
1543  for (i = 0; i < 9; i++) {
1544    int o;
1545
1546    o = offset2 + i * 4;
1547    uint[i] = bios[o] | (bios[o+1] << 8) | (bios[o+2] << 16) | (bios[o+3] << 24);
1548    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UINT32[%d] is 0x%08lx\n", i, uint[i]);
1549  }
1550
1551#if 1
1552  uint[0] = 0x0584fb04;
1553  uint[1] = 0x00000000;
1554  uint[2] = 0x03000001;
1555  uint[3] = 0x0c17a9e9;
1556  uint[4] = 0x00202031;
1557  uint[5] = 0x8000049e;
1558  uint[6] = 0x00003a05;
1559  uint[7] = 0x00000c00;
1560#endif
1561
1562  pTDFX->writeLong(pTDFX, PCIINIT0, uint[0]);
1563  pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
1564  pTDFX->writeLong(pTDFX, MISCINIT1, uint[2]);
1565  pTDFX->writeLong(pTDFX, DRAMINIT0, uint[3]);
1566  pTDFX->writeLong(pTDFX, DRAMINIT1, uint[4]);
1567  pTDFX->writeLong(pTDFX, AGPINIT, uint[5]);
1568  pTDFX->writeLong(pTDFX, PLLCTRL1, uint[6]);
1569  pTDFX->writeLong(pTDFX, PLLCTRL2, uint[7]);
1570#if 0
1571  pTDFX->writeLong(pTDFX, DRAMCOMMAND, uint[8]);
1572#endif
1573
1574  /* reset */
1575  pTDFX->writeLong(pTDFX, MISCINIT0, 0xF3);
1576  pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
1577
1578  xfree(bios);
1579  return TRUE;
1580}
1581#endif
1582
1583
1584static Bool
1585TDFXInitVGA(ScrnInfoPtr pScrn)
1586{
1587  TDFXPtr pTDFX;
1588  TDFXRegPtr tdfxReg;
1589
1590  TDFXTRACE("TDFXInitVGA start\n");
1591  pTDFX=TDFXPTR(pScrn);
1592  if (pTDFX->initDone) return TRUE;
1593  pTDFX->initDone=TRUE;
1594
1595  tdfxReg = &pTDFX->ModeReg;
1596  tdfxReg->vgainit0 = 0;
1597  tdfxReg->vgainit0 |= SST_VGA0_EXTENSIONS;
1598  tdfxReg->vgainit0 |= SST_WAKEUP_3C3 << SST_VGA0_WAKEUP_SELECT_SHIFT;
1599#if USE_PCIVGAIO
1600  tdfxReg->vgainit0 |= SST_VGA0_LEGACY_DECODE;
1601#endif
1602  tdfxReg->vgainit0 |= SST_ENABLE_ALT_READBACK << SST_VGA0_CONFIG_READBACK_SHIFT;
1603  tdfxReg->vgainit0 |= SST_CLUT_SELECT_8BIT << SST_VGA0_CLUT_SELECT_SHIFT;
1604
1605  tdfxReg->vgainit0 |= BIT(12);
1606#if 0
1607  tdfxReg->vgainit1 |= 0;
1608  tdfxReg->miscinit1 = 0;
1609#endif
1610
1611  tdfxReg->vidcfg = SST_VIDEO_PROCESSOR_EN | SST_CURSOR_X11 | SST_DESKTOP_EN |
1612    (pTDFX->cpp-1)<<SST_DESKTOP_PIXEL_FORMAT_SHIFT;
1613
1614  /* tdfxReg->vidcfg |= SST_DESKTOP_CLUT_BYPASS; */
1615
1616  tdfxReg->stride = pTDFX->stride;
1617
1618  tdfxReg->clip0min = tdfxReg->clip1min = 0;
1619  tdfxReg->clip0max = tdfxReg->clip1max = pTDFX->maxClip;
1620
1621  return TRUE;
1622}
1623
1624static Bool
1625TDFXSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) {
1626  TDFXPtr pTDFX;
1627  TDFXRegPtr tdfxReg;
1628  vgaRegPtr pVga;
1629  int hbs, hbe, vbs, vbe, hse;
1630  int hd, hss, ht, vt, vd;
1631
1632  TDFXTRACE("TDFXSetMode start\n");
1633
1634  pTDFX = TDFXPTR(pScrn);
1635  tdfxReg = &pTDFX->ModeReg;
1636  pVga = &VGAHWPTR(pScrn)->ModeReg;
1637
1638  /* Tell the board we're using a programmable clock */
1639  pVga->MiscOutReg |= 0xC;
1640
1641  /* Calculate the CRTC values */
1642  hd = (mode->CrtcHDisplay>>3)-1;
1643  hss = (mode->CrtcHSyncStart>>3);
1644  hse = (mode->CrtcHSyncEnd>>3);
1645  ht = (mode->CrtcHTotal>>3)-5;
1646  hbs = (mode->CrtcHBlankStart>>3)-1;
1647  hbe = (mode->CrtcHBlankEnd>>3)-1;
1648
1649  vd = mode->CrtcVDisplay-1;
1650  vt = mode->CrtcVTotal-2;
1651  vbs = mode->CrtcVBlankStart-1;
1652  vbe = mode->CrtcVBlankEnd-1;
1653
1654  /* Undo the "KGA fixes" */
1655  pVga->CRTC[3] = (hbe&0x1F)|0x80;
1656  pVga->CRTC[5] = (((hbe)&0x20)<<2) | (hse&0x1F);
1657  pVga->CRTC[22] =vbe&0xFF;
1658
1659  /* Handle the higher resolution modes */
1660  tdfxReg->ExtVga[0] = (ht&0x100)>>8 | (hd&0x100)>>6 | (hbs&0x100)>>4 |
1661    (hbe&0x40)>>1 | (hss&0x100)>>2 | (hse&0x20)<<2;
1662
1663  tdfxReg->ExtVga[1] = (vt&0x400)>>10 | (vd&0x400)>>8 | (vbs&0x400)>>6 |
1664    (vbe&0x400)>>4;
1665
1666  if (!SetupVidPLL(pScrn, mode)) return FALSE;
1667
1668  /* Set the screen size */
1669  if (mode->Flags&V_DBLSCAN) {
1670    pVga->CRTC[9] |= 0x80;
1671    tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<13);
1672    tdfxReg->vidcfg |= SST_HALF_MODE;
1673  } else {
1674    tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<12);
1675    tdfxReg->vidcfg &= ~SST_HALF_MODE;
1676  }
1677  if (mode->Flags&V_INTERLACE) {
1678    tdfxReg->vidcfg|=SST_INTERLACE;
1679  } else
1680    tdfxReg->vidcfg&=~SST_INTERLACE;
1681
1682  TDFXTRACEREG("cpp=%d Hdisplay=%d Vdisplay=%d stride=%d screensize=%x\n",
1683	     pTDFX->cpp, mode->HDisplay, mode->VDisplay, tdfxReg->stride,
1684	     tdfxReg->screensize);
1685
1686  return TRUE;
1687}
1688
1689static Bool
1690TDFXModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1691{
1692  vgaHWPtr hwp;
1693  TDFXPtr pTDFX;
1694  int hd, hbs, hss, hse, hbe, ht, hskew;
1695  Bool dbl;
1696
1697  hd = hbs = hss = hse = hbe = ht = hskew = 0;
1698  hwp = VGAHWPTR(pScrn);
1699  pTDFX = TDFXPTR(pScrn);
1700
1701  TDFXTRACE("TDFXModeInit start\n");
1702  dbl=FALSE;
1703  /* Check for 2x mode and halve all the timing values */
1704  if (mode->Clock>TDFX2XCUTOFF) {
1705    hd=mode->CrtcHDisplay;
1706    hbs=mode->CrtcHBlankStart;
1707    hss=mode->CrtcHSyncStart;
1708    hse=mode->CrtcHSyncEnd;
1709    hbe=mode->CrtcHBlankEnd;
1710    ht=mode->CrtcHTotal;
1711    hskew=mode->CrtcHSkew;
1712    mode->CrtcHDisplay=hd>>1;
1713    mode->CrtcHBlankStart=hbs>>1;
1714    mode->CrtcHSyncStart=hss>>1;
1715    mode->CrtcHSyncEnd=hse>>1;
1716    mode->CrtcHBlankEnd=hbe>>1;
1717    mode->CrtcHTotal=ht>>1;
1718    mode->CrtcHSkew=hskew>>1;
1719    dbl=TRUE;
1720  }
1721
1722  vgaHWUnlock(hwp);
1723
1724  if (!vgaHWInit(pScrn, mode)) return FALSE;
1725
1726  pScrn->vtSema = TRUE;
1727
1728  if (!TDFXSetMode(pScrn, mode)) return FALSE;
1729
1730  if (dbl) {
1731    mode->CrtcHDisplay=hd;
1732    mode->CrtcHBlankStart=hbs;
1733    mode->CrtcHSyncStart=hss;
1734    mode->CrtcHSyncEnd=hse;
1735    mode->CrtcHBlankEnd=hbe;
1736    mode->CrtcHTotal=ht;
1737    mode->CrtcHSkew=hskew;
1738  }
1739
1740#ifdef XF86DRI
1741  if (pTDFX->directRenderingEnabled) {
1742    DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
1743    TDFXSwapContextFifo(screenInfo.screens[pScrn->scrnIndex]);
1744  }
1745#endif
1746  DoRestore(pScrn, &hwp->ModeReg, &pTDFX->ModeReg, FALSE);
1747#ifdef XF86DRI
1748  if (pTDFX->directRenderingEnabled) {
1749    DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
1750  }
1751#endif
1752
1753  return TRUE;
1754}
1755
1756static void
1757TDFXLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1758		  VisualPtr pVisual) {
1759  TDFXPtr pTDFX;
1760  int i, j, index, v, repeat, max;
1761
1762  TDFXTRACE("TDFXLoadPalette16 start\n");
1763  pTDFX = TDFXPTR(pScrn);
1764
1765  for (i=0; i<numColors; i++) {
1766    index=indices[i];
1767    v=(colors[index/2].red<<16)|(colors[index].green<<8)|colors[index/2].blue;
1768    max=min((index+1)<<2, 256);
1769    for (j = index<<2; j < max; j++)
1770    {
1771      repeat=100;
1772      do {
1773	TDFXWriteLongMMIO(pTDFX, DACADDR, j);
1774      } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=j);
1775      if (!repeat) {
1776	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, bypassing CLUT\n");
1777	pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1778	return;
1779      }
1780
1781      repeat=100;
1782      do {
1783	TDFXWriteLongMMIO(pTDFX, DACDATA, v);
1784      } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
1785      if (!repeat) {
1786	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, bypassing CLUT\n");
1787	pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1788	return;
1789      }
1790    }
1791  }
1792}
1793
1794static void
1795TDFXLoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1796		  VisualPtr pVisual) {
1797  TDFXPtr pTDFX;
1798  int i, index, v, repeat;
1799
1800  TDFXTRACE("TDFXLoadPalette24 start\n");
1801  pTDFX = TDFXPTR(pScrn);
1802  for (i=0; i<numColors; i++) {
1803    index=indices[i];
1804    v=(colors[index].red<<16)|(colors[index].green<<8)|colors[index].blue;
1805    repeat=100;
1806    do {
1807      TDFXWriteLongMMIO(pTDFX, DACADDR, index);
1808    } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=index);
1809    if (!repeat) {
1810      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, "
1811		 "bypassing CLUT\n");
1812      pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1813      return;
1814    }
1815    repeat=100;
1816    do {
1817      TDFXWriteLongMMIO(pTDFX, DACDATA, v);
1818    } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
1819    if (!repeat) {
1820      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, "
1821		 "bypassing CLUT\n");
1822      pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1823      return;
1824    }
1825  }
1826}
1827
1828#define TILE_WIDTH 128
1829#define TILE_HEIGHT 32
1830
1831static int
1832calcBufferStride(int xres, Bool tiled, int cpp)
1833{
1834  int strideInTiles;
1835
1836  if (tiled == TRUE) {
1837    /* Calculate tile width stuff */
1838    strideInTiles = (xres+TILE_WIDTH-1)/TILE_WIDTH;
1839
1840    return strideInTiles*cpp*TILE_WIDTH;
1841  } else {
1842    return xres*cpp;
1843  }
1844} /* calcBufferStride */
1845
1846static int
1847calcBufferHeightInTiles(int yres)
1848{
1849  int heightInTiles;            /* Height of buffer in tiles */
1850
1851
1852  /* Calculate tile height stuff */
1853  heightInTiles = yres >> 5;
1854
1855  if (yres & (TILE_HEIGHT - 1))
1856    heightInTiles++;
1857
1858  return heightInTiles;
1859
1860} /* calcBufferHeightInTiles */
1861
1862#if 0
1863static int
1864calcBufferSizeInTiles(int xres, int yres, int cpp) {
1865  int bufSizeInTiles;           /* Size of buffer in tiles */
1866
1867  bufSizeInTiles =
1868    calcBufferHeightInTiles(yres) * (calcBufferStride(xres, TRUE, cpp) >> 7);
1869
1870  return bufSizeInTiles;
1871
1872} /* calcBufferSizeInTiles */
1873#endif
1874
1875static int
1876calcBufferSize(int xres, int yres, Bool tiled, int cpp)
1877{
1878  int stride, height, bufSize;
1879
1880  if (tiled) {
1881    stride = calcBufferStride(xres, tiled, cpp);
1882    height = TILE_HEIGHT * calcBufferHeightInTiles(yres);
1883  } else {
1884    stride = xres*cpp;
1885    height = yres;
1886  }
1887
1888  bufSize = stride * height;
1889
1890  return bufSize;
1891
1892} /* calcBufferSize */
1893
1894static void allocateMemory(ScrnInfoPtr pScrn) {
1895  TDFXPtr pTDFX;
1896  int memRemaining, fifoSize, screenSizeInTiles, cursorSize;
1897  int fbSize;
1898  int verb;
1899  char *str;
1900
1901  pTDFX = TDFXPTR(pScrn);
1902
1903  if (pTDFX->cpp!=3) {
1904    screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
1905				     TRUE, pTDFX->cpp);
1906  }
1907  else {
1908    /* cpp==3 needs to bump up to 4 */
1909    screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
1910				     TRUE, 4);
1911  }
1912
1913  /*
1914   * Layout is:
1915   *    cursor, fifo, fb, tex, bb, db
1916   */
1917
1918  fbSize = (pScrn->virtualY + pTDFX->pixmapCacheLinesMin) * pTDFX->stride;
1919
1920  memRemaining=((pScrn->videoRam<<10) - 1) &~ 0xFFF;
1921  /* Note that a page is 4096 bytes, and a  */
1922  /* tile is 32 x 128 = 4096 bytes.  So,    */
1923  /* page and tile boundaries are the same  */
1924  /* Place the depth offset first, forcing  */
1925  /* it to be on an *odd* page boundary.    */
1926  pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF;
1927  if ((pTDFX->depthOffset & (0x1 << 12)) == 0) {
1928#if	1
1929    if (pTDFX->depthOffset > 0) {
1930      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1931                 "Changing depth offset from 0x%08x to 0x%08x\n",
1932                 pTDFX->depthOffset,
1933                 pTDFX->depthOffset - (0x1 << 12));
1934    }
1935#endif
1936      pTDFX->depthOffset -= (0x1 << 12);
1937  }
1938  /* Now, place the back buffer, forcing it */
1939  /* to be on an *even* page boundary.      */
1940  pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF;
1941  if (pTDFX->backOffset & (0x1 << 12)) {
1942#if	1
1943    if (pTDFX->backOffset > 0) {
1944      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1945                 "Changing back offset from 0x%08x to 0x%08x\n",
1946                 pTDFX->backOffset,
1947                 pTDFX->backOffset - (0x1 << 12));
1948    }
1949#endif
1950      pTDFX->backOffset -= (0x1 << 12);
1951  }
1952  /* Give the cmd fifo at least             */
1953  /* CMDFIFO_PAGES pages, but no more than  */
1954  /* 64. NOTE: Don't go higher than 64, as  */
1955  /* there is suspect code in Glide3 !      */
1956  fifoSize = ((64 <= CMDFIFO_PAGES) ? 64 : CMDFIFO_PAGES) << 12;
1957
1958  /* We give 4096 bytes to the cursor  */
1959  cursorSize = 4096;
1960  pTDFX->cursorOffset = 0;
1961
1962  pTDFX->fifoOffset = pTDFX->cursorOffset + cursorSize;
1963  pTDFX->fifoSize = fifoSize;
1964  /* Now, place the front buffer, forcing   */
1965  /* it to be on a page boundary too, just  */
1966  /* for giggles.                           */
1967  pTDFX->fbOffset = pTDFX->fifoOffset + pTDFX->fifoSize;
1968  pTDFX->texOffset = pTDFX->fbOffset + fbSize;
1969  if (pTDFX->depthOffset <= pTDFX->texOffset ||
1970	pTDFX->backOffset <= pTDFX->texOffset) {
1971    /*
1972     * pTDFX->texSize < 0 means that the DRI is disabled.  pTDFX->backOffset
1973     * is used to calculate the maximum amount of memory available for
1974     * 2D offscreen use.  With DRI disabled, set this to the top of memory.
1975     */
1976
1977    pTDFX->texSize = -1;
1978    pTDFX->backOffset = pScrn->videoRam * 1024;
1979    pTDFX->depthOffset = -1;
1980    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1981	"Not enough video memory available for textures and depth buffer\n"
1982	"\tand/or back buffer.  Disabling DRI.  To use DRI try lower\n"
1983	"\tresolution modes and/or a smaller virtual screen size\n");
1984  } else {
1985    pTDFX->texSize = pTDFX->backOffset - pTDFX->texOffset;
1986    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textures Memory %0.02f MB\n",
1987		(float)pTDFX->texSize/1024.0/1024.0);
1988  }
1989
1990/* This could be set to 2 or 3 */
1991#define OFFSET_VERB 1
1992  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
1993             "Cursor Offset: [0x%08X,0x%08X)\n",
1994             pTDFX->cursorOffset,
1995             pTDFX->cursorOffset + cursorSize);
1996  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
1997             "Fifo Offset: [0x%08X, 0x%08X)\n",
1998             pTDFX->fifoOffset,
1999             pTDFX->fifoOffset + pTDFX->fifoSize);
2000  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
2001             "Front Buffer Offset: [0x%08X, 0x%08X)\n",
2002             pTDFX->fbOffset,
2003             pTDFX->fbOffset +
2004		(pScrn->virtualY+pTDFX->pixmapCacheLinesMin)*pTDFX->stride);
2005  if (pTDFX->texSize > 0) {
2006    verb = OFFSET_VERB;
2007    str = "";
2008  } else {
2009    verb = 3;
2010    str = "(NOT USED) ";
2011  }
2012  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2013             "%sTexture Offset: [0x%08X, 0x%08X)\n", str,
2014             pTDFX->texOffset,
2015             pTDFX->texOffset + pTDFX->texSize);
2016  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2017             "%sBackOffset: [0x%08X, 0x%08X)\n", str,
2018             pTDFX->backOffset,
2019             pTDFX->backOffset + screenSizeInTiles);
2020  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2021             "%sDepthOffset: [0x%08X, 0x%08X)\n", str,
2022             pTDFX->depthOffset,
2023             pTDFX->depthOffset + screenSizeInTiles);
2024}
2025
2026static Bool
2027TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
2028  ScrnInfoPtr pScrn;
2029  vgaHWPtr hwp;
2030  TDFXPtr pTDFX;
2031  VisualPtr visual;
2032  BoxRec MemBox;
2033#ifdef XF86DRI
2034  MessageType driFrom = X_DEFAULT;
2035#endif
2036  int scanlines;
2037
2038  TDFXTRACE("TDFXScreenInit start\n");
2039  pScrn = xf86Screens[pScreen->myNum];
2040  pTDFX = TDFXPTR(pScrn);
2041  hwp = VGAHWPTR(pScrn);
2042
2043  if (!TDFXMapMem(pScrn)) return FALSE;
2044  pScrn->memPhysBase = (int)pTDFX->LinearAddr[0];
2045
2046  if (!pTDFX->usePIO) TDFXSetMMIOAccess(pTDFX);
2047
2048#if USE_PCIVGAIO
2049  hwp->PIOOffset = pTDFX->PIOBase[0] - 0x300;
2050#endif
2051  vgaHWGetIOBase(hwp);
2052  /* Map VGA memory only for primary cards (to save/restore textmode data). */
2053  if (pTDFX->Primary) {
2054    if (!vgaHWMapMem(pScrn))
2055      return FALSE;
2056  }
2057
2058  pTDFX->stride = pScrn->displayWidth*pTDFX->cpp;
2059
2060  /* enough to do DVD */
2061  pTDFX->pixmapCacheLinesMin = ((720*480*pTDFX->cpp) +
2062					pTDFX->stride - 1)/pTDFX->stride;
2063
2064  if (pTDFX->ChipType > PCI_CHIP_VOODOO3) {
2065  	if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 4095)
2066		pTDFX->pixmapCacheLinesMin = 4095 - pScrn->virtualY;
2067  } else {
2068  	if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 2047)
2069		pTDFX->pixmapCacheLinesMin = 2047 - pScrn->virtualY;
2070  }
2071
2072  allocateMemory(pScrn);
2073
2074  pScrn->fbOffset = pTDFX->fbOffset;
2075
2076#if 0
2077  if (pTDFX->numChips>1) {
2078    if (xf86ReturnOptValBool(pTDFX->Options, OPTION_NO_SLI, FALSE)) {
2079      TDFXSetupSLI(pScrn, FALSE, 0);
2080    } else {
2081      TDFXSetupSLI(pScrn, TRUE, 0);
2082    }
2083  }
2084#endif
2085
2086  TDFXSetLFBConfig(pTDFX);
2087
2088  /* We initialize in the state that our FIFO is up to date */
2089  pTDFX->syncDone=TRUE;
2090  if (!TDFXInitFifo(pScreen)) {
2091    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize private\n");
2092    return FALSE;
2093  }
2094
2095  scanlines = (pTDFX->backOffset - pTDFX->fbOffset) / pTDFX->stride;
2096  if(pTDFX->ChipType < PCI_CHIP_VOODOO5) {
2097      if (scanlines > 2047)
2098	scanlines = 2047;
2099  } else {
2100      /* MaxClip seems to have only 12 bits => 0->4095 */
2101      if (scanlines > 4095)
2102	scanlines = 4095;
2103  }
2104
2105  pTDFX->pixmapCacheLinesMax = scanlines - pScrn->virtualY;
2106
2107  /*
2108   * Note, pTDFX->pixmapCacheLinesMax may be smaller than
2109   * pTDFX->pixmapCacheLinesMin when pTDFX->texSize < 0.  DRI is disabled
2110   * in that case, so pTDFX->pixmapCacheLinesMin isn't used when that's true.
2111   */
2112  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2113    "Minimum %d, Maximum %d lines of offscreen memory available\n",
2114	pTDFX->pixmapCacheLinesMin, pTDFX->pixmapCacheLinesMax);
2115
2116  MemBox.y1 = 0;
2117  MemBox.x1 = 0;
2118  MemBox.x2 = pScrn->displayWidth;
2119  MemBox.y2 = scanlines;
2120
2121  pTDFX->maxClip = MemBox.x2 | (MemBox.y2 << 16);
2122
2123#if 0
2124  TDFXInitWithBIOSData(pScrn);
2125#endif
2126  TDFXInitVGA(pScrn);
2127  TDFXSave(pScrn);
2128  if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
2129
2130  TDFXSetLFBConfig(pTDFX);
2131
2132  miClearVisualTypes();
2133
2134  if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
2135			pScrn->rgbBits, pScrn->defaultVisual))
2136    return FALSE;
2137
2138  miSetPixmapDepths ();
2139
2140  pTDFX->NoAccel=xf86ReturnOptValBool(pTDFX->Options, OPTION_NOACCEL, FALSE);
2141#ifdef XF86DRI
2142  /*
2143   * Setup DRI after visuals have been established, but before fbScreenInit
2144   * is called.   fbScreenInit will eventually call into the drivers
2145   * InitGLXVisuals call back.
2146   */
2147  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_DRI, TRUE) || pTDFX->NoAccel) {
2148      pTDFX->directRenderingEnabled = FALSE;
2149      driFrom = X_CONFIG;
2150  } else if (pTDFX->texSize < 0) {
2151      pTDFX->directRenderingEnabled = FALSE;
2152      driFrom = X_PROBED;
2153  } else {
2154      pTDFX->directRenderingEnabled = TDFXDRIScreenInit(pScreen);
2155  }
2156#endif
2157
2158  switch (pScrn->bitsPerPixel) {
2159  case 8:
2160  case 16:
2161  case 24:
2162  case 32:
2163    if (!fbScreenInit(pScreen, pTDFX->FbBase+pTDFX->fbOffset,
2164		       pScrn->virtualX, pScrn->virtualY,
2165		       pScrn->xDpi, pScrn->yDpi,
2166		       pScrn->displayWidth, pScrn->bitsPerPixel))
2167      return FALSE;
2168    break;
2169  default:
2170    xf86DrvMsg(scrnIndex, X_ERROR,
2171	       "Internal error: invalid bpp (%d) in TDFXScrnInit\n",
2172	       pScrn->bitsPerPixel);
2173    return FALSE;
2174  }
2175
2176  if (pScrn->bitsPerPixel>8) {
2177    visual = pScreen->visuals + pScreen->numVisuals;
2178    while (--visual >= pScreen->visuals) {
2179      if ((visual->class | DynamicClass) == DirectColor) {
2180	visual->offsetRed = pScrn->offset.red;
2181	visual->offsetGreen = pScrn->offset.green;
2182	visual->offsetBlue = pScrn->offset.blue;
2183	visual->redMask = pScrn->mask.red;
2184	visual->greenMask = pScrn->mask.green;
2185	visual->blueMask = pScrn->mask.blue;
2186      }
2187    }
2188  }
2189
2190  /* must be after RGB ordering fixed */
2191  fbPictureInit (pScreen, 0, 0);
2192
2193  xf86SetBlackWhitePixels(pScreen);
2194
2195  TDFXDGAInit(pScreen);
2196
2197  xf86InitFBManager(pScreen, &MemBox);
2198
2199  if (!pTDFX->NoAccel) {
2200    if (!TDFXAccelInit(pScreen)) {
2201      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2202		 "Hardware acceleration initialization failed\n");
2203    }
2204  }
2205
2206  miInitializeBackingStore(pScreen);
2207  xf86SetBackingStore(pScreen);
2208  xf86SetSilkenMouse(pScreen);
2209
2210  miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2211
2212  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
2213    if (!TDFXCursorInit(pScreen)) {
2214      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2215		 "Hardware cursor initialization failed\n");
2216    }
2217  }
2218
2219  if (!miCreateDefColormap(pScreen)) return FALSE;
2220
2221  if (pScrn->bitsPerPixel==16) {
2222    if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette16, 0,
2223			     CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
2224      return FALSE;
2225  } else {
2226    if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette24, 0,
2227			     CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
2228      return FALSE;
2229  }
2230
2231  TDFXAdjustFrame(scrnIndex, 0, 0, 0);
2232
2233  xf86DPMSInit(pScreen, TDFXDisplayPowerManagementSet, 0);
2234
2235  /* Initialize Xv support */
2236  TDFXInitVideo (pScreen);
2237
2238  pScreen->SaveScreen = TDFXSaveScreen;
2239  pTDFX->CloseScreen = pScreen->CloseScreen;
2240  pScreen->CloseScreen = TDFXCloseScreen;
2241
2242  pTDFX->BlockHandler = pScreen->BlockHandler;
2243  pScreen->BlockHandler = TDFXBlockHandler;
2244
2245  /*
2246   * DRICloseScreen isn't called thru a wrapper but explicitely
2247   * in of TDFXCloseScreen() before the rest is unwrapped
2248   */
2249
2250#ifdef XF86DRI
2251  if (pTDFX->directRenderingEnabled) {
2252	/* Now that mi, fb, drm and others have done their thing,
2253         * complete the DRI setup.
2254         */
2255	pTDFX->directRenderingEnabled = TDFXDRIFinishScreenInit(pScreen);
2256  }
2257  if (pTDFX->directRenderingEnabled) {
2258	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2259  } else {
2260	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
2261  }
2262#endif
2263
2264  if (serverGeneration == 1)
2265    xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2266
2267  return TRUE;
2268}
2269
2270Bool
2271TDFXSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) {
2272  ScrnInfoPtr pScrn;
2273
2274  TDFXTRACE("TDFXSwitchMode start\n");
2275  pScrn=xf86Screens[scrnIndex];
2276  return TDFXModeInit(pScrn, mode);
2277}
2278
2279void
2280TDFXAdjustFrame(int scrnIndex, int x, int y, int flags) {
2281  ScrnInfoPtr pScrn;
2282  TDFXPtr pTDFX;
2283  TDFXRegPtr tdfxReg;
2284
2285  TDFXTRACE("TDFXAdjustFrame start\n");
2286  pScrn = xf86Screens[scrnIndex];
2287  pTDFX = TDFXPTR(pScrn);
2288
2289  if (pTDFX->ShowCache && y && pScrn->vtSema)
2290    y += pScrn->virtualY - 1;
2291
2292  tdfxReg = &pTDFX->ModeReg;
2293  if(pTDFX->ShowCache && y && pScrn->vtSema)
2294     y += pScrn->virtualY - 1;
2295  tdfxReg->startaddr = pTDFX->fbOffset+y*pTDFX->stride+(x*pTDFX->cpp);
2296  TDFXTRACE("TDFXAdjustFrame to x=%d y=%d offset=%d\n", x, y, tdfxReg->startaddr);
2297  pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
2298}
2299
2300static Bool
2301TDFXEnterVT(int scrnIndex, int flags) {
2302  ScrnInfoPtr pScrn;
2303  ScreenPtr pScreen;
2304#ifdef XF86DRI
2305  TDFXPtr pTDFX;
2306#endif
2307
2308  TDFXTRACE("TDFXEnterVT start\n");
2309  pScrn = xf86Screens[scrnIndex];
2310  pScreen = screenInfo.screens[scrnIndex];
2311  TDFXInitFifo(pScreen);
2312#ifdef XF86DRI
2313  pTDFX = TDFXPTR(pScrn);
2314  if (pTDFX->directRenderingEnabled) {
2315    DRIUnlock(pScreen);
2316  }
2317#endif
2318  if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
2319  TDFXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2320  return TRUE;
2321}
2322
2323static void
2324TDFXLeaveVT(int scrnIndex, int flags) {
2325  ScrnInfoPtr pScrn;
2326  vgaHWPtr hwp;
2327  ScreenPtr pScreen;
2328  TDFXPtr pTDFX;
2329
2330  TDFXTRACE("TDFXLeaveVT start\n");
2331  pScrn = xf86Screens[scrnIndex];
2332  hwp=VGAHWPTR(pScrn);
2333  TDFXRestore(pScrn);
2334  vgaHWLock(hwp);
2335  pScreen = screenInfo.screens[scrnIndex];
2336  pTDFX = TDFXPTR(pScrn);
2337  pTDFX->sync(pScrn);
2338  TDFXShutdownFifo(pScreen);
2339#ifdef XF86DRI
2340  if (pTDFX->directRenderingEnabled) {
2341    DRILock(pScreen, 0);
2342  }
2343#endif
2344}
2345
2346static Bool
2347TDFXCloseScreen(int scrnIndex, ScreenPtr pScreen)
2348{
2349  ScrnInfoPtr pScrn;
2350  vgaHWPtr hwp;
2351  TDFXPtr pTDFX;
2352
2353  TDFXTRACE("TDFXCloseScreen start\n");
2354  pScrn = xf86Screens[scrnIndex];
2355  hwp = VGAHWPTR(pScrn);
2356  pTDFX = TDFXPTR(pScrn);
2357
2358#ifdef XF86DRI
2359    if (pTDFX->directRenderingEnabled) {
2360	TDFXDRICloseScreen(pScreen);
2361	pTDFX->directRenderingEnabled=FALSE;
2362    }
2363#endif
2364
2365  TDFXShutdownFifo(pScreen);
2366
2367  if (pScrn->vtSema) {
2368      TDFXRestore(pScrn);
2369      vgaHWLock(hwp);
2370      TDFXUnmapMem(pScrn);
2371      vgaHWUnmapMem(pScrn);
2372  }
2373
2374  if (pTDFX->AccelInfoRec) XAADestroyInfoRec(pTDFX->AccelInfoRec);
2375  pTDFX->AccelInfoRec=0;
2376  if (pTDFX->DGAModes) xfree(pTDFX->DGAModes);
2377  pTDFX->DGAModes=0;
2378  if (pTDFX->scanlineColorExpandBuffers[0])
2379    xfree(pTDFX->scanlineColorExpandBuffers[0]);
2380  pTDFX->scanlineColorExpandBuffers[0]=0;
2381  if (pTDFX->scanlineColorExpandBuffers[1])
2382    xfree(pTDFX->scanlineColorExpandBuffers[1]);
2383  pTDFX->scanlineColorExpandBuffers[1]=0;
2384  if (pTDFX->overlayAdaptor)
2385    xfree(pTDFX->overlayAdaptor);
2386  pTDFX->overlayAdaptor=0;
2387  if (pTDFX->textureAdaptor)
2388    xfree(pTDFX->textureAdaptor);
2389  pTDFX->textureAdaptor=0;
2390
2391  pScrn->vtSema=FALSE;
2392
2393  pScreen->BlockHandler = pTDFX->BlockHandler;
2394  pScreen->CloseScreen = pTDFX->CloseScreen;
2395  return (*pScreen->CloseScreen)(scrnIndex, pScreen);
2396}
2397
2398static void
2399TDFXFreeScreen(int scrnIndex, int flags) {
2400  TDFXTRACE("TDFXFreeScreen start\n");
2401  TDFXFreeRec(xf86Screens[scrnIndex]);
2402  if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
2403    vgaHWFreeHWRec(xf86Screens[scrnIndex]);
2404}
2405
2406static ModeStatus
2407TDFXValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) {
2408  ScrnInfoPtr pScrn;
2409  TDFXPtr pTDFX;
2410
2411  TDFXTRACE("TDFXValidMode start\n");
2412  if ((mode->HDisplay>2048) || (mode->VDisplay>1536))
2413    return MODE_BAD;
2414  /* Banshee doesn't support interlace, but Voodoo 3 and higher do. */
2415  pScrn = xf86Screens[scrnIndex];
2416  pTDFX = TDFXPTR(pScrn);
2417  if (mode->Flags&V_INTERLACE) {
2418    switch (pTDFX->ChipType) {
2419      case PCI_CHIP_BANSHEE:
2420        return MODE_BAD;
2421        break;
2422      case PCI_CHIP_VOODOO3:
2423      case PCI_CHIP_VOODOO5:
2424        return MODE_OK;
2425        break;
2426      default:
2427        return MODE_BAD;
2428        break;
2429    }
2430  }
2431  /* In clock doubled mode widths must be divisible by 16 instead of 8 */
2432  if ((mode->Clock>TDFX2XCUTOFF) && (mode->HDisplay%16))
2433    return MODE_BAD;
2434  return MODE_OK;
2435}
2436
2437/* replacement of vgaHWBlankScreen(pScrn, unblank) which doesn't unblank
2438 * the screen if it is already unblanked. */
2439static void
2440TDFXBlankScreen(ScrnInfoPtr pScrn, Bool unblank)
2441{
2442  vgaHWPtr hwp = VGAHWPTR(pScrn);
2443  unsigned char scrn;
2444
2445  TDFXTRACE("TDFXBlankScreen start\n");
2446
2447  scrn = hwp->readSeq(hwp, 0x01);
2448
2449  if (unblank) {
2450    if((scrn & 0x20) == 0) return;
2451    scrn &= ~0x20;                    /* enable screen */
2452  } else {
2453    scrn |= 0x20;                     /* blank screen */
2454  }
2455
2456  vgaHWSeqReset(hwp, TRUE);
2457  hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
2458  vgaHWSeqReset(hwp, FALSE);
2459}
2460
2461static Bool
2462TDFXSaveScreen(ScreenPtr pScreen, int mode)
2463{
2464  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2465  Bool unblank;
2466
2467  TDFXTRACE("TDFXSaveScreen start\n");
2468
2469  unblank = xf86IsUnblank(mode);
2470
2471  if (unblank)
2472    SetTimeSinceLastInputEvent();
2473
2474  if (pScrn->vtSema) {
2475    TDFXBlankScreen(pScrn, unblank);
2476  }
2477  return TRUE;
2478}
2479
2480static void
2481TDFXBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
2482{
2483    ScreenPtr   pScreen = screenInfo.screens[i];
2484    ScrnInfoPtr pScrn   = xf86Screens[i];
2485    TDFXPtr     pTDFX   = TDFXPTR(pScrn);
2486
2487    pScreen->BlockHandler = pTDFX->BlockHandler;
2488    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
2489    pScreen->BlockHandler = TDFXBlockHandler;
2490
2491    if(pTDFX->VideoTimerCallback) {
2492        (*pTDFX->VideoTimerCallback)(pScrn, currentTime.milliseconds);
2493    }
2494}
2495
2496static void
2497TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
2498			      int flags) {
2499  TDFXPtr pTDFX;
2500  int dacmode, state=0;
2501
2502  TDFXTRACE("TDFXDPMS start\n");
2503  pTDFX = TDFXPTR(pScrn);
2504  dacmode=pTDFX->readLong(pTDFX, DACMODE);
2505  switch (PowerManagementMode) {
2506  case DPMSModeOn:
2507    /* Screen: On; HSync: On, VSync: On */
2508    state=0;
2509    break;
2510  case DPMSModeStandby:
2511    /* Screen: Off; HSync: Off, VSync: On */
2512    state=BIT(3);
2513    break;
2514  case DPMSModeSuspend:
2515    /* Screen: Off; HSync: On, VSync: Off */
2516    state=BIT(1);
2517    break;
2518  case DPMSModeOff:
2519    /* Screen: Off; HSync: Off, VSync: Off */
2520    state=BIT(1)|BIT(3);
2521    break;
2522  }
2523  dacmode&=~(BIT(1)|BIT(3));
2524  dacmode|=state;
2525  pTDFX->writeLong(pTDFX, DACMODE, dacmode);
2526}
2527