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