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