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