vesa.c revision a0c41156
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> 4745bc899bSmrg#include "vesa.h" 4845bc899bSmrg 4945bc899bSmrg/* All drivers initialising the SW cursor need this */ 5045bc899bSmrg#include "mipointer.h" 5145bc899bSmrg 5245bc899bSmrg/* Colormap handling */ 5345bc899bSmrg#include "micmap.h" 5445bc899bSmrg#include "xf86cmap.h" 5550f2e948Smrg#include "xf86Modes.h" 5645bc899bSmrg 5745bc899bSmrg/* DPMS */ 583a925b30Smrg#ifdef HAVE_XEXTPROTO_71 593a925b30Smrg#include <X11/extensions/dpmsconst.h> 603a925b30Smrg#else 6145bc899bSmrg#define DPMS_SERVER 6245bc899bSmrg#include <X11/extensions/dpms.h> 633a925b30Smrg#endif 64b40a6198Smrg#include "compat-api.h" 6545bc899bSmrg 6645bc899bSmrg/* Mandatory functions */ 6745bc899bSmrgstatic const OptionInfoRec * VESAAvailableOptions(int chipid, int busid); 6845bc899bSmrgstatic void VESAIdentify(int flags); 69f2408745Smrg#if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA) 70f2408745Smrg#define VESAProbe NULL 71f2408745Smrg#else 7245bc899bSmrgstatic Bool VESAProbe(DriverPtr drv, int flags); 73f2408745Smrg#endif 7450f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 7550f2e948Smrgstatic Bool VESAPciProbe(DriverPtr drv, int entity_num, 7650f2e948Smrg struct pci_device *dev, intptr_t match_data); 7750f2e948Smrg#endif 7845bc899bSmrgstatic Bool VESAPreInit(ScrnInfoPtr pScrn, int flags); 79b40a6198Smrgstatic Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL); 80b40a6198Smrgstatic Bool VESAEnterVT(VT_FUNC_ARGS_DECL); 81b40a6198Smrgstatic void VESALeaveVT(VT_FUNC_ARGS_DECL); 82b40a6198Smrgstatic Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL); 8345bc899bSmrgstatic Bool VESASaveScreen(ScreenPtr pScreen, int mode); 8445bc899bSmrg 85b40a6198Smrgstatic Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL); 8645bc899bSmrgstatic Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); 87b40a6198Smrgstatic void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL); 88b40a6198Smrgstatic void VESAFreeScreen(FREE_SCREEN_ARGS_DECL); 8945bc899bSmrgstatic void VESAFreeRec(ScrnInfoPtr pScrn); 9050f2e948Smrgstatic VESAPtr VESAGetRec(ScrnInfoPtr pScrn); 9145bc899bSmrg 9245bc899bSmrgstatic void 9345bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 9445bc899bSmrg int flags); 9545bc899bSmrg 9645bc899bSmrg/* locally used functions */ 975592a31fSmrg#ifdef HAVE_ISA 9845bc899bSmrgstatic int VESAFindIsaDevice(GDevPtr dev); 995592a31fSmrg#endif 10045bc899bSmrgstatic Bool VESAMapVidMem(ScrnInfoPtr pScrn); 10145bc899bSmrgstatic void VESAUnmapVidMem(ScrnInfoPtr pScrn); 10245bc899bSmrgstatic int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank); 10345bc899bSmrgstatic void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 10445bc899bSmrg LOCO *colors, VisualPtr pVisual); 10545bc899bSmrgstatic void SaveFonts(ScrnInfoPtr pScrn); 10645bc899bSmrgstatic void RestoreFonts(ScrnInfoPtr pScrn); 10745bc899bSmrgstatic Bool 10845bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); 10945bc899bSmrg 1105592a31fSmrgstatic void * 1115592a31fSmrgVESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1125592a31fSmrg CARD32 *size, void *closure) 1135592a31fSmrg{ 114b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1155592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1165592a31fSmrg 1175592a31fSmrg *size = pVesa->maxBytesPerScanline; 1185592a31fSmrg return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset); 1195592a31fSmrg} 1205592a31fSmrg 1215592a31fSmrgstatic void * 1225592a31fSmrgVESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1235592a31fSmrg CARD32 *size, void *closure) 1245592a31fSmrg{ 125b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1265592a31fSmrg VESAPtr pVesa = VESAGetRec(pScrn); 1275592a31fSmrg VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 1285592a31fSmrg int window; 1295592a31fSmrg 1305592a31fSmrg offset += pVesa->maxBytesPerScanline * row; 1315592a31fSmrg window = offset / (data->WinGranularity * 1024); 1325592a31fSmrg pVesa->windowAoffset = window * data->WinGranularity * 1024; 1335592a31fSmrg VESABankSwitch(pScreen, window); 1345592a31fSmrg *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset); 1355592a31fSmrg 1365592a31fSmrg return (void *)((unsigned long)pVesa->base + 1375592a31fSmrg (offset - pVesa->windowAoffset)); 1385592a31fSmrg} 1395592a31fSmrg 1405592a31fSmrgstatic void 1415592a31fSmrgvesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 1425592a31fSmrg{ 1435592a31fSmrg shadowUpdatePacked(pScreen, pBuf); 1445592a31fSmrg} 14545bc899bSmrg 14645bc899bSmrgstatic Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen); 14745bc899bSmrg 14845bc899bSmrgenum GenericTypes 14945bc899bSmrg{ 15045bc899bSmrg CHIP_VESA_GENERIC 15145bc899bSmrg}; 15245bc899bSmrg 15350f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 15450f2e948Smrgstatic const struct pci_id_match vesa_device_match[] = { 15550f2e948Smrg { 15650f2e948Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 15750f2e948Smrg 0x00030000, 0x00ffffff, CHIP_VESA_GENERIC 15850f2e948Smrg }, 15950f2e948Smrg 16050f2e948Smrg { 0, 0, 0 }, 16150f2e948Smrg}; 16250f2e948Smrg#endif 16350f2e948Smrg 16445bc899bSmrg/* Supported chipsets */ 16545bc899bSmrgstatic SymTabRec VESAChipsets[] = 16645bc899bSmrg{ 16745bc899bSmrg {CHIP_VESA_GENERIC, "vesa"}, 16845bc899bSmrg {-1, NULL} 16945bc899bSmrg}; 17045bc899bSmrg 17150f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 17245bc899bSmrgstatic PciChipsets VESAPCIchipsets[] = { 17345bc899bSmrg { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA }, 17445bc899bSmrg { -1, -1, RES_UNDEFINED }, 17545bc899bSmrg}; 17650f2e948Smrg#endif 17745bc899bSmrg 17850f2e948Smrg#ifdef HAVE_ISA 17945bc899bSmrgstatic IsaChipsets VESAISAchipsets[] = { 18045bc899bSmrg {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA}, 18145bc899bSmrg {-1, 0 } 18245bc899bSmrg}; 18350f2e948Smrg#endif 18450f2e948Smrg 18550f2e948Smrg 18650f2e948Smrg/* 18750f2e948Smrg * This contains the functions needed by the server after loading the 18850f2e948Smrg * driver module. It must be supplied, and gets added the driver list by 18950f2e948Smrg * the Module Setup funtion in the dynamic case. In the static case a 19050f2e948Smrg * reference to this is compiled in, and this requires that the name of 19150f2e948Smrg * this DriverRec be an upper-case version of the driver name. 19250f2e948Smrg */ 19350f2e948Smrg_X_EXPORT DriverRec VESA = { 19450f2e948Smrg VESA_VERSION, 19550f2e948Smrg VESA_DRIVER_NAME, 19650f2e948Smrg VESAIdentify, 19750f2e948Smrg VESAProbe, 19850f2e948Smrg VESAAvailableOptions, 19950f2e948Smrg NULL, 20050f2e948Smrg 0, 20150f2e948Smrg NULL, 20250f2e948Smrg 20350f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 20450f2e948Smrg vesa_device_match, 20550f2e948Smrg VESAPciProbe 20650f2e948Smrg#endif 20750f2e948Smrg}; 20850f2e948Smrg 20945bc899bSmrg 21045bc899bSmrgtypedef enum { 21145bc899bSmrg OPTION_SHADOW_FB, 21245bc899bSmrg OPTION_DFLT_REFRESH, 21345bc899bSmrg OPTION_MODESET_CLEAR_SCREEN 21445bc899bSmrg} VESAOpts; 21545bc899bSmrg 21645bc899bSmrgstatic const OptionInfoRec VESAOptions[] = { 21745bc899bSmrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 21845bc899bSmrg { OPTION_DFLT_REFRESH, "DefaultRefresh", OPTV_BOOLEAN, {0}, FALSE }, 21945bc899bSmrg { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen", 22045bc899bSmrg OPTV_BOOLEAN, {0}, FALSE }, 22145bc899bSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 22245bc899bSmrg}; 22345bc899bSmrg 22445bc899bSmrg#ifdef XFree86LOADER 22545bc899bSmrg 22645bc899bSmrg/* Module loader interface */ 22745bc899bSmrgstatic MODULESETUPPROTO(vesaSetup); 22845bc899bSmrg 22945bc899bSmrgstatic XF86ModuleVersionInfo vesaVersionRec = 23045bc899bSmrg{ 23145bc899bSmrg VESA_DRIVER_NAME, 23245bc899bSmrg MODULEVENDORSTRING, 23345bc899bSmrg MODINFOSTRING1, 23445bc899bSmrg MODINFOSTRING2, 23545bc899bSmrg XORG_VERSION_CURRENT, 23645bc899bSmrg VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL, 23745bc899bSmrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 23845bc899bSmrg ABI_VIDEODRV_VERSION, 23945bc899bSmrg MOD_CLASS_VIDEODRV, 24045bc899bSmrg {0, 0, 0, 0} 24145bc899bSmrg}; 24245bc899bSmrg 24345bc899bSmrg/* 24445bc899bSmrg * This data is accessed by the loader. The name must be the module name 24545bc899bSmrg * followed by "ModuleData". 24645bc899bSmrg */ 24745bc899bSmrg_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL }; 24845bc899bSmrg 24945bc899bSmrgstatic pointer 25045bc899bSmrgvesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor) 25145bc899bSmrg{ 25245bc899bSmrg static Bool Initialised = FALSE; 25345bc899bSmrg 25445bc899bSmrg if (!Initialised) 25545bc899bSmrg { 25645bc899bSmrg Initialised = TRUE; 25750f2e948Smrg xf86AddDriver(&VESA, Module, 1); 25845bc899bSmrg return (pointer)TRUE; 25945bc899bSmrg } 26045bc899bSmrg 26145bc899bSmrg if (ErrorMajor) 26245bc899bSmrg *ErrorMajor = LDR_ONCEONLY; 26345bc899bSmrg return (NULL); 26445bc899bSmrg} 26545bc899bSmrg 26645bc899bSmrg#endif 26745bc899bSmrg 26845bc899bSmrgstatic const OptionInfoRec * 26945bc899bSmrgVESAAvailableOptions(int chipid, int busid) 27045bc899bSmrg{ 27145bc899bSmrg return (VESAOptions); 27245bc899bSmrg} 27345bc899bSmrg 27445bc899bSmrgstatic void 27545bc899bSmrgVESAIdentify(int flags) 27645bc899bSmrg{ 27745bc899bSmrg xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets); 27845bc899bSmrg} 27945bc899bSmrg 28050f2e948Smrgstatic VESAPtr 28150f2e948SmrgVESAGetRec(ScrnInfoPtr pScrn) 28250f2e948Smrg{ 28350f2e948Smrg if (!pScrn->driverPrivate) 284b40a6198Smrg pScrn->driverPrivate = calloc(sizeof(VESARec), 1); 28550f2e948Smrg 28650f2e948Smrg return ((VESAPtr)pScrn->driverPrivate); 28750f2e948Smrg} 28850f2e948Smrg 28950f2e948Smrg/* Only a little like VBESetModeParameters */ 29050f2e948Smrgstatic void 29150f2e948SmrgVESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode, 29250f2e948Smrg DisplayModePtr ddcmode) 29350f2e948Smrg{ 29450f2e948Smrg VbeModeInfoData *data; 29550f2e948Smrg int clock; 29650f2e948Smrg 29750f2e948Smrg data = (VbeModeInfoData *)vbemode->Private; 29850f2e948Smrg 299b40a6198Smrg data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); 30050f2e948Smrg data->block->HorizontalTotal = ddcmode->HTotal; 30150f2e948Smrg data->block->HorizontalSyncStart = ddcmode->HSyncStart; 30250f2e948Smrg data->block->HorizontalSyncEnd = ddcmode->HSyncEnd; 30350f2e948Smrg data->block->VerticalTotal = ddcmode->VTotal; 30450f2e948Smrg data->block->VerticalSyncStart = ddcmode->VSyncStart; 30550f2e948Smrg data->block->VerticalSyncEnd = ddcmode->VSyncEnd; 30650f2e948Smrg data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | 30750f2e948Smrg ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); 30850f2e948Smrg data->block->PixelClock = ddcmode->Clock * 1000; 30950f2e948Smrg 31050f2e948Smrg /* ask the BIOS to figure out the real clock */ 31150f2e948Smrg clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); 31250f2e948Smrg if (clock) 31350f2e948Smrg data->block->PixelClock = clock; 31450f2e948Smrg 31550f2e948Smrg data->mode |= (1 << 11); 31650f2e948Smrg data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) / 31750f2e948Smrg (double)(ddcmode->HTotal * ddcmode->VTotal)); 31850f2e948Smrg} 31950f2e948Smrg 320b40a6198Smrg/* 321b40a6198Smrg * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes 322b40a6198Smrg * think they can only give sizes in multiples of character cells; and 323b40a6198Smrg * indeed, the reference CVT and GTF formulae only give results where 324b40a6198Smrg * (h % 8) == 0. Whatever, let's just try to cope. What we're looking for 325b40a6198Smrg * here is cases where the display says 1366x768 and the BIOS says 1360x768. 326b40a6198Smrg */ 327b40a6198Smrgstatic Bool 328b40a6198SmrgvesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe) 329b40a6198Smrg{ 330b40a6198Smrg if (!(edid->type & M_T_DRIVER)) 331b40a6198Smrg return FALSE; 332b40a6198Smrg 333b40a6198Smrg /* never seen a height granularity... */ 334b40a6198Smrg if (edid->VDisplay != vbe->VDisplay) 335b40a6198Smrg return FALSE; 336b40a6198Smrg 337b40a6198Smrg if (edid->HDisplay >= vbe->HDisplay && 338b40a6198Smrg (edid->HDisplay & ~7) == (vbe->HDisplay & ~7)) 339b40a6198Smrg return TRUE; 340b40a6198Smrg 341b40a6198Smrg return FALSE; 342b40a6198Smrg} 343b40a6198Smrg 34450f2e948Smrgstatic ModeStatus 345b40a6198SmrgVESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass) 34650f2e948Smrg{ 347b40a6198Smrg SCRN_INFO_PTR(arg); 34850f2e948Smrg static int warned = 0; 34950f2e948Smrg int found = 0; 35050f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 35150f2e948Smrg MonPtr mon = pScrn->monitor; 35250f2e948Smrg ModeStatus ret = MODE_BAD; 35350f2e948Smrg DisplayModePtr mode; 35450f2e948Smrg float v; 35550f2e948Smrg 35650f2e948Smrg pVesa = VESAGetRec(pScrn); 35750f2e948Smrg 35850f2e948Smrg if (pass != MODECHECK_FINAL) { 35950f2e948Smrg if (!warned) { 360b40a6198Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n"); 36150f2e948Smrg warned = 1; 36250f2e948Smrg } 36350f2e948Smrg return MODE_OK; 36450f2e948Smrg } 36550f2e948Smrg 36650f2e948Smrg /* 36750f2e948Smrg * This is suboptimal. We pass in just the barest description of a mode 36850f2e948Smrg * we can get away with to VBEValidateModes, so it can't really throw 36950f2e948Smrg * out anything we give it. But we need to filter the list so that we 37050f2e948Smrg * don't populate the mode list with things the monitor can't do. 37150f2e948Smrg * 37250f2e948Smrg * So first off, if this isn't a mode we handed to the server (ie, 37350f2e948Smrg * M_T_BUILTIN), then we know we can't do it. 37450f2e948Smrg */ 37550f2e948Smrg if (!(p->type & M_T_BUILTIN)) 37650f2e948Smrg return MODE_NOMODE; 37750f2e948Smrg 37850f2e948Smrg if (pVesa->strict_validation) { 37950f2e948Smrg /* 38050f2e948Smrg * If it's our first pass at mode validation, we'll try for a strict 38150f2e948Smrg * intersection between the VBE and DDC mode lists. 38250f2e948Smrg */ 38350f2e948Smrg if (pScrn->monitor->DDC) { 38450f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) { 385b40a6198Smrg if (vesaModesCloseEnough(mode, p)) { 38650f2e948Smrg if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) { 38750f2e948Smrg found = 1; 38850f2e948Smrg break; 38950f2e948Smrg } 39050f2e948Smrg } 39150f2e948Smrg if (mode == pScrn->monitor->Last) 39250f2e948Smrg break; 39350f2e948Smrg } 39450f2e948Smrg if (!found) 39550f2e948Smrg return MODE_NOMODE; 39650f2e948Smrg 39750f2e948Smrg /* having found a matching mode, stash the CRTC values aside */ 39850f2e948Smrg VESASetModeParameters(pVesa->pVbe, p, mode); 39950f2e948Smrg return MODE_OK; 40050f2e948Smrg } 40150f2e948Smrg 40250f2e948Smrg /* No DDC and no modes make Homer something something... */ 40350f2e948Smrg return MODE_NOMODE; 40450f2e948Smrg } 40550f2e948Smrg 40650f2e948Smrg /* 40750f2e948Smrg * Finally, walk through the vsync rates 1Hz at a time looking for a mode 40850f2e948Smrg * that will fit. This is assuredly a terrible way to do this, but 40950f2e948Smrg * there's no obvious method for computing a mode of a given size that 41050f2e948Smrg * will pass xf86CheckModeForMonitor. XXX this path is terrible, but 41150f2e948Smrg * then, by this point, you're well into despair territory. 41250f2e948Smrg */ 41350f2e948Smrg for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) { 41450f2e948Smrg mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0); 41550f2e948Smrg ret = xf86CheckModeForMonitor(mode, mon); 416b40a6198Smrg free(mode->name); 417b40a6198Smrg free(mode); 41850f2e948Smrg if (ret == MODE_OK) 41950f2e948Smrg break; 42050f2e948Smrg } 42150f2e948Smrg 42250f2e948Smrg return ret; 42350f2e948Smrg} 42450f2e948Smrg 42550f2e948Smrgstatic void 42650f2e948SmrgVESAInitScrn(ScrnInfoPtr pScrn) 42750f2e948Smrg{ 42850f2e948Smrg pScrn->driverVersion = VESA_VERSION; 42950f2e948Smrg pScrn->driverName = VESA_DRIVER_NAME; 43050f2e948Smrg pScrn->name = VESA_NAME; 43150f2e948Smrg pScrn->Probe = VESAProbe; 43250f2e948Smrg pScrn->PreInit = VESAPreInit; 43350f2e948Smrg pScrn->ScreenInit = VESAScreenInit; 43450f2e948Smrg pScrn->SwitchMode = VESASwitchMode; 43550f2e948Smrg pScrn->ValidMode = VESAValidMode; 43650f2e948Smrg pScrn->AdjustFrame = VESAAdjustFrame; 43750f2e948Smrg pScrn->EnterVT = VESAEnterVT; 43850f2e948Smrg pScrn->LeaveVT = VESALeaveVT; 43950f2e948Smrg pScrn->FreeScreen = VESAFreeScreen; 44050f2e948Smrg} 44150f2e948Smrg 44245bc899bSmrg/* 44345bc899bSmrg * This function is called once, at the start of the first server generation to 44445bc899bSmrg * do a minimal probe for supported hardware. 44545bc899bSmrg */ 44645bc899bSmrg 44750f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 44850f2e948Smrgstatic Bool 44950f2e948SmrgVESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, 45050f2e948Smrg intptr_t match_data) 45150f2e948Smrg{ 45250f2e948Smrg ScrnInfoPtr pScrn; 453a0c41156Smrg 454a0c41156Smrg#ifdef __linux__ 455a0c41156Smrg if (access("/sys/devices/platform/efi-framebuffer.0", F_OK) == 0 || 456a0c41156Smrg access("/sys/devices/platform/efifb.0", F_OK) == 0) { 457a0c41156Smrg ErrorF("vesa: Refusing to run on UEFI\n"); 458a0c41156Smrg return FALSE; 459a0c41156Smrg } 460a0c41156Smrg#endif 461a0c41156Smrg 46250f2e948Smrg pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, 46350f2e948Smrg NULL, NULL, NULL, NULL, NULL); 46450f2e948Smrg if (pScrn != NULL) { 465b40a6198Smrg VESAPtr pVesa; 466b40a6198Smrg 467b40a6198Smrg if (pci_device_has_kernel_driver(dev)) { 468b40a6198Smrg ErrorF("vesa: Ignoring device with a bound kernel driver\n"); 469b40a6198Smrg return FALSE; 470b40a6198Smrg } 47150f2e948Smrg 472b40a6198Smrg pVesa = VESAGetRec(pScrn); 47350f2e948Smrg VESAInitScrn(pScrn); 47450f2e948Smrg pVesa->pciInfo = dev; 47550f2e948Smrg } 47650f2e948Smrg 47750f2e948Smrg return (pScrn != NULL); 47850f2e948Smrg} 47950f2e948Smrg#endif 48050f2e948Smrg 481f2408745Smrg#ifndef VESAProbe 48245bc899bSmrgstatic Bool 48345bc899bSmrgVESAProbe(DriverPtr drv, int flags) 48445bc899bSmrg{ 48545bc899bSmrg Bool foundScreen = FALSE; 48645bc899bSmrg int numDevSections, numUsed; 48745bc899bSmrg GDevPtr *devSections; 48845bc899bSmrg int *usedChips; 48945bc899bSmrg int i; 49045bc899bSmrg 49145bc899bSmrg /* 49245bc899bSmrg * Find the config file Device sections that match this 49345bc899bSmrg * driver, and return if there are none. 49445bc899bSmrg */ 49545bc899bSmrg if ((numDevSections = xf86MatchDevice(VESA_NAME, 49645bc899bSmrg &devSections)) <= 0) 49745bc899bSmrg return (FALSE); 49845bc899bSmrg 49950f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 50045bc899bSmrg /* PCI BUS */ 50145bc899bSmrg if (xf86GetPciVideoInfo()) { 50245bc899bSmrg numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC, 50345bc899bSmrg VESAChipsets, VESAPCIchipsets, 50445bc899bSmrg devSections, numDevSections, 50545bc899bSmrg drv, &usedChips); 50645bc899bSmrg if (numUsed > 0) { 50745bc899bSmrg if (flags & PROBE_DETECT) 50845bc899bSmrg foundScreen = TRUE; 50945bc899bSmrg else { 51045bc899bSmrg for (i = 0; i < numUsed; i++) { 51145bc899bSmrg ScrnInfoPtr pScrn = NULL; 51245bc899bSmrg /* Allocate a ScrnInfoRec */ 51345bc899bSmrg if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 51445bc899bSmrg VESAPCIchipsets,NULL, 51545bc899bSmrg NULL,NULL,NULL,NULL))) { 51650f2e948Smrg VESAInitScrn(pScrn); 51745bc899bSmrg foundScreen = TRUE; 51845bc899bSmrg } 51945bc899bSmrg } 52045bc899bSmrg } 521b40a6198Smrg free(usedChips); 52245bc899bSmrg } 52345bc899bSmrg } 52450f2e948Smrg#endif 52545bc899bSmrg 52650f2e948Smrg#ifdef HAVE_ISA 52745bc899bSmrg /* Isa Bus */ 52845bc899bSmrg numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets, 52945bc899bSmrg VESAISAchipsets, drv, 53045bc899bSmrg VESAFindIsaDevice, devSections, 53145bc899bSmrg numDevSections, &usedChips); 53245bc899bSmrg if(numUsed > 0) { 53345bc899bSmrg if (flags & PROBE_DETECT) 53445bc899bSmrg foundScreen = TRUE; 53545bc899bSmrg else for (i = 0; i < numUsed; i++) { 53645bc899bSmrg ScrnInfoPtr pScrn = NULL; 53745bc899bSmrg if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i], 53845bc899bSmrg VESAISAchipsets, NULL, 53945bc899bSmrg NULL, NULL, NULL, NULL))) { 54050f2e948Smrg VESAInitScrn(pScrn); 54145bc899bSmrg foundScreen = TRUE; 54245bc899bSmrg } 54345bc899bSmrg } 544b40a6198Smrg free(usedChips); 54545bc899bSmrg } 54650f2e948Smrg#endif 54745bc899bSmrg 548b40a6198Smrg free(devSections); 54945bc899bSmrg 55045bc899bSmrg return (foundScreen); 55145bc899bSmrg} 552f2408745Smrg#endif 55345bc899bSmrg 55450f2e948Smrg#ifdef HAVE_ISA 55545bc899bSmrgstatic int 55645bc899bSmrgVESAFindIsaDevice(GDevPtr dev) 55745bc899bSmrg{ 55845bc899bSmrg#ifndef PC98_EGC 55945bc899bSmrg CARD16 GenericIOBase = VGAHW_GET_IOBASE(); 56045bc899bSmrg CARD8 CurrentValue, TestValue; 56145bc899bSmrg 56245bc899bSmrg /* There's no need to unlock VGA CRTC registers here */ 56345bc899bSmrg 56445bc899bSmrg /* VGA has one more read/write attribute register than EGA */ 56545bc899bSmrg (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */ 56645bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 56745bc899bSmrg CurrentValue = inb(VGA_ATTR_DATA_R); 56845bc899bSmrg outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F); 56945bc899bSmrg outb(VGA_ATTR_INDEX, 0x14 | 0x20); 57045bc899bSmrg TestValue = inb(VGA_ATTR_DATA_R); 57145bc899bSmrg outb(VGA_ATTR_DATA_R, CurrentValue); 57245bc899bSmrg 57345bc899bSmrg /* Quit now if no VGA is present */ 57445bc899bSmrg if ((CurrentValue ^ 0x0F) != TestValue) 57545bc899bSmrg return -1; 57645bc899bSmrg#endif 57745bc899bSmrg return (int)CHIP_VESA_GENERIC; 57845bc899bSmrg} 57950f2e948Smrg#endif 58045bc899bSmrg 58145bc899bSmrgstatic void 58245bc899bSmrgVESAFreeRec(ScrnInfoPtr pScrn) 58345bc899bSmrg{ 58445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 58545bc899bSmrg#if 0 58645bc899bSmrg DisplayModePtr mode = pScrn->modes; 58745bc899bSmrg /* I am not sure if the modes will ever get freed. 58845bc899bSmrg * Anyway, the data unknown to other modules is being freed here. 58945bc899bSmrg */ 59045bc899bSmrg if (mode) { 59145bc899bSmrg do { 59245bc899bSmrg if (mode->Private) { 59345bc899bSmrg VbeModeInfoData *data = (VbeModeInfoData*)mode->Private; 59445bc899bSmrg 59545bc899bSmrg if (data->block) 596b40a6198Smrg free(data->block); 59745bc899bSmrg 598b40a6198Smrg free(data); 59945bc899bSmrg 60045bc899bSmrg mode->Private = NULL; 60145bc899bSmrg } 60245bc899bSmrg mode = mode->next; 60345bc899bSmrg } while (mode && mode != pScrn->modes); 60445bc899bSmrg } 60545bc899bSmrg#endif 606b40a6198Smrg free(pVesa->monitor); 607f2408745Smrg if (pVesa->vbeInfo) 608f2408745Smrg VBEFreeVBEInfo(pVesa->vbeInfo); 609b40a6198Smrg free(pVesa->pal); 610b40a6198Smrg free(pVesa->savedPal); 611b40a6198Smrg free(pVesa->fonts); 612b40a6198Smrg free(pScrn->driverPrivate); 61345bc899bSmrg pScrn->driverPrivate = NULL; 61445bc899bSmrg} 61545bc899bSmrg 61650f2e948Smrgstatic int 61750f2e948SmrgVESAValidateModes(ScrnInfoPtr pScrn) 61850f2e948Smrg{ 61950f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 62050f2e948Smrg DisplayModePtr mode; 62150f2e948Smrg 62250f2e948Smrg for (mode = pScrn->monitor->Modes; mode; mode = mode->next) 62350f2e948Smrg mode->status = MODE_OK; 62450f2e948Smrg 62550f2e948Smrg return VBEValidateModes(pScrn, NULL, pScrn->display->modes, 6265592a31fSmrg NULL, NULL, 0, 32767, 1, 0, 32767, 62750f2e948Smrg pScrn->display->virtualX, 62850f2e948Smrg pScrn->display->virtualY, 62950f2e948Smrg pVesa->mapSize, LOOKUP_BEST_REFRESH); 63050f2e948Smrg} 63150f2e948Smrg 63245bc899bSmrg/* 63345bc899bSmrg * This function is called once for each screen at the start of the first 63445bc899bSmrg * server generation to initialise the screen for all server generations. 63545bc899bSmrg */ 63645bc899bSmrgstatic Bool 63745bc899bSmrgVESAPreInit(ScrnInfoPtr pScrn, int flags) 63845bc899bSmrg{ 63945bc899bSmrg VESAPtr pVesa; 64045bc899bSmrg VbeInfoBlock *vbe; 64145bc899bSmrg DisplayModePtr pMode; 64245bc899bSmrg VbeModeInfoBlock *mode; 64345bc899bSmrg Gamma gzeros = {0.0, 0.0, 0.0}; 64445bc899bSmrg rgb rzeros = {0, 0, 0}; 64545bc899bSmrg pointer pDDCModule; 64645bc899bSmrg int i; 64745bc899bSmrg int flags24 = 0; 64845bc899bSmrg int defaultDepth = 0; 64950f2e948Smrg int defaultBpp = 0; 65045bc899bSmrg int depths = 0; 65145bc899bSmrg 65245bc899bSmrg if (flags & PROBE_DETECT) 65345bc899bSmrg return (FALSE); 65445bc899bSmrg 65545bc899bSmrg pVesa = VESAGetRec(pScrn); 65645bc899bSmrg pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 65745bc899bSmrg 65845bc899bSmrg /* Load vbe module */ 65945bc899bSmrg if (!xf86LoadSubModule(pScrn, "vbe")) 66045bc899bSmrg return (FALSE); 66145bc899bSmrg 66245bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 66345bc899bSmrg SET_BIOS_SCRATCH 66445bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 66545bc899bSmrg return (FALSE); 66645bc899bSmrg 66750f2e948Smrg#ifndef XSERVER_LIBPCIACCESS 66845bc899bSmrg if (pVesa->pEnt->location.type == BUS_PCI) { 66945bc899bSmrg pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index); 67045bc899bSmrg pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device, 67145bc899bSmrg pVesa->pciInfo->func); 67245bc899bSmrg } 67350f2e948Smrg#endif 67445bc899bSmrg 67545bc899bSmrg pScrn->chipset = "vesa"; 67645bc899bSmrg pScrn->monitor = pScrn->confScreen->monitor; 67745bc899bSmrg pScrn->progClock = TRUE; 67845bc899bSmrg pScrn->rgbBits = 8; 67945bc899bSmrg 68045bc899bSmrg if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL) 68145bc899bSmrg return (FALSE); 68245bc899bSmrg pVesa->major = (unsigned)(vbe->VESAVersion >> 8); 68345bc899bSmrg pVesa->minor = vbe->VESAVersion & 0xff; 68445bc899bSmrg pVesa->vbeInfo = vbe; 68545bc899bSmrg pScrn->videoRam = vbe->TotalMemory * 64; 68645bc899bSmrg 68745bc899bSmrg /* 68845bc899bSmrg * Find what depths are available. 68945bc899bSmrg */ 69045bc899bSmrg depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24, 69145bc899bSmrg V_MODETYPE_VBE); 69245bc899bSmrg 69345bc899bSmrg /* Preferred order for default depth selection. */ 694a0c41156Smrg if (depths & V_DEPTH_24 && (flags24 & Support32bppFb)) 69550f2e948Smrg defaultDepth = 24; 69650f2e948Smrg else if (depths & V_DEPTH_16) 69745bc899bSmrg defaultDepth = 16; 69845bc899bSmrg else if (depths & V_DEPTH_15) 69945bc899bSmrg defaultDepth = 15; 700a0c41156Smrg else if (depths & V_DEPTH_24) 701a0c41156Smrg defaultDepth = 24; /* ew though */ 70245bc899bSmrg else if (depths & V_DEPTH_8) 70345bc899bSmrg defaultDepth = 8; 70445bc899bSmrg else if (depths & V_DEPTH_4) 70545bc899bSmrg defaultDepth = 4; 70645bc899bSmrg else if (depths & V_DEPTH_1) 70745bc899bSmrg defaultDepth = 1; 70845bc899bSmrg 70950f2e948Smrg if (defaultDepth == 24 && !(flags24 & Support32bppFb)) 71050f2e948Smrg defaultBpp = 24; 71145bc899bSmrg 71250f2e948Smrg /* Prefer 32bpp because 1999 called and wants its packed pixels back */ 71350f2e948Smrg if (flags24 & Support32bppFb) 71450f2e948Smrg flags24 |= SupportConvert24to32 | PreferConvert24to32; 71545bc899bSmrg if (flags24 & Support24bppFb) 71650f2e948Smrg flags24 |= SupportConvert32to24; 71745bc899bSmrg 71850f2e948Smrg if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) { 71945bc899bSmrg vbeFree(pVesa->pVbe); 72045bc899bSmrg return (FALSE); 72145bc899bSmrg } 72245bc899bSmrg xf86PrintDepthBpp(pScrn); 72345bc899bSmrg 72445bc899bSmrg /* color weight */ 72545bc899bSmrg if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) { 72645bc899bSmrg vbeFree(pVesa->pVbe); 72745bc899bSmrg return (FALSE); 72845bc899bSmrg } 72945bc899bSmrg /* visual init */ 73045bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) { 73145bc899bSmrg vbeFree(pVesa->pVbe); 73245bc899bSmrg return (FALSE); 73345bc899bSmrg } 73445bc899bSmrg 73545bc899bSmrg xf86SetGamma(pScrn, gzeros); 73645bc899bSmrg 737f2408745Smrg /* set up options before loading any modules that may look at them */ 738f2408745Smrg xf86CollectOptions(pScrn, NULL); 739f2408745Smrg 74045bc899bSmrg if (pVesa->major >= 2) { 74145bc899bSmrg /* Load ddc module */ 74245bc899bSmrg if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { 74345bc899bSmrg vbeFree(pVesa->pVbe); 74445bc899bSmrg return (FALSE); 74545bc899bSmrg } 74645bc899bSmrg 74745bc899bSmrg if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) { 74845bc899bSmrg xf86PrintEDID(pVesa->monitor); 74945bc899bSmrg } 75045bc899bSmrg 75145bc899bSmrg xf86UnloadSubModule(pDDCModule); 75245bc899bSmrg } 75345bc899bSmrg 75445bc899bSmrg if ((pScrn->monitor->DDC = pVesa->monitor) != NULL) 75545bc899bSmrg xf86SetDDCproperties(pScrn, pVesa->monitor); 7563a925b30Smrg else { 7573a925b30Smrg void *panelid = VBEReadPanelID(pVesa->pVbe); 758b40a6198Smrg VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid); 759b40a6198Smrg free(panelid); 7603a925b30Smrg } 76145bc899bSmrg 76245bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 76345bc899bSmrg "Searching for matching VESA mode(s):\n"); 76445bc899bSmrg 76545bc899bSmrg /* 76645bc899bSmrg * Check the available BIOS modes, and extract those that match the 76745bc899bSmrg * requirements into the modePool. Note: modePool is a NULL-terminated 76845bc899bSmrg * list. 76945bc899bSmrg */ 77045bc899bSmrg pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo, 77145bc899bSmrg V_MODETYPE_VBE); 77245bc899bSmrg 77345bc899bSmrg xf86ErrorFVerb(DEBUG_VERB, "\n"); 77445bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 77545bc899bSmrg "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory, 77645bc899bSmrg (vbe->TotalMemory * 65536) / 1024); 77745bc899bSmrg 77845bc899bSmrg pVesa->mapSize = vbe->TotalMemory * 65536; 77945bc899bSmrg if (pScrn->modePool == NULL) { 78045bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n"); 78145bc899bSmrg vbeFree(pVesa->pVbe); 78245bc899bSmrg return (FALSE); 78345bc899bSmrg } 78445bc899bSmrg 78545bc899bSmrg VBESetModeNames(pScrn->modePool); 78645bc899bSmrg 78750f2e948Smrg pVesa->strict_validation = TRUE; 78850f2e948Smrg i = VESAValidateModes(pScrn); 78950f2e948Smrg 79050f2e948Smrg if (i <= 0) { 79150f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 79250f2e948Smrg "No valid modes left. Trying less strict filter...\n"); 79350f2e948Smrg pVesa->strict_validation = FALSE; 79450f2e948Smrg i = VESAValidateModes(pScrn); 79550f2e948Smrg } 79650f2e948Smrg 79750f2e948Smrg if (i <= 0) do { 79850f2e948Smrg Bool changed = FALSE; 79950f2e948Smrg /* maybe there's more modes at the bottom... */ 80050f2e948Smrg if (pScrn->monitor->vrefresh[0].lo > 50) { 80150f2e948Smrg changed = TRUE; 80250f2e948Smrg pScrn->monitor->vrefresh[0].lo = 50; 80350f2e948Smrg } 80450f2e948Smrg if (pScrn->monitor->hsync[0].lo > 31.5) { 80550f2e948Smrg changed = TRUE; 80650f2e948Smrg pScrn->monitor->hsync[0].lo = 31.5; 80750f2e948Smrg } 80850f2e948Smrg 80950f2e948Smrg if (!changed) 81050f2e948Smrg break; 81150f2e948Smrg 81250f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 81350f2e948Smrg "No valid modes left. Trying aggressive sync range...\n"); 81450f2e948Smrg i = VESAValidateModes(pScrn); 81550f2e948Smrg } while (0); 81645bc899bSmrg 81745bc899bSmrg if (i <= 0) { 81850f2e948Smrg /* alright, i'm out of ideas */ 81945bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n"); 82045bc899bSmrg vbeFree(pVesa->pVbe); 82145bc899bSmrg return (FALSE); 82245bc899bSmrg } 82345bc899bSmrg 82445bc899bSmrg xf86PruneDriverModes(pScrn); 82545bc899bSmrg 82645bc899bSmrg pMode = pScrn->modes; 82745bc899bSmrg do { 82845bc899bSmrg mode = ((VbeModeInfoData*)pMode->Private)->data; 82945bc899bSmrg if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) { 83045bc899bSmrg pVesa->maxBytesPerScanline = mode->BytesPerScanline; 83145bc899bSmrg } 83245bc899bSmrg pMode = pMode->next; 83345bc899bSmrg } while (pMode != pScrn->modes); 83445bc899bSmrg 83545bc899bSmrg pScrn->currentMode = pScrn->modes; 83645bc899bSmrg pScrn->displayWidth = pScrn->virtualX; 83745bc899bSmrg 83845bc899bSmrg VBEPrintModes(pScrn); 83945bc899bSmrg 84045bc899bSmrg /* Set display resolution */ 84145bc899bSmrg xf86SetDpi(pScrn, 0, 0); 84245bc899bSmrg 84345bc899bSmrg if (pScrn->modes == NULL) { 84445bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); 84545bc899bSmrg vbeFree(pVesa->pVbe); 84645bc899bSmrg return (FALSE); 84745bc899bSmrg } 84845bc899bSmrg 84945bc899bSmrg /* options */ 850b40a6198Smrg if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) { 85145bc899bSmrg vbeFree(pVesa->pVbe); 85245bc899bSmrg return FALSE; 85345bc899bSmrg } 85445bc899bSmrg memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions)); 85545bc899bSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options); 85645bc899bSmrg 857a0c41156Smrg /* Use shadow by default, for non-virt hardware */ 858a0c41156Smrg if (!xf86GetOptValBool(pVesa->Options, OPTION_SHADOW_FB, &pVesa->shadowFB)) 859a0c41156Smrg { 860a0c41156Smrg switch (pVesa->pciInfo->vendor_id) { 861a0c41156Smrg case 0x1234: /* bochs vga (not in pci.ids) */ 862a0c41156Smrg case 0x15ad: /* vmware */ 863a0c41156Smrg case 0x1b36: /* qemu qxl */ 864a0c41156Smrg case 0x80ee: /* virtualbox */ 865a0c41156Smrg case 0xaaaa: /* parallels (not in pci.ids) */ 866a0c41156Smrg pVesa->shadowFB = FALSE; 867a0c41156Smrg break; 868a0c41156Smrg 869a0c41156Smrg case 0x1013: /* qemu's cirrus emulation */ 870a0c41156Smrg if (pVesa->pciInfo->subvendor_id == 0x1af4) 871a0c41156Smrg pVesa->shadowFB = FALSE; 872a0c41156Smrg else 873a0c41156Smrg pVesa->shadowFB = TRUE; 874a0c41156Smrg break; 875a0c41156Smrg 876a0c41156Smrg case 0x1414: /* microsoft hyper-v */ 877a0c41156Smrg if (pVesa->pciInfo->device_id == 0x5353) 878a0c41156Smrg pVesa->shadowFB = FALSE; 879a0c41156Smrg else 880a0c41156Smrg pVesa->shadowFB = TRUE; 881a0c41156Smrg break; 882a0c41156Smrg 883a0c41156Smrg default: 884a0c41156Smrg pVesa->shadowFB = TRUE; 885a0c41156Smrg break; 886a0c41156Smrg } 887a0c41156Smrg } 888a0c41156Smrg 889f2408745Smrg /* Use default refresh by default. Too many VBE 3.0 890f2408745Smrg * BIOSes are incorrectly implemented. 891f2408745Smrg */ 892f2408745Smrg pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options, 893f2408745Smrg OPTION_DFLT_REFRESH, TRUE); 89445bc899bSmrg 895c97b1c41Smrg pVesa->ModeSetClearScreen = 896c97b1c41Smrg xf86ReturnOptValBool(pVesa->Options, 897c97b1c41Smrg OPTION_MODESET_CLEAR_SCREEN, FALSE); 89845bc899bSmrg 89950f2e948Smrg if (!pVesa->defaultRefresh && !pVesa->strict_validation) 90045bc899bSmrg VBESetModeParameters(pScrn, pVesa->pVbe); 90145bc899bSmrg 90245bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 90345bc899bSmrg switch (mode->MemoryModel) { 90445bc899bSmrg case 0x4: /* Packed pixel */ 90550f2e948Smrg case 0x6: /* Direct Color */ 90645bc899bSmrg pScrn->bitmapBitOrder = BITMAP_BIT_ORDER; 90745bc899bSmrg 90845bc899bSmrg switch (pScrn->bitsPerPixel) { 90945bc899bSmrg case 8: 91045bc899bSmrg case 16: 91145bc899bSmrg case 24: 91245bc899bSmrg case 32: 91345bc899bSmrg break; 91445bc899bSmrg default: 91545bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 916a0c41156Smrg "Unsupported bpp: %d\n", pScrn->bitsPerPixel); 91745bc899bSmrg vbeFree(pVesa->pVbe); 91845bc899bSmrg return FALSE; 91945bc899bSmrg } 92045bc899bSmrg break; 92150f2e948Smrg default: 92250f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 923a0c41156Smrg "Unsupported Memory Model: %d\n", mode->MemoryModel); 92450f2e948Smrg return FALSE; 92545bc899bSmrg } 92645bc899bSmrg 92745bc899bSmrg if (pVesa->shadowFB) { 92845bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); 92945bc899bSmrg if (!xf86LoadSubModule(pScrn, "shadow")) { 93045bc899bSmrg vbeFree(pVesa->pVbe); 93145bc899bSmrg return (FALSE); 93245bc899bSmrg } 93345bc899bSmrg } 93445bc899bSmrg 93550f2e948Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 93645bc899bSmrg VESAFreeRec(pScrn); 93745bc899bSmrg vbeFree(pVesa->pVbe); 93845bc899bSmrg return (FALSE); 93945bc899bSmrg } 94045bc899bSmrg 94145bc899bSmrg vbeFree(pVesa->pVbe); 94245bc899bSmrg 94345bc899bSmrg return (TRUE); 94445bc899bSmrg} 94545bc899bSmrg 94645bc899bSmrgstatic Bool 94745bc899bSmrgvesaCreateScreenResources(ScreenPtr pScreen) 94845bc899bSmrg{ 949b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 95045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 95145bc899bSmrg Bool ret; 95245bc899bSmrg 95345bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 95445bc899bSmrg ret = pScreen->CreateScreenResources(pScreen); 95545bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 95645bc899bSmrg 95745bc899bSmrg shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update, 95845bc899bSmrg pVesa->window, 0, 0); 95945bc899bSmrg 96045bc899bSmrg return ret; 96145bc899bSmrg} 96245bc899bSmrg 96350f2e948Smrgstatic void 964b40a6198SmrgvesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable) 96550f2e948Smrg{ 966b40a6198Smrg SCRN_INFO_PTR(arg); 96750f2e948Smrg VESAPtr pVesa = VESAGetRec(pScrn); 96850f2e948Smrg 96950f2e948Smrg pVesa->accessEnabled = enable; 970b40a6198Smrg pVesa->EnableDisableFBAccess(arg, enable); 97150f2e948Smrg} 97250f2e948Smrg 97345bc899bSmrgstatic Bool 974b40a6198SmrgVESAScreenInit(SCREEN_INIT_ARGS_DECL) 97545bc899bSmrg{ 976b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 97745bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 97845bc899bSmrg VisualPtr visual; 97945bc899bSmrg VbeModeInfoBlock *mode; 98045bc899bSmrg int flags; 98145bc899bSmrg 98245bc899bSmrg if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index, 98345bc899bSmrg SET_BIOS_SCRATCH 98445bc899bSmrg | RESTORE_BIOS_SCRATCH)) == NULL) 98545bc899bSmrg return (FALSE); 98645bc899bSmrg 98745bc899bSmrg if (pVesa->mapPhys == 0) { 98845bc899bSmrg mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data; 98945bc899bSmrg pScrn->videoRam = pVesa->mapSize; 99045bc899bSmrg pVesa->mapPhys = mode->PhysBasePtr; 99145bc899bSmrg pVesa->mapOff = 0; 99245bc899bSmrg } 99345bc899bSmrg 99445bc899bSmrg if (pVesa->mapPhys == 0) { 99545bc899bSmrg pVesa->mapPhys = 0xa0000; 99645bc899bSmrg pVesa->mapSize = 0x10000; 99745bc899bSmrg } 99845bc899bSmrg 99945bc899bSmrg if (!VESAMapVidMem(pScrn)) { 100045bc899bSmrg if (pVesa->mapPhys != 0xa0000) { 100145bc899bSmrg pVesa->mapPhys = 0xa0000; 100245bc899bSmrg pVesa->mapSize = 0x10000; 100345bc899bSmrg if (!VESAMapVidMem(pScrn)) 100445bc899bSmrg return (FALSE); 100545bc899bSmrg } 100645bc899bSmrg else 100745bc899bSmrg return (FALSE); 100845bc899bSmrg } 100945bc899bSmrg 101045bc899bSmrg /* Set bpp to 8 for depth 4 when using shadowfb. */ 101145bc899bSmrg if (pVesa->shadowFB && pScrn->bitsPerPixel == 4) 101245bc899bSmrg pScrn->bitsPerPixel = 8; 101345bc899bSmrg 101445bc899bSmrg if (pVesa->shadowFB) { 1015b40a6198Smrg pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY * 101645bc899bSmrg ((pScrn->bitsPerPixel + 7) / 8)); 101745bc899bSmrg if (!pVesa->shadow) { 101845bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 101945bc899bSmrg "Failed to allocate shadow buffer\n"); 102045bc899bSmrg return FALSE; 102145bc899bSmrg } 102245bc899bSmrg } 102345bc899bSmrg 102445bc899bSmrg /* save current video state */ 102545bc899bSmrg VESASaveRestore(pScrn, MODE_SAVE); 102645bc899bSmrg pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256, 102745bc899bSmrg NULL, FALSE, FALSE); 102845bc899bSmrg 102945bc899bSmrg /* set first video mode */ 103045bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 103145bc899bSmrg return (FALSE); 103245bc899bSmrg 103345bc899bSmrg /* set the viewport */ 1034b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 103545bc899bSmrg 103645bc899bSmrg /* Blank the screen for aesthetic reasons. */ 103745bc899bSmrg VESASaveScreen(pScreen, SCREEN_SAVER_ON); 103845bc899bSmrg 103945bc899bSmrg /* mi layer */ 104045bc899bSmrg miClearVisualTypes(); 104145bc899bSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 104245bc899bSmrg return (FALSE); 104345bc899bSmrg if (pScrn->bitsPerPixel > 8) { 104445bc899bSmrg if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 104545bc899bSmrg pScrn->rgbBits, TrueColor)) 104645bc899bSmrg return (FALSE); 104745bc899bSmrg } 104845bc899bSmrg else { 104945bc899bSmrg if (!miSetVisualTypes(pScrn->depth, 105045bc899bSmrg miGetDefaultVisualMask(pScrn->depth), 105145bc899bSmrg pScrn->rgbBits, pScrn->defaultVisual)) 105245bc899bSmrg return (FALSE); 105345bc899bSmrg } 105445bc899bSmrg if (!miSetPixmapDepths()) 105545bc899bSmrg return (FALSE); 105645bc899bSmrg 105745bc899bSmrg mode = ((VbeModeInfoData*)pScrn->modes->Private)->data; 105845bc899bSmrg switch (mode->MemoryModel) { 105945bc899bSmrg case 0x4: /* Packed pixel */ 106050f2e948Smrg case 0x6: /* Direct Color */ 106145bc899bSmrg switch (pScrn->bitsPerPixel) { 106245bc899bSmrg case 8: 106345bc899bSmrg case 16: 106445bc899bSmrg case 24: 106545bc899bSmrg case 32: 106645bc899bSmrg if (!fbScreenInit(pScreen, 106745bc899bSmrg pVesa->shadowFB ? pVesa->shadow : pVesa->base, 106845bc899bSmrg pScrn->virtualX, pScrn->virtualY, 106945bc899bSmrg pScrn->xDpi, pScrn->yDpi, 107045bc899bSmrg pScrn->displayWidth, pScrn->bitsPerPixel)) 107145bc899bSmrg return (FALSE); 107245bc899bSmrg break; 107345bc899bSmrg default: 107445bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 107545bc899bSmrg "Unsupported bpp: %d", pScrn->bitsPerPixel); 107645bc899bSmrg return (FALSE); 107745bc899bSmrg } 107845bc899bSmrg break; 107950f2e948Smrg default: 108050f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 108150f2e948Smrg "Unsupported Memory Model: %d", mode->MemoryModel); 108250f2e948Smrg return (FALSE); 108345bc899bSmrg } 108445bc899bSmrg 108545bc899bSmrg 108645bc899bSmrg if (pScrn->bitsPerPixel > 8) { 108745bc899bSmrg /* Fixup RGB ordering */ 108845bc899bSmrg visual = pScreen->visuals + pScreen->numVisuals; 108945bc899bSmrg while (--visual >= pScreen->visuals) { 109045bc899bSmrg if ((visual->class | DynamicClass) == DirectColor) { 109145bc899bSmrg visual->offsetRed = pScrn->offset.red; 109245bc899bSmrg visual->offsetGreen = pScrn->offset.green; 109345bc899bSmrg visual->offsetBlue = pScrn->offset.blue; 109445bc899bSmrg visual->redMask = pScrn->mask.red; 109545bc899bSmrg visual->greenMask = pScrn->mask.green; 109645bc899bSmrg visual->blueMask = pScrn->mask.blue; 109745bc899bSmrg } 109845bc899bSmrg } 109945bc899bSmrg } 110045bc899bSmrg 110145bc899bSmrg /* must be after RGB ordering fixed */ 11025592a31fSmrg fbPictureInit(pScreen, 0, 0); 110345bc899bSmrg 110445bc899bSmrg if (pVesa->shadowFB) { 110550f2e948Smrg if (pVesa->mapPhys == 0xa0000) { /* Windowed */ 11065592a31fSmrg pVesa->update = vesaUpdatePacked; 110745bc899bSmrg pVesa->window = VESAWindowWindowed; 110845bc899bSmrg } 110945bc899bSmrg else { /* Linear */ 11105592a31fSmrg pVesa->update = vesaUpdatePacked; 111145bc899bSmrg pVesa->window = VESAWindowLinear; 111245bc899bSmrg } 111345bc899bSmrg 111445bc899bSmrg if (!shadowSetup(pScreen)) 111545bc899bSmrg return FALSE; 111645bc899bSmrg pVesa->CreateScreenResources = pScreen->CreateScreenResources; 111745bc899bSmrg pScreen->CreateScreenResources = vesaCreateScreenResources; 111845bc899bSmrg } 111950f2e948Smrg else if (pVesa->mapPhys == 0xa0000) { 11205592a31fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 11215592a31fSmrg "Banked framebuffer requires ShadowFB\n"); 11225592a31fSmrg return FALSE; 112345bc899bSmrg } 112445bc899bSmrg 112545bc899bSmrg VESADGAInit(pScrn, pScreen); 112645bc899bSmrg 112745bc899bSmrg xf86SetBlackWhitePixels(pScreen); 112845bc899bSmrg xf86SetBackingStore(pScreen); 112945bc899bSmrg 113045bc899bSmrg /* software cursor */ 113145bc899bSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 113245bc899bSmrg 113345bc899bSmrg /* colormap */ 113445bc899bSmrg if (!miCreateDefColormap(pScreen)) 113545bc899bSmrg return (FALSE); 113645bc899bSmrg 113745bc899bSmrg flags = CMAP_RELOAD_ON_MODE_SWITCH; 113845bc899bSmrg 113945bc899bSmrg if(!xf86HandleColormaps(pScreen, 256, 114045bc899bSmrg pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6, 114145bc899bSmrg VESALoadPalette, NULL, flags)) 114245bc899bSmrg return (FALSE); 114345bc899bSmrg 114450f2e948Smrg pVesa->accessEnabled = TRUE; 114550f2e948Smrg pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; 114650f2e948Smrg pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess; 114750f2e948Smrg 114845bc899bSmrg pVesa->CloseScreen = pScreen->CloseScreen; 114945bc899bSmrg pScreen->CloseScreen = VESACloseScreen; 115045bc899bSmrg pScreen->SaveScreen = VESASaveScreen; 115145bc899bSmrg 115245bc899bSmrg xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0); 115345bc899bSmrg 115445bc899bSmrg /* Report any unused options (only for the first generation) */ 115545bc899bSmrg if (serverGeneration == 1) 115645bc899bSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 115745bc899bSmrg 115845bc899bSmrg return (TRUE); 115945bc899bSmrg} 116045bc899bSmrg 116145bc899bSmrgstatic Bool 1162b40a6198SmrgVESAEnterVT(VT_FUNC_ARGS_DECL) 116345bc899bSmrg{ 1164b40a6198Smrg SCRN_INFO_PTR(arg); 116545bc899bSmrg 116645bc899bSmrg if (!VESASetMode(pScrn, pScrn->currentMode)) 116745bc899bSmrg return FALSE; 1168b40a6198Smrg VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 116945bc899bSmrg return TRUE; 117045bc899bSmrg} 117145bc899bSmrg 117245bc899bSmrgstatic void 1173b40a6198SmrgVESALeaveVT(VT_FUNC_ARGS_DECL) 117445bc899bSmrg{ 1175b40a6198Smrg SCRN_INFO_PTR(arg); 1176b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 117745bc899bSmrg} 117845bc899bSmrg 117945bc899bSmrgstatic Bool 1180b40a6198SmrgVESACloseScreen(CLOSE_SCREEN_ARGS_DECL) 118145bc899bSmrg{ 1182b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 118345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 118445bc899bSmrg 118545bc899bSmrg if (pScrn->vtSema) { 1186b40a6198Smrg VESASaveRestore(pScrn, MODE_RESTORE); 118745bc899bSmrg if (pVesa->savedPal) 118845bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256, 118945bc899bSmrg pVesa->savedPal, FALSE, TRUE); 119045bc899bSmrg VESAUnmapVidMem(pScrn); 119145bc899bSmrg } 11925592a31fSmrg if (pVesa->shadowFB && pVesa->shadow) { 11935592a31fSmrg shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); 1194b40a6198Smrg free(pVesa->shadow); 11955592a31fSmrg } 119645bc899bSmrg if (pVesa->pDGAMode) { 1197b40a6198Smrg free(pVesa->pDGAMode); 119845bc899bSmrg pVesa->pDGAMode = NULL; 119945bc899bSmrg pVesa->nDGAMode = 0; 120045bc899bSmrg } 120145bc899bSmrg pScrn->vtSema = FALSE; 120245bc899bSmrg 120350f2e948Smrg pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess; 120445bc899bSmrg pScreen->CreateScreenResources = pVesa->CreateScreenResources; 120545bc899bSmrg pScreen->CloseScreen = pVesa->CloseScreen; 1206b40a6198Smrg return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); 120745bc899bSmrg} 120845bc899bSmrg 120945bc899bSmrgstatic Bool 1210b40a6198SmrgVESASwitchMode(SWITCH_MODE_ARGS_DECL) 121145bc899bSmrg{ 1212b40a6198Smrg SCRN_INFO_PTR(arg); 121345bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 121450f2e948Smrg Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled; 121545bc899bSmrg 121650f2e948Smrg if (disableAccess) 1217b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE); 1218b40a6198Smrg ret = VESASetMode(pScrn, mode); 121950f2e948Smrg if (disableAccess) 1220b40a6198Smrg pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE); 122145bc899bSmrg return ret; 122245bc899bSmrg} 122345bc899bSmrg 122445bc899bSmrg/* Set a graphics mode */ 122545bc899bSmrgstatic Bool 122645bc899bSmrgVESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 122745bc899bSmrg{ 122845bc899bSmrg VESAPtr pVesa; 122945bc899bSmrg VbeModeInfoData *data; 123045bc899bSmrg int mode; 123145bc899bSmrg 123245bc899bSmrg pVesa = VESAGetRec(pScrn); 123345bc899bSmrg 123445bc899bSmrg data = (VbeModeInfoData*)pMode->Private; 123550f2e948Smrg 123650f2e948Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 123750f2e948Smrg "Setting up VESA Mode 0x%X (%dx%d)\n", 123850f2e948Smrg data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay); 123950f2e948Smrg 124050f2e948Smrg /* careful, setting the bit means don't clear the screen */ 124150f2e948Smrg mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15)); 124245bc899bSmrg 124345bc899bSmrg /* enable linear addressing */ 124445bc899bSmrg if (pVesa->mapPhys != 0xa0000) 124545bc899bSmrg mode |= 1 << 14; 124645bc899bSmrg 124745bc899bSmrg if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) { 124845bc899bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed"); 124945bc899bSmrg if ((data->block || (data->mode & (1 << 11))) && 125045bc899bSmrg VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) { 125145bc899bSmrg /* Some cards do not like setting the clock. 125245bc899bSmrg * Free it as it will not be any longer useful 125345bc899bSmrg */ 12545592a31fSmrg xf86ErrorF(", mode set without customized refresh.\n"); 1255b40a6198Smrg free(data->block); 125645bc899bSmrg data->block = NULL; 125745bc899bSmrg data->mode &= ~(1 << 11); 125845bc899bSmrg } 125945bc899bSmrg else { 126045bc899bSmrg ErrorF("\n"); 126145bc899bSmrg return (FALSE); 126245bc899bSmrg } 126345bc899bSmrg } 126445bc899bSmrg 126545bc899bSmrg pVesa->bankSwitchWindowB = 126645bc899bSmrg !((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0)); 126745bc899bSmrg 126845bc899bSmrg if (data->data->XResolution != pScrn->displayWidth) 126945bc899bSmrg VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth); 127045bc899bSmrg 127145bc899bSmrg if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 && 127250f2e948Smrg !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7)) 127345bc899bSmrg VBESetGetDACPaletteFormat(pVesa->pVbe, 8); 127445bc899bSmrg 127545bc899bSmrg pScrn->vtSema = TRUE; 127645bc899bSmrg 127745bc899bSmrg return (TRUE); 127845bc899bSmrg} 127945bc899bSmrg 128045bc899bSmrgstatic void 1281b40a6198SmrgVESAAdjustFrame(ADJUST_FRAME_ARGS_DECL) 128245bc899bSmrg{ 1283b40a6198Smrg SCRN_INFO_PTR(arg); 1284b40a6198Smrg VESAPtr pVesa = VESAGetRec(pScrn); 128545bc899bSmrg 128645bc899bSmrg VBESetDisplayStart(pVesa->pVbe, x, y, TRUE); 128745bc899bSmrg} 128845bc899bSmrg 128945bc899bSmrgstatic void 1290b40a6198SmrgVESAFreeScreen(FREE_SCREEN_ARGS_DECL) 129145bc899bSmrg{ 1292b40a6198Smrg SCRN_INFO_PTR(arg); 1293b40a6198Smrg VESAFreeRec(pScrn); 129445bc899bSmrg} 129545bc899bSmrg 129645bc899bSmrgstatic Bool 129745bc899bSmrgVESAMapVidMem(ScrnInfoPtr pScrn) 129845bc899bSmrg{ 129945bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 130045bc899bSmrg 130145bc899bSmrg if (pVesa->base != NULL) 130245bc899bSmrg return (TRUE); 130345bc899bSmrg 130445bc899bSmrg pScrn->memPhysBase = pVesa->mapPhys; 130545bc899bSmrg pScrn->fbOffset = pVesa->mapOff; 130645bc899bSmrg 130750f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 1308b40a6198Smrg if (pVesa->pciInfo != NULL) { 1309b40a6198Smrg if (pVesa->mapPhys != 0xa0000) { 1310b40a6198Smrg (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase, 1311b40a6198Smrg pVesa->mapSize, 1312b40a6198Smrg (PCI_DEV_MAP_FLAG_WRITABLE 1313b40a6198Smrg | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 1314b40a6198Smrg & pVesa->base); 1315b40a6198Smrg 1316b40a6198Smrg if (pVesa->base) 1317b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000, 1318b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1319b40a6198Smrg & pVesa->VGAbase); 1320b40a6198Smrg } 1321b40a6198Smrg else { 1322b40a6198Smrg (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase, 1323b40a6198Smrg pVesa->mapSize, 1324b40a6198Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1325b40a6198Smrg & pVesa->base); 132650f2e948Smrg 1327b40a6198Smrg if (pVesa->base) 1328b40a6198Smrg pVesa->VGAbase = pVesa->base; 1329b40a6198Smrg } 133050f2e948Smrg } 133150f2e948Smrg#else 133245bc899bSmrg if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI) 133345bc899bSmrg pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 133445bc899bSmrg pVesa->pciTag, pScrn->memPhysBase, 133545bc899bSmrg pVesa->mapSize); 133645bc899bSmrg else 133745bc899bSmrg pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag, 133845bc899bSmrg pScrn->memPhysBase, pVesa->mapSize); 133945bc899bSmrg 134045bc899bSmrg if (pVesa->base) { 134145bc899bSmrg if (pVesa->mapPhys != 0xa0000) 134245bc899bSmrg pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0, 134345bc899bSmrg pVesa->pciTag, 134445bc899bSmrg 0xa0000, 0x10000); 134545bc899bSmrg else 134645bc899bSmrg pVesa->VGAbase = pVesa->base; 134745bc899bSmrg } 134850f2e948Smrg#endif 134945bc899bSmrg 1350b40a6198Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 135145bc899bSmrg pVesa->ioBase = pScrn->domainIOBase; 1352b40a6198Smrg#else 1353b40a6198Smrg pVesa->ioBase = 0; 1354b40a6198Smrg#endif 135545bc899bSmrg 135645bc899bSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB, 1357b1fb1a22Smrg "virtual address = %p, VGAbase = %p\n" 135845bc899bSmrg "\tphysical address = 0x%lx, size = %ld\n", 1359b1fb1a22Smrg pVesa->base, pVesa->VGAbase, 1360b1fb1a22Smrg pScrn->memPhysBase, pVesa->mapSize); 136145bc899bSmrg 136245bc899bSmrg return (pVesa->base != NULL); 136345bc899bSmrg} 136445bc899bSmrg 136545bc899bSmrgstatic void 136645bc899bSmrgVESAUnmapVidMem(ScrnInfoPtr pScrn) 136745bc899bSmrg{ 136845bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 136945bc899bSmrg 137045bc899bSmrg if (pVesa->base == NULL) 137145bc899bSmrg return; 137245bc899bSmrg 137350f2e948Smrg#ifdef XSERVER_LIBPCIACCESS 137450f2e948Smrg if (pVesa->mapPhys != 0xa0000) { 137550f2e948Smrg (void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base, 137650f2e948Smrg pVesa->mapSize); 1377b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase, 1378b40a6198Smrg 0x10000); 137950f2e948Smrg } 138050f2e948Smrg else { 1381b40a6198Smrg (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base, 1382b40a6198Smrg pVesa->mapSize); 138350f2e948Smrg } 138450f2e948Smrg#else 138545bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize); 138645bc899bSmrg if (pVesa->mapPhys != 0xa0000) 138745bc899bSmrg xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000); 138850f2e948Smrg#endif 138945bc899bSmrg pVesa->base = NULL; 139045bc899bSmrg} 139145bc899bSmrg 13925592a31fSmrg/* This code works, but is very slow for programs that use it intensively */ 139345bc899bSmrgstatic void 139445bc899bSmrgVESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 139545bc899bSmrg LOCO *colors, VisualPtr pVisual) 139645bc899bSmrg{ 139745bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 139845bc899bSmrg int i, idx; 139945bc899bSmrg int base; 140045bc899bSmrg 1401f2408745Smrg if (!pVesa->savedPal) { 1402f2408745Smrg#define VESADACDelay() \ 1403f2408745Smrg do { \ 1404f2408745Smrg (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1405f2408745Smrg (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \ 1406f2408745Smrg } while (0) 1407f2408745Smrg 1408f2408745Smrg for (i = 0; i < numColors; i++) { 1409f2408745Smrg idx = indices[i]; 1410f2408745Smrg outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx); 1411f2408745Smrg VESADACDelay(); 1412f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red); 1413f2408745Smrg VESADACDelay(); 1414f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green); 1415f2408745Smrg VESADACDelay(); 1416f2408745Smrg outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue); 1417f2408745Smrg VESADACDelay(); 1418f2408745Smrg } 1419f2408745Smrg return; 1420f2408745Smrg } 1421f2408745Smrg 142245bc899bSmrg if (pVesa->pal == NULL) 1423b40a6198Smrg pVesa->pal = calloc(1, sizeof(CARD32) * 256); 142445bc899bSmrg 142545bc899bSmrg for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) { 142645bc899bSmrg int j = indices[i]; 142745bc899bSmrg 142845bc899bSmrg if (j < 0 || j >= 256) 142945bc899bSmrg continue; 143045bc899bSmrg pVesa->pal[j] = colors[j].blue | 143145bc899bSmrg (colors[j].green << 8) | 143245bc899bSmrg (colors[j].red << 16); 143345bc899bSmrg if (j != idx) { 143445bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 143545bc899bSmrg pVesa->pal + base, FALSE, TRUE); 143645bc899bSmrg idx = base = j; 143745bc899bSmrg } 143845bc899bSmrg } 143945bc899bSmrg 144045bc899bSmrg if (idx - 1 == indices[i - 1]) 144145bc899bSmrg VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base, 144245bc899bSmrg pVesa->pal + base, FALSE, TRUE); 144345bc899bSmrg} 144445bc899bSmrg 144545bc899bSmrg/* 144645bc899bSmrg * Just adapted from the std* functions in vgaHW.c 144745bc899bSmrg */ 144845bc899bSmrgstatic void 144945bc899bSmrgWriteAttr(VESAPtr pVesa, int index, int value) 145045bc899bSmrg{ 145145bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 145245bc899bSmrg 145345bc899bSmrg index |= 0x20; 145445bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 145545bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_DATA_W, value); 145645bc899bSmrg} 145745bc899bSmrg 145845bc899bSmrgstatic int 145945bc899bSmrgReadAttr(VESAPtr pVesa, int index) 146045bc899bSmrg{ 146145bc899bSmrg (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 146245bc899bSmrg 146345bc899bSmrg index |= 0x20; 146445bc899bSmrg outb(pVesa->ioBase + VGA_ATTR_INDEX, index); 146545bc899bSmrg return (inb(pVesa->ioBase + VGA_ATTR_DATA_R)); 146645bc899bSmrg} 146745bc899bSmrg 146845bc899bSmrg#define WriteMiscOut(value) outb(pVesa->ioBase + VGA_MISC_OUT_W, value) 146945bc899bSmrg#define ReadMiscOut() inb(pVesa->ioBase + VGA_MISC_OUT_R) 147045bc899bSmrg#define WriteSeq(index, value) outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\ 147145bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_DATA, value) 147245bc899bSmrg 147345bc899bSmrgstatic int 147445bc899bSmrgReadSeq(VESAPtr pVesa, int index) 147545bc899bSmrg{ 147645bc899bSmrg outb(pVesa->ioBase + VGA_SEQ_INDEX, index); 147745bc899bSmrg 147845bc899bSmrg return (inb(pVesa->ioBase + VGA_SEQ_DATA)); 147945bc899bSmrg} 148045bc899bSmrg 148145bc899bSmrg#define WriteGr(index, value) \ 148245bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); \ 148345bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_DATA, value) 148445bc899bSmrg 148545bc899bSmrgstatic int 148645bc899bSmrgReadGr(VESAPtr pVesa, int index) 148745bc899bSmrg{ 148845bc899bSmrg outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); 148945bc899bSmrg 149045bc899bSmrg return (inb(pVesa->ioBase + VGA_GRAPH_DATA)); 149145bc899bSmrg} 149245bc899bSmrg 149345bc899bSmrg#define WriteCrtc(index, value) \ 149445bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \ 149545bc899bSmrg outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value) 149645bc899bSmrg 149745bc899bSmrgstatic void 149845bc899bSmrgSeqReset(VESAPtr pVesa, Bool start) 149945bc899bSmrg{ 150045bc899bSmrg if (start) { 150145bc899bSmrg WriteSeq(0x00, 0x01); /* Synchronous Reset */ 150245bc899bSmrg } 150345bc899bSmrg else { 150445bc899bSmrg WriteSeq(0x00, 0x03); /* End Reset */ 150545bc899bSmrg } 150645bc899bSmrg} 150745bc899bSmrg 150845bc899bSmrgstatic void 150945bc899bSmrgSaveFonts(ScrnInfoPtr pScrn) 151045bc899bSmrg{ 151145bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 151245bc899bSmrg unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 151345bc899bSmrg 151445bc899bSmrg if (pVesa->fonts != NULL) 151545bc899bSmrg return; 151645bc899bSmrg 151745bc899bSmrg /* If in graphics mode, don't save anything */ 151845bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 151945bc899bSmrg if (attr10 & 0x01) 152045bc899bSmrg return; 152145bc899bSmrg 1522b40a6198Smrg pVesa->fonts = malloc(16384); 152345bc899bSmrg 152445bc899bSmrg /* save the registers that are needed here */ 152545bc899bSmrg miscOut = ReadMiscOut(); 152645bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 152745bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 152845bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 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 154245bc899bSmrg /*font1 */ 154345bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 154445bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 154545bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 154645bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 154745bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 154845bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192); 154945bc899bSmrg 155045bc899bSmrg /* font2 */ 155145bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 155245bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 155345bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 155445bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 155545bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 155645bc899bSmrg slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192); 155745bc899bSmrg 155845bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 155945bc899bSmrg SeqReset(pVesa, TRUE); 156045bc899bSmrg WriteSeq(0x01, scrn); 156145bc899bSmrg SeqReset(pVesa, FALSE); 156245bc899bSmrg 156345bc899bSmrg /* Restore clobbered registers */ 156445bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 156545bc899bSmrg WriteSeq(0x02, seq2); 156645bc899bSmrg WriteSeq(0x04, seq4); 156745bc899bSmrg WriteGr(0x04, gr4); 156845bc899bSmrg WriteGr(0x05, gr5); 156945bc899bSmrg WriteGr(0x06, gr6); 157045bc899bSmrg WriteMiscOut(miscOut); 157145bc899bSmrg} 157245bc899bSmrg 157345bc899bSmrgstatic void 157445bc899bSmrgRestoreFonts(ScrnInfoPtr pScrn) 157545bc899bSmrg{ 157645bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 157745bc899bSmrg unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 157845bc899bSmrg 157945bc899bSmrg if (pVesa->fonts == NULL) 158045bc899bSmrg return; 158145bc899bSmrg 158245bc899bSmrg if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0) 158345bc899bSmrg VESABankSwitch(pScrn->pScreen, 0); 158445bc899bSmrg 158545bc899bSmrg /* save the registers that are needed here */ 158645bc899bSmrg miscOut = ReadMiscOut(); 158745bc899bSmrg attr10 = ReadAttr(pVesa, 0x10); 158845bc899bSmrg gr1 = ReadGr(pVesa, 0x01); 158945bc899bSmrg gr3 = ReadGr(pVesa, 0x03); 159045bc899bSmrg gr4 = ReadGr(pVesa, 0x04); 159145bc899bSmrg gr5 = ReadGr(pVesa, 0x05); 159245bc899bSmrg gr6 = ReadGr(pVesa, 0x06); 159345bc899bSmrg gr8 = ReadGr(pVesa, 0x08); 159445bc899bSmrg seq2 = ReadSeq(pVesa, 0x02); 159545bc899bSmrg seq4 = ReadSeq(pVesa, 0x04); 159645bc899bSmrg 159745bc899bSmrg /* Force into colour mode */ 159845bc899bSmrg WriteMiscOut(miscOut | 0x01); 159945bc899bSmrg 160045bc899bSmrg scrn = ReadSeq(pVesa, 0x01) | 0x20; 160145bc899bSmrg SeqReset(pVesa, TRUE); 160245bc899bSmrg WriteSeq(0x01, scrn); 160345bc899bSmrg SeqReset(pVesa, FALSE); 160445bc899bSmrg 160545bc899bSmrg WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */ 160645bc899bSmrg if (pScrn->depth == 4) { 160745bc899bSmrg /* GJA */ 160845bc899bSmrg WriteGr(0x03, 0x00); /* don't rotate, write unmodified */ 160945bc899bSmrg WriteGr(0x08, 0xFF); /* write all bits in a byte */ 161045bc899bSmrg WriteGr(0x01, 0x00); /* all planes come from CPU */ 161145bc899bSmrg } 161245bc899bSmrg 161345bc899bSmrg WriteSeq(0x02, 0x04); /* write to plane 2 */ 161445bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 161545bc899bSmrg WriteGr(0x04, 0x02); /* read plane 2 */ 161645bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 161745bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 161845bc899bSmrg slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192); 161945bc899bSmrg 162045bc899bSmrg WriteSeq(0x02, 0x08); /* write to plane 3 */ 162145bc899bSmrg WriteSeq(0x04, 0x06); /* enable plane graphics */ 162245bc899bSmrg WriteGr(0x04, 0x03); /* read plane 3 */ 162345bc899bSmrg WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */ 162445bc899bSmrg WriteGr(0x06, 0x05); /* set graphics */ 162545bc899bSmrg slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192); 162645bc899bSmrg 162745bc899bSmrg scrn = ReadSeq(pVesa, 0x01) & ~0x20; 162845bc899bSmrg SeqReset(pVesa, TRUE); 162945bc899bSmrg WriteSeq(0x01, scrn); 163045bc899bSmrg SeqReset(pVesa, FALSE); 163145bc899bSmrg 163245bc899bSmrg /* restore the registers that were changed */ 163345bc899bSmrg WriteMiscOut(miscOut); 163445bc899bSmrg WriteAttr(pVesa, 0x10, attr10); 163545bc899bSmrg WriteGr(0x01, gr1); 163645bc899bSmrg WriteGr(0x03, gr3); 163745bc899bSmrg WriteGr(0x04, gr4); 163845bc899bSmrg WriteGr(0x05, gr5); 163945bc899bSmrg WriteGr(0x06, gr6); 164045bc899bSmrg WriteGr(0x08, gr8); 164145bc899bSmrg WriteSeq(0x02, seq2); 164245bc899bSmrg WriteSeq(0x04, seq4); 164345bc899bSmrg} 164445bc899bSmrg 164545bc899bSmrgstatic Bool 164645bc899bSmrgVESASaveScreen(ScreenPtr pScreen, int mode) 164745bc899bSmrg{ 1648b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 164945bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 165045bc899bSmrg Bool on = xf86IsUnblank(mode); 165145bc899bSmrg 165245bc899bSmrg if (on) 165345bc899bSmrg SetTimeSinceLastInputEvent(); 165445bc899bSmrg 165545bc899bSmrg if (pScrn->vtSema) { 165645bc899bSmrg unsigned char scrn = ReadSeq(pVesa, 0x01); 165745bc899bSmrg 165845bc899bSmrg if (on) 165945bc899bSmrg scrn &= ~0x20; 166045bc899bSmrg else 166145bc899bSmrg scrn |= 0x20; 166245bc899bSmrg SeqReset(pVesa, TRUE); 166345bc899bSmrg WriteSeq(0x01, scrn); 166445bc899bSmrg SeqReset(pVesa, FALSE); 166545bc899bSmrg } 166645bc899bSmrg 166745bc899bSmrg return (TRUE); 166845bc899bSmrg} 166945bc899bSmrg 167045bc899bSmrgstatic int 167145bc899bSmrgVESABankSwitch(ScreenPtr pScreen, unsigned int iBank) 167245bc899bSmrg{ 1673b40a6198Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 167445bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 167545bc899bSmrg 167645bc899bSmrg if (pVesa->curBank == iBank) 167745bc899bSmrg return (0); 167845bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 0)) 167945bc899bSmrg return (1); 168045bc899bSmrg if (pVesa->bankSwitchWindowB) { 168145bc899bSmrg if (!VBEBankSwitch(pVesa->pVbe, iBank, 1)) 168245bc899bSmrg return (1); 168345bc899bSmrg } 168445bc899bSmrg pVesa->curBank = iBank; 168545bc899bSmrg 168645bc899bSmrg return (0); 168745bc899bSmrg} 168845bc899bSmrg 168945bc899bSmrgBool 169045bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 169145bc899bSmrg{ 169245bc899bSmrg VESAPtr pVesa; 169345bc899bSmrg 1694c97b1c41Smrg if (function < MODE_QUERY || function > MODE_RESTORE) 169545bc899bSmrg return (FALSE); 169645bc899bSmrg 169745bc899bSmrg pVesa = VESAGetRec(pScrn); 169845bc899bSmrg 169945bc899bSmrg 170045bc899bSmrg /* Query amount of memory to save state */ 170145bc899bSmrg if (function == MODE_QUERY || 170245bc899bSmrg (function == MODE_SAVE && pVesa->state == NULL)) { 170345bc899bSmrg 170445bc899bSmrg /* Make sure we save at least this information in case of failure */ 170545bc899bSmrg (void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode); 170645bc899bSmrg SaveFonts(pScrn); 170745bc899bSmrg 170845bc899bSmrg if (pVesa->major > 1) { 170945bc899bSmrg if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state, 171045bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 171145bc899bSmrg return FALSE; 171245bc899bSmrg 171345bc899bSmrg } 171445bc899bSmrg } 171545bc899bSmrg 171645bc899bSmrg /* Save/Restore Super VGA state */ 171745bc899bSmrg if (function != MODE_QUERY) { 171845bc899bSmrg Bool retval = TRUE; 171945bc899bSmrg 172045bc899bSmrg if (pVesa->major > 1) { 172145bc899bSmrg if (function == MODE_RESTORE) 172245bc899bSmrg memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize); 172345bc899bSmrg 172445bc899bSmrg if ((retval = VBESaveRestore(pVesa->pVbe,function, 172545bc899bSmrg (pointer)&pVesa->state, 172645bc899bSmrg &pVesa->stateSize,&pVesa->statePage)) 172745bc899bSmrg && function == MODE_SAVE) { 172845bc899bSmrg /* don't rely on the memory not being touched */ 172945bc899bSmrg if (pVesa->pstate == NULL) 1730b40a6198Smrg pVesa->pstate = malloc(pVesa->stateSize); 173145bc899bSmrg memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize); 173245bc899bSmrg } 173345bc899bSmrg } 173445bc899bSmrg 173545bc899bSmrg if (function == MODE_RESTORE) { 173645bc899bSmrg VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL); 173745bc899bSmrg RestoreFonts(pScrn); 173845bc899bSmrg } 173945bc899bSmrg 174045bc899bSmrg if (!retval) 174145bc899bSmrg return (FALSE); 174245bc899bSmrg 174345bc899bSmrg } 174445bc899bSmrg 174545bc899bSmrg return (TRUE); 174645bc899bSmrg} 174745bc899bSmrg 174845bc899bSmrgstatic void 174945bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, 175045bc899bSmrg int flags) 175145bc899bSmrg{ 175245bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 175345bc899bSmrg 175445bc899bSmrg if (!pScrn->vtSema) 175545bc899bSmrg return; 175645bc899bSmrg 175750f2e948Smrg VBEDPMSSet(pVesa->pVbe, mode); 175845bc899bSmrg} 175945bc899bSmrg 176045bc899bSmrg/*********************************************************************** 176145bc899bSmrg * DGA stuff 176245bc899bSmrg ***********************************************************************/ 176345bc899bSmrgstatic Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 176445bc899bSmrg unsigned char **ApertureBase, 176545bc899bSmrg int *ApertureSize, int *ApertureOffset, 176645bc899bSmrg int *flags); 176745bc899bSmrgstatic Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode); 176845bc899bSmrgstatic void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 176945bc899bSmrg 177045bc899bSmrgstatic Bool 177145bc899bSmrgVESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 177245bc899bSmrg unsigned char **ApertureBase, int *ApertureSize, 177345bc899bSmrg int *ApertureOffset, int *flags) 177445bc899bSmrg{ 177545bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 177645bc899bSmrg 177745bc899bSmrg *DeviceName = NULL; /* No special device */ 177845bc899bSmrg *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys); 177945bc899bSmrg *ApertureSize = pVesa->mapSize; 178045bc899bSmrg *ApertureOffset = pVesa->mapOff; 178145bc899bSmrg *flags = DGA_NEED_ROOT; 178245bc899bSmrg 178345bc899bSmrg return (TRUE); 178445bc899bSmrg} 178545bc899bSmrg 178645bc899bSmrgstatic Bool 178745bc899bSmrgVESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 178845bc899bSmrg{ 178945bc899bSmrg DisplayModePtr pMode; 179045bc899bSmrg int scrnIdx = pScrn->pScreen->myNum; 179145bc899bSmrg int frameX0, frameY0; 179245bc899bSmrg 179345bc899bSmrg if (pDGAMode) { 179445bc899bSmrg pMode = pDGAMode->mode; 179545bc899bSmrg frameX0 = frameY0 = 0; 179645bc899bSmrg } 179745bc899bSmrg else { 179845bc899bSmrg if (!(pMode = pScrn->currentMode)) 179945bc899bSmrg return (TRUE); 180045bc899bSmrg 180145bc899bSmrg frameX0 = pScrn->frameX0; 180245bc899bSmrg frameY0 = pScrn->frameY0; 180345bc899bSmrg } 180445bc899bSmrg 1805b40a6198Smrg if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 180645bc899bSmrg return (FALSE); 1807b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 180845bc899bSmrg 180945bc899bSmrg return (TRUE); 181045bc899bSmrg} 181145bc899bSmrg 181245bc899bSmrgstatic void 181345bc899bSmrgVESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 181445bc899bSmrg{ 1815b40a6198Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 181645bc899bSmrg} 181745bc899bSmrg 181845bc899bSmrgstatic int 181945bc899bSmrgVESADGAGetViewport(ScrnInfoPtr pScrn) 182045bc899bSmrg{ 182145bc899bSmrg return (0); 182245bc899bSmrg} 182345bc899bSmrg 182445bc899bSmrgstatic DGAFunctionRec VESADGAFunctions = 182545bc899bSmrg{ 182645bc899bSmrg VESADGAOpenFramebuffer, 182745bc899bSmrg NULL, /* CloseFramebuffer */ 182845bc899bSmrg VESADGASetMode, 182945bc899bSmrg VESADGASetViewport, 183045bc899bSmrg VESADGAGetViewport, 183145bc899bSmrg NULL, /* Sync */ 183245bc899bSmrg NULL, /* FillRect */ 183345bc899bSmrg NULL, /* BlitRect */ 183445bc899bSmrg NULL, /* BlitTransRect */ 183545bc899bSmrg}; 183645bc899bSmrg 183745bc899bSmrgstatic void 183845bc899bSmrgVESADGAAddModes(ScrnInfoPtr pScrn) 183945bc899bSmrg{ 184045bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 184145bc899bSmrg DisplayModePtr pMode = pScrn->modes; 184245bc899bSmrg DGAModePtr pDGAMode; 184345bc899bSmrg 184445bc899bSmrg do { 1845b40a6198Smrg pDGAMode = realloc(pVesa->pDGAMode, 184645bc899bSmrg (pVesa->nDGAMode + 1) * sizeof(DGAModeRec)); 184745bc899bSmrg if (!pDGAMode) 184845bc899bSmrg break; 184945bc899bSmrg 185045bc899bSmrg pVesa->pDGAMode = pDGAMode; 185145bc899bSmrg pDGAMode += pVesa->nDGAMode; 185245bc899bSmrg (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 185345bc899bSmrg 185445bc899bSmrg ++pVesa->nDGAMode; 185545bc899bSmrg pDGAMode->mode = pMode; 185645bc899bSmrg pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 185745bc899bSmrg pDGAMode->byteOrder = pScrn->imageByteOrder; 185845bc899bSmrg pDGAMode->depth = pScrn->depth; 185945bc899bSmrg pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 186045bc899bSmrg pDGAMode->red_mask = pScrn->mask.red; 186145bc899bSmrg pDGAMode->green_mask = pScrn->mask.green; 186245bc899bSmrg pDGAMode->blue_mask = pScrn->mask.blue; 186345bc899bSmrg pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 186445bc899bSmrg TrueColor : PseudoColor; 186545bc899bSmrg pDGAMode->xViewportStep = 1; 186645bc899bSmrg pDGAMode->yViewportStep = 1; 186745bc899bSmrg pDGAMode->viewportWidth = pMode->HDisplay; 186845bc899bSmrg pDGAMode->viewportHeight = pMode->VDisplay; 186945bc899bSmrg 187045bc899bSmrg pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline; 187145bc899bSmrg pDGAMode->imageWidth = pMode->HDisplay; 187245bc899bSmrg pDGAMode->imageHeight = pMode->VDisplay; 187345bc899bSmrg pDGAMode->pixmapWidth = pDGAMode->imageWidth; 187445bc899bSmrg pDGAMode->pixmapHeight = pDGAMode->imageHeight; 187545bc899bSmrg pDGAMode->maxViewportX = pScrn->virtualX - 187645bc899bSmrg pDGAMode->viewportWidth; 187745bc899bSmrg pDGAMode->maxViewportY = pScrn->virtualY - 187845bc899bSmrg pDGAMode->viewportHeight; 187945bc899bSmrg 188045bc899bSmrg pDGAMode->address = pVesa->base; 188145bc899bSmrg 188245bc899bSmrg pMode = pMode->next; 188345bc899bSmrg } while (pMode != pScrn->modes); 188445bc899bSmrg} 188545bc899bSmrg 188645bc899bSmrgstatic Bool 188745bc899bSmrgVESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 188845bc899bSmrg{ 188945bc899bSmrg VESAPtr pVesa = VESAGetRec(pScrn); 189045bc899bSmrg 189145bc899bSmrg if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L) 189245bc899bSmrg return (FALSE); 189345bc899bSmrg 189445bc899bSmrg if (!pVesa->nDGAMode) 189545bc899bSmrg VESADGAAddModes(pScrn); 189645bc899bSmrg 189745bc899bSmrg return (DGAInit(pScreen, &VESADGAFunctions, 189845bc899bSmrg pVesa->pDGAMode, pVesa->nDGAMode)); 189945bc899bSmrg} 1900