vesa.c revision 50f2e948
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 * - PanelID might give us useful size hints.
3750f2e948Smrg * - Port to RANDR 1.2 setup to make mode selection slightly better
3850f2e948Smrg * - Port to RANDR 1.2 to drop the old-school DGA junk
3950f2e948Smrg * - VBE/SCI for secondary DDC method?
4045bc899bSmrg */
4145bc899bSmrg
4245bc899bSmrg#ifdef HAVE_CONFIG_H
4345bc899bSmrg#include "config.h"
4445bc899bSmrg#endif
4545bc899bSmrg
4645bc899bSmrg#include <string.h>
4745bc899bSmrg
4845bc899bSmrg#include "vesa.h"
4945bc899bSmrg
5045bc899bSmrg/* All drivers initialising the SW cursor need this */
5145bc899bSmrg#include "mipointer.h"
5245bc899bSmrg
5345bc899bSmrg/* All drivers implementing backing store need this */
5445bc899bSmrg#include "mibstore.h"
5545bc899bSmrg
5645bc899bSmrg/* Colormap handling */
5745bc899bSmrg#include "micmap.h"
5845bc899bSmrg#include "xf86cmap.h"
5950f2e948Smrg#include "xf86Modes.h"
6045bc899bSmrg
6145bc899bSmrg/* DPMS */
6245bc899bSmrg#define DPMS_SERVER
6345bc899bSmrg#include <X11/extensions/dpms.h>
6445bc899bSmrg
6545bc899bSmrg/* Mandatory functions */
6645bc899bSmrgstatic const OptionInfoRec * VESAAvailableOptions(int chipid, int busid);
6745bc899bSmrgstatic void VESAIdentify(int flags);
6845bc899bSmrgstatic Bool VESAProbe(DriverPtr drv, int flags);
6950f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
7050f2e948Smrgstatic Bool VESAPciProbe(DriverPtr drv, int entity_num,
7150f2e948Smrg     struct pci_device *dev, intptr_t match_data);
7250f2e948Smrg#endif
7345bc899bSmrgstatic Bool VESAPreInit(ScrnInfoPtr pScrn, int flags);
7445bc899bSmrgstatic Bool VESAScreenInit(int Index, ScreenPtr pScreen, int argc,
7545bc899bSmrg			   char **argv);
7645bc899bSmrgstatic Bool VESAEnterVT(int scrnIndex, int flags);
7745bc899bSmrgstatic void VESALeaveVT(int scrnIndex, int flags);
7845bc899bSmrgstatic Bool VESACloseScreen(int scrnIndex, ScreenPtr pScreen);
7945bc899bSmrgstatic Bool VESASaveScreen(ScreenPtr pScreen, int mode);
8045bc899bSmrg
8145bc899bSmrgstatic Bool VESASwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
8245bc899bSmrgstatic Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
8345bc899bSmrgstatic void VESAAdjustFrame(int scrnIndex, int x, int y, int flags);
8445bc899bSmrgstatic void VESAFreeScreen(int scrnIndex, int flags);
8545bc899bSmrgstatic void VESAFreeRec(ScrnInfoPtr pScrn);
8650f2e948Smrgstatic VESAPtr VESAGetRec(ScrnInfoPtr pScrn);
8745bc899bSmrg
8845bc899bSmrgstatic void
8945bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
9045bc899bSmrg                int flags);
9145bc899bSmrg
9245bc899bSmrg/* locally used functions */
9345bc899bSmrgstatic int VESAFindIsaDevice(GDevPtr dev);
9445bc899bSmrgstatic Bool VESAMapVidMem(ScrnInfoPtr pScrn);
9545bc899bSmrgstatic void VESAUnmapVidMem(ScrnInfoPtr pScrn);
9645bc899bSmrgstatic int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank);
9745bc899bSmrgstatic void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
9845bc899bSmrg			    LOCO *colors, VisualPtr pVisual);
9945bc899bSmrgstatic void SaveFonts(ScrnInfoPtr pScrn);
10045bc899bSmrgstatic void RestoreFonts(ScrnInfoPtr pScrn);
10145bc899bSmrgstatic Bool
10245bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function);
10345bc899bSmrg
10445bc899bSmrgstatic void *VESAWindowLinear(ScreenPtr pScrn, CARD32 row, CARD32 offset,
10545bc899bSmrg			      int mode, CARD32 *size, void *closure);
10645bc899bSmrgstatic void *VESAWindowWindowed(ScreenPtr pScrn, CARD32 row, CARD32 offset,
10745bc899bSmrg				int mode, CARD32 *size, void *closure);
10845bc899bSmrg
10945bc899bSmrgstatic Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
11045bc899bSmrg
11145bc899bSmrgenum GenericTypes
11245bc899bSmrg{
11345bc899bSmrg    CHIP_VESA_GENERIC
11445bc899bSmrg};
11545bc899bSmrg
11650f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
11750f2e948Smrgstatic const struct pci_id_match vesa_device_match[] = {
11850f2e948Smrg    {
11950f2e948Smrg	PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
12050f2e948Smrg	0x00030000, 0x00ffffff, CHIP_VESA_GENERIC
12150f2e948Smrg    },
12250f2e948Smrg
12350f2e948Smrg    { 0, 0, 0 },
12450f2e948Smrg};
12550f2e948Smrg#endif
12650f2e948Smrg
12745bc899bSmrg/* Supported chipsets */
12845bc899bSmrgstatic SymTabRec VESAChipsets[] =
12945bc899bSmrg{
13045bc899bSmrg    {CHIP_VESA_GENERIC, "vesa"},
13145bc899bSmrg    {-1,		 NULL}
13245bc899bSmrg};
13345bc899bSmrg
13450f2e948Smrg#ifndef XSERVER_LIBPCIACCESS
13545bc899bSmrgstatic PciChipsets VESAPCIchipsets[] = {
13645bc899bSmrg  { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA },
13745bc899bSmrg  { -1,		-1,	   RES_UNDEFINED },
13845bc899bSmrg};
13950f2e948Smrg#endif
14045bc899bSmrg
14150f2e948Smrg#ifdef HAVE_ISA
14245bc899bSmrgstatic IsaChipsets VESAISAchipsets[] = {
14345bc899bSmrg  {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA},
14445bc899bSmrg  {-1,		0 }
14545bc899bSmrg};
14650f2e948Smrg#endif
14750f2e948Smrg
14850f2e948Smrg
14950f2e948Smrg/*
15050f2e948Smrg * This contains the functions needed by the server after loading the
15150f2e948Smrg * driver module.  It must be supplied, and gets added the driver list by
15250f2e948Smrg * the Module Setup funtion in the dynamic case.  In the static case a
15350f2e948Smrg * reference to this is compiled in, and this requires that the name of
15450f2e948Smrg * this DriverRec be an upper-case version of the driver name.
15550f2e948Smrg */
15650f2e948Smrg_X_EXPORT DriverRec VESA = {
15750f2e948Smrg    VESA_VERSION,
15850f2e948Smrg    VESA_DRIVER_NAME,
15950f2e948Smrg    VESAIdentify,
16050f2e948Smrg    VESAProbe,
16150f2e948Smrg    VESAAvailableOptions,
16250f2e948Smrg    NULL,
16350f2e948Smrg    0,
16450f2e948Smrg    NULL,
16550f2e948Smrg
16650f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
16750f2e948Smrg    vesa_device_match,
16850f2e948Smrg    VESAPciProbe
16950f2e948Smrg#endif
17050f2e948Smrg};
17150f2e948Smrg
17245bc899bSmrg
17345bc899bSmrgtypedef enum {
17445bc899bSmrg    OPTION_SHADOW_FB,
17545bc899bSmrg    OPTION_DFLT_REFRESH,
17645bc899bSmrg    OPTION_MODESET_CLEAR_SCREEN
17745bc899bSmrg} VESAOpts;
17845bc899bSmrg
17945bc899bSmrgstatic const OptionInfoRec VESAOptions[] = {
18045bc899bSmrg    { OPTION_SHADOW_FB,    "ShadowFB",		OPTV_BOOLEAN,	{0},	FALSE },
18145bc899bSmrg    { OPTION_DFLT_REFRESH, "DefaultRefresh",	OPTV_BOOLEAN,	{0},	FALSE },
18245bc899bSmrg    { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen",
18345bc899bSmrg						OPTV_BOOLEAN,	{0},	FALSE },
18445bc899bSmrg    { -1,		   NULL,		OPTV_NONE,	{0},	FALSE }
18545bc899bSmrg};
18645bc899bSmrg
18745bc899bSmrg#ifdef XFree86LOADER
18845bc899bSmrg
18945bc899bSmrg/* Module loader interface */
19045bc899bSmrgstatic MODULESETUPPROTO(vesaSetup);
19145bc899bSmrg
19245bc899bSmrgstatic XF86ModuleVersionInfo vesaVersionRec =
19345bc899bSmrg{
19445bc899bSmrg    VESA_DRIVER_NAME,
19545bc899bSmrg    MODULEVENDORSTRING,
19645bc899bSmrg    MODINFOSTRING1,
19745bc899bSmrg    MODINFOSTRING2,
19845bc899bSmrg    XORG_VERSION_CURRENT,
19945bc899bSmrg    VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL,
20045bc899bSmrg    ABI_CLASS_VIDEODRV,			/* This is a video driver */
20145bc899bSmrg    ABI_VIDEODRV_VERSION,
20245bc899bSmrg    MOD_CLASS_VIDEODRV,
20345bc899bSmrg    {0, 0, 0, 0}
20445bc899bSmrg};
20545bc899bSmrg
20645bc899bSmrg/*
20745bc899bSmrg * This data is accessed by the loader.  The name must be the module name
20845bc899bSmrg * followed by "ModuleData".
20945bc899bSmrg */
21045bc899bSmrg_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL };
21145bc899bSmrg
21245bc899bSmrgstatic pointer
21345bc899bSmrgvesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
21445bc899bSmrg{
21545bc899bSmrg    static Bool Initialised = FALSE;
21645bc899bSmrg
21745bc899bSmrg    if (!Initialised)
21845bc899bSmrg    {
21945bc899bSmrg	Initialised = TRUE;
22050f2e948Smrg	xf86AddDriver(&VESA, Module, 1);
22145bc899bSmrg	return (pointer)TRUE;
22245bc899bSmrg    }
22345bc899bSmrg
22445bc899bSmrg    if (ErrorMajor)
22545bc899bSmrg	*ErrorMajor = LDR_ONCEONLY;
22645bc899bSmrg    return (NULL);
22745bc899bSmrg}
22845bc899bSmrg
22945bc899bSmrg#endif
23045bc899bSmrg
23145bc899bSmrgstatic const OptionInfoRec *
23245bc899bSmrgVESAAvailableOptions(int chipid, int busid)
23345bc899bSmrg{
23445bc899bSmrg    return (VESAOptions);
23545bc899bSmrg}
23645bc899bSmrg
23745bc899bSmrgstatic void
23845bc899bSmrgVESAIdentify(int flags)
23945bc899bSmrg{
24045bc899bSmrg    xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
24145bc899bSmrg}
24245bc899bSmrg
24350f2e948Smrgstatic VESAPtr
24450f2e948SmrgVESAGetRec(ScrnInfoPtr pScrn)
24550f2e948Smrg{
24650f2e948Smrg    if (!pScrn->driverPrivate)
24750f2e948Smrg	pScrn->driverPrivate = xcalloc(sizeof(VESARec), 1);
24850f2e948Smrg
24950f2e948Smrg    return ((VESAPtr)pScrn->driverPrivate);
25050f2e948Smrg}
25150f2e948Smrg
25250f2e948Smrg/* Only a little like VBESetModeParameters */
25350f2e948Smrgstatic void
25450f2e948SmrgVESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode,
25550f2e948Smrg		      DisplayModePtr ddcmode)
25650f2e948Smrg{
25750f2e948Smrg    VbeModeInfoData *data;
25850f2e948Smrg    int clock;
25950f2e948Smrg
26050f2e948Smrg    data = (VbeModeInfoData *)vbemode->Private;
26150f2e948Smrg
26250f2e948Smrg    data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
26350f2e948Smrg    data->block->HorizontalTotal = ddcmode->HTotal;
26450f2e948Smrg    data->block->HorizontalSyncStart = ddcmode->HSyncStart;
26550f2e948Smrg    data->block->HorizontalSyncEnd = ddcmode->HSyncEnd;
26650f2e948Smrg    data->block->VerticalTotal = ddcmode->VTotal;
26750f2e948Smrg    data->block->VerticalSyncStart = ddcmode->VSyncStart;
26850f2e948Smrg    data->block->VerticalSyncEnd = ddcmode->VSyncEnd;
26950f2e948Smrg    data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
27050f2e948Smrg	                 ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
27150f2e948Smrg    data->block->PixelClock = ddcmode->Clock * 1000;
27250f2e948Smrg
27350f2e948Smrg    /* ask the BIOS to figure out the real clock */
27450f2e948Smrg    clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
27550f2e948Smrg    if (clock)
27650f2e948Smrg	data->block->PixelClock = clock;
27750f2e948Smrg
27850f2e948Smrg    data->mode |= (1 << 11);
27950f2e948Smrg    data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) /
28050f2e948Smrg				(double)(ddcmode->HTotal * ddcmode->VTotal));
28150f2e948Smrg}
28250f2e948Smrg
28350f2e948Smrgstatic ModeStatus
28450f2e948SmrgVESAValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
28550f2e948Smrg{
28650f2e948Smrg    static int warned = 0;
28750f2e948Smrg    int found = 0;
28850f2e948Smrg    ScrnInfoPtr pScrn = xf86Screens[scrn];
28950f2e948Smrg    VESAPtr pVesa = VESAGetRec(pScrn);
29050f2e948Smrg    MonPtr mon = pScrn->monitor;
29150f2e948Smrg    ModeStatus ret = MODE_BAD;
29250f2e948Smrg    DisplayModePtr mode;
29350f2e948Smrg    float v;
29450f2e948Smrg
29550f2e948Smrg    pVesa = VESAGetRec(pScrn);
29650f2e948Smrg
29750f2e948Smrg    if (pass != MODECHECK_FINAL) {
29850f2e948Smrg	if (!warned) {
29950f2e948Smrg	    xf86DrvMsg(scrn, X_WARNING, "VESAValidMode called unexpectedly\n");
30050f2e948Smrg	    warned = 1;
30150f2e948Smrg	}
30250f2e948Smrg	return MODE_OK;
30350f2e948Smrg    }
30450f2e948Smrg
30550f2e948Smrg    /*
30650f2e948Smrg     * This is suboptimal.  We pass in just the barest description of a mode
30750f2e948Smrg     * we can get away with to VBEValidateModes, so it can't really throw
30850f2e948Smrg     * out anything we give it.  But we need to filter the list so that we
30950f2e948Smrg     * don't populate the mode list with things the monitor can't do.
31050f2e948Smrg     *
31150f2e948Smrg     * So first off, if this isn't a mode we handed to the server (ie,
31250f2e948Smrg     * M_T_BUILTIN), then we know we can't do it.
31350f2e948Smrg     */
31450f2e948Smrg    if (!(p->type & M_T_BUILTIN))
31550f2e948Smrg	return MODE_NOMODE;
31650f2e948Smrg
31750f2e948Smrg    if (pVesa->strict_validation) {
31850f2e948Smrg	/*
31950f2e948Smrg	 * If it's our first pass at mode validation, we'll try for a strict
32050f2e948Smrg	 * intersection between the VBE and DDC mode lists.
32150f2e948Smrg	 */
32250f2e948Smrg	if (pScrn->monitor->DDC) {
32350f2e948Smrg	    for (mode = pScrn->monitor->Modes; mode; mode = mode->next) {
32450f2e948Smrg		if (mode->type & M_T_DRIVER &&
32550f2e948Smrg			mode->HDisplay == p->HDisplay &&
32650f2e948Smrg			mode->VDisplay == p->VDisplay) {
32750f2e948Smrg		    if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) {
32850f2e948Smrg			found = 1;
32950f2e948Smrg			break;
33050f2e948Smrg		    }
33150f2e948Smrg		}
33250f2e948Smrg		if (mode == pScrn->monitor->Last)
33350f2e948Smrg		    break;
33450f2e948Smrg	    }
33550f2e948Smrg	    if (!found)
33650f2e948Smrg		return MODE_NOMODE;
33750f2e948Smrg
33850f2e948Smrg	    /* having found a matching mode, stash the CRTC values aside */
33950f2e948Smrg	    VESASetModeParameters(pVesa->pVbe, p, mode);
34050f2e948Smrg	    return MODE_OK;
34150f2e948Smrg	}
34250f2e948Smrg
34350f2e948Smrg	/* No DDC and no modes make Homer something something... */
34450f2e948Smrg	return MODE_NOMODE;
34550f2e948Smrg    }
34650f2e948Smrg
34750f2e948Smrg    /*
34850f2e948Smrg     * Finally, walk through the vsync rates 1Hz at a time looking for a mode
34950f2e948Smrg     * that will fit.  This is assuredly a terrible way to do this, but
35050f2e948Smrg     * there's no obvious method for computing a mode of a given size that
35150f2e948Smrg     * will pass xf86CheckModeForMonitor.  XXX this path is terrible, but
35250f2e948Smrg     * then, by this point, you're well into despair territory.
35350f2e948Smrg     */
35450f2e948Smrg    for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
35550f2e948Smrg	mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0);
35650f2e948Smrg	ret = xf86CheckModeForMonitor(mode, mon);
35750f2e948Smrg	xfree(mode);
35850f2e948Smrg	if (ret == MODE_OK)
35950f2e948Smrg	    break;
36050f2e948Smrg    }
36150f2e948Smrg
36250f2e948Smrg    return ret;
36350f2e948Smrg}
36450f2e948Smrg
36550f2e948Smrgstatic void
36650f2e948SmrgVESAInitScrn(ScrnInfoPtr pScrn)
36750f2e948Smrg{
36850f2e948Smrg    pScrn->driverVersion = VESA_VERSION;
36950f2e948Smrg    pScrn->driverName    = VESA_DRIVER_NAME;
37050f2e948Smrg    pScrn->name		 = VESA_NAME;
37150f2e948Smrg    pScrn->Probe	 = VESAProbe;
37250f2e948Smrg    pScrn->PreInit       = VESAPreInit;
37350f2e948Smrg    pScrn->ScreenInit    = VESAScreenInit;
37450f2e948Smrg    pScrn->SwitchMode    = VESASwitchMode;
37550f2e948Smrg    pScrn->ValidMode     = VESAValidMode;
37650f2e948Smrg    pScrn->AdjustFrame   = VESAAdjustFrame;
37750f2e948Smrg    pScrn->EnterVT       = VESAEnterVT;
37850f2e948Smrg    pScrn->LeaveVT       = VESALeaveVT;
37950f2e948Smrg    pScrn->FreeScreen    = VESAFreeScreen;
38050f2e948Smrg}
38150f2e948Smrg
38245bc899bSmrg/*
38345bc899bSmrg * This function is called once, at the start of the first server generation to
38445bc899bSmrg * do a minimal probe for supported hardware.
38545bc899bSmrg */
38645bc899bSmrg
38750f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
38850f2e948Smrgstatic Bool
38950f2e948SmrgVESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
39050f2e948Smrg	     intptr_t match_data)
39150f2e948Smrg{
39250f2e948Smrg    ScrnInfoPtr pScrn;
39350f2e948Smrg
39450f2e948Smrg    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL,
39550f2e948Smrg				NULL, NULL, NULL, NULL, NULL);
39650f2e948Smrg    if (pScrn != NULL) {
39750f2e948Smrg	VESAPtr pVesa = VESAGetRec(pScrn);
39850f2e948Smrg
39950f2e948Smrg	VESAInitScrn(pScrn);
40050f2e948Smrg	pVesa->pciInfo = dev;
40150f2e948Smrg    }
40250f2e948Smrg
40350f2e948Smrg    return (pScrn != NULL);
40450f2e948Smrg}
40550f2e948Smrg#endif
40650f2e948Smrg
40745bc899bSmrgstatic Bool
40845bc899bSmrgVESAProbe(DriverPtr drv, int flags)
40945bc899bSmrg{
41045bc899bSmrg    Bool foundScreen = FALSE;
41145bc899bSmrg    int numDevSections, numUsed;
41245bc899bSmrg    GDevPtr *devSections;
41345bc899bSmrg    int *usedChips;
41445bc899bSmrg    int i;
41545bc899bSmrg
41645bc899bSmrg    /*
41745bc899bSmrg     * Find the config file Device sections that match this
41845bc899bSmrg     * driver, and return if there are none.
41945bc899bSmrg     */
42045bc899bSmrg    if ((numDevSections = xf86MatchDevice(VESA_NAME,
42145bc899bSmrg					  &devSections)) <= 0)
42245bc899bSmrg	return (FALSE);
42345bc899bSmrg
42450f2e948Smrg#ifndef XSERVER_LIBPCIACCESS
42545bc899bSmrg    /* PCI BUS */
42645bc899bSmrg    if (xf86GetPciVideoInfo()) {
42745bc899bSmrg	numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC,
42845bc899bSmrg					VESAChipsets, VESAPCIchipsets,
42945bc899bSmrg					devSections, numDevSections,
43045bc899bSmrg					drv, &usedChips);
43145bc899bSmrg	if (numUsed > 0) {
43245bc899bSmrg	    if (flags & PROBE_DETECT)
43345bc899bSmrg		foundScreen = TRUE;
43445bc899bSmrg	    else {
43545bc899bSmrg		for (i = 0; i < numUsed; i++) {
43645bc899bSmrg		    ScrnInfoPtr pScrn = NULL;
43745bc899bSmrg		    /* Allocate a ScrnInfoRec  */
43845bc899bSmrg		    if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
43945bc899bSmrg						     VESAPCIchipsets,NULL,
44045bc899bSmrg						     NULL,NULL,NULL,NULL))) {
44150f2e948Smrg			VESAInitScrn(pScrn);
44245bc899bSmrg			foundScreen = TRUE;
44345bc899bSmrg		    }
44445bc899bSmrg		}
44545bc899bSmrg	    }
44645bc899bSmrg	    xfree(usedChips);
44745bc899bSmrg	}
44845bc899bSmrg    }
44950f2e948Smrg#endif
45045bc899bSmrg
45150f2e948Smrg#ifdef HAVE_ISA
45245bc899bSmrg    /* Isa Bus */
45345bc899bSmrg    numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets,
45445bc899bSmrg				    VESAISAchipsets, drv,
45545bc899bSmrg				    VESAFindIsaDevice, devSections,
45645bc899bSmrg				    numDevSections, &usedChips);
45745bc899bSmrg    if(numUsed > 0) {
45845bc899bSmrg	if (flags & PROBE_DETECT)
45945bc899bSmrg	    foundScreen = TRUE;
46045bc899bSmrg	else for (i = 0; i < numUsed; i++) {
46145bc899bSmrg	    ScrnInfoPtr pScrn = NULL;
46245bc899bSmrg	    if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i],
46345bc899bSmrg					     VESAISAchipsets, NULL,
46445bc899bSmrg					     NULL, NULL, NULL, NULL))) {
46550f2e948Smrg		VESAInitScrn(pScrn);
46645bc899bSmrg		foundScreen = TRUE;
46745bc899bSmrg	    }
46845bc899bSmrg	}
46945bc899bSmrg	xfree(usedChips);
47045bc899bSmrg    }
47150f2e948Smrg#endif
47245bc899bSmrg
47345bc899bSmrg    xfree(devSections);
47445bc899bSmrg
47545bc899bSmrg    return (foundScreen);
47645bc899bSmrg}
47745bc899bSmrg
47850f2e948Smrg#ifdef HAVE_ISA
47945bc899bSmrgstatic int
48045bc899bSmrgVESAFindIsaDevice(GDevPtr dev)
48145bc899bSmrg{
48245bc899bSmrg#ifndef PC98_EGC
48345bc899bSmrg    CARD16 GenericIOBase = VGAHW_GET_IOBASE();
48445bc899bSmrg    CARD8 CurrentValue, TestValue;
48545bc899bSmrg
48645bc899bSmrg    /* There's no need to unlock VGA CRTC registers here */
48745bc899bSmrg
48845bc899bSmrg    /* VGA has one more read/write attribute register than EGA */
48945bc899bSmrg    (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET);  /* Reset flip-flop */
49045bc899bSmrg    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
49145bc899bSmrg    CurrentValue = inb(VGA_ATTR_DATA_R);
49245bc899bSmrg    outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
49345bc899bSmrg    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
49445bc899bSmrg    TestValue = inb(VGA_ATTR_DATA_R);
49545bc899bSmrg    outb(VGA_ATTR_DATA_R, CurrentValue);
49645bc899bSmrg
49745bc899bSmrg    /* Quit now if no VGA is present */
49845bc899bSmrg    if ((CurrentValue ^ 0x0F) != TestValue)
49945bc899bSmrg      return -1;
50045bc899bSmrg#endif
50145bc899bSmrg    return (int)CHIP_VESA_GENERIC;
50245bc899bSmrg}
50350f2e948Smrg#endif
50445bc899bSmrg
50545bc899bSmrgstatic void
50645bc899bSmrgVESAFreeRec(ScrnInfoPtr pScrn)
50745bc899bSmrg{
50845bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
50945bc899bSmrg#if 0
51045bc899bSmrg    DisplayModePtr mode = pScrn->modes;
51145bc899bSmrg    /* I am not sure if the modes will ever get freed.
51245bc899bSmrg     * Anyway, the data unknown to other modules is being freed here.
51345bc899bSmrg     */
51445bc899bSmrg    if (mode) {
51545bc899bSmrg	do {
51645bc899bSmrg	    if (mode->Private) {
51745bc899bSmrg		VbeModeInfoData *data = (VbeModeInfoData*)mode->Private;
51845bc899bSmrg
51945bc899bSmrg		if (data->block)
52045bc899bSmrg		    xfree(data->block);
52145bc899bSmrg
52245bc899bSmrg		xfree(data);
52345bc899bSmrg
52445bc899bSmrg		mode->Private = NULL;
52545bc899bSmrg	    }
52645bc899bSmrg	    mode = mode->next;
52745bc899bSmrg	} while (mode && mode != pScrn->modes);
52845bc899bSmrg    }
52945bc899bSmrg#endif
53045bc899bSmrg    xfree(pVesa->monitor);
53145bc899bSmrg    xfree(pVesa->vbeInfo);
53245bc899bSmrg    xfree(pVesa->pal);
53345bc899bSmrg    xfree(pVesa->savedPal);
53445bc899bSmrg    xfree(pVesa->fonts);
53545bc899bSmrg    xfree(pScrn->driverPrivate);
53645bc899bSmrg    pScrn->driverPrivate = NULL;
53745bc899bSmrg}
53845bc899bSmrg
53950f2e948Smrgstatic int
54050f2e948SmrgVESAValidateModes(ScrnInfoPtr pScrn)
54150f2e948Smrg{
54250f2e948Smrg    VESAPtr pVesa = VESAGetRec(pScrn);
54350f2e948Smrg    DisplayModePtr mode;
54450f2e948Smrg
54550f2e948Smrg    for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
54650f2e948Smrg	mode->status = MODE_OK;
54750f2e948Smrg
54850f2e948Smrg    return VBEValidateModes(pScrn, NULL, pScrn->display->modes,
54950f2e948Smrg			    NULL, NULL, 0, 2048, 1, 0, 2048,
55050f2e948Smrg			    pScrn->display->virtualX,
55150f2e948Smrg			    pScrn->display->virtualY,
55250f2e948Smrg			    pVesa->mapSize, LOOKUP_BEST_REFRESH);
55350f2e948Smrg}
55450f2e948Smrg
55545bc899bSmrg/*
55645bc899bSmrg * This function is called once for each screen at the start of the first
55745bc899bSmrg * server generation to initialise the screen for all server generations.
55845bc899bSmrg */
55945bc899bSmrgstatic Bool
56045bc899bSmrgVESAPreInit(ScrnInfoPtr pScrn, int flags)
56145bc899bSmrg{
56245bc899bSmrg    VESAPtr pVesa;
56345bc899bSmrg    VbeInfoBlock *vbe;
56445bc899bSmrg    DisplayModePtr pMode;
56545bc899bSmrg    VbeModeInfoBlock *mode;
56645bc899bSmrg    Gamma gzeros = {0.0, 0.0, 0.0};
56745bc899bSmrg    rgb rzeros = {0, 0, 0};
56845bc899bSmrg    pointer pDDCModule;
56945bc899bSmrg    int i;
57045bc899bSmrg    int flags24 = 0;
57145bc899bSmrg    int defaultDepth = 0;
57250f2e948Smrg    int defaultBpp = 0;
57345bc899bSmrg    int depths = 0;
57445bc899bSmrg
57545bc899bSmrg    if (flags & PROBE_DETECT)
57645bc899bSmrg	return (FALSE);
57745bc899bSmrg
57845bc899bSmrg    pVesa = VESAGetRec(pScrn);
57945bc899bSmrg    pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
58045bc899bSmrg
58145bc899bSmrg    /* Load vbe module */
58245bc899bSmrg    if (!xf86LoadSubModule(pScrn, "vbe"))
58345bc899bSmrg        return (FALSE);
58445bc899bSmrg
58545bc899bSmrg    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
58645bc899bSmrg				       SET_BIOS_SCRATCH
58745bc899bSmrg				       | RESTORE_BIOS_SCRATCH)) == NULL)
58845bc899bSmrg        return (FALSE);
58945bc899bSmrg
59050f2e948Smrg#ifndef XSERVER_LIBPCIACCESS
59145bc899bSmrg    if (pVesa->pEnt->location.type == BUS_PCI) {
59245bc899bSmrg	pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index);
59345bc899bSmrg	pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device,
59445bc899bSmrg			       pVesa->pciInfo->func);
59545bc899bSmrg    }
59650f2e948Smrg#endif
59745bc899bSmrg
59845bc899bSmrg    pScrn->chipset = "vesa";
59945bc899bSmrg    pScrn->monitor = pScrn->confScreen->monitor;
60045bc899bSmrg    pScrn->progClock = TRUE;
60145bc899bSmrg    pScrn->rgbBits = 8;
60245bc899bSmrg
60345bc899bSmrg    if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL)
60445bc899bSmrg	return (FALSE);
60545bc899bSmrg    pVesa->major = (unsigned)(vbe->VESAVersion >> 8);
60645bc899bSmrg    pVesa->minor = vbe->VESAVersion & 0xff;
60745bc899bSmrg    pVesa->vbeInfo = vbe;
60845bc899bSmrg    pScrn->videoRam = vbe->TotalMemory * 64;
60945bc899bSmrg
61045bc899bSmrg    /*
61145bc899bSmrg     * Find what depths are available.
61245bc899bSmrg     */
61345bc899bSmrg    depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24,
61445bc899bSmrg				    V_MODETYPE_VBE);
61545bc899bSmrg
61645bc899bSmrg    /* Preferred order for default depth selection. */
61750f2e948Smrg    if (depths & V_DEPTH_24)
61850f2e948Smrg	defaultDepth = 24;
61950f2e948Smrg    else if (depths & V_DEPTH_16)
62045bc899bSmrg	defaultDepth = 16;
62145bc899bSmrg    else if (depths & V_DEPTH_15)
62245bc899bSmrg	defaultDepth = 15;
62345bc899bSmrg    else if (depths & V_DEPTH_8)
62445bc899bSmrg	defaultDepth = 8;
62545bc899bSmrg    else if (depths & V_DEPTH_4)
62645bc899bSmrg	defaultDepth = 4;
62745bc899bSmrg    else if (depths & V_DEPTH_1)
62845bc899bSmrg	defaultDepth = 1;
62945bc899bSmrg
63050f2e948Smrg    if (defaultDepth == 24 && !(flags24 & Support32bppFb))
63150f2e948Smrg	defaultBpp = 24;
63245bc899bSmrg
63350f2e948Smrg    /* Prefer 32bpp because 1999 called and wants its packed pixels back */
63450f2e948Smrg    if (flags24 & Support32bppFb)
63550f2e948Smrg	flags24 |= SupportConvert24to32 | PreferConvert24to32;
63645bc899bSmrg    if (flags24 & Support24bppFb)
63750f2e948Smrg	flags24 |= SupportConvert32to24;
63845bc899bSmrg
63950f2e948Smrg    if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) {
64045bc899bSmrg        vbeFree(pVesa->pVbe);
64145bc899bSmrg	return (FALSE);
64245bc899bSmrg    }
64345bc899bSmrg    xf86PrintDepthBpp(pScrn);
64445bc899bSmrg
64545bc899bSmrg    /* color weight */
64645bc899bSmrg    if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) {
64745bc899bSmrg        vbeFree(pVesa->pVbe);
64845bc899bSmrg	return (FALSE);
64945bc899bSmrg    }
65045bc899bSmrg    /* visual init */
65145bc899bSmrg    if (!xf86SetDefaultVisual(pScrn, -1)) {
65245bc899bSmrg        vbeFree(pVesa->pVbe);
65345bc899bSmrg	return (FALSE);
65445bc899bSmrg    }
65545bc899bSmrg
65645bc899bSmrg    xf86SetGamma(pScrn, gzeros);
65745bc899bSmrg
65845bc899bSmrg    if (pVesa->major >= 2) {
65945bc899bSmrg	/* Load ddc module */
66045bc899bSmrg	if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
66145bc899bSmrg	    vbeFree(pVesa->pVbe);
66245bc899bSmrg	    return (FALSE);
66345bc899bSmrg	}
66445bc899bSmrg
66545bc899bSmrg	if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) {
66645bc899bSmrg	    xf86PrintEDID(pVesa->monitor);
66745bc899bSmrg	}
66845bc899bSmrg
66945bc899bSmrg	xf86UnloadSubModule(pDDCModule);
67045bc899bSmrg    }
67145bc899bSmrg
67245bc899bSmrg    if ((pScrn->monitor->DDC = pVesa->monitor) != NULL)
67345bc899bSmrg	xf86SetDDCproperties(pScrn, pVesa->monitor);
67445bc899bSmrg
67545bc899bSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
67645bc899bSmrg			"Searching for matching VESA mode(s):\n");
67745bc899bSmrg
67845bc899bSmrg    /*
67945bc899bSmrg     * Check the available BIOS modes, and extract those that match the
68045bc899bSmrg     * requirements into the modePool.  Note: modePool is a NULL-terminated
68145bc899bSmrg     * list.
68245bc899bSmrg     */
68345bc899bSmrg    pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo,
68445bc899bSmrg				      V_MODETYPE_VBE);
68545bc899bSmrg
68645bc899bSmrg    xf86ErrorFVerb(DEBUG_VERB, "\n");
68745bc899bSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
68845bc899bSmrg		   "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory,
68945bc899bSmrg		   (vbe->TotalMemory * 65536) / 1024);
69045bc899bSmrg
69145bc899bSmrg    pVesa->mapSize = vbe->TotalMemory * 65536;
69245bc899bSmrg    if (pScrn->modePool == NULL) {
69345bc899bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n");
69445bc899bSmrg        vbeFree(pVesa->pVbe);
69545bc899bSmrg	return (FALSE);
69645bc899bSmrg    }
69745bc899bSmrg
69845bc899bSmrg    VBESetModeNames(pScrn->modePool);
69945bc899bSmrg
70050f2e948Smrg    pVesa->strict_validation = TRUE;
70150f2e948Smrg    i = VESAValidateModes(pScrn);
70250f2e948Smrg
70350f2e948Smrg    if (i <= 0) {
70450f2e948Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
70550f2e948Smrg		"No valid modes left. Trying less strict filter...\n");
70650f2e948Smrg	pVesa->strict_validation = FALSE;
70750f2e948Smrg	i = VESAValidateModes(pScrn);
70850f2e948Smrg    }
70950f2e948Smrg
71050f2e948Smrg    if (i <= 0) do {
71150f2e948Smrg	Bool changed = FALSE;
71250f2e948Smrg	/* maybe there's more modes at the bottom... */
71350f2e948Smrg	if (pScrn->monitor->vrefresh[0].lo > 50) {
71450f2e948Smrg	    changed = TRUE;
71550f2e948Smrg	    pScrn->monitor->vrefresh[0].lo = 50;
71650f2e948Smrg	}
71750f2e948Smrg	if (pScrn->monitor->hsync[0].lo > 31.5) {
71850f2e948Smrg	    changed = TRUE;
71950f2e948Smrg	    pScrn->monitor->hsync[0].lo = 31.5;
72050f2e948Smrg	}
72150f2e948Smrg
72250f2e948Smrg	if (!changed)
72350f2e948Smrg	    break;
72450f2e948Smrg
72550f2e948Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
72650f2e948Smrg		   "No valid modes left. Trying aggressive sync range...\n");
72750f2e948Smrg	i = VESAValidateModes(pScrn);
72850f2e948Smrg    } while (0);
72945bc899bSmrg
73045bc899bSmrg    if (i <= 0) {
73150f2e948Smrg	/* alright, i'm out of ideas */
73245bc899bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n");
73345bc899bSmrg        vbeFree(pVesa->pVbe);
73445bc899bSmrg	return (FALSE);
73545bc899bSmrg    }
73645bc899bSmrg
73745bc899bSmrg    xf86PruneDriverModes(pScrn);
73845bc899bSmrg
73945bc899bSmrg    pMode = pScrn->modes;
74045bc899bSmrg    do {
74145bc899bSmrg	mode = ((VbeModeInfoData*)pMode->Private)->data;
74245bc899bSmrg	if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) {
74345bc899bSmrg	    pVesa->maxBytesPerScanline = mode->BytesPerScanline;
74445bc899bSmrg	}
74545bc899bSmrg	pMode = pMode->next;
74645bc899bSmrg    } while (pMode != pScrn->modes);
74745bc899bSmrg
74845bc899bSmrg    pScrn->currentMode = pScrn->modes;
74945bc899bSmrg    pScrn->displayWidth = pScrn->virtualX;
75045bc899bSmrg
75145bc899bSmrg    VBEPrintModes(pScrn);
75245bc899bSmrg
75345bc899bSmrg    /* Set display resolution */
75445bc899bSmrg    xf86SetDpi(pScrn, 0, 0);
75545bc899bSmrg
75645bc899bSmrg    if (pScrn->modes == NULL) {
75745bc899bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
75845bc899bSmrg        vbeFree(pVesa->pVbe);
75945bc899bSmrg	return (FALSE);
76045bc899bSmrg    }
76145bc899bSmrg
76245bc899bSmrg    /* options */
76345bc899bSmrg    xf86CollectOptions(pScrn, NULL);
76445bc899bSmrg    if (!(pVesa->Options = xalloc(sizeof(VESAOptions)))) {
76545bc899bSmrg        vbeFree(pVesa->pVbe);
76645bc899bSmrg	return FALSE;
76745bc899bSmrg    }
76845bc899bSmrg    memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions));
76945bc899bSmrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options);
77045bc899bSmrg
77145bc899bSmrg    /* Use shadow by default */
77245bc899bSmrg    if (xf86ReturnOptValBool(pVesa->Options, OPTION_SHADOW_FB, TRUE))
77345bc899bSmrg	pVesa->shadowFB = TRUE;
77445bc899bSmrg
77545bc899bSmrg    if (xf86ReturnOptValBool(pVesa->Options, OPTION_DFLT_REFRESH, FALSE))
77645bc899bSmrg	pVesa->defaultRefresh = TRUE;
77745bc899bSmrg
77850f2e948Smrg    pVesa->ModeSetClearScreen = FALSE;
77945bc899bSmrg    if (xf86ReturnOptValBool(pVesa->Options, OPTION_MODESET_CLEAR_SCREEN,
78050f2e948Smrg			     FALSE))
78145bc899bSmrg	pVesa->ModeSetClearScreen = TRUE;
78245bc899bSmrg
78350f2e948Smrg    if (!pVesa->defaultRefresh && !pVesa->strict_validation)
78445bc899bSmrg	VBESetModeParameters(pScrn, pVesa->pVbe);
78545bc899bSmrg
78645bc899bSmrg    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
78745bc899bSmrg    switch (mode->MemoryModel) {
78845bc899bSmrg	case 0x4:	/* Packed pixel */
78950f2e948Smrg	case 0x6:	/* Direct Color */
79045bc899bSmrg	    pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
79145bc899bSmrg
79245bc899bSmrg	    switch (pScrn->bitsPerPixel) {
79345bc899bSmrg		case 8:
79445bc899bSmrg		case 16:
79545bc899bSmrg		case 24:
79645bc899bSmrg		case 32:
79745bc899bSmrg		    break;
79845bc899bSmrg		default:
79945bc899bSmrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
80045bc899bSmrg			       "Unsupported bpp: %d", pScrn->bitsPerPixel);
80145bc899bSmrg		    vbeFree(pVesa->pVbe);
80245bc899bSmrg		    return FALSE;
80345bc899bSmrg	    }
80445bc899bSmrg	    break;
80550f2e948Smrg	default:
80650f2e948Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
80750f2e948Smrg		       "Unsupported Memory Model: %d", mode->MemoryModel);
80850f2e948Smrg	    return FALSE;
80945bc899bSmrg    }
81045bc899bSmrg
81145bc899bSmrg    if (pVesa->shadowFB) {
81245bc899bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n");
81345bc899bSmrg	if (!xf86LoadSubModule(pScrn, "shadow")) {
81445bc899bSmrg	    vbeFree(pVesa->pVbe);
81545bc899bSmrg	    return (FALSE);
81645bc899bSmrg	}
81745bc899bSmrg    }
81845bc899bSmrg
81950f2e948Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
82045bc899bSmrg	VESAFreeRec(pScrn);
82145bc899bSmrg        vbeFree(pVesa->pVbe);
82245bc899bSmrg	return (FALSE);
82345bc899bSmrg    }
82445bc899bSmrg
82545bc899bSmrg    vbeFree(pVesa->pVbe);
82645bc899bSmrg
82745bc899bSmrg    return (TRUE);
82845bc899bSmrg}
82945bc899bSmrg
83045bc899bSmrgstatic Bool
83145bc899bSmrgvesaCreateScreenResources(ScreenPtr pScreen)
83245bc899bSmrg{
83345bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
83445bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
83545bc899bSmrg    Bool ret;
83645bc899bSmrg
83745bc899bSmrg    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
83845bc899bSmrg    ret = pScreen->CreateScreenResources(pScreen);
83945bc899bSmrg    pScreen->CreateScreenResources = vesaCreateScreenResources;
84045bc899bSmrg
84145bc899bSmrg    shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update,
84245bc899bSmrg	      pVesa->window, 0, 0);
84345bc899bSmrg
84445bc899bSmrg    return ret;
84545bc899bSmrg}
84645bc899bSmrg
84750f2e948Smrgstatic void
84850f2e948SmrgvesaEnableDisableFBAccess(int scrnIndex, Bool enable)
84950f2e948Smrg{
85050f2e948Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
85150f2e948Smrg    VESAPtr pVesa = VESAGetRec(pScrn);
85250f2e948Smrg
85350f2e948Smrg    pVesa->accessEnabled = enable;
85450f2e948Smrg    pVesa->EnableDisableFBAccess(scrnIndex, enable);
85550f2e948Smrg}
85650f2e948Smrg
85745bc899bSmrgstatic Bool
85845bc899bSmrgVESAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
85945bc899bSmrg{
86045bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
86145bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
86245bc899bSmrg    VisualPtr visual;
86345bc899bSmrg    VbeModeInfoBlock *mode;
86445bc899bSmrg    int flags;
86545bc899bSmrg    int init_picture = 0;
86645bc899bSmrg
86745bc899bSmrg    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
86845bc899bSmrg				       SET_BIOS_SCRATCH
86945bc899bSmrg				       | RESTORE_BIOS_SCRATCH)) == NULL)
87045bc899bSmrg        return (FALSE);
87145bc899bSmrg
87245bc899bSmrg    if (pVesa->mapPhys == 0) {
87345bc899bSmrg	mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
87445bc899bSmrg	pScrn->videoRam = pVesa->mapSize;
87545bc899bSmrg	pVesa->mapPhys = mode->PhysBasePtr;
87645bc899bSmrg	pVesa->mapOff = 0;
87745bc899bSmrg    }
87845bc899bSmrg
87945bc899bSmrg    if (pVesa->mapPhys == 0) {
88045bc899bSmrg	pVesa->mapPhys = 0xa0000;
88145bc899bSmrg	pVesa->mapSize = 0x10000;
88245bc899bSmrg    }
88345bc899bSmrg
88445bc899bSmrg    if (!VESAMapVidMem(pScrn)) {
88545bc899bSmrg	if (pVesa->mapPhys != 0xa0000) {
88645bc899bSmrg	    pVesa->mapPhys = 0xa0000;
88745bc899bSmrg	    pVesa->mapSize = 0x10000;
88845bc899bSmrg	    if (!VESAMapVidMem(pScrn))
88945bc899bSmrg		return (FALSE);
89045bc899bSmrg	}
89145bc899bSmrg	else
89245bc899bSmrg	    return (FALSE);
89345bc899bSmrg    }
89445bc899bSmrg
89545bc899bSmrg    /* Set bpp to 8 for depth 4 when using shadowfb. */
89645bc899bSmrg    if (pVesa->shadowFB && pScrn->bitsPerPixel == 4)
89745bc899bSmrg	pScrn->bitsPerPixel = 8;
89845bc899bSmrg
89945bc899bSmrg    if (pVesa->shadowFB) {
90045bc899bSmrg	pVesa->shadow = xcalloc(1, pScrn->displayWidth * pScrn->virtualY *
90145bc899bSmrg				   ((pScrn->bitsPerPixel + 7) / 8));
90245bc899bSmrg	if (!pVesa->shadow) {
90345bc899bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
90445bc899bSmrg		       "Failed to allocate shadow buffer\n");
90545bc899bSmrg	    return FALSE;
90645bc899bSmrg	}
90745bc899bSmrg    }
90845bc899bSmrg
90945bc899bSmrg    /* save current video state */
91045bc899bSmrg    VESASaveRestore(pScrn, MODE_SAVE);
91145bc899bSmrg    pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256,
91245bc899bSmrg					    NULL, FALSE, FALSE);
91345bc899bSmrg
91445bc899bSmrg    /* set first video mode */
91545bc899bSmrg    if (!VESASetMode(pScrn, pScrn->currentMode))
91645bc899bSmrg	return (FALSE);
91745bc899bSmrg
91845bc899bSmrg    /* set the viewport */
91945bc899bSmrg    VESAAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
92045bc899bSmrg
92145bc899bSmrg    /* Blank the screen for aesthetic reasons. */
92245bc899bSmrg    VESASaveScreen(pScreen, SCREEN_SAVER_ON);
92345bc899bSmrg
92445bc899bSmrg    /* mi layer */
92545bc899bSmrg    miClearVisualTypes();
92645bc899bSmrg    if (!xf86SetDefaultVisual(pScrn, -1))
92745bc899bSmrg	return (FALSE);
92845bc899bSmrg    if (pScrn->bitsPerPixel > 8) {
92945bc899bSmrg	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
93045bc899bSmrg			      pScrn->rgbBits, TrueColor))
93145bc899bSmrg	    return (FALSE);
93245bc899bSmrg    }
93345bc899bSmrg    else {
93445bc899bSmrg	if (!miSetVisualTypes(pScrn->depth,
93545bc899bSmrg			      miGetDefaultVisualMask(pScrn->depth),
93645bc899bSmrg			      pScrn->rgbBits, pScrn->defaultVisual))
93745bc899bSmrg	    return (FALSE);
93845bc899bSmrg    }
93945bc899bSmrg    if (!miSetPixmapDepths())
94045bc899bSmrg	return (FALSE);
94145bc899bSmrg
94245bc899bSmrg    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
94345bc899bSmrg    switch (mode->MemoryModel) {
94445bc899bSmrg	case 0x4:	/* Packed pixel */
94550f2e948Smrg	case 0x6:	/* Direct Color */
94645bc899bSmrg	    switch (pScrn->bitsPerPixel) {
94745bc899bSmrg		case 8:
94845bc899bSmrg		case 16:
94945bc899bSmrg		case 24:
95045bc899bSmrg		case 32:
95145bc899bSmrg		    if (!fbScreenInit(pScreen,
95245bc899bSmrg				pVesa->shadowFB ? pVesa->shadow : pVesa->base,
95345bc899bSmrg				       pScrn->virtualX, pScrn->virtualY,
95445bc899bSmrg				       pScrn->xDpi, pScrn->yDpi,
95545bc899bSmrg				       pScrn->displayWidth, pScrn->bitsPerPixel))
95645bc899bSmrg			return (FALSE);
95745bc899bSmrg		    init_picture = 1;
95845bc899bSmrg		    break;
95945bc899bSmrg		default:
96045bc899bSmrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
96145bc899bSmrg			       "Unsupported bpp: %d", pScrn->bitsPerPixel);
96245bc899bSmrg		    return (FALSE);
96345bc899bSmrg	    }
96445bc899bSmrg	    break;
96550f2e948Smrg	default:
96650f2e948Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
96750f2e948Smrg		       "Unsupported Memory Model: %d", mode->MemoryModel);
96850f2e948Smrg	    return (FALSE);
96945bc899bSmrg    }
97045bc899bSmrg
97145bc899bSmrg
97245bc899bSmrg    if (pScrn->bitsPerPixel > 8) {
97345bc899bSmrg	/* Fixup RGB ordering */
97445bc899bSmrg	visual = pScreen->visuals + pScreen->numVisuals;
97545bc899bSmrg	while (--visual >= pScreen->visuals) {
97645bc899bSmrg	    if ((visual->class | DynamicClass) == DirectColor) {
97745bc899bSmrg		visual->offsetRed   = pScrn->offset.red;
97845bc899bSmrg		visual->offsetGreen = pScrn->offset.green;
97945bc899bSmrg		visual->offsetBlue  = pScrn->offset.blue;
98045bc899bSmrg		visual->redMask     = pScrn->mask.red;
98145bc899bSmrg		visual->greenMask   = pScrn->mask.green;
98245bc899bSmrg		visual->blueMask    = pScrn->mask.blue;
98345bc899bSmrg	    }
98445bc899bSmrg	}
98545bc899bSmrg    }
98645bc899bSmrg
98745bc899bSmrg    /* must be after RGB ordering fixed */
98845bc899bSmrg    if (init_picture)
98945bc899bSmrg	fbPictureInit(pScreen, 0, 0);
99045bc899bSmrg
99145bc899bSmrg    if (pVesa->shadowFB) {
99250f2e948Smrg	if (pVesa->mapPhys == 0xa0000) {	/* Windowed */
99345bc899bSmrg	    pVesa->update = shadowUpdatePackedWeak();
99445bc899bSmrg	    pVesa->window = VESAWindowWindowed;
99545bc899bSmrg	}
99645bc899bSmrg	else {	/* Linear */
99745bc899bSmrg	    pVesa->update = shadowUpdatePackedWeak();
99845bc899bSmrg	    pVesa->window = VESAWindowLinear;
99945bc899bSmrg	}
100045bc899bSmrg
100145bc899bSmrg	if (!shadowSetup(pScreen))
100245bc899bSmrg	    return FALSE;
100345bc899bSmrg	pVesa->CreateScreenResources = pScreen->CreateScreenResources;
100445bc899bSmrg	pScreen->CreateScreenResources = vesaCreateScreenResources;
100545bc899bSmrg    }
100650f2e948Smrg    else if (pVesa->mapPhys == 0xa0000) {
100745bc899bSmrg	unsigned int bankShift = 0;
100845bc899bSmrg	while ((unsigned)(64 >> bankShift) != mode->WinGranularity)
100945bc899bSmrg	    bankShift++;
101045bc899bSmrg	pVesa->curBank = -1;
101145bc899bSmrg	pVesa->bank.SetSourceBank =
101245bc899bSmrg	pVesa->bank.SetDestinationBank =
101345bc899bSmrg	pVesa->bank.SetSourceAndDestinationBanks = VESABankSwitch;
101445bc899bSmrg	pVesa->bank.pBankA = pVesa->bank.pBankB = pVesa->base;
101545bc899bSmrg	pVesa->bank.BankSize = (mode->WinSize * 1024) >> bankShift;
101645bc899bSmrg	pVesa->bank.nBankDepth = pScrn->depth;
101745bc899bSmrg	if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
101845bc899bSmrg				 pScrn->virtualX, &pVesa->bank)) {
101945bc899bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
102045bc899bSmrg		       "Bank switch initialization failed!\n");
102145bc899bSmrg	    return (FALSE);
102245bc899bSmrg	}
102345bc899bSmrg    }
102445bc899bSmrg
102545bc899bSmrg    VESADGAInit(pScrn, pScreen);
102645bc899bSmrg
102745bc899bSmrg    xf86SetBlackWhitePixels(pScreen);
102845bc899bSmrg    miInitializeBackingStore(pScreen);
102945bc899bSmrg    xf86SetBackingStore(pScreen);
103045bc899bSmrg
103145bc899bSmrg    /* software cursor */
103245bc899bSmrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
103345bc899bSmrg
103445bc899bSmrg    /* colormap */
103545bc899bSmrg    if (!miCreateDefColormap(pScreen))
103645bc899bSmrg	return (FALSE);
103745bc899bSmrg
103845bc899bSmrg    flags = CMAP_RELOAD_ON_MODE_SWITCH;
103945bc899bSmrg
104045bc899bSmrg    if(!xf86HandleColormaps(pScreen, 256,
104145bc899bSmrg	pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6,
104245bc899bSmrg	VESALoadPalette, NULL, flags))
104345bc899bSmrg	return (FALSE);
104445bc899bSmrg
104550f2e948Smrg    pVesa->accessEnabled = TRUE;
104650f2e948Smrg    pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
104750f2e948Smrg    pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess;
104850f2e948Smrg
104945bc899bSmrg    pVesa->CloseScreen = pScreen->CloseScreen;
105045bc899bSmrg    pScreen->CloseScreen = VESACloseScreen;
105145bc899bSmrg    pScreen->SaveScreen = VESASaveScreen;
105245bc899bSmrg
105345bc899bSmrg    xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0);
105445bc899bSmrg
105545bc899bSmrg    /* Report any unused options (only for the first generation) */
105645bc899bSmrg    if (serverGeneration == 1)
105745bc899bSmrg        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
105845bc899bSmrg
105945bc899bSmrg    return (TRUE);
106045bc899bSmrg}
106145bc899bSmrg
106245bc899bSmrgstatic Bool
106345bc899bSmrgVESAEnterVT(int scrnIndex, int flags)
106445bc899bSmrg{
106545bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
106645bc899bSmrg
106745bc899bSmrg    if (!VESASetMode(pScrn, pScrn->currentMode))
106845bc899bSmrg	return FALSE;
106945bc899bSmrg    VESAAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
107045bc899bSmrg    return TRUE;
107145bc899bSmrg}
107245bc899bSmrg
107345bc899bSmrgstatic void
107445bc899bSmrgVESALeaveVT(int scrnIndex, int flags)
107545bc899bSmrg{
107645bc899bSmrg    VESASaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
107745bc899bSmrg}
107845bc899bSmrg
107945bc899bSmrgstatic Bool
108045bc899bSmrgVESACloseScreen(int scrnIndex, ScreenPtr pScreen)
108145bc899bSmrg{
108245bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
108345bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
108445bc899bSmrg
108545bc899bSmrg    if (pScrn->vtSema) {
108645bc899bSmrg	VESASaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
108745bc899bSmrg	if (pVesa->savedPal)
108845bc899bSmrg	    VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256,
108945bc899bSmrg				 pVesa->savedPal, FALSE, TRUE);
109045bc899bSmrg	VESAUnmapVidMem(pScrn);
109145bc899bSmrg    }
109245bc899bSmrg    if (pVesa->shadowFB && pVesa->shadow)
109345bc899bSmrg	xfree(pVesa->shadow);
109445bc899bSmrg    if (pVesa->pDGAMode) {
109545bc899bSmrg	xfree(pVesa->pDGAMode);
109645bc899bSmrg	pVesa->pDGAMode = NULL;
109745bc899bSmrg	pVesa->nDGAMode = 0;
109845bc899bSmrg    }
109945bc899bSmrg    pScrn->vtSema = FALSE;
110045bc899bSmrg
110150f2e948Smrg    pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess;
110245bc899bSmrg    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
110345bc899bSmrg    pScreen->CloseScreen = pVesa->CloseScreen;
110445bc899bSmrg    return pScreen->CloseScreen(scrnIndex, pScreen);
110545bc899bSmrg}
110645bc899bSmrg
110745bc899bSmrgstatic Bool
110845bc899bSmrgVESASwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
110945bc899bSmrg{
111045bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
111145bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
111250f2e948Smrg    Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled;
111345bc899bSmrg
111450f2e948Smrg    if (disableAccess)
111545bc899bSmrg	pScrn->EnableDisableFBAccess(scrnIndex,FALSE);
111645bc899bSmrg    ret = VESASetMode(xf86Screens[scrnIndex], pMode);
111750f2e948Smrg    if (disableAccess)
111845bc899bSmrg	pScrn->EnableDisableFBAccess(scrnIndex,TRUE);
111945bc899bSmrg    return ret;
112045bc899bSmrg}
112145bc899bSmrg
112245bc899bSmrg/* Set a graphics mode */
112345bc899bSmrgstatic Bool
112445bc899bSmrgVESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
112545bc899bSmrg{
112645bc899bSmrg    VESAPtr pVesa;
112745bc899bSmrg    VbeModeInfoData *data;
112845bc899bSmrg    int mode;
112945bc899bSmrg
113045bc899bSmrg    pVesa = VESAGetRec(pScrn);
113145bc899bSmrg
113245bc899bSmrg    data = (VbeModeInfoData*)pMode->Private;
113350f2e948Smrg
113450f2e948Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
113550f2e948Smrg	       "Setting up VESA Mode 0x%X (%dx%d)\n",
113650f2e948Smrg	       data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay);
113750f2e948Smrg
113850f2e948Smrg    /* careful, setting the bit means don't clear the screen */
113950f2e948Smrg    mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15));
114045bc899bSmrg
114145bc899bSmrg    /* enable linear addressing */
114245bc899bSmrg    if (pVesa->mapPhys != 0xa0000)
114345bc899bSmrg	mode |= 1 << 14;
114445bc899bSmrg
114545bc899bSmrg    if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) {
114645bc899bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed");
114745bc899bSmrg	if ((data->block || (data->mode & (1 << 11))) &&
114845bc899bSmrg	    VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) {
114945bc899bSmrg	    /* Some cards do not like setting the clock.
115045bc899bSmrg	     * Free it as it will not be any longer useful
115145bc899bSmrg	     */
115245bc899bSmrg	    xf86ErrorF("...Tried again without customized values.\n");
115345bc899bSmrg	    xfree(data->block);
115445bc899bSmrg	    data->block = NULL;
115545bc899bSmrg	    data->mode &= ~(1 << 11);
115645bc899bSmrg	}
115745bc899bSmrg	else {
115845bc899bSmrg	    ErrorF("\n");
115945bc899bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
116045bc899bSmrg	    return (FALSE);
116145bc899bSmrg	}
116245bc899bSmrg    }
116345bc899bSmrg
116445bc899bSmrg    pVesa->bankSwitchWindowB =
116545bc899bSmrg	!((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0));
116645bc899bSmrg
116745bc899bSmrg    if (data->data->XResolution != pScrn->displayWidth)
116845bc899bSmrg	VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth);
116945bc899bSmrg
117045bc899bSmrg    if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 &&
117150f2e948Smrg        !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7))
117245bc899bSmrg	VBESetGetDACPaletteFormat(pVesa->pVbe, 8);
117345bc899bSmrg
117445bc899bSmrg    pScrn->vtSema = TRUE;
117545bc899bSmrg
117645bc899bSmrg    return (TRUE);
117745bc899bSmrg}
117845bc899bSmrg
117945bc899bSmrgstatic void
118045bc899bSmrgVESAAdjustFrame(int scrnIndex, int x, int y, int flags)
118145bc899bSmrg{
118245bc899bSmrg    VESAPtr pVesa = VESAGetRec(xf86Screens[scrnIndex]);
118345bc899bSmrg
118445bc899bSmrg    VBESetDisplayStart(pVesa->pVbe, x, y, TRUE);
118545bc899bSmrg}
118645bc899bSmrg
118745bc899bSmrgstatic void
118845bc899bSmrgVESAFreeScreen(int scrnIndex, int flags)
118945bc899bSmrg{
119045bc899bSmrg    VESAFreeRec(xf86Screens[scrnIndex]);
119145bc899bSmrg}
119245bc899bSmrg
119345bc899bSmrgstatic Bool
119445bc899bSmrgVESAMapVidMem(ScrnInfoPtr pScrn)
119545bc899bSmrg{
119645bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
119745bc899bSmrg
119845bc899bSmrg    if (pVesa->base != NULL)
119945bc899bSmrg	return (TRUE);
120045bc899bSmrg
120145bc899bSmrg    pScrn->memPhysBase = pVesa->mapPhys;
120245bc899bSmrg    pScrn->fbOffset = pVesa->mapOff;
120345bc899bSmrg
120450f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
120550f2e948Smrg    if ((pVesa->mapPhys != 0xa0000) && (pVesa->pciInfo != NULL)) {
120650f2e948Smrg	(void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase,
120750f2e948Smrg				    pVesa->mapSize,
120850f2e948Smrg				    (PCI_DEV_MAP_FLAG_WRITABLE
120950f2e948Smrg				     | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
121050f2e948Smrg				    & pVesa->base);
121150f2e948Smrg    }
121250f2e948Smrg    else
121350f2e948Smrg	pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciInfo,
121450f2e948Smrg					  pScrn->memPhysBase, pVesa->mapSize);
121550f2e948Smrg
121650f2e948Smrg    if (pVesa->base) {
121750f2e948Smrg	if (pVesa->mapPhys != 0xa0000)
121850f2e948Smrg	    pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
121950f2e948Smrg						 pVesa->pciInfo,
122050f2e948Smrg						 0xa0000, 0x10000);
122150f2e948Smrg	else
122250f2e948Smrg	    pVesa->VGAbase = pVesa->base;
122350f2e948Smrg
122450f2e948Smrg    }
122550f2e948Smrg#else
122645bc899bSmrg    if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI)
122745bc899bSmrg	pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
122845bc899bSmrg				    pVesa->pciTag, pScrn->memPhysBase,
122945bc899bSmrg				    pVesa->mapSize);
123045bc899bSmrg    else
123145bc899bSmrg	pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag,
123245bc899bSmrg					  pScrn->memPhysBase, pVesa->mapSize);
123345bc899bSmrg
123445bc899bSmrg    if (pVesa->base) {
123545bc899bSmrg	if (pVesa->mapPhys != 0xa0000)
123645bc899bSmrg	    pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
123745bc899bSmrg						 pVesa->pciTag,
123845bc899bSmrg						 0xa0000, 0x10000);
123945bc899bSmrg	else
124045bc899bSmrg	    pVesa->VGAbase = pVesa->base;
124145bc899bSmrg    }
124250f2e948Smrg#endif
124345bc899bSmrg
124445bc899bSmrg    pVesa->ioBase = pScrn->domainIOBase;
124545bc899bSmrg
124645bc899bSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
124745bc899bSmrg		   "virtual address = %p,\n"
124845bc899bSmrg		   "\tphysical address = 0x%lx, size = %ld\n",
124945bc899bSmrg		   pVesa->base, pScrn->memPhysBase, pVesa->mapSize);
125045bc899bSmrg
125145bc899bSmrg    return (pVesa->base != NULL);
125245bc899bSmrg}
125345bc899bSmrg
125445bc899bSmrgstatic void
125545bc899bSmrgVESAUnmapVidMem(ScrnInfoPtr pScrn)
125645bc899bSmrg{
125745bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
125845bc899bSmrg
125945bc899bSmrg    if (pVesa->base == NULL)
126045bc899bSmrg	return;
126145bc899bSmrg
126250f2e948Smrg#ifdef XSERVER_LIBPCIACCESS
126350f2e948Smrg    if (pVesa->mapPhys != 0xa0000) {
126450f2e948Smrg	(void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base,
126550f2e948Smrg				      pVesa->mapSize);
126650f2e948Smrg	xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000);
126750f2e948Smrg    }
126850f2e948Smrg    else {
126950f2e948Smrg	xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize);
127050f2e948Smrg    }
127150f2e948Smrg#else
127245bc899bSmrg    xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize);
127345bc899bSmrg    if (pVesa->mapPhys != 0xa0000)
127445bc899bSmrg	xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000);
127550f2e948Smrg#endif
127645bc899bSmrg    pVesa->base = NULL;
127745bc899bSmrg}
127845bc899bSmrg
127945bc899bSmrgstatic void *
128045bc899bSmrgVESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
128145bc899bSmrg		 CARD32 *size, void *closure)
128245bc899bSmrg{
128345bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
128445bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
128545bc899bSmrg
128645bc899bSmrg    *size = pVesa->maxBytesPerScanline;
128745bc899bSmrg    return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset);
128845bc899bSmrg}
128945bc899bSmrg
129045bc899bSmrgstatic void *
129145bc899bSmrgVESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
129245bc899bSmrg		   CARD32 *size, void *closure)
129345bc899bSmrg{
129445bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
129545bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
129645bc899bSmrg    VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
129745bc899bSmrg    int window;
129845bc899bSmrg
129945bc899bSmrg    offset += pVesa->maxBytesPerScanline * row;
130045bc899bSmrg    window = offset / (data->WinGranularity * 1024);
130145bc899bSmrg    pVesa->windowAoffset = window * data->WinGranularity * 1024;
130245bc899bSmrg    VESABankSwitch(pScreen, window);
130345bc899bSmrg    *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset);
130445bc899bSmrg
130545bc899bSmrg    return (void *)((unsigned long)pVesa->base +
130645bc899bSmrg		    (offset - pVesa->windowAoffset));
130745bc899bSmrg}
130845bc899bSmrg
130945bc899bSmrgstatic void
131045bc899bSmrgVESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
131145bc899bSmrg		LOCO *colors, VisualPtr pVisual)
131245bc899bSmrg{
131345bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
131445bc899bSmrg    int i, idx;
131545bc899bSmrg
131645bc899bSmrg#if 0
131745bc899bSmrg
131845bc899bSmrg    /* This code works, but is very slow for programs that use it intensively */
131945bc899bSmrg    int base;
132045bc899bSmrg
132145bc899bSmrg    if (pVesa->pal == NULL)
132245bc899bSmrg	pVesa->pal = xcalloc(1, sizeof(CARD32) * 256);
132345bc899bSmrg
132445bc899bSmrg    for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) {
132545bc899bSmrg	int j = indices[i];
132645bc899bSmrg
132745bc899bSmrg	if (j < 0 || j >= 256)
132845bc899bSmrg	    continue;
132945bc899bSmrg	pVesa->pal[j] = colors[j].blue |
133045bc899bSmrg			(colors[j].green << 8) |
133145bc899bSmrg			(colors[j].red << 16);
133245bc899bSmrg	if (j != idx) {
133345bc899bSmrg	    VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
133445bc899bSmrg				  pVesa->pal + base, FALSE, TRUE);
133545bc899bSmrg	    idx = base = j;
133645bc899bSmrg	}
133745bc899bSmrg    }
133845bc899bSmrg
133945bc899bSmrg    if (idx - 1 == indices[i - 1])
134045bc899bSmrg	VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
134145bc899bSmrg			      pVesa->pal + base, FALSE, TRUE);
134245bc899bSmrg
134345bc899bSmrg#else
134445bc899bSmrg
134545bc899bSmrg#define VESADACDelay()							    \
134645bc899bSmrg    do {								    \
134745bc899bSmrg	(void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
134845bc899bSmrg	(void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
134945bc899bSmrg    } while (0)
135045bc899bSmrg
135145bc899bSmrg    for (i = 0; i < numColors; i++) {
135245bc899bSmrg	idx = indices[i];
135345bc899bSmrg	outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx);
135445bc899bSmrg	VESADACDelay();
135545bc899bSmrg	outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red);
135645bc899bSmrg	VESADACDelay();
135745bc899bSmrg	outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green);
135845bc899bSmrg	VESADACDelay();
135945bc899bSmrg	outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue);
136045bc899bSmrg	VESADACDelay();
136145bc899bSmrg    }
136245bc899bSmrg
136345bc899bSmrg#endif
136445bc899bSmrg}
136545bc899bSmrg
136645bc899bSmrg/*
136745bc899bSmrg * Just adapted from the std* functions in vgaHW.c
136845bc899bSmrg */
136945bc899bSmrgstatic void
137045bc899bSmrgWriteAttr(VESAPtr pVesa, int index, int value)
137145bc899bSmrg{
137245bc899bSmrg    (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
137345bc899bSmrg
137445bc899bSmrg    index |= 0x20;
137545bc899bSmrg    outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
137645bc899bSmrg    outb(pVesa->ioBase + VGA_ATTR_DATA_W, value);
137745bc899bSmrg}
137845bc899bSmrg
137945bc899bSmrgstatic int
138045bc899bSmrgReadAttr(VESAPtr pVesa, int index)
138145bc899bSmrg{
138245bc899bSmrg    (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
138345bc899bSmrg
138445bc899bSmrg    index |= 0x20;
138545bc899bSmrg    outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
138645bc899bSmrg    return (inb(pVesa->ioBase + VGA_ATTR_DATA_R));
138745bc899bSmrg}
138845bc899bSmrg
138945bc899bSmrg#define WriteMiscOut(value)	outb(pVesa->ioBase + VGA_MISC_OUT_W, value)
139045bc899bSmrg#define ReadMiscOut()		inb(pVesa->ioBase + VGA_MISC_OUT_R)
139145bc899bSmrg#define WriteSeq(index, value)	outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\
139245bc899bSmrg				outb(pVesa->ioBase + VGA_SEQ_DATA, value)
139345bc899bSmrg
139445bc899bSmrgstatic int
139545bc899bSmrgReadSeq(VESAPtr pVesa, int index)
139645bc899bSmrg{
139745bc899bSmrg    outb(pVesa->ioBase + VGA_SEQ_INDEX, index);
139845bc899bSmrg
139945bc899bSmrg    return (inb(pVesa->ioBase + VGA_SEQ_DATA));
140045bc899bSmrg}
140145bc899bSmrg
140245bc899bSmrg#define WriteGr(index, value)				\
140345bc899bSmrg    outb(pVesa->ioBase + VGA_GRAPH_INDEX, index);	\
140445bc899bSmrg    outb(pVesa->ioBase + VGA_GRAPH_DATA, value)
140545bc899bSmrg
140645bc899bSmrgstatic int
140745bc899bSmrgReadGr(VESAPtr pVesa, int index)
140845bc899bSmrg{
140945bc899bSmrg    outb(pVesa->ioBase + VGA_GRAPH_INDEX, index);
141045bc899bSmrg
141145bc899bSmrg    return (inb(pVesa->ioBase + VGA_GRAPH_DATA));
141245bc899bSmrg}
141345bc899bSmrg
141445bc899bSmrg#define WriteCrtc(index, value)						     \
141545bc899bSmrg    outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
141645bc899bSmrg    outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
141745bc899bSmrg
141845bc899bSmrgstatic void
141945bc899bSmrgSeqReset(VESAPtr pVesa, Bool start)
142045bc899bSmrg{
142145bc899bSmrg    if (start) {
142245bc899bSmrg	WriteSeq(0x00, 0x01);		/* Synchronous Reset */
142345bc899bSmrg    }
142445bc899bSmrg    else {
142545bc899bSmrg	WriteSeq(0x00, 0x03);		/* End Reset */
142645bc899bSmrg    }
142745bc899bSmrg}
142845bc899bSmrg
142945bc899bSmrgstatic void
143045bc899bSmrgSaveFonts(ScrnInfoPtr pScrn)
143145bc899bSmrg{
143245bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
143345bc899bSmrg    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
143445bc899bSmrg
143545bc899bSmrg    if (pVesa->fonts != NULL)
143645bc899bSmrg	return;
143745bc899bSmrg
143845bc899bSmrg    /* If in graphics mode, don't save anything */
143945bc899bSmrg    attr10 = ReadAttr(pVesa, 0x10);
144045bc899bSmrg    if (attr10 & 0x01)
144145bc899bSmrg	return;
144245bc899bSmrg
144345bc899bSmrg    pVesa->fonts = xalloc(16384);
144445bc899bSmrg
144545bc899bSmrg    /* save the registers that are needed here */
144645bc899bSmrg    miscOut = ReadMiscOut();
144745bc899bSmrg    gr4 = ReadGr(pVesa, 0x04);
144845bc899bSmrg    gr5 = ReadGr(pVesa, 0x05);
144945bc899bSmrg    gr6 = ReadGr(pVesa, 0x06);
145045bc899bSmrg    seq2 = ReadSeq(pVesa, 0x02);
145145bc899bSmrg    seq4 = ReadSeq(pVesa, 0x04);
145245bc899bSmrg
145345bc899bSmrg    /* Force into colour mode */
145445bc899bSmrg    WriteMiscOut(miscOut | 0x01);
145545bc899bSmrg
145645bc899bSmrg    scrn = ReadSeq(pVesa, 0x01) | 0x20;
145745bc899bSmrg    SeqReset(pVesa, TRUE);
145845bc899bSmrg    WriteSeq(0x01, scrn);
145945bc899bSmrg    SeqReset(pVesa, FALSE);
146045bc899bSmrg
146145bc899bSmrg    WriteAttr(pVesa, 0x10, 0x01);	/* graphics mode */
146245bc899bSmrg
146345bc899bSmrg    /*font1 */
146445bc899bSmrg    WriteSeq(0x02, 0x04);	/* write to plane 2 */
146545bc899bSmrg    WriteSeq(0x04, 0x06);	/* enable plane graphics */
146645bc899bSmrg    WriteGr(0x04, 0x02);	/* read plane 2 */
146745bc899bSmrg    WriteGr(0x05, 0x00);	/* write mode 0, read mode 0 */
146845bc899bSmrg    WriteGr(0x06, 0x05);	/* set graphics */
146945bc899bSmrg    slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192);
147045bc899bSmrg
147145bc899bSmrg    /* font2 */
147245bc899bSmrg    WriteSeq(0x02, 0x08);	/* write to plane 3 */
147345bc899bSmrg    WriteSeq(0x04, 0x06);	/* enable plane graphics */
147445bc899bSmrg    WriteGr(0x04, 0x03);	/* read plane 3 */
147545bc899bSmrg    WriteGr(0x05, 0x00);	/* write mode 0, read mode 0 */
147645bc899bSmrg    WriteGr(0x06, 0x05);	/* set graphics */
147745bc899bSmrg    slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192);
147845bc899bSmrg
147945bc899bSmrg    scrn = ReadSeq(pVesa, 0x01) & ~0x20;
148045bc899bSmrg    SeqReset(pVesa, TRUE);
148145bc899bSmrg    WriteSeq(0x01, scrn);
148245bc899bSmrg    SeqReset(pVesa, FALSE);
148345bc899bSmrg
148445bc899bSmrg    /* Restore clobbered registers */
148545bc899bSmrg    WriteAttr(pVesa, 0x10, attr10);
148645bc899bSmrg    WriteSeq(0x02, seq2);
148745bc899bSmrg    WriteSeq(0x04, seq4);
148845bc899bSmrg    WriteGr(0x04, gr4);
148945bc899bSmrg    WriteGr(0x05, gr5);
149045bc899bSmrg    WriteGr(0x06, gr6);
149145bc899bSmrg    WriteMiscOut(miscOut);
149245bc899bSmrg}
149345bc899bSmrg
149445bc899bSmrgstatic void
149545bc899bSmrgRestoreFonts(ScrnInfoPtr pScrn)
149645bc899bSmrg{
149745bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
149845bc899bSmrg    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
149945bc899bSmrg
150045bc899bSmrg    if (pVesa->fonts == NULL)
150145bc899bSmrg	return;
150245bc899bSmrg
150345bc899bSmrg    if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0)
150445bc899bSmrg	VESABankSwitch(pScrn->pScreen, 0);
150545bc899bSmrg
150645bc899bSmrg    /* save the registers that are needed here */
150745bc899bSmrg    miscOut = ReadMiscOut();
150845bc899bSmrg    attr10 = ReadAttr(pVesa, 0x10);
150945bc899bSmrg    gr1 = ReadGr(pVesa, 0x01);
151045bc899bSmrg    gr3 = ReadGr(pVesa, 0x03);
151145bc899bSmrg    gr4 = ReadGr(pVesa, 0x04);
151245bc899bSmrg    gr5 = ReadGr(pVesa, 0x05);
151345bc899bSmrg    gr6 = ReadGr(pVesa, 0x06);
151445bc899bSmrg    gr8 = ReadGr(pVesa, 0x08);
151545bc899bSmrg    seq2 = ReadSeq(pVesa, 0x02);
151645bc899bSmrg    seq4 = ReadSeq(pVesa, 0x04);
151745bc899bSmrg
151845bc899bSmrg    /* Force into colour mode */
151945bc899bSmrg    WriteMiscOut(miscOut | 0x01);
152045bc899bSmrg
152145bc899bSmrg    scrn = ReadSeq(pVesa, 0x01) | 0x20;
152245bc899bSmrg    SeqReset(pVesa, TRUE);
152345bc899bSmrg    WriteSeq(0x01, scrn);
152445bc899bSmrg    SeqReset(pVesa, FALSE);
152545bc899bSmrg
152645bc899bSmrg    WriteAttr(pVesa, 0x10, 0x01);	/* graphics mode */
152745bc899bSmrg    if (pScrn->depth == 4) {
152845bc899bSmrg	/* GJA */
152945bc899bSmrg	WriteGr(0x03, 0x00);	/* don't rotate, write unmodified */
153045bc899bSmrg	WriteGr(0x08, 0xFF);	/* write all bits in a byte */
153145bc899bSmrg	WriteGr(0x01, 0x00);	/* all planes come from CPU */
153245bc899bSmrg    }
153345bc899bSmrg
153445bc899bSmrg    WriteSeq(0x02, 0x04);   /* write to plane 2 */
153545bc899bSmrg    WriteSeq(0x04, 0x06);   /* enable plane graphics */
153645bc899bSmrg    WriteGr(0x04, 0x02);    /* read plane 2 */
153745bc899bSmrg    WriteGr(0x05, 0x00);    /* write mode 0, read mode 0 */
153845bc899bSmrg    WriteGr(0x06, 0x05);    /* set graphics */
153945bc899bSmrg    slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192);
154045bc899bSmrg
154145bc899bSmrg    WriteSeq(0x02, 0x08);   /* write to plane 3 */
154245bc899bSmrg    WriteSeq(0x04, 0x06);   /* enable plane graphics */
154345bc899bSmrg    WriteGr(0x04, 0x03);    /* read plane 3 */
154445bc899bSmrg    WriteGr(0x05, 0x00);    /* write mode 0, read mode 0 */
154545bc899bSmrg    WriteGr(0x06, 0x05);    /* set graphics */
154645bc899bSmrg    slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192);
154745bc899bSmrg
154845bc899bSmrg    scrn = ReadSeq(pVesa, 0x01) & ~0x20;
154945bc899bSmrg    SeqReset(pVesa, TRUE);
155045bc899bSmrg    WriteSeq(0x01, scrn);
155145bc899bSmrg    SeqReset(pVesa, FALSE);
155245bc899bSmrg
155345bc899bSmrg    /* restore the registers that were changed */
155445bc899bSmrg    WriteMiscOut(miscOut);
155545bc899bSmrg    WriteAttr(pVesa, 0x10, attr10);
155645bc899bSmrg    WriteGr(0x01, gr1);
155745bc899bSmrg    WriteGr(0x03, gr3);
155845bc899bSmrg    WriteGr(0x04, gr4);
155945bc899bSmrg    WriteGr(0x05, gr5);
156045bc899bSmrg    WriteGr(0x06, gr6);
156145bc899bSmrg    WriteGr(0x08, gr8);
156245bc899bSmrg    WriteSeq(0x02, seq2);
156345bc899bSmrg    WriteSeq(0x04, seq4);
156445bc899bSmrg}
156545bc899bSmrg
156645bc899bSmrgstatic Bool
156745bc899bSmrgVESASaveScreen(ScreenPtr pScreen, int mode)
156845bc899bSmrg{
156945bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
157045bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
157145bc899bSmrg    Bool on = xf86IsUnblank(mode);
157245bc899bSmrg
157345bc899bSmrg    if (on)
157445bc899bSmrg	SetTimeSinceLastInputEvent();
157545bc899bSmrg
157645bc899bSmrg    if (pScrn->vtSema) {
157745bc899bSmrg	unsigned char scrn = ReadSeq(pVesa, 0x01);
157845bc899bSmrg
157945bc899bSmrg	if (on)
158045bc899bSmrg	    scrn &= ~0x20;
158145bc899bSmrg	else
158245bc899bSmrg	    scrn |= 0x20;
158345bc899bSmrg	SeqReset(pVesa, TRUE);
158445bc899bSmrg	WriteSeq(0x01, scrn);
158545bc899bSmrg	SeqReset(pVesa, FALSE);
158645bc899bSmrg    }
158745bc899bSmrg
158845bc899bSmrg    return (TRUE);
158945bc899bSmrg}
159045bc899bSmrg
159145bc899bSmrgstatic int
159245bc899bSmrgVESABankSwitch(ScreenPtr pScreen, unsigned int iBank)
159345bc899bSmrg{
159445bc899bSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
159545bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
159645bc899bSmrg
159745bc899bSmrg    if (pVesa->curBank == iBank)
159845bc899bSmrg	return (0);
159945bc899bSmrg    if (!VBEBankSwitch(pVesa->pVbe, iBank, 0))
160045bc899bSmrg        return (1);
160145bc899bSmrg    if (pVesa->bankSwitchWindowB) {
160245bc899bSmrg        if (!VBEBankSwitch(pVesa->pVbe, iBank, 1))
160345bc899bSmrg	   return (1);
160445bc899bSmrg    }
160545bc899bSmrg    pVesa->curBank = iBank;
160645bc899bSmrg
160745bc899bSmrg    return (0);
160845bc899bSmrg}
160945bc899bSmrg
161045bc899bSmrgBool
161145bc899bSmrgVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
161245bc899bSmrg{
161345bc899bSmrg    VESAPtr pVesa;
161445bc899bSmrg
161545bc899bSmrg    if (MODE_QUERY < 0 || function > MODE_RESTORE)
161645bc899bSmrg	return (FALSE);
161745bc899bSmrg
161845bc899bSmrg    pVesa = VESAGetRec(pScrn);
161945bc899bSmrg
162045bc899bSmrg
162145bc899bSmrg    /* Query amount of memory to save state */
162245bc899bSmrg    if (function == MODE_QUERY ||
162345bc899bSmrg	(function == MODE_SAVE && pVesa->state == NULL)) {
162445bc899bSmrg
162545bc899bSmrg	/* Make sure we save at least this information in case of failure */
162645bc899bSmrg	(void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode);
162745bc899bSmrg	SaveFonts(pScrn);
162845bc899bSmrg
162945bc899bSmrg	if (pVesa->major > 1) {
163045bc899bSmrg	    if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state,
163145bc899bSmrg				&pVesa->stateSize,&pVesa->statePage))
163245bc899bSmrg	        return FALSE;
163345bc899bSmrg
163445bc899bSmrg	}
163545bc899bSmrg    }
163645bc899bSmrg
163745bc899bSmrg    /* Save/Restore Super VGA state */
163845bc899bSmrg    if (function != MODE_QUERY) {
163945bc899bSmrg        Bool retval = TRUE;
164045bc899bSmrg
164145bc899bSmrg	if (pVesa->major > 1) {
164245bc899bSmrg	    if (function == MODE_RESTORE)
164345bc899bSmrg		memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
164445bc899bSmrg
164545bc899bSmrg	    if ((retval = VBESaveRestore(pVesa->pVbe,function,
164645bc899bSmrg					 (pointer)&pVesa->state,
164745bc899bSmrg					 &pVesa->stateSize,&pVesa->statePage))
164845bc899bSmrg		&& function == MODE_SAVE) {
164945bc899bSmrg	        /* don't rely on the memory not being touched */
165045bc899bSmrg	        if (pVesa->pstate == NULL)
165145bc899bSmrg		    pVesa->pstate = xalloc(pVesa->stateSize);
165245bc899bSmrg		memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
165345bc899bSmrg	    }
165445bc899bSmrg	}
165545bc899bSmrg
165645bc899bSmrg	if (function == MODE_RESTORE) {
165745bc899bSmrg	    VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL);
165845bc899bSmrg	    RestoreFonts(pScrn);
165945bc899bSmrg	}
166045bc899bSmrg
166145bc899bSmrg	if (!retval)
166245bc899bSmrg	    return (FALSE);
166345bc899bSmrg
166445bc899bSmrg    }
166545bc899bSmrg
166645bc899bSmrg    return (TRUE);
166745bc899bSmrg}
166845bc899bSmrg
166945bc899bSmrgstatic void
167045bc899bSmrgVESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
167145bc899bSmrg                int flags)
167245bc899bSmrg{
167345bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
167445bc899bSmrg
167545bc899bSmrg    if (!pScrn->vtSema)
167645bc899bSmrg	return;
167745bc899bSmrg
167850f2e948Smrg    VBEDPMSSet(pVesa->pVbe, mode);
167945bc899bSmrg}
168045bc899bSmrg
168145bc899bSmrg/***********************************************************************
168245bc899bSmrg * DGA stuff
168345bc899bSmrg ***********************************************************************/
168445bc899bSmrgstatic Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
168545bc899bSmrg				   unsigned char **ApertureBase,
168645bc899bSmrg				   int *ApertureSize, int *ApertureOffset,
168745bc899bSmrg				   int *flags);
168845bc899bSmrgstatic Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
168945bc899bSmrgstatic void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
169045bc899bSmrg
169145bc899bSmrgstatic Bool
169245bc899bSmrgVESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
169345bc899bSmrg		       unsigned char **ApertureBase, int *ApertureSize,
169445bc899bSmrg		       int *ApertureOffset, int *flags)
169545bc899bSmrg{
169645bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
169745bc899bSmrg
169845bc899bSmrg    *DeviceName = NULL;		/* No special device */
169945bc899bSmrg    *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys);
170045bc899bSmrg    *ApertureSize = pVesa->mapSize;
170145bc899bSmrg    *ApertureOffset = pVesa->mapOff;
170245bc899bSmrg    *flags = DGA_NEED_ROOT;
170345bc899bSmrg
170445bc899bSmrg    return (TRUE);
170545bc899bSmrg}
170645bc899bSmrg
170745bc899bSmrgstatic Bool
170845bc899bSmrgVESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
170945bc899bSmrg{
171045bc899bSmrg    DisplayModePtr pMode;
171145bc899bSmrg    int scrnIdx = pScrn->pScreen->myNum;
171245bc899bSmrg    int frameX0, frameY0;
171345bc899bSmrg
171445bc899bSmrg    if (pDGAMode) {
171545bc899bSmrg	pMode = pDGAMode->mode;
171645bc899bSmrg	frameX0 = frameY0 = 0;
171745bc899bSmrg    }
171845bc899bSmrg    else {
171945bc899bSmrg	if (!(pMode = pScrn->currentMode))
172045bc899bSmrg	    return (TRUE);
172145bc899bSmrg
172245bc899bSmrg	frameX0 = pScrn->frameX0;
172345bc899bSmrg	frameY0 = pScrn->frameY0;
172445bc899bSmrg    }
172545bc899bSmrg
172645bc899bSmrg    if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
172745bc899bSmrg	return (FALSE);
172845bc899bSmrg    (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
172945bc899bSmrg
173045bc899bSmrg    return (TRUE);
173145bc899bSmrg}
173245bc899bSmrg
173345bc899bSmrgstatic void
173445bc899bSmrgVESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
173545bc899bSmrg{
173645bc899bSmrg    (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
173745bc899bSmrg}
173845bc899bSmrg
173945bc899bSmrgstatic int
174045bc899bSmrgVESADGAGetViewport(ScrnInfoPtr pScrn)
174145bc899bSmrg{
174245bc899bSmrg    return (0);
174345bc899bSmrg}
174445bc899bSmrg
174545bc899bSmrgstatic DGAFunctionRec VESADGAFunctions =
174645bc899bSmrg{
174745bc899bSmrg    VESADGAOpenFramebuffer,
174845bc899bSmrg    NULL,       /* CloseFramebuffer */
174945bc899bSmrg    VESADGASetMode,
175045bc899bSmrg    VESADGASetViewport,
175145bc899bSmrg    VESADGAGetViewport,
175245bc899bSmrg    NULL,       /* Sync */
175345bc899bSmrg    NULL,       /* FillRect */
175445bc899bSmrg    NULL,       /* BlitRect */
175545bc899bSmrg    NULL,       /* BlitTransRect */
175645bc899bSmrg};
175745bc899bSmrg
175845bc899bSmrgstatic void
175945bc899bSmrgVESADGAAddModes(ScrnInfoPtr pScrn)
176045bc899bSmrg{
176145bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
176245bc899bSmrg    DisplayModePtr pMode = pScrn->modes;
176345bc899bSmrg    DGAModePtr pDGAMode;
176445bc899bSmrg
176545bc899bSmrg    do {
176645bc899bSmrg	pDGAMode = xrealloc(pVesa->pDGAMode,
176745bc899bSmrg			    (pVesa->nDGAMode + 1) * sizeof(DGAModeRec));
176845bc899bSmrg	if (!pDGAMode)
176945bc899bSmrg	    break;
177045bc899bSmrg
177145bc899bSmrg	pVesa->pDGAMode = pDGAMode;
177245bc899bSmrg	pDGAMode += pVesa->nDGAMode;
177345bc899bSmrg	(void)memset(pDGAMode, 0, sizeof(DGAModeRec));
177445bc899bSmrg
177545bc899bSmrg	++pVesa->nDGAMode;
177645bc899bSmrg	pDGAMode->mode = pMode;
177745bc899bSmrg	pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
177845bc899bSmrg	pDGAMode->byteOrder = pScrn->imageByteOrder;
177945bc899bSmrg	pDGAMode->depth = pScrn->depth;
178045bc899bSmrg	pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
178145bc899bSmrg	pDGAMode->red_mask = pScrn->mask.red;
178245bc899bSmrg	pDGAMode->green_mask = pScrn->mask.green;
178345bc899bSmrg	pDGAMode->blue_mask = pScrn->mask.blue;
178445bc899bSmrg	pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
178545bc899bSmrg	    TrueColor : PseudoColor;
178645bc899bSmrg	pDGAMode->xViewportStep = 1;
178745bc899bSmrg	pDGAMode->yViewportStep = 1;
178845bc899bSmrg	pDGAMode->viewportWidth = pMode->HDisplay;
178945bc899bSmrg	pDGAMode->viewportHeight = pMode->VDisplay;
179045bc899bSmrg
179145bc899bSmrg	pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline;
179245bc899bSmrg	pDGAMode->imageWidth = pMode->HDisplay;
179345bc899bSmrg	pDGAMode->imageHeight =  pMode->VDisplay;
179445bc899bSmrg	pDGAMode->pixmapWidth = pDGAMode->imageWidth;
179545bc899bSmrg	pDGAMode->pixmapHeight = pDGAMode->imageHeight;
179645bc899bSmrg	pDGAMode->maxViewportX = pScrn->virtualX -
179745bc899bSmrg				    pDGAMode->viewportWidth;
179845bc899bSmrg	pDGAMode->maxViewportY = pScrn->virtualY -
179945bc899bSmrg				    pDGAMode->viewportHeight;
180045bc899bSmrg
180145bc899bSmrg	pDGAMode->address = pVesa->base;
180245bc899bSmrg
180345bc899bSmrg	pMode = pMode->next;
180445bc899bSmrg    } while (pMode != pScrn->modes);
180545bc899bSmrg}
180645bc899bSmrg
180745bc899bSmrgstatic Bool
180845bc899bSmrgVESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
180945bc899bSmrg{
181045bc899bSmrg    VESAPtr pVesa = VESAGetRec(pScrn);
181145bc899bSmrg
181245bc899bSmrg    if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L)
181345bc899bSmrg	return (FALSE);
181445bc899bSmrg
181545bc899bSmrg    if (!pVesa->nDGAMode)
181645bc899bSmrg	VESADGAAddModes(pScrn);
181745bc899bSmrg
181845bc899bSmrg    return (DGAInit(pScreen, &VESADGAFunctions,
181945bc899bSmrg	    pVesa->pDGAMode, pVesa->nDGAMode));
182045bc899bSmrg}
1821