vesa.c revision 78f6f648
1#define DEBUG_VERB 2 2/* 3 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) 4 * Copyright 2008 Red Hat, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * Except as contained in this notice, the name of Conectiva Linux shall 25 * not be used in advertising or otherwise to promote the sale, use or other 26 * dealings in this Software without prior written authorization from 27 * Conectiva Linux. 28 * 29 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> 30 * David Dawes <dawes@xfree86.org> 31 * Adam Jackson <ajax@redhat.com> 32 */ 33 34/* 35 * TODO: 36 * - Port to RANDR 1.2 setup to make mode selection slightly better 37 * - Port to RANDR 1.2 to drop the old-school DGA junk 38 * - VBE/SCI for secondary DDC method? 39 */ 40 41#ifdef HAVE_CONFIG_H 42#include "config.h" 43#endif 44 45#include <string.h> 46#include <unistd.h> 47#include <dirent.h> 48#include "vesa.h" 49 50/* All drivers initialising the SW cursor need this */ 51#include "mipointer.h" 52 53/* Colormap handling */ 54#include "micmap.h" 55#include "xf86cmap.h" 56#include "xf86Modes.h" 57 58/* DPMS */ 59#ifdef HAVE_XEXTPROTO_71 60#include <X11/extensions/dpmsconst.h> 61#else 62#define DPMS_SERVER 63#include <X11/extensions/dpms.h> 64#endif 65#include "compat-api.h" 66 67#if defined(__NetBSD__) 68#include <sys/sysctl.h> 69#endif 70 71/* Mandatory functions */ 72static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid); 73static void VESAIdentify(int flags); 74#if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA) 75#define VESAProbe NULL 76#else 77static Bool VESAProbe(DriverPtr drv, int flags); 78#endif 79#ifdef XSERVER_LIBPCIACCESS 80static Bool VESAPciProbe(DriverPtr drv, int entity_num, 81 struct pci_device *dev, intptr_t match_data); 82#endif 83static Bool VESAPreInit(ScrnInfoPtr pScrn, int flags); 84static Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL); 85static Bool VESAEnterVT(VT_FUNC_ARGS_DECL); 86static void VESALeaveVT(VT_FUNC_ARGS_DECL); 87static Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL); 88static Bool VESASaveScreen(ScreenPtr pScreen, int mode); 89 90static Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL); 91static Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); 92static void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL); 93static void VESAFreeScreen(FREE_SCREEN_ARGS_DECL); 94static void VESAFreeRec(ScrnInfoPtr pScrn); 95static VESAPtr VESAGetRec(ScrnInfoPtr pScrn); 96 97static void 98VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 99 int flags); 100 101/* locally used functions */ 102#ifdef HAVE_ISA 103static int VESAFindIsaDevice(GDevPtr dev); 104#endif 105static Bool VESAMapVidMem(ScrnInfoPtr pScrn); 106static void VESAUnmapVidMem(ScrnInfoPtr pScrn); 107static int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank); 108static void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 109 LOCO *colors, VisualPtr pVisual); 110static void SaveFonts(ScrnInfoPtr pScrn); 111static void RestoreFonts(ScrnInfoPtr pScrn); 112static Bool 113VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); 114 115static void * 116VESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 117 CARD32 *size, void *closure) 118{ 119 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 120 VESAPtr pVesa = VESAGetRec(pScrn); 121 122 *size = pVesa->maxBytesPerScanline; 123 return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset); 124} 125 126static void * 127VESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 128 CARD32 *size, void *closure) 129{ 130 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 131 VESAPtr pVesa = VESAGetRec(pScrn); 132 VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 133 int window; 134 135 offset += pVesa->maxBytesPerScanline * row; 136 window = offset / (data->WinGranularity * 1024); 137 pVesa->windowAoffset = window * data->WinGranularity * 1024; 138 VESABankSwitch(pScreen, window); 139 *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset); 140 141 return (void *)((unsigned long)pVesa->base + 142 (offset - pVesa->windowAoffset)); 143} 144 145static void 146vesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 147{ 148 shadowUpdatePacked(pScreen, pBuf); 149} 150 151static Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen); 152 153enum GenericTypes 154{ 155 CHIP_VESA_GENERIC 156}; 157 158#ifdef XSERVER_LIBPCIACCESS 159static const struct pci_id_match vesa_device_match[] = { 160 { 161 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 162 0x00030000, 0x00ffffff, CHIP_VESA_GENERIC 163 }, 164 165 { 0, 0, 0 }, 166}; 167#endif 168 169/* Supported chipsets */ 170static SymTabRec VESAChipsets[] = 171{ 172 {CHIP_VESA_GENERIC, "vesa"}, 173 {-1, NULL} 174}; 175 176#ifndef XSERVER_LIBPCIACCESS 177static PciChipsets VESAPCIchipsets[] = { 178 { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA }, 179 { -1, -1, RES_UNDEFINED }, 180}; 181#endif 182 183#ifdef HAVE_ISA 184static IsaChipsets VESAISAchipsets[] = { 185 {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA}, 186 {-1, 0 } 187}; 188#endif 189 190 191/* 192 * This contains the functions needed by the server after loading the 193 * driver module. It must be supplied, and gets added the driver list by 194 * the Module Setup function in the dynamic case. In the static case a 195 * reference to this is compiled in, and this requires that the name of 196 * this DriverRec be an upper-case version of the driver name. 197 */ 198_X_EXPORT DriverRec VESA = { 199 VESA_VERSION, 200 VESA_DRIVER_NAME, 201 VESAIdentify, 202 VESAProbe, 203 VESAAvailableOptions, 204 NULL, 205 0, 206 NULL, 207 208#ifdef XSERVER_LIBPCIACCESS 209 vesa_device_match, 210 VESAPciProbe 211#endif 212}; 213 214 215typedef enum { 216 OPTION_SHADOW_FB, 217 OPTION_DFLT_REFRESH, 218 OPTION_MODESET_CLEAR_SCREEN 219} VESAOpts; 220 221static const OptionInfoRec VESAOptions[] = { 222 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 223 { OPTION_DFLT_REFRESH, "DefaultRefresh", OPTV_BOOLEAN, {0}, FALSE }, 224 { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen", 225 OPTV_BOOLEAN, {0}, FALSE }, 226 { -1, NULL, OPTV_NONE, {0}, FALSE } 227}; 228 229#ifdef XFree86LOADER 230 231/* Module loader interface */ 232static MODULESETUPPROTO(vesaSetup); 233 234static XF86ModuleVersionInfo vesaVersionRec = 235{ 236 VESA_DRIVER_NAME, 237 MODULEVENDORSTRING, 238 MODINFOSTRING1, 239 MODINFOSTRING2, 240 XORG_VERSION_CURRENT, 241 VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL, 242 ABI_CLASS_VIDEODRV, /* This is a video driver */ 243 ABI_VIDEODRV_VERSION, 244 MOD_CLASS_VIDEODRV, 245 {0, 0, 0, 0} 246}; 247 248/* 249 * This data is accessed by the loader. The name must be the module name 250 * followed by "ModuleData". 251 */ 252_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL }; 253 254static pointer 255vesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) 256{ 257 static Bool Initialised = FALSE; 258 259 if (!Initialised) 260 { 261 Initialised = TRUE; 262 xf86AddDriver(&VESA, Module, 1); 263 return (pointer)TRUE; 264 } 265 266 if (ErrorMajor) 267 *ErrorMajor = LDR_ONCEONLY; 268 return (NULL); 269} 270 271#endif 272 273static const OptionInfoRec * 274VESAAvailableOptions(int chipid, int busid) 275{ 276 return (VESAOptions); 277} 278 279static void 280VESAIdentify(int flags) 281{ 282 xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets); 283} 284 285static VESAPtr 286VESAGetRec(ScrnInfoPtr pScrn) 287{ 288 if (!pScrn->driverPrivate) 289 pScrn->driverPrivate = calloc(sizeof(VESARec), 1); 290 291 return ((VESAPtr)pScrn->driverPrivate); 292} 293 294/* Only a little like VBESetModeParameters */ 295static void 296VESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode, 297 DisplayModePtr ddcmode) 298{ 299 VbeModeInfoData *data; 300 int clock; 301 302 data = (VbeModeInfoData *)vbemode->Private; 303 304 data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); 305 data->block->HorizontalTotal = ddcmode->HTotal; 306 data->block->HorizontalSyncStart = ddcmode->HSyncStart; 307 data->block->HorizontalSyncEnd = ddcmode->HSyncEnd; 308 data->block->VerticalTotal = ddcmode->VTotal; 309 data->block->VerticalSyncStart = ddcmode->VSyncStart; 310 data->block->VerticalSyncEnd = ddcmode->VSyncEnd; 311 data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | 312 ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); 313 data->block->PixelClock = ddcmode->Clock * 1000; 314 315 /* ask the BIOS to figure out the real clock */ 316 clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); 317 if (clock) 318 data->block->PixelClock = clock; 319 320 data->mode |= (1 << 11); 321 data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) / 322 (double)(ddcmode->HTotal * ddcmode->VTotal)); 323} 324 325/* 326 * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes 327 * think they can only give sizes in multiples of character cells; and 328 * indeed, the reference CVT and GTF formulae only give results where 329 * (h % 8) == 0. Whatever, let's just try to cope. What we're looking for 330 * here is cases where the display says 1366x768 and the BIOS says 1360x768. 331 */ 332static Bool 333vesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe) 334{ 335 if (!(edid->type & M_T_DRIVER)) 336 return FALSE; 337 338 /* never seen a height granularity... */ 339 if (edid->VDisplay != vbe->VDisplay) 340 return FALSE; 341 342 if (edid->HDisplay >= vbe->HDisplay && 343 (edid->HDisplay & ~7) == (vbe->HDisplay & ~7)) 344 return TRUE; 345 346 return FALSE; 347} 348 349static ModeStatus 350VESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass) 351{ 352 SCRN_INFO_PTR(arg); 353 static int warned = 0; 354 int found = 0; 355 VESAPtr pVesa = VESAGetRec(pScrn); 356 MonPtr mon = pScrn->monitor; 357 ModeStatus ret = MODE_BAD; 358 DisplayModePtr mode; 359 float v; 360 361 if (pass != MODECHECK_FINAL) { 362 if (!warned) { 363 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n"); 364 warned = 1; 365 } 366 return MODE_OK; 367 } 368 369 /* 370 * This is suboptimal. We pass in just the barest description of a mode 371 * we can get away with to VBEValidateModes, so it can't really throw 372 * out anything we give it. But we need to filter the list so that we 373 * don't populate the mode list with things the monitor can't do. 374 * 375 * So first off, if this isn't a mode we handed to the server (ie, 376 * M_T_BUILTIN), then we know we can't do it. 377 */ 378 if (!(p->type & M_T_BUILTIN)) 379 return MODE_NOMODE; 380 381 if (pVesa->strict_validation) { 382 /* 383 * If it's our first pass at mode validation, we'll try for a strict 384 * intersection between the VBE and DDC mode lists. 385 */ 386 if (pScrn->monitor->DDC) { 387 for (mode = pScrn->monitor->Modes; mode; mode = mode->next) { 388 if (vesaModesCloseEnough(mode, p)) { 389 if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) { 390 found = 1; 391 break; 392 } 393 } 394 if (mode == pScrn->monitor->Last) 395 break; 396 } 397 if (!found) 398 return MODE_NOMODE; 399 400 /* having found a matching mode, stash the CRTC values aside */ 401 VESASetModeParameters(pVesa->pVbe, p, mode); 402 return MODE_OK; 403 } 404 405 /* No DDC and no modes make Homer something something... */ 406 return MODE_NOMODE; 407 } 408 409 /* 410 * Finally, walk through the vsync rates 1Hz at a time looking for a mode 411 * that will fit. This is assuredly a terrible way to do this, but 412 * there's no obvious method for computing a mode of a given size that 413 * will pass xf86CheckModeForMonitor. XXX this path is terrible, but 414 * then, by this point, you're well into despair territory. 415 */ 416 for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) { 417 mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0); 418 ret = xf86CheckModeForMonitor(mode, mon); 419 free(mode->name); 420 free(mode); 421 if (ret == MODE_OK) 422 break; 423 } 424 425 return ret; 426} 427 428static void 429VESAInitScrn(ScrnInfoPtr pScrn) 430{ 431 pScrn->driverVersion = VESA_VERSION; 432 pScrn->driverName = VESA_DRIVER_NAME; 433 pScrn->name = VESA_NAME; 434 pScrn->Probe = VESAProbe; 435 pScrn->PreInit = VESAPreInit; 436 pScrn->ScreenInit = VESAScreenInit; 437 pScrn->SwitchMode = VESASwitchMode; 438 pScrn->ValidMode = VESAValidMode; 439 pScrn->AdjustFrame = VESAAdjustFrame; 440 pScrn->EnterVT = VESAEnterVT; 441 pScrn->LeaveVT = VESALeaveVT; 442 pScrn->FreeScreen = VESAFreeScreen; 443} 444 445#ifdef XSERVER_LIBPCIACCESS 446#ifdef __linux__ 447/* 448 * check if a file exist in directory 449 * should be equivalent to a glob ${directory}/${prefix}* 450 */ 451 452static Bool 453VESAFileExistsPrefix(const char *directory, const char *prefix) { 454 DIR *dir; 455 struct dirent *entry; 456 Bool found = FALSE; 457 int len = strlen(prefix); 458 459 dir = opendir(directory); 460 if (!dir) 461 return FALSE; 462 463 while ((entry = readdir(dir)) != NULL) { 464 if (strlen(entry->d_name) > len && 465 !memcmp(entry->d_name, prefix, len)) { 466 found = TRUE; 467 break; 468 } 469 } 470 closedir(dir); 471 return found; 472} 473#endif 474 475/* 476 * This function is called once, at the start of the first server generation to 477 * do a minimal probe for supported hardware. 478 */ 479static Bool 480VESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, 481 intptr_t match_data) 482{ 483 ScrnInfoPtr pScrn; 484 485#ifdef __linux__ 486 if (VESAFileExistsPrefix("/dev", "fb") || 487 VESAFileExistsPrefix("/dev/dri", "card")) { 488 ErrorF("vesa: Refusing to run, Framebuffer or dri device present\n"); 489 return FALSE; 490 } 491#endif 492#if defined(__NetBSD__) 493 { 494 char method[10]; 495 size_t len = sizeof(method); 496 497 if (sysctlbyname("machdep.bootmethod", &method, &len, NULL, 0) == 0 && 498 strcmp(method, "UEFI") == 0) { 499 ErrorF("vesa: Refusing to run, UEFI booted\n"); 500 return FALSE; 501 } 502 } 503#endif 504 505 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, 506 NULL, NULL, NULL, NULL, NULL); 507 if (pScrn != NULL) { 508 VESAPtr pVesa; 509 510 if (pci_device_has_kernel_driver(dev)) { 511 ErrorF("vesa: Ignoring device with a bound kernel driver\n"); 512 return FALSE; 513 } 514 515 pVesa = VESAGetRec(pScrn); 516 VESAInitScrn(pScrn); 517 pVesa->pciInfo = dev; 518 } 519 520 return (pScrn != NULL); 521} 522#endif 523 524#ifndef VESAProbe 525static Bool 526VESAProbe(DriverPtr drv, int flags) 527{ 528 Bool foundScreen = FALSE; 529 int numDevSections, numUsed; 530 GDevPtr *devSections; 531 int *usedChips; 532 int i; 533 534 /* 535 * Find the config file Device sections that match this 536 * driver, and return if there are none. 537 */ 538 if ((numDevSections = xf86MatchDevice(VESA_NAME, 539 &devSections)) <= 0) 540 return (FALSE); 541 542#ifndef XSERVER_LIBPCIACCESS 543 /* PCI BUS */ 544 if (xf86GetPciVideoInfo()) { 545 numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC, 546 VESAChipsets, VESAPCIchipsets, 547 devSections, numDevSections, 548 drv, &usedChips); 549 if (numUsed > 0) { 550 if (flags & PROBE_DETECT) 551 foundScreen = TRUE; 552 else { 553 for (i = 0; i < numUsed; i++) { 554 ScrnInfoPtr pScrn = NULL; 555 /* Allocate a ScrnInfoRec */ 556 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 557 VESAPCIchipsets,NULL, 558 NULL,NULL,NULL,NULL))) { 559 VESAInitScrn(pScrn); 560 foundScreen = TRUE; 561 } 562 } 563 } 564 free(usedChips); 565 } 566 } 567#endif 568 569#ifdef HAVE_ISA 570 /* Isa Bus */ 571 numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets, 572 VESAISAchipsets, drv, 573 VESAFindIsaDevice, devSections, 574 numDevSections, &usedChips); 575 if(numUsed > 0) { 576 if (flags & PROBE_DETECT) 577 foundScreen = TRUE; 578 else for (i = 0; i < numUsed; i++) { 579 ScrnInfoPtr pScrn = NULL; 580 if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i], 581 VESAISAchipsets, NULL, 582 NULL, NULL, NULL, NULL))) { 583 VESAInitScrn(pScrn); 584 foundScreen = TRUE; 585 } 586 } 587 free(usedChips); 588 } 589#endif 590 591 free(devSections); 592 593 return (foundScreen); 594} 595#endif 596 597#ifdef HAVE_ISA 598static int 599VESAFindIsaDevice(GDevPtr dev) 600{ 601#ifndef PC98_EGC 602 CARD16 GenericIOBase = VGAHW_GET_IOBASE(); 603 CARD8 CurrentValue, TestValue; 604 605 /* There's no need to unlock VGA CRTC registers here */ 606 607 /* VGA has one more read/write attribute register than EGA */ 608 (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */ 609 outb(VGA_ATTR_INDEX, 0x14 | 0x20); 610 CurrentValue = inb(VGA_ATTR_DATA_R); 611 outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F); 612 outb(VGA_ATTR_INDEX, 0x14 | 0x20); 613 TestValue = inb(VGA_ATTR_DATA_R); 614 outb(VGA_ATTR_DATA_R, CurrentValue); 615 616 /* Quit now if no VGA is present */ 617 if ((CurrentValue ^ 0x0F) != TestValue) 618 return -1; 619#endif 620 return (int)CHIP_VESA_GENERIC; 621} 622#endif 623 624static void 625VESAFreeRec(ScrnInfoPtr pScrn) 626{ 627 VESAPtr pVesa = VESAGetRec(pScrn); 628#if 0 629 DisplayModePtr mode = pScrn->modes; 630 /* I am not sure if the modes will ever get freed. 631 * Anyway, the data unknown to other modules is being freed here. 632 */ 633 if (mode) { 634 do { 635 if (mode->Private) { 636 VbeModeInfoData *data = (VbeModeInfoData*)mode->Private; 637 638 if (data->block) 639 free(data->block); 640 641 free(data); 642 643 mode->Private = NULL; 644 } 645 mode = mode->next; 646 } while (mode && mode != pScrn->modes); 647 } 648#endif 649 free(pVesa->monitor); 650 if (pVesa->vbeInfo) 651 VBEFreeVBEInfo(pVesa->vbeInfo); 652 free(pVesa->pal); 653 free(pVesa->savedPal); 654 free(pVesa->fonts); 655 free(pScrn->driverPrivate); 656 pScrn->driverPrivate = NULL; 657} 658 659static int 660VESAValidateModes(ScrnInfoPtr pScrn) 661{ 662 VESAPtr pVesa = VESAGetRec(pScrn); 663 DisplayModePtr mode; 664 665 for (mode = pScrn->monitor->Modes; mode; mode = mode->next) 666 mode->status = MODE_OK; 667 668 return VBEValidateModes(pScrn, NULL, pScrn->display->modes, 669 NULL, NULL, 0, 32767, 1, 0, 32767, 670 pScrn->display->virtualX, 671 pScrn->display->virtualY, 672 pVesa->mapSize, LOOKUP_BEST_REFRESH); 673} 674 675/* 676 * This function is called once for each screen at the start of the first 677 * server generation to initialise the screen for all server generations. 678 */ 679static Bool 680VESAPreInit(ScrnInfoPtr pScrn, int flags) 681{ 682 VESAPtr pVesa; 683 VbeInfoBlock *vbe; 684 DisplayModePtr pMode; 685 VbeModeInfoBlock *mode; 686 Gamma gzeros = {0.0, 0.0, 0.0}; 687 rgb rzeros = {0, 0, 0}; 688 pointer pDDCModule; 689 int i; 690 int flags24 = 0; 691 int defaultDepth = 0; 692 int defaultBpp = 0; 693 int depths = 0; 694 695 if (flags & PROBE_DETECT) 696 return (FALSE); 697 698 pVesa = VESAGetRec(pScrn); 699 pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 700 701 /* Load vbe module */ 702 if (!xf86LoadSubModule(pScrn, "vbe")) 703 return (FALSE); 704 705 if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 706 SET_BIOS_SCRATCH 707 | RESTORE_BIOS_SCRATCH)) == NULL) 708 return (FALSE); 709 710#ifndef XSERVER_LIBPCIACCESS 711 if (pVesa->pEnt->location.type == BUS_PCI) { 712 pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index); 713 pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device, 714 pVesa->pciInfo->func); 715 } 716#endif 717 718 pScrn->chipset = "vesa"; 719 pScrn->monitor = pScrn->confScreen->monitor; 720 pScrn->progClock = TRUE; 721 pScrn->rgbBits = 8; 722 723 if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL) 724 return (FALSE); 725 pVesa->major = (unsigned)(vbe->VESAVersion >> 8); 726 pVesa->minor = vbe->VESAVersion & 0xff; 727 pVesa->vbeInfo = vbe; 728 pScrn->videoRam = vbe->TotalMemory * 64; 729 730 /* 731 * Find what depths are available. 732 */ 733 depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24, 734 V_MODETYPE_VBE); 735 736 /* Preferred order for default depth selection. */ 737 if (depths & V_DEPTH_24 && (flags24 & Support32bppFb)) 738 defaultDepth = 24; 739 else if (depths & V_DEPTH_16) 740 defaultDepth = 16; 741 else if (depths & V_DEPTH_15) 742 defaultDepth = 15; 743 else if (depths & V_DEPTH_24) 744 defaultDepth = 24; /* ew though */ 745 else if (depths & V_DEPTH_8) 746 defaultDepth = 8; 747 else if (depths & V_DEPTH_4) 748 defaultDepth = 4; 749 else if (depths & V_DEPTH_1) 750 defaultDepth = 1; 751 752 if (defaultDepth == 24 && !(flags24 & Support32bppFb)) 753 defaultBpp = 24; 754 755 /* Prefer 32bpp because 1999 called and wants its packed pixels back */ 756 if (flags24 & Support32bppFb) 757 flags24 |= SupportConvert24to32 | PreferConvert24to32; 758 if (flags24 & Support24bppFb) 759 flags24 |= SupportConvert32to24; 760 761 if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) { 762 vbeFree(pVesa->pVbe); 763 return (FALSE); 764 } 765 xf86PrintDepthBpp(pScrn); 766 767 /* color weight */ 768 if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) { 769 vbeFree(pVesa->pVbe); 770 return (FALSE); 771 } 772 /* visual init */ 773 if (!xf86SetDefaultVisual(pScrn, -1)) { 774 vbeFree(pVesa->pVbe); 775 return (FALSE); 776 } 777 778 xf86SetGamma(pScrn, gzeros); 779 780 /* set up options before loading any modules that may look at them */ 781 xf86CollectOptions(pScrn, NULL); 782 783 if (pVesa->major >= 2) { 784 /* Load ddc module */ 785 if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { 786 vbeFree(pVesa->pVbe); 787 return (FALSE); 788 } 789 790 if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) { 791 xf86PrintEDID(pVesa->monitor); 792 } 793 794 xf86UnloadSubModule(pDDCModule); 795 } 796 797 if ((pScrn->monitor->DDC = pVesa->monitor) != NULL) 798 xf86SetDDCproperties(pScrn, pVesa->monitor); 799 else { 800 void *panelid = VBEReadPanelID(pVesa->pVbe); 801 VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid); 802 free(panelid); 803 } 804 805 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 806 "Searching for matching VESA mode(s):\n"); 807 808 /* 809 * Check the available BIOS modes, and extract those that match the 810 * requirements into the modePool. Note: modePool is a NULL-terminated 811 * list. 812 */ 813 pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo, 814 V_MODETYPE_VBE); 815 816 xf86ErrorFVerb(DEBUG_VERB, "\n"); 817 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 818 "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory, 819 (vbe->TotalMemory * 65536) / 1024); 820 821 pVesa->mapSize = vbe->TotalMemory * 65536; 822 if (pScrn->modePool == NULL) { 823 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n"); 824 vbeFree(pVesa->pVbe); 825 return (FALSE); 826 } 827 828 VBESetModeNames(pScrn->modePool); 829 830 pVesa->strict_validation = TRUE; 831 i = VESAValidateModes(pScrn); 832 833 if (i <= 0) { 834 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 835 "No valid modes left. Trying less strict filter...\n"); 836 pVesa->strict_validation = FALSE; 837 i = VESAValidateModes(pScrn); 838 } 839 840 if (i <= 0) do { 841 Bool changed = FALSE; 842 /* maybe there's more modes at the bottom... */ 843 if (pScrn->monitor->vrefresh[0].lo > 50) { 844 changed = TRUE; 845 pScrn->monitor->vrefresh[0].lo = 50; 846 } 847 if (pScrn->monitor->hsync[0].lo > 31.5) { 848 changed = TRUE; 849 pScrn->monitor->hsync[0].lo = 31.5; 850 } 851 852 if (!changed) 853 break; 854 855 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 856 "No valid modes left. Trying aggressive sync range...\n"); 857 i = VESAValidateModes(pScrn); 858 } while (0); 859 860 if (i <= 0) { 861 /* alright, i'm out of ideas */ 862 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n"); 863 vbeFree(pVesa->pVbe); 864 return (FALSE); 865 } 866 867 xf86PruneDriverModes(pScrn); 868 869 pMode = pScrn->modes; 870 do { 871 mode = ((VbeModeInfoData*)pMode->Private)->data; 872 if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) { 873 pVesa->maxBytesPerScanline = mode->BytesPerScanline; 874 } 875 pMode = pMode->next; 876 } while (pMode != pScrn->modes); 877 878 pScrn->currentMode = pScrn->modes; 879 pScrn->displayWidth = pScrn->virtualX; 880 881 VBEPrintModes(pScrn); 882 883 /* Set display resolution */ 884 xf86SetDpi(pScrn, 0, 0); 885 886 if (pScrn->modes == NULL) { 887 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); 888 vbeFree(pVesa->pVbe); 889 return (FALSE); 890 } 891 892 /* options */ 893 if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) { 894 vbeFree(pVesa->pVbe); 895 return FALSE; 896 } 897 memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions)); 898 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options); 899 900 /* Use shadow by default, for non-virt hardware */ 901 if (!xf86GetOptValBool(pVesa->Options, OPTION_SHADOW_FB, &pVesa->shadowFB)) 902 { 903 switch (pVesa->pciInfo->vendor_id) { 904 case 0x1234: /* bochs vga (not in pci.ids) */ 905 case 0x15ad: /* vmware */ 906 case 0x1b36: /* qemu qxl */ 907 case 0x80ee: /* virtualbox */ 908 case 0xaaaa: /* parallels (not in pci.ids) */ 909 pVesa->shadowFB = FALSE; 910 break; 911 912 case 0x1013: /* qemu's cirrus emulation */ 913 if (pVesa->pciInfo->subvendor_id == 0x1af4) 914 pVesa->shadowFB = FALSE; 915 else 916 pVesa->shadowFB = TRUE; 917 break; 918 919 case 0x1414: /* microsoft hyper-v */ 920 if (pVesa->pciInfo->device_id == 0x5353) 921 pVesa->shadowFB = FALSE; 922 else 923 pVesa->shadowFB = TRUE; 924 break; 925 926 default: 927 pVesa->shadowFB = TRUE; 928 break; 929 } 930 } 931 932 /* Use default refresh by default. Too many VBE 3.0 933 * BIOSes are incorrectly implemented. 934 */ 935 pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options, 936 OPTION_DFLT_REFRESH, TRUE); 937 938 pVesa->ModeSetClearScreen = 939 xf86ReturnOptValBool(pVesa->Options, 940 OPTION_MODESET_CLEAR_SCREEN, FALSE); 941 942 if (!pVesa->defaultRefresh && !pVesa->strict_validation) 943 VBESetModeParameters(pScrn, pVesa->pVbe); 944 945 mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 946 switch (mode->MemoryModel) { 947 case 0x4: /* Packed pixel */ 948 case 0x6: /* Direct Color */ 949 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER; 950 951 switch (pScrn->bitsPerPixel) { 952 case 8: 953 case 16: 954 case 24: 955 case 32: 956 break; 957 default: 958 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 959 "Unsupported bpp: %d\n", pScrn->bitsPerPixel); 960 vbeFree(pVesa->pVbe); 961 return FALSE; 962 } 963 break; 964 default: 965 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 966 "Unsupported Memory Model: %d\n", mode->MemoryModel); 967 return FALSE; 968 } 969 970 if (pVesa->shadowFB) { 971 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); 972 if (!xf86LoadSubModule(pScrn, "shadow")) { 973 vbeFree(pVesa->pVbe); 974 return (FALSE); 975 } 976 } 977 978 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 979 VESAFreeRec(pScrn); 980 vbeFree(pVesa->pVbe); 981 return (FALSE); 982 } 983 984 vbeFree(pVesa->pVbe); 985 986 return (TRUE); 987} 988 989static Bool 990vesaCreateScreenResources(ScreenPtr pScreen) 991{ 992 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 993 VESAPtr pVesa = VESAGetRec(pScrn); 994 Bool ret; 995 996 pScreen->CreateScreenResources = pVesa->CreateScreenResources; 997 ret = pScreen->CreateScreenResources(pScreen); 998 pScreen->CreateScreenResources = vesaCreateScreenResources; 999 1000 shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update, 1001 pVesa->window, 0, 0); 1002 1003 return ret; 1004} 1005 1006static void 1007vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable) 1008{ 1009 SCRN_INFO_PTR(arg); 1010 VESAPtr pVesa = VESAGetRec(pScrn); 1011 1012 pVesa->accessEnabled = enable; 1013 pVesa->EnableDisableFBAccess(arg, enable); 1014} 1015 1016static Bool 1017VESAScreenInit(SCREEN_INIT_ARGS_DECL) 1018{ 1019 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1020 VESAPtr pVesa = VESAGetRec(pScrn); 1021 VisualPtr visual; 1022 VbeModeInfoBlock *mode; 1023 int flags; 1024 1025 if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 1026 SET_BIOS_SCRATCH 1027 | RESTORE_BIOS_SCRATCH)) == NULL) 1028 return (FALSE); 1029 1030 if (pVesa->mapPhys == 0) { 1031 mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 1032 pScrn->videoRam = pVesa->mapSize; 1033 pVesa->mapPhys = mode->PhysBasePtr; 1034 pVesa->mapOff = 0; 1035 } 1036 1037 if (pVesa->mapPhys == 0) { 1038 pVesa->mapPhys = 0xa0000; 1039 pVesa->mapSize = 0x10000; 1040 } 1041 1042 if (!VESAMapVidMem(pScrn)) { 1043 if (pVesa->mapPhys != 0xa0000) { 1044 pVesa->mapPhys = 0xa0000; 1045 pVesa->mapSize = 0x10000; 1046 if (!VESAMapVidMem(pScrn)) 1047 return (FALSE); 1048 } 1049 else 1050 return (FALSE); 1051 } 1052 1053 /* Set bpp to 8 for depth 4 when using shadowfb. */ 1054 if (pVesa->shadowFB && pScrn->bitsPerPixel == 4) 1055 pScrn->bitsPerPixel = 8; 1056 1057 if (pVesa->shadowFB) { 1058 pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY * 1059 ((pScrn->bitsPerPixel + 7) / 8)); 1060 if (!pVesa->shadow) { 1061 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1062 "Failed to allocate shadow buffer\n"); 1063 return FALSE; 1064 } 1065 } 1066 1067 /* save current video state */ 1068 VESASaveRestore(pScrn, MODE_SAVE); 1069 pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256, 1070 NULL, FALSE, FALSE); 1071 1072 /* set first video mode */ 1073 if (!VESASetMode(pScrn, pScrn->currentMode)) 1074 return (FALSE); 1075 1076 /* set the viewport */ 1077 VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1078 1079 /* Blank the screen for aesthetic reasons. */ 1080 VESASaveScreen(pScreen, SCREEN_SAVER_ON); 1081 1082 /* mi layer */ 1083 miClearVisualTypes(); 1084 if (!xf86SetDefaultVisual(pScrn, -1)) 1085 return (FALSE); 1086 if (pScrn->bitsPerPixel > 8) { 1087 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1088 pScrn->rgbBits, TrueColor)) 1089 return (FALSE); 1090 } 1091 else { 1092 if (!miSetVisualTypes(pScrn->depth, 1093 miGetDefaultVisualMask(pScrn->depth), 1094 pScrn->rgbBits, pScrn->defaultVisual)) 1095 return (FALSE); 1096 } 1097 if (!miSetPixmapDepths()) 1098 return (FALSE); 1099 1100 mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 1101 switch (mode->MemoryModel) { 1102 case 0x4: /* Packed pixel */ 1103 case 0x6: /* Direct Color */ 1104 switch (pScrn->bitsPerPixel) { 1105 case 8: 1106 case 16: 1107 case 24: 1108 case 32: 1109 if (!fbScreenInit(pScreen, 1110 pVesa->shadowFB ? pVesa->shadow : pVesa->base, 1111 pScrn->virtualX, pScrn->virtualY, 1112 pScrn->xDpi, pScrn->yDpi, 1113 pScrn->displayWidth, pScrn->bitsPerPixel)) 1114 return (FALSE); 1115 break; 1116 default: 1117 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1118 "Unsupported bpp: %d", pScrn->bitsPerPixel); 1119 return (FALSE); 1120 } 1121 break; 1122 default: 1123 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1124 "Unsupported Memory Model: %d", mode->MemoryModel); 1125 return (FALSE); 1126 } 1127 1128 1129 if (pScrn->bitsPerPixel > 8) { 1130 /* Fixup RGB ordering */ 1131 visual = pScreen->visuals + pScreen->numVisuals; 1132 while (--visual >= pScreen->visuals) { 1133 if ((visual->class | DynamicClass) == DirectColor) { 1134 visual->offsetRed = pScrn->offset.red; 1135 visual->offsetGreen = pScrn->offset.green; 1136 visual->offsetBlue = pScrn->offset.blue; 1137 visual->redMask = pScrn->mask.red; 1138 visual->greenMask = pScrn->mask.green; 1139 visual->blueMask = pScrn->mask.blue; 1140 } 1141 } 1142 } 1143 1144 /* must be after RGB ordering fixed */ 1145 fbPictureInit(pScreen, 0, 0); 1146 1147 if (pVesa->shadowFB) { 1148 if (pVesa->mapPhys == 0xa0000) { /* Windowed */ 1149 pVesa->update = vesaUpdatePacked; 1150 pVesa->window = VESAWindowWindowed; 1151 } 1152 else { /* Linear */ 1153 pVesa->update = vesaUpdatePacked; 1154 pVesa->window = VESAWindowLinear; 1155 } 1156 1157 if (!shadowSetup(pScreen)) 1158 return FALSE; 1159 pVesa->CreateScreenResources = pScreen->CreateScreenResources; 1160 pScreen->CreateScreenResources = vesaCreateScreenResources; 1161 } 1162 else if (pVesa->mapPhys == 0xa0000) { 1163 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1164 "Banked framebuffer requires ShadowFB\n"); 1165 return FALSE; 1166 } 1167 1168 VESADGAInit(pScrn, pScreen); 1169 1170 xf86SetBlackWhitePixels(pScreen); 1171 xf86SetBackingStore(pScreen); 1172 1173 /* software cursor */ 1174 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1175 1176 /* colormap */ 1177 if (!miCreateDefColormap(pScreen)) 1178 return (FALSE); 1179 1180 flags = CMAP_RELOAD_ON_MODE_SWITCH; 1181 1182 if(!xf86HandleColormaps(pScreen, 256, 1183 pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6, 1184 VESALoadPalette, NULL, flags)) 1185 return (FALSE); 1186 1187 pVesa->accessEnabled = TRUE; 1188 pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; 1189 pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess; 1190 1191 pVesa->CloseScreen = pScreen->CloseScreen; 1192 pScreen->CloseScreen = VESACloseScreen; 1193 pScreen->SaveScreen = VESASaveScreen; 1194 1195 xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0); 1196 1197 /* Report any unused options (only for the first generation) */ 1198 if (serverGeneration == 1) 1199 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1200 1201 return (TRUE); 1202} 1203 1204static Bool 1205VESAEnterVT(VT_FUNC_ARGS_DECL) 1206{ 1207 SCRN_INFO_PTR(arg); 1208 1209 if (!VESASetMode(pScrn, pScrn->currentMode)) 1210 return FALSE; 1211 VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1212 return TRUE; 1213} 1214 1215static void 1216VESALeaveVT(VT_FUNC_ARGS_DECL) 1217{ 1218 SCRN_INFO_PTR(arg); 1219 VESASaveRestore(pScrn, MODE_RESTORE); 1220} 1221 1222static Bool 1223VESACloseScreen(CLOSE_SCREEN_ARGS_DECL) 1224{ 1225 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1226 VESAPtr pVesa = VESAGetRec(pScrn); 1227 1228 if (pScrn->vtSema) { 1229 VESASaveRestore(pScrn, MODE_RESTORE); 1230 if (pVesa->savedPal) 1231 VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256, 1232 pVesa->savedPal, FALSE, TRUE); 1233 VESAUnmapVidMem(pScrn); 1234 } 1235 if (pVesa->shadowFB && pVesa->shadow) { 1236 shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); 1237 free(pVesa->shadow); 1238 } 1239 if (pVesa->pDGAMode) { 1240 free(pVesa->pDGAMode); 1241 pVesa->pDGAMode = NULL; 1242 pVesa->nDGAMode = 0; 1243 } 1244 pScrn->vtSema = FALSE; 1245 1246 pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess; 1247 pScreen->CreateScreenResources = pVesa->CreateScreenResources; 1248 pScreen->CloseScreen = pVesa->CloseScreen; 1249 return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); 1250} 1251 1252static Bool 1253VESASwitchMode(SWITCH_MODE_ARGS_DECL) 1254{ 1255 SCRN_INFO_PTR(arg); 1256 VESAPtr pVesa = VESAGetRec(pScrn); 1257 Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled; 1258 1259 if (disableAccess) 1260 pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE); 1261 ret = VESASetMode(pScrn, mode); 1262 if (disableAccess) 1263 pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE); 1264 return ret; 1265} 1266 1267/* Set a graphics mode */ 1268static Bool 1269VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 1270{ 1271 VESAPtr pVesa; 1272 VbeModeInfoData *data; 1273 int mode; 1274 1275 pVesa = VESAGetRec(pScrn); 1276 1277 data = (VbeModeInfoData*)pMode->Private; 1278 1279 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1280 "Setting up VESA Mode 0x%X (%dx%d)\n", 1281 data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay); 1282 1283 /* careful, setting the bit means don't clear the screen */ 1284 mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15)); 1285 1286 /* enable linear addressing */ 1287 if (pVesa->mapPhys != 0xa0000) 1288 mode |= 1 << 14; 1289 1290 if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) { 1291 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed"); 1292 if ((data->block || (data->mode & (1 << 11))) && 1293 VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) { 1294 /* Some cards do not like setting the clock. 1295 * Free it as it will not be any longer useful 1296 */ 1297 xf86ErrorF(", mode set without customized refresh.\n"); 1298 free(data->block); 1299 data->block = NULL; 1300 data->mode &= ~(1 << 11); 1301 } 1302 else { 1303 ErrorF("\n"); 1304 return (FALSE); 1305 } 1306 } 1307 1308 pVesa->bankSwitchWindowB = 1309 !((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0)); 1310 1311 if (data->data->XResolution != pScrn->displayWidth) 1312 VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth); 1313 1314 if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 && 1315 !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7)) 1316 VBESetGetDACPaletteFormat(pVesa->pVbe, 8); 1317 1318 pScrn->vtSema = TRUE; 1319 1320 return (TRUE); 1321} 1322 1323static void 1324VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL) 1325{ 1326 SCRN_INFO_PTR(arg); 1327 VESAPtr pVesa = VESAGetRec(pScrn); 1328 1329 VBESetDisplayStart(pVesa->pVbe, x, y, TRUE); 1330} 1331 1332static void 1333VESAFreeScreen(FREE_SCREEN_ARGS_DECL) 1334{ 1335 SCRN_INFO_PTR(arg); 1336 VESAFreeRec(pScrn); 1337} 1338 1339static Bool 1340VESAMapVidMem(ScrnInfoPtr pScrn) 1341{ 1342 VESAPtr pVesa = VESAGetRec(pScrn); 1343 1344 if (pVesa->base != NULL) 1345 return (TRUE); 1346 1347 pScrn->memPhysBase = pVesa->mapPhys; 1348 pScrn->fbOffset = pVesa->mapOff; 1349 1350#ifdef XSERVER_LIBPCIACCESS 1351 if (pVesa->pciInfo != NULL) { 1352 if (pVesa->mapPhys != 0xa0000) { 1353 (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase, 1354 pVesa->mapSize, 1355 (PCI_DEV_MAP_FLAG_WRITABLE 1356 | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 1357 & pVesa->base); 1358 1359 if (pVesa->base) 1360 (void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000, 1361 PCI_DEV_MAP_FLAG_WRITABLE, 1362 & pVesa->VGAbase); 1363 } 1364 else { 1365 (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase, 1366 pVesa->mapSize, 1367 PCI_DEV_MAP_FLAG_WRITABLE, 1368 & pVesa->base); 1369 1370 if (pVesa->base) 1371 pVesa->VGAbase = pVesa->base; 1372 } 1373 } 1374#else 1375 if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI) 1376 pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1377 pVesa->pciTag, pScrn->memPhysBase, 1378 pVesa->mapSize); 1379 else 1380 pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag, 1381 pScrn->memPhysBase, pVesa->mapSize); 1382 1383 if (pVesa->base) { 1384 if (pVesa->mapPhys != 0xa0000) 1385 pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0, 1386 pVesa->pciTag, 1387 0xa0000, 0x10000); 1388 else 1389 pVesa->VGAbase = pVesa->base; 1390 } 1391#endif 1392 1393#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 1394 pVesa->ioBase = pScrn->domainIOBase; 1395#else 1396 pVesa->ioBase = 0; 1397#endif 1398 1399 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 1400 "virtual address = %p, VGAbase = %p\n" 1401 "\tphysical address = 0x%lx, size = %ld\n", 1402 pVesa->base, pVesa->VGAbase, 1403 pScrn->memPhysBase, pVesa->mapSize); 1404 1405 return (pVesa->base != NULL); 1406} 1407 1408static void 1409VESAUnmapVidMem(ScrnInfoPtr pScrn) 1410{ 1411 VESAPtr pVesa = VESAGetRec(pScrn); 1412 1413 if (pVesa->base == NULL) 1414 return; 1415 1416#ifdef XSERVER_LIBPCIACCESS 1417 if (pVesa->mapPhys != 0xa0000) { 1418 (void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base, 1419 pVesa->mapSize); 1420 (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase, 1421 0x10000); 1422 } 1423 else { 1424 (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base, 1425 pVesa->mapSize); 1426 } 1427#else 1428 xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize); 1429 if (pVesa->mapPhys != 0xa0000) 1430 xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000); 1431#endif 1432 pVesa->base = NULL; 1433} 1434 1435/* This code works, but is very slow for programs that use it intensively */ 1436static void 1437VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 1438 LOCO *colors, VisualPtr pVisual) 1439{ 1440 VESAPtr pVesa = VESAGetRec(pScrn); 1441 int i, idx; 1442 int base; 1443 1444 if (!pVesa->savedPal) { 1445#define VESADACDelay() \ 1446 do { \ 1447 (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1448 (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1449 } while (0) 1450 1451 for (i = 0; i < numColors; i++) { 1452 idx = indices[i]; 1453 outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx); 1454 VESADACDelay(); 1455 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red); 1456 VESADACDelay(); 1457 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green); 1458 VESADACDelay(); 1459 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue); 1460 VESADACDelay(); 1461 } 1462 return; 1463 } 1464 1465 if (pVesa->pal == NULL) 1466 pVesa->pal = calloc(1, sizeof(CARD32) * 256); 1467 1468 for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) { 1469 int j = indices[i]; 1470 1471 if (j < 0 || j >= 256) 1472 continue; 1473 pVesa->pal[j] = colors[j].blue | 1474 (colors[j].green << 8) | 1475 (colors[j].red << 16); 1476 if (j != idx) { 1477 VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 1478 pVesa->pal + base, FALSE, TRUE); 1479 idx = base = j; 1480 } 1481 } 1482 1483 if (idx - 1 == indices[i - 1]) 1484 VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 1485 pVesa->pal + base, FALSE, TRUE); 1486} 1487 1488/* 1489 * Just adapted from the std* functions in vgaHW.c 1490 */ 1491static void 1492WriteAttr(VESAPtr pVesa, int index, int value) 1493{ 1494 (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 1495 1496 index |= 0x20; 1497 outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 1498 outb(pVesa->ioBase + VGA_ATTR_DATA_W, value); 1499} 1500 1501static int 1502ReadAttr(VESAPtr pVesa, int index) 1503{ 1504 (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 1505 1506 index |= 0x20; 1507 outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 1508 return (inb(pVesa->ioBase + VGA_ATTR_DATA_R)); 1509} 1510 1511#define WriteMiscOut(value) outb(pVesa->ioBase + VGA_MISC_OUT_W, value) 1512#define ReadMiscOut() inb(pVesa->ioBase + VGA_MISC_OUT_R) 1513#define WriteSeq(index, value) outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\ 1514 outb(pVesa->ioBase + VGA_SEQ_DATA, value) 1515 1516static int 1517ReadSeq(VESAPtr pVesa, int index) 1518{ 1519 outb(pVesa->ioBase + VGA_SEQ_INDEX, index); 1520 1521 return (inb(pVesa->ioBase + VGA_SEQ_DATA)); 1522} 1523 1524#define WriteGr(index, value) \ 1525 outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); \ 1526 outb(pVesa->ioBase + VGA_GRAPH_DATA, value) 1527 1528static int 1529ReadGr(VESAPtr pVesa, int index) 1530{ 1531 outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); 1532 1533 return (inb(pVesa->ioBase + VGA_GRAPH_DATA)); 1534} 1535 1536#define WriteCrtc(index, value) \ 1537 outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \ 1538 outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value) 1539 1540static void 1541SeqReset(VESAPtr pVesa, Bool start) 1542{ 1543 if (start) { 1544 WriteSeq(0x00, 0x01); /* Synchronous Reset */ 1545 } 1546 else { 1547 WriteSeq(0x00, 0x03); /* End Reset */ 1548 } 1549} 1550 1551static void 1552SaveFonts(ScrnInfoPtr pScrn) 1553{ 1554 VESAPtr pVesa = VESAGetRec(pScrn); 1555 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 1556 1557 if (pVesa->fonts != NULL) 1558 return; 1559 1560 /* If in graphics mode, don't save anything */ 1561 attr10 = ReadAttr(pVesa, 0x10); 1562 if (attr10 & 0x01) 1563 return; 1564 1565 pVesa->fonts = malloc(16384); 1566 1567 /* save the registers that are needed here */ 1568 miscOut = ReadMiscOut(); 1569 gr4 = ReadGr(pVesa, 0x04); 1570 gr5 = ReadGr(pVesa, 0x05); 1571 gr6 = ReadGr(pVesa, 0x06); 1572 seq2 = ReadSeq(pVesa, 0x02); 1573 seq4 = ReadSeq(pVesa, 0x04); 1574 1575 /* Force into colour mode */ 1576 WriteMiscOut(miscOut | 0x01); 1577 1578 scrn = ReadSeq(pVesa, 0x01) | 0x20; 1579 SeqReset(pVesa, TRUE); 1580 WriteSeq(0x01, scrn); 1581 SeqReset(pVesa, FALSE); 1582 1583 WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 1584 1585 /*font1 */ 1586 WriteSeq(0x02, 0x04); /* write to plane 2 */ 1587 WriteSeq(0x04, 0x06); /* enable plane graphics */ 1588 WriteGr(0x04, 0x02); /* read plane 2 */ 1589 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 1590 WriteGr(0x06, 0x05); /* set graphics */ 1591 slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192); 1592 1593 /* font2 */ 1594 WriteSeq(0x02, 0x08); /* write to plane 3 */ 1595 WriteSeq(0x04, 0x06); /* enable plane graphics */ 1596 WriteGr(0x04, 0x03); /* read plane 3 */ 1597 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 1598 WriteGr(0x06, 0x05); /* set graphics */ 1599 slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192); 1600 1601 scrn = ReadSeq(pVesa, 0x01) & ~0x20; 1602 SeqReset(pVesa, TRUE); 1603 WriteSeq(0x01, scrn); 1604 SeqReset(pVesa, FALSE); 1605 1606 /* Restore clobbered registers */ 1607 WriteAttr(pVesa, 0x10, attr10); 1608 WriteSeq(0x02, seq2); 1609 WriteSeq(0x04, seq4); 1610 WriteGr(0x04, gr4); 1611 WriteGr(0x05, gr5); 1612 WriteGr(0x06, gr6); 1613 WriteMiscOut(miscOut); 1614} 1615 1616static void 1617RestoreFonts(ScrnInfoPtr pScrn) 1618{ 1619 VESAPtr pVesa = VESAGetRec(pScrn); 1620 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 1621 1622 if (pVesa->fonts == NULL) 1623 return; 1624 1625 if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0) 1626 VESABankSwitch(pScrn->pScreen, 0); 1627 1628 /* save the registers that are needed here */ 1629 miscOut = ReadMiscOut(); 1630 attr10 = ReadAttr(pVesa, 0x10); 1631 gr1 = ReadGr(pVesa, 0x01); 1632 gr3 = ReadGr(pVesa, 0x03); 1633 gr4 = ReadGr(pVesa, 0x04); 1634 gr5 = ReadGr(pVesa, 0x05); 1635 gr6 = ReadGr(pVesa, 0x06); 1636 gr8 = ReadGr(pVesa, 0x08); 1637 seq2 = ReadSeq(pVesa, 0x02); 1638 seq4 = ReadSeq(pVesa, 0x04); 1639 1640 /* Force into colour mode */ 1641 WriteMiscOut(miscOut | 0x01); 1642 1643 scrn = ReadSeq(pVesa, 0x01) | 0x20; 1644 SeqReset(pVesa, TRUE); 1645 WriteSeq(0x01, scrn); 1646 SeqReset(pVesa, FALSE); 1647 1648 WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 1649 if (pScrn->depth == 4) { 1650 /* GJA */ 1651 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */ 1652 WriteGr(0x08, 0xFF); /* write all bits in a byte */ 1653 WriteGr(0x01, 0x00); /* all planes come from CPU */ 1654 } 1655 1656 WriteSeq(0x02, 0x04); /* write to plane 2 */ 1657 WriteSeq(0x04, 0x06); /* enable plane graphics */ 1658 WriteGr(0x04, 0x02); /* read plane 2 */ 1659 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 1660 WriteGr(0x06, 0x05); /* set graphics */ 1661 slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192); 1662 1663 WriteSeq(0x02, 0x08); /* write to plane 3 */ 1664 WriteSeq(0x04, 0x06); /* enable plane graphics */ 1665 WriteGr(0x04, 0x03); /* read plane 3 */ 1666 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 1667 WriteGr(0x06, 0x05); /* set graphics */ 1668 slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192); 1669 1670 scrn = ReadSeq(pVesa, 0x01) & ~0x20; 1671 SeqReset(pVesa, TRUE); 1672 WriteSeq(0x01, scrn); 1673 SeqReset(pVesa, FALSE); 1674 1675 /* restore the registers that were changed */ 1676 WriteMiscOut(miscOut); 1677 WriteAttr(pVesa, 0x10, attr10); 1678 WriteGr(0x01, gr1); 1679 WriteGr(0x03, gr3); 1680 WriteGr(0x04, gr4); 1681 WriteGr(0x05, gr5); 1682 WriteGr(0x06, gr6); 1683 WriteGr(0x08, gr8); 1684 WriteSeq(0x02, seq2); 1685 WriteSeq(0x04, seq4); 1686} 1687 1688static Bool 1689VESASaveScreen(ScreenPtr pScreen, int mode) 1690{ 1691 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1692 VESAPtr pVesa = VESAGetRec(pScrn); 1693 Bool on = xf86IsUnblank(mode); 1694 1695 if (on) 1696 SetTimeSinceLastInputEvent(); 1697 1698 if (pScrn->vtSema) { 1699 unsigned char scrn = ReadSeq(pVesa, 0x01); 1700 1701 if (on) 1702 scrn &= ~0x20; 1703 else 1704 scrn |= 0x20; 1705 SeqReset(pVesa, TRUE); 1706 WriteSeq(0x01, scrn); 1707 SeqReset(pVesa, FALSE); 1708 } 1709 1710 return (TRUE); 1711} 1712 1713static int 1714VESABankSwitch(ScreenPtr pScreen, unsigned int iBank) 1715{ 1716 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1717 VESAPtr pVesa = VESAGetRec(pScrn); 1718 1719 if (pVesa->curBank == iBank) 1720 return (0); 1721 if (!VBEBankSwitch(pVesa->pVbe, iBank, 0)) 1722 return (1); 1723 if (pVesa->bankSwitchWindowB) { 1724 if (!VBEBankSwitch(pVesa->pVbe, iBank, 1)) 1725 return (1); 1726 } 1727 pVesa->curBank = iBank; 1728 1729 return (0); 1730} 1731 1732Bool 1733VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 1734{ 1735 VESAPtr pVesa; 1736 1737 if (function < MODE_QUERY || function > MODE_RESTORE) 1738 return (FALSE); 1739 1740 pVesa = VESAGetRec(pScrn); 1741 1742 1743 /* Query amount of memory to save state */ 1744 if (function == MODE_QUERY || 1745 (function == MODE_SAVE && pVesa->state == NULL)) { 1746 1747 /* Make sure we save at least this information in case of failure */ 1748 (void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode); 1749 SaveFonts(pScrn); 1750 1751 if (pVesa->major > 1) { 1752 if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state, 1753 &pVesa->stateSize,&pVesa->statePage)) 1754 return FALSE; 1755 1756 } 1757 } 1758 1759 /* Save/Restore Super VGA state */ 1760 if (function != MODE_QUERY) { 1761 Bool retval = TRUE; 1762 1763 if (pVesa->major > 1) { 1764 if (function == MODE_RESTORE) 1765 memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize); 1766 1767 if ((retval = VBESaveRestore(pVesa->pVbe,function, 1768 (pointer)&pVesa->state, 1769 &pVesa->stateSize,&pVesa->statePage)) 1770 && function == MODE_SAVE) { 1771 /* don't rely on the memory not being touched */ 1772 if (pVesa->pstate == NULL) 1773 pVesa->pstate = malloc(pVesa->stateSize); 1774 memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize); 1775 } 1776 } 1777 1778 if (function == MODE_RESTORE) { 1779 VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL); 1780 RestoreFonts(pScrn); 1781 } 1782 1783 if (!retval) 1784 return (FALSE); 1785 1786 } 1787 1788 return (TRUE); 1789} 1790 1791static void 1792VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 1793 int flags) 1794{ 1795 VESAPtr pVesa = VESAGetRec(pScrn); 1796 1797 if (!pScrn->vtSema) 1798 return; 1799 1800 VBEDPMSSet(pVesa->pVbe, mode); 1801} 1802 1803/*********************************************************************** 1804 * DGA stuff 1805 ***********************************************************************/ 1806static Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 1807 unsigned char **ApertureBase, 1808 int *ApertureSize, int *ApertureOffset, 1809 int *flags); 1810static Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode); 1811static void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 1812 1813static Bool 1814VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 1815 unsigned char **ApertureBase, int *ApertureSize, 1816 int *ApertureOffset, int *flags) 1817{ 1818 VESAPtr pVesa = VESAGetRec(pScrn); 1819 1820 *DeviceName = NULL; /* No special device */ 1821 *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys); 1822 *ApertureSize = pVesa->mapSize; 1823 *ApertureOffset = pVesa->mapOff; 1824 *flags = DGA_NEED_ROOT; 1825 1826 return (TRUE); 1827} 1828 1829static Bool 1830VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 1831{ 1832 DisplayModePtr pMode; 1833 int frameX0, frameY0; 1834 1835 if (pDGAMode) { 1836 pMode = pDGAMode->mode; 1837 frameX0 = frameY0 = 0; 1838 } 1839 else { 1840 if (!(pMode = pScrn->currentMode)) 1841 return (TRUE); 1842 1843 frameX0 = pScrn->frameX0; 1844 frameY0 = pScrn->frameY0; 1845 } 1846 1847 if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 1848 return (FALSE); 1849 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 1850 1851 return (TRUE); 1852} 1853 1854static void 1855VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 1856{ 1857 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 1858} 1859 1860static int 1861VESADGAGetViewport(ScrnInfoPtr pScrn) 1862{ 1863 return (0); 1864} 1865 1866static DGAFunctionRec VESADGAFunctions = 1867{ 1868 VESADGAOpenFramebuffer, 1869 NULL, /* CloseFramebuffer */ 1870 VESADGASetMode, 1871 VESADGASetViewport, 1872 VESADGAGetViewport, 1873 NULL, /* Sync */ 1874 NULL, /* FillRect */ 1875 NULL, /* BlitRect */ 1876 NULL, /* BlitTransRect */ 1877}; 1878 1879static void 1880VESADGAAddModes(ScrnInfoPtr pScrn) 1881{ 1882 VESAPtr pVesa = VESAGetRec(pScrn); 1883 DisplayModePtr pMode = pScrn->modes; 1884 DGAModePtr pDGAMode; 1885 1886 do { 1887 pDGAMode = realloc(pVesa->pDGAMode, 1888 (pVesa->nDGAMode + 1) * sizeof(DGAModeRec)); 1889 if (!pDGAMode) 1890 break; 1891 1892 pVesa->pDGAMode = pDGAMode; 1893 pDGAMode += pVesa->nDGAMode; 1894 (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 1895 1896 ++pVesa->nDGAMode; 1897 pDGAMode->mode = pMode; 1898 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 1899 pDGAMode->byteOrder = pScrn->imageByteOrder; 1900 pDGAMode->depth = pScrn->depth; 1901 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 1902 pDGAMode->red_mask = pScrn->mask.red; 1903 pDGAMode->green_mask = pScrn->mask.green; 1904 pDGAMode->blue_mask = pScrn->mask.blue; 1905 pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 1906 TrueColor : PseudoColor; 1907 pDGAMode->xViewportStep = 1; 1908 pDGAMode->yViewportStep = 1; 1909 pDGAMode->viewportWidth = pMode->HDisplay; 1910 pDGAMode->viewportHeight = pMode->VDisplay; 1911 1912 pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline; 1913 pDGAMode->imageWidth = pMode->HDisplay; 1914 pDGAMode->imageHeight = pMode->VDisplay; 1915 pDGAMode->pixmapWidth = pDGAMode->imageWidth; 1916 pDGAMode->pixmapHeight = pDGAMode->imageHeight; 1917 pDGAMode->maxViewportX = pScrn->virtualX - 1918 pDGAMode->viewportWidth; 1919 pDGAMode->maxViewportY = pScrn->virtualY - 1920 pDGAMode->viewportHeight; 1921 1922 pDGAMode->address = pVesa->base; 1923 1924 pMode = pMode->next; 1925 } while (pMode != pScrn->modes); 1926} 1927 1928static Bool 1929VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 1930{ 1931 VESAPtr pVesa = VESAGetRec(pScrn); 1932 1933 if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L) 1934 return (FALSE); 1935 1936 if (!pVesa->nDGAMode) 1937 VESADGAAddModes(pScrn); 1938 1939 return (DGAInit(pScreen, &VESADGAFunctions, 1940 pVesa->pDGAMode, pVesa->nDGAMode)); 1941} 1942