vesa.c revision b40a6198
145bc899bSmrg#define DEBUG_VERB 2 245bc899bSmrg/* 345bc899bSmrg * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) 450f2e948Smrg * Copyright 2008 Red Hat, Inc. 545bc899bSmrg * 645bc899bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 745bc899bSmrg * copy of this software and associated documentation files (the "Software"), 845bc899bSmrg * to deal in the Software without restriction, including without limitation 945bc899bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1045bc899bSmrg * and/or sell copies of the Software, and to permit persons to whom the 1145bc899bSmrg * Software is furnished to do so, subject to the following conditions: 1245bc899bSmrg * 1345bc899bSmrg * The above copyright notice and this permission notice shall be included in 1445bc899bSmrg * all copies or substantial portions of the Software. 1545bc899bSmrg * 1645bc899bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1745bc899bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1845bc899bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1945bc899bSmrg * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 2045bc899bSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 2145bc899bSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2245bc899bSmrg * SOFTWARE. 2345bc899bSmrg * 2445bc899bSmrg * Except as contained in this notice, the name of Conectiva Linux shall 2545bc899bSmrg * not be used in advertising or otherwise to promote the sale, use or other 2645bc899bSmrg * dealings in this Software without prior written authorization from 2745bc899bSmrg * Conectiva Linux. 2845bc899bSmrg * 2945bc899bSmrg * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> 3045bc899bSmrg * David Dawes <dawes@xfree86.org> 3150f2e948Smrg * Adam Jackson <ajax@redhat.com> 3250f2e948Smrg */ 3350f2e948Smrg 3450f2e948Smrg/* 3550f2e948Smrg * TODO: 3650f2e948Smrg * - Port to RANDR 1.2 setup to make mode selection slightly better 3750f2e948Smrg * - Port to RANDR 1.2 to drop the old-school DGA junk 3850f2e948Smrg * - VBE/SCI for secondary DDC method? 3945bc899bSmrg */ 4045bc899bSmrg 4145bc899bSmrg#ifdef HAVE_CONFIG_H 4245bc899bSmrg#include "config.h" 4345bc899bSmrg#endif 4445bc899bSmrg 4545bc899bSmrg#include <string.h> 4645bc899bSmrg 4745bc899bSmrg#include "vesa.h" 4845bc899bSmrg 4945bc899bSmrg/* All drivers initialising the SW cursor need this */ 5045bc899bSmrg#include "mipointer.h" 5145bc899bSmrg 5245bc899bSmrg/* All drivers implementing backing store need this */ 5345bc899bSmrg#include "mibstore.h" 5445bc899bSmrg 5545bc899bSmrg/* Colormap handling */ 5645bc899bSmrg#include "micmap.h" 5745bc899bSmrg#include "xf86cmap.h" 5850f2e948Smrg#include "xf86Modes.h" 5945bc899bSmrg 6045bc899bSmrg/* DPMS */ 613a925b30Smrg#ifdef HAVE_XEXTPROTO_71 623a925b30Smrg#include <X11/extensions/dpmsconst.h> 633a925b30Smrg#else 6445bc899bSmrg#define DPMS_SERVER 6545bc899bSmrg#include <X11/extensions/dpms.h> 663a925b30Smrg#endif 67b40a6198Smrg#include "compat-api.h" 6845bc899bSmrg 6945bc899bSmrg/* Mandatory functions */ 7045bc899bSmrgstatic const OptionInfoRec * VESAAvailableOptions(int chipid, int busid); 7145bc899bSmrgstatic void VESAIdentify(int flags); 7245bc899bSmrgstatic Bool VESAProbe(DriverPtr drv, int flags); 7350f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 7450f2e948Smrgstatic Bool VESAPciProbe(DriverPtr drv, int entity_num, 7550f2e948Smrg struct pci_device *dev, intptr_t match_data); 7650f2e948Smrg#endif 7745bc899bSmrgstatic Bool VESAPreInit(ScrnInfoPtr pScrn, int flags); 78b40a6198Smrgstatic Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL); 79b40a6198Smrgstatic Bool VESAEnterVT(VT_FUNC_ARGS_DECL); 80b40a6198Smrgstatic void VESALeaveVT(VT_FUNC_ARGS_DECL); 81b40a6198Smrgstatic Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL); 8245bc899bSmrgstatic Bool VESASaveScreen(ScreenPtr pScreen, int mode); 8345bc899bSmrg 84b40a6198Smrgstatic Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL); 8545bc899bSmrgstatic Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); 86b40a6198Smrgstatic void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL); 87b40a6198Smrgstatic void VESAFreeScreen(FREE_SCREEN_ARGS_DECL); 8845bc899bSmrgstatic void VESAFreeRec(ScrnInfoPtr pScrn); 8950f2e948Smrgstatic VESAPtr VESAGetRec(ScrnInfoPtr pScrn); 9045bc899bSmrg 9145bc899bSmrgstatic void 9245bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 9345bc899bSmrg int flags); 9445bc899bSmrg 9545bc899bSmrg/* locally used functions */ 965592a31fSmrg#ifdef HAVE_ISA 9745bc899bSmrgstatic int VESAFindIsaDevice(GDevPtr dev); 985592a31fSmrg#endif 9945bc899bSmrgstatic Bool VESAMapVidMem(ScrnInfoPtr pScrn); 10045bc899bSmrgstatic void VESAUnmapVidMem(ScrnInfoPtr pScrn); 10145bc899bSmrgstatic int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank); 10245bc899bSmrgstatic void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 10345bc899bSmrg LOCO *colors, VisualPtr pVisual); 10445bc899bSmrgstatic void SaveFonts(ScrnInfoPtr pScrn); 10545bc899bSmrgstatic void RestoreFonts(ScrnInfoPtr pScrn); 10645bc899bSmrgstatic Bool 10745bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); 10845bc899bSmrg 1095592a31fSmrgstatic void * 1105592a31fSmrgVESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1115592a31fSmrg CARD32 *size, void *closure) 1125592a31fSmrg{ 113b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1145592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1155592a31fSmrg 1165592a31fSmrg *size = pVesa->maxBytesPerScanline; 1175592a31fSmrg return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset); 1185592a31fSmrg} 1195592a31fSmrg 1205592a31fSmrgstatic void * 1215592a31fSmrgVESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1225592a31fSmrg CARD32 *size, void *closure) 1235592a31fSmrg{ 124b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1255592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1265592a31fSmrg VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 1275592a31fSmrg int window; 1285592a31fSmrg 1295592a31fSmrg offset += pVesa->maxBytesPerScanline * row; 1305592a31fSmrg window = offset / (data->WinGranularity * 1024); 1315592a31fSmrg pVesa->windowAoffset = window * data->WinGranularity * 1024; 1325592a31fSmrg VESABankSwitch(pScreen, window); 1335592a31fSmrg *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset); 1345592a31fSmrg 1355592a31fSmrg return (void *)((unsigned long)pVesa->base + 1365592a31fSmrg (offset - pVesa->windowAoffset)); 1375592a31fSmrg} 1385592a31fSmrg 1395592a31fSmrgstatic void 1405592a31fSmrgvesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 1415592a31fSmrg{ 1425592a31fSmrg shadowUpdatePacked(pScreen, pBuf); 1435592a31fSmrg} 14445bc899bSmrg 14545bc899bSmrgstatic Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen); 14645bc899bSmrg 14745bc899bSmrgenum GenericTypes 14845bc899bSmrg{ 14945bc899bSmrg CHIP_VESA_GENERIC 15045bc899bSmrg}; 15145bc899bSmrg 15250f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 15350f2e948Smrgstatic const struct pci_id_match vesa_device_match[] = { 15450f2e948Smrg { 15550f2e948Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 15650f2e948Smrg 0x00030000, 0x00ffffff, CHIP_VESA_GENERIC 15750f2e948Smrg }, 15850f2e948Smrg 15950f2e948Smrg { 0, 0, 0 }, 16050f2e948Smrg}; 16150f2e948Smrg#endif 16250f2e948Smrg 16345bc899bSmrg/* Supported chipsets */ 16445bc899bSmrgstatic SymTabRec VESAChipsets[] = 16545bc899bSmrg{ 16645bc899bSmrg {CHIP_VESA_GENERIC, "vesa"}, 16745bc899bSmrg {-1, NULL} 16845bc899bSmrg}; 16945bc899bSmrg 17050f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 17145bc899bSmrgstatic PciChipsets VESAPCIchipsets[] = { 17245bc899bSmrg { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA }, 17345bc899bSmrg { -1, -1, RES_UNDEFINED }, 17445bc899bSmrg}; 17550f2e948Smrg#endif 17645bc899bSmrg 17750f2e948Smrg#ifdef HAVE_ISA 17845bc899bSmrgstatic IsaChipsets VESAISAchipsets[] = { 17945bc899bSmrg {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA}, 18045bc899bSmrg {-1, 0 } 18145bc899bSmrg}; 18250f2e948Smrg#endif 18350f2e948Smrg 18450f2e948Smrg 18550f2e948Smrg/* 18650f2e948Smrg * This contains the functions needed by the server after loading the 18750f2e948Smrg * driver module. It must be supplied, and gets added the driver list by 18850f2e948Smrg * the Module Setup funtion in the dynamic case. In the static case a 18950f2e948Smrg * reference to this is compiled in, and this requires that the name of 19050f2e948Smrg * this DriverRec be an upper-case version of the driver name. 19150f2e948Smrg */ 19250f2e948Smrg_X_EXPORT DriverRec VESA = { 19350f2e948Smrg VESA_VERSION, 19450f2e948Smrg VESA_DRIVER_NAME, 19550f2e948Smrg VESAIdentify, 19650f2e948Smrg VESAProbe, 19750f2e948Smrg VESAAvailableOptions, 19850f2e948Smrg NULL, 19950f2e948Smrg 0, 20050f2e948Smrg NULL, 20150f2e948Smrg 20250f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 20350f2e948Smrg vesa_device_match, 20450f2e948Smrg VESAPciProbe 20550f2e948Smrg#endif 20650f2e948Smrg}; 20750f2e948Smrg 20845bc899bSmrg 20945bc899bSmrgtypedef enum { 21045bc899bSmrg OPTION_SHADOW_FB, 21145bc899bSmrg OPTION_DFLT_REFRESH, 21245bc899bSmrg OPTION_MODESET_CLEAR_SCREEN 21345bc899bSmrg} VESAOpts; 21445bc899bSmrg 21545bc899bSmrgstatic const OptionInfoRec VESAOptions[] = { 21645bc899bSmrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 21745bc899bSmrg { OPTION_DFLT_REFRESH, "DefaultRefresh", OPTV_BOOLEAN, {0}, FALSE }, 21845bc899bSmrg { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen", 21945bc899bSmrg OPTV_BOOLEAN, {0}, FALSE }, 22045bc899bSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 22145bc899bSmrg}; 22245bc899bSmrg 22345bc899bSmrg#ifdef XFree86LOADER 22445bc899bSmrg 22545bc899bSmrg/* Module loader interface */ 22645bc899bSmrgstatic MODULESETUPPROTO(vesaSetup); 22745bc899bSmrg 22845bc899bSmrgstatic XF86ModuleVersionInfo vesaVersionRec = 22945bc899bSmrg{ 23045bc899bSmrg VESA_DRIVER_NAME, 23145bc899bSmrg MODULEVENDORSTRING, 23245bc899bSmrg MODINFOSTRING1, 23345bc899bSmrg MODINFOSTRING2, 23445bc899bSmrg XORG_VERSION_CURRENT, 23545bc899bSmrg VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL, 23645bc899bSmrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 23745bc899bSmrg ABI_VIDEODRV_VERSION, 23845bc899bSmrg MOD_CLASS_VIDEODRV, 23945bc899bSmrg {0, 0, 0, 0} 24045bc899bSmrg}; 24145bc899bSmrg 24245bc899bSmrg/* 24345bc899bSmrg * This data is accessed by the loader. The name must be the module name 24445bc899bSmrg * followed by "ModuleData". 24545bc899bSmrg */ 24645bc899bSmrg_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL }; 24745bc899bSmrg 24845bc899bSmrgstatic pointer 24945bc899bSmrgvesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) 25045bc899bSmrg{ 25145bc899bSmrg static Bool Initialised = FALSE; 25245bc899bSmrg 25345bc899bSmrg if (!Initialised) 25445bc899bSmrg { 25545bc899bSmrg Initialised = TRUE; 25650f2e948Smrg xf86AddDriver(&VESA, Module, 1); 25745bc899bSmrg return (pointer)TRUE; 25845bc899bSmrg } 25945bc899bSmrg 26045bc899bSmrg if (ErrorMajor) 26145bc899bSmrg *ErrorMajor = LDR_ONCEONLY; 26245bc899bSmrg return (NULL); 26345bc899bSmrg} 26445bc899bSmrg 26545bc899bSmrg#endif 26645bc899bSmrg 26745bc899bSmrgstatic const OptionInfoRec * 26845bc899bSmrgVESAAvailableOptions(int chipid, int busid) 26945bc899bSmrg{ 27045bc899bSmrg return (VESAOptions); 27145bc899bSmrg} 27245bc899bSmrg 27345bc899bSmrgstatic void 27445bc899bSmrgVESAIdentify(int flags) 27545bc899bSmrg{ 27645bc899bSmrg xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets); 27745bc899bSmrg} 27845bc899bSmrg 27950f2e948Smrgstatic VESAPtr 28050f2e948SmrgVESAGetRec(ScrnInfoPtr pScrn) 28150f2e948Smrg{ 28250f2e948Smrg if (!pScrn->driverPrivate) 283b40a6198Smrg pScrn->driverPrivate = calloc(sizeof(VESARec), 1); 28450f2e948Smrg 28550f2e948Smrg return ((VESAPtr)pScrn->driverPrivate); 28650f2e948Smrg} 28750f2e948Smrg 28850f2e948Smrg/* Only a little like VBESetModeParameters */ 28950f2e948Smrgstatic void 29050f2e948SmrgVESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode, 29150f2e948Smrg DisplayModePtr ddcmode) 29250f2e948Smrg{ 29350f2e948Smrg VbeModeInfoData *data; 29450f2e948Smrg int clock; 29550f2e948Smrg 29650f2e948Smrg data = (VbeModeInfoData *)vbemode->Private; 29750f2e948Smrg 298b40a6198Smrg data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); 29950f2e948Smrg data->block->HorizontalTotal = ddcmode->HTotal; 30050f2e948Smrg data->block->HorizontalSyncStart = ddcmode->HSyncStart; 30150f2e948Smrg data->block->HorizontalSyncEnd = ddcmode->HSyncEnd; 30250f2e948Smrg data->block->VerticalTotal = ddcmode->VTotal; 30350f2e948Smrg data->block->VerticalSyncStart = ddcmode->VSyncStart; 30450f2e948Smrg data->block->VerticalSyncEnd = ddcmode->VSyncEnd; 30550f2e948Smrg data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | 30650f2e948Smrg ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); 30750f2e948Smrg data->block->PixelClock = ddcmode->Clock * 1000; 30850f2e948Smrg 30950f2e948Smrg /* ask the BIOS to figure out the real clock */ 31050f2e948Smrg clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); 31150f2e948Smrg if (clock) 31250f2e948Smrg data->block->PixelClock = clock; 31350f2e948Smrg 31450f2e948Smrg data->mode |= (1 << 11); 31550f2e948Smrg data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) / 31650f2e948Smrg (double)(ddcmode->HTotal * ddcmode->VTotal)); 31750f2e948Smrg} 31850f2e948Smrg 319b40a6198Smrg/* 320b40a6198Smrg * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes 321b40a6198Smrg * think they can only give sizes in multiples of character cells; and 322b40a6198Smrg * indeed, the reference CVT and GTF formulae only give results where 323b40a6198Smrg * (h % 8) == 0. Whatever, let's just try to cope. What we're looking for 324b40a6198Smrg * here is cases where the display says 1366x768 and the BIOS says 1360x768. 325b40a6198Smrg */ 326b40a6198Smrgstatic Bool 327b40a6198SmrgvesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe) 328b40a6198Smrg{ 329b40a6198Smrg if (!(edid->type & M_T_DRIVER)) 330b40a6198Smrg return FALSE; 331b40a6198Smrg 332b40a6198Smrg /* never seen a height granularity... */ 333b40a6198Smrg if (edid->VDisplay != vbe->VDisplay) 334b40a6198Smrg return FALSE; 335b40a6198Smrg 336b40a6198Smrg if (edid->HDisplay >= vbe->HDisplay && 337b40a6198Smrg (edid->HDisplay & ~7) == (vbe->HDisplay & ~7)) 338b40a6198Smrg return TRUE; 339b40a6198Smrg 340b40a6198Smrg return FALSE; 341b40a6198Smrg} 342b40a6198Smrg 34350f2e948Smrgstatic ModeStatus 344b40a6198SmrgVESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass) 34550f2e948Smrg{ 346b40a6198Smrg SCRN_INFO_PTR(arg); 34750f2e948Smrg static int warned = 0; 34850f2e948Smrg int found = 0; 34950f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 35050f2e948Smrg MonPtr mon = pScrn->monitor; 35150f2e948Smrg ModeStatus ret = MODE_BAD; 35250f2e948Smrg DisplayModePtr mode; 35350f2e948Smrg float v; 35450f2e948Smrg 35550f2e948Smrg pVesa = VESAGetRec(pScrn); 35650f2e948Smrg 35750f2e948Smrg if (pass != MODECHECK_FINAL) { 35850f2e948Smrg if (!warned) { 359b40a6198Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n"); 36050f2e948Smrg warned = 1; 36150f2e948Smrg } 36250f2e948Smrg return MODE_OK; 36350f2e948Smrg } 36450f2e948Smrg 36550f2e948Smrg /* 36650f2e948Smrg * This is suboptimal. We pass in just the barest description of a mode 36750f2e948Smrg * we can get away with to VBEValidateModes, so it can't really throw 36850f2e948Smrg * out anything we give it. But we need to filter the list so that we 36950f2e948Smrg * don't populate the mode list with things the monitor can't do. 37050f2e948Smrg * 37150f2e948Smrg * So first off, if this isn't a mode we handed to the server (ie, 37250f2e948Smrg * M_T_BUILTIN), then we know we can't do it. 37350f2e948Smrg */ 37450f2e948Smrg if (!(p->type & M_T_BUILTIN)) 37550f2e948Smrg return MODE_NOMODE; 37650f2e948Smrg 37750f2e948Smrg if (pVesa->strict_validation) { 37850f2e948Smrg /* 37950f2e948Smrg * If it's our first pass at mode validation, we'll try for a strict 38050f2e948Smrg * intersection between the VBE and DDC mode lists. 38150f2e948Smrg */ 38250f2e948Smrg if (pScrn->monitor->DDC) { 38350f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) { 384b40a6198Smrg if (vesaModesCloseEnough(mode, p)) { 38550f2e948Smrg if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) { 38650f2e948Smrg found = 1; 38750f2e948Smrg break; 38850f2e948Smrg } 38950f2e948Smrg } 39050f2e948Smrg if (mode == pScrn->monitor->Last) 39150f2e948Smrg break; 39250f2e948Smrg } 39350f2e948Smrg if (!found) 39450f2e948Smrg return MODE_NOMODE; 39550f2e948Smrg 39650f2e948Smrg /* having found a matching mode, stash the CRTC values aside */ 39750f2e948Smrg VESASetModeParameters(pVesa->pVbe, p, mode); 39850f2e948Smrg return MODE_OK; 39950f2e948Smrg } 40050f2e948Smrg 40150f2e948Smrg /* No DDC and no modes make Homer something something... */ 40250f2e948Smrg return MODE_NOMODE; 40350f2e948Smrg } 40450f2e948Smrg 40550f2e948Smrg /* 40650f2e948Smrg * Finally, walk through the vsync rates 1Hz at a time looking for a mode 40750f2e948Smrg * that will fit. This is assuredly a terrible way to do this, but 40850f2e948Smrg * there's no obvious method for computing a mode of a given size that 40950f2e948Smrg * will pass xf86CheckModeForMonitor. XXX this path is terrible, but 41050f2e948Smrg * then, by this point, you're well into despair territory. 41150f2e948Smrg */ 41250f2e948Smrg for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) { 41350f2e948Smrg mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0); 41450f2e948Smrg ret = xf86CheckModeForMonitor(mode, mon); 415b40a6198Smrg free(mode->name); 416b40a6198Smrg free(mode); 41750f2e948Smrg if (ret == MODE_OK) 41850f2e948Smrg break; 41950f2e948Smrg } 42050f2e948Smrg 42150f2e948Smrg return ret; 42250f2e948Smrg} 42350f2e948Smrg 42450f2e948Smrgstatic void 42550f2e948SmrgVESAInitScrn(ScrnInfoPtr pScrn) 42650f2e948Smrg{ 42750f2e948Smrg pScrn->driverVersion = VESA_VERSION; 42850f2e948Smrg pScrn->driverName = VESA_DRIVER_NAME; 42950f2e948Smrg pScrn->name = VESA_NAME; 43050f2e948Smrg pScrn->Probe = VESAProbe; 43150f2e948Smrg pScrn->PreInit = VESAPreInit; 43250f2e948Smrg pScrn->ScreenInit = VESAScreenInit; 43350f2e948Smrg pScrn->SwitchMode = VESASwitchMode; 43450f2e948Smrg pScrn->ValidMode = VESAValidMode; 43550f2e948Smrg pScrn->AdjustFrame = VESAAdjustFrame; 43650f2e948Smrg pScrn->EnterVT = VESAEnterVT; 43750f2e948Smrg pScrn->LeaveVT = VESALeaveVT; 43850f2e948Smrg pScrn->FreeScreen = VESAFreeScreen; 43950f2e948Smrg} 44050f2e948Smrg 44145bc899bSmrg/* 44245bc899bSmrg * This function is called once, at the start of the first server generation to 44345bc899bSmrg * do a minimal probe for supported hardware. 44445bc899bSmrg */ 44545bc899bSmrg 44650f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 44750f2e948Smrgstatic Bool 44850f2e948SmrgVESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, 44950f2e948Smrg intptr_t match_data) 45050f2e948Smrg{ 45150f2e948Smrg ScrnInfoPtr pScrn; 45250f2e948Smrg 45350f2e948Smrg pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, 45450f2e948Smrg NULL, NULL, NULL, NULL, NULL); 45550f2e948Smrg if (pScrn != NULL) { 456b40a6198Smrg VESAPtr pVesa; 457b40a6198Smrg 458b40a6198Smrg if (pci_device_has_kernel_driver(dev)) { 459b40a6198Smrg ErrorF("vesa: Ignoring device with a bound kernel driver\n"); 460b40a6198Smrg return FALSE; 461b40a6198Smrg } 46250f2e948Smrg 463b40a6198Smrg pVesa = VESAGetRec(pScrn); 46450f2e948Smrg VESAInitScrn(pScrn); 46550f2e948Smrg pVesa->pciInfo = dev; 46650f2e948Smrg } 46750f2e948Smrg 46850f2e948Smrg return (pScrn != NULL); 46950f2e948Smrg} 47050f2e948Smrg#endif 47150f2e948Smrg 47245bc899bSmrgstatic Bool 47345bc899bSmrgVESAProbe(DriverPtr drv, int flags) 47445bc899bSmrg{ 47545bc899bSmrg Bool foundScreen = FALSE; 47645bc899bSmrg int numDevSections, numUsed; 47745bc899bSmrg GDevPtr *devSections; 47845bc899bSmrg int *usedChips; 47945bc899bSmrg int i; 48045bc899bSmrg 48145bc899bSmrg /* 48245bc899bSmrg * Find the config file Device sections that match this 48345bc899bSmrg * driver, and return if there are none. 48445bc899bSmrg */ 48545bc899bSmrg if ((numDevSections = xf86MatchDevice(VESA_NAME, 48645bc899bSmrg &devSections)) <= 0) 48745bc899bSmrg return (FALSE); 48845bc899bSmrg 48950f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 49045bc899bSmrg /* PCI BUS */ 49145bc899bSmrg if (xf86GetPciVideoInfo()) { 49245bc899bSmrg numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC, 49345bc899bSmrg VESAChipsets, VESAPCIchipsets, 49445bc899bSmrg devSections, numDevSections, 49545bc899bSmrg drv, &usedChips); 49645bc899bSmrg if (numUsed > 0) { 49745bc899bSmrg if (flags & PROBE_DETECT) 49845bc899bSmrg foundScreen = TRUE; 49945bc899bSmrg else { 50045bc899bSmrg for (i = 0; i < numUsed; i++) { 50145bc899bSmrg ScrnInfoPtr pScrn = NULL; 50245bc899bSmrg /* Allocate a ScrnInfoRec */ 50345bc899bSmrg if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 50445bc899bSmrg VESAPCIchipsets,NULL, 50545bc899bSmrg NULL,NULL,NULL,NULL))) { 50650f2e948Smrg VESAInitScrn(pScrn); 50745bc899bSmrg foundScreen = TRUE; 50845bc899bSmrg } 50945bc899bSmrg } 51045bc899bSmrg } 511b40a6198Smrg free(usedChips); 51245bc899bSmrg } 51345bc899bSmrg } 51450f2e948Smrg#endif 51545bc899bSmrg 51650f2e948Smrg#ifdef HAVE_ISA 51745bc899bSmrg /* Isa Bus */ 51845bc899bSmrg numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets, 51945bc899bSmrg VESAISAchipsets, drv, 52045bc899bSmrg VESAFindIsaDevice, devSections, 52145bc899bSmrg numDevSections, &usedChips); 52245bc899bSmrg if(numUsed > 0) { 52345bc899bSmrg if (flags & PROBE_DETECT) 52445bc899bSmrg foundScreen = TRUE; 52545bc899bSmrg else for (i = 0; i < numUsed; i++) { 52645bc899bSmrg ScrnInfoPtr pScrn = NULL; 52745bc899bSmrg if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i], 52845bc899bSmrg VESAISAchipsets, NULL, 52945bc899bSmrg NULL, NULL, NULL, NULL))) { 53050f2e948Smrg VESAInitScrn(pScrn); 53145bc899bSmrg foundScreen = TRUE; 53245bc899bSmrg } 53345bc899bSmrg } 534b40a6198Smrg free(usedChips); 53545bc899bSmrg } 53650f2e948Smrg#endif 53745bc899bSmrg 538b40a6198Smrg free(devSections); 53945bc899bSmrg 54045bc899bSmrg return (foundScreen); 54145bc899bSmrg} 54245bc899bSmrg 54350f2e948Smrg#ifdef HAVE_ISA 54445bc899bSmrgstatic int 54545bc899bSmrgVESAFindIsaDevice(GDevPtr dev) 54645bc899bSmrg{ 54745bc899bSmrg#ifndef PC98_EGC 54845bc899bSmrg CARD16 GenericIOBase = VGAHW_GET_IOBASE(); 54945bc899bSmrg CARD8 CurrentValue, TestValue; 55045bc899bSmrg 55145bc899bSmrg /* There's no need to unlock VGA CRTC registers here */ 55245bc899bSmrg 55345bc899bSmrg /* VGA has one more read/write attribute register than EGA */ 55445bc899bSmrg (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */ 55545bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 55645bc899bSmrg CurrentValue = inb(VGA_ATTR_DATA_R); 55745bc899bSmrg outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F); 55845bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 55945bc899bSmrg TestValue = inb(VGA_ATTR_DATA_R); 56045bc899bSmrg outb(VGA_ATTR_DATA_R, CurrentValue); 56145bc899bSmrg 56245bc899bSmrg /* Quit now if no VGA is present */ 56345bc899bSmrg if ((CurrentValue ^ 0x0F) != TestValue) 56445bc899bSmrg return -1; 56545bc899bSmrg#endif 56645bc899bSmrg return (int)CHIP_VESA_GENERIC; 56745bc899bSmrg} 56850f2e948Smrg#endif 56945bc899bSmrg 57045bc899bSmrgstatic void 57145bc899bSmrgVESAFreeRec(ScrnInfoPtr pScrn) 57245bc899bSmrg{ 57345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 57445bc899bSmrg#if 0 57545bc899bSmrg DisplayModePtr mode = pScrn->modes; 57645bc899bSmrg /* I am not sure if the modes will ever get freed. 57745bc899bSmrg * Anyway, the data unknown to other modules is being freed here. 57845bc899bSmrg */ 57945bc899bSmrg if (mode) { 58045bc899bSmrg do { 58145bc899bSmrg if (mode->Private) { 58245bc899bSmrg VbeModeInfoData *data = (VbeModeInfoData*)mode->Private; 58345bc899bSmrg 58445bc899bSmrg if (data->block) 585b40a6198Smrg free(data->block); 58645bc899bSmrg 587b40a6198Smrg free(data); 58845bc899bSmrg 58945bc899bSmrg mode->Private = NULL; 59045bc899bSmrg } 59145bc899bSmrg mode = mode->next; 59245bc899bSmrg } while (mode && mode != pScrn->modes); 59345bc899bSmrg } 59445bc899bSmrg#endif 595b40a6198Smrg free(pVesa->monitor); 596b40a6198Smrg free(pVesa->vbeInfo); 597b40a6198Smrg free(pVesa->pal); 598b40a6198Smrg free(pVesa->savedPal); 599b40a6198Smrg free(pVesa->fonts); 600b40a6198Smrg free(pScrn->driverPrivate); 60145bc899bSmrg pScrn->driverPrivate = NULL; 60245bc899bSmrg} 60345bc899bSmrg 60450f2e948Smrgstatic int 60550f2e948SmrgVESAValidateModes(ScrnInfoPtr pScrn) 60650f2e948Smrg{ 60750f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 60850f2e948Smrg DisplayModePtr mode; 60950f2e948Smrg 61050f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) 61150f2e948Smrg mode->status = MODE_OK; 61250f2e948Smrg 61350f2e948Smrg return VBEValidateModes(pScrn, NULL, pScrn->display->modes, 6145592a31fSmrg NULL, NULL, 0, 32767, 1, 0, 32767, 61550f2e948Smrg pScrn->display->virtualX, 61650f2e948Smrg pScrn->display->virtualY, 61750f2e948Smrg pVesa->mapSize, LOOKUP_BEST_REFRESH); 61850f2e948Smrg} 61950f2e948Smrg 62045bc899bSmrg/* 62145bc899bSmrg * This function is called once for each screen at the start of the first 62245bc899bSmrg * server generation to initialise the screen for all server generations. 62345bc899bSmrg */ 62445bc899bSmrgstatic Bool 62545bc899bSmrgVESAPreInit(ScrnInfoPtr pScrn, int flags) 62645bc899bSmrg{ 62745bc899bSmrg VESAPtr pVesa; 62845bc899bSmrg VbeInfoBlock *vbe; 62945bc899bSmrg DisplayModePtr pMode; 63045bc899bSmrg VbeModeInfoBlock *mode; 63145bc899bSmrg Gamma gzeros = {0.0, 0.0, 0.0}; 63245bc899bSmrg rgb rzeros = {0, 0, 0}; 63345bc899bSmrg pointer pDDCModule; 63445bc899bSmrg int i; 63545bc899bSmrg int flags24 = 0; 63645bc899bSmrg int defaultDepth = 0; 63750f2e948Smrg int defaultBpp = 0; 63845bc899bSmrg int depths = 0; 63945bc899bSmrg 64045bc899bSmrg if (flags & PROBE_DETECT) 64145bc899bSmrg return (FALSE); 64245bc899bSmrg 64345bc899bSmrg pVesa = VESAGetRec(pScrn); 64445bc899bSmrg pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 64545bc899bSmrg 64645bc899bSmrg /* Load vbe module */ 64745bc899bSmrg if (!xf86LoadSubModule(pScrn, "vbe")) 64845bc899bSmrg return (FALSE); 64945bc899bSmrg 65045bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 65145bc899bSmrg SET_BIOS_SCRATCH 65245bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 65345bc899bSmrg return (FALSE); 65445bc899bSmrg 65550f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 65645bc899bSmrg if (pVesa->pEnt->location.type == BUS_PCI) { 65745bc899bSmrg pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index); 65845bc899bSmrg pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device, 65945bc899bSmrg pVesa->pciInfo->func); 66045bc899bSmrg } 66150f2e948Smrg#endif 66245bc899bSmrg 66345bc899bSmrg pScrn->chipset = "vesa"; 66445bc899bSmrg pScrn->monitor = pScrn->confScreen->monitor; 66545bc899bSmrg pScrn->progClock = TRUE; 66645bc899bSmrg pScrn->rgbBits = 8; 66745bc899bSmrg 66845bc899bSmrg if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL) 66945bc899bSmrg return (FALSE); 67045bc899bSmrg pVesa->major = (unsigned)(vbe->VESAVersion >> 8); 67145bc899bSmrg pVesa->minor = vbe->VESAVersion & 0xff; 67245bc899bSmrg pVesa->vbeInfo = vbe; 67345bc899bSmrg pScrn->videoRam = vbe->TotalMemory * 64; 67445bc899bSmrg 67545bc899bSmrg /* 67645bc899bSmrg * Find what depths are available. 67745bc899bSmrg */ 67845bc899bSmrg depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24, 67945bc899bSmrg V_MODETYPE_VBE); 68045bc899bSmrg 68145bc899bSmrg /* Preferred order for default depth selection. */ 68250f2e948Smrg if (depths & V_DEPTH_24) 68350f2e948Smrg defaultDepth = 24; 68450f2e948Smrg else if (depths & V_DEPTH_16) 68545bc899bSmrg defaultDepth = 16; 68645bc899bSmrg else if (depths & V_DEPTH_15) 68745bc899bSmrg defaultDepth = 15; 68845bc899bSmrg else if (depths & V_DEPTH_8) 68945bc899bSmrg defaultDepth = 8; 69045bc899bSmrg else if (depths & V_DEPTH_4) 69145bc899bSmrg defaultDepth = 4; 69245bc899bSmrg else if (depths & V_DEPTH_1) 69345bc899bSmrg defaultDepth = 1; 69445bc899bSmrg 69550f2e948Smrg if (defaultDepth == 24 && !(flags24 & Support32bppFb)) 69650f2e948Smrg defaultBpp = 24; 69745bc899bSmrg 69850f2e948Smrg /* Prefer 32bpp because 1999 called and wants its packed pixels back */ 69950f2e948Smrg if (flags24 & Support32bppFb) 70050f2e948Smrg flags24 |= SupportConvert24to32 | PreferConvert24to32; 70145bc899bSmrg if (flags24 & Support24bppFb) 70250f2e948Smrg flags24 |= SupportConvert32to24; 70345bc899bSmrg 70450f2e948Smrg if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) { 70545bc899bSmrg vbeFree(pVesa->pVbe); 70645bc899bSmrg return (FALSE); 70745bc899bSmrg } 70845bc899bSmrg xf86PrintDepthBpp(pScrn); 70945bc899bSmrg 71045bc899bSmrg /* color weight */ 71145bc899bSmrg if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) { 71245bc899bSmrg vbeFree(pVesa->pVbe); 71345bc899bSmrg return (FALSE); 71445bc899bSmrg } 71545bc899bSmrg /* visual init */ 71645bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) { 71745bc899bSmrg vbeFree(pVesa->pVbe); 71845bc899bSmrg return (FALSE); 71945bc899bSmrg } 72045bc899bSmrg 72145bc899bSmrg xf86SetGamma(pScrn, gzeros); 72245bc899bSmrg 72345bc899bSmrg if (pVesa->major >= 2) { 72445bc899bSmrg /* Load ddc module */ 72545bc899bSmrg if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { 72645bc899bSmrg vbeFree(pVesa->pVbe); 72745bc899bSmrg return (FALSE); 72845bc899bSmrg } 72945bc899bSmrg 73045bc899bSmrg if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) { 73145bc899bSmrg xf86PrintEDID(pVesa->monitor); 73245bc899bSmrg } 73345bc899bSmrg 73445bc899bSmrg xf86UnloadSubModule(pDDCModule); 73545bc899bSmrg } 73645bc899bSmrg 73745bc899bSmrg if ((pScrn->monitor->DDC = pVesa->monitor) != NULL) 73845bc899bSmrg xf86SetDDCproperties(pScrn, pVesa->monitor); 7393a925b30Smrg#ifdef HAVE_PANELID 7403a925b30Smrg else { 7413a925b30Smrg void *panelid = VBEReadPanelID(pVesa->pVbe); 742b40a6198Smrg VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid); 743b40a6198Smrg free(panelid); 7443a925b30Smrg } 7453a925b30Smrg#endif 74645bc899bSmrg 74745bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 74845bc899bSmrg "Searching for matching VESA mode(s):\n"); 74945bc899bSmrg 75045bc899bSmrg /* 75145bc899bSmrg * Check the available BIOS modes, and extract those that match the 75245bc899bSmrg * requirements into the modePool. Note: modePool is a NULL-terminated 75345bc899bSmrg * list. 75445bc899bSmrg */ 75545bc899bSmrg pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo, 75645bc899bSmrg V_MODETYPE_VBE); 75745bc899bSmrg 75845bc899bSmrg xf86ErrorFVerb(DEBUG_VERB, "\n"); 75945bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 76045bc899bSmrg "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory, 76145bc899bSmrg (vbe->TotalMemory * 65536) / 1024); 76245bc899bSmrg 76345bc899bSmrg pVesa->mapSize = vbe->TotalMemory * 65536; 76445bc899bSmrg if (pScrn->modePool == NULL) { 76545bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n"); 76645bc899bSmrg vbeFree(pVesa->pVbe); 76745bc899bSmrg return (FALSE); 76845bc899bSmrg } 76945bc899bSmrg 77045bc899bSmrg VBESetModeNames(pScrn->modePool); 77145bc899bSmrg 77250f2e948Smrg pVesa->strict_validation = TRUE; 77350f2e948Smrg i = VESAValidateModes(pScrn); 77450f2e948Smrg 77550f2e948Smrg if (i <= 0) { 77650f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 77750f2e948Smrg "No valid modes left. Trying less strict filter...\n"); 77850f2e948Smrg pVesa->strict_validation = FALSE; 77950f2e948Smrg i = VESAValidateModes(pScrn); 78050f2e948Smrg } 78150f2e948Smrg 78250f2e948Smrg if (i <= 0) do { 78350f2e948Smrg Bool changed = FALSE; 78450f2e948Smrg /* maybe there's more modes at the bottom... */ 78550f2e948Smrg if (pScrn->monitor->vrefresh[0].lo > 50) { 78650f2e948Smrg changed = TRUE; 78750f2e948Smrg pScrn->monitor->vrefresh[0].lo = 50; 78850f2e948Smrg } 78950f2e948Smrg if (pScrn->monitor->hsync[0].lo > 31.5) { 79050f2e948Smrg changed = TRUE; 79150f2e948Smrg pScrn->monitor->hsync[0].lo = 31.5; 79250f2e948Smrg } 79350f2e948Smrg 79450f2e948Smrg if (!changed) 79550f2e948Smrg break; 79650f2e948Smrg 79750f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 79850f2e948Smrg "No valid modes left. Trying aggressive sync range...\n"); 79950f2e948Smrg i = VESAValidateModes(pScrn); 80050f2e948Smrg } while (0); 80145bc899bSmrg 80245bc899bSmrg if (i <= 0) { 80350f2e948Smrg /* alright, i'm out of ideas */ 80445bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n"); 80545bc899bSmrg vbeFree(pVesa->pVbe); 80645bc899bSmrg return (FALSE); 80745bc899bSmrg } 80845bc899bSmrg 80945bc899bSmrg xf86PruneDriverModes(pScrn); 81045bc899bSmrg 81145bc899bSmrg pMode = pScrn->modes; 81245bc899bSmrg do { 81345bc899bSmrg mode = ((VbeModeInfoData*)pMode->Private)->data; 81445bc899bSmrg if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) { 81545bc899bSmrg pVesa->maxBytesPerScanline = mode->BytesPerScanline; 81645bc899bSmrg } 81745bc899bSmrg pMode = pMode->next; 81845bc899bSmrg } while (pMode != pScrn->modes); 81945bc899bSmrg 82045bc899bSmrg pScrn->currentMode = pScrn->modes; 82145bc899bSmrg pScrn->displayWidth = pScrn->virtualX; 82245bc899bSmrg 82345bc899bSmrg VBEPrintModes(pScrn); 82445bc899bSmrg 82545bc899bSmrg /* Set display resolution */ 82645bc899bSmrg xf86SetDpi(pScrn, 0, 0); 82745bc899bSmrg 82845bc899bSmrg if (pScrn->modes == NULL) { 82945bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); 83045bc899bSmrg vbeFree(pVesa->pVbe); 83145bc899bSmrg return (FALSE); 83245bc899bSmrg } 83345bc899bSmrg 83445bc899bSmrg /* options */ 83545bc899bSmrg xf86CollectOptions(pScrn, NULL); 836b40a6198Smrg if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) { 83745bc899bSmrg vbeFree(pVesa->pVbe); 83845bc899bSmrg return FALSE; 83945bc899bSmrg } 84045bc899bSmrg memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions)); 84145bc899bSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options); 84245bc899bSmrg 84345bc899bSmrg /* Use shadow by default */ 84445bc899bSmrg if (xf86ReturnOptValBool(pVesa->Options, OPTION_SHADOW_FB, TRUE)) 84545bc899bSmrg pVesa->shadowFB = TRUE; 84645bc899bSmrg 84745bc899bSmrg if (xf86ReturnOptValBool(pVesa->Options, OPTION_DFLT_REFRESH, FALSE)) 84845bc899bSmrg pVesa->defaultRefresh = TRUE; 84945bc899bSmrg 85050f2e948Smrg pVesa->ModeSetClearScreen = FALSE; 85145bc899bSmrg if (xf86ReturnOptValBool(pVesa->Options, OPTION_MODESET_CLEAR_SCREEN, 85250f2e948Smrg FALSE)) 85345bc899bSmrg pVesa->ModeSetClearScreen = TRUE; 85445bc899bSmrg 85550f2e948Smrg if (!pVesa->defaultRefresh && !pVesa->strict_validation) 85645bc899bSmrg VBESetModeParameters(pScrn, pVesa->pVbe); 85745bc899bSmrg 85845bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 85945bc899bSmrg switch (mode->MemoryModel) { 86045bc899bSmrg case 0x4: /* Packed pixel */ 86150f2e948Smrg case 0x6: /* Direct Color */ 86245bc899bSmrg pScrn->bitmapBitOrder = BITMAP_BIT_ORDER; 86345bc899bSmrg 86445bc899bSmrg switch (pScrn->bitsPerPixel) { 86545bc899bSmrg case 8: 86645bc899bSmrg case 16: 86745bc899bSmrg case 24: 86845bc899bSmrg case 32: 86945bc899bSmrg break; 87045bc899bSmrg default: 87145bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 87245bc899bSmrg "Unsupported bpp: %d", pScrn->bitsPerPixel); 87345bc899bSmrg vbeFree(pVesa->pVbe); 87445bc899bSmrg return FALSE; 87545bc899bSmrg } 87645bc899bSmrg break; 87750f2e948Smrg default: 87850f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 87950f2e948Smrg "Unsupported Memory Model: %d", mode->MemoryModel); 88050f2e948Smrg return FALSE; 88145bc899bSmrg } 88245bc899bSmrg 88345bc899bSmrg if (pVesa->shadowFB) { 88445bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); 88545bc899bSmrg if (!xf86LoadSubModule(pScrn, "shadow")) { 88645bc899bSmrg vbeFree(pVesa->pVbe); 88745bc899bSmrg return (FALSE); 88845bc899bSmrg } 88945bc899bSmrg } 89045bc899bSmrg 89150f2e948Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 89245bc899bSmrg VESAFreeRec(pScrn); 89345bc899bSmrg vbeFree(pVesa->pVbe); 89445bc899bSmrg return (FALSE); 89545bc899bSmrg } 89645bc899bSmrg 89745bc899bSmrg vbeFree(pVesa->pVbe); 89845bc899bSmrg 89945bc899bSmrg return (TRUE); 90045bc899bSmrg} 90145bc899bSmrg 90245bc899bSmrgstatic Bool 90345bc899bSmrgvesaCreateScreenResources(ScreenPtr pScreen) 90445bc899bSmrg{ 905b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 90645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 90745bc899bSmrg Bool ret; 90845bc899bSmrg 90945bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 91045bc899bSmrg ret = pScreen->CreateScreenResources(pScreen); 91145bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 91245bc899bSmrg 91345bc899bSmrg shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update, 91445bc899bSmrg pVesa->window, 0, 0); 91545bc899bSmrg 91645bc899bSmrg return ret; 91745bc899bSmrg} 91845bc899bSmrg 91950f2e948Smrgstatic void 920b40a6198SmrgvesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable) 92150f2e948Smrg{ 922b40a6198Smrg SCRN_INFO_PTR(arg); 92350f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 92450f2e948Smrg 92550f2e948Smrg pVesa->accessEnabled = enable; 926b40a6198Smrg pVesa->EnableDisableFBAccess(arg, enable); 92750f2e948Smrg} 92850f2e948Smrg 92945bc899bSmrgstatic Bool 930b40a6198SmrgVESAScreenInit(SCREEN_INIT_ARGS_DECL) 93145bc899bSmrg{ 932b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 93345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 93445bc899bSmrg VisualPtr visual; 93545bc899bSmrg VbeModeInfoBlock *mode; 93645bc899bSmrg int flags; 93745bc899bSmrg 93845bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 93945bc899bSmrg SET_BIOS_SCRATCH 94045bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 94145bc899bSmrg return (FALSE); 94245bc899bSmrg 94345bc899bSmrg if (pVesa->mapPhys == 0) { 94445bc899bSmrg mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 94545bc899bSmrg pScrn->videoRam = pVesa->mapSize; 94645bc899bSmrg pVesa->mapPhys = mode->PhysBasePtr; 94745bc899bSmrg pVesa->mapOff = 0; 94845bc899bSmrg } 94945bc899bSmrg 95045bc899bSmrg if (pVesa->mapPhys == 0) { 95145bc899bSmrg pVesa->mapPhys = 0xa0000; 95245bc899bSmrg pVesa->mapSize = 0x10000; 95345bc899bSmrg } 95445bc899bSmrg 95545bc899bSmrg if (!VESAMapVidMem(pScrn)) { 95645bc899bSmrg if (pVesa->mapPhys != 0xa0000) { 95745bc899bSmrg pVesa->mapPhys = 0xa0000; 95845bc899bSmrg pVesa->mapSize = 0x10000; 95945bc899bSmrg if (!VESAMapVidMem(pScrn)) 96045bc899bSmrg return (FALSE); 96145bc899bSmrg } 96245bc899bSmrg else 96345bc899bSmrg return (FALSE); 96445bc899bSmrg } 96545bc899bSmrg 96645bc899bSmrg /* Set bpp to 8 for depth 4 when using shadowfb. */ 96745bc899bSmrg if (pVesa->shadowFB && pScrn->bitsPerPixel == 4) 96845bc899bSmrg pScrn->bitsPerPixel = 8; 96945bc899bSmrg 97045bc899bSmrg if (pVesa->shadowFB) { 971b40a6198Smrg pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY * 97245bc899bSmrg ((pScrn->bitsPerPixel + 7) / 8)); 97345bc899bSmrg if (!pVesa->shadow) { 97445bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 97545bc899bSmrg "Failed to allocate shadow buffer\n"); 97645bc899bSmrg return FALSE; 97745bc899bSmrg } 97845bc899bSmrg } 97945bc899bSmrg 98045bc899bSmrg /* save current video state */ 98145bc899bSmrg VESASaveRestore(pScrn, MODE_SAVE); 98245bc899bSmrg pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256, 98345bc899bSmrg NULL, FALSE, FALSE); 98445bc899bSmrg 98545bc899bSmrg /* set first video mode */ 98645bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 98745bc899bSmrg return (FALSE); 98845bc899bSmrg 98945bc899bSmrg /* set the viewport */ 990b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 99145bc899bSmrg 99245bc899bSmrg /* Blank the screen for aesthetic reasons. */ 99345bc899bSmrg VESASaveScreen(pScreen, SCREEN_SAVER_ON); 99445bc899bSmrg 99545bc899bSmrg /* mi layer */ 99645bc899bSmrg miClearVisualTypes(); 99745bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 99845bc899bSmrg return (FALSE); 99945bc899bSmrg if (pScrn->bitsPerPixel > 8) { 100045bc899bSmrg if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 100145bc899bSmrg pScrn->rgbBits, TrueColor)) 100245bc899bSmrg return (FALSE); 100345bc899bSmrg } 100445bc899bSmrg else { 100545bc899bSmrg if (!miSetVisualTypes(pScrn->depth, 100645bc899bSmrg miGetDefaultVisualMask(pScrn->depth), 100745bc899bSmrg pScrn->rgbBits, pScrn->defaultVisual)) 100845bc899bSmrg return (FALSE); 100945bc899bSmrg } 101045bc899bSmrg if (!miSetPixmapDepths()) 101145bc899bSmrg return (FALSE); 101245bc899bSmrg 101345bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 101445bc899bSmrg switch (mode->MemoryModel) { 101545bc899bSmrg case 0x4: /* Packed pixel */ 101650f2e948Smrg case 0x6: /* Direct Color */ 101745bc899bSmrg switch (pScrn->bitsPerPixel) { 101845bc899bSmrg case 8: 101945bc899bSmrg case 16: 102045bc899bSmrg case 24: 102145bc899bSmrg case 32: 102245bc899bSmrg if (!fbScreenInit(pScreen, 102345bc899bSmrg pVesa->shadowFB ? pVesa->shadow : pVesa->base, 102445bc899bSmrg pScrn->virtualX, pScrn->virtualY, 102545bc899bSmrg pScrn->xDpi, pScrn->yDpi, 102645bc899bSmrg pScrn->displayWidth, pScrn->bitsPerPixel)) 102745bc899bSmrg return (FALSE); 102845bc899bSmrg break; 102945bc899bSmrg default: 103045bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 103145bc899bSmrg "Unsupported bpp: %d", pScrn->bitsPerPixel); 103245bc899bSmrg return (FALSE); 103345bc899bSmrg } 103445bc899bSmrg break; 103550f2e948Smrg default: 103650f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 103750f2e948Smrg "Unsupported Memory Model: %d", mode->MemoryModel); 103850f2e948Smrg return (FALSE); 103945bc899bSmrg } 104045bc899bSmrg 104145bc899bSmrg 104245bc899bSmrg if (pScrn->bitsPerPixel > 8) { 104345bc899bSmrg /* Fixup RGB ordering */ 104445bc899bSmrg visual = pScreen->visuals + pScreen->numVisuals; 104545bc899bSmrg while (--visual >= pScreen->visuals) { 104645bc899bSmrg if ((visual->class | DynamicClass) == DirectColor) { 104745bc899bSmrg visual->offsetRed = pScrn->offset.red; 104845bc899bSmrg visual->offsetGreen = pScrn->offset.green; 104945bc899bSmrg visual->offsetBlue = pScrn->offset.blue; 105045bc899bSmrg visual->redMask = pScrn->mask.red; 105145bc899bSmrg visual->greenMask = pScrn->mask.green; 105245bc899bSmrg visual->blueMask = pScrn->mask.blue; 105345bc899bSmrg } 105445bc899bSmrg } 105545bc899bSmrg } 105645bc899bSmrg 105745bc899bSmrg /* must be after RGB ordering fixed */ 10585592a31fSmrg fbPictureInit(pScreen, 0, 0); 105945bc899bSmrg 106045bc899bSmrg if (pVesa->shadowFB) { 106150f2e948Smrg if (pVesa->mapPhys == 0xa0000) { /* Windowed */ 10625592a31fSmrg pVesa->update = vesaUpdatePacked; 106345bc899bSmrg pVesa->window = VESAWindowWindowed; 106445bc899bSmrg } 106545bc899bSmrg else { /* Linear */ 10665592a31fSmrg pVesa->update = vesaUpdatePacked; 106745bc899bSmrg pVesa->window = VESAWindowLinear; 106845bc899bSmrg } 106945bc899bSmrg 107045bc899bSmrg if (!shadowSetup(pScreen)) 107145bc899bSmrg return FALSE; 107245bc899bSmrg pVesa->CreateScreenResources = pScreen->CreateScreenResources; 107345bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 107445bc899bSmrg } 107550f2e948Smrg else if (pVesa->mapPhys == 0xa0000) { 10765592a31fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 10775592a31fSmrg "Banked framebuffer requires ShadowFB\n"); 10785592a31fSmrg return FALSE; 107945bc899bSmrg } 108045bc899bSmrg 108145bc899bSmrg VESADGAInit(pScrn, pScreen); 108245bc899bSmrg 108345bc899bSmrg xf86SetBlackWhitePixels(pScreen); 108445bc899bSmrg miInitializeBackingStore(pScreen); 108545bc899bSmrg xf86SetBackingStore(pScreen); 108645bc899bSmrg 108745bc899bSmrg /* software cursor */ 108845bc899bSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 108945bc899bSmrg 109045bc899bSmrg /* colormap */ 109145bc899bSmrg if (!miCreateDefColormap(pScreen)) 109245bc899bSmrg return (FALSE); 109345bc899bSmrg 109445bc899bSmrg flags = CMAP_RELOAD_ON_MODE_SWITCH; 109545bc899bSmrg 109645bc899bSmrg if(!xf86HandleColormaps(pScreen, 256, 109745bc899bSmrg pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6, 109845bc899bSmrg VESALoadPalette, NULL, flags)) 109945bc899bSmrg return (FALSE); 110045bc899bSmrg 110150f2e948Smrg pVesa->accessEnabled = TRUE; 110250f2e948Smrg pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; 110350f2e948Smrg pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess; 110450f2e948Smrg 110545bc899bSmrg pVesa->CloseScreen = pScreen->CloseScreen; 110645bc899bSmrg pScreen->CloseScreen = VESACloseScreen; 110745bc899bSmrg pScreen->SaveScreen = VESASaveScreen; 110845bc899bSmrg 110945bc899bSmrg xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0); 111045bc899bSmrg 111145bc899bSmrg /* Report any unused options (only for the first generation) */ 111245bc899bSmrg if (serverGeneration == 1) 111345bc899bSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 111445bc899bSmrg 111545bc899bSmrg return (TRUE); 111645bc899bSmrg} 111745bc899bSmrg 111845bc899bSmrgstatic Bool 1119b40a6198SmrgVESAEnterVT(VT_FUNC_ARGS_DECL) 112045bc899bSmrg{ 1121b40a6198Smrg SCRN_INFO_PTR(arg); 112245bc899bSmrg 112345bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 112445bc899bSmrg return FALSE; 1125b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 112645bc899bSmrg return TRUE; 112745bc899bSmrg} 112845bc899bSmrg 112945bc899bSmrgstatic void 1130b40a6198SmrgVESALeaveVT(VT_FUNC_ARGS_DECL) 113145bc899bSmrg{ 1132b40a6198Smrg SCRN_INFO_PTR(arg); 1133b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 113445bc899bSmrg} 113545bc899bSmrg 113645bc899bSmrgstatic Bool 1137b40a6198SmrgVESACloseScreen(CLOSE_SCREEN_ARGS_DECL) 113845bc899bSmrg{ 1139b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 114045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 114145bc899bSmrg 114245bc899bSmrg if (pScrn->vtSema) { 1143b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 114445bc899bSmrg if (pVesa->savedPal) 114545bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256, 114645bc899bSmrg pVesa->savedPal, FALSE, TRUE); 114745bc899bSmrg VESAUnmapVidMem(pScrn); 114845bc899bSmrg } 11495592a31fSmrg if (pVesa->shadowFB && pVesa->shadow) { 11505592a31fSmrg shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); 1151b40a6198Smrg free(pVesa->shadow); 11525592a31fSmrg } 115345bc899bSmrg if (pVesa->pDGAMode) { 1154b40a6198Smrg free(pVesa->pDGAMode); 115545bc899bSmrg pVesa->pDGAMode = NULL; 115645bc899bSmrg pVesa->nDGAMode = 0; 115745bc899bSmrg } 115845bc899bSmrg pScrn->vtSema = FALSE; 115945bc899bSmrg 116050f2e948Smrg pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess; 116145bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 116245bc899bSmrg pScreen->CloseScreen = pVesa->CloseScreen; 1163b40a6198Smrg return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); 116445bc899bSmrg} 116545bc899bSmrg 116645bc899bSmrgstatic Bool 1167b40a6198SmrgVESASwitchMode(SWITCH_MODE_ARGS_DECL) 116845bc899bSmrg{ 1169b40a6198Smrg SCRN_INFO_PTR(arg); 117045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 117150f2e948Smrg Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled; 117245bc899bSmrg 117350f2e948Smrg if (disableAccess) 1174b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE); 1175b40a6198Smrg ret = VESASetMode(pScrn, mode); 117650f2e948Smrg if (disableAccess) 1177b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE); 117845bc899bSmrg return ret; 117945bc899bSmrg} 118045bc899bSmrg 118145bc899bSmrg/* Set a graphics mode */ 118245bc899bSmrgstatic Bool 118345bc899bSmrgVESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 118445bc899bSmrg{ 118545bc899bSmrg VESAPtr pVesa; 118645bc899bSmrg VbeModeInfoData *data; 118745bc899bSmrg int mode; 118845bc899bSmrg 118945bc899bSmrg pVesa = VESAGetRec(pScrn); 119045bc899bSmrg 119145bc899bSmrg data = (VbeModeInfoData*)pMode->Private; 119250f2e948Smrg 119350f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 119450f2e948Smrg "Setting up VESA Mode 0x%X (%dx%d)\n", 119550f2e948Smrg data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay); 119650f2e948Smrg 119750f2e948Smrg /* careful, setting the bit means don't clear the screen */ 119850f2e948Smrg mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15)); 119945bc899bSmrg 120045bc899bSmrg /* enable linear addressing */ 120145bc899bSmrg if (pVesa->mapPhys != 0xa0000) 120245bc899bSmrg mode |= 1 << 14; 120345bc899bSmrg 120445bc899bSmrg if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) { 120545bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed"); 120645bc899bSmrg if ((data->block || (data->mode & (1 << 11))) && 120745bc899bSmrg VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) { 120845bc899bSmrg /* Some cards do not like setting the clock. 120945bc899bSmrg * Free it as it will not be any longer useful 121045bc899bSmrg */ 12115592a31fSmrg xf86ErrorF(", mode set without customized refresh.\n"); 1212b40a6198Smrg free(data->block); 121345bc899bSmrg data->block = NULL; 121445bc899bSmrg data->mode &= ~(1 << 11); 121545bc899bSmrg } 121645bc899bSmrg else { 121745bc899bSmrg ErrorF("\n"); 121845bc899bSmrg return (FALSE); 121945bc899bSmrg } 122045bc899bSmrg } 122145bc899bSmrg 122245bc899bSmrg pVesa->bankSwitchWindowB = 122345bc899bSmrg !((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0)); 122445bc899bSmrg 122545bc899bSmrg if (data->data->XResolution != pScrn->displayWidth) 122645bc899bSmrg VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth); 122745bc899bSmrg 122845bc899bSmrg if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 && 122950f2e948Smrg !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7)) 123045bc899bSmrg VBESetGetDACPaletteFormat(pVesa->pVbe, 8); 123145bc899bSmrg 123245bc899bSmrg pScrn->vtSema = TRUE; 123345bc899bSmrg 123445bc899bSmrg return (TRUE); 123545bc899bSmrg} 123645bc899bSmrg 123745bc899bSmrgstatic void 1238b40a6198SmrgVESAAdjustFrame(ADJUST_FRAME_ARGS_DECL) 123945bc899bSmrg{ 1240b40a6198Smrg SCRN_INFO_PTR(arg); 1241b40a6198Smrg VESAPtr pVesa = VESAGetRec(pScrn); 124245bc899bSmrg 124345bc899bSmrg VBESetDisplayStart(pVesa->pVbe, x, y, TRUE); 124445bc899bSmrg} 124545bc899bSmrg 124645bc899bSmrgstatic void 1247b40a6198SmrgVESAFreeScreen(FREE_SCREEN_ARGS_DECL) 124845bc899bSmrg{ 1249b40a6198Smrg SCRN_INFO_PTR(arg); 1250b40a6198Smrg VESAFreeRec(pScrn); 125145bc899bSmrg} 125245bc899bSmrg 125345bc899bSmrgstatic Bool 125445bc899bSmrgVESAMapVidMem(ScrnInfoPtr pScrn) 125545bc899bSmrg{ 125645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 125745bc899bSmrg 125845bc899bSmrg if (pVesa->base != NULL) 125945bc899bSmrg return (TRUE); 126045bc899bSmrg 126145bc899bSmrg pScrn->memPhysBase = pVesa->mapPhys; 126245bc899bSmrg pScrn->fbOffset = pVesa->mapOff; 126345bc899bSmrg 126450f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 1265b40a6198Smrg if (pVesa->pciInfo != NULL) { 1266b40a6198Smrg if (pVesa->mapPhys != 0xa0000) { 1267b40a6198Smrg (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase, 1268b40a6198Smrg pVesa->mapSize, 1269b40a6198Smrg (PCI_DEV_MAP_FLAG_WRITABLE 1270b40a6198Smrg | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 1271b40a6198Smrg & pVesa->base); 1272b40a6198Smrg 1273b40a6198Smrg if (pVesa->base) 1274b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000, 1275b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1276b40a6198Smrg & pVesa->VGAbase); 1277b40a6198Smrg } 1278b40a6198Smrg else { 1279b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase, 1280b40a6198Smrg pVesa->mapSize, 1281b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1282b40a6198Smrg & pVesa->base); 128350f2e948Smrg 1284b40a6198Smrg if (pVesa->base) 1285b40a6198Smrg pVesa->VGAbase = pVesa->base; 1286b40a6198Smrg } 128750f2e948Smrg } 128850f2e948Smrg#else 128945bc899bSmrg if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI) 129045bc899bSmrg pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 129145bc899bSmrg pVesa->pciTag, pScrn->memPhysBase, 129245bc899bSmrg pVesa->mapSize); 129345bc899bSmrg else 129445bc899bSmrg pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag, 129545bc899bSmrg pScrn->memPhysBase, pVesa->mapSize); 129645bc899bSmrg 129745bc899bSmrg if (pVesa->base) { 129845bc899bSmrg if (pVesa->mapPhys != 0xa0000) 129945bc899bSmrg pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0, 130045bc899bSmrg pVesa->pciTag, 130145bc899bSmrg 0xa0000, 0x10000); 130245bc899bSmrg else 130345bc899bSmrg pVesa->VGAbase = pVesa->base; 130445bc899bSmrg } 130550f2e948Smrg#endif 130645bc899bSmrg 1307b40a6198Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 130845bc899bSmrg pVesa->ioBase = pScrn->domainIOBase; 1309b40a6198Smrg#else 1310b40a6198Smrg pVesa->ioBase = 0; 1311b40a6198Smrg#endif 131245bc899bSmrg 131345bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 131445bc899bSmrg "virtual address = %p,\n" 131545bc899bSmrg "\tphysical address = 0x%lx, size = %ld\n", 131645bc899bSmrg pVesa->base, pScrn->memPhysBase, pVesa->mapSize); 131745bc899bSmrg 131845bc899bSmrg return (pVesa->base != NULL); 131945bc899bSmrg} 132045bc899bSmrg 132145bc899bSmrgstatic void 132245bc899bSmrgVESAUnmapVidMem(ScrnInfoPtr pScrn) 132345bc899bSmrg{ 132445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 132545bc899bSmrg 132645bc899bSmrg if (pVesa->base == NULL) 132745bc899bSmrg return; 132845bc899bSmrg 132950f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 133050f2e948Smrg if (pVesa->mapPhys != 0xa0000) { 133150f2e948Smrg (void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base, 133250f2e948Smrg pVesa->mapSize); 1333b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase, 1334b40a6198Smrg 0x10000); 133550f2e948Smrg } 133650f2e948Smrg else { 1337b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base, 1338b40a6198Smrg pVesa->mapSize); 133950f2e948Smrg } 134050f2e948Smrg#else 134145bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize); 134245bc899bSmrg if (pVesa->mapPhys != 0xa0000) 134345bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000); 134450f2e948Smrg#endif 134545bc899bSmrg pVesa->base = NULL; 134645bc899bSmrg} 134745bc899bSmrg 13485592a31fSmrg/* This code works, but is very slow for programs that use it intensively */ 134945bc899bSmrgstatic void 135045bc899bSmrgVESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 135145bc899bSmrg LOCO *colors, VisualPtr pVisual) 135245bc899bSmrg{ 135345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 135445bc899bSmrg int i, idx; 135545bc899bSmrg int base; 135645bc899bSmrg 135745bc899bSmrg if (pVesa->pal == NULL) 1358b40a6198Smrg pVesa->pal = calloc(1, sizeof(CARD32) * 256); 135945bc899bSmrg 136045bc899bSmrg for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) { 136145bc899bSmrg int j = indices[i]; 136245bc899bSmrg 136345bc899bSmrg if (j < 0 || j >= 256) 136445bc899bSmrg continue; 136545bc899bSmrg pVesa->pal[j] = colors[j].blue | 136645bc899bSmrg (colors[j].green << 8) | 136745bc899bSmrg (colors[j].red << 16); 136845bc899bSmrg if (j != idx) { 136945bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 137045bc899bSmrg pVesa->pal + base, FALSE, TRUE); 137145bc899bSmrg idx = base = j; 137245bc899bSmrg } 137345bc899bSmrg } 137445bc899bSmrg 137545bc899bSmrg if (idx - 1 == indices[i - 1]) 137645bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 137745bc899bSmrg pVesa->pal + base, FALSE, TRUE); 137845bc899bSmrg} 137945bc899bSmrg 138045bc899bSmrg/* 138145bc899bSmrg * Just adapted from the std* functions in vgaHW.c 138245bc899bSmrg */ 138345bc899bSmrgstatic void 138445bc899bSmrgWriteAttr(VESAPtr pVesa, int index, int value) 138545bc899bSmrg{ 138645bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 138745bc899bSmrg 138845bc899bSmrg index |= 0x20; 138945bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 139045bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_DATA_W, value); 139145bc899bSmrg} 139245bc899bSmrg 139345bc899bSmrgstatic int 139445bc899bSmrgReadAttr(VESAPtr pVesa, int index) 139545bc899bSmrg{ 139645bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 139745bc899bSmrg 139845bc899bSmrg index |= 0x20; 139945bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 140045bc899bSmrg return (inb(pVesa->ioBase + VGA_ATTR_DATA_R)); 140145bc899bSmrg} 140245bc899bSmrg 140345bc899bSmrg#define WriteMiscOut(value) outb(pVesa->ioBase + VGA_MISC_OUT_W, value) 140445bc899bSmrg#define ReadMiscOut() inb(pVesa->ioBase + VGA_MISC_OUT_R) 140545bc899bSmrg#define WriteSeq(index, value) outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\ 140645bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_DATA, value) 140745bc899bSmrg 140845bc899bSmrgstatic int 140945bc899bSmrgReadSeq(VESAPtr pVesa, int index) 141045bc899bSmrg{ 141145bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_INDEX, index); 141245bc899bSmrg 141345bc899bSmrg return (inb(pVesa->ioBase + VGA_SEQ_DATA)); 141445bc899bSmrg} 141545bc899bSmrg 141645bc899bSmrg#define WriteGr(index, value) \ 141745bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); \ 141845bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_DATA, value) 141945bc899bSmrg 142045bc899bSmrgstatic int 142145bc899bSmrgReadGr(VESAPtr pVesa, int index) 142245bc899bSmrg{ 142345bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); 142445bc899bSmrg 142545bc899bSmrg return (inb(pVesa->ioBase + VGA_GRAPH_DATA)); 142645bc899bSmrg} 142745bc899bSmrg 142845bc899bSmrg#define WriteCrtc(index, value) \ 142945bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \ 143045bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value) 143145bc899bSmrg 143245bc899bSmrgstatic void 143345bc899bSmrgSeqReset(VESAPtr pVesa, Bool start) 143445bc899bSmrg{ 143545bc899bSmrg if (start) { 143645bc899bSmrg WriteSeq(0x00, 0x01); /* Synchronous Reset */ 143745bc899bSmrg } 143845bc899bSmrg else { 143945bc899bSmrg WriteSeq(0x00, 0x03); /* End Reset */ 144045bc899bSmrg } 144145bc899bSmrg} 144245bc899bSmrg 144345bc899bSmrgstatic void 144445bc899bSmrgSaveFonts(ScrnInfoPtr pScrn) 144545bc899bSmrg{ 144645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 144745bc899bSmrg unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 144845bc899bSmrg 144945bc899bSmrg if (pVesa->fonts != NULL) 145045bc899bSmrg return; 145145bc899bSmrg 145245bc899bSmrg /* If in graphics mode, don't save anything */ 145345bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 145445bc899bSmrg if (attr10 & 0x01) 145545bc899bSmrg return; 145645bc899bSmrg 1457b40a6198Smrg pVesa->fonts = malloc(16384); 145845bc899bSmrg 145945bc899bSmrg /* save the registers that are needed here */ 146045bc899bSmrg miscOut = ReadMiscOut(); 146145bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 146245bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 146345bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 146445bc899bSmrg seq2 = ReadSeq(pVesa, 0x02); 146545bc899bSmrg seq4 = ReadSeq(pVesa, 0x04); 146645bc899bSmrg 146745bc899bSmrg /* Force into colour mode */ 146845bc899bSmrg WriteMiscOut(miscOut | 0x01); 146945bc899bSmrg 147045bc899bSmrg scrn = ReadSeq(pVesa, 0x01) | 0x20; 147145bc899bSmrg SeqReset(pVesa, TRUE); 147245bc899bSmrg WriteSeq(0x01, scrn); 147345bc899bSmrg SeqReset(pVesa, FALSE); 147445bc899bSmrg 147545bc899bSmrg WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 147645bc899bSmrg 147745bc899bSmrg /*font1 */ 147845bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 147945bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 148045bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 148145bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 148245bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 148345bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192); 148445bc899bSmrg 148545bc899bSmrg /* font2 */ 148645bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 148745bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 148845bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 148945bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 149045bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 149145bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192); 149245bc899bSmrg 149345bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 149445bc899bSmrg SeqReset(pVesa, TRUE); 149545bc899bSmrg WriteSeq(0x01, scrn); 149645bc899bSmrg SeqReset(pVesa, FALSE); 149745bc899bSmrg 149845bc899bSmrg /* Restore clobbered registers */ 149945bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 150045bc899bSmrg WriteSeq(0x02, seq2); 150145bc899bSmrg WriteSeq(0x04, seq4); 150245bc899bSmrg WriteGr(0x04, gr4); 150345bc899bSmrg WriteGr(0x05, gr5); 150445bc899bSmrg WriteGr(0x06, gr6); 150545bc899bSmrg WriteMiscOut(miscOut); 150645bc899bSmrg} 150745bc899bSmrg 150845bc899bSmrgstatic void 150945bc899bSmrgRestoreFonts(ScrnInfoPtr pScrn) 151045bc899bSmrg{ 151145bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 151245bc899bSmrg unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 151345bc899bSmrg 151445bc899bSmrg if (pVesa->fonts == NULL) 151545bc899bSmrg return; 151645bc899bSmrg 151745bc899bSmrg if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0) 151845bc899bSmrg VESABankSwitch(pScrn->pScreen, 0); 151945bc899bSmrg 152045bc899bSmrg /* save the registers that are needed here */ 152145bc899bSmrg miscOut = ReadMiscOut(); 152245bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 152345bc899bSmrg gr1 = ReadGr(pVesa, 0x01); 152445bc899bSmrg gr3 = ReadGr(pVesa, 0x03); 152545bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 152645bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 152745bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 152845bc899bSmrg gr8 = ReadGr(pVesa, 0x08); 152945bc899bSmrg seq2 = ReadSeq(pVesa, 0x02); 153045bc899bSmrg seq4 = ReadSeq(pVesa, 0x04); 153145bc899bSmrg 153245bc899bSmrg /* Force into colour mode */ 153345bc899bSmrg WriteMiscOut(miscOut | 0x01); 153445bc899bSmrg 153545bc899bSmrg scrn = ReadSeq(pVesa, 0x01) | 0x20; 153645bc899bSmrg SeqReset(pVesa, TRUE); 153745bc899bSmrg WriteSeq(0x01, scrn); 153845bc899bSmrg SeqReset(pVesa, FALSE); 153945bc899bSmrg 154045bc899bSmrg WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 154145bc899bSmrg if (pScrn->depth == 4) { 154245bc899bSmrg /* GJA */ 154345bc899bSmrg WriteGr(0x03, 0x00); /* don't rotate, write unmodified */ 154445bc899bSmrg WriteGr(0x08, 0xFF); /* write all bits in a byte */ 154545bc899bSmrg WriteGr(0x01, 0x00); /* all planes come from CPU */ 154645bc899bSmrg } 154745bc899bSmrg 154845bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 154945bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 155045bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 155145bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 155245bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 155345bc899bSmrg slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192); 155445bc899bSmrg 155545bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 155645bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 155745bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 155845bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 155945bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 156045bc899bSmrg slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192); 156145bc899bSmrg 156245bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 156345bc899bSmrg SeqReset(pVesa, TRUE); 156445bc899bSmrg WriteSeq(0x01, scrn); 156545bc899bSmrg SeqReset(pVesa, FALSE); 156645bc899bSmrg 156745bc899bSmrg /* restore the registers that were changed */ 156845bc899bSmrg WriteMiscOut(miscOut); 156945bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 157045bc899bSmrg WriteGr(0x01, gr1); 157145bc899bSmrg WriteGr(0x03, gr3); 157245bc899bSmrg WriteGr(0x04, gr4); 157345bc899bSmrg WriteGr(0x05, gr5); 157445bc899bSmrg WriteGr(0x06, gr6); 157545bc899bSmrg WriteGr(0x08, gr8); 157645bc899bSmrg WriteSeq(0x02, seq2); 157745bc899bSmrg WriteSeq(0x04, seq4); 157845bc899bSmrg} 157945bc899bSmrg 158045bc899bSmrgstatic Bool 158145bc899bSmrgVESASaveScreen(ScreenPtr pScreen, int mode) 158245bc899bSmrg{ 1583b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 158445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 158545bc899bSmrg Bool on = xf86IsUnblank(mode); 158645bc899bSmrg 158745bc899bSmrg if (on) 158845bc899bSmrg SetTimeSinceLastInputEvent(); 158945bc899bSmrg 159045bc899bSmrg if (pScrn->vtSema) { 159145bc899bSmrg unsigned char scrn = ReadSeq(pVesa, 0x01); 159245bc899bSmrg 159345bc899bSmrg if (on) 159445bc899bSmrg scrn &= ~0x20; 159545bc899bSmrg else 159645bc899bSmrg scrn |= 0x20; 159745bc899bSmrg SeqReset(pVesa, TRUE); 159845bc899bSmrg WriteSeq(0x01, scrn); 159945bc899bSmrg SeqReset(pVesa, FALSE); 160045bc899bSmrg } 160145bc899bSmrg 160245bc899bSmrg return (TRUE); 160345bc899bSmrg} 160445bc899bSmrg 160545bc899bSmrgstatic int 160645bc899bSmrgVESABankSwitch(ScreenPtr pScreen, unsigned int iBank) 160745bc899bSmrg{ 1608b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 160945bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 161045bc899bSmrg 161145bc899bSmrg if (pVesa->curBank == iBank) 161245bc899bSmrg return (0); 161345bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 0)) 161445bc899bSmrg return (1); 161545bc899bSmrg if (pVesa->bankSwitchWindowB) { 161645bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 1)) 161745bc899bSmrg return (1); 161845bc899bSmrg } 161945bc899bSmrg pVesa->curBank = iBank; 162045bc899bSmrg 162145bc899bSmrg return (0); 162245bc899bSmrg} 162345bc899bSmrg 162445bc899bSmrgBool 162545bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 162645bc899bSmrg{ 162745bc899bSmrg VESAPtr pVesa; 162845bc899bSmrg 162945bc899bSmrg if (MODE_QUERY < 0 || function > MODE_RESTORE) 163045bc899bSmrg return (FALSE); 163145bc899bSmrg 163245bc899bSmrg pVesa = VESAGetRec(pScrn); 163345bc899bSmrg 163445bc899bSmrg 163545bc899bSmrg /* Query amount of memory to save state */ 163645bc899bSmrg if (function == MODE_QUERY || 163745bc899bSmrg (function == MODE_SAVE && pVesa->state == NULL)) { 163845bc899bSmrg 163945bc899bSmrg /* Make sure we save at least this information in case of failure */ 164045bc899bSmrg (void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode); 164145bc899bSmrg SaveFonts(pScrn); 164245bc899bSmrg 164345bc899bSmrg if (pVesa->major > 1) { 164445bc899bSmrg if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state, 164545bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 164645bc899bSmrg return FALSE; 164745bc899bSmrg 164845bc899bSmrg } 164945bc899bSmrg } 165045bc899bSmrg 165145bc899bSmrg /* Save/Restore Super VGA state */ 165245bc899bSmrg if (function != MODE_QUERY) { 165345bc899bSmrg Bool retval = TRUE; 165445bc899bSmrg 165545bc899bSmrg if (pVesa->major > 1) { 165645bc899bSmrg if (function == MODE_RESTORE) 165745bc899bSmrg memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize); 165845bc899bSmrg 165945bc899bSmrg if ((retval = VBESaveRestore(pVesa->pVbe,function, 166045bc899bSmrg (pointer)&pVesa->state, 166145bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 166245bc899bSmrg && function == MODE_SAVE) { 166345bc899bSmrg /* don't rely on the memory not being touched */ 166445bc899bSmrg if (pVesa->pstate == NULL) 1665b40a6198Smrg pVesa->pstate = malloc(pVesa->stateSize); 166645bc899bSmrg memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize); 166745bc899bSmrg } 166845bc899bSmrg } 166945bc899bSmrg 167045bc899bSmrg if (function == MODE_RESTORE) { 167145bc899bSmrg VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL); 167245bc899bSmrg RestoreFonts(pScrn); 167345bc899bSmrg } 167445bc899bSmrg 167545bc899bSmrg if (!retval) 167645bc899bSmrg return (FALSE); 167745bc899bSmrg 167845bc899bSmrg } 167945bc899bSmrg 168045bc899bSmrg return (TRUE); 168145bc899bSmrg} 168245bc899bSmrg 168345bc899bSmrgstatic void 168445bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 168545bc899bSmrg int flags) 168645bc899bSmrg{ 168745bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 168845bc899bSmrg 168945bc899bSmrg if (!pScrn->vtSema) 169045bc899bSmrg return; 169145bc899bSmrg 169250f2e948Smrg VBEDPMSSet(pVesa->pVbe, mode); 169345bc899bSmrg} 169445bc899bSmrg 169545bc899bSmrg/*********************************************************************** 169645bc899bSmrg * DGA stuff 169745bc899bSmrg ***********************************************************************/ 169845bc899bSmrgstatic Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 169945bc899bSmrg unsigned char **ApertureBase, 170045bc899bSmrg int *ApertureSize, int *ApertureOffset, 170145bc899bSmrg int *flags); 170245bc899bSmrgstatic Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode); 170345bc899bSmrgstatic void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 170445bc899bSmrg 170545bc899bSmrgstatic Bool 170645bc899bSmrgVESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 170745bc899bSmrg unsigned char **ApertureBase, int *ApertureSize, 170845bc899bSmrg int *ApertureOffset, int *flags) 170945bc899bSmrg{ 171045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 171145bc899bSmrg 171245bc899bSmrg *DeviceName = NULL; /* No special device */ 171345bc899bSmrg *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys); 171445bc899bSmrg *ApertureSize = pVesa->mapSize; 171545bc899bSmrg *ApertureOffset = pVesa->mapOff; 171645bc899bSmrg *flags = DGA_NEED_ROOT; 171745bc899bSmrg 171845bc899bSmrg return (TRUE); 171945bc899bSmrg} 172045bc899bSmrg 172145bc899bSmrgstatic Bool 172245bc899bSmrgVESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 172345bc899bSmrg{ 172445bc899bSmrg DisplayModePtr pMode; 172545bc899bSmrg int scrnIdx = pScrn->pScreen->myNum; 172645bc899bSmrg int frameX0, frameY0; 172745bc899bSmrg 172845bc899bSmrg if (pDGAMode) { 172945bc899bSmrg pMode = pDGAMode->mode; 173045bc899bSmrg frameX0 = frameY0 = 0; 173145bc899bSmrg } 173245bc899bSmrg else { 173345bc899bSmrg if (!(pMode = pScrn->currentMode)) 173445bc899bSmrg return (TRUE); 173545bc899bSmrg 173645bc899bSmrg frameX0 = pScrn->frameX0; 173745bc899bSmrg frameY0 = pScrn->frameY0; 173845bc899bSmrg } 173945bc899bSmrg 1740b40a6198Smrg if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 174145bc899bSmrg return (FALSE); 1742b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 174345bc899bSmrg 174445bc899bSmrg return (TRUE); 174545bc899bSmrg} 174645bc899bSmrg 174745bc899bSmrgstatic void 174845bc899bSmrgVESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 174945bc899bSmrg{ 1750b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 175145bc899bSmrg} 175245bc899bSmrg 175345bc899bSmrgstatic int 175445bc899bSmrgVESADGAGetViewport(ScrnInfoPtr pScrn) 175545bc899bSmrg{ 175645bc899bSmrg return (0); 175745bc899bSmrg} 175845bc899bSmrg 175945bc899bSmrgstatic DGAFunctionRec VESADGAFunctions = 176045bc899bSmrg{ 176145bc899bSmrg VESADGAOpenFramebuffer, 176245bc899bSmrg NULL, /* CloseFramebuffer */ 176345bc899bSmrg VESADGASetMode, 176445bc899bSmrg VESADGASetViewport, 176545bc899bSmrg VESADGAGetViewport, 176645bc899bSmrg NULL, /* Sync */ 176745bc899bSmrg NULL, /* FillRect */ 176845bc899bSmrg NULL, /* BlitRect */ 176945bc899bSmrg NULL, /* BlitTransRect */ 177045bc899bSmrg}; 177145bc899bSmrg 177245bc899bSmrgstatic void 177345bc899bSmrgVESADGAAddModes(ScrnInfoPtr pScrn) 177445bc899bSmrg{ 177545bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 177645bc899bSmrg DisplayModePtr pMode = pScrn->modes; 177745bc899bSmrg DGAModePtr pDGAMode; 177845bc899bSmrg 177945bc899bSmrg do { 1780b40a6198Smrg pDGAMode = realloc(pVesa->pDGAMode, 178145bc899bSmrg (pVesa->nDGAMode + 1) * sizeof(DGAModeRec)); 178245bc899bSmrg if (!pDGAMode) 178345bc899bSmrg break; 178445bc899bSmrg 178545bc899bSmrg pVesa->pDGAMode = pDGAMode; 178645bc899bSmrg pDGAMode += pVesa->nDGAMode; 178745bc899bSmrg (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 178845bc899bSmrg 178945bc899bSmrg ++pVesa->nDGAMode; 179045bc899bSmrg pDGAMode->mode = pMode; 179145bc899bSmrg pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 179245bc899bSmrg pDGAMode->byteOrder = pScrn->imageByteOrder; 179345bc899bSmrg pDGAMode->depth = pScrn->depth; 179445bc899bSmrg pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 179545bc899bSmrg pDGAMode->red_mask = pScrn->mask.red; 179645bc899bSmrg pDGAMode->green_mask = pScrn->mask.green; 179745bc899bSmrg pDGAMode->blue_mask = pScrn->mask.blue; 179845bc899bSmrg pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 179945bc899bSmrg TrueColor : PseudoColor; 180045bc899bSmrg pDGAMode->xViewportStep = 1; 180145bc899bSmrg pDGAMode->yViewportStep = 1; 180245bc899bSmrg pDGAMode->viewportWidth = pMode->HDisplay; 180345bc899bSmrg pDGAMode->viewportHeight = pMode->VDisplay; 180445bc899bSmrg 180545bc899bSmrg pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline; 180645bc899bSmrg pDGAMode->imageWidth = pMode->HDisplay; 180745bc899bSmrg pDGAMode->imageHeight = pMode->VDisplay; 180845bc899bSmrg pDGAMode->pixmapWidth = pDGAMode->imageWidth; 180945bc899bSmrg pDGAMode->pixmapHeight = pDGAMode->imageHeight; 181045bc899bSmrg pDGAMode->maxViewportX = pScrn->virtualX - 181145bc899bSmrg pDGAMode->viewportWidth; 181245bc899bSmrg pDGAMode->maxViewportY = pScrn->virtualY - 181345bc899bSmrg pDGAMode->viewportHeight; 181445bc899bSmrg 181545bc899bSmrg pDGAMode->address = pVesa->base; 181645bc899bSmrg 181745bc899bSmrg pMode = pMode->next; 181845bc899bSmrg } while (pMode != pScrn->modes); 181945bc899bSmrg} 182045bc899bSmrg 182145bc899bSmrgstatic Bool 182245bc899bSmrgVESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 182345bc899bSmrg{ 182445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 182545bc899bSmrg 182645bc899bSmrg if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L) 182745bc899bSmrg return (FALSE); 182845bc899bSmrg 182945bc899bSmrg if (!pVesa->nDGAMode) 183045bc899bSmrg VESADGAAddModes(pScrn); 183145bc899bSmrg 183245bc899bSmrg return (DGAInit(pScreen, &VESADGAFunctions, 183345bc899bSmrg pVesa->pDGAMode, pVesa->nDGAMode)); 183445bc899bSmrg} 1835