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