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