vesa.c revision 78f6f648
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> 46a0c41156Smrg#include <unistd.h> 47e8b4ed9fSmrg#include <dirent.h> 4845bc899bSmrg#include "vesa.h" 4945bc899bSmrg 5045bc899bSmrg/* All drivers initialising the SW cursor need this */ 5145bc899bSmrg#include "mipointer.h" 5245bc899bSmrg 5345bc899bSmrg/* Colormap handling */ 5445bc899bSmrg#include "micmap.h" 5545bc899bSmrg#include "xf86cmap.h" 5650f2e948Smrg#include "xf86Modes.h" 5745bc899bSmrg 5845bc899bSmrg/* DPMS */ 593a925b30Smrg#ifdef HAVE_XEXTPROTO_71 603a925b30Smrg#include <X11/extensions/dpmsconst.h> 613a925b30Smrg#else 6245bc899bSmrg#define DPMS_SERVER 6345bc899bSmrg#include <X11/extensions/dpms.h> 643a925b30Smrg#endif 65b40a6198Smrg#include "compat-api.h" 6645bc899bSmrg 6778f6f648Smrg#if defined(__NetBSD__) 6878f6f648Smrg#include <sys/sysctl.h> 6978f6f648Smrg#endif 7078f6f648Smrg 7145bc899bSmrg/* Mandatory functions */ 7245bc899bSmrgstatic const OptionInfoRec * VESAAvailableOptions(int chipid, int busid); 7345bc899bSmrgstatic void VESAIdentify(int flags); 74f2408745Smrg#if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA) 75f2408745Smrg#define VESAProbe NULL 76f2408745Smrg#else 7745bc899bSmrgstatic Bool VESAProbe(DriverPtr drv, int flags); 78f2408745Smrg#endif 7950f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 8050f2e948Smrgstatic Bool VESAPciProbe(DriverPtr drv, int entity_num, 8150f2e948Smrg struct pci_device *dev, intptr_t match_data); 8250f2e948Smrg#endif 8345bc899bSmrgstatic Bool VESAPreInit(ScrnInfoPtr pScrn, int flags); 84b40a6198Smrgstatic Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL); 85b40a6198Smrgstatic Bool VESAEnterVT(VT_FUNC_ARGS_DECL); 86b40a6198Smrgstatic void VESALeaveVT(VT_FUNC_ARGS_DECL); 87b40a6198Smrgstatic Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL); 8845bc899bSmrgstatic Bool VESASaveScreen(ScreenPtr pScreen, int mode); 8945bc899bSmrg 90b40a6198Smrgstatic Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL); 9145bc899bSmrgstatic Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); 92b40a6198Smrgstatic void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL); 93b40a6198Smrgstatic void VESAFreeScreen(FREE_SCREEN_ARGS_DECL); 9445bc899bSmrgstatic void VESAFreeRec(ScrnInfoPtr pScrn); 9550f2e948Smrgstatic VESAPtr VESAGetRec(ScrnInfoPtr pScrn); 9645bc899bSmrg 9745bc899bSmrgstatic void 9845bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 9945bc899bSmrg int flags); 10045bc899bSmrg 10145bc899bSmrg/* locally used functions */ 1025592a31fSmrg#ifdef HAVE_ISA 10345bc899bSmrgstatic int VESAFindIsaDevice(GDevPtr dev); 1045592a31fSmrg#endif 10545bc899bSmrgstatic Bool VESAMapVidMem(ScrnInfoPtr pScrn); 10645bc899bSmrgstatic void VESAUnmapVidMem(ScrnInfoPtr pScrn); 10745bc899bSmrgstatic int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank); 10845bc899bSmrgstatic void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 10945bc899bSmrg LOCO *colors, VisualPtr pVisual); 11045bc899bSmrgstatic void SaveFonts(ScrnInfoPtr pScrn); 11145bc899bSmrgstatic void RestoreFonts(ScrnInfoPtr pScrn); 11245bc899bSmrgstatic Bool 11345bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); 11445bc899bSmrg 1155592a31fSmrgstatic void * 1165592a31fSmrgVESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1175592a31fSmrg CARD32 *size, void *closure) 1185592a31fSmrg{ 119b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1205592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1215592a31fSmrg 1225592a31fSmrg *size = pVesa->maxBytesPerScanline; 1235592a31fSmrg return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset); 1245592a31fSmrg} 1255592a31fSmrg 1265592a31fSmrgstatic void * 1275592a31fSmrgVESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1285592a31fSmrg CARD32 *size, void *closure) 1295592a31fSmrg{ 130b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1315592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1325592a31fSmrg VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 1335592a31fSmrg int window; 1345592a31fSmrg 1355592a31fSmrg offset += pVesa->maxBytesPerScanline * row; 1365592a31fSmrg window = offset / (data->WinGranularity * 1024); 1375592a31fSmrg pVesa->windowAoffset = window * data->WinGranularity * 1024; 1385592a31fSmrg VESABankSwitch(pScreen, window); 1395592a31fSmrg *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset); 1405592a31fSmrg 1415592a31fSmrg return (void *)((unsigned long)pVesa->base + 1425592a31fSmrg (offset - pVesa->windowAoffset)); 1435592a31fSmrg} 1445592a31fSmrg 1455592a31fSmrgstatic void 1465592a31fSmrgvesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 1475592a31fSmrg{ 1485592a31fSmrg shadowUpdatePacked(pScreen, pBuf); 1495592a31fSmrg} 15045bc899bSmrg 15145bc899bSmrgstatic Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen); 15245bc899bSmrg 15345bc899bSmrgenum GenericTypes 15445bc899bSmrg{ 15545bc899bSmrg CHIP_VESA_GENERIC 15645bc899bSmrg}; 15745bc899bSmrg 15850f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 15950f2e948Smrgstatic const struct pci_id_match vesa_device_match[] = { 16050f2e948Smrg { 16150f2e948Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 16250f2e948Smrg 0x00030000, 0x00ffffff, CHIP_VESA_GENERIC 16350f2e948Smrg }, 16450f2e948Smrg 16550f2e948Smrg { 0, 0, 0 }, 16650f2e948Smrg}; 16750f2e948Smrg#endif 16850f2e948Smrg 16945bc899bSmrg/* Supported chipsets */ 17045bc899bSmrgstatic SymTabRec VESAChipsets[] = 17145bc899bSmrg{ 17245bc899bSmrg {CHIP_VESA_GENERIC, "vesa"}, 17345bc899bSmrg {-1, NULL} 17445bc899bSmrg}; 17545bc899bSmrg 17650f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 17745bc899bSmrgstatic PciChipsets VESAPCIchipsets[] = { 17845bc899bSmrg { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA }, 17945bc899bSmrg { -1, -1, RES_UNDEFINED }, 18045bc899bSmrg}; 18150f2e948Smrg#endif 18245bc899bSmrg 18350f2e948Smrg#ifdef HAVE_ISA 18445bc899bSmrgstatic IsaChipsets VESAISAchipsets[] = { 18545bc899bSmrg {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA}, 18645bc899bSmrg {-1, 0 } 18745bc899bSmrg}; 18850f2e948Smrg#endif 18950f2e948Smrg 19050f2e948Smrg 19150f2e948Smrg/* 19250f2e948Smrg * This contains the functions needed by the server after loading the 19350f2e948Smrg * driver module. It must be supplied, and gets added the driver list by 194e8b4ed9fSmrg * the Module Setup function in the dynamic case. In the static case a 19550f2e948Smrg * reference to this is compiled in, and this requires that the name of 19650f2e948Smrg * this DriverRec be an upper-case version of the driver name. 19750f2e948Smrg */ 19850f2e948Smrg_X_EXPORT DriverRec VESA = { 19950f2e948Smrg VESA_VERSION, 20050f2e948Smrg VESA_DRIVER_NAME, 20150f2e948Smrg VESAIdentify, 20250f2e948Smrg VESAProbe, 20350f2e948Smrg VESAAvailableOptions, 20450f2e948Smrg NULL, 20550f2e948Smrg 0, 20650f2e948Smrg NULL, 20750f2e948Smrg 20850f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 20950f2e948Smrg vesa_device_match, 21050f2e948Smrg VESAPciProbe 21150f2e948Smrg#endif 21250f2e948Smrg}; 21350f2e948Smrg 21445bc899bSmrg 21545bc899bSmrgtypedef enum { 21645bc899bSmrg OPTION_SHADOW_FB, 21745bc899bSmrg OPTION_DFLT_REFRESH, 21845bc899bSmrg OPTION_MODESET_CLEAR_SCREEN 21945bc899bSmrg} VESAOpts; 22045bc899bSmrg 22145bc899bSmrgstatic const OptionInfoRec VESAOptions[] = { 22245bc899bSmrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 22345bc899bSmrg { OPTION_DFLT_REFRESH, "DefaultRefresh", OPTV_BOOLEAN, {0}, FALSE }, 22445bc899bSmrg { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen", 22545bc899bSmrg OPTV_BOOLEAN, {0}, FALSE }, 22645bc899bSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 22745bc899bSmrg}; 22845bc899bSmrg 22945bc899bSmrg#ifdef XFree86LOADER 23045bc899bSmrg 23145bc899bSmrg/* Module loader interface */ 23245bc899bSmrgstatic MODULESETUPPROTO(vesaSetup); 23345bc899bSmrg 23445bc899bSmrgstatic XF86ModuleVersionInfo vesaVersionRec = 23545bc899bSmrg{ 23645bc899bSmrg VESA_DRIVER_NAME, 23745bc899bSmrg MODULEVENDORSTRING, 23845bc899bSmrg MODINFOSTRING1, 23945bc899bSmrg MODINFOSTRING2, 24045bc899bSmrg XORG_VERSION_CURRENT, 24145bc899bSmrg VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL, 24245bc899bSmrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 24345bc899bSmrg ABI_VIDEODRV_VERSION, 24445bc899bSmrg MOD_CLASS_VIDEODRV, 24545bc899bSmrg {0, 0, 0, 0} 24645bc899bSmrg}; 24745bc899bSmrg 24845bc899bSmrg/* 24945bc899bSmrg * This data is accessed by the loader. The name must be the module name 25045bc899bSmrg * followed by "ModuleData". 25145bc899bSmrg */ 25245bc899bSmrg_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL }; 25345bc899bSmrg 25445bc899bSmrgstatic pointer 25545bc899bSmrgvesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) 25645bc899bSmrg{ 25745bc899bSmrg static Bool Initialised = FALSE; 25845bc899bSmrg 25945bc899bSmrg if (!Initialised) 26045bc899bSmrg { 26145bc899bSmrg Initialised = TRUE; 26250f2e948Smrg xf86AddDriver(&VESA, Module, 1); 26345bc899bSmrg return (pointer)TRUE; 26445bc899bSmrg } 26545bc899bSmrg 26645bc899bSmrg if (ErrorMajor) 26745bc899bSmrg *ErrorMajor = LDR_ONCEONLY; 26845bc899bSmrg return (NULL); 26945bc899bSmrg} 27045bc899bSmrg 27145bc899bSmrg#endif 27245bc899bSmrg 27345bc899bSmrgstatic const OptionInfoRec * 27445bc899bSmrgVESAAvailableOptions(int chipid, int busid) 27545bc899bSmrg{ 27645bc899bSmrg return (VESAOptions); 27745bc899bSmrg} 27845bc899bSmrg 27945bc899bSmrgstatic void 28045bc899bSmrgVESAIdentify(int flags) 28145bc899bSmrg{ 28245bc899bSmrg xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets); 28345bc899bSmrg} 28445bc899bSmrg 28550f2e948Smrgstatic VESAPtr 28650f2e948SmrgVESAGetRec(ScrnInfoPtr pScrn) 28750f2e948Smrg{ 28850f2e948Smrg if (!pScrn->driverPrivate) 289b40a6198Smrg pScrn->driverPrivate = calloc(sizeof(VESARec), 1); 29050f2e948Smrg 29150f2e948Smrg return ((VESAPtr)pScrn->driverPrivate); 29250f2e948Smrg} 29350f2e948Smrg 29450f2e948Smrg/* Only a little like VBESetModeParameters */ 29550f2e948Smrgstatic void 29650f2e948SmrgVESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode, 29750f2e948Smrg DisplayModePtr ddcmode) 29850f2e948Smrg{ 29950f2e948Smrg VbeModeInfoData *data; 30050f2e948Smrg int clock; 30150f2e948Smrg 30250f2e948Smrg data = (VbeModeInfoData *)vbemode->Private; 30350f2e948Smrg 304b40a6198Smrg data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); 30550f2e948Smrg data->block->HorizontalTotal = ddcmode->HTotal; 30650f2e948Smrg data->block->HorizontalSyncStart = ddcmode->HSyncStart; 30750f2e948Smrg data->block->HorizontalSyncEnd = ddcmode->HSyncEnd; 30850f2e948Smrg data->block->VerticalTotal = ddcmode->VTotal; 30950f2e948Smrg data->block->VerticalSyncStart = ddcmode->VSyncStart; 31050f2e948Smrg data->block->VerticalSyncEnd = ddcmode->VSyncEnd; 31150f2e948Smrg data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | 31250f2e948Smrg ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); 31350f2e948Smrg data->block->PixelClock = ddcmode->Clock * 1000; 31450f2e948Smrg 31550f2e948Smrg /* ask the BIOS to figure out the real clock */ 31650f2e948Smrg clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); 31750f2e948Smrg if (clock) 31850f2e948Smrg data->block->PixelClock = clock; 31950f2e948Smrg 32050f2e948Smrg data->mode |= (1 << 11); 32150f2e948Smrg data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) / 32250f2e948Smrg (double)(ddcmode->HTotal * ddcmode->VTotal)); 32350f2e948Smrg} 32450f2e948Smrg 325b40a6198Smrg/* 326b40a6198Smrg * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes 327b40a6198Smrg * think they can only give sizes in multiples of character cells; and 328b40a6198Smrg * indeed, the reference CVT and GTF formulae only give results where 329b40a6198Smrg * (h % 8) == 0. Whatever, let's just try to cope. What we're looking for 330b40a6198Smrg * here is cases where the display says 1366x768 and the BIOS says 1360x768. 331b40a6198Smrg */ 332b40a6198Smrgstatic Bool 333b40a6198SmrgvesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe) 334b40a6198Smrg{ 335b40a6198Smrg if (!(edid->type & M_T_DRIVER)) 336b40a6198Smrg return FALSE; 337b40a6198Smrg 338b40a6198Smrg /* never seen a height granularity... */ 339b40a6198Smrg if (edid->VDisplay != vbe->VDisplay) 340b40a6198Smrg return FALSE; 341b40a6198Smrg 342b40a6198Smrg if (edid->HDisplay >= vbe->HDisplay && 343b40a6198Smrg (edid->HDisplay & ~7) == (vbe->HDisplay & ~7)) 344b40a6198Smrg return TRUE; 345b40a6198Smrg 346b40a6198Smrg return FALSE; 347b40a6198Smrg} 348b40a6198Smrg 34950f2e948Smrgstatic ModeStatus 350b40a6198SmrgVESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass) 35150f2e948Smrg{ 352b40a6198Smrg SCRN_INFO_PTR(arg); 35350f2e948Smrg static int warned = 0; 35450f2e948Smrg int found = 0; 35550f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 35650f2e948Smrg MonPtr mon = pScrn->monitor; 35750f2e948Smrg ModeStatus ret = MODE_BAD; 35850f2e948Smrg DisplayModePtr mode; 35950f2e948Smrg float v; 36050f2e948Smrg 36150f2e948Smrg if (pass != MODECHECK_FINAL) { 36250f2e948Smrg if (!warned) { 363b40a6198Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n"); 36450f2e948Smrg warned = 1; 36550f2e948Smrg } 36650f2e948Smrg return MODE_OK; 36750f2e948Smrg } 36850f2e948Smrg 36950f2e948Smrg /* 37050f2e948Smrg * This is suboptimal. We pass in just the barest description of a mode 37150f2e948Smrg * we can get away with to VBEValidateModes, so it can't really throw 37250f2e948Smrg * out anything we give it. But we need to filter the list so that we 37350f2e948Smrg * don't populate the mode list with things the monitor can't do. 37450f2e948Smrg * 37550f2e948Smrg * So first off, if this isn't a mode we handed to the server (ie, 37650f2e948Smrg * M_T_BUILTIN), then we know we can't do it. 37750f2e948Smrg */ 37850f2e948Smrg if (!(p->type & M_T_BUILTIN)) 37950f2e948Smrg return MODE_NOMODE; 38050f2e948Smrg 38150f2e948Smrg if (pVesa->strict_validation) { 38250f2e948Smrg /* 38350f2e948Smrg * If it's our first pass at mode validation, we'll try for a strict 38450f2e948Smrg * intersection between the VBE and DDC mode lists. 38550f2e948Smrg */ 38650f2e948Smrg if (pScrn->monitor->DDC) { 38750f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) { 388b40a6198Smrg if (vesaModesCloseEnough(mode, p)) { 38950f2e948Smrg if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) { 39050f2e948Smrg found = 1; 39150f2e948Smrg break; 39250f2e948Smrg } 39350f2e948Smrg } 39450f2e948Smrg if (mode == pScrn->monitor->Last) 39550f2e948Smrg break; 39650f2e948Smrg } 39750f2e948Smrg if (!found) 39850f2e948Smrg return MODE_NOMODE; 39950f2e948Smrg 40050f2e948Smrg /* having found a matching mode, stash the CRTC values aside */ 40150f2e948Smrg VESASetModeParameters(pVesa->pVbe, p, mode); 40250f2e948Smrg return MODE_OK; 40350f2e948Smrg } 40450f2e948Smrg 40550f2e948Smrg /* No DDC and no modes make Homer something something... */ 40650f2e948Smrg return MODE_NOMODE; 40750f2e948Smrg } 40850f2e948Smrg 40950f2e948Smrg /* 41050f2e948Smrg * Finally, walk through the vsync rates 1Hz at a time looking for a mode 41150f2e948Smrg * that will fit. This is assuredly a terrible way to do this, but 41250f2e948Smrg * there's no obvious method for computing a mode of a given size that 41350f2e948Smrg * will pass xf86CheckModeForMonitor. XXX this path is terrible, but 41450f2e948Smrg * then, by this point, you're well into despair territory. 41550f2e948Smrg */ 41650f2e948Smrg for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) { 41750f2e948Smrg mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0); 41850f2e948Smrg ret = xf86CheckModeForMonitor(mode, mon); 419b40a6198Smrg free(mode->name); 420b40a6198Smrg free(mode); 42150f2e948Smrg if (ret == MODE_OK) 42250f2e948Smrg break; 42350f2e948Smrg } 42450f2e948Smrg 42550f2e948Smrg return ret; 42650f2e948Smrg} 42750f2e948Smrg 42850f2e948Smrgstatic void 42950f2e948SmrgVESAInitScrn(ScrnInfoPtr pScrn) 43050f2e948Smrg{ 43150f2e948Smrg pScrn->driverVersion = VESA_VERSION; 43250f2e948Smrg pScrn->driverName = VESA_DRIVER_NAME; 43350f2e948Smrg pScrn->name = VESA_NAME; 43450f2e948Smrg pScrn->Probe = VESAProbe; 43550f2e948Smrg pScrn->PreInit = VESAPreInit; 43650f2e948Smrg pScrn->ScreenInit = VESAScreenInit; 43750f2e948Smrg pScrn->SwitchMode = VESASwitchMode; 43850f2e948Smrg pScrn->ValidMode = VESAValidMode; 43950f2e948Smrg pScrn->AdjustFrame = VESAAdjustFrame; 44050f2e948Smrg pScrn->EnterVT = VESAEnterVT; 44150f2e948Smrg pScrn->LeaveVT = VESALeaveVT; 44250f2e948Smrg pScrn->FreeScreen = VESAFreeScreen; 44350f2e948Smrg} 44450f2e948Smrg 445e8b4ed9fSmrg#ifdef XSERVER_LIBPCIACCESS 446e8b4ed9fSmrg#ifdef __linux__ 447e8b4ed9fSmrg/* 448e8b4ed9fSmrg * check if a file exist in directory 449e8b4ed9fSmrg * should be equivalent to a glob ${directory}/${prefix}* 450e8b4ed9fSmrg */ 451e8b4ed9fSmrg 452e8b4ed9fSmrgstatic Bool 453e8b4ed9fSmrgVESAFileExistsPrefix(const char *directory, const char *prefix) { 454e8b4ed9fSmrg DIR *dir; 455e8b4ed9fSmrg struct dirent *entry; 456e8b4ed9fSmrg Bool found = FALSE; 457e8b4ed9fSmrg int len = strlen(prefix); 458e8b4ed9fSmrg 459e8b4ed9fSmrg dir = opendir(directory); 460e8b4ed9fSmrg if (!dir) 461e8b4ed9fSmrg return FALSE; 462e8b4ed9fSmrg 463e8b4ed9fSmrg while ((entry = readdir(dir)) != NULL) { 464e8b4ed9fSmrg if (strlen(entry->d_name) > len && 465e8b4ed9fSmrg !memcmp(entry->d_name, prefix, len)) { 466e8b4ed9fSmrg found = TRUE; 467e8b4ed9fSmrg break; 468e8b4ed9fSmrg } 469e8b4ed9fSmrg } 470e8b4ed9fSmrg closedir(dir); 471e8b4ed9fSmrg return found; 472e8b4ed9fSmrg} 473e8b4ed9fSmrg#endif 474e8b4ed9fSmrg 47545bc899bSmrg/* 47645bc899bSmrg * This function is called once, at the start of the first server generation to 47745bc899bSmrg * do a minimal probe for supported hardware. 47845bc899bSmrg */ 47950f2e948Smrgstatic Bool 48050f2e948SmrgVESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, 48150f2e948Smrg intptr_t match_data) 48250f2e948Smrg{ 48350f2e948Smrg ScrnInfoPtr pScrn; 484a0c41156Smrg 485a0c41156Smrg#ifdef __linux__ 486e8b4ed9fSmrg if (VESAFileExistsPrefix("/dev", "fb") || 487e8b4ed9fSmrg VESAFileExistsPrefix("/dev/dri", "card")) { 488e8b4ed9fSmrg ErrorF("vesa: Refusing to run, Framebuffer or dri device present\n"); 489a0c41156Smrg return FALSE; 490a0c41156Smrg } 491a0c41156Smrg#endif 49278f6f648Smrg#if defined(__NetBSD__) 49378f6f648Smrg { 49478f6f648Smrg char method[10]; 49578f6f648Smrg size_t len = sizeof(method); 49678f6f648Smrg 49778f6f648Smrg if (sysctlbyname("machdep.bootmethod", &method, &len, NULL, 0) == 0 && 49878f6f648Smrg strcmp(method, "UEFI") == 0) { 49978f6f648Smrg ErrorF("vesa: Refusing to run, UEFI booted\n"); 50078f6f648Smrg return FALSE; 50178f6f648Smrg } 50278f6f648Smrg } 50378f6f648Smrg#endif 504a0c41156Smrg 50550f2e948Smrg pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, 50650f2e948Smrg NULL, NULL, NULL, NULL, NULL); 50750f2e948Smrg if (pScrn != NULL) { 508b40a6198Smrg VESAPtr pVesa; 509b40a6198Smrg 510b40a6198Smrg if (pci_device_has_kernel_driver(dev)) { 511b40a6198Smrg ErrorF("vesa: Ignoring device with a bound kernel driver\n"); 512b40a6198Smrg return FALSE; 513b40a6198Smrg } 51450f2e948Smrg 515b40a6198Smrg pVesa = VESAGetRec(pScrn); 51650f2e948Smrg VESAInitScrn(pScrn); 51750f2e948Smrg pVesa->pciInfo = dev; 51850f2e948Smrg } 51950f2e948Smrg 52050f2e948Smrg return (pScrn != NULL); 52150f2e948Smrg} 52250f2e948Smrg#endif 52350f2e948Smrg 524f2408745Smrg#ifndef VESAProbe 52545bc899bSmrgstatic Bool 52645bc899bSmrgVESAProbe(DriverPtr drv, int flags) 52745bc899bSmrg{ 52845bc899bSmrg Bool foundScreen = FALSE; 52945bc899bSmrg int numDevSections, numUsed; 53045bc899bSmrg GDevPtr *devSections; 53145bc899bSmrg int *usedChips; 53245bc899bSmrg int i; 53345bc899bSmrg 53445bc899bSmrg /* 53545bc899bSmrg * Find the config file Device sections that match this 53645bc899bSmrg * driver, and return if there are none. 53745bc899bSmrg */ 53845bc899bSmrg if ((numDevSections = xf86MatchDevice(VESA_NAME, 53945bc899bSmrg &devSections)) <= 0) 54045bc899bSmrg return (FALSE); 54145bc899bSmrg 54250f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 54345bc899bSmrg /* PCI BUS */ 54445bc899bSmrg if (xf86GetPciVideoInfo()) { 54545bc899bSmrg numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC, 54645bc899bSmrg VESAChipsets, VESAPCIchipsets, 54745bc899bSmrg devSections, numDevSections, 54845bc899bSmrg drv, &usedChips); 54945bc899bSmrg if (numUsed > 0) { 55045bc899bSmrg if (flags & PROBE_DETECT) 55145bc899bSmrg foundScreen = TRUE; 55245bc899bSmrg else { 55345bc899bSmrg for (i = 0; i < numUsed; i++) { 55445bc899bSmrg ScrnInfoPtr pScrn = NULL; 55545bc899bSmrg /* Allocate a ScrnInfoRec */ 55645bc899bSmrg if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 55745bc899bSmrg VESAPCIchipsets,NULL, 55845bc899bSmrg NULL,NULL,NULL,NULL))) { 55950f2e948Smrg VESAInitScrn(pScrn); 56045bc899bSmrg foundScreen = TRUE; 56145bc899bSmrg } 56245bc899bSmrg } 56345bc899bSmrg } 564b40a6198Smrg free(usedChips); 56545bc899bSmrg } 56645bc899bSmrg } 56750f2e948Smrg#endif 56845bc899bSmrg 56950f2e948Smrg#ifdef HAVE_ISA 57045bc899bSmrg /* Isa Bus */ 57145bc899bSmrg numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets, 57245bc899bSmrg VESAISAchipsets, drv, 57345bc899bSmrg VESAFindIsaDevice, devSections, 57445bc899bSmrg numDevSections, &usedChips); 57545bc899bSmrg if(numUsed > 0) { 57645bc899bSmrg if (flags & PROBE_DETECT) 57745bc899bSmrg foundScreen = TRUE; 57845bc899bSmrg else for (i = 0; i < numUsed; i++) { 57945bc899bSmrg ScrnInfoPtr pScrn = NULL; 58045bc899bSmrg if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i], 58145bc899bSmrg VESAISAchipsets, NULL, 58245bc899bSmrg NULL, NULL, NULL, NULL))) { 58350f2e948Smrg VESAInitScrn(pScrn); 58445bc899bSmrg foundScreen = TRUE; 58545bc899bSmrg } 58645bc899bSmrg } 587b40a6198Smrg free(usedChips); 58845bc899bSmrg } 58950f2e948Smrg#endif 59045bc899bSmrg 591b40a6198Smrg free(devSections); 59245bc899bSmrg 59345bc899bSmrg return (foundScreen); 59445bc899bSmrg} 595f2408745Smrg#endif 59645bc899bSmrg 59750f2e948Smrg#ifdef HAVE_ISA 59845bc899bSmrgstatic int 59945bc899bSmrgVESAFindIsaDevice(GDevPtr dev) 60045bc899bSmrg{ 60145bc899bSmrg#ifndef PC98_EGC 60245bc899bSmrg CARD16 GenericIOBase = VGAHW_GET_IOBASE(); 60345bc899bSmrg CARD8 CurrentValue, TestValue; 60445bc899bSmrg 60545bc899bSmrg /* There's no need to unlock VGA CRTC registers here */ 60645bc899bSmrg 60745bc899bSmrg /* VGA has one more read/write attribute register than EGA */ 60845bc899bSmrg (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */ 60945bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 61045bc899bSmrg CurrentValue = inb(VGA_ATTR_DATA_R); 61145bc899bSmrg outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F); 61245bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 61345bc899bSmrg TestValue = inb(VGA_ATTR_DATA_R); 61445bc899bSmrg outb(VGA_ATTR_DATA_R, CurrentValue); 61545bc899bSmrg 61645bc899bSmrg /* Quit now if no VGA is present */ 61745bc899bSmrg if ((CurrentValue ^ 0x0F) != TestValue) 61845bc899bSmrg return -1; 61945bc899bSmrg#endif 62045bc899bSmrg return (int)CHIP_VESA_GENERIC; 62145bc899bSmrg} 62250f2e948Smrg#endif 62345bc899bSmrg 62445bc899bSmrgstatic void 62545bc899bSmrgVESAFreeRec(ScrnInfoPtr pScrn) 62645bc899bSmrg{ 62745bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 62845bc899bSmrg#if 0 62945bc899bSmrg DisplayModePtr mode = pScrn->modes; 63045bc899bSmrg /* I am not sure if the modes will ever get freed. 63145bc899bSmrg * Anyway, the data unknown to other modules is being freed here. 63245bc899bSmrg */ 63345bc899bSmrg if (mode) { 63445bc899bSmrg do { 63545bc899bSmrg if (mode->Private) { 63645bc899bSmrg VbeModeInfoData *data = (VbeModeInfoData*)mode->Private; 63745bc899bSmrg 63845bc899bSmrg if (data->block) 639b40a6198Smrg free(data->block); 64045bc899bSmrg 641b40a6198Smrg free(data); 64245bc899bSmrg 64345bc899bSmrg mode->Private = NULL; 64445bc899bSmrg } 64545bc899bSmrg mode = mode->next; 64645bc899bSmrg } while (mode && mode != pScrn->modes); 64745bc899bSmrg } 64845bc899bSmrg#endif 649b40a6198Smrg free(pVesa->monitor); 650f2408745Smrg if (pVesa->vbeInfo) 651f2408745Smrg VBEFreeVBEInfo(pVesa->vbeInfo); 652b40a6198Smrg free(pVesa->pal); 653b40a6198Smrg free(pVesa->savedPal); 654b40a6198Smrg free(pVesa->fonts); 655b40a6198Smrg free(pScrn->driverPrivate); 65645bc899bSmrg pScrn->driverPrivate = NULL; 65745bc899bSmrg} 65845bc899bSmrg 65950f2e948Smrgstatic int 66050f2e948SmrgVESAValidateModes(ScrnInfoPtr pScrn) 66150f2e948Smrg{ 66250f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 66350f2e948Smrg DisplayModePtr mode; 66450f2e948Smrg 66550f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) 66650f2e948Smrg mode->status = MODE_OK; 66750f2e948Smrg 66850f2e948Smrg return VBEValidateModes(pScrn, NULL, pScrn->display->modes, 6695592a31fSmrg NULL, NULL, 0, 32767, 1, 0, 32767, 67050f2e948Smrg pScrn->display->virtualX, 67150f2e948Smrg pScrn->display->virtualY, 67250f2e948Smrg pVesa->mapSize, LOOKUP_BEST_REFRESH); 67350f2e948Smrg} 67450f2e948Smrg 67545bc899bSmrg/* 67645bc899bSmrg * This function is called once for each screen at the start of the first 67745bc899bSmrg * server generation to initialise the screen for all server generations. 67845bc899bSmrg */ 67945bc899bSmrgstatic Bool 68045bc899bSmrgVESAPreInit(ScrnInfoPtr pScrn, int flags) 68145bc899bSmrg{ 68245bc899bSmrg VESAPtr pVesa; 68345bc899bSmrg VbeInfoBlock *vbe; 68445bc899bSmrg DisplayModePtr pMode; 68545bc899bSmrg VbeModeInfoBlock *mode; 68645bc899bSmrg Gamma gzeros = {0.0, 0.0, 0.0}; 68745bc899bSmrg rgb rzeros = {0, 0, 0}; 68845bc899bSmrg pointer pDDCModule; 68945bc899bSmrg int i; 69045bc899bSmrg int flags24 = 0; 69145bc899bSmrg int defaultDepth = 0; 69250f2e948Smrg int defaultBpp = 0; 69345bc899bSmrg int depths = 0; 69445bc899bSmrg 69545bc899bSmrg if (flags & PROBE_DETECT) 69645bc899bSmrg return (FALSE); 69745bc899bSmrg 69845bc899bSmrg pVesa = VESAGetRec(pScrn); 69945bc899bSmrg pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 70045bc899bSmrg 70145bc899bSmrg /* Load vbe module */ 70245bc899bSmrg if (!xf86LoadSubModule(pScrn, "vbe")) 70345bc899bSmrg return (FALSE); 70445bc899bSmrg 70545bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 70645bc899bSmrg SET_BIOS_SCRATCH 70745bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 70845bc899bSmrg return (FALSE); 70945bc899bSmrg 71050f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 71145bc899bSmrg if (pVesa->pEnt->location.type == BUS_PCI) { 71245bc899bSmrg pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index); 71345bc899bSmrg pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device, 71445bc899bSmrg pVesa->pciInfo->func); 71545bc899bSmrg } 71650f2e948Smrg#endif 71745bc899bSmrg 71845bc899bSmrg pScrn->chipset = "vesa"; 71945bc899bSmrg pScrn->monitor = pScrn->confScreen->monitor; 72045bc899bSmrg pScrn->progClock = TRUE; 72145bc899bSmrg pScrn->rgbBits = 8; 72245bc899bSmrg 72345bc899bSmrg if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL) 72445bc899bSmrg return (FALSE); 72545bc899bSmrg pVesa->major = (unsigned)(vbe->VESAVersion >> 8); 72645bc899bSmrg pVesa->minor = vbe->VESAVersion & 0xff; 72745bc899bSmrg pVesa->vbeInfo = vbe; 72845bc899bSmrg pScrn->videoRam = vbe->TotalMemory * 64; 72945bc899bSmrg 73045bc899bSmrg /* 73145bc899bSmrg * Find what depths are available. 73245bc899bSmrg */ 73345bc899bSmrg depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24, 73445bc899bSmrg V_MODETYPE_VBE); 73545bc899bSmrg 73645bc899bSmrg /* Preferred order for default depth selection. */ 737a0c41156Smrg if (depths & V_DEPTH_24 && (flags24 & Support32bppFb)) 73850f2e948Smrg defaultDepth = 24; 73950f2e948Smrg else if (depths & V_DEPTH_16) 74045bc899bSmrg defaultDepth = 16; 74145bc899bSmrg else if (depths & V_DEPTH_15) 74245bc899bSmrg defaultDepth = 15; 743a0c41156Smrg else if (depths & V_DEPTH_24) 744a0c41156Smrg defaultDepth = 24; /* ew though */ 74545bc899bSmrg else if (depths & V_DEPTH_8) 74645bc899bSmrg defaultDepth = 8; 74745bc899bSmrg else if (depths & V_DEPTH_4) 74845bc899bSmrg defaultDepth = 4; 74945bc899bSmrg else if (depths & V_DEPTH_1) 75045bc899bSmrg defaultDepth = 1; 75145bc899bSmrg 75250f2e948Smrg if (defaultDepth == 24 && !(flags24 & Support32bppFb)) 75350f2e948Smrg defaultBpp = 24; 75445bc899bSmrg 75550f2e948Smrg /* Prefer 32bpp because 1999 called and wants its packed pixels back */ 75650f2e948Smrg if (flags24 & Support32bppFb) 75750f2e948Smrg flags24 |= SupportConvert24to32 | PreferConvert24to32; 75845bc899bSmrg if (flags24 & Support24bppFb) 75950f2e948Smrg flags24 |= SupportConvert32to24; 76045bc899bSmrg 76150f2e948Smrg if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) { 76245bc899bSmrg vbeFree(pVesa->pVbe); 76345bc899bSmrg return (FALSE); 76445bc899bSmrg } 76545bc899bSmrg xf86PrintDepthBpp(pScrn); 76645bc899bSmrg 76745bc899bSmrg /* color weight */ 76845bc899bSmrg if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) { 76945bc899bSmrg vbeFree(pVesa->pVbe); 77045bc899bSmrg return (FALSE); 77145bc899bSmrg } 77245bc899bSmrg /* visual init */ 77345bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) { 77445bc899bSmrg vbeFree(pVesa->pVbe); 77545bc899bSmrg return (FALSE); 77645bc899bSmrg } 77745bc899bSmrg 77845bc899bSmrg xf86SetGamma(pScrn, gzeros); 77945bc899bSmrg 780f2408745Smrg /* set up options before loading any modules that may look at them */ 781f2408745Smrg xf86CollectOptions(pScrn, NULL); 782f2408745Smrg 78345bc899bSmrg if (pVesa->major >= 2) { 78445bc899bSmrg /* Load ddc module */ 78545bc899bSmrg if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { 78645bc899bSmrg vbeFree(pVesa->pVbe); 78745bc899bSmrg return (FALSE); 78845bc899bSmrg } 78945bc899bSmrg 79045bc899bSmrg if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) { 79145bc899bSmrg xf86PrintEDID(pVesa->monitor); 79245bc899bSmrg } 79345bc899bSmrg 79445bc899bSmrg xf86UnloadSubModule(pDDCModule); 79545bc899bSmrg } 79645bc899bSmrg 79745bc899bSmrg if ((pScrn->monitor->DDC = pVesa->monitor) != NULL) 79845bc899bSmrg xf86SetDDCproperties(pScrn, pVesa->monitor); 7993a925b30Smrg else { 8003a925b30Smrg void *panelid = VBEReadPanelID(pVesa->pVbe); 801b40a6198Smrg VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid); 802b40a6198Smrg free(panelid); 8033a925b30Smrg } 80445bc899bSmrg 80545bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 80645bc899bSmrg "Searching for matching VESA mode(s):\n"); 80745bc899bSmrg 80845bc899bSmrg /* 80945bc899bSmrg * Check the available BIOS modes, and extract those that match the 81045bc899bSmrg * requirements into the modePool. Note: modePool is a NULL-terminated 81145bc899bSmrg * list. 81245bc899bSmrg */ 81345bc899bSmrg pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo, 81445bc899bSmrg V_MODETYPE_VBE); 81545bc899bSmrg 81645bc899bSmrg xf86ErrorFVerb(DEBUG_VERB, "\n"); 81745bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 81845bc899bSmrg "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory, 81945bc899bSmrg (vbe->TotalMemory * 65536) / 1024); 82045bc899bSmrg 82145bc899bSmrg pVesa->mapSize = vbe->TotalMemory * 65536; 82245bc899bSmrg if (pScrn->modePool == NULL) { 82345bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n"); 82445bc899bSmrg vbeFree(pVesa->pVbe); 82545bc899bSmrg return (FALSE); 82645bc899bSmrg } 82745bc899bSmrg 82845bc899bSmrg VBESetModeNames(pScrn->modePool); 82945bc899bSmrg 83050f2e948Smrg pVesa->strict_validation = TRUE; 83150f2e948Smrg i = VESAValidateModes(pScrn); 83250f2e948Smrg 83350f2e948Smrg if (i <= 0) { 83450f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 83550f2e948Smrg "No valid modes left. Trying less strict filter...\n"); 83650f2e948Smrg pVesa->strict_validation = FALSE; 83750f2e948Smrg i = VESAValidateModes(pScrn); 83850f2e948Smrg } 83950f2e948Smrg 84050f2e948Smrg if (i <= 0) do { 84150f2e948Smrg Bool changed = FALSE; 84250f2e948Smrg /* maybe there's more modes at the bottom... */ 84350f2e948Smrg if (pScrn->monitor->vrefresh[0].lo > 50) { 84450f2e948Smrg changed = TRUE; 84550f2e948Smrg pScrn->monitor->vrefresh[0].lo = 50; 84650f2e948Smrg } 84750f2e948Smrg if (pScrn->monitor->hsync[0].lo > 31.5) { 84850f2e948Smrg changed = TRUE; 84950f2e948Smrg pScrn->monitor->hsync[0].lo = 31.5; 85050f2e948Smrg } 85150f2e948Smrg 85250f2e948Smrg if (!changed) 85350f2e948Smrg break; 85450f2e948Smrg 85550f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 85650f2e948Smrg "No valid modes left. Trying aggressive sync range...\n"); 85750f2e948Smrg i = VESAValidateModes(pScrn); 85850f2e948Smrg } while (0); 85945bc899bSmrg 86045bc899bSmrg if (i <= 0) { 86150f2e948Smrg /* alright, i'm out of ideas */ 86245bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n"); 86345bc899bSmrg vbeFree(pVesa->pVbe); 86445bc899bSmrg return (FALSE); 86545bc899bSmrg } 86645bc899bSmrg 86745bc899bSmrg xf86PruneDriverModes(pScrn); 86845bc899bSmrg 86945bc899bSmrg pMode = pScrn->modes; 87045bc899bSmrg do { 87145bc899bSmrg mode = ((VbeModeInfoData*)pMode->Private)->data; 87245bc899bSmrg if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) { 87345bc899bSmrg pVesa->maxBytesPerScanline = mode->BytesPerScanline; 87445bc899bSmrg } 87545bc899bSmrg pMode = pMode->next; 87645bc899bSmrg } while (pMode != pScrn->modes); 87745bc899bSmrg 87845bc899bSmrg pScrn->currentMode = pScrn->modes; 87945bc899bSmrg pScrn->displayWidth = pScrn->virtualX; 88045bc899bSmrg 88145bc899bSmrg VBEPrintModes(pScrn); 88245bc899bSmrg 88345bc899bSmrg /* Set display resolution */ 88445bc899bSmrg xf86SetDpi(pScrn, 0, 0); 88545bc899bSmrg 88645bc899bSmrg if (pScrn->modes == NULL) { 88745bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); 88845bc899bSmrg vbeFree(pVesa->pVbe); 88945bc899bSmrg return (FALSE); 89045bc899bSmrg } 89145bc899bSmrg 89245bc899bSmrg /* options */ 893b40a6198Smrg if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) { 89445bc899bSmrg vbeFree(pVesa->pVbe); 89545bc899bSmrg return FALSE; 89645bc899bSmrg } 89745bc899bSmrg memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions)); 89845bc899bSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options); 89945bc899bSmrg 900a0c41156Smrg /* Use shadow by default, for non-virt hardware */ 901a0c41156Smrg if (!xf86GetOptValBool(pVesa->Options, OPTION_SHADOW_FB, &pVesa->shadowFB)) 902a0c41156Smrg { 903a0c41156Smrg switch (pVesa->pciInfo->vendor_id) { 904a0c41156Smrg case 0x1234: /* bochs vga (not in pci.ids) */ 905a0c41156Smrg case 0x15ad: /* vmware */ 906a0c41156Smrg case 0x1b36: /* qemu qxl */ 907a0c41156Smrg case 0x80ee: /* virtualbox */ 908a0c41156Smrg case 0xaaaa: /* parallels (not in pci.ids) */ 909a0c41156Smrg pVesa->shadowFB = FALSE; 910a0c41156Smrg break; 911a0c41156Smrg 912a0c41156Smrg case 0x1013: /* qemu's cirrus emulation */ 913a0c41156Smrg if (pVesa->pciInfo->subvendor_id == 0x1af4) 914a0c41156Smrg pVesa->shadowFB = FALSE; 915a0c41156Smrg else 916a0c41156Smrg pVesa->shadowFB = TRUE; 917a0c41156Smrg break; 918a0c41156Smrg 919a0c41156Smrg case 0x1414: /* microsoft hyper-v */ 920a0c41156Smrg if (pVesa->pciInfo->device_id == 0x5353) 921a0c41156Smrg pVesa->shadowFB = FALSE; 922a0c41156Smrg else 923a0c41156Smrg pVesa->shadowFB = TRUE; 924a0c41156Smrg break; 925a0c41156Smrg 926a0c41156Smrg default: 927a0c41156Smrg pVesa->shadowFB = TRUE; 928a0c41156Smrg break; 929a0c41156Smrg } 930a0c41156Smrg } 931a0c41156Smrg 932f2408745Smrg /* Use default refresh by default. Too many VBE 3.0 933f2408745Smrg * BIOSes are incorrectly implemented. 934f2408745Smrg */ 935f2408745Smrg pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options, 936f2408745Smrg OPTION_DFLT_REFRESH, TRUE); 93745bc899bSmrg 938c97b1c41Smrg pVesa->ModeSetClearScreen = 939c97b1c41Smrg xf86ReturnOptValBool(pVesa->Options, 940c97b1c41Smrg OPTION_MODESET_CLEAR_SCREEN, FALSE); 94145bc899bSmrg 94250f2e948Smrg if (!pVesa->defaultRefresh && !pVesa->strict_validation) 94345bc899bSmrg VBESetModeParameters(pScrn, pVesa->pVbe); 94445bc899bSmrg 94545bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 94645bc899bSmrg switch (mode->MemoryModel) { 94745bc899bSmrg case 0x4: /* Packed pixel */ 94850f2e948Smrg case 0x6: /* Direct Color */ 94945bc899bSmrg pScrn->bitmapBitOrder = BITMAP_BIT_ORDER; 95045bc899bSmrg 95145bc899bSmrg switch (pScrn->bitsPerPixel) { 95245bc899bSmrg case 8: 95345bc899bSmrg case 16: 95445bc899bSmrg case 24: 95545bc899bSmrg case 32: 95645bc899bSmrg break; 95745bc899bSmrg default: 95845bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 959a0c41156Smrg "Unsupported bpp: %d\n", pScrn->bitsPerPixel); 96045bc899bSmrg vbeFree(pVesa->pVbe); 96145bc899bSmrg return FALSE; 96245bc899bSmrg } 96345bc899bSmrg break; 96450f2e948Smrg default: 96550f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 966a0c41156Smrg "Unsupported Memory Model: %d\n", mode->MemoryModel); 96750f2e948Smrg return FALSE; 96845bc899bSmrg } 96945bc899bSmrg 97045bc899bSmrg if (pVesa->shadowFB) { 97145bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); 97245bc899bSmrg if (!xf86LoadSubModule(pScrn, "shadow")) { 97345bc899bSmrg vbeFree(pVesa->pVbe); 97445bc899bSmrg return (FALSE); 97545bc899bSmrg } 97645bc899bSmrg } 97745bc899bSmrg 97850f2e948Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 97945bc899bSmrg VESAFreeRec(pScrn); 98045bc899bSmrg vbeFree(pVesa->pVbe); 98145bc899bSmrg return (FALSE); 98245bc899bSmrg } 98345bc899bSmrg 98445bc899bSmrg vbeFree(pVesa->pVbe); 98545bc899bSmrg 98645bc899bSmrg return (TRUE); 98745bc899bSmrg} 98845bc899bSmrg 98945bc899bSmrgstatic Bool 99045bc899bSmrgvesaCreateScreenResources(ScreenPtr pScreen) 99145bc899bSmrg{ 992b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 99345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 99445bc899bSmrg Bool ret; 99545bc899bSmrg 99645bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 99745bc899bSmrg ret = pScreen->CreateScreenResources(pScreen); 99845bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 99945bc899bSmrg 100045bc899bSmrg shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update, 100145bc899bSmrg pVesa->window, 0, 0); 100245bc899bSmrg 100345bc899bSmrg return ret; 100445bc899bSmrg} 100545bc899bSmrg 100650f2e948Smrgstatic void 1007b40a6198SmrgvesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable) 100850f2e948Smrg{ 1009b40a6198Smrg SCRN_INFO_PTR(arg); 101050f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 101150f2e948Smrg 101250f2e948Smrg pVesa->accessEnabled = enable; 1013b40a6198Smrg pVesa->EnableDisableFBAccess(arg, enable); 101450f2e948Smrg} 101550f2e948Smrg 101645bc899bSmrgstatic Bool 1017b40a6198SmrgVESAScreenInit(SCREEN_INIT_ARGS_DECL) 101845bc899bSmrg{ 1019b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 102045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 102145bc899bSmrg VisualPtr visual; 102245bc899bSmrg VbeModeInfoBlock *mode; 102345bc899bSmrg int flags; 102445bc899bSmrg 102545bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 102645bc899bSmrg SET_BIOS_SCRATCH 102745bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 102845bc899bSmrg return (FALSE); 102945bc899bSmrg 103045bc899bSmrg if (pVesa->mapPhys == 0) { 103145bc899bSmrg mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 103245bc899bSmrg pScrn->videoRam = pVesa->mapSize; 103345bc899bSmrg pVesa->mapPhys = mode->PhysBasePtr; 103445bc899bSmrg pVesa->mapOff = 0; 103545bc899bSmrg } 103645bc899bSmrg 103745bc899bSmrg if (pVesa->mapPhys == 0) { 103845bc899bSmrg pVesa->mapPhys = 0xa0000; 103945bc899bSmrg pVesa->mapSize = 0x10000; 104045bc899bSmrg } 104145bc899bSmrg 104245bc899bSmrg if (!VESAMapVidMem(pScrn)) { 104345bc899bSmrg if (pVesa->mapPhys != 0xa0000) { 104445bc899bSmrg pVesa->mapPhys = 0xa0000; 104545bc899bSmrg pVesa->mapSize = 0x10000; 104645bc899bSmrg if (!VESAMapVidMem(pScrn)) 104745bc899bSmrg return (FALSE); 104845bc899bSmrg } 104945bc899bSmrg else 105045bc899bSmrg return (FALSE); 105145bc899bSmrg } 105245bc899bSmrg 105345bc899bSmrg /* Set bpp to 8 for depth 4 when using shadowfb. */ 105445bc899bSmrg if (pVesa->shadowFB && pScrn->bitsPerPixel == 4) 105545bc899bSmrg pScrn->bitsPerPixel = 8; 105645bc899bSmrg 105745bc899bSmrg if (pVesa->shadowFB) { 1058b40a6198Smrg pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY * 105945bc899bSmrg ((pScrn->bitsPerPixel + 7) / 8)); 106045bc899bSmrg if (!pVesa->shadow) { 106145bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 106245bc899bSmrg "Failed to allocate shadow buffer\n"); 106345bc899bSmrg return FALSE; 106445bc899bSmrg } 106545bc899bSmrg } 106645bc899bSmrg 106745bc899bSmrg /* save current video state */ 106845bc899bSmrg VESASaveRestore(pScrn, MODE_SAVE); 106945bc899bSmrg pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256, 107045bc899bSmrg NULL, FALSE, FALSE); 107145bc899bSmrg 107245bc899bSmrg /* set first video mode */ 107345bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 107445bc899bSmrg return (FALSE); 107545bc899bSmrg 107645bc899bSmrg /* set the viewport */ 1077b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 107845bc899bSmrg 107945bc899bSmrg /* Blank the screen for aesthetic reasons. */ 108045bc899bSmrg VESASaveScreen(pScreen, SCREEN_SAVER_ON); 108145bc899bSmrg 108245bc899bSmrg /* mi layer */ 108345bc899bSmrg miClearVisualTypes(); 108445bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 108545bc899bSmrg return (FALSE); 108645bc899bSmrg if (pScrn->bitsPerPixel > 8) { 108745bc899bSmrg if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 108845bc899bSmrg pScrn->rgbBits, TrueColor)) 108945bc899bSmrg return (FALSE); 109045bc899bSmrg } 109145bc899bSmrg else { 109245bc899bSmrg if (!miSetVisualTypes(pScrn->depth, 109345bc899bSmrg miGetDefaultVisualMask(pScrn->depth), 109445bc899bSmrg pScrn->rgbBits, pScrn->defaultVisual)) 109545bc899bSmrg return (FALSE); 109645bc899bSmrg } 109745bc899bSmrg if (!miSetPixmapDepths()) 109845bc899bSmrg return (FALSE); 109945bc899bSmrg 110045bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 110145bc899bSmrg switch (mode->MemoryModel) { 110245bc899bSmrg case 0x4: /* Packed pixel */ 110350f2e948Smrg case 0x6: /* Direct Color */ 110445bc899bSmrg switch (pScrn->bitsPerPixel) { 110545bc899bSmrg case 8: 110645bc899bSmrg case 16: 110745bc899bSmrg case 24: 110845bc899bSmrg case 32: 110945bc899bSmrg if (!fbScreenInit(pScreen, 111045bc899bSmrg pVesa->shadowFB ? pVesa->shadow : pVesa->base, 111145bc899bSmrg pScrn->virtualX, pScrn->virtualY, 111245bc899bSmrg pScrn->xDpi, pScrn->yDpi, 111345bc899bSmrg pScrn->displayWidth, pScrn->bitsPerPixel)) 111445bc899bSmrg return (FALSE); 111545bc899bSmrg break; 111645bc899bSmrg default: 111745bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 111845bc899bSmrg "Unsupported bpp: %d", pScrn->bitsPerPixel); 111945bc899bSmrg return (FALSE); 112045bc899bSmrg } 112145bc899bSmrg break; 112250f2e948Smrg default: 112350f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 112450f2e948Smrg "Unsupported Memory Model: %d", mode->MemoryModel); 112550f2e948Smrg return (FALSE); 112645bc899bSmrg } 112745bc899bSmrg 112845bc899bSmrg 112945bc899bSmrg if (pScrn->bitsPerPixel > 8) { 113045bc899bSmrg /* Fixup RGB ordering */ 113145bc899bSmrg visual = pScreen->visuals + pScreen->numVisuals; 113245bc899bSmrg while (--visual >= pScreen->visuals) { 113345bc899bSmrg if ((visual->class | DynamicClass) == DirectColor) { 113445bc899bSmrg visual->offsetRed = pScrn->offset.red; 113545bc899bSmrg visual->offsetGreen = pScrn->offset.green; 113645bc899bSmrg visual->offsetBlue = pScrn->offset.blue; 113745bc899bSmrg visual->redMask = pScrn->mask.red; 113845bc899bSmrg visual->greenMask = pScrn->mask.green; 113945bc899bSmrg visual->blueMask = pScrn->mask.blue; 114045bc899bSmrg } 114145bc899bSmrg } 114245bc899bSmrg } 114345bc899bSmrg 114445bc899bSmrg /* must be after RGB ordering fixed */ 11455592a31fSmrg fbPictureInit(pScreen, 0, 0); 114645bc899bSmrg 114745bc899bSmrg if (pVesa->shadowFB) { 114850f2e948Smrg if (pVesa->mapPhys == 0xa0000) { /* Windowed */ 11495592a31fSmrg pVesa->update = vesaUpdatePacked; 115045bc899bSmrg pVesa->window = VESAWindowWindowed; 115145bc899bSmrg } 115245bc899bSmrg else { /* Linear */ 11535592a31fSmrg pVesa->update = vesaUpdatePacked; 115445bc899bSmrg pVesa->window = VESAWindowLinear; 115545bc899bSmrg } 115645bc899bSmrg 115745bc899bSmrg if (!shadowSetup(pScreen)) 115845bc899bSmrg return FALSE; 115945bc899bSmrg pVesa->CreateScreenResources = pScreen->CreateScreenResources; 116045bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 116145bc899bSmrg } 116250f2e948Smrg else if (pVesa->mapPhys == 0xa0000) { 11635592a31fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 11645592a31fSmrg "Banked framebuffer requires ShadowFB\n"); 11655592a31fSmrg return FALSE; 116645bc899bSmrg } 116745bc899bSmrg 116845bc899bSmrg VESADGAInit(pScrn, pScreen); 116945bc899bSmrg 117045bc899bSmrg xf86SetBlackWhitePixels(pScreen); 117145bc899bSmrg xf86SetBackingStore(pScreen); 117245bc899bSmrg 117345bc899bSmrg /* software cursor */ 117445bc899bSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 117545bc899bSmrg 117645bc899bSmrg /* colormap */ 117745bc899bSmrg if (!miCreateDefColormap(pScreen)) 117845bc899bSmrg return (FALSE); 117945bc899bSmrg 118045bc899bSmrg flags = CMAP_RELOAD_ON_MODE_SWITCH; 118145bc899bSmrg 118245bc899bSmrg if(!xf86HandleColormaps(pScreen, 256, 118345bc899bSmrg pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6, 118445bc899bSmrg VESALoadPalette, NULL, flags)) 118545bc899bSmrg return (FALSE); 118645bc899bSmrg 118750f2e948Smrg pVesa->accessEnabled = TRUE; 118850f2e948Smrg pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; 118950f2e948Smrg pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess; 119050f2e948Smrg 119145bc899bSmrg pVesa->CloseScreen = pScreen->CloseScreen; 119245bc899bSmrg pScreen->CloseScreen = VESACloseScreen; 119345bc899bSmrg pScreen->SaveScreen = VESASaveScreen; 119445bc899bSmrg 119545bc899bSmrg xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0); 119645bc899bSmrg 119745bc899bSmrg /* Report any unused options (only for the first generation) */ 119845bc899bSmrg if (serverGeneration == 1) 119945bc899bSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 120045bc899bSmrg 120145bc899bSmrg return (TRUE); 120245bc899bSmrg} 120345bc899bSmrg 120445bc899bSmrgstatic Bool 1205b40a6198SmrgVESAEnterVT(VT_FUNC_ARGS_DECL) 120645bc899bSmrg{ 1207b40a6198Smrg SCRN_INFO_PTR(arg); 120845bc899bSmrg 120945bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 121045bc899bSmrg return FALSE; 1211b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 121245bc899bSmrg return TRUE; 121345bc899bSmrg} 121445bc899bSmrg 121545bc899bSmrgstatic void 1216b40a6198SmrgVESALeaveVT(VT_FUNC_ARGS_DECL) 121745bc899bSmrg{ 1218b40a6198Smrg SCRN_INFO_PTR(arg); 1219b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 122045bc899bSmrg} 122145bc899bSmrg 122245bc899bSmrgstatic Bool 1223b40a6198SmrgVESACloseScreen(CLOSE_SCREEN_ARGS_DECL) 122445bc899bSmrg{ 1225b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 122645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 122745bc899bSmrg 122845bc899bSmrg if (pScrn->vtSema) { 1229b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 123045bc899bSmrg if (pVesa->savedPal) 123145bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256, 123245bc899bSmrg pVesa->savedPal, FALSE, TRUE); 123345bc899bSmrg VESAUnmapVidMem(pScrn); 123445bc899bSmrg } 12355592a31fSmrg if (pVesa->shadowFB && pVesa->shadow) { 12365592a31fSmrg shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); 1237b40a6198Smrg free(pVesa->shadow); 12385592a31fSmrg } 123945bc899bSmrg if (pVesa->pDGAMode) { 1240b40a6198Smrg free(pVesa->pDGAMode); 124145bc899bSmrg pVesa->pDGAMode = NULL; 124245bc899bSmrg pVesa->nDGAMode = 0; 124345bc899bSmrg } 124445bc899bSmrg pScrn->vtSema = FALSE; 124545bc899bSmrg 124650f2e948Smrg pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess; 124745bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 124845bc899bSmrg pScreen->CloseScreen = pVesa->CloseScreen; 1249b40a6198Smrg return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); 125045bc899bSmrg} 125145bc899bSmrg 125245bc899bSmrgstatic Bool 1253b40a6198SmrgVESASwitchMode(SWITCH_MODE_ARGS_DECL) 125445bc899bSmrg{ 1255b40a6198Smrg SCRN_INFO_PTR(arg); 125645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 125750f2e948Smrg Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled; 125845bc899bSmrg 125950f2e948Smrg if (disableAccess) 1260b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE); 1261b40a6198Smrg ret = VESASetMode(pScrn, mode); 126250f2e948Smrg if (disableAccess) 1263b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE); 126445bc899bSmrg return ret; 126545bc899bSmrg} 126645bc899bSmrg 126745bc899bSmrg/* Set a graphics mode */ 126845bc899bSmrgstatic Bool 126945bc899bSmrgVESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 127045bc899bSmrg{ 127145bc899bSmrg VESAPtr pVesa; 127245bc899bSmrg VbeModeInfoData *data; 127345bc899bSmrg int mode; 127445bc899bSmrg 127545bc899bSmrg pVesa = VESAGetRec(pScrn); 127645bc899bSmrg 127745bc899bSmrg data = (VbeModeInfoData*)pMode->Private; 127850f2e948Smrg 127950f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 128050f2e948Smrg "Setting up VESA Mode 0x%X (%dx%d)\n", 128150f2e948Smrg data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay); 128250f2e948Smrg 128350f2e948Smrg /* careful, setting the bit means don't clear the screen */ 128450f2e948Smrg mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15)); 128545bc899bSmrg 128645bc899bSmrg /* enable linear addressing */ 128745bc899bSmrg if (pVesa->mapPhys != 0xa0000) 128845bc899bSmrg mode |= 1 << 14; 128945bc899bSmrg 129045bc899bSmrg if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) { 129145bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed"); 129245bc899bSmrg if ((data->block || (data->mode & (1 << 11))) && 129345bc899bSmrg VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) { 129445bc899bSmrg /* Some cards do not like setting the clock. 129545bc899bSmrg * Free it as it will not be any longer useful 129645bc899bSmrg */ 12975592a31fSmrg xf86ErrorF(", mode set without customized refresh.\n"); 1298b40a6198Smrg free(data->block); 129945bc899bSmrg data->block = NULL; 130045bc899bSmrg data->mode &= ~(1 << 11); 130145bc899bSmrg } 130245bc899bSmrg else { 130345bc899bSmrg ErrorF("\n"); 130445bc899bSmrg return (FALSE); 130545bc899bSmrg } 130645bc899bSmrg } 130745bc899bSmrg 130845bc899bSmrg pVesa->bankSwitchWindowB = 130945bc899bSmrg !((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0)); 131045bc899bSmrg 131145bc899bSmrg if (data->data->XResolution != pScrn->displayWidth) 131245bc899bSmrg VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth); 131345bc899bSmrg 131445bc899bSmrg if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 && 131550f2e948Smrg !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7)) 131645bc899bSmrg VBESetGetDACPaletteFormat(pVesa->pVbe, 8); 131745bc899bSmrg 131845bc899bSmrg pScrn->vtSema = TRUE; 131945bc899bSmrg 132045bc899bSmrg return (TRUE); 132145bc899bSmrg} 132245bc899bSmrg 132345bc899bSmrgstatic void 1324b40a6198SmrgVESAAdjustFrame(ADJUST_FRAME_ARGS_DECL) 132545bc899bSmrg{ 1326b40a6198Smrg SCRN_INFO_PTR(arg); 1327b40a6198Smrg VESAPtr pVesa = VESAGetRec(pScrn); 132845bc899bSmrg 132945bc899bSmrg VBESetDisplayStart(pVesa->pVbe, x, y, TRUE); 133045bc899bSmrg} 133145bc899bSmrg 133245bc899bSmrgstatic void 1333b40a6198SmrgVESAFreeScreen(FREE_SCREEN_ARGS_DECL) 133445bc899bSmrg{ 1335b40a6198Smrg SCRN_INFO_PTR(arg); 1336b40a6198Smrg VESAFreeRec(pScrn); 133745bc899bSmrg} 133845bc899bSmrg 133945bc899bSmrgstatic Bool 134045bc899bSmrgVESAMapVidMem(ScrnInfoPtr pScrn) 134145bc899bSmrg{ 134245bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 134345bc899bSmrg 134445bc899bSmrg if (pVesa->base != NULL) 134545bc899bSmrg return (TRUE); 134645bc899bSmrg 134745bc899bSmrg pScrn->memPhysBase = pVesa->mapPhys; 134845bc899bSmrg pScrn->fbOffset = pVesa->mapOff; 134945bc899bSmrg 135050f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 1351b40a6198Smrg if (pVesa->pciInfo != NULL) { 1352b40a6198Smrg if (pVesa->mapPhys != 0xa0000) { 1353b40a6198Smrg (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase, 1354b40a6198Smrg pVesa->mapSize, 1355b40a6198Smrg (PCI_DEV_MAP_FLAG_WRITABLE 1356b40a6198Smrg | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 1357b40a6198Smrg & pVesa->base); 1358b40a6198Smrg 1359b40a6198Smrg if (pVesa->base) 1360b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000, 1361b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1362b40a6198Smrg & pVesa->VGAbase); 1363b40a6198Smrg } 1364b40a6198Smrg else { 1365b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase, 1366b40a6198Smrg pVesa->mapSize, 1367b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1368b40a6198Smrg & pVesa->base); 136950f2e948Smrg 1370b40a6198Smrg if (pVesa->base) 1371b40a6198Smrg pVesa->VGAbase = pVesa->base; 1372b40a6198Smrg } 137350f2e948Smrg } 137450f2e948Smrg#else 137545bc899bSmrg if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI) 137645bc899bSmrg pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 137745bc899bSmrg pVesa->pciTag, pScrn->memPhysBase, 137845bc899bSmrg pVesa->mapSize); 137945bc899bSmrg else 138045bc899bSmrg pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag, 138145bc899bSmrg pScrn->memPhysBase, pVesa->mapSize); 138245bc899bSmrg 138345bc899bSmrg if (pVesa->base) { 138445bc899bSmrg if (pVesa->mapPhys != 0xa0000) 138545bc899bSmrg pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0, 138645bc899bSmrg pVesa->pciTag, 138745bc899bSmrg 0xa0000, 0x10000); 138845bc899bSmrg else 138945bc899bSmrg pVesa->VGAbase = pVesa->base; 139045bc899bSmrg } 139150f2e948Smrg#endif 139245bc899bSmrg 1393b40a6198Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 139445bc899bSmrg pVesa->ioBase = pScrn->domainIOBase; 1395b40a6198Smrg#else 1396b40a6198Smrg pVesa->ioBase = 0; 1397b40a6198Smrg#endif 139845bc899bSmrg 139945bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 1400b1fb1a22Smrg "virtual address = %p, VGAbase = %p\n" 140145bc899bSmrg "\tphysical address = 0x%lx, size = %ld\n", 1402b1fb1a22Smrg pVesa->base, pVesa->VGAbase, 1403b1fb1a22Smrg pScrn->memPhysBase, pVesa->mapSize); 140445bc899bSmrg 140545bc899bSmrg return (pVesa->base != NULL); 140645bc899bSmrg} 140745bc899bSmrg 140845bc899bSmrgstatic void 140945bc899bSmrgVESAUnmapVidMem(ScrnInfoPtr pScrn) 141045bc899bSmrg{ 141145bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 141245bc899bSmrg 141345bc899bSmrg if (pVesa->base == NULL) 141445bc899bSmrg return; 141545bc899bSmrg 141650f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 141750f2e948Smrg if (pVesa->mapPhys != 0xa0000) { 141850f2e948Smrg (void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base, 141950f2e948Smrg pVesa->mapSize); 1420b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase, 1421b40a6198Smrg 0x10000); 142250f2e948Smrg } 142350f2e948Smrg else { 1424b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base, 1425b40a6198Smrg pVesa->mapSize); 142650f2e948Smrg } 142750f2e948Smrg#else 142845bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize); 142945bc899bSmrg if (pVesa->mapPhys != 0xa0000) 143045bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000); 143150f2e948Smrg#endif 143245bc899bSmrg pVesa->base = NULL; 143345bc899bSmrg} 143445bc899bSmrg 14355592a31fSmrg/* This code works, but is very slow for programs that use it intensively */ 143645bc899bSmrgstatic void 143745bc899bSmrgVESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 143845bc899bSmrg LOCO *colors, VisualPtr pVisual) 143945bc899bSmrg{ 144045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 144145bc899bSmrg int i, idx; 144245bc899bSmrg int base; 144345bc899bSmrg 1444f2408745Smrg if (!pVesa->savedPal) { 1445f2408745Smrg#define VESADACDelay() \ 1446f2408745Smrg do { \ 1447f2408745Smrg (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1448f2408745Smrg (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1449f2408745Smrg } while (0) 1450f2408745Smrg 1451f2408745Smrg for (i = 0; i < numColors; i++) { 1452f2408745Smrg idx = indices[i]; 1453f2408745Smrg outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx); 1454f2408745Smrg VESADACDelay(); 1455f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red); 1456f2408745Smrg VESADACDelay(); 1457f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green); 1458f2408745Smrg VESADACDelay(); 1459f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue); 1460f2408745Smrg VESADACDelay(); 1461f2408745Smrg } 1462f2408745Smrg return; 1463f2408745Smrg } 1464f2408745Smrg 146545bc899bSmrg if (pVesa->pal == NULL) 1466b40a6198Smrg pVesa->pal = calloc(1, sizeof(CARD32) * 256); 146745bc899bSmrg 146845bc899bSmrg for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) { 146945bc899bSmrg int j = indices[i]; 147045bc899bSmrg 147145bc899bSmrg if (j < 0 || j >= 256) 147245bc899bSmrg continue; 147345bc899bSmrg pVesa->pal[j] = colors[j].blue | 147445bc899bSmrg (colors[j].green << 8) | 147545bc899bSmrg (colors[j].red << 16); 147645bc899bSmrg if (j != idx) { 147745bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 147845bc899bSmrg pVesa->pal + base, FALSE, TRUE); 147945bc899bSmrg idx = base = j; 148045bc899bSmrg } 148145bc899bSmrg } 148245bc899bSmrg 148345bc899bSmrg if (idx - 1 == indices[i - 1]) 148445bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 148545bc899bSmrg pVesa->pal + base, FALSE, TRUE); 148645bc899bSmrg} 148745bc899bSmrg 148845bc899bSmrg/* 148945bc899bSmrg * Just adapted from the std* functions in vgaHW.c 149045bc899bSmrg */ 149145bc899bSmrgstatic void 149245bc899bSmrgWriteAttr(VESAPtr pVesa, int index, int value) 149345bc899bSmrg{ 149445bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 149545bc899bSmrg 149645bc899bSmrg index |= 0x20; 149745bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 149845bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_DATA_W, value); 149945bc899bSmrg} 150045bc899bSmrg 150145bc899bSmrgstatic int 150245bc899bSmrgReadAttr(VESAPtr pVesa, int index) 150345bc899bSmrg{ 150445bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 150545bc899bSmrg 150645bc899bSmrg index |= 0x20; 150745bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 150845bc899bSmrg return (inb(pVesa->ioBase + VGA_ATTR_DATA_R)); 150945bc899bSmrg} 151045bc899bSmrg 151145bc899bSmrg#define WriteMiscOut(value) outb(pVesa->ioBase + VGA_MISC_OUT_W, value) 151245bc899bSmrg#define ReadMiscOut() inb(pVesa->ioBase + VGA_MISC_OUT_R) 151345bc899bSmrg#define WriteSeq(index, value) outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\ 151445bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_DATA, value) 151545bc899bSmrg 151645bc899bSmrgstatic int 151745bc899bSmrgReadSeq(VESAPtr pVesa, int index) 151845bc899bSmrg{ 151945bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_INDEX, index); 152045bc899bSmrg 152145bc899bSmrg return (inb(pVesa->ioBase + VGA_SEQ_DATA)); 152245bc899bSmrg} 152345bc899bSmrg 152445bc899bSmrg#define WriteGr(index, value) \ 152545bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); \ 152645bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_DATA, value) 152745bc899bSmrg 152845bc899bSmrgstatic int 152945bc899bSmrgReadGr(VESAPtr pVesa, int index) 153045bc899bSmrg{ 153145bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); 153245bc899bSmrg 153345bc899bSmrg return (inb(pVesa->ioBase + VGA_GRAPH_DATA)); 153445bc899bSmrg} 153545bc899bSmrg 153645bc899bSmrg#define WriteCrtc(index, value) \ 153745bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \ 153845bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value) 153945bc899bSmrg 154045bc899bSmrgstatic void 154145bc899bSmrgSeqReset(VESAPtr pVesa, Bool start) 154245bc899bSmrg{ 154345bc899bSmrg if (start) { 154445bc899bSmrg WriteSeq(0x00, 0x01); /* Synchronous Reset */ 154545bc899bSmrg } 154645bc899bSmrg else { 154745bc899bSmrg WriteSeq(0x00, 0x03); /* End Reset */ 154845bc899bSmrg } 154945bc899bSmrg} 155045bc899bSmrg 155145bc899bSmrgstatic void 155245bc899bSmrgSaveFonts(ScrnInfoPtr pScrn) 155345bc899bSmrg{ 155445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 155545bc899bSmrg unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 155645bc899bSmrg 155745bc899bSmrg if (pVesa->fonts != NULL) 155845bc899bSmrg return; 155945bc899bSmrg 156045bc899bSmrg /* If in graphics mode, don't save anything */ 156145bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 156245bc899bSmrg if (attr10 & 0x01) 156345bc899bSmrg return; 156445bc899bSmrg 1565b40a6198Smrg pVesa->fonts = malloc(16384); 156645bc899bSmrg 156745bc899bSmrg /* save the registers that are needed here */ 156845bc899bSmrg miscOut = ReadMiscOut(); 156945bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 157045bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 157145bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 157245bc899bSmrg seq2 = ReadSeq(pVesa, 0x02); 157345bc899bSmrg seq4 = ReadSeq(pVesa, 0x04); 157445bc899bSmrg 157545bc899bSmrg /* Force into colour mode */ 157645bc899bSmrg WriteMiscOut(miscOut | 0x01); 157745bc899bSmrg 157845bc899bSmrg scrn = ReadSeq(pVesa, 0x01) | 0x20; 157945bc899bSmrg SeqReset(pVesa, TRUE); 158045bc899bSmrg WriteSeq(0x01, scrn); 158145bc899bSmrg SeqReset(pVesa, FALSE); 158245bc899bSmrg 158345bc899bSmrg WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 158445bc899bSmrg 158545bc899bSmrg /*font1 */ 158645bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 158745bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 158845bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 158945bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 159045bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 159145bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192); 159245bc899bSmrg 159345bc899bSmrg /* font2 */ 159445bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 159545bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 159645bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 159745bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 159845bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 159945bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192); 160045bc899bSmrg 160145bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 160245bc899bSmrg SeqReset(pVesa, TRUE); 160345bc899bSmrg WriteSeq(0x01, scrn); 160445bc899bSmrg SeqReset(pVesa, FALSE); 160545bc899bSmrg 160645bc899bSmrg /* Restore clobbered registers */ 160745bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 160845bc899bSmrg WriteSeq(0x02, seq2); 160945bc899bSmrg WriteSeq(0x04, seq4); 161045bc899bSmrg WriteGr(0x04, gr4); 161145bc899bSmrg WriteGr(0x05, gr5); 161245bc899bSmrg WriteGr(0x06, gr6); 161345bc899bSmrg WriteMiscOut(miscOut); 161445bc899bSmrg} 161545bc899bSmrg 161645bc899bSmrgstatic void 161745bc899bSmrgRestoreFonts(ScrnInfoPtr pScrn) 161845bc899bSmrg{ 161945bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 162045bc899bSmrg unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 162145bc899bSmrg 162245bc899bSmrg if (pVesa->fonts == NULL) 162345bc899bSmrg return; 162445bc899bSmrg 162545bc899bSmrg if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0) 162645bc899bSmrg VESABankSwitch(pScrn->pScreen, 0); 162745bc899bSmrg 162845bc899bSmrg /* save the registers that are needed here */ 162945bc899bSmrg miscOut = ReadMiscOut(); 163045bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 163145bc899bSmrg gr1 = ReadGr(pVesa, 0x01); 163245bc899bSmrg gr3 = ReadGr(pVesa, 0x03); 163345bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 163445bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 163545bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 163645bc899bSmrg gr8 = ReadGr(pVesa, 0x08); 163745bc899bSmrg seq2 = ReadSeq(pVesa, 0x02); 163845bc899bSmrg seq4 = ReadSeq(pVesa, 0x04); 163945bc899bSmrg 164045bc899bSmrg /* Force into colour mode */ 164145bc899bSmrg WriteMiscOut(miscOut | 0x01); 164245bc899bSmrg 164345bc899bSmrg scrn = ReadSeq(pVesa, 0x01) | 0x20; 164445bc899bSmrg SeqReset(pVesa, TRUE); 164545bc899bSmrg WriteSeq(0x01, scrn); 164645bc899bSmrg SeqReset(pVesa, FALSE); 164745bc899bSmrg 164845bc899bSmrg WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 164945bc899bSmrg if (pScrn->depth == 4) { 165045bc899bSmrg /* GJA */ 165145bc899bSmrg WriteGr(0x03, 0x00); /* don't rotate, write unmodified */ 165245bc899bSmrg WriteGr(0x08, 0xFF); /* write all bits in a byte */ 165345bc899bSmrg WriteGr(0x01, 0x00); /* all planes come from CPU */ 165445bc899bSmrg } 165545bc899bSmrg 165645bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 165745bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 165845bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 165945bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 166045bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 166145bc899bSmrg slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192); 166245bc899bSmrg 166345bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 166445bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 166545bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 166645bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 166745bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 166845bc899bSmrg slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192); 166945bc899bSmrg 167045bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 167145bc899bSmrg SeqReset(pVesa, TRUE); 167245bc899bSmrg WriteSeq(0x01, scrn); 167345bc899bSmrg SeqReset(pVesa, FALSE); 167445bc899bSmrg 167545bc899bSmrg /* restore the registers that were changed */ 167645bc899bSmrg WriteMiscOut(miscOut); 167745bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 167845bc899bSmrg WriteGr(0x01, gr1); 167945bc899bSmrg WriteGr(0x03, gr3); 168045bc899bSmrg WriteGr(0x04, gr4); 168145bc899bSmrg WriteGr(0x05, gr5); 168245bc899bSmrg WriteGr(0x06, gr6); 168345bc899bSmrg WriteGr(0x08, gr8); 168445bc899bSmrg WriteSeq(0x02, seq2); 168545bc899bSmrg WriteSeq(0x04, seq4); 168645bc899bSmrg} 168745bc899bSmrg 168845bc899bSmrgstatic Bool 168945bc899bSmrgVESASaveScreen(ScreenPtr pScreen, int mode) 169045bc899bSmrg{ 1691b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 169245bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 169345bc899bSmrg Bool on = xf86IsUnblank(mode); 169445bc899bSmrg 169545bc899bSmrg if (on) 169645bc899bSmrg SetTimeSinceLastInputEvent(); 169745bc899bSmrg 169845bc899bSmrg if (pScrn->vtSema) { 169945bc899bSmrg unsigned char scrn = ReadSeq(pVesa, 0x01); 170045bc899bSmrg 170145bc899bSmrg if (on) 170245bc899bSmrg scrn &= ~0x20; 170345bc899bSmrg else 170445bc899bSmrg scrn |= 0x20; 170545bc899bSmrg SeqReset(pVesa, TRUE); 170645bc899bSmrg WriteSeq(0x01, scrn); 170745bc899bSmrg SeqReset(pVesa, FALSE); 170845bc899bSmrg } 170945bc899bSmrg 171045bc899bSmrg return (TRUE); 171145bc899bSmrg} 171245bc899bSmrg 171345bc899bSmrgstatic int 171445bc899bSmrgVESABankSwitch(ScreenPtr pScreen, unsigned int iBank) 171545bc899bSmrg{ 1716b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 171745bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 171845bc899bSmrg 171945bc899bSmrg if (pVesa->curBank == iBank) 172045bc899bSmrg return (0); 172145bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 0)) 172245bc899bSmrg return (1); 172345bc899bSmrg if (pVesa->bankSwitchWindowB) { 172445bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 1)) 172545bc899bSmrg return (1); 172645bc899bSmrg } 172745bc899bSmrg pVesa->curBank = iBank; 172845bc899bSmrg 172945bc899bSmrg return (0); 173045bc899bSmrg} 173145bc899bSmrg 173245bc899bSmrgBool 173345bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 173445bc899bSmrg{ 173545bc899bSmrg VESAPtr pVesa; 173645bc899bSmrg 1737c97b1c41Smrg if (function < MODE_QUERY || function > MODE_RESTORE) 173845bc899bSmrg return (FALSE); 173945bc899bSmrg 174045bc899bSmrg pVesa = VESAGetRec(pScrn); 174145bc899bSmrg 174245bc899bSmrg 174345bc899bSmrg /* Query amount of memory to save state */ 174445bc899bSmrg if (function == MODE_QUERY || 174545bc899bSmrg (function == MODE_SAVE && pVesa->state == NULL)) { 174645bc899bSmrg 174745bc899bSmrg /* Make sure we save at least this information in case of failure */ 174845bc899bSmrg (void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode); 174945bc899bSmrg SaveFonts(pScrn); 175045bc899bSmrg 175145bc899bSmrg if (pVesa->major > 1) { 175245bc899bSmrg if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state, 175345bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 175445bc899bSmrg return FALSE; 175545bc899bSmrg 175645bc899bSmrg } 175745bc899bSmrg } 175845bc899bSmrg 175945bc899bSmrg /* Save/Restore Super VGA state */ 176045bc899bSmrg if (function != MODE_QUERY) { 176145bc899bSmrg Bool retval = TRUE; 176245bc899bSmrg 176345bc899bSmrg if (pVesa->major > 1) { 176445bc899bSmrg if (function == MODE_RESTORE) 176545bc899bSmrg memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize); 176645bc899bSmrg 176745bc899bSmrg if ((retval = VBESaveRestore(pVesa->pVbe,function, 176845bc899bSmrg (pointer)&pVesa->state, 176945bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 177045bc899bSmrg && function == MODE_SAVE) { 177145bc899bSmrg /* don't rely on the memory not being touched */ 177245bc899bSmrg if (pVesa->pstate == NULL) 1773b40a6198Smrg pVesa->pstate = malloc(pVesa->stateSize); 177445bc899bSmrg memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize); 177545bc899bSmrg } 177645bc899bSmrg } 177745bc899bSmrg 177845bc899bSmrg if (function == MODE_RESTORE) { 177945bc899bSmrg VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL); 178045bc899bSmrg RestoreFonts(pScrn); 178145bc899bSmrg } 178245bc899bSmrg 178345bc899bSmrg if (!retval) 178445bc899bSmrg return (FALSE); 178545bc899bSmrg 178645bc899bSmrg } 178745bc899bSmrg 178845bc899bSmrg return (TRUE); 178945bc899bSmrg} 179045bc899bSmrg 179145bc899bSmrgstatic void 179245bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 179345bc899bSmrg int flags) 179445bc899bSmrg{ 179545bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 179645bc899bSmrg 179745bc899bSmrg if (!pScrn->vtSema) 179845bc899bSmrg return; 179945bc899bSmrg 180050f2e948Smrg VBEDPMSSet(pVesa->pVbe, mode); 180145bc899bSmrg} 180245bc899bSmrg 180345bc899bSmrg/*********************************************************************** 180445bc899bSmrg * DGA stuff 180545bc899bSmrg ***********************************************************************/ 180645bc899bSmrgstatic Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 180745bc899bSmrg unsigned char **ApertureBase, 180845bc899bSmrg int *ApertureSize, int *ApertureOffset, 180945bc899bSmrg int *flags); 181045bc899bSmrgstatic Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode); 181145bc899bSmrgstatic void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 181245bc899bSmrg 181345bc899bSmrgstatic Bool 181445bc899bSmrgVESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 181545bc899bSmrg unsigned char **ApertureBase, int *ApertureSize, 181645bc899bSmrg int *ApertureOffset, int *flags) 181745bc899bSmrg{ 181845bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 181945bc899bSmrg 182045bc899bSmrg *DeviceName = NULL; /* No special device */ 182145bc899bSmrg *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys); 182245bc899bSmrg *ApertureSize = pVesa->mapSize; 182345bc899bSmrg *ApertureOffset = pVesa->mapOff; 182445bc899bSmrg *flags = DGA_NEED_ROOT; 182545bc899bSmrg 182645bc899bSmrg return (TRUE); 182745bc899bSmrg} 182845bc899bSmrg 182945bc899bSmrgstatic Bool 183045bc899bSmrgVESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 183145bc899bSmrg{ 183245bc899bSmrg DisplayModePtr pMode; 183345bc899bSmrg int frameX0, frameY0; 183445bc899bSmrg 183545bc899bSmrg if (pDGAMode) { 183645bc899bSmrg pMode = pDGAMode->mode; 183745bc899bSmrg frameX0 = frameY0 = 0; 183845bc899bSmrg } 183945bc899bSmrg else { 184045bc899bSmrg if (!(pMode = pScrn->currentMode)) 184145bc899bSmrg return (TRUE); 184245bc899bSmrg 184345bc899bSmrg frameX0 = pScrn->frameX0; 184445bc899bSmrg frameY0 = pScrn->frameY0; 184545bc899bSmrg } 184645bc899bSmrg 1847b40a6198Smrg if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 184845bc899bSmrg return (FALSE); 1849b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 185045bc899bSmrg 185145bc899bSmrg return (TRUE); 185245bc899bSmrg} 185345bc899bSmrg 185445bc899bSmrgstatic void 185545bc899bSmrgVESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 185645bc899bSmrg{ 1857b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 185845bc899bSmrg} 185945bc899bSmrg 186045bc899bSmrgstatic int 186145bc899bSmrgVESADGAGetViewport(ScrnInfoPtr pScrn) 186245bc899bSmrg{ 186345bc899bSmrg return (0); 186445bc899bSmrg} 186545bc899bSmrg 186645bc899bSmrgstatic DGAFunctionRec VESADGAFunctions = 186745bc899bSmrg{ 186845bc899bSmrg VESADGAOpenFramebuffer, 186945bc899bSmrg NULL, /* CloseFramebuffer */ 187045bc899bSmrg VESADGASetMode, 187145bc899bSmrg VESADGASetViewport, 187245bc899bSmrg VESADGAGetViewport, 187345bc899bSmrg NULL, /* Sync */ 187445bc899bSmrg NULL, /* FillRect */ 187545bc899bSmrg NULL, /* BlitRect */ 187645bc899bSmrg NULL, /* BlitTransRect */ 187745bc899bSmrg}; 187845bc899bSmrg 187945bc899bSmrgstatic void 188045bc899bSmrgVESADGAAddModes(ScrnInfoPtr pScrn) 188145bc899bSmrg{ 188245bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 188345bc899bSmrg DisplayModePtr pMode = pScrn->modes; 188445bc899bSmrg DGAModePtr pDGAMode; 188545bc899bSmrg 188645bc899bSmrg do { 1887b40a6198Smrg pDGAMode = realloc(pVesa->pDGAMode, 188845bc899bSmrg (pVesa->nDGAMode + 1) * sizeof(DGAModeRec)); 188945bc899bSmrg if (!pDGAMode) 189045bc899bSmrg break; 189145bc899bSmrg 189245bc899bSmrg pVesa->pDGAMode = pDGAMode; 189345bc899bSmrg pDGAMode += pVesa->nDGAMode; 189445bc899bSmrg (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 189545bc899bSmrg 189645bc899bSmrg ++pVesa->nDGAMode; 189745bc899bSmrg pDGAMode->mode = pMode; 189845bc899bSmrg pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 189945bc899bSmrg pDGAMode->byteOrder = pScrn->imageByteOrder; 190045bc899bSmrg pDGAMode->depth = pScrn->depth; 190145bc899bSmrg pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 190245bc899bSmrg pDGAMode->red_mask = pScrn->mask.red; 190345bc899bSmrg pDGAMode->green_mask = pScrn->mask.green; 190445bc899bSmrg pDGAMode->blue_mask = pScrn->mask.blue; 190545bc899bSmrg pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 190645bc899bSmrg TrueColor : PseudoColor; 190745bc899bSmrg pDGAMode->xViewportStep = 1; 190845bc899bSmrg pDGAMode->yViewportStep = 1; 190945bc899bSmrg pDGAMode->viewportWidth = pMode->HDisplay; 191045bc899bSmrg pDGAMode->viewportHeight = pMode->VDisplay; 191145bc899bSmrg 191245bc899bSmrg pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline; 191345bc899bSmrg pDGAMode->imageWidth = pMode->HDisplay; 191445bc899bSmrg pDGAMode->imageHeight = pMode->VDisplay; 191545bc899bSmrg pDGAMode->pixmapWidth = pDGAMode->imageWidth; 191645bc899bSmrg pDGAMode->pixmapHeight = pDGAMode->imageHeight; 191745bc899bSmrg pDGAMode->maxViewportX = pScrn->virtualX - 191845bc899bSmrg pDGAMode->viewportWidth; 191945bc899bSmrg pDGAMode->maxViewportY = pScrn->virtualY - 192045bc899bSmrg pDGAMode->viewportHeight; 192145bc899bSmrg 192245bc899bSmrg pDGAMode->address = pVesa->base; 192345bc899bSmrg 192445bc899bSmrg pMode = pMode->next; 192545bc899bSmrg } while (pMode != pScrn->modes); 192645bc899bSmrg} 192745bc899bSmrg 192845bc899bSmrgstatic Bool 192945bc899bSmrgVESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 193045bc899bSmrg{ 193145bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 193245bc899bSmrg 193345bc899bSmrg if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L) 193445bc899bSmrg return (FALSE); 193545bc899bSmrg 193645bc899bSmrg if (!pVesa->nDGAMode) 193745bc899bSmrg VESADGAAddModes(pScrn); 193845bc899bSmrg 193945bc899bSmrg return (DGAInit(pScreen, &VESADGAFunctions, 194045bc899bSmrg pVesa->pDGAMode, pVesa->nDGAMode)); 194145bc899bSmrg} 1942