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