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