tdfx_driver.c revision 3a56a767
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       * XXX
664       * Do not fudge BARs with only one chip present.
665       * Now this works again on NetBSD/macppc.
666       */
667      pTDFX->MMIOAddr[0] = mem0base & 0xffffff00;
668      pTDFX->LinearAddr[0] = mem1base & 0xffffff00;
669    } else {
670      for (i = 0; i < pTDFX->numChips; i++) {
671	PCI_WRITE_LONG(initbits | BIT(10), CFG_INIT_ENABLE, i);
672
673	#if 0
674		v=pciReadWord(pTDFX->PciTag[i], CFG_PCI_COMMAND);
675		if (!i)
676		    pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v | 0x3);
677		else
678		    pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v | 0x2);
679	#endif
680
681	pTDFX->MMIOAddr[i] = mem0base + (i * mem0size);
682
683	PCI_WRITE_LONG(pTDFX->MMIOAddr[i], CFG_MEM0BASE, i);
684
685	pTDFX->MMIOAddr[i] &= 0xFFFFFF00;
686	pTDFX->LinearAddr[i] = mem1base + (i * mem1size);
687
688	PCI_WRITE_LONG(pTDFX->LinearAddr[i], CFG_MEM1BASE, i);
689
690	pTDFX->LinearAddr[i] &= 0xFFFFFF00;
691
692	PCI_WRITE_LONG(cfgbits, CFG_PCI_DECODE, i);
693	PCI_WRITE_LONG(initbits, CFG_INIT_ENABLE, i);
694      }
695    }
696    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
697		       "TDFXInitChips: MMIOAddr[%d] = 0x%08lx\n",
698		       0, pTDFX->MMIOAddr[0]);
699    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
700		       "TDFXInitChips: LinearAddr[%d] = 0x%08lx\n",
701		       0, pTDFX->LinearAddr[0]);
702}
703
704void
705TDFXPutBits(I2CBusPtr b, int  scl, int  sda)
706{
707  TDFXPtr pTDFX= b->DriverPrivate.ptr;
708  CARD32 reg;
709
710  reg = pTDFX->readLong(pTDFX, VIDSERIALPARALLELPORT);
711  reg = (reg & ~(VSP_SDA0_OUT | VSP_SCL0_OUT)) |
712  	(scl ? VSP_SCL0_OUT : 0) |
713  	(sda ? VSP_SDA0_OUT : 0);
714  pTDFX->writeLong(pTDFX, VIDSERIALPARALLELPORT, reg);
715}
716
717void
718TDFXGetBits(I2CBusPtr b, int *scl, int *sda)
719{
720  TDFXPtr pTDFX = b->DriverPrivate.ptr;
721  CARD32 reg;
722
723  reg = pTDFX->readLong(pTDFX, VIDSERIALPARALLELPORT);
724  *sda = (reg & VSP_SDA0_IN) ? 1 : 0;
725  *scl = (reg & VSP_SCL0_IN) ? 1 : 0;
726}
727
728Bool TDFXI2cInit(ScrnInfoPtr pScrn)
729{
730  TDFXPtr pTDFX = TDFXPTR(pScrn);
731
732  if (!(pTDFX->pI2CBus = xf86CreateI2CBusRec()))
733  {
734    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unable to allocate I2C Bus record.\n");
735    return FALSE;
736  }
737
738  /* Fill in generic structure fields */
739  pTDFX->pI2CBus->BusName           = "DDC";
740  pTDFX->pI2CBus->scrnIndex         = pScrn->scrnIndex;
741  pTDFX->pI2CBus->I2CPutBits        = TDFXPutBits;
742  pTDFX->pI2CBus->I2CGetBits        = TDFXGetBits;
743  pTDFX->pI2CBus->DriverPrivate.ptr = pTDFX;
744
745  /* longer timeouts as per the vesa spec */
746  pTDFX->pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
747  pTDFX->pI2CBus->StartTimeout = 550;
748  pTDFX->pI2CBus->BitTimeout = 40;
749  pTDFX->pI2CBus->ByteTimeout = 40;
750  pTDFX->pI2CBus->AcknTimeout = 40;
751
752  if (!xf86I2CBusInit(pTDFX->pI2CBus)) {
753    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unable to init I2C Bus.\n");
754    return FALSE;
755  }
756  return TRUE;
757}
758
759static xf86MonPtr doTDFXDDC(ScrnInfoPtr pScrn)
760{
761  TDFXPtr pTDFX = TDFXPTR(pScrn);
762  I2CBusPtr pI2CBus;
763  xf86MonPtr pMon = NULL;
764  CARD32 reg;
765
766  reg = pTDFX->readLong(pTDFX, VIDSERIALPARALLELPORT);
767  pTDFX->writeLong(pTDFX, VIDSERIALPARALLELPORT, reg | VSP_ENABLE_IIC0);
768
769  pMon = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pTDFX->pI2CBus);
770
771  if (pMon == NULL)
772    xf86Msg(X_WARNING, "No DDC2 capable monitor found\n");
773
774  pTDFX->writeLong(pTDFX, VIDSERIALPARALLELPORT, reg);
775
776  return pMon;
777}
778
779/*
780 * TDFXPreInit --
781 *
782 * Do initial setup of the board before we know what resolution we will
783 * be running at.
784 *
785 */
786static Bool
787TDFXPreInit(ScrnInfoPtr pScrn, int flags)
788{
789  TDFXPtr pTDFX;
790  ClockRangePtr clockRanges;
791  xf86MonPtr pMon;
792  int i;
793  MessageType from;
794  int flags24;
795  rgb defaultWeight = {0, 0, 0};
796#ifdef XSERVER_LIBPCIACCESS
797    struct pci_device *match;
798#else
799  pciVideoPtr match;
800#endif
801  int availableMem;
802
803  TDFXTRACE("TDFXPreInit start\n");
804  if (pScrn->numEntities != 1) return FALSE;
805
806#ifndef XSERVER_LIBPCIACCESS
807  /* Allocate driverPrivate */
808  pTDFX = TDFXGetRec(pScrn);
809  if (pTDFX == NULL) {
810    return FALSE;
811  }
812
813
814  pTDFX->initDone=FALSE;
815  pTDFX->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
816#else
817    pTDFX = TDFXPTR(pScrn);
818#endif
819
820  if (flags & PROBE_DETECT) {
821#if !defined(__powerpc__)
822    TDFXProbeDDC(pScrn, pTDFX->pEnt->index);
823    return TRUE;
824#else
825    return FALSE;
826#endif
827  }
828
829  if (pTDFX->pEnt->location.type != BUS_PCI) return FALSE;
830
831  /* The vgahw module should be loaded here when needed */
832  if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
833
834  /* Allocate a vgaHWRec */
835  if (!vgaHWGetHWRec(pScrn)) return FALSE;
836  vgaHWSetStdFuncs(VGAHWPTR(pScrn));
837
838#if USE_INT10
839#if !defined(__powerpc__)
840  if (xf86LoadSubModule(pScrn, "int10")) {
841    xf86Int10InfoPtr pInt;
842
843    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
844               "Softbooting the board (through the int10 interface).\n");
845    pInt = xf86InitInt10(pTDFX->pEnt->index);
846    if (!pInt)
847    {
848      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
849                 "Softbooting the board failed.\n");
850    }
851    else
852    {
853      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
854                 "Softbooting the board succeeded.\n");
855      xf86FreeInt10(pInt);
856    }
857  }
858#endif
859#endif
860
861#ifdef XSERVER_LIBPCIACCESS
862    match = pTDFX->PciInfo[0];
863    pTDFX->ChipType = DEVICE_ID(match);
864#else
865  match=pTDFX->PciInfo=xf86GetPciInfoForEntity(pTDFX->pEnt->index);
866  TDFXFindChips(pScrn, match);
867  pTDFX->Primary = xf86IsPrimaryPci(pTDFX->PciInfo);
868#endif
869
870#ifndef XSERVER_LIBPCIACCESS
871  if (xf86RegisterResources(pTDFX->pEnt->index, NULL, ResExclusive)) {
872      TDFXFreeRec(pScrn);
873      return FALSE;
874  }
875
876  /*
877   * We don't need VGA resources during OPERATING state. However I'm
878   * not sure if they are disabled.
879   */
880  xf86SetOperatingState(resVgaIo, pTDFX->pEnt->index, ResDisableOpr);
881
882  /* Is VGA memory disabled during OPERATING state? */
883  xf86SetOperatingState(resVgaMem, pTDFX->pEnt->index, ResUnusedOpr);
884    /*
885     * I'm sure we don't need to set these. All resources
886     * for these operations are exclusive.
887     */
888  if (pTDFX->usePIO) {
889      pScrn->racMemFlags = 0;
890      pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
891  } else
892      pScrn->racMemFlags = 0;
893#endif
894  /* Set pScrn->monitor */
895  pScrn->monitor = pScrn->confScreen->monitor;
896
897  flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
898  if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
899    return FALSE;
900  } else {
901    switch (pScrn->depth) {
902    case 8:
903    case 16:
904    case 24:
905      break;
906    default:
907      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
908		 "Given depth (%d) is not supported by tdfx driver\n",
909		 pScrn->depth);
910      return FALSE;
911    }
912  }
913  xf86PrintDepthBpp(pScrn);
914
915  pScrn->rgbBits=8;
916  if (pScrn->depth>8) {
917    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
918      return FALSE;
919  }
920
921  if (!xf86SetDefaultVisual(pScrn, -1)) {
922    return FALSE;
923  } else {
924    /* We don't currently support DirectColor at > 8bpp */
925    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
926      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
927		 " (%s) is not supported at depth %d\n",
928		 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
929      return FALSE;
930    }
931  }
932
933  /* We use a programmable clock */
934  pScrn->progClock = TRUE;
935
936  pTDFX->cpp = pScrn->bitsPerPixel/8;
937
938  /* Process the options */
939  xf86CollectOptions(pScrn, NULL);
940  if (!(pTDFX->Options = malloc(sizeof(TDFXOptions))))
941    return FALSE;
942  memcpy(pTDFX->Options, TDFXOptions, sizeof(TDFXOptions));
943  xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTDFX->Options);
944
945  /*
946   * Set the Chipset and ChipRev, allowing config file entries to
947   * override.
948   */
949  if (pTDFX->pEnt->device->chipset && *pTDFX->pEnt->device->chipset) {
950    pScrn->chipset = pTDFX->pEnt->device->chipset;
951    from = X_CONFIG;
952  } else if (pTDFX->pEnt->device->chipID >= 0) {
953    pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets, pTDFX->pEnt->device->chipID);
954    from = X_CONFIG;
955    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
956	       pTDFX->pEnt->device->chipID);
957  } else {
958    from = X_PROBED;
959    pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets,
960					       DEVICE_ID(match));
961  }
962  if (pTDFX->pEnt->device->chipRev >= 0) {
963    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
964	       pTDFX->pEnt->device->chipRev);
965  }
966
967  xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
968
969  if (pTDFX->pEnt->device->MemBase != 0) {
970    pTDFX->LinearAddr[0] = pTDFX->pEnt->device->MemBase;
971    from = X_CONFIG;
972  } else {
973    if (PCI_MEM_BASE(match, 1) != 0) {
974      pTDFX->LinearAddr[0] = PCI_MEM_BASE(match, 1);
975      from = X_PROBED;
976    } else {
977      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
978		 "No valid FB address in PCI config space\n");
979      TDFXFreeRec(pScrn);
980      return FALSE;
981    }
982  }
983  xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
984	     (unsigned long)pTDFX->LinearAddr[0]);
985
986  if (pTDFX->pEnt->device->IOBase != 0) {
987    pTDFX->MMIOAddr[0] = pTDFX->pEnt->device->IOBase;
988    from = X_CONFIG;
989  } else {
990    if (PCI_MEM_BASE(match, 0)) {
991      pTDFX->MMIOAddr[0] = PCI_MEM_BASE(match, 0);
992      from = X_PROBED;
993    } else {
994      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
995		 "No valid MMIO address in PCI config space\n");
996      TDFXFreeRec(pScrn);
997      return FALSE;
998    }
999  }
1000  xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at addr 0x%lX\n",
1001	     (unsigned long)pTDFX->MMIOAddr[0]);
1002
1003  if (!PCI_IO_BASE(match, 2)) {
1004    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1005	       "No valid PIO address in PCI config space\n");
1006    TDFXFreeRec(pScrn);
1007    return FALSE;
1008  }
1009  xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PIO registers at addr 0x%lX\n",
1010	     (unsigned long)pTDFX->PIOBase[0]);
1011
1012  /* We have to use PIO to probe, because we haven't mappend yet */
1013  TDFXSetPIOAccess(pTDFX);
1014
1015  /* Calculate memory */
1016  pScrn->videoRam = TDFXCountRam(pScrn);
1017  from = X_PROBED;
1018  if (pTDFX->pEnt->device->videoRam) {
1019    pScrn->videoRam = pTDFX->pEnt->device->videoRam;
1020    from = X_CONFIG;
1021  }
1022
1023  TDFXInitChips(pScrn);
1024
1025  /* Multiple by two because tiled access requires more address space */
1026  pTDFX->FbMapSize = pScrn->videoRam*1024*2;
1027  xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte Mapping %ld kByte\n",
1028	     pScrn->videoRam, pTDFX->FbMapSize/1024);
1029
1030  /* Since we can do gamma correction, we call xf86SetGamma */
1031  {
1032    Gamma zeros = {0.0, 0.0, 0.0};
1033
1034    if (!xf86SetGamma(pScrn, zeros)) {
1035      return FALSE;
1036    }
1037  }
1038
1039  pTDFX->MaxClock = 0;
1040  if (pTDFX->pEnt->device->dacSpeeds[0]) {
1041    switch (pScrn->bitsPerPixel) {
1042    case 8:
1043      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP8];
1044      break;
1045    case 16:
1046      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP16];
1047      break;
1048    case 24:
1049      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP24];
1050      break;
1051    case 32:
1052      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP32];
1053      break;
1054    }
1055    if (!pTDFX->MaxClock)
1056      pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[0];
1057    from = X_CONFIG;
1058  } else {
1059#ifdef XSERVER_LIBPCIACCESS
1060      pTDFX->MaxClock = MaxClocks[pTDFX->match_id];
1061#else
1062    switch (pTDFX->ChipType) {
1063    case PCI_CHIP_BANSHEE:
1064      pTDFX->MaxClock = 270000;
1065      break;
1066    case PCI_CHIP_VOODOO3:
1067      switch(match->subsysCard) {
1068      case PCI_CARD_VOODOO3_2000:
1069	pTDFX->MaxClock = 300000;
1070	break;
1071      case PCI_CARD_VOODOO3_3000:
1072	pTDFX->MaxClock = 350000;
1073	break;
1074      default:
1075	pTDFX->MaxClock = 300000;
1076	break;
1077      }
1078      break;
1079    case PCI_CHIP_VOODOO5:
1080      pTDFX->MaxClock = 350000;
1081      break;
1082    }
1083#endif
1084  }
1085  clockRanges = xnfcalloc(sizeof(ClockRange), 1);
1086  clockRanges->next=NULL;
1087  clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
1088  clockRanges->maxClock=pTDFX->MaxClock;
1089  clockRanges->clockIndex = -1;
1090  switch (pTDFX->ChipType) {
1091    case PCI_CHIP_BANSHEE:
1092      clockRanges->interlaceAllowed = FALSE;
1093      break;
1094    case PCI_CHIP_VOODOO3:
1095    case PCI_CHIP_VOODOO5:
1096      clockRanges->interlaceAllowed = TRUE;
1097      break;
1098    default:
1099      clockRanges->interlaceAllowed = FALSE;
1100      break;
1101  }
1102  clockRanges->doubleScanAllowed = TRUE;
1103
1104  /*
1105   * Max memory available for the framebuffer is the total less the
1106   * HW cursor space and FIFO space.
1107   */
1108  availableMem = pScrn->videoRam - 4096 -
1109		 (((255 <= CMDFIFO_PAGES) ? 255 : CMDFIFO_PAGES) << 12);
1110
1111  if (!xf86LoadSubModule(pScrn, "fb")) {
1112    TDFXFreeRec(pScrn);
1113    return FALSE;
1114  }
1115
1116  pTDFX->NoAccel = xf86ReturnOptValBool(pTDFX->Options, OPTION_NOACCEL, FALSE);
1117  if (!pTDFX->NoAccel) {
1118    if (!xf86LoadSubModule(pScrn, "xaa")) {
1119      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration available\n");
1120      pTDFX->NoAccel = TRUE;
1121    }
1122  }
1123
1124  if (!xf86GetOptValBool(pTDFX->Options, OPTION_SHOWCACHE, &(pTDFX->ShowCache))) {
1125    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache %s\n", pTDFX->ShowCache ? "Enabled" : "Disabled");
1126  } else {
1127    pTDFX->ShowCache = FALSE;
1128  }
1129
1130  if (xf86GetOptValBool(pTDFX->Options, OPTION_TEXTURED_VIDEO, &(pTDFX->TextureXvideo))) {
1131    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Texture Xvideo Adaptor %s\n", pTDFX->TextureXvideo ? "Enabled" : "Disabled");
1132  } else {
1133    pTDFX->TextureXvideo = FALSE;
1134  }
1135
1136  if (xf86GetOptValInteger(pTDFX->Options, OPTION_VIDEO_KEY, &(pTDFX->videoKey))) {
1137    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pTDFX->videoKey);
1138  } else {
1139    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key default 0x%x\n", pTDFX->videoKey = 0x1E);
1140  }
1141
1142  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
1143    if (!xf86LoadSubModule(pScrn, "ramdac")) {
1144      TDFXFreeRec(pScrn);
1145      return FALSE;
1146    }
1147  }
1148
1149  /* Load DDC and I2C for monitor ID */
1150  if (!xf86LoadSubModule(pScrn, "i2c")) {
1151    TDFXFreeRec(pScrn);
1152    return FALSE;
1153  }
1154
1155  if (!xf86LoadSubModule(pScrn, "ddc")) {
1156    TDFXFreeRec(pScrn);
1157    return FALSE;
1158  }
1159
1160  /* try to read read DDC2 data */
1161  if (TDFXI2cInit(pScrn)) {
1162    pMon = doTDFXDDC(pScrn);
1163    if (pMon != NULL)
1164      xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
1165  } else {
1166    /* try to use vbe if we didn't find anything */
1167#if USE_INT10
1168#if !defined(__powerpc__)
1169    /* Initialize DDC1 if possible */
1170    if (xf86LoadSubModule(pScrn, "vbe")) {
1171      vbeInfoPtr pVbe = VBEInit(NULL,pTDFX->pEnt->index);
1172
1173      pMon = vbeDoEDID(pVbe, NULL);
1174      vbeFree(pVbe);
1175      xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
1176    }
1177#endif
1178#endif
1179  }
1180
1181  i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
1182			pScrn->display->modes, clockRanges,
1183			0, 320, 2048, 16*pScrn->bitsPerPixel,
1184			200, 2047,
1185			pScrn->display->virtualX, pScrn->display->virtualY,
1186			availableMem, LOOKUP_BEST_REFRESH);
1187
1188  if (i==-1) {
1189    TDFXFreeRec(pScrn);
1190    return FALSE;
1191  }
1192
1193  xf86PruneDriverModes(pScrn);
1194
1195  if (!i || !pScrn->modes) {
1196    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
1197    TDFXFreeRec(pScrn);
1198    return FALSE;
1199  }
1200
1201  xf86SetCrtcForModes(pScrn, 0);
1202
1203  pScrn->currentMode = pScrn->modes;
1204
1205  xf86PrintModes(pScrn);
1206
1207  xf86SetDpi(pScrn, 0, 0);
1208
1209  if (xf86ReturnOptValBool(pTDFX->Options, OPTION_USE_PIO, FALSE)) {
1210    pTDFX->usePIO=TRUE;
1211  }
1212
1213#if X_BYTE_ORDER == X_BIG_ENDIAN
1214  pTDFX->ModeReg.miscinit0 = pTDFX->readLong(pTDFX, MISCINIT0);
1215  pTDFX->SavedReg.miscinit0 = pTDFX->ModeReg.miscinit0;
1216
1217  switch (pScrn->bitsPerPixel) {
1218  case 8:
1219    pTDFX->writeFifo = TDFXWriteFifo_8;
1220    pTDFX->ModeReg.miscinit0 &= ~BIT(30); /* LFB byte swizzle */
1221    pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
1222    break;
1223  case 15:
1224  case 16:
1225    pTDFX->writeFifo = TDFXWriteFifo_16;
1226    pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
1227    pTDFX->ModeReg.miscinit0 |= BIT(31); /* LFB word swizzle */
1228    break;
1229  case 24:
1230  case 32:
1231    pTDFX->writeFifo = TDFXWriteFifo_24;
1232    pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
1233    pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
1234    break;
1235  default:
1236    return FALSE;
1237    break;
1238  }
1239  pTDFX->writeLong(pTDFX, MISCINIT0, pTDFX->ModeReg.miscinit0);
1240#endif
1241
1242#ifdef TDFXDRI
1243  /* Load the dri module if requested. */
1244  if (xf86ReturnOptValBool(pTDFX->Options, OPTION_DRI, FALSE)) {
1245    xf86LoadSubModule(pScrn, "dri");
1246  }
1247#endif
1248  return TRUE;
1249}
1250
1251static Bool
1252TDFXMapMem(ScrnInfoPtr pScrn)
1253{
1254    int i;
1255    TDFXPtr pTDFX = TDFXPTR(pScrn);
1256#ifdef XSERVER_LIBPCIACCESS
1257    int err;
1258#else
1259    const int mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
1260#endif
1261
1262  TDFXTRACE("TDFXMapMem start\n");
1263
1264#ifdef XSERVER_LIBPCIACCESS
1265    /* FIXME: I'm not convinced that this is correct for SLI cards, but I
1266     * FIXME: don't have any such hardware to test.
1267     */
1268    for (i = 0; i < pTDFX->numChips; i++) {
1269	err = pci_device_map_memory_range(pTDFX->PciInfo[i],
1270					  pTDFX->MMIOAddr[i],
1271					  TDFXIOMAPSIZE,
1272					  TRUE,
1273					  & pTDFX->MMIOBase[i]);
1274	if (err) {
1275	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1276		       "Unable to map MMIO region for card %u (%d).\n",
1277		       i, err);
1278	    return FALSE;
1279	}
1280    }
1281
1282
1283    err = pci_device_map_memory_range(pTDFX->PciInfo[0],
1284				      pTDFX->LinearAddr[0],
1285				      pTDFX->FbMapSize,
1286				      TRUE,
1287				      & pTDFX->FbBase);
1288    if (err) {
1289	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1290		   "Unable to map framebuffer (%d).\n", err);
1291	return FALSE;
1292    }
1293#else
1294  for (i=0; i<pTDFX->numChips; i++) {
1295    pTDFX->MMIOBase[i] = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
1296				       pTDFX->PciTag[i],
1297				       pTDFX->MMIOAddr[i],
1298				       TDFXIOMAPSIZE);
1299
1300    if (!pTDFX->MMIOBase[i]) return FALSE;
1301  }
1302
1303  pTDFX->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1304				pTDFX->PciTag[0],
1305				pTDFX->LinearAddr[0],
1306				pTDFX->FbMapSize);
1307  if (!pTDFX->FbBase) return FALSE;
1308#endif
1309
1310  return TRUE;
1311}
1312
1313static Bool
1314TDFXUnmapMem(ScrnInfoPtr pScrn)
1315{
1316  TDFXPtr pTDFX;
1317  int i;
1318
1319  TDFXTRACE("TDFXUnmapMem start\n");
1320  pTDFX = TDFXPTR(pScrn);
1321
1322#ifdef XSERVER_LIBPCIACCESS
1323    pci_device_unmap_region(pTDFX->PciInfo[0], 0);
1324    pci_device_unmap_region(pTDFX->PciInfo[0], 1);
1325
1326    (void) memset(pTDFX->MMIOBase, 0, sizeof(pTDFX->MMIOBase));
1327    pTDFX->FbBase = NULL;
1328#else
1329  for (i=0; i<pTDFX->numChips; i++) {
1330    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->MMIOBase[i],
1331		    TDFXIOMAPSIZE);
1332    pTDFX->MMIOBase[i]=0;
1333  }
1334
1335  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->FbBase, pTDFX->FbMapSize);
1336  pTDFX->FbBase = 0;
1337#endif
1338  return TRUE;
1339}
1340
1341static void
1342PrintRegisters(ScrnInfoPtr pScrn, TDFXRegPtr regs)
1343{
1344#ifdef TRACE
1345  int i;
1346  TDFXPtr pTDFX;
1347  vgaHWPtr pHW = VGAHWPTR(pScrn);
1348  vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
1349
1350
1351  pTDFX = TDFXPTR(pScrn);
1352#if 1
1353  ErrorF("VGA Registers\n");
1354  ErrorF("MiscOutReg = %x versus %x\n", pHW->readMiscOut(pHW), pVga->MiscOutReg);
1355  ErrorF("EnableReg = %x\n", pHW->readEnable(pHW));
1356  for (i=0; i<25; i++) {
1357    int x;
1358    x = pHW->readCrtc(pHW, i);
1359    ErrorF("CRTC[%d]=%d versus %d\n", i, x, pVga->CRTC[i]);
1360  }
1361  for (i=0; i<21; i++) {
1362    ErrorF("Attribute[%d]=%d versus %d\n", i, pHW->readAttr(pHW, i), pVga->Attribute[i]);
1363  }
1364  for (i=0; i<9; i++) {
1365    ErrorF("Graphics[%d]=%d versus %d\n", i, pHW->readGr(pHW, i), pVga->Graphics[i]);
1366  }
1367  for (i=0; i<5; i++) {
1368    ErrorF("Sequencer[%d]=%d versus %d\n", i, pHW->readSeq(pHW, i), pVga->Sequencer[i]);
1369  }
1370#endif
1371#if 1
1372  ErrorF("Banshee Registers\n");
1373  ErrorF("VidCfg = %x versus %x\n",  pTDFX->readLong(pTDFX, VIDPROCCFG), regs->vidcfg);
1374  ErrorF("DACmode = %x versus %x\n", pTDFX->readLong(pTDFX, DACMODE), regs->dacmode);
1375  ErrorF("Vgainit0 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT0), regs->vgainit0);
1376  ErrorF("Vgainit1 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT1), regs->vgainit1);
1377  ErrorF("Miscinit0 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT0), regs->miscinit0);
1378  ErrorF("Miscinit1 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT1), regs->miscinit1);
1379  ErrorF("DramInit0 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT0));
1380  ErrorF("DramInit1 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT1));
1381  ErrorF("VidPLL = %x versus %x\n", pTDFX->readLong(pTDFX, PLLCTRL0), regs->vidpll);
1382  ErrorF("screensize = %x versus %x\n", pTDFX->readLong(pTDFX, VIDSCREENSIZE), regs->screensize);
1383  ErrorF("stride = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE), regs->stride);
1384  ErrorF("startaddr = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR), regs->startaddr);
1385  ErrorF("Input Status 0 = %x\n", pTDFX->readLong(pTDFX, 0xc2));
1386  ErrorF("Input Status 1 = %x\n", pTDFX->readLong(pTDFX, 0xda));
1387  ErrorF("2D Status = %x\n", pTDFX->readLong(pTDFX, SST_2D_OFFSET));
1388  ErrorF("3D Status = %x\n", pTDFX->readLong(pTDFX, SST_3D_OFFSET));
1389#endif
1390#endif
1391}
1392
1393/*
1394 * TDFXSave --
1395 *
1396 * This function saves the video state.  It reads all of the SVGA registers
1397 * into the vgaTDFXRec data structure.  There is in general no need to
1398 * mask out bits here - just read the registers.
1399 */
1400static void
1401DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg, Bool saveFonts)
1402{
1403  TDFXPtr pTDFX;
1404  vgaHWPtr hwp;
1405  int i, dummy, count;
1406
1407  TDFXTRACE("TDFXDoSave start\n");
1408  pTDFX = TDFXPTR(pScrn);
1409  hwp = VGAHWPTR(pScrn);
1410
1411  /*
1412   * This function will handle creating the data structure and filling
1413   * in the generic VGA portion.
1414   */
1415  if (saveFonts && pTDFX->Primary) {
1416    /* Enable legacy VGA to access font memory. */
1417    dummy = pTDFX->readLong(pTDFX, VGAINIT0);
1418    pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
1419    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS);
1420    pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
1421  } else
1422    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
1423
1424  tdfxReg->ExtVga[0] = hwp->readCrtc(hwp, 0x1a);
1425  tdfxReg->ExtVga[1] = hwp->readCrtc(hwp, 0x1b);
1426  tdfxReg->miscinit1=pTDFX->readLong(pTDFX, MISCINIT1);
1427  tdfxReg->vidcfg=pTDFX->readLong(pTDFX, VIDPROCCFG);
1428  tdfxReg->vidpll=pTDFX->readLong(pTDFX, PLLCTRL0);
1429  tdfxReg->dacmode=pTDFX->readLong(pTDFX, DACMODE);
1430  tdfxReg->screensize=pTDFX->readLong(pTDFX, VIDSCREENSIZE);
1431  tdfxReg->stride=pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE);
1432  tdfxReg->cursloc=pTDFX->readLong(pTDFX, HWCURPATADDR);
1433  tdfxReg->startaddr=pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR);
1434  tdfxReg->clip0min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MIN);
1435  tdfxReg->clip0max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MAX);
1436  tdfxReg->clip1min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MIN);
1437  tdfxReg->clip1max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MAX);
1438  tdfxReg->srcbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_SRCBASEADDR);
1439  tdfxReg->dstbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_DSTBASEADDR);
1440  for (i=0; i<512; i++) {
1441    count=0;
1442    do {
1443      TDFXWriteLongMMIO(pTDFX, DACADDR, i);
1444      dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
1445    } while (count++<100 && dummy!=i);
1446    tdfxReg->dactable[i]=TDFXReadLongMMIO(pTDFX, DACDATA);
1447  }
1448  PrintRegisters(pScrn, tdfxReg);
1449}
1450
1451static void
1452TDFXSave(ScrnInfoPtr pScrn)
1453{
1454  vgaHWPtr hwp;
1455  TDFXPtr pTDFX;
1456
1457  TDFXTRACE("TDFXSave start\n");
1458  hwp = VGAHWPTR(pScrn);
1459  pTDFX = TDFXPTR(pScrn);
1460  /* Make sure VGA functionality is enabled */
1461  pTDFX->SavedReg.vgainit0=pTDFX->readLong(pTDFX, VGAINIT0);
1462#if 0
1463  pTDFX->SavedReg.vgainit1=pTDFX->readLong(pTDFX, VGAINIT1);
1464#endif
1465  pTDFX->writeLong(pTDFX, VGAINIT0, pTDFX->ModeReg.vgainit0);
1466#if 0
1467  pTDFX->writeLong(pTDFX, VGAINIT1, pTDFX->ModeReg.vgainit1);
1468#endif
1469  vgaHWEnable(hwp);
1470
1471  DoSave(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
1472}
1473
1474static void
1475DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg,
1476	  Bool restoreFonts) {
1477  TDFXPtr pTDFX;
1478  vgaHWPtr hwp;
1479  int i, dummy, count;
1480
1481  TDFXTRACE("TDFXDoRestore start\n");
1482  pTDFX = TDFXPTR(pScrn);
1483  hwp = VGAHWPTR(pScrn);
1484
1485  pTDFX->sync(pScrn);
1486
1487  vgaHWProtect(pScrn, TRUE);
1488
1489  if (restoreFonts && pTDFX->Primary) {
1490    /* Enable legacy VGA to access font memory. */
1491    dummy = pTDFX->readLong(pTDFX, VGAINIT0);
1492    pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
1493    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
1494    pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
1495  } else
1496    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
1497
1498  hwp->writeCrtc(hwp, 0x1a, tdfxReg->ExtVga[0]);
1499  hwp->writeCrtc(hwp, 0x1b, tdfxReg->ExtVga[1]);
1500  pTDFX->writeLong(pTDFX, PLLCTRL0, tdfxReg->vidpll);
1501  pTDFX->writeLong(pTDFX, DACMODE, tdfxReg->dacmode);
1502  pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, tdfxReg->stride);
1503  pTDFX->writeLong(pTDFX, HWCURPATADDR, tdfxReg->cursloc);
1504  pTDFX->writeLong(pTDFX, VIDSCREENSIZE, tdfxReg->screensize);
1505  pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
1506  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MIN, tdfxReg->clip0min);
1507  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MAX, tdfxReg->clip0max);
1508  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MIN, tdfxReg->clip1min);
1509  TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MAX, tdfxReg->clip1max);
1510#if X_BYTE_ORDER == X_BIG_ENDIAN
1511  pTDFX->writeLong(pTDFX, MISCINIT0, tdfxReg->miscinit0);
1512#endif
1513  pTDFX->writeLong(pTDFX, VIDPROCCFG, tdfxReg->vidcfg);
1514  TDFXWriteLongMMIO(pTDFX, SST_2D_SRCBASEADDR, tdfxReg->srcbaseaddr);
1515  TDFXWriteLongMMIO(pTDFX, SST_2D_DSTBASEADDR, tdfxReg->dstbaseaddr);
1516  for (i=0; i<512; i++) {
1517    count=0;
1518    do {
1519      TDFXWriteLongMMIO(pTDFX, DACADDR, i);
1520      dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
1521    } while (count++<100 && dummy!=i);
1522    count=0;
1523    do {
1524      TDFXWriteLongMMIO(pTDFX, DACDATA, tdfxReg->dactable[i]);
1525      dummy=TDFXReadLongMMIO(pTDFX, DACDATA);
1526    } while (count++<100 && dummy!=tdfxReg->dactable[i]);
1527  }
1528  pTDFX->writeLong(pTDFX, VGAINIT0, tdfxReg->vgainit0);
1529#if 0
1530  pTDFX->writeLong(pTDFX, VGAINIT1, tdfxReg->vgainit1);
1531  pTDFX->writeLong(pTDFX, MISCINIT1, tdfxReg->miscinit1);
1532#endif
1533  vgaHWProtect(pScrn, FALSE);
1534
1535  pTDFX->sync(pScrn);
1536  PrintRegisters(pScrn, tdfxReg);
1537}
1538
1539static void
1540TDFXRestore(ScrnInfoPtr pScrn) {
1541  vgaHWPtr hwp;
1542  TDFXPtr pTDFX;
1543
1544  TDFXTRACE("TDFXRestore start\n");
1545  hwp = VGAHWPTR(pScrn);
1546  pTDFX = TDFXPTR(pScrn);
1547
1548  DoRestore(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
1549}
1550
1551#define REFFREQ 14318.18
1552
1553static int
1554CalcPLL(int freq, int *f_out, int isBanshee) {
1555  int m, n, k, best_m, best_n, best_k, f_cur, best_error;
1556  int minm, maxm;
1557
1558  TDFXTRACE("CalcPLL start\n");
1559  best_error=freq;
1560  best_n=best_m=best_k=0;
1561  if (isBanshee) {
1562    minm=24;
1563    maxm=24;
1564  } else {
1565    minm=1;
1566    maxm=57; /* This used to be 64, alas it seems the last 8 (funny that ?)
1567              * values cause jittering at lower resolutions. I've not done
1568              * any calculations to what the adjustment affects clock ranges,
1569              * but I can still run at 1600x1200@75Hz */
1570  }
1571  for (n=1; n<256; n++) {
1572    f_cur=REFFREQ*(n+2);
1573    if (f_cur<freq) {
1574      f_cur=f_cur/3;
1575      if (freq-f_cur<best_error) {
1576	best_error=freq-f_cur;
1577	best_n=n;
1578	best_m=1;
1579	best_k=0;
1580	continue;
1581      }
1582    }
1583    for (m=minm; m<maxm; m++) {
1584      for (k=0; k<4; k++) {
1585	f_cur=REFFREQ*(n+2)/(m+2)/(1<<k);
1586	if (abs(f_cur-freq)<best_error) {
1587	  best_error=abs(f_cur-freq);
1588	  best_n=n;
1589	  best_m=m;
1590	  best_k=k;
1591	}
1592      }
1593    }
1594  }
1595  n=best_n;
1596  m=best_m;
1597  k=best_k;
1598  *f_out=REFFREQ*(n+2)/(m+2)/(1<<k);
1599  return (n<<8)|(m<<2)|k;
1600}
1601
1602static Bool
1603SetupVidPLL(ScrnInfoPtr pScrn, DisplayModePtr mode) {
1604  TDFXPtr pTDFX;
1605  TDFXRegPtr tdfxReg;
1606  int freq, f_out;
1607
1608  TDFXTRACE("SetupVidPLL start\n");
1609  pTDFX = TDFXPTR(pScrn);
1610  tdfxReg = &pTDFX->ModeReg;
1611  freq=mode->Clock;
1612  tdfxReg->dacmode&=~SST_DAC_MODE_2X;
1613  tdfxReg->vidcfg&=~SST_VIDEO_2X_MODE_EN;
1614  if (freq>TDFX2XCUTOFF) {
1615    if (freq>pTDFX->MaxClock) {
1616      ErrorF("Overclocked PLLs\n");
1617      freq=pTDFX->MaxClock;
1618    }
1619    tdfxReg->dacmode|=SST_DAC_MODE_2X;
1620    tdfxReg->vidcfg|=SST_VIDEO_2X_MODE_EN;
1621  }
1622  tdfxReg->vidpll=CalcPLL(freq, &f_out, 0);
1623  TDFXTRACEREG("Vid PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1624     tdfxReg->vidpll);
1625  return TRUE;
1626}
1627
1628#if 0
1629static Bool
1630SetupMemPLL(int freq) {
1631  TDFXPtr pTDFX;
1632  vgaTDFXPtr tdfxReg;
1633  int f_out;
1634
1635  TDFXTRACE("SetupMemPLL start\n");
1636  pTDFX=TDFXPTR();
1637  tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
1638  tdfxReg->mempll=CalcPLL(freq, &f_out);
1639  pTDFX->writeLong(pTDFX, PLLCTRL1, tdfxReg->mempll);
1640  TDFXTRACEREG("Mem PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1641     tdfxReg->mempll);
1642  return TRUE;
1643}
1644
1645static Bool
1646SetupGfxPLL(int freq) {
1647  TDFXPtr pTDFX;
1648  vgaTDFXPtr tdfxReg;
1649  int f_out;
1650
1651  TDFXTRACE("SetupGfxPLL start\n");
1652  pTDFX=TDFXPTR();
1653  tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
1654  if (pTDFX->chipType==PCI_CHIP_BANSHEE)
1655    tdfxReg->gfxpll=CalcPLL(freq, &f_out, 1);
1656  else
1657    tdfxReg->gfxpll=CalcPLL(freq, &f_out, 0);
1658  pTDFX->writeLong(pTDFX, PLLCTRL2, tdfxReg->gfxpll);
1659  TDFXTRACEREG("Gfx PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
1660     tdfxReg->gfxpll);
1661  return TRUE;
1662}
1663#endif
1664
1665#if 0
1666static Bool
1667TDFXInitWithBIOSData(ScrnInfoPtr pScrn)
1668{
1669  TDFXPtr pTDFX;
1670  unsigned char *bios = NULL;
1671  int offset1, offset2;
1672  int i;
1673  CARD32 uint[9];
1674
1675  pTDFX=TDFXPTR(pScrn);
1676
1677  if (pTDFX->initDone)
1678    return TRUE;
1679
1680  if (pTDFX->Primary) {
1681    uint[0] = pTDFX->readLong(pTDFX, PCIINIT0);
1682    uint[1] = pTDFX->readLong(pTDFX, MISCINIT0);
1683    uint[2] = pTDFX->readLong(pTDFX, MISCINIT1);
1684    uint[3] = pTDFX->readLong(pTDFX, DRAMINIT0);
1685    uint[4] = pTDFX->readLong(pTDFX, DRAMINIT1);
1686    uint[5] = pTDFX->readLong(pTDFX, AGPINIT);
1687    uint[6] = pTDFX->readLong(pTDFX, PLLCTRL1);
1688    uint[7] = pTDFX->readLong(pTDFX, PLLCTRL2);
1689    for (i = 0; i < 8; i++) {
1690      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Primary UINT32[%d] is 0x%08lx\n", i, uint[i]);
1691    }
1692    return TRUE;
1693  }
1694
1695#define T_B_SIZE (64 * 1024)
1696  bios = calloc(T_B_SIZE, 1);
1697  if (!bios)
1698    return FALSE;
1699
1700#ifdef XSERVER_LIBPCIACCESS
1701    pci_device_read_rom(pTDFX->PciInfo[0], bios);
1702#else
1703  if (!xf86ReadPciBIOS(0, pTDFX->PciTag[0], 1, bios, T_B_SIZE)) {
1704#if 0
1705    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS read.\n");
1706    free(bios);
1707    return FALSE;
1708#endif
1709  }
1710#endif
1711
1712  if (bios[0] != 0x55 || bios[1] != 0xAA) {
1713    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS signature.\n");
1714    free(bios);
1715    return FALSE;
1716  }
1717
1718  offset1 = bios[0x50] | (bios[0x51] << 8);
1719  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 1 is (0x%04x)\n", offset1);
1720  offset2 = bios[offset1] | (bios[offset1 + 1] << 8);
1721  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 2 is (0x%04x)\n", offset2);
1722
1723  for (i = 0; i < 9; i++) {
1724    int o;
1725
1726    o = offset2 + i * 4;
1727    uint[i] = bios[o] | (bios[o+1] << 8) | (bios[o+2] << 16) | (bios[o+3] << 24);
1728    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UINT32[%d] is 0x%08lx\n", i, uint[i]);
1729  }
1730
1731#if 1
1732  uint[0] = 0x0584fb04;
1733  uint[1] = 0x00000000;
1734  uint[2] = 0x03000001;
1735  uint[3] = 0x0c17a9e9;
1736  uint[4] = 0x00202031;
1737  uint[5] = 0x8000049e;
1738  uint[6] = 0x00003a05;
1739  uint[7] = 0x00000c00;
1740#endif
1741
1742  pTDFX->writeLong(pTDFX, PCIINIT0, uint[0]);
1743  pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
1744  pTDFX->writeLong(pTDFX, MISCINIT1, uint[2]);
1745  pTDFX->writeLong(pTDFX, DRAMINIT0, uint[3]);
1746  pTDFX->writeLong(pTDFX, DRAMINIT1, uint[4]);
1747  pTDFX->writeLong(pTDFX, AGPINIT, uint[5]);
1748  pTDFX->writeLong(pTDFX, PLLCTRL1, uint[6]);
1749  pTDFX->writeLong(pTDFX, PLLCTRL2, uint[7]);
1750#if 0
1751  pTDFX->writeLong(pTDFX, DRAMCOMMAND, uint[8]);
1752#endif
1753
1754  /* reset */
1755  pTDFX->writeLong(pTDFX, MISCINIT0, 0xF3);
1756  pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
1757
1758  free(bios);
1759  return TRUE;
1760}
1761#endif
1762
1763
1764static Bool
1765TDFXInitVGA(ScrnInfoPtr pScrn)
1766{
1767  TDFXPtr pTDFX;
1768  TDFXRegPtr tdfxReg;
1769
1770  TDFXTRACE("TDFXInitVGA start\n");
1771  pTDFX=TDFXPTR(pScrn);
1772  if (pTDFX->initDone) return TRUE;
1773  pTDFX->initDone=TRUE;
1774
1775  tdfxReg = &pTDFX->ModeReg;
1776  tdfxReg->vgainit0 = 0;
1777  tdfxReg->vgainit0 |= SST_VGA0_EXTENSIONS;
1778  tdfxReg->vgainit0 |= SST_WAKEUP_3C3 << SST_VGA0_WAKEUP_SELECT_SHIFT;
1779#if USE_PCIVGAIO
1780  tdfxReg->vgainit0 |= SST_VGA0_LEGACY_DECODE;
1781#endif
1782  tdfxReg->vgainit0 |= SST_ENABLE_ALT_READBACK << SST_VGA0_CONFIG_READBACK_SHIFT;
1783  tdfxReg->vgainit0 |= SST_CLUT_SELECT_8BIT << SST_VGA0_CLUT_SELECT_SHIFT;
1784
1785  tdfxReg->vgainit0 |= BIT(12);
1786#if 0
1787  tdfxReg->vgainit1 |= 0;
1788  tdfxReg->miscinit1 = 0;
1789#endif
1790
1791  tdfxReg->vidcfg = SST_VIDEO_PROCESSOR_EN | SST_CURSOR_X11 | SST_DESKTOP_EN |
1792    (pTDFX->cpp-1)<<SST_DESKTOP_PIXEL_FORMAT_SHIFT;
1793
1794  /* tdfxReg->vidcfg |= SST_DESKTOP_CLUT_BYPASS; */
1795
1796  tdfxReg->stride = pTDFX->stride;
1797
1798  tdfxReg->clip0min = tdfxReg->clip1min = 0;
1799  tdfxReg->clip0max = tdfxReg->clip1max = pTDFX->maxClip;
1800
1801  return TRUE;
1802}
1803
1804static Bool
1805TDFXSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) {
1806  TDFXPtr pTDFX;
1807  TDFXRegPtr tdfxReg;
1808  vgaRegPtr pVga;
1809  int hbs, hbe, vbs, vbe, hse;
1810  int hd, hss, ht, vt, vd;
1811
1812  TDFXTRACE("TDFXSetMode start\n");
1813
1814  pTDFX = TDFXPTR(pScrn);
1815  tdfxReg = &pTDFX->ModeReg;
1816  pVga = &VGAHWPTR(pScrn)->ModeReg;
1817
1818  /* Tell the board we're using a programmable clock */
1819  pVga->MiscOutReg |= 0xC;
1820
1821  /* Calculate the CRTC values */
1822  hd = (mode->CrtcHDisplay>>3)-1;
1823  hss = (mode->CrtcHSyncStart>>3);
1824  hse = (mode->CrtcHSyncEnd>>3);
1825  ht = (mode->CrtcHTotal>>3)-5;
1826  hbs = (mode->CrtcHBlankStart>>3)-1;
1827  hbe = (mode->CrtcHBlankEnd>>3)-1;
1828
1829  vd = mode->CrtcVDisplay-1;
1830  vt = mode->CrtcVTotal-2;
1831  vbs = mode->CrtcVBlankStart-1;
1832  vbe = mode->CrtcVBlankEnd-1;
1833
1834  /* Undo the "KGA fixes" */
1835  pVga->CRTC[3] = (hbe&0x1F)|0x80;
1836  pVga->CRTC[5] = (((hbe)&0x20)<<2) | (hse&0x1F);
1837  pVga->CRTC[22] =vbe&0xFF;
1838
1839  /* Handle the higher resolution modes */
1840  tdfxReg->ExtVga[0] = (ht&0x100)>>8 | (hd&0x100)>>6 | (hbs&0x100)>>4 |
1841    (hbe&0x40)>>1 | (hss&0x100)>>2 | (hse&0x20)<<2;
1842
1843  tdfxReg->ExtVga[1] = (vt&0x400)>>10 | (vd&0x400)>>8 | (vbs&0x400)>>6 |
1844    (vbe&0x400)>>4;
1845
1846  if (!SetupVidPLL(pScrn, mode)) return FALSE;
1847
1848  /* Set the screen size */
1849  if (mode->Flags&V_DBLSCAN) {
1850    pVga->CRTC[9] |= 0x80;
1851    tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<13);
1852    tdfxReg->vidcfg |= SST_HALF_MODE;
1853  } else {
1854    tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<12);
1855    tdfxReg->vidcfg &= ~SST_HALF_MODE;
1856  }
1857  if (mode->Flags&V_INTERLACE) {
1858    tdfxReg->vidcfg|=SST_INTERLACE;
1859  } else
1860    tdfxReg->vidcfg&=~SST_INTERLACE;
1861
1862  TDFXTRACEREG("cpp=%d Hdisplay=%d Vdisplay=%d stride=%d screensize=%x\n",
1863	     pTDFX->cpp, mode->HDisplay, mode->VDisplay, tdfxReg->stride,
1864	     tdfxReg->screensize);
1865
1866  return TRUE;
1867}
1868
1869static Bool
1870TDFXModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1871{
1872  vgaHWPtr hwp;
1873  TDFXPtr pTDFX;
1874  int hd, hbs, hss, hse, hbe, ht, hskew;
1875  Bool dbl;
1876
1877  hd = hbs = hss = hse = hbe = ht = hskew = 0;
1878  hwp = VGAHWPTR(pScrn);
1879  pTDFX = TDFXPTR(pScrn);
1880
1881  TDFXTRACE("TDFXModeInit start\n");
1882  dbl=FALSE;
1883  /* Check for 2x mode and halve all the timing values */
1884  if (mode->Clock>TDFX2XCUTOFF) {
1885    hd=mode->CrtcHDisplay;
1886    hbs=mode->CrtcHBlankStart;
1887    hss=mode->CrtcHSyncStart;
1888    hse=mode->CrtcHSyncEnd;
1889    hbe=mode->CrtcHBlankEnd;
1890    ht=mode->CrtcHTotal;
1891    hskew=mode->CrtcHSkew;
1892    mode->CrtcHDisplay=hd>>1;
1893    mode->CrtcHBlankStart=hbs>>1;
1894    mode->CrtcHSyncStart=hss>>1;
1895    mode->CrtcHSyncEnd=hse>>1;
1896    mode->CrtcHBlankEnd=hbe>>1;
1897    mode->CrtcHTotal=ht>>1;
1898    mode->CrtcHSkew=hskew>>1;
1899    dbl=TRUE;
1900  }
1901
1902  vgaHWUnlock(hwp);
1903
1904  if (!vgaHWInit(pScrn, mode)) return FALSE;
1905
1906  pScrn->vtSema = TRUE;
1907
1908  if (!TDFXSetMode(pScrn, mode)) return FALSE;
1909
1910  if (dbl) {
1911    mode->CrtcHDisplay=hd;
1912    mode->CrtcHBlankStart=hbs;
1913    mode->CrtcHSyncStart=hss;
1914    mode->CrtcHSyncEnd=hse;
1915    mode->CrtcHBlankEnd=hbe;
1916    mode->CrtcHTotal=ht;
1917    mode->CrtcHSkew=hskew;
1918  }
1919
1920#ifdef TDFXDRI
1921  if (pTDFX->directRenderingEnabled) {
1922    DRILock(xf86ScrnToScreen(pScrn), 0);
1923    TDFXSwapContextFifo(xf86ScrnToScreen(pScrn));
1924  }
1925#endif
1926  DoRestore(pScrn, &hwp->ModeReg, &pTDFX->ModeReg, FALSE);
1927#ifdef TDFXDRI
1928  if (pTDFX->directRenderingEnabled) {
1929    DRIUnlock(xf86ScrnToScreen(pScrn));
1930  }
1931#endif
1932
1933  return TRUE;
1934}
1935
1936static void
1937TDFXLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1938		  VisualPtr pVisual) {
1939  TDFXPtr pTDFX;
1940  int i, j, index, v, repeat, max;
1941
1942  TDFXTRACE("TDFXLoadPalette16 start\n");
1943  pTDFX = TDFXPTR(pScrn);
1944
1945  for (i=0; i<numColors; i++) {
1946    index=indices[i];
1947    v=(colors[index/2].red<<16)|(colors[index].green<<8)|colors[index/2].blue;
1948    max=min((index+1)<<2, 256);
1949    for (j = index<<2; j < max; j++)
1950    {
1951      repeat=100;
1952      do {
1953	TDFXWriteLongMMIO(pTDFX, DACADDR, j);
1954      } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=j);
1955      if (!repeat) {
1956	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, bypassing CLUT\n");
1957	pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1958	return;
1959      }
1960
1961      repeat=100;
1962      do {
1963	TDFXWriteLongMMIO(pTDFX, DACDATA, v);
1964      } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
1965      if (!repeat) {
1966	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, bypassing CLUT\n");
1967	pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1968	return;
1969      }
1970    }
1971  }
1972}
1973
1974static void
1975TDFXLoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1976		  VisualPtr pVisual) {
1977  TDFXPtr pTDFX;
1978  int i, index, v, repeat;
1979
1980  TDFXTRACE("TDFXLoadPalette24 start\n");
1981  pTDFX = TDFXPTR(pScrn);
1982  for (i=0; i<numColors; i++) {
1983    index=indices[i];
1984    v=(colors[index].red<<16)|(colors[index].green<<8)|colors[index].blue;
1985    repeat=100;
1986    do {
1987      TDFXWriteLongMMIO(pTDFX, DACADDR, index);
1988    } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=index);
1989    if (!repeat) {
1990      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, "
1991		 "bypassing CLUT\n");
1992      pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
1993      return;
1994    }
1995    repeat=100;
1996    do {
1997      TDFXWriteLongMMIO(pTDFX, DACDATA, v);
1998    } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
1999    if (!repeat) {
2000      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, "
2001		 "bypassing CLUT\n");
2002      pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
2003      return;
2004    }
2005  }
2006}
2007
2008#define TILE_WIDTH 128
2009#define TILE_HEIGHT 32
2010
2011static int
2012calcBufferStride(int xres, Bool tiled, int cpp)
2013{
2014  int strideInTiles;
2015
2016  if (tiled == TRUE) {
2017    /* Calculate tile width stuff */
2018    strideInTiles = (xres+TILE_WIDTH-1)/TILE_WIDTH;
2019
2020    return strideInTiles*cpp*TILE_WIDTH;
2021  } else {
2022    return xres*cpp;
2023  }
2024} /* calcBufferStride */
2025
2026static int
2027calcBufferHeightInTiles(int yres)
2028{
2029  int heightInTiles;            /* Height of buffer in tiles */
2030
2031
2032  /* Calculate tile height stuff */
2033  heightInTiles = yres >> 5;
2034
2035  if (yres & (TILE_HEIGHT - 1))
2036    heightInTiles++;
2037
2038  return heightInTiles;
2039
2040} /* calcBufferHeightInTiles */
2041
2042#if 0
2043static int
2044calcBufferSizeInTiles(int xres, int yres, int cpp) {
2045  int bufSizeInTiles;           /* Size of buffer in tiles */
2046
2047  bufSizeInTiles =
2048    calcBufferHeightInTiles(yres) * (calcBufferStride(xres, TRUE, cpp) >> 7);
2049
2050  return bufSizeInTiles;
2051
2052} /* calcBufferSizeInTiles */
2053#endif
2054
2055static int
2056calcBufferSize(int xres, int yres, Bool tiled, int cpp)
2057{
2058  int stride, height, bufSize;
2059
2060  if (tiled) {
2061    stride = calcBufferStride(xres, tiled, cpp);
2062    height = TILE_HEIGHT * calcBufferHeightInTiles(yres);
2063  } else {
2064    stride = xres*cpp;
2065    height = yres;
2066  }
2067
2068  bufSize = stride * height;
2069
2070  return bufSize;
2071
2072} /* calcBufferSize */
2073
2074static void allocateMemory(ScrnInfoPtr pScrn) {
2075  TDFXPtr pTDFX;
2076  int memRemaining, fifoSize, screenSizeInTiles, cursorSize;
2077  int fbSize;
2078  int verb;
2079  char *str;
2080
2081  pTDFX = TDFXPTR(pScrn);
2082
2083  if (pTDFX->cpp!=3) {
2084    screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
2085				     TRUE, pTDFX->cpp);
2086  }
2087  else {
2088    /* cpp==3 needs to bump up to 4 */
2089    screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
2090				     TRUE, 4);
2091  }
2092
2093  /*
2094   * Layout is:
2095   *    cursor, fifo, fb, tex, bb, db
2096   */
2097
2098  fbSize = (pScrn->virtualY + pTDFX->pixmapCacheLinesMin) * pTDFX->stride;
2099
2100  memRemaining=((pScrn->videoRam<<10) - 1) &~ 0xFFF;
2101  /* Note that a page is 4096 bytes, and a  */
2102  /* tile is 32 x 128 = 4096 bytes.  So,    */
2103  /* page and tile boundaries are the same  */
2104  /* Place the depth offset first, forcing  */
2105  /* it to be on an *odd* page boundary.    */
2106  pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF;
2107  if ((pTDFX->depthOffset & (0x1 << 12)) == 0) {
2108#if	1
2109    if (pTDFX->depthOffset > 0) {
2110      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2111                 "Changing depth offset from 0x%08x to 0x%08x\n",
2112                 pTDFX->depthOffset,
2113                 pTDFX->depthOffset - (0x1 << 12));
2114    }
2115#endif
2116      pTDFX->depthOffset -= (0x1 << 12);
2117  }
2118  /* Now, place the back buffer, forcing it */
2119  /* to be on an *even* page boundary.      */
2120  pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF;
2121  if (pTDFX->backOffset & (0x1 << 12)) {
2122#if	1
2123    if (pTDFX->backOffset > 0) {
2124      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2125                 "Changing back offset from 0x%08x to 0x%08x\n",
2126                 pTDFX->backOffset,
2127                 pTDFX->backOffset - (0x1 << 12));
2128    }
2129#endif
2130      pTDFX->backOffset -= (0x1 << 12);
2131  }
2132  /* Give the cmd fifo at least             */
2133  /* CMDFIFO_PAGES pages, but no more than  */
2134  /* 64. NOTE: Don't go higher than 64, as  */
2135  /* there is suspect code in Glide3 !      */
2136  fifoSize = ((64 <= CMDFIFO_PAGES) ? 64 : CMDFIFO_PAGES) << 12;
2137
2138  /* We give 4096 bytes to the cursor  */
2139  cursorSize = 4096;
2140  pTDFX->cursorOffset = 0;
2141
2142  pTDFX->fifoOffset = pTDFX->cursorOffset + cursorSize;
2143  pTDFX->fifoSize = fifoSize;
2144  /* Now, place the front buffer, forcing   */
2145  /* it to be on a page boundary too, just  */
2146  /* for giggles.                           */
2147  pTDFX->fbOffset = pTDFX->fifoOffset + pTDFX->fifoSize;
2148  pTDFX->texOffset = pTDFX->fbOffset + fbSize;
2149  if (pTDFX->depthOffset <= pTDFX->texOffset ||
2150	pTDFX->backOffset <= pTDFX->texOffset) {
2151    /*
2152     * pTDFX->texSize < 0 means that the DRI is disabled.  pTDFX->backOffset
2153     * is used to calculate the maximum amount of memory available for
2154     * 2D offscreen use.  With DRI disabled, set this to the top of memory.
2155     */
2156
2157    pTDFX->texSize = -1;
2158    pTDFX->backOffset = pScrn->videoRam * 1024;
2159    pTDFX->depthOffset = -1;
2160    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2161	"Not enough video memory available for textures and depth buffer\n"
2162	"\tand/or back buffer.  Disabling DRI.  To use DRI try lower\n"
2163	"\tresolution modes and/or a smaller virtual screen size\n");
2164  } else {
2165    pTDFX->texSize = pTDFX->backOffset - pTDFX->texOffset;
2166    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textures Memory %0.02f MB\n",
2167		(float)pTDFX->texSize/1024.0/1024.0);
2168  }
2169
2170/* This could be set to 2 or 3 */
2171#define OFFSET_VERB 1
2172  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
2173             "Cursor Offset: [0x%08X,0x%08X)\n",
2174             pTDFX->cursorOffset,
2175             pTDFX->cursorOffset + cursorSize);
2176  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
2177             "Fifo Offset: [0x%08X, 0x%08X)\n",
2178             pTDFX->fifoOffset,
2179             pTDFX->fifoOffset + pTDFX->fifoSize);
2180  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
2181             "Front Buffer Offset: [0x%08X, 0x%08X)\n",
2182             pTDFX->fbOffset,
2183             pTDFX->fbOffset +
2184		(pScrn->virtualY+pTDFX->pixmapCacheLinesMin)*pTDFX->stride);
2185  if (pTDFX->texSize > 0) {
2186    verb = OFFSET_VERB;
2187    str = "";
2188  } else {
2189    verb = 3;
2190    str = "(NOT USED) ";
2191  }
2192  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2193             "%sTexture Offset: [0x%08X, 0x%08X)\n", str,
2194             pTDFX->texOffset,
2195             pTDFX->texOffset + pTDFX->texSize);
2196  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2197             "%sBackOffset: [0x%08X, 0x%08X)\n", str,
2198             pTDFX->backOffset,
2199             pTDFX->backOffset + screenSizeInTiles);
2200  xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
2201             "%sDepthOffset: [0x%08X, 0x%08X)\n", str,
2202             pTDFX->depthOffset,
2203             pTDFX->depthOffset + screenSizeInTiles);
2204}
2205
2206static Bool
2207TDFXScreenInit(SCREEN_INIT_ARGS_DECL) {
2208  ScrnInfoPtr pScrn;
2209  vgaHWPtr hwp;
2210  TDFXPtr pTDFX;
2211  VisualPtr visual;
2212  BoxRec MemBox;
2213#ifdef TDFXDRI
2214  MessageType driFrom = X_DEFAULT;
2215#endif
2216  int scanlines;
2217
2218  TDFXTRACE("TDFXScreenInit start\n");
2219  pScrn = xf86ScreenToScrn(pScreen);
2220  pTDFX = TDFXPTR(pScrn);
2221  hwp = VGAHWPTR(pScrn);
2222
2223  if (!TDFXMapMem(pScrn)) return FALSE;
2224  pScrn->memPhysBase = (int)pTDFX->LinearAddr[0];
2225
2226  if (!pTDFX->usePIO) TDFXSetMMIOAccess(pTDFX);
2227
2228#ifndef USE_PCIVGAIO
2229  /* access VGA registers through the IO BAR, not legacy decoding */
2230  hwp->PIOOffset = pTDFX->PIOBase[0] - 0x300;
2231#endif
2232  vgaHWGetIOBase(hwp);
2233  /* Map VGA memory only for primary cards (to save/restore textmode data). */
2234  if (pTDFX->Primary) {
2235    if (!vgaHWMapMem(pScrn))
2236      return FALSE;
2237  }
2238
2239  pTDFX->stride = pScrn->displayWidth*pTDFX->cpp;
2240
2241  /* enough to do DVD */
2242  pTDFX->pixmapCacheLinesMin = ((720*480*pTDFX->cpp) +
2243					pTDFX->stride - 1)/pTDFX->stride;
2244
2245  if (pTDFX->ChipType > PCI_CHIP_VOODOO3) {
2246  	if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 4095)
2247		pTDFX->pixmapCacheLinesMin = 4095 - pScrn->virtualY;
2248  } else {
2249  	if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 2047)
2250		pTDFX->pixmapCacheLinesMin = 2047 - pScrn->virtualY;
2251  }
2252
2253  allocateMemory(pScrn);
2254
2255  pScrn->fbOffset = pTDFX->fbOffset;
2256
2257#if 0
2258  if (pTDFX->numChips>1) {
2259    if (xf86ReturnOptValBool(pTDFX->Options, OPTION_NO_SLI, FALSE)) {
2260      TDFXSetupSLI(pScrn, FALSE, 0);
2261    } else {
2262      TDFXSetupSLI(pScrn, TRUE, 0);
2263    }
2264  }
2265#endif
2266
2267  TDFXSetLFBConfig(pTDFX);
2268
2269  /* We initialize in the state that our FIFO is up to date */
2270  pTDFX->syncDone=TRUE;
2271  if (!TDFXInitFifo(pScreen)) {
2272    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize private\n");
2273    return FALSE;
2274  }
2275
2276  scanlines = (pTDFX->backOffset - pTDFX->fbOffset) / pTDFX->stride;
2277  if(pTDFX->ChipType < PCI_CHIP_VOODOO5) {
2278      if (scanlines > 2047)
2279	scanlines = 2047;
2280  } else {
2281      /* MaxClip seems to have only 12 bits => 0->4095 */
2282      if (scanlines > 4095)
2283	scanlines = 4095;
2284  }
2285
2286  pTDFX->pixmapCacheLinesMax = scanlines - pScrn->virtualY;
2287
2288  /*
2289   * Note, pTDFX->pixmapCacheLinesMax may be smaller than
2290   * pTDFX->pixmapCacheLinesMin when pTDFX->texSize < 0.  DRI is disabled
2291   * in that case, so pTDFX->pixmapCacheLinesMin isn't used when that's true.
2292   */
2293  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2294    "Minimum %d, Maximum %d lines of offscreen memory available\n",
2295	pTDFX->pixmapCacheLinesMin, pTDFX->pixmapCacheLinesMax);
2296
2297  MemBox.y1 = 0;
2298  MemBox.x1 = 0;
2299  MemBox.x2 = pScrn->displayWidth;
2300  MemBox.y2 = scanlines;
2301
2302  pTDFX->maxClip = MemBox.x2 | (MemBox.y2 << 16);
2303
2304#if 0
2305  TDFXInitWithBIOSData(pScrn);
2306#endif
2307  TDFXInitVGA(pScrn);
2308  TDFXSave(pScrn);
2309  if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
2310
2311  TDFXSetLFBConfig(pTDFX);
2312
2313  miClearVisualTypes();
2314
2315  if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
2316			pScrn->rgbBits, pScrn->defaultVisual))
2317    return FALSE;
2318
2319  miSetPixmapDepths ();
2320
2321#ifdef TDFXDRI
2322  /*
2323   * Setup DRI after visuals have been established, but before fbScreenInit
2324   * is called.   fbScreenInit will eventually call into the drivers
2325   * InitGLXVisuals call back.
2326   */
2327  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_DRI, TRUE) || pTDFX->NoAccel) {
2328      pTDFX->directRenderingEnabled = FALSE;
2329      driFrom = X_CONFIG;
2330  } else if (pTDFX->texSize < 0) {
2331      pTDFX->directRenderingEnabled = FALSE;
2332      driFrom = X_PROBED;
2333  } else {
2334      pTDFX->directRenderingEnabled = TDFXDRIScreenInit(pScreen);
2335  }
2336#endif
2337
2338  switch (pScrn->bitsPerPixel) {
2339  case 8:
2340  case 16:
2341  case 24:
2342  case 32:
2343    if (!fbScreenInit(pScreen, pTDFX->FbBase+pTDFX->fbOffset,
2344		       pScrn->virtualX, pScrn->virtualY,
2345		       pScrn->xDpi, pScrn->yDpi,
2346		       pScrn->displayWidth, pScrn->bitsPerPixel))
2347      return FALSE;
2348    break;
2349  default:
2350    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2351	       "Internal error: invalid bpp (%d) in TDFXScrnInit\n",
2352	       pScrn->bitsPerPixel);
2353    return FALSE;
2354  }
2355
2356  if (pScrn->bitsPerPixel>8) {
2357    visual = pScreen->visuals + pScreen->numVisuals;
2358    while (--visual >= pScreen->visuals) {
2359      if ((visual->class | DynamicClass) == DirectColor) {
2360	visual->offsetRed = pScrn->offset.red;
2361	visual->offsetGreen = pScrn->offset.green;
2362	visual->offsetBlue = pScrn->offset.blue;
2363	visual->redMask = pScrn->mask.red;
2364	visual->greenMask = pScrn->mask.green;
2365	visual->blueMask = pScrn->mask.blue;
2366      }
2367    }
2368  }
2369
2370  /* must be after RGB ordering fixed */
2371  fbPictureInit (pScreen, 0, 0);
2372
2373  xf86SetBlackWhitePixels(pScreen);
2374
2375  TDFXDGAInit(pScreen);
2376
2377  xf86InitFBManager(pScreen, &MemBox);
2378
2379  if (!pTDFX->NoAccel) {
2380    if (!TDFXAccelInit(pScreen)) {
2381      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2382		 "Hardware acceleration initialization failed\n");
2383    }
2384  }
2385
2386  miInitializeBackingStore(pScreen);
2387  xf86SetBackingStore(pScreen);
2388  xf86SetSilkenMouse(pScreen);
2389
2390  miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2391
2392  if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
2393    if (!TDFXCursorInit(pScreen)) {
2394      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2395		 "Hardware cursor initialization failed\n");
2396    }
2397  }
2398
2399  if (!miCreateDefColormap(pScreen)) return FALSE;
2400
2401  if (pScrn->bitsPerPixel==16) {
2402    if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette16, 0,
2403			     CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
2404      return FALSE;
2405  } else {
2406    if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette24, 0,
2407			     CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
2408      return FALSE;
2409  }
2410
2411  TDFXAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
2412
2413  xf86DPMSInit(pScreen, TDFXDisplayPowerManagementSet, 0);
2414
2415  /* Initialize Xv support */
2416  TDFXInitVideo (pScreen);
2417
2418  pScreen->SaveScreen = TDFXSaveScreen;
2419  pTDFX->CloseScreen = pScreen->CloseScreen;
2420  pScreen->CloseScreen = TDFXCloseScreen;
2421
2422  pTDFX->BlockHandler = pScreen->BlockHandler;
2423  pScreen->BlockHandler = TDFXBlockHandler;
2424
2425  /*
2426   * DRICloseScreen isn't called thru a wrapper but explicitely
2427   * in of TDFXCloseScreen() before the rest is unwrapped
2428   */
2429
2430#ifdef TDFXDRI
2431  if (pTDFX->directRenderingEnabled) {
2432	/* Now that mi, fb, drm and others have done their thing,
2433         * complete the DRI setup.
2434         */
2435	pTDFX->directRenderingEnabled = TDFXDRIFinishScreenInit(pScreen);
2436  }
2437  if (pTDFX->directRenderingEnabled) {
2438	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2439  } else {
2440	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
2441  }
2442#endif
2443
2444  if (serverGeneration == 1)
2445    xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2446
2447  return TRUE;
2448}
2449
2450Bool
2451TDFXSwitchMode(SWITCH_MODE_ARGS_DECL) {
2452  SCRN_INFO_PTR(arg);
2453
2454  TDFXTRACE("TDFXSwitchMode start\n");
2455  return TDFXModeInit(pScrn, mode);
2456}
2457
2458void
2459TDFXAdjustFrame(ADJUST_FRAME_ARGS_DECL) {
2460  SCRN_INFO_PTR(arg);
2461  TDFXPtr pTDFX;
2462  TDFXRegPtr tdfxReg;
2463
2464  TDFXTRACE("TDFXAdjustFrame start\n");
2465  pTDFX = TDFXPTR(pScrn);
2466
2467  if (pTDFX->ShowCache && y && pScrn->vtSema)
2468    y += pScrn->virtualY - 1;
2469
2470  tdfxReg = &pTDFX->ModeReg;
2471  if(pTDFX->ShowCache && y && pScrn->vtSema)
2472     y += pScrn->virtualY - 1;
2473  tdfxReg->startaddr = pTDFX->fbOffset+y*pTDFX->stride+(x*pTDFX->cpp);
2474  TDFXTRACE("TDFXAdjustFrame to x=%d y=%d offset=%d\n", x, y, tdfxReg->startaddr);
2475  pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
2476}
2477
2478static Bool
2479TDFXEnterVT(VT_FUNC_ARGS_DECL) {
2480  SCRN_INFO_PTR(arg);
2481  ScreenPtr pScreen;
2482#ifdef TDFXDRI
2483  TDFXPtr pTDFX;
2484#endif
2485
2486  TDFXTRACE("TDFXEnterVT start\n");
2487  pScreen = xf86ScrnToScreen(pScrn);
2488  TDFXInitFifo(pScreen);
2489#ifdef TDFXDRI
2490  pTDFX = TDFXPTR(pScrn);
2491  if (pTDFX->directRenderingEnabled) {
2492    DRIUnlock(pScreen);
2493  }
2494#endif
2495  if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
2496  TDFXAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2497  return TRUE;
2498}
2499
2500static void
2501TDFXLeaveVT(VT_FUNC_ARGS_DECL) {
2502  SCRN_INFO_PTR(arg);
2503  vgaHWPtr hwp;
2504  ScreenPtr pScreen;
2505  TDFXPtr pTDFX;
2506
2507  TDFXTRACE("TDFXLeaveVT start\n");
2508  hwp=VGAHWPTR(pScrn);
2509  TDFXRestore(pScrn);
2510  vgaHWLock(hwp);
2511  pScreen = xf86ScrnToScreen(pScrn);
2512  pTDFX = TDFXPTR(pScrn);
2513  pTDFX->sync(pScrn);
2514  TDFXShutdownFifo(pScreen);
2515#ifdef TDFXDRI
2516  if (pTDFX->directRenderingEnabled) {
2517    DRILock(pScreen, 0);
2518  }
2519#endif
2520}
2521
2522static Bool
2523TDFXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
2524{
2525  ScrnInfoPtr pScrn;
2526  vgaHWPtr hwp;
2527  TDFXPtr pTDFX;
2528
2529  TDFXTRACE("TDFXCloseScreen start\n");
2530  pScrn = xf86ScreenToScrn(pScreen);
2531  hwp = VGAHWPTR(pScrn);
2532  pTDFX = TDFXPTR(pScrn);
2533
2534#ifdef TDFXDRI
2535    if (pTDFX->directRenderingEnabled) {
2536	TDFXDRICloseScreen(pScreen);
2537	pTDFX->directRenderingEnabled=FALSE;
2538    }
2539#endif
2540
2541  TDFXShutdownFifo(pScreen);
2542
2543  if (pScrn->vtSema) {
2544      TDFXRestore(pScrn);
2545      vgaHWLock(hwp);
2546      TDFXUnmapMem(pScrn);
2547      vgaHWUnmapMem(pScrn);
2548  }
2549
2550#ifdef HAVE_XAA_H
2551  if (pTDFX->AccelInfoRec) XAADestroyInfoRec(pTDFX->AccelInfoRec);
2552  pTDFX->AccelInfoRec=0;
2553#endif
2554  if (pTDFX->DGAModes) free(pTDFX->DGAModes);
2555  pTDFX->DGAModes=0;
2556  if (pTDFX->scanlineColorExpandBuffers[0])
2557    free(pTDFX->scanlineColorExpandBuffers[0]);
2558  pTDFX->scanlineColorExpandBuffers[0]=0;
2559  if (pTDFX->scanlineColorExpandBuffers[1])
2560    free(pTDFX->scanlineColorExpandBuffers[1]);
2561  pTDFX->scanlineColorExpandBuffers[1]=0;
2562  if (pTDFX->overlayAdaptor)
2563    free(pTDFX->overlayAdaptor);
2564  pTDFX->overlayAdaptor=0;
2565  if (pTDFX->textureAdaptor)
2566    free(pTDFX->textureAdaptor);
2567  pTDFX->textureAdaptor=0;
2568
2569  pScrn->vtSema=FALSE;
2570
2571  pScreen->BlockHandler = pTDFX->BlockHandler;
2572  pScreen->CloseScreen = pTDFX->CloseScreen;
2573  return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
2574}
2575
2576static void
2577TDFXFreeScreen(FREE_SCREEN_ARGS_DECL) {
2578  SCRN_INFO_PTR(arg);
2579  TDFXTRACE("TDFXFreeScreen start\n");
2580  TDFXFreeRec(pScrn);
2581  if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
2582    vgaHWFreeHWRec(pScrn);
2583}
2584
2585static ModeStatus
2586TDFXValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) {
2587  SCRN_INFO_PTR(arg);
2588  TDFXPtr pTDFX;
2589
2590  TDFXTRACE("TDFXValidMode start\n");
2591  if ((mode->HDisplay>2048) || (mode->VDisplay>1536))
2592    return MODE_BAD;
2593  /* Banshee doesn't support interlace, but Voodoo 3 and higher do. */
2594  pTDFX = TDFXPTR(pScrn);
2595  if (mode->Flags&V_INTERLACE) {
2596    switch (pTDFX->ChipType) {
2597      case PCI_CHIP_BANSHEE:
2598        return MODE_BAD;
2599        break;
2600      case PCI_CHIP_VOODOO3:
2601      case PCI_CHIP_VOODOO5:
2602        return MODE_OK;
2603        break;
2604      default:
2605        return MODE_BAD;
2606        break;
2607    }
2608  }
2609  /* In clock doubled mode widths must be divisible by 16 instead of 8 */
2610  if ((mode->Clock>TDFX2XCUTOFF) && (mode->HDisplay%16))
2611    return MODE_BAD;
2612  return MODE_OK;
2613}
2614
2615/* replacement of vgaHWBlankScreen(pScrn, unblank) which doesn't unblank
2616 * the screen if it is already unblanked. */
2617static void
2618TDFXBlankScreen(ScrnInfoPtr pScrn, Bool unblank)
2619{
2620  vgaHWPtr hwp = VGAHWPTR(pScrn);
2621  unsigned char scrn;
2622
2623  TDFXTRACE("TDFXBlankScreen start\n");
2624
2625  scrn = hwp->readSeq(hwp, 0x01);
2626
2627  if (unblank) {
2628    if((scrn & 0x20) == 0) return;
2629    scrn &= ~0x20;                    /* enable screen */
2630  } else {
2631    scrn |= 0x20;                     /* blank screen */
2632  }
2633
2634  vgaHWSeqReset(hwp, TRUE);
2635  hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
2636  vgaHWSeqReset(hwp, FALSE);
2637}
2638
2639static Bool
2640TDFXSaveScreen(ScreenPtr pScreen, int mode)
2641{
2642  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2643  Bool unblank;
2644
2645  TDFXTRACE("TDFXSaveScreen start\n");
2646
2647  unblank = xf86IsUnblank(mode);
2648
2649  if (unblank)
2650    SetTimeSinceLastInputEvent();
2651
2652  if (pScrn->vtSema) {
2653    TDFXBlankScreen(pScrn, unblank);
2654  }
2655  return TRUE;
2656}
2657
2658static void
2659TDFXBlockHandler(BLOCKHANDLER_ARGS_DECL)
2660{
2661    SCREEN_PTR(arg);
2662    ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
2663    TDFXPtr     pTDFX   = TDFXPTR(pScrn);
2664
2665    pScreen->BlockHandler = pTDFX->BlockHandler;
2666    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
2667    pScreen->BlockHandler = TDFXBlockHandler;
2668
2669    if(pTDFX->VideoTimerCallback) {
2670        (*pTDFX->VideoTimerCallback)(pScrn, currentTime.milliseconds);
2671    }
2672}
2673
2674static void
2675TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
2676			      int flags) {
2677  TDFXPtr pTDFX;
2678  int dacmode, state=0;
2679
2680  TDFXTRACE("TDFXDPMS start\n");
2681  pTDFX = TDFXPTR(pScrn);
2682  dacmode=pTDFX->readLong(pTDFX, DACMODE);
2683  switch (PowerManagementMode) {
2684  case DPMSModeOn:
2685    /* Screen: On; HSync: On, VSync: On */
2686    state=0;
2687    break;
2688  case DPMSModeStandby:
2689    /* Screen: Off; HSync: Off, VSync: On */
2690    state=BIT(3);
2691    break;
2692  case DPMSModeSuspend:
2693    /* Screen: Off; HSync: On, VSync: Off */
2694    state=BIT(1);
2695    break;
2696  case DPMSModeOff:
2697    /* Screen: Off; HSync: Off, VSync: Off */
2698    state=BIT(1)|BIT(3);
2699    break;
2700  }
2701  dacmode&=~(BIT(1)|BIT(3));
2702  dacmode|=state;
2703  pTDFX->writeLong(pTDFX, DACMODE, dacmode);
2704}
2705