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