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