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