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