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