apm_driver.c revision 8e0ed500
1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "apm.h" 7#include "xf86cmap.h" 8#include "shadowfb.h" 9#include "xf86Resources.h" 10#include "xf86int10.h" 11#include "xf86RAC.h" 12#include "vbe.h" 13 14#include "opaque.h" 15#define DPMS_SERVER 16#include <X11/extensions/dpms.h> 17 18#define APM_VERSION 4000 19#define APM_NAME "APM" 20#define APM_DRIVER_NAME "apm" 21#define APM_MAJOR_VERSION PACKAGE_VERSION_MAJOR 22#define APM_MINOR_VERSION PACKAGE_VERSION_MINOR 23#define APM_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 24#ifndef PCI_CHIP_AT3D 25#define PCI_CHIP_AT3D 0x643D 26#endif 27 28/* bytes to save for text/font data */ 29#define TEXT_AMOUNT 32768 30 31/* Mandatory functions */ 32static const OptionInfoRec * ApmAvailableOptions(int chipid, int busid); 33static void ApmIdentify(int flags); 34static Bool ApmProbe(DriverPtr drv, int flags); 35static Bool ApmPreInit(ScrnInfoPtr pScrn, int flags); 36static Bool ApmScreenInit(int Index, ScreenPtr pScreen, int argc, 37 char **argv); 38static Bool ApmEnterVT(int scrnIndex, int flags); 39static void ApmLeaveVT(int scrnIndex, int flags); 40static Bool ApmCloseScreen(int scrnIndex, ScreenPtr pScreen); 41static void ApmFreeScreen(int scrnIndex, int flags); 42static ModeStatus ApmValidMode(int scrnIndex, DisplayModePtr mode, 43 Bool verbose, int flags); 44static Bool ApmSaveScreen(ScreenPtr pScreen, int mode); 45static void ApmUnlock(ApmPtr pApm); 46static void ApmLock(ApmPtr pApm); 47static void ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, 48 ApmRegPtr ApmReg); 49static void ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 50 LOCO *colors, VisualPtr pVisual); 51static void ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, 52 int PowerManagementMode, 53 int flags); 54static void ApmProbeDDC(ScrnInfoPtr pScrn, int index); 55 56#ifdef XF86RUSH 57int ApmPixmapIndex = -1; 58static unsigned long ApmGeneration = 0; 59#endif 60 61_X_EXPORT DriverRec APM = { 62 APM_VERSION, 63 APM_DRIVER_NAME, 64 ApmIdentify, 65 ApmProbe, 66 ApmAvailableOptions, 67 NULL, 68 0 69}; 70 71static SymTabRec ApmChipsets[] = { 72 { AP6422, "AP6422" }, 73 { AT24, "AT24" }, 74 { AT3D, "AT3D" }, 75 { -1, NULL } 76}; 77 78static PciChipsets ApmPciChipsets[] = { 79 { PCI_CHIP_AP6422, PCI_CHIP_AP6422, RES_SHARED_VGA }, 80 { PCI_CHIP_AT24, PCI_CHIP_AT24, RES_SHARED_VGA }, 81 { PCI_CHIP_AT3D, PCI_CHIP_AT3D, RES_SHARED_VGA }, 82 { -1, -1, RES_UNDEFINED } 83}; 84 85#ifdef HAVE_ISA 86static IsaChipsets ApmIsaChipsets[] = { 87 { PCI_CHIP_AP6422, RES_EXCLUSIVE_VGA}, 88 {-1, RES_UNDEFINED} 89}; 90#endif 91 92typedef enum { 93 OPTION_SET_MCLK, 94 OPTION_SW_CURSOR, 95 OPTION_HW_CURSOR, 96 OPTION_NOLINEAR, 97 OPTION_NOACCEL, 98 OPTION_SHADOW_FB, 99 OPTION_PCI_BURST, 100 OPTION_REMAP_DPMS_ON, 101 OPTION_REMAP_DPMS_STANDBY, 102 OPTION_REMAP_DPMS_SUSPEND, 103 OPTION_REMAP_DPMS_OFF, 104 OPTION_PCI_RETRY 105} ApmOpts; 106 107static const OptionInfoRec ApmOptions[] = 108{ 109 {OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, 110 {0}, FALSE}, 111 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, 112 {0}, FALSE}, 113 {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, 114 {0}, TRUE}, 115 {OPTION_NOLINEAR, "NoLinear", OPTV_BOOLEAN, 116 {0}, FALSE}, 117 {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, 118 {0}, FALSE}, 119 {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, 120 {0}, FALSE}, 121 {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, 122 {0}, FALSE}, 123 {OPTION_REMAP_DPMS_ON, "Remap_DPMS_On", OPTV_ANYSTR, 124 {0}, FALSE}, 125 {OPTION_REMAP_DPMS_STANDBY, "Remap_DPMS_Standby", OPTV_ANYSTR, 126 {0}, FALSE}, 127 {OPTION_REMAP_DPMS_SUSPEND, "Remap_DPMS_Suspend", OPTV_ANYSTR, 128 {0}, FALSE}, 129 {OPTION_REMAP_DPMS_OFF, "Remap_DPMS_Off", OPTV_ANYSTR, 130 {0}, FALSE}, 131 {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, 132 {0}, FALSE}, 133 {-1, NULL, OPTV_NONE, 134 {0}, FALSE} 135}; 136 137/* 138 * List of symbols from other modules that this module references. This 139 * list is used to tell the loader that it is OK for symbols here to be 140 * unresolved providing that it hasn't been told that they haven't been 141 * told that they are essential via a call to xf86LoaderReqSymbols() or 142 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about 143 * unresolved symbols that are not required. 144 */ 145 146static const char *vgahwSymbols[] = { 147 "vgaHWBlankScreen", 148 "vgaHWCursor", 149 "vgaHWFreeHWRec", 150 "vgaHWGetHWRec", 151 "vgaHWGetIOBase", 152 "vgaHWInit", 153 "vgaHWLock", 154 "vgaHWMapMem", 155 "vgaHWProtect", 156 "vgaHWRestore", 157 "vgaHWSave", 158 "vgaHWSetMmioFuncs", 159 "vgaHWUnlock", 160 NULL 161}; 162 163static const char *xaaSymbols[] = { 164 "XAACreateInfoRec", 165 "XAACursorInfoRec", 166 "XAACursorInit", 167 "XAADestroyInfoRec", 168 "XAAGlyphScanlineFuncLSBFirst", 169 "XAAInit", 170 "XAAReverseBitOrder", 171 "XAAStippleScanlineFuncMSBFirst", 172 NULL 173}; 174 175static const char *ramdacSymbols[] = { 176 "xf86CreateCursorInfoRec", 177 "xf86DestroyCursorInfoRec", 178 "xf86InitCursor", 179 NULL 180}; 181 182#ifdef XFree86LOADER 183static const char *vbeSymbols[] = { 184 "VBEInit", 185 "vbeDoEDID", 186 "vbeFree", 187 NULL 188}; 189#endif 190 191static const char *ddcSymbols[] = { 192 "xf86DoEDID_DDC1", 193 "xf86DoEDID_DDC2", 194 "xf86PrintEDID", 195 NULL 196}; 197 198static const char *i2cSymbols[] = { 199 "xf86CreateI2CBusRec", 200 "xf86I2CBusInit", 201 NULL 202}; 203 204static const char *shadowSymbols[] = { 205 "ShadowFBInit", 206 NULL 207}; 208 209#ifdef XFree86LOADER 210static const char *miscfbSymbols[] = { 211#ifdef HAVE_XF1BPP 212 "xf1bppScreenInit", 213#endif 214#ifdef HAVE_XF4BPP 215 "xf4bppScreenInit", 216#endif 217 NULL 218}; 219#endif 220 221static const char *fbSymbols[] = { 222 "fbPictureInit", 223 "fbScreenInit", 224 NULL 225}; 226 227static const char *int10Symbols[] = { 228 "xf86Free10", 229 "xf86InitInt10", 230 NULL 231}; 232 233#ifdef XFree86LOADER 234 235static XF86ModuleVersionInfo apmVersRec = { 236 "apm", 237 MODULEVENDORSTRING, 238 MODINFOSTRING1, 239 MODINFOSTRING2, 240 XORG_VERSION_CURRENT, 241 APM_MAJOR_VERSION, APM_MINOR_VERSION, APM_PATCHLEVEL, 242 ABI_CLASS_VIDEODRV, /* This is a video driver */ 243 ABI_VIDEODRV_VERSION, 244 MOD_CLASS_VIDEODRV, 245 {0,0,0,0} 246}; 247 248static MODULESETUPPROTO(apmSetup); 249 250/* 251 * This is the module init data. 252 * Its name has to be the driver name followed by ModuleData. 253 */ 254_X_EXPORT XF86ModuleData apmModuleData = { &apmVersRec, apmSetup, NULL }; 255 256static pointer 257apmSetup(pointer module, pointer opts, int *errmaj, int *errmain) 258{ 259 static Bool setupDone = FALSE; 260 261 if (!setupDone) { 262 setupDone = TRUE; 263 xf86AddDriver(&APM, module, 0); 264 265 LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, 266 miscfbSymbols, ramdacSymbols, vbeSymbols, 267 ddcSymbols, i2cSymbols, shadowSymbols, 268 int10Symbols, NULL); 269 270 return (pointer)1; 271 } 272 else { 273 if (errmaj) *errmaj = LDR_ONCEONLY; 274 return NULL; 275 } 276} 277#endif 278 279static Bool 280ApmGetRec(ScrnInfoPtr pScrn) 281{ 282 if (pScrn->driverPrivate) 283 return TRUE; 284 pScrn->driverPrivate = xnfcalloc(sizeof(ApmRec), 1); 285 /* pScrn->driverPrivate != NULL at this point */ 286 287 return TRUE; 288} 289 290static void 291ApmFreeRec(ScrnInfoPtr pScrn) 292{ 293 if (pScrn->driverPrivate) { 294 xfree(pScrn->driverPrivate); 295 pScrn->driverPrivate = NULL; 296 } 297} 298 299 300/* unlock Alliance registers */ 301static void 302ApmUnlock(ApmPtr pApm) 303{ 304 if (pApm->Chipset >= AT3D && !pApm->noLinear) 305 ApmWriteSeq(0x10, 0x12); 306 else 307 wrinx(pApm->xport, 0x10, 0x12); 308} 309 310/* lock Alliance registers */ 311static void 312ApmLock(ApmPtr pApm) 313{ 314 if (pApm->Chipset >= AT3D && !pApm->noLinear) 315 ApmWriteSeq(0x10, pApm->savedSR10 ? 0 : 0x12); 316 else 317 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12); 318} 319 320static void 321ApmIdentify(int flags) 322{ 323 xf86PrintChipsets(APM_NAME, "driver for the Alliance chipsets", 324 ApmChipsets); 325} 326 327static const OptionInfoRec * 328ApmAvailableOptions(int chipid, int busid) 329{ 330 return ApmOptions; 331} 332 333#ifdef HAVE_ISA 334static int 335ApmFindIsaDevice(GDevPtr dev) 336{ 337 char save = rdinx(0x3C4, 0x10); 338 int i; 339 int apmChip = -1; 340 341 /* 342 * Start by probing the VGA chipset. 343 */ 344 outw(0x3C4, 0x1210); 345 if (rdinx(0x3C4, 0x11) == 'P' && rdinx(0x3C4, 0x12) == 'r' && 346 rdinx(0x3C4, 0x13) == 'o') { 347 char id_ap6420[] = "6420"; 348 char id_ap6422[] = "6422"; 349 char id_at24[] = "6424"; 350 char id_at3d[] = "AT3D"; 351 char idstring[] = " "; 352 353 /* 354 * Must be an Alliance !!! 355 */ 356 for (i = 0; i < 4; i++) 357 idstring[i] = rdinx(0x3C4, 0x14 + i); 358 if (!memcmp(id_ap6420, idstring, 4) || 359 !memcmp(id_ap6422, idstring, 4)) 360 apmChip = AP6422; 361 else if (!memcmp(id_at24, idstring, 4)) 362 apmChip = AT24; 363 else if (!memcmp(id_at3d, idstring, 4)) 364 apmChip = AT3D; 365 if (apmChip >= 0) { 366 int apm_xbase; 367 368 apm_xbase = (rdinx(0x3C4, 0x1F) << 8) | rdinx(0x3C4, 0x1E); 369 370 if (!(wrinx(0x3C4, 0x1D, 0xCA >> 2), inb(apm_xbase + 2))) { 371 /* 372 * TODO Not PCI 373 */ 374 } 375 376 } 377 } 378 wrinx(0x3C4, 0x10, save); 379 380 return apmChip; 381} 382#endif 383 384static void 385ApmAssignFPtr(ScrnInfoPtr pScrn) 386{ 387 pScrn->driverVersion = APM_VERSION; 388 pScrn->driverName = APM_DRIVER_NAME; 389 pScrn->name = APM_NAME; 390 pScrn->Probe = ApmProbe; 391 pScrn->PreInit = ApmPreInit; 392 pScrn->ScreenInit = ApmScreenInit; 393 pScrn->SwitchMode = ApmSwitchMode; 394 pScrn->AdjustFrame = ApmAdjustFrame; 395 pScrn->EnterVT = ApmEnterVT; 396 pScrn->LeaveVT = ApmLeaveVT; 397 pScrn->FreeScreen = ApmFreeScreen; 398 pScrn->ValidMode = ApmValidMode; 399} 400 401static Bool 402ApmProbe(DriverPtr drv, int flags) 403{ 404 int numDevSections, numUsed, i; 405 GDevPtr *DevSections; 406 int *usedChips; 407 int foundScreen = FALSE; 408 409 /* 410 * Check if there is a chipset override in the config file 411 */ 412 if ((numDevSections = xf86MatchDevice(APM_DRIVER_NAME, 413 &DevSections)) <= 0) 414 return FALSE; 415 416 /* 417 * We need to probe the hardware first. We then need to see how this 418 * fits in with what is given in the config file, and allow the config 419 * file info to override any contradictions. 420 */ 421 422#ifndef XSERVER_LIBPCIACCESS 423 if (xf86GetPciVideoInfo() == NULL) { 424 return FALSE; 425 } 426#endif 427 numUsed = xf86MatchPciInstances(APM_NAME, PCI_VENDOR_ALLIANCE, 428 ApmChipsets, ApmPciChipsets, DevSections, numDevSections, 429 drv, &usedChips); 430 431 if (numUsed > 0) { 432 if (flags & PROBE_DETECT) 433 foundScreen = TRUE; 434 else for (i = 0; i < numUsed; i++) { 435 ScrnInfoPtr pScrn; 436 437 /* 438 * Allocate a ScrnInfoRec and claim the slot 439 */ 440 pScrn = NULL; 441 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 442 ApmPciChipsets, NULL, 443 NULL,NULL,NULL,NULL))){ 444 445 /* 446 * Fill in what we can of the ScrnInfoRec 447 */ 448 ApmAssignFPtr(pScrn); 449 foundScreen = TRUE; 450 } 451 } 452 } 453 454#ifdef HAVE_ISA 455 /* Check for non-PCI cards */ 456 numUsed = xf86MatchIsaInstances(APM_NAME, ApmChipsets, 457 ApmIsaChipsets, drv, ApmFindIsaDevice, DevSections, 458 numDevSections, &usedChips); 459 if (numUsed > 0) { 460 if (flags & PROBE_DETECT) 461 foundScreen = TRUE; 462 else for (i = 0; i < numUsed; i++) { 463 ScrnInfoPtr pScrn = NULL; 464 if ((pScrn = xf86ConfigIsaEntity(pScrn, 0, usedChips[i], 465 ApmIsaChipsets, NULL, NULL, NULL, 466 NULL, NULL))) { 467 /* 468 * Fill in what we can of the ScrnInfoRec 469 */ 470 ApmAssignFPtr(pScrn); 471 foundScreen = TRUE; 472 } 473 } 474 } 475#endif 476 477 xfree(DevSections); 478 return foundScreen; 479} 480 481/* 482 * GetAccelPitchValues - 483 * 484 * This function returns a list of display width (pitch) values that can 485 * be used in accelerated mode. 486 */ 487static int * 488GetAccelPitchValues(ScrnInfoPtr pScrn) 489{ 490 int *linePitches = NULL; 491 int linep[] = {640, 800, 1024, 1152, 1280, 0}; 492 493 if (sizeof linep > 0) { 494 linePitches = (int *)xnfalloc(sizeof linep); 495 memcpy(linePitches, linep, sizeof linep); 496 } 497 498 return linePitches; 499} 500 501static unsigned int 502ddc1Read(ScrnInfoPtr pScrn) 503{ 504 APMDECL(pScrn); 505 unsigned char tmp; 506 507 tmp = RDXB_IOP(0xD0); 508 WRXB_IOP(0xD0, tmp & 0x07); 509 while (STATUS_IOP() & 0x800); 510 while (!(STATUS_IOP() & 0x800)); 511 return (STATUS_IOP() & STATUS_SDA) != 0; 512} 513 514static void 515ApmProbeDDC(ScrnInfoPtr pScrn, int index) 516{ 517 vbeInfoPtr pVbe; 518 519 if (xf86LoadSubModule(pScrn, "vbe")) { 520 pVbe = VBEInit(NULL, index); 521 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 522 vbeFree(pVbe); 523 } 524} 525 526static Bool 527ApmPreInit(ScrnInfoPtr pScrn, int flags) 528{ 529 APMDECL(pScrn); 530 EntityInfoPtr pEnt; 531 vgaHWPtr hwp; 532 MessageType from; 533 char *mod = NULL, *req = NULL, *s; 534 ClockRangePtr clockRanges; 535 int i; 536 xf86MonPtr MonInfo = NULL; 537 double real; 538 539 /* 540 * Note: This function is only called once at server startup, and 541 * not at the start of each server generation. This means that 542 * only things that are persistent across server generations can 543 * be initialised here. xf86Screens[] is (pScrn is a pointer to one 544 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 545 * are too, and should be used for data that must persist across 546 * server generations. 547 * 548 * Per-generation data should be allocated with 549 * AllocateScreenPrivateIndex() from the ScreenInit() function. 550 */ 551 552 /* Check the number of entities, and fail if it isn't one. */ 553 if (pScrn->numEntities != 1) 554 return FALSE; 555 556 /* Allocate the ApmRec driverPrivate */ 557 if (!ApmGetRec(pScrn)) { 558 return FALSE; 559 } 560 pApm = APMPTR(pScrn); 561 562 /* Get the entity */ 563 pEnt = pApm->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 564 if (pEnt->location.type == BUS_PCI) { 565 pApm->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 566#ifndef XSERVER_LIBPCIACCESS 567 pApm->PciTag = pciTag(pApm->PciInfo->bus, pApm->PciInfo->device, 568 pApm->PciInfo->func); 569#endif 570 } 571 else { 572 pApm->PciInfo = NULL; 573#ifndef XSERVER_LIBPCIACCESS 574 pApm->PciTag = 0; 575#endif 576 } 577 578 if (flags & PROBE_DETECT) { 579 ApmProbeDDC(pScrn, pEnt->index); 580 return TRUE; 581 } 582 583 /* The vgahw module should be allocated here when needed */ 584 if (!xf86LoadSubModule(pScrn, "vgahw")) 585 return FALSE; 586 587 xf86LoaderReqSymLists(vgahwSymbols, NULL); 588 589 /* 590 * Allocate a vgaHWRec 591 */ 592 if (!vgaHWGetHWRec(pScrn)) 593 return FALSE; 594 595 hwp = VGAHWPTR(pScrn); 596 vgaHWGetIOBase(hwp); 597 pApm->iobase = hwp->PIOOffset; 598 pApm->xport = hwp->PIOOffset + 0x3C4; 599 600 /* Set pScrn->monitor */ 601 pScrn->monitor = pScrn->confScreen->monitor; 602 603 /* XXX: Access funcs */ 604 /* 605 * The first thing we should figure out is the depth, bpp, etc. 606 */ 607 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) { 608 return FALSE; 609 } else { 610 /* Check that the returned depth is one we support */ 611 switch (pScrn->depth) { 612 case 4: 613 case 8: 614 case 15: 615 case 16: 616 case 24: 617 /* OK */ 618 break; 619 default: 620 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 621 "Given depth (%d) is not supported by this driver\n", 622 pScrn->depth); 623 return FALSE; 624 } 625 } 626 xf86PrintDepthBpp(pScrn); 627 628 /* 629 * This must happen after pScrn->display has been set because 630 * xf86SetWeight references it. 631 */ 632 if (pScrn->depth > 8) { 633 /* The defaults are OK for us */ 634 rgb zeros = {0, 0, 0}; 635 636 if (!xf86SetWeight(pScrn, zeros, zeros)) { 637 return FALSE; 638 } else { 639 /* XXX check that weight returned is supported */ 640 ; 641 } 642 } 643 644 if (!xf86SetDefaultVisual(pScrn, -1)) { 645 return FALSE; 646 } else { 647 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 648 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 649 " (%s) is not supported at depth %d\n", 650 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 651 return FALSE; 652 } 653 } 654 655 /* We use a programmable clock */ 656 pScrn->progClock = TRUE; 657 658 /* Collect all of the relevant option flags (fill in pScrn->options) */ 659 xf86CollectOptions(pScrn, NULL); 660 661 /* Process the options */ 662 if (!(pApm->Options = xalloc(sizeof(ApmOptions)))) 663 return FALSE; 664 memcpy(pApm->Options, ApmOptions, sizeof(ApmOptions)); 665 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pApm->Options); 666 667 pApm->scrnIndex = pScrn->scrnIndex; 668 /* Set the bits per RGB for 8bpp mode */ 669 if (pScrn->depth > 1 && pScrn->depth <= 8) { 670 /* Default to 8 */ 671 pScrn->rgbBits = 8; 672 } 673#ifndef XSERVER_LIBPCIACCESS 674 /* you're getting a linear framebuffer with pciaccess */ 675 if (xf86ReturnOptValBool(pApm->Options, OPTION_NOLINEAR, FALSE)) { 676 pApm->noLinear = TRUE; 677 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "No linear framebuffer\n"); 678 } 679#else 680 pApm->noLinear = FALSE; 681#endif 682 from = X_DEFAULT; 683 pApm->hwCursor = FALSE; 684 if (xf86GetOptValBool(pApm->Options, OPTION_HW_CURSOR, &pApm->hwCursor)) 685 from = X_CONFIG; 686 if (pApm->noLinear || 687 xf86ReturnOptValBool(pApm->Options, OPTION_SW_CURSOR, FALSE)) { 688 from = X_CONFIG; 689 pApm->hwCursor = FALSE; 690 } 691 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 692 pApm->hwCursor ? "HW" : "SW"); 693 from = X_DEFAULT; 694 if (pScrn->bitsPerPixel < 8) 695 pApm->NoAccel = TRUE; 696 if (xf86ReturnOptValBool(pApm->Options, OPTION_NOACCEL, FALSE)) { 697 from = X_CONFIG; 698 pApm->NoAccel = TRUE; 699 } 700 if (pApm->NoAccel) 701 xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration disabled\n"); 702 if (xf86GetOptValFreq(pApm->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { 703 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MCLK used is %.1f MHz\n", real); 704 pApm->MemClk = (int)(real * 1000.0); 705 } 706 if (xf86ReturnOptValBool(pApm->Options, OPTION_SHADOW_FB, FALSE)) { 707 pApm->ShadowFB = TRUE; 708 pApm->NoAccel = TRUE; 709 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 710 "Using \"Shadow Framebuffer\" - acceleration disabled\n"); 711 } 712 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_RETRY, FALSE)) { 713 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_BURST, FALSE)) { 714 pApm->UsePCIRetry = TRUE; 715 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); 716 } 717 else 718 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires pci_burst \"on\".\n"); 719 } 720 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn; 721 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby; 722 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend; 723 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff; 724 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_ON))) { 725 if (!strcmp(s, "on")) 726 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn; 727 else if (!strcmp(s, "standby")) 728 pApm->DPMSMask[DPMSModeOn] = DPMSModeStandby; 729 else if (!strcmp(s, "suspend")) 730 pApm->DPMSMask[DPMSModeOn] = DPMSModeSuspend; 731 else if (!strcmp(s, "off")) 732 pApm->DPMSMask[DPMSModeOn] = DPMSModeOff; 733 else if (s[0] >= '0' && s[0] <= '9') { 734 pApm->DPMSMask[DPMSModeOn] = strtol(s, NULL, 0); 735 if (pApm->DPMSMask[DPMSModeOn] > (sizeof pApm->DPMSMask)-1) 736 pApm->DPMSMask[DPMSModeOn] = (sizeof pApm->DPMSMask) - 1; 737 } 738 } 739 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_STANDBY))) { 740 if (!strcmp(s, "on")) 741 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOn; 742 else if (!strcmp(s, "standby")) 743 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby; 744 else if (!strcmp(s, "suspend")) 745 pApm->DPMSMask[DPMSModeStandby] = DPMSModeSuspend; 746 else if (!strcmp(s, "off")) 747 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOff; 748 else if (s[0] >= '0' && s[0] <= '9') { 749 pApm->DPMSMask[DPMSModeStandby] = strtol(s, NULL, 0); 750 if (pApm->DPMSMask[DPMSModeStandby] > (sizeof pApm->DPMSMask)-1) 751 pApm->DPMSMask[DPMSModeStandby] = (sizeof pApm->DPMSMask) - 1; 752 } 753 } 754 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_SUSPEND))) { 755 if (!strcmp(s, "on")) 756 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOn; 757 else if (!strcmp(s, "standby")) 758 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeStandby; 759 else if (!strcmp(s, "suspend")) 760 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend; 761 else if (!strcmp(s, "off")) 762 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOff; 763 else if (s[0] >= '0' && s[0] <= '9') { 764 pApm->DPMSMask[DPMSModeSuspend] = strtol(s, NULL, 0); 765 if (pApm->DPMSMask[DPMSModeSuspend] > (sizeof pApm->DPMSMask)-1) 766 pApm->DPMSMask[DPMSModeSuspend] = (sizeof pApm->DPMSMask) - 1; 767 } 768 } 769 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_OFF))) { 770 if (!strcmp(s, "on")) 771 pApm->DPMSMask[DPMSModeOff] = DPMSModeOn; 772 else if (!strcmp(s, "standby")) 773 pApm->DPMSMask[DPMSModeOff] = DPMSModeStandby; 774 else if (!strcmp(s, "suspend")) 775 pApm->DPMSMask[DPMSModeOff] = DPMSModeSuspend; 776 else if (!strcmp(s, "off")) 777 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff; 778 else if (s[0] >= '0' && s[0] <= '9') { 779 pApm->DPMSMask[DPMSModeOff] = strtol(s, NULL, 0); 780 if (pApm->DPMSMask[DPMSModeOff] > (sizeof pApm->DPMSMask)-1) 781 pApm->DPMSMask[DPMSModeOff] = (sizeof pApm->DPMSMask) - 1; 782 } 783 } 784 785 /* 786 * Set the Chipset and ChipRev, allowing config file entries to 787 * override. 788 */ 789 if (pEnt->device->chipset && *pEnt->device->chipset) { 790 pScrn->chipset = pEnt->device->chipset; 791 pApm->Chipset = xf86StringToToken(ApmChipsets, pScrn->chipset); 792 from = X_CONFIG; 793 } else if (pEnt->device->chipID >= 0) { 794 pApm->Chipset = pEnt->device->chipID; 795 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset); 796 797 from = X_CONFIG; 798 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 799 pApm->Chipset); 800 } else { 801 from = X_PROBED; 802 if (pApm->PciInfo) 803 pApm->Chipset = PCI_DEV_DEVICE_ID(pApm->PciInfo); 804 else 805 pApm->Chipset = pEnt->chipset; 806 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset); 807 } 808 if (pScrn->bitsPerPixel == 24 && pApm->Chipset < AT24) { 809 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 810 "Given depth (%d) is not supported by this driver\n", 811 pScrn->depth); 812 return FALSE; 813 } 814 if (pEnt->device->chipRev >= 0) { 815 pApm->ChipRev = pEnt->device->chipRev; 816 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 817 pApm->ChipRev); 818 } else if (pApm->PciInfo) { 819 pApm->ChipRev = PCI_DEV_REVISION(pApm->PciInfo); 820 } 821 822 /* 823 * This shouldn't happen because such problems should be caught in 824 * ApmProbe(), but check it just in case. 825 */ 826 if (pScrn->chipset == NULL) { 827 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 828 "ChipID 0x%04X is not recognised\n", pApm->Chipset); 829 return FALSE; 830 } 831 if (pApm->Chipset < 0) { 832 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 833 "Chipset \"%s\" is not recognised\n", pScrn->chipset); 834 return FALSE; 835 } 836 837 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 838 839 if (pEnt->device->MemBase != 0) { 840 pApm->LinAddress = pEnt->device->MemBase; 841 from = X_CONFIG; 842 } else if (pApm->PciInfo) { 843 pApm->LinAddress = PCI_REGION_BASE(pApm->PciInfo, 0, REGION_MEM) & 0xFF800000; 844 from = X_PROBED; 845 } else { 846 /* 847 * VESA local bus. 848 * Pray that 2048MB works. 849 */ 850 pApm->LinAddress = 0x80000000; 851 } 852 853 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 854 (unsigned long)pApm->LinAddress); 855 856 if (xf86LoadSubModule(pScrn, "ddc")) { 857 xf86LoaderReqSymLists(ddcSymbols, NULL); 858 if (xf86LoadSubModule(pScrn, "i2c")) { 859 xf86LoaderReqSymLists(i2cSymbols, NULL); 860 pApm->I2C = TRUE; 861 } 862 } 863 864 if (pApm->noLinear) { 865 /* 866 * TODO not AT3D. 867 * XXX ICI XXX 868 */ 869 pApm->LinMapSize = 4 * 1024 * 1024 /* 0x10000 */; 870 pApm->FbMapSize = 4 * 1024 * 1024 /* 0x10000 */; 871 if (pApm->Chipset >= AT3D) 872 pApm->LinAddress += 8 * 1024 * 1024 /* 0xA0000 */; 873 } 874 else { 875 if (pApm->Chipset >= AT3D) 876 pApm->LinMapSize = 16 * 1024 * 1024; 877 else 878 pApm->LinMapSize = 6 * 1024 * 1024; 879 pApm->FbMapSize = 4 * 1024 * 1024; 880 } 881 882 if (xf86LoadSubModule(pScrn, "int10")) { 883 void *ptr; 884 885 xf86LoaderReqSymLists(int10Symbols, NULL); 886 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 887 ptr = xf86InitInt10(pEnt->index); 888 if (ptr) 889 xf86FreeInt10(ptr); 890 } 891 892 xf86RegisterResources(pEnt->index, NULL, ResNone); 893 xf86SetOperatingState(resVga, pEnt->index, ResDisableOpr); 894 pScrn->racMemFlags = 0; /* For noLinear, access to 0xA0000 */ 895 if (pApm->VGAMap) 896 pScrn->racIoFlags = 0; 897 else 898 pScrn->racIoFlags = RAC_COLORMAP | RAC_VIEWPORT; 899 900 if (pEnt->device->videoRam != 0) { 901 pScrn->videoRam = pEnt->device->videoRam; 902 from = X_CONFIG; 903 } else if (!pApm->noLinear && pApm->Chipset >= AT3D) { 904 unsigned char d9, db, uc; 905 /*unsigned long save;*/ 906 volatile unsigned char *LinMap; 907 908#ifndef XSERVER_LIBPCIACCESS 909 LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 910 pApm->PciTag, pApm->LinAddress, 911 pApm->LinMapSize); 912#else 913 { 914 void** result = (void**)&LinMap; 915 int err = pci_device_map_range(pApm->PciInfo, 916 pApm->LinAddress, 917 pApm->LinMapSize, 918 PCI_DEV_MAP_FLAG_WRITABLE, 919 result); 920 921 if (err) 922 return FALSE; 923 } 924#endif 925 926 /*save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG); 927 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_MEM_ENABLE);*/ 928 d9 = LinMap[0xFFECD9]; 929 db = LinMap[0xFFECDB]; 930 LinMap[0xFFECDB] = (db & 0xF4) | 0x0A; 931 LinMap[0xFFECD9] = (d9 & 0xCF) | 0x20; 932 LinMap[0xFFF3C4] = 0x1C; 933 uc = LinMap[0xFFF3C5]; 934 LinMap[0xFFF3C5] = 0x3F; 935 LinMap[0xFFF3C4] = 0x20; 936 pScrn->videoRam = LinMap[0xFFF3C5] * 64; 937 LinMap[0xFFF3C4] = 0x10; 938 pApm->savedSR10 = LinMap[0xFFF3C5]; 939 LinMap[0xFFF3C4] = 0x1E; 940 pApm->xbase = LinMap[0xFFF3C5]; 941 LinMap[0xFFF3C4] = 0x1F; 942 pApm->xbase |= LinMap[0xFFF3C5] << 8; 943 LinMap[0xFFF3C4] = 0x1C; 944 LinMap[0xFFF3C5] = uc; 945 LinMap[0xFFECDB] = db; 946 LinMap[0xFFECD9] = d9; 947 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/ 948 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)LinMap, pApm->LinMapSize); 949 from = X_PROBED; 950 } 951 else { 952 /*unsigned long save; 953 954 save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG); 955 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_IO_ENABLE);*/ 956 pApm->savedSR10 = rdinx(pApm->xport, 0x10); 957 wrinx(pApm->xport, 0x10, 0x12); 958 pScrn->videoRam = rdinx(pApm->xport, 0x20) * 64; 959 pApm->xbase = rdinx(pApm->xport, 0x1F) << 8; 960 pApm->xbase |= rdinx(pApm->xport, 0x1E); 961 pApm->xbase += pApm->iobase; 962 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12); 963 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/ 964 from = X_PROBED; 965 } 966 if (pApm->Chipset < AT3D && pScrn->videoRam >= 4096) 967 pScrn->videoRam -= 32; 968 969 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", 970 pScrn->videoRam); 971 972 if (!xf86IsPc98()) { 973 hwp->MapSize = 0x10000; 974 vgaHWMapMem(pScrn); 975 if (pApm->I2C) { 976 if (!ApmI2CInit(pScrn)) { 977 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n"); 978 } 979 else { 980 MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pApm->I2CPtr); 981 } 982 } 983 if (0 && !MonInfo) 984 MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex,vgaHWddc1SetSpeed,ddc1Read); 985 if (MonInfo) { 986 xf86PrintEDID(MonInfo); 987 xf86SetDDCproperties(pScrn, MonInfo); 988 } 989 pScrn->monitor->DDC = MonInfo; 990 } 991 992 /* The gamma fields must be initialised when using the new cmap code */ 993 if (pScrn->depth > 1) { 994 Gamma zeros = {0.0, 0.0, 0.0}; 995 996 if (!xf86SetGamma(pScrn, zeros)) { 997 return FALSE; 998 } 999 } 1000 1001 pApm->MinClock = 23125; 1002 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock set to %d MHz\n", 1003 pApm->MinClock / 1000); 1004 1005 /* 1006 * If the user has specified ramdac speed in the XF86Config 1007 * file, we respect that setting. 1008 */ 1009 from = X_DEFAULT; 1010 if (pEnt->device->dacSpeeds[0]) { 1011 int speed = 0; 1012 1013 switch (pScrn->bitsPerPixel) { 1014 case 4: 1015 case 8: 1016 speed = pEnt->device->dacSpeeds[DAC_BPP8]; 1017 break; 1018 case 16: 1019 speed = pEnt->device->dacSpeeds[DAC_BPP16]; 1020 break; 1021 case 24: 1022 speed = pEnt->device->dacSpeeds[DAC_BPP24]; 1023 break; 1024 case 32: 1025 speed = pEnt->device->dacSpeeds[DAC_BPP32]; 1026 break; 1027 } 1028 if (speed == 0) 1029 pApm->MaxClock = pEnt->device->dacSpeeds[0]; 1030 else 1031 pApm->MaxClock = speed; 1032 from = X_CONFIG; 1033 } else { 1034 switch(pApm->Chipset) 1035 { 1036 /* These values come from the Manual for AT24 and AT3D 1037 in the overview of various modes. I've taken the largest 1038 number for the different modes. Alliance wouldn't 1039 tell me what the maximum frequency was, so... 1040 */ 1041 case AT24: 1042 switch(pScrn->bitsPerPixel) 1043 { 1044 case 4: 1045 case 8: 1046 pApm->MaxClock = 160000; 1047 break; 1048 case 16: 1049 pApm->MaxClock = 144000; 1050 break; 1051 case 24: 1052 pApm->MaxClock = 75000; /* Hmm. */ 1053 break; 1054 case 32: 1055 pApm->MaxClock = 94500; 1056 break; 1057 default: 1058 return FALSE; 1059 } 1060 break; 1061 case AT3D: 1062 switch(pScrn->bitsPerPixel) 1063 { 1064 case 4: 1065 case 8: 1066 pApm->MaxClock = 175500; 1067 break; 1068 case 16: 1069 pApm->MaxClock = 144000; 1070 break; 1071 case 24: 1072 pApm->MaxClock = 94000; /* Changed from 75000 by Grenié */ 1073 break; 1074 case 32: 1075 pApm->MaxClock = 94500; 1076 break; 1077 default: 1078 return FALSE; 1079 } 1080 break; 1081 case AP6422: 1082 switch(pScrn->bitsPerPixel) 1083 { 1084 case 4: 1085 case 8: 1086 pApm->MaxClock = 135000; 1087 break; 1088 case 16: 1089 pApm->MaxClock = 75000; 1090 break; 1091 case 32: 1092 pApm->MaxClock = 60000; 1093 break; 1094 default: 1095 return FALSE; 1096 } 1097 break; 1098 default: 1099 pApm->MaxClock = 135000; 1100 break; 1101 } 1102 } 1103 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 1104 pApm->MaxClock / 1000); 1105 1106 /* 1107 * Setup the ClockRanges, which describe what clock ranges are available, 1108 * and what sort of modes they can be used for. 1109 */ 1110 clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1); 1111 clockRanges->next = NULL; 1112 clockRanges->minClock = pApm->MinClock; 1113 clockRanges->maxClock = pApm->MaxClock; 1114 clockRanges->clockIndex = -1; /* programmable */ 1115 clockRanges->interlaceAllowed = FALSE; /* XXX change this */ 1116 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 1117 1118 /* Select valid modes from those available */ 1119 if (pApm->NoAccel) { 1120 /* 1121 * XXX Assuming min pitch 256, max 2048 1122 * XXX Assuming min height 128, max 1024 (changed EE) 1123 */ 1124 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1125 pScrn->display->modes, clockRanges, 1126 NULL, 256, 2048, 1127 pScrn->bitsPerPixel, 128, 1024, 1128 pScrn->display->virtualX, 1129 pScrn->display->virtualY, 1130 pApm->FbMapSize, 1131 LOOKUP_BEST_REFRESH); 1132 } else { 1133 /* 1134 * XXX Assuming min height 128, max 2048 1135 */ 1136 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1137 pScrn->display->modes, clockRanges, 1138 GetAccelPitchValues(pScrn), 0, 0, 1139 pScrn->bitsPerPixel, 128, 1024, 1140 pScrn->display->virtualX, 1141 pScrn->display->virtualY, 1142 pApm->FbMapSize, 1143 LOOKUP_BEST_REFRESH); 1144 } 1145 1146 if (i == -1) { 1147 ApmFreeRec(pScrn); 1148 return FALSE; 1149 } 1150 1151 /* Prune the modes marked as invalid */ 1152 xf86PruneDriverModes(pScrn); 1153 1154 if (i == 0 || pScrn->modes == NULL) { 1155 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1156 ApmFreeRec(pScrn); 1157 return FALSE; 1158 } 1159 1160 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 1161 1162 /* Set the current mode to the first in the list */ 1163 pScrn->currentMode = pScrn->modes; 1164 1165 /* Print the list of modes being used */ 1166 xf86PrintModes(pScrn); 1167 1168 /* Set display resolution */ 1169 xf86SetDpi(pScrn, 0, 0); 1170 1171 /* Load bpp-specific modules */ 1172 switch (pScrn->bitsPerPixel) { 1173#ifdef HAVE_XF1BPP 1174 case 1: 1175 mod = "xf1bpp"; 1176 req = "xf1bppScreenInit"; 1177 break; 1178#endif 1179#ifndef HAVE_XF4BPP 1180 case 4: 1181 mod = "xf4bpp"; 1182 req = "xf4bppScreenInit"; 1183 break; 1184#endif 1185 case 8: 1186 case 16: 1187 case 24: 1188 case 32: 1189 mod = "fb"; 1190 break; 1191 } 1192 1193 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) { 1194 ApmFreeRec(pScrn); 1195 return FALSE; 1196 } 1197 1198 if (mod) { 1199 if (req) { 1200 xf86LoaderReqSymbols(req, NULL); 1201 } else { 1202 xf86LoaderReqSymLists(fbSymbols, NULL); 1203 } 1204 } 1205 1206 /* Load XAA if needed */ 1207 if (!pApm->NoAccel) { 1208 if (!xf86LoadSubModule(pScrn, "xaa")) { 1209 ApmFreeRec(pScrn); 1210 return FALSE; 1211 } 1212 xf86LoaderReqSymLists(xaaSymbols, NULL); 1213 } 1214 1215 /* Load ramdac if needed */ 1216 if (pApm->hwCursor) { 1217 if (!xf86LoadSubModule(pScrn, "ramdac")) { 1218 ApmFreeRec(pScrn); 1219 return FALSE; 1220 } 1221 xf86LoaderReqSymLists(ramdacSymbols, NULL); 1222 } 1223 1224 /* Load shadowfb if needed */ 1225 if (pApm->ShadowFB) { 1226 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1227 ApmFreeRec(pScrn); 1228 return FALSE; 1229 } 1230 xf86LoaderReqSymLists(shadowSymbols, NULL); 1231 } 1232 1233 pApm->CurrentLayout.displayWidth = pScrn->virtualX; 1234 pApm->CurrentLayout.displayHeight = pScrn->virtualY; 1235 pApm->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 1236 pApm->CurrentLayout.bytesPerScanline= (pApm->CurrentLayout.displayWidth * pApm->CurrentLayout.bitsPerPixel) >> 3; 1237 pApm->CurrentLayout.depth = pScrn->depth; 1238 pApm->CurrentLayout.Scanlines = 2 * (pScrn->videoRam << 10) / pApm->CurrentLayout.bytesPerScanline; 1239 if (pScrn->bitsPerPixel == 24) 1240 pApm->CurrentLayout.mask32 = 3; 1241 else 1242 pApm->CurrentLayout.mask32 = 32 / pScrn->bitsPerPixel - 1; 1243 1244 return TRUE; 1245} 1246 1247/* 1248 * Map the framebuffer and MMIO memory. 1249 */ 1250 1251static Bool 1252ApmMapMem(ScrnInfoPtr pScrn) 1253{ 1254 APMDECL(pScrn); 1255 vgaHWPtr hwp = VGAHWPTR(pScrn); 1256 1257#ifndef XSERVER_LIBPCIACCESS 1258 pApm->LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1259 pApm->PciTag, 1260 (unsigned long)pApm->LinAddress, 1261 pApm->LinMapSize); 1262#else 1263 { 1264 void** result = (void**)&pApm->LinMap; 1265 int err = pci_device_map_range(pApm->PciInfo, 1266 pApm->LinAddress, 1267 pApm->LinMapSize, 1268 PCI_DEV_MAP_FLAG_WRITABLE | 1269 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1270 result); 1271 1272 if (err) 1273 return FALSE; 1274 } 1275#endif 1276 1277 1278 if (pApm->LinMap == NULL) 1279 return FALSE; 1280 1281 if (!pApm->noLinear) { 1282 if (pApm->Chipset >= AT3D) { 1283 pApm->FbBase = (void *)(((char *)pApm->LinMap) + 0x800000); 1284 pApm->VGAMap = ((char *)pApm->LinMap) + 0xFFF000; 1285 pApm->MemMap = ((char *)pApm->LinMap) + 0xFFEC00; 1286 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000); 1287 } 1288 else { 1289 pApm->FbBase = (void *)pApm->LinMap; 1290 pApm->VGAMap = NULL; 1291 if (pScrn->videoRam == 6 * 1024 - 32) { 1292 pApm->MemMap = ((char *)pApm->LinMap) + 0x5FF800; 1293 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x5F8000); 1294 } 1295 else { 1296 pApm->MemMap = ((char *)pApm->LinMap) + 0x3FF800; 1297 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000); 1298 } 1299 } 1300 1301 /* 1302 * Initialize chipset 1303 */ 1304 pApm->c9 = RDXB(0xC9); 1305 if (pApm->Chipset >= AT3D) { 1306 pApm->d9 = RDXB(0xD9); 1307 pApm->db = RDXB(0xDB); 1308 1309 /* If you change these two, change them also in apm_funcs.c */ 1310 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A); 1311 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20); 1312 1313 vgaHWSetMmioFuncs(hwp, (CARD8 *)pApm->LinMap, 0xFFF000); 1314 } 1315 if (pApm->Chipset >= AP6422) 1316 WRXB(0xC9, pApm->c9 | 0x10); 1317 } 1318 else { 1319 pApm->FbBase = pApm->LinMap; 1320 1321 /* 1322 * Initialize chipset 1323 */ 1324 if (pApm->Chipset >= AT3D) { 1325 pApm->d9 = RDXB_IOP(0xD9); 1326 pApm->db = RDXB_IOP(0xDB); 1327 WRXB_IOP(0xDB, pApm->db & 0xF4); 1328 } 1329 } 1330 /* 1331 * Save color mode 1332 */ 1333 pApm->MiscOut = hwp->readMiscOut(hwp); 1334 1335 return TRUE; 1336} 1337 1338/* 1339 * Unmap the framebuffer and MMIO memory 1340 */ 1341 1342static Bool 1343ApmUnmapMem(ScrnInfoPtr pScrn) 1344{ 1345 APMDECL(pScrn); 1346 vgaHWPtr hwp = VGAHWPTR(pScrn); 1347 1348 /* 1349 * Reset color mode 1350 */ 1351 hwp->writeMiscOut(hwp, pApm->MiscOut); 1352 if (pApm->LinMap) { 1353 if (pApm->Chipset >= AT3D) { 1354 if (!pApm->noLinear) { 1355 WRXB(0xD9, pApm->d9); 1356 WRXB(0xDB, pApm->db); 1357 } 1358 else { 1359 WRXB_IOP(0xD9, pApm->d9); 1360 WRXB_IOP(0xDB, pApm->db); 1361 } 1362 } 1363 WRXB(0xC9, pApm->c9); 1364 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, pApm->LinMapSize); 1365 pApm->LinMap = NULL; 1366 } 1367 else if (pApm->FbBase) 1368 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, 0x10000); 1369 1370 return TRUE; 1371} 1372 1373/* 1374 * This function saves the video state. 1375 */ 1376static void 1377ApmSave(ScrnInfoPtr pScrn) 1378{ 1379 APMDECL(pScrn); 1380 ApmRegPtr ApmReg = &pApm->SavedReg; 1381 vgaHWPtr hwp = VGAHWPTR(pScrn); 1382 1383 if (pApm->VGAMap) { 1384 ApmReg->SEQ[0x1B] = ApmReadSeq(0x1B); 1385 ApmReg->SEQ[0x1C] = ApmReadSeq(0x1C); 1386 1387 /* 1388 * Save fonts 1389 */ 1390 if (!(hwp->SavedReg.Attribute[0x10] & 1)) { 1391 if (pApm->FontInfo || (pApm->FontInfo = (pointer)xalloc(TEXT_AMOUNT))) { 1392 int locked; 1393 1394 locked = ApmReadSeq(0x10); 1395 if (locked) 1396 ApmWriteSeq(0x10, 0x12); 1397 ApmWriteSeq(0x1C, 0x3F); 1398 memcpy(pApm->FontInfo, pApm->FbBase, TEXT_AMOUNT); 1399 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]); 1400 if (locked) 1401 ApmWriteSeq(0x10, 0); 1402 } 1403 } 1404 /* 1405 * This function will handle creating the data structure and filling 1406 * in the generic VGA portion. 1407 */ 1408 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_CMAP); 1409 1410 /* Hardware cursor registers. */ 1411 ApmReg->EX[XR140] = RDXL(0x140); 1412 ApmReg->EX[XR144] = RDXW(0x144); 1413 ApmReg->EX[XR148] = RDXL(0x148); 1414 ApmReg->EX[XR14C] = RDXW(0x14C); 1415 1416 ApmReg->CRT[0x19] = ApmReadCrtc(0x19); 1417 ApmReg->CRT[0x1A] = ApmReadCrtc(0x1A); 1418 ApmReg->CRT[0x1B] = ApmReadCrtc(0x1B); 1419 ApmReg->CRT[0x1C] = ApmReadCrtc(0x1C); 1420 ApmReg->CRT[0x1D] = ApmReadCrtc(0x1D); 1421 ApmReg->CRT[0x1E] = ApmReadCrtc(0x1E); 1422 1423 /* RAMDAC registers. */ 1424 ApmReg->EX[XRE8] = RDXL(0xE8); 1425 ApmReg->EX[XREC] = RDXL(0xEC); 1426 1427 /* Color correction */ 1428 ApmReg->EX[XRE0] = RDXL(0xE0); 1429 1430 ApmReg->EX[XR80] = RDXB(0x80); 1431 } 1432 else { 1433 /* 1434 * This function will handle creating the data structure and filling 1435 * in the generic VGA portion. 1436 */ 1437 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); 1438 1439 ApmReg->SEQ[0x1B] = rdinx(pApm->xport, 0x1B); 1440 ApmReg->SEQ[0x1C] = rdinx(pApm->xport, 0x1C); 1441 1442 /* Hardware cursor registers. */ 1443 if (pApm->noLinear) { 1444 ApmReg->EX[XR140] = RDXL_IOP(0x140); 1445 ApmReg->EX[XR144] = RDXW_IOP(0x144); 1446 ApmReg->EX[XR148] = RDXL_IOP(0x148); 1447 ApmReg->EX[XR14C] = RDXW_IOP(0x14C); 1448 } 1449 else { 1450 ApmReg->EX[XR140] = RDXL(0x140); 1451 ApmReg->EX[XR144] = RDXW(0x144); 1452 ApmReg->EX[XR148] = RDXL(0x148); 1453 ApmReg->EX[XR14C] = RDXW(0x14C); 1454 } 1455 1456 ApmReg->CRT[0x19] = rdinx(pApm->iobase + 0x3D4, 0x19); 1457 ApmReg->CRT[0x1A] = rdinx(pApm->iobase + 0x3D4, 0x1A); 1458 ApmReg->CRT[0x1B] = rdinx(pApm->iobase + 0x3D4, 0x1B); 1459 ApmReg->CRT[0x1C] = rdinx(pApm->iobase + 0x3D4, 0x1C); 1460 ApmReg->CRT[0x1D] = rdinx(pApm->iobase + 0x3D4, 0x1D); 1461 ApmReg->CRT[0x1E] = rdinx(pApm->iobase + 0x3D4, 0x1E); 1462 1463 if (pApm->noLinear) { 1464 /* RAMDAC registers. */ 1465 ApmReg->EX[XRE8] = RDXL_IOP(0xE8); 1466 ApmReg->EX[XREC] = RDXL_IOP(0xEC); 1467 1468 /* Color correction */ 1469 ApmReg->EX[XRE0] = RDXL_IOP(0xE0); 1470 1471 ApmReg->EX[XR80] = RDXB_IOP(0x80); 1472 } 1473 else { 1474 /* RAMDAC registers. */ 1475 ApmReg->EX[XRE8] = RDXL(0xE8); 1476 ApmReg->EX[XREC] = RDXL(0xEC); 1477 1478 /* Color correction */ 1479 ApmReg->EX[XRE0] = RDXL(0xE0); 1480 1481 ApmReg->EX[XR80] = RDXB(0x80); 1482 } 1483 } 1484} 1485 1486#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2))) 1487 1488static unsigned 1489comp_lmn(ApmPtr pApm, long clock) 1490{ 1491 int n, m, l, f; 1492 double fvco; 1493 double fout; 1494 double fmax, fmin; 1495 double fref; 1496 double fvco_goal; 1497 double k, c; 1498 double fout_best = 0; 1499 unsigned int best = 0; 1500 1501 if (pApm->Chipset >= AT3D) 1502 fmax = 370000.0; 1503 else 1504 fmax = 250000.0; 1505 1506 fref = 14318.0; 1507 fmin = fmax / 2.0; 1508 1509 for (m = 1; m <= 5; m++) 1510 { 1511 for (l = 3; l >= 0; l--) 1512 { 1513 for (n = 8; n <= 127; n++) 1514 { 1515 fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l)); 1516 fvco_goal = (double)clock * (double)(1 << l); 1517 fvco = fout * (double)(1 << l); 1518 if (!WITHIN(fvco, 0.99*fvco_goal, 1.01*fvco_goal)) 1519 continue; 1520 if (!WITHIN(fvco, fmin, fmax)) 1521 continue; 1522 if (!WITHIN(fvco / (double)(n+1), 300.0, 300000.0)) 1523 continue; 1524 if (!WITHIN(fref / (double)(m+1), 300.0, 300000.0)) 1525 continue; 1526 1527 if (fout_best != 0) { 1528 double diff_new = clock - fout; 1529 double diff_old = clock - best; 1530 diff_new = diff_new < 0 ? -diff_new : diff_new; 1531 diff_old = diff_old < 0 ? -diff_old : diff_old; 1532 if (diff_new > diff_old) 1533 continue; 1534 } 1535 fout_best = fout; 1536 1537 /* The following formula was empirically derived by 1538 matching a number of fvco values with acceptable 1539 values of f. 1540 1541 (fvco can be 185MHz - 370MHz on AT3D) 1542 (fvco can be 125MHz - 250MHz on AT24/AP6422) 1543 1544 The table that was measured up follows: 1545 1546 AT3D 1547 1548 fvco f 1549 (125) (x-7) guess 1550 200 5-7 1551 219 4-7 1552 253 3-6 1553 289 2-5 1554 320 0-4 1555 (400) (0-x) guess 1556 1557 AT24 1558 1559 fvco f 1560 126 7 1561 200 5-7 1562 211 4-7 1563 1564 AP6422 1565 1566 fvco f 1567 126 7 1568 169 5-7 1569 200 4-5 1570 211 4-5 1571 1572 From this, a function "f = k * fvco + c" was derived. 1573 1574 For AT3D, this table was measured with MCLK == 50MHz. 1575 The driver has since been set to use MCLK == 57.3MHz for, 1576 but I don't think that makes a difference here. 1577 */ 1578 1579 if (pApm->Chipset >= AT24) 1580 { 1581 k = 7.0 / (175.0 - 380.0); 1582 c = -k * 380.0; 1583 f = (int)(k * fvco/1000.0 + c + 0.5); 1584 if (f > 7) f = 7; 1585 if (f < 0) f = 0; 1586 } else { /* i.e AP6422 */ 1587 c = (211.0*6.0-169.0*4.5)/(211.0-169.0); 1588 k = (4.5-c)/211.0; 1589 f = (int)(k * fvco/1000.0 + c + 0.5); 1590 if (f > 7) f = 7; 1591 if (f < 0) f = 0; 1592 } 1593 1594 best = (n << 16) | (m << 8) | (l << 2) | (f << 4); 1595 } 1596 } 1597 } 1598 1599 if (fout_best != 0) 1600 return best; 1601 1602 xf86DrvMsg(pApm->scrnIndex, X_PROBED, 1603 "Cannot find register values for clock %6.2f MHz. " 1604 "Please use a (slightly) different clock.\n", 1605 (double)clock / 1000.0); 1606 return 0; 1607} 1608 1609/* 1610 * Initialise a new mode. This is currently still using the old 1611 * "initialise struct, restore/write struct to HW" model. That could 1612 * be changed. 1613 */ 1614 1615static Bool 1616ApmModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 1617{ 1618 APMDECL(pScrn); 1619 ApmRegPtr ApmReg = &pApm->ModeReg; 1620 vgaHWPtr hwp; 1621 1622 1623 /* set clockIndex to "2" for programmable clocks */ 1624 if (pScrn->progClock) 1625 mode->ClockIndex = 2; 1626 1627 /* prepare standard VGA register contents */ 1628 if (!vgaHWInit(pScrn, mode)) 1629 return FALSE; 1630 pScrn->vtSema = TRUE; 1631 hwp = VGAHWPTR(pScrn); 1632 1633 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F); 1634 1635 if (xf86IsPc98()) 1636 outb(0xFAC, 0xFF); 1637 1638 memcpy(ApmReg, &pApm->SavedReg, sizeof pApm->SavedReg); 1639 1640 /* 1641 * The APM chips have a scale factor of 8 for the 1642 * scanline offset. There are four extended bit in addition 1643 * to the 8 VGA bits. 1644 */ 1645 { 1646 int offset; 1647 1648 offset = (pApm->CurrentLayout.displayWidth * 1649 pApm->CurrentLayout.bitsPerPixel / 8) >> 3; 1650 hwp->ModeReg.CRTC[0x13] = offset; 1651 /* Bit 8 resides at CR1C bits 7:4. */ 1652 ApmReg->CRT[0x1C] = (offset & 0xF00) >> 4; 1653 } 1654 1655 /* Set pixel depth. */ 1656 switch(pApm->CurrentLayout.bitsPerPixel) 1657 { 1658 case 4: 1659 ApmReg->EX[XR80] = 0x01; 1660 break; 1661 case 8: 1662 ApmReg->EX[XR80] = 0x02; 1663 break; 1664 case 16: 1665 if (pApm->CurrentLayout.depth == 15) 1666 ApmReg->EX[XR80] = 0x0C; 1667 else 1668 ApmReg->EX[XR80] = 0x0D; 1669 break; 1670 case 24: 1671 ApmReg->EX[XR80] = 0x0E; 1672 break; 1673 case 32: 1674 ApmReg->EX[XR80] = 0x0F; 1675 break; 1676 default: 1677 FatalError("Unsupported bit depth %d\n", pApm->CurrentLayout.depth); 1678 break; 1679 } 1680 1681 /* Set banking register to zero. */ 1682 ApmReg->EX[XRC0] = 0; 1683 1684 /* Handle the CRTC overflow bits. */ 1685 { 1686 unsigned char val; 1687 /* Vertical Overflow. */ 1688 val = 0; 1689 if ((mode->CrtcVTotal - 2) & 0x400) 1690 val |= 0x01; 1691 if ((mode->CrtcVDisplay - 1) & 0x400) 1692 val |= 0x02; 1693 /* VBlankStart is equal to VSyncStart + 1. */ 1694 if (mode->CrtcVSyncStart & 0x400) 1695 val |= 0x04; 1696 /* VRetraceStart is equal to VSyncStart + 1. */ 1697 if (mode->CrtcVSyncStart & 0x400) 1698 val |= 0x08; 1699 ApmReg->CRT[0x1A] = val; 1700 1701 /* Horizontal Overflow. */ 1702 val = 0; 1703 if ((mode->CrtcHTotal / 8 - 5) & 0x100) 1704 val |= 1; 1705 if ((mode->CrtcHDisplay / 8 - 1) & 0x100) 1706 val |= 2; 1707 /* HBlankStart is equal to HSyncStart - 1. */ 1708 if ((mode->CrtcHSyncStart / 8 - 1) & 0x100) 1709 val |= 4; 1710 /* HRetraceStart is equal to HSyncStart. */ 1711 if ((mode->CrtcHSyncStart / 8) & 0x100) 1712 val |= 8; 1713 ApmReg->CRT[0x1B] = val; 1714 1715 /* Assume the CRTC is not KGA (see vgaHWInit) */ 1716 hwp->ModeReg.CRTC[3] = (hwp->ModeReg.CRTC[3] & 0xE0) | 1717 (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); 1718 hwp->ModeReg.CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 1719 | (hwp->ModeReg.CRTC[5] & 0x7F); 1720 hwp->ModeReg.CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1721 } 1722 ApmReg->CRT[0x1E] = 1; /* disable autoreset feature */ 1723 1724 /* Program clock select. */ 1725 ApmReg->EX[XREC] = comp_lmn(pApm, mode->Clock); 1726 if (!ApmReg->EX[XREC]) 1727 return FALSE; 1728 hwp->ModeReg.MiscOutReg |= 0x0C; 1729 1730 /* Set up the RAMDAC registers. */ 1731 1732 if (pApm->CurrentLayout.bitsPerPixel > 8) 1733 /* Get rid of white border. */ 1734 hwp->ModeReg.Attribute[0x11] = 0x00; 1735 else 1736 hwp->ModeReg.Attribute[0x11] = 0xFF; 1737 if (pApm->MemClk) 1738 ApmReg->EX[XRE8] = comp_lmn(pApm, pApm->MemClk); 1739 else if (pApm->Chipset >= AT3D) 1740 ApmReg->EX[XRE8] = 0x071F01E8; /* Enable 58MHz MCLK (actually 57.3 MHz) 1741 This is what is used in the Windows 1742 drivers. The BIOS sets it to 50MHz. */ 1743 else if (!pApm->noLinear) 1744 ApmReg->EX[XRE8] = RDXL(0xE8); /* No change */ 1745 else 1746 ApmReg->EX[XRE8] = RDXL_IOP(0xE8); /* No change */ 1747 1748 ApmReg->EX[XRE0] = 0x10; 1749 1750 /* If you change it, change in apm_funcs.c as well */ 1751 if (pApm->Chipset >= AT3D) { 1752 ApmReg->SEQ[0x1B] = 0x20; 1753 ApmReg->SEQ[0x1C] = 0x2F; 1754 } 1755 else { 1756 ApmReg->SEQ[0x1B] = 0x24; 1757 if (pScrn->videoRam >= 6 * 1024) 1758 ApmReg->SEQ[0x1C] = 0x2F; 1759 else 1760 ApmReg->SEQ[0x1C] = 0x2D; 1761 } 1762 1763 /* ICICICICI */ 1764 ApmRestore(pScrn, &hwp->ModeReg, ApmReg); 1765 1766 return TRUE; 1767} 1768 1769/* 1770 * Restore the initial mode. 1771 */ 1772static void 1773ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, ApmRegPtr ApmReg) 1774{ 1775 APMDECL(pScrn); 1776 1777 vgaHWProtect(pScrn, TRUE); 1778 ApmUnlock(pApm); 1779 1780 if (pApm->VGAMap) { 1781 /* 1782 * Restore fonts 1783 */ 1784 if (!(vgaReg->Attribute[0x10] & 1) && pApm->FontInfo) { 1785 ApmWriteSeq(0x1C, 0x3F); 1786 memcpy(pApm->FbBase, pApm->FontInfo, TEXT_AMOUNT); 1787 } 1788 1789 /* Set aperture index to 0. */ 1790 WRXW(0xC0, 0); 1791 1792 /* 1793 * Write the extended registers first 1794 */ 1795 ApmWriteSeq(0x1B, ApmReg->SEQ[0x1B]); 1796 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]); 1797 1798 /* Hardware cursor registers. */ 1799 WRXL(0x140, ApmReg->EX[XR140]); 1800 WRXW(0x144, ApmReg->EX[XR144]); 1801 WRXL(0x148, ApmReg->EX[XR148]); 1802 WRXW(0x14C, ApmReg->EX[XR14C]); 1803 1804 ApmWriteCrtc(0x19, ApmReg->CRT[0x19]); 1805 ApmWriteCrtc(0x1A, ApmReg->CRT[0x1A]); 1806 ApmWriteCrtc(0x1B, ApmReg->CRT[0x1B]); 1807 ApmWriteCrtc(0x1D, ApmReg->CRT[0x1D]); 1808 ApmWriteCrtc(0x1E, ApmReg->CRT[0x1E]); 1809 1810 /* RAMDAC registers. */ 1811 WRXL(0xE8, ApmReg->EX[XRE8]); 1812 1813 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7)); 1814 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */ 1815 1816 /* Color correction */ 1817 WRXL(0xE0, ApmReg->EX[XRE0]); 1818 1819 /* 1820 * This function handles restoring the generic VGA registers. 1821 */ 1822 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 1823 1824 /* set these after setting the default VGA registers */ 1825 ApmWriteCrtc(0x1C, ApmReg->CRT[0x1C]); 1826 WRXB(0x80, ApmReg->EX[XR80]); 1827 } 1828 else { 1829 /* Set aperture index to 0. */ 1830 if (pApm->noLinear) 1831 WRXW_IOP(0xC0, 0); 1832 else 1833 WRXW(0xC0, 0); 1834 1835 /* 1836 * Write the extended registers first 1837 */ 1838 wrinx(pApm->xport, 0x1B, ApmReg->SEQ[0x1B]); 1839 wrinx(pApm->xport, 0x1C, ApmReg->SEQ[0x1C]); 1840 1841 /* Hardware cursor registers. */ 1842 if (pApm->noLinear) { 1843 WRXL_IOP(0x140, ApmReg->EX[XR140]); 1844 WRXW_IOP(0x144, ApmReg->EX[XR144]); 1845 WRXL_IOP(0x148, ApmReg->EX[XR148]); 1846 WRXW_IOP(0x14C, ApmReg->EX[XR14C]); 1847 } 1848 else { 1849 WRXL(0x140, ApmReg->EX[XR140]); 1850 WRXW(0x144, ApmReg->EX[XR144]); 1851 WRXL(0x148, ApmReg->EX[XR148]); 1852 WRXW(0x14C, ApmReg->EX[XR14C]); 1853 } 1854 1855 wrinx(pApm->iobase + 0x3D4, 0x19, ApmReg->CRT[0x19]); 1856 wrinx(pApm->iobase + 0x3D4, 0x1A, ApmReg->CRT[0x1A]); 1857 wrinx(pApm->iobase + 0x3D4, 0x1B, ApmReg->CRT[0x1B]); 1858 wrinx(pApm->iobase + 0x3D4, 0x1C, ApmReg->CRT[0x1C]); 1859 wrinx(pApm->iobase + 0x3D4, 0x1D, ApmReg->CRT[0x1D]); 1860 wrinx(pApm->iobase + 0x3D4, 0x1E, ApmReg->CRT[0x1E]); 1861 1862 /* RAMDAC registers. */ 1863 if (pApm->noLinear) { 1864 WRXL_IOP(0xE8, ApmReg->EX[XRE8]); 1865 WRXL_IOP(0xEC, ApmReg->EX[XREC] & ~(1 << 7)); 1866 WRXL_IOP(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */ 1867 } 1868 else { 1869 WRXL(0xE8, ApmReg->EX[XRE8]); 1870 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7)); 1871 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */ 1872 } 1873 1874 /* Color correction */ 1875 if (pApm->noLinear) 1876 WRXL_IOP(0xE0, ApmReg->EX[XRE0]); 1877 else 1878 WRXL(0xE0, ApmReg->EX[XRE0]); 1879 1880 if (pApm->noLinear) 1881 WRXB_IOP(0x80, ApmReg->EX[XR80]); 1882 else 1883 WRXB(0x80, ApmReg->EX[XR80]); 1884 1885 /* 1886 * This function handles restoring the generic VGA registers. 1887 */ 1888 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1889 } 1890 1891 vgaHWProtect(pScrn, FALSE); 1892} 1893 1894 1895/* Refresh a region of the shadow framebuffer to the screen */ 1896static void 1897ApmRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) 1898{ 1899 APMDECL(pScrn); 1900 int width, height, Bpp, FBPitch; 1901 unsigned char *src, *dst; 1902 1903 Bpp = pApm->CurrentLayout.bitsPerPixel >> 3; 1904 FBPitch = pApm->CurrentLayout.bytesPerScanline; 1905 1906 while(num--) { 1907 width = (pbox->x2 - pbox->x1) * Bpp; 1908 height = pbox->y2 - pbox->y1; 1909 src = pApm->ShadowPtr + (pbox->y1 * pApm->ShadowPitch) + 1910 (pbox->x1 * Bpp); 1911 dst = (unsigned char *)pApm->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); 1912 1913 while(height--) { 1914 memcpy(dst, src, width); 1915 dst += FBPitch; 1916 src += pApm->ShadowPitch; 1917 } 1918 1919 pbox++; 1920 } 1921} 1922 1923 1924/* Mandatory */ 1925 1926/* This gets called at the start of each server generation */ 1927 1928static Bool 1929ApmScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1930{ 1931 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1932 APMDECL(pScrn); 1933 int ret; 1934 unsigned char *FbBase; 1935 1936 pApm->pScreen = pScreen; 1937 1938 /* Map the chip memory and MMIO areas */ 1939 if (pApm->noLinear) { 1940 PCI_READ_LONG(pApm->PciInfo, &pApm->saveCmd, PCI_CMD_STAT_REG); 1941 PCI_WRITE_LONG(pApm->PciInfo, pApm->saveCmd | (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE), PCI_CMD_STAT_REG); 1942#ifndef XSERVER_LIBPCIACCESS 1943 pApm->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1944 pApm->PciTag, 0xA0000, 0x10000); 1945#endif 1946 } 1947 else 1948 if (!ApmMapMem(pScrn)) 1949 return FALSE; 1950 1951 /* No memory reserved yet */ 1952 pApm->OffscreenReserved = 0; 1953 1954 /* Save the current state */ 1955 ApmSave(pScrn); 1956 1957 /* Initialise the first mode */ 1958 ApmModeInit(pScrn, pScrn->currentMode); 1959 pApm->CurrentLayout.pMode = pScrn->currentMode; 1960 1961 /* Darken the screen for aesthetic reasons and set the viewport */ 1962 ApmSaveScreen(pScreen, SCREEN_SAVER_ON); 1963 ApmAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1964 1965 /* 1966 * Reset fb's visual list. 1967 */ 1968 miClearVisualTypes(); 1969 1970 /* Setup the visuals we support. */ 1971 1972 /* 1973 * For bpp > 8, the default visuals are not acceptable because we only 1974 * support TrueColor and not DirectColor. To deal with this, call 1975 * miSetVisualTypes for each visual supported. 1976 */ 1977 1978 if (pApm->CurrentLayout.bitsPerPixel > 8) { 1979 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, 1980 pScrn->defaultVisual)) 1981 return FALSE; 1982 } else { 1983 if (!miSetVisualTypes(pScrn->depth, 1984 miGetDefaultVisualMask(pScrn->depth), 1985 pScrn->rgbBits, pScrn->defaultVisual)) 1986 return FALSE; 1987 } 1988 1989 /* 1990 * Call the framebuffer layer's ScreenInit function, and fill in other 1991 * pScreen fields. 1992 */ 1993 1994 if(pApm->ShadowFB) { 1995 pApm->ShadowPitch = 1996 ((pScrn->virtualX * pScrn->bitsPerPixel >> 3) + 3) & ~3L; 1997 pApm->ShadowPtr = xalloc(pApm->ShadowPitch * pScrn->virtualY); 1998 FbBase = pApm->ShadowPtr; 1999 } else { 2000 pApm->ShadowPtr = NULL; 2001 FbBase = pApm->FbBase; 2002 } 2003 2004 /* Reserve memory */ 2005 ApmHWCursorReserveSpace(pApm); 2006 ApmAccelReserveSpace(pApm); 2007 2008 miSetPixmapDepths(); 2009 2010 switch (pScrn->bitsPerPixel) { 2011#ifdef HAVE_XF1BPP 2012 case 1: 2013 ret = xf1bppScreenInit(pScreen, FbBase, 2014 pScrn->virtualX, pScrn->virtualY, 2015 pScrn->xDpi, pScrn->yDpi, 2016 pScrn->displayWidth); 2017 break; 2018#endif 2019#ifdef HAVE_XF4BPP 2020 case 4: 2021 ret = xf4bppScreenInit(pScreen, FbBase, 2022 pScrn->virtualX, pScrn->virtualY, 2023 pScrn->xDpi, pScrn->yDpi, 2024 pScrn->displayWidth); 2025 break; 2026#endif 2027 case 8: 2028 case 16: 2029 case 24: 2030 case 32: 2031 ret = fbScreenInit(pScreen, FbBase, pScrn->virtualX, 2032 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 2033 pScrn->displayWidth, pScrn->bitsPerPixel); 2034 break; 2035 default: 2036 xf86DrvMsg(scrnIndex, X_ERROR, 2037 "Internal error: invalid bpp (%d) in ApmScrnInit\n", 2038 pScrn->bitsPerPixel); 2039 ret = FALSE; 2040 break; 2041 } 2042 if (!ret) 2043 return FALSE; 2044 2045 if (pScrn->bitsPerPixel > 8) { 2046 VisualPtr visual; 2047 2048 /* Fixup RGB ordering */ 2049 visual = pScreen->visuals + pScreen->numVisuals; 2050 while (--visual >= pScreen->visuals) { 2051 if ((visual->class | DynamicClass) == DirectColor) { 2052 visual->offsetRed = pScrn->offset.red; 2053 visual->offsetGreen = pScrn->offset.green; 2054 visual->offsetBlue = pScrn->offset.blue; 2055 visual->redMask = pScrn->mask.red; 2056 visual->greenMask = pScrn->mask.green; 2057 visual->blueMask = pScrn->mask.blue; 2058 } 2059 } 2060 } 2061 2062 /* must be after visual RGB order fixed */ 2063 if (pScrn->bitsPerPixel > 4) 2064 fbPictureInit(pScreen, 0, 0); 2065 2066 xf86SetBlackWhitePixels(pScreen); 2067 2068 if (!pApm->ShadowFB) { /* hardware cursor needs to wrap this layer */ 2069 if(!ApmDGAInit(pScreen)) { 2070 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DGA initialization failed\n"); 2071 } 2072 } 2073 2074 /* 2075 * Initialize the acceleration interface. 2076 */ 2077 if (!pApm->NoAccel) { 2078 ApmAccelInit(pScreen); /* set up XAA interface */ 2079 } 2080 2081 miInitializeBackingStore(pScreen); 2082 xf86SetBackingStore(pScreen); 2083 xf86SetSilkenMouse(pScreen); 2084 2085 /* Initialise cursor functions */ 2086 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 2087 2088 /* Initialize HW cursor layer (after DGA and SW cursor) */ 2089 if (pApm->hwCursor) { 2090 if (!ApmHWCursorInit(pScreen)) 2091 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2092 "Hardware cursor initialization failed\n"); 2093 } 2094 2095 2096 /* Initialise default colourmap */ 2097 if (!miCreateDefColormap(pScreen)) 2098 return FALSE; 2099 2100 /* 2101 * Initialize colormap layer. 2102 * Must follow initialization of the default colormap. 2103 */ 2104 if (!xf86HandleColormaps(pScreen, 256, 8, ApmLoadPalette, NULL, 2105 CMAP_RELOAD_ON_MODE_SWITCH)) { 2106 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Colormap initialization failed\n"); 2107 return FALSE; 2108 } 2109 2110 if (pApm->ShadowFB) 2111 ShadowFBInit(pScreen, ApmRefreshArea); 2112 2113 xf86DPMSInit(pScreen, ApmDisplayPowerManagementSet, 0); 2114 2115 if (pApm->noLinear) 2116 ApmInitVideo_IOP(pScreen); 2117 else 2118 ApmInitVideo(pScreen); 2119 2120 pScreen->SaveScreen = ApmSaveScreen; 2121 2122 pApm->CloseScreen = pScreen->CloseScreen; 2123 pScreen->CloseScreen = ApmCloseScreen; 2124 2125 pScrn->memPhysBase = pApm->LinAddress; 2126 pScrn->fbOffset = (((char *)pApm->FbBase) - ((char *)pApm->LinMap)); 2127 2128 /* Report any unused options (only for the first generation) */ 2129 if (serverGeneration == 1) { 2130 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2131 } 2132 2133#ifdef XF86RUSH 2134 if (ApmGeneration != serverGeneration) { 2135 if ((ApmPixmapIndex = AllocatePixmapPrivateIndex()) < 0) 2136 return FALSE; 2137 ApmGeneration = serverGeneration; 2138 } 2139 2140 if (!AllocatePixmapPrivate(pScreen, ApmPixmapIndex, sizeof(ApmPixmapRec))) 2141 return FALSE; 2142#endif 2143 2144 /* Done */ 2145 return TRUE; 2146} 2147 2148/* mandatory */ 2149static void 2150ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 2151 VisualPtr pVisual) 2152{ 2153 APMDECL(pScrn); 2154 int i, index, last = -1; 2155 2156 if (pApm->VGAMap) { 2157 for (i = 0; i < numColors; i++) { 2158 index = indices[i]; 2159 if (index != last) 2160 ApmWriteDacWriteAddr(index); 2161 last = index + 1; 2162 ApmWriteDacData(colors[index].red); 2163 ApmWriteDacData(colors[index].green); 2164 ApmWriteDacData(colors[index].blue); 2165 } 2166 } 2167 else { 2168 for (i = 0; i < numColors; i++) { 2169 index = indices[i]; 2170 if (index != last) 2171 outb(pApm->iobase + 0x3C8, index); 2172 last = index + 1; 2173 outb(pApm->iobase + 0x3C9, colors[index].red); 2174 outb(pApm->iobase + 0x3C9, colors[index].green); 2175 outb(pApm->iobase + 0x3C9, colors[index].blue); 2176 } 2177 } 2178} 2179 2180/* Usually mandatory */ 2181Bool 2182ApmSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 2183{ 2184 return ApmModeInit(xf86Screens[scrnIndex], mode); 2185} 2186 2187/* 2188 * This function is used to initialize the Start Address - the first 2189 * displayed location in the video memory. 2190 */ 2191/* Usually mandatory */ 2192void 2193ApmAdjustFrame(int scrnIndex, int x, int y, int flags) 2194{ 2195 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2196 APMDECL(pScrn); 2197 int Base; 2198 2199 if (pApm->CurrentLayout.bitsPerPixel == 24) 2200 x = (x + 3) & ~3; 2201 Base = ((y * pApm->CurrentLayout.displayWidth + x) * (pApm->CurrentLayout.bitsPerPixel / 8)) >> 2; 2202 /* 2203 * These are the generic starting address registers. 2204 */ 2205 if (pApm->VGAMap) { 2206 ApmWriteCrtc(0x0C, Base >> 8); 2207 ApmWriteCrtc(0x0D, Base); 2208 2209 /* 2210 * Here the high-order bits are masked and shifted, and put into 2211 * the appropriate extended registers. 2212 */ 2213 ApmWriteCrtc(0x1C, (ApmReadCrtc(0x1C) & 0xF0) | ((Base & 0x0F0000) >> 16)); 2214 } 2215 else { 2216 outw(pApm->iobase + 0x3D4, (Base & 0x00FF00) | 0x0C); 2217 outw(pApm->iobase + 0x3D4, ((Base & 0x00FF) << 8) | 0x0D); 2218 2219 /* 2220 * Here the high-order bits are masked and shifted, and put into 2221 * the appropriate extended registers. 2222 */ 2223 modinx(pApm->iobase + 0x3D4, 0x1C, 0x0F, (Base & 0x0F0000) >> 16); 2224 } 2225} 2226 2227/* 2228 * This is called when VT switching back to the X server. Its job is 2229 * to reinitialise the video mode. 2230 * 2231 * We may wish to unmap video/MMIO memory too. 2232 */ 2233 2234/* Mandatory */ 2235static Bool 2236ApmEnterVT(int scrnIndex, int flags) 2237{ 2238 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2239 APMDECL(pScrn); 2240 vgaHWPtr hwp = VGAHWPTR(pScrn); 2241 2242 if (pApm->Chipset >= AT3D) { 2243 if (!pApm->noLinear) { 2244 /* If you change it, change it also in apm_funcs.c */ 2245 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A | pApm->Rush); 2246 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20); 2247 } 2248 else { 2249 WRXB_IOP(0xDB, pApm->db & 0xF4); 2250 } 2251 } 2252 if (pApm->Chipset >= AP6422) 2253 WRXB(0xC9, pApm->c9 | 0x10); 2254 ApmUnlock(APMPTR(pScrn)); 2255 vgaHWUnlock(hwp); 2256 /* 2257 * Set color mode 2258 */ 2259 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F); 2260 2261 if (!ApmModeInit(pScrn, pScrn->currentMode)) 2262 return FALSE; 2263 ApmAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 2264 2265 return TRUE; 2266} 2267 2268/* Mandatory */ 2269static void 2270ApmLeaveVT(int scrnIndex, int flags) 2271{ 2272 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2273 APMDECL(pScrn); 2274 vgaHWPtr hwp = VGAHWPTR(pScrn); 2275 2276 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg); 2277 /* 2278 * Reset color mode 2279 */ 2280 (*hwp->writeMiscOut)(hwp, pApm->MiscOut); 2281 vgaHWLock(hwp); 2282 ApmLock(pApm); 2283 if (pApm->Chipset >= AT3D) { 2284 if (!pApm->noLinear) { 2285 WRXB(0xD9, pApm->d9); 2286 WRXB(0xDB, pApm->db); 2287 } 2288 else { 2289 WRXB_IOP(0xD9, pApm->d9); 2290 WRXB_IOP(0xDB, pApm->db); 2291 } 2292 } 2293 WRXB(0xC9, pApm->c9); 2294 2295 if (xf86IsPc98()) 2296 outb(0xFAC, 0xFE); 2297} 2298 2299/* 2300 * This is called at the end of each server generation. It restores the 2301 * original (text) mode. It should really also unmap the video memory too. 2302 */ 2303 2304/* Mandatory */ 2305static Bool 2306ApmCloseScreen(int scrnIndex, ScreenPtr pScreen) 2307{ 2308 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2309 vgaHWPtr hwp = VGAHWPTR(pScrn); 2310 APMDECL(pScrn); 2311 2312 if (pScrn->vtSema) { 2313 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg); 2314 vgaHWLock(hwp); 2315 ApmUnmapMem(pScrn); 2316 } 2317 if(pApm->AccelInfoRec) 2318 XAADestroyInfoRec(pApm->AccelInfoRec); 2319 if(pApm->DGAXAAInfo) 2320 XAADestroyInfoRec(pApm->DGAXAAInfo); 2321 pApm->AccelInfoRec = NULL; 2322 if(pApm->CursorInfoRec) 2323 xf86DestroyCursorInfoRec(pApm->CursorInfoRec); 2324 pApm->CursorInfoRec = NULL; 2325 if (pApm->DGAModes) 2326 xfree(pApm->DGAModes); 2327 if (pApm->adaptor) 2328 xfree(pApm->adaptor); 2329 2330 pScrn->vtSema = FALSE; 2331 2332 if (xf86IsPc98()) 2333 outb(0xFAC, 0xFE); 2334 2335 pScreen->CloseScreen = pApm->CloseScreen; 2336 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 2337} 2338 2339/* Free up any per-generation data structures */ 2340 2341/* Optional */ 2342static void 2343ApmFreeScreen(int scrnIndex, int flags) 2344{ 2345 vgaHWFreeHWRec(xf86Screens[scrnIndex]); 2346 ApmFreeRec(xf86Screens[scrnIndex]); 2347} 2348 2349/* Checks if a mode is suitable for the selected chipset. */ 2350 2351/* Optional */ 2352static ModeStatus 2353ApmValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 2354{ 2355 if (mode->Flags & V_INTERLACE) 2356 return(MODE_BAD); 2357 2358 return(MODE_OK); 2359} 2360 2361 2362/* 2363 * ApmDisplayPowerManagementSet -- 2364 * 2365 * Sets VESA Display Power Management Signaling (DPMS) Mode. 2366 */ 2367static void 2368ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 2369 int flags) 2370{ 2371 APMDECL(pScrn); 2372 unsigned char dpmsreg, tmp; 2373 2374 if (PowerManagementMode < sizeof pApm->DPMSMask && 2375 PowerManagementMode >= 0) 2376 PowerManagementMode = pApm->DPMSMask[PowerManagementMode]; 2377 switch (PowerManagementMode) 2378 { 2379 case DPMSModeOn: 2380 /* Screen: On; HSync: On, VSync: On */ 2381 dpmsreg = 0x00; 2382 break; 2383 case DPMSModeStandby: 2384 /* Screen: Off; HSync: Off, VSync: On */ 2385 dpmsreg = 0x01; 2386 break; 2387 case DPMSModeSuspend: 2388 /* Screen: Off; HSync: On, VSync: Off */ 2389 dpmsreg = 0x02; 2390 break; 2391 case DPMSModeOff: 2392 /* Screen: Off; HSync: Off, VSync: Off */ 2393 dpmsreg = 0x03; 2394 break; 2395 default: 2396 dpmsreg = 0; 2397 } 2398 if (pApm->noLinear) { 2399 tmp = RDXB_IOP(0xD0); 2400 WRXB_IOP(0xD0, (tmp & 0xFC) | dpmsreg); 2401 } else { 2402 tmp = RDXB(0xD0); 2403 WRXB(0xD0, (tmp & 0xFC) | dpmsreg); 2404 } 2405} 2406 2407static Bool 2408ApmSaveScreen(ScreenPtr pScreen, int mode) 2409{ 2410 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2411 Bool unblank; 2412 2413 unblank = xf86IsUnblank(mode); 2414 2415 if (unblank) 2416 SetTimeSinceLastInputEvent(); 2417 2418 if (pScrn->vtSema) 2419 vgaHWBlankScreen(pScrn, unblank); 2420 return TRUE; 2421} 2422 2423#ifdef APM_DEBUG 2424unsigned char _L_ACR(unsigned char *x); 2425unsigned char _L_ACR(unsigned char *x) 2426{ 2427 return *x; 2428} 2429 2430unsigned short _L_ASR(unsigned short *x); 2431unsigned short _L_ASR(unsigned short *x) 2432{ 2433 return *x; 2434} 2435 2436unsigned int _L_AIR(unsigned int *x); 2437unsigned int _L_AIR(unsigned int *x) 2438{ 2439 return *x; 2440} 2441 2442void _L_ACW(char *x, char y); 2443void _L_ACW(char *x, char y) 2444{ 2445 *x = y; 2446} 2447 2448void _L_ASW(short *x, short y); 2449void _L_ASW(short *x, short y) 2450{ 2451 *x = y; 2452} 2453 2454void _L_AIW(int *x, int y); 2455void _L_AIW(int *x, int y) 2456{ 2457 *x = y; 2458} 2459#endif 2460