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