vesa.c revision 78f6f648
1#define DEBUG_VERB 2
2/*
3 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
4 * Copyright 2008 Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Except as contained in this notice, the name of Conectiva Linux shall
25 * not be used in advertising or otherwise to promote the sale, use or other
26 * dealings in this Software without prior written authorization from
27 * Conectiva Linux.
28 *
29 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
30 *          David Dawes <dawes@xfree86.org>
31 *          Adam Jackson <ajax@redhat.com>
32 */
33
34/*
35 * TODO:
36 * - Port to RANDR 1.2 setup to make mode selection slightly better
37 * - Port to RANDR 1.2 to drop the old-school DGA junk
38 * - VBE/SCI for secondary DDC method?
39 */
40
41#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
44
45#include <string.h>
46#include <unistd.h>
47#include <dirent.h>
48#include "vesa.h"
49
50/* All drivers initialising the SW cursor need this */
51#include "mipointer.h"
52
53/* Colormap handling */
54#include "micmap.h"
55#include "xf86cmap.h"
56#include "xf86Modes.h"
57
58/* DPMS */
59#ifdef HAVE_XEXTPROTO_71
60#include <X11/extensions/dpmsconst.h>
61#else
62#define DPMS_SERVER
63#include <X11/extensions/dpms.h>
64#endif
65#include "compat-api.h"
66
67#if defined(__NetBSD__)
68#include <sys/sysctl.h>
69#endif
70
71/* Mandatory functions */
72static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid);
73static void VESAIdentify(int flags);
74#if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA)
75#define VESAProbe NULL
76#else
77static Bool VESAProbe(DriverPtr drv, int flags);
78#endif
79#ifdef XSERVER_LIBPCIACCESS
80static Bool VESAPciProbe(DriverPtr drv, int entity_num,
81     struct pci_device *dev, intptr_t match_data);
82#endif
83static Bool VESAPreInit(ScrnInfoPtr pScrn, int flags);
84static Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL);
85static Bool VESAEnterVT(VT_FUNC_ARGS_DECL);
86static void VESALeaveVT(VT_FUNC_ARGS_DECL);
87static Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL);
88static Bool VESASaveScreen(ScreenPtr pScreen, int mode);
89
90static Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL);
91static Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
92static void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL);
93static void VESAFreeScreen(FREE_SCREEN_ARGS_DECL);
94static void VESAFreeRec(ScrnInfoPtr pScrn);
95static VESAPtr VESAGetRec(ScrnInfoPtr pScrn);
96
97static void
98VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
99                int flags);
100
101/* locally used functions */
102#ifdef HAVE_ISA
103static int VESAFindIsaDevice(GDevPtr dev);
104#endif
105static Bool VESAMapVidMem(ScrnInfoPtr pScrn);
106static void VESAUnmapVidMem(ScrnInfoPtr pScrn);
107static int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank);
108static void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
109			    LOCO *colors, VisualPtr pVisual);
110static void SaveFonts(ScrnInfoPtr pScrn);
111static void RestoreFonts(ScrnInfoPtr pScrn);
112static Bool
113VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function);
114
115static void *
116VESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
117		 CARD32 *size, void *closure)
118{
119    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
120    VESAPtr pVesa = VESAGetRec(pScrn);
121
122    *size = pVesa->maxBytesPerScanline;
123    return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset);
124}
125
126static void *
127VESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
128		   CARD32 *size, void *closure)
129{
130    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
131    VESAPtr pVesa = VESAGetRec(pScrn);
132    VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
133    int window;
134
135    offset += pVesa->maxBytesPerScanline * row;
136    window = offset / (data->WinGranularity * 1024);
137    pVesa->windowAoffset = window * data->WinGranularity * 1024;
138    VESABankSwitch(pScreen, window);
139    *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset);
140
141    return (void *)((unsigned long)pVesa->base +
142		    (offset - pVesa->windowAoffset));
143}
144
145static void
146vesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
147{
148    shadowUpdatePacked(pScreen, pBuf);
149}
150
151static Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
152
153enum GenericTypes
154{
155    CHIP_VESA_GENERIC
156};
157
158#ifdef XSERVER_LIBPCIACCESS
159static const struct pci_id_match vesa_device_match[] = {
160    {
161	PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
162	0x00030000, 0x00ffffff, CHIP_VESA_GENERIC
163    },
164
165    { 0, 0, 0 },
166};
167#endif
168
169/* Supported chipsets */
170static SymTabRec VESAChipsets[] =
171{
172    {CHIP_VESA_GENERIC, "vesa"},
173    {-1,		 NULL}
174};
175
176#ifndef XSERVER_LIBPCIACCESS
177static PciChipsets VESAPCIchipsets[] = {
178  { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA },
179  { -1,		-1,	   RES_UNDEFINED },
180};
181#endif
182
183#ifdef HAVE_ISA
184static IsaChipsets VESAISAchipsets[] = {
185  {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA},
186  {-1,		0 }
187};
188#endif
189
190
191/*
192 * This contains the functions needed by the server after loading the
193 * driver module.  It must be supplied, and gets added the driver list by
194 * the Module Setup function in the dynamic case.  In the static case a
195 * reference to this is compiled in, and this requires that the name of
196 * this DriverRec be an upper-case version of the driver name.
197 */
198_X_EXPORT DriverRec VESA = {
199    VESA_VERSION,
200    VESA_DRIVER_NAME,
201    VESAIdentify,
202    VESAProbe,
203    VESAAvailableOptions,
204    NULL,
205    0,
206    NULL,
207
208#ifdef XSERVER_LIBPCIACCESS
209    vesa_device_match,
210    VESAPciProbe
211#endif
212};
213
214
215typedef enum {
216    OPTION_SHADOW_FB,
217    OPTION_DFLT_REFRESH,
218    OPTION_MODESET_CLEAR_SCREEN
219} VESAOpts;
220
221static const OptionInfoRec VESAOptions[] = {
222    { OPTION_SHADOW_FB,    "ShadowFB",		OPTV_BOOLEAN,	{0},	FALSE },
223    { OPTION_DFLT_REFRESH, "DefaultRefresh",	OPTV_BOOLEAN,	{0},	FALSE },
224    { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen",
225						OPTV_BOOLEAN,	{0},	FALSE },
226    { -1,		   NULL,		OPTV_NONE,	{0},	FALSE }
227};
228
229#ifdef XFree86LOADER
230
231/* Module loader interface */
232static MODULESETUPPROTO(vesaSetup);
233
234static XF86ModuleVersionInfo vesaVersionRec =
235{
236    VESA_DRIVER_NAME,
237    MODULEVENDORSTRING,
238    MODINFOSTRING1,
239    MODINFOSTRING2,
240    XORG_VERSION_CURRENT,
241    VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL,
242    ABI_CLASS_VIDEODRV,			/* This is a video driver */
243    ABI_VIDEODRV_VERSION,
244    MOD_CLASS_VIDEODRV,
245    {0, 0, 0, 0}
246};
247
248/*
249 * This data is accessed by the loader.  The name must be the module name
250 * followed by "ModuleData".
251 */
252_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL };
253
254static pointer
255vesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
256{
257    static Bool Initialised = FALSE;
258
259    if (!Initialised)
260    {
261	Initialised = TRUE;
262	xf86AddDriver(&VESA, Module, 1);
263	return (pointer)TRUE;
264    }
265
266    if (ErrorMajor)
267	*ErrorMajor = LDR_ONCEONLY;
268    return (NULL);
269}
270
271#endif
272
273static const OptionInfoRec *
274VESAAvailableOptions(int chipid, int busid)
275{
276    return (VESAOptions);
277}
278
279static void
280VESAIdentify(int flags)
281{
282    xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
283}
284
285static VESAPtr
286VESAGetRec(ScrnInfoPtr pScrn)
287{
288    if (!pScrn->driverPrivate)
289	pScrn->driverPrivate = calloc(sizeof(VESARec), 1);
290
291    return ((VESAPtr)pScrn->driverPrivate);
292}
293
294/* Only a little like VBESetModeParameters */
295static void
296VESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode,
297		      DisplayModePtr ddcmode)
298{
299    VbeModeInfoData *data;
300    int clock;
301
302    data = (VbeModeInfoData *)vbemode->Private;
303
304    data->block = calloc(sizeof(VbeCRTCInfoBlock), 1);
305    data->block->HorizontalTotal = ddcmode->HTotal;
306    data->block->HorizontalSyncStart = ddcmode->HSyncStart;
307    data->block->HorizontalSyncEnd = ddcmode->HSyncEnd;
308    data->block->VerticalTotal = ddcmode->VTotal;
309    data->block->VerticalSyncStart = ddcmode->VSyncStart;
310    data->block->VerticalSyncEnd = ddcmode->VSyncEnd;
311    data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
312	                 ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
313    data->block->PixelClock = ddcmode->Clock * 1000;
314
315    /* ask the BIOS to figure out the real clock */
316    clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
317    if (clock)
318	data->block->PixelClock = clock;
319
320    data->mode |= (1 << 11);
321    data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) /
322				(double)(ddcmode->HTotal * ddcmode->VTotal));
323}
324
325/*
326 * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes
327 * think they can only give sizes in multiples of character cells; and
328 * indeed, the reference CVT and GTF formulae only give results where
329 * (h % 8) == 0.  Whatever, let's just try to cope.  What we're looking for
330 * here is cases where the display says 1366x768 and the BIOS says 1360x768.
331 */
332static Bool
333vesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe)
334{
335    if (!(edid->type & M_T_DRIVER))
336	return FALSE;
337
338    /* never seen a height granularity... */
339    if (edid->VDisplay != vbe->VDisplay)
340	return FALSE;
341
342    if (edid->HDisplay >= vbe->HDisplay &&
343	(edid->HDisplay & ~7) == (vbe->HDisplay & ~7))
344	return TRUE;
345
346    return FALSE;
347}
348
349static ModeStatus
350VESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass)
351{
352    SCRN_INFO_PTR(arg);
353    static int warned = 0;
354    int found = 0;
355    VESAPtr pVesa = VESAGetRec(pScrn);
356    MonPtr mon = pScrn->monitor;
357    ModeStatus ret = MODE_BAD;
358    DisplayModePtr mode;
359    float v;
360
361    if (pass != MODECHECK_FINAL) {
362	if (!warned) {
363	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n");
364	    warned = 1;
365	}
366	return MODE_OK;
367    }
368
369    /*
370     * This is suboptimal.  We pass in just the barest description of a mode
371     * we can get away with to VBEValidateModes, so it can't really throw
372     * out anything we give it.  But we need to filter the list so that we
373     * don't populate the mode list with things the monitor can't do.
374     *
375     * So first off, if this isn't a mode we handed to the server (ie,
376     * M_T_BUILTIN), then we know we can't do it.
377     */
378    if (!(p->type & M_T_BUILTIN))
379	return MODE_NOMODE;
380
381    if (pVesa->strict_validation) {
382	/*
383	 * If it's our first pass at mode validation, we'll try for a strict
384	 * intersection between the VBE and DDC mode lists.
385	 */
386	if (pScrn->monitor->DDC) {
387	    for (mode = pScrn->monitor->Modes; mode; mode = mode->next) {
388		if (vesaModesCloseEnough(mode, p)) {
389		    if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) {
390			found = 1;
391			break;
392		    }
393		}
394		if (mode == pScrn->monitor->Last)
395		    break;
396	    }
397	    if (!found)
398		return MODE_NOMODE;
399
400	    /* having found a matching mode, stash the CRTC values aside */
401	    VESASetModeParameters(pVesa->pVbe, p, mode);
402	    return MODE_OK;
403	}
404
405	/* No DDC and no modes make Homer something something... */
406	return MODE_NOMODE;
407    }
408
409    /*
410     * Finally, walk through the vsync rates 1Hz at a time looking for a mode
411     * that will fit.  This is assuredly a terrible way to do this, but
412     * there's no obvious method for computing a mode of a given size that
413     * will pass xf86CheckModeForMonitor.  XXX this path is terrible, but
414     * then, by this point, you're well into despair territory.
415     */
416    for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
417	mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0);
418	ret = xf86CheckModeForMonitor(mode, mon);
419	free(mode->name);
420	free(mode);
421	if (ret == MODE_OK)
422	    break;
423    }
424
425    return ret;
426}
427
428static void
429VESAInitScrn(ScrnInfoPtr pScrn)
430{
431    pScrn->driverVersion = VESA_VERSION;
432    pScrn->driverName    = VESA_DRIVER_NAME;
433    pScrn->name		 = VESA_NAME;
434    pScrn->Probe	 = VESAProbe;
435    pScrn->PreInit       = VESAPreInit;
436    pScrn->ScreenInit    = VESAScreenInit;
437    pScrn->SwitchMode    = VESASwitchMode;
438    pScrn->ValidMode     = VESAValidMode;
439    pScrn->AdjustFrame   = VESAAdjustFrame;
440    pScrn->EnterVT       = VESAEnterVT;
441    pScrn->LeaveVT       = VESALeaveVT;
442    pScrn->FreeScreen    = VESAFreeScreen;
443}
444
445#ifdef XSERVER_LIBPCIACCESS
446#ifdef __linux__
447/*
448 * check if a file exist in directory
449 * should be equivalent to a glob ${directory}/${prefix}*
450 */
451
452static Bool
453VESAFileExistsPrefix(const char *directory, const char *prefix) {
454    DIR *dir;
455    struct dirent *entry;
456    Bool found = FALSE;
457    int len = strlen(prefix);
458
459    dir = opendir(directory);
460    if (!dir)
461        return FALSE;
462
463    while ((entry = readdir(dir)) != NULL) {
464        if (strlen(entry->d_name) > len &&
465            !memcmp(entry->d_name, prefix, len)) {
466            found = TRUE;
467            break;
468        }
469    }
470    closedir(dir);
471    return found;
472}
473#endif
474
475/*
476 * This function is called once, at the start of the first server generation to
477 * do a minimal probe for supported hardware.
478 */
479static Bool
480VESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
481	     intptr_t match_data)
482{
483    ScrnInfoPtr pScrn;
484
485#ifdef __linux__
486    if (VESAFileExistsPrefix("/dev", "fb") ||
487        VESAFileExistsPrefix("/dev/dri", "card")) {
488        ErrorF("vesa: Refusing to run, Framebuffer or dri device present\n");
489        return FALSE;
490    }
491#endif
492#if defined(__NetBSD__)
493    {
494	char method[10];
495	size_t len = sizeof(method);
496
497        if (sysctlbyname("machdep.bootmethod", &method, &len, NULL, 0) == 0 &&
498	    strcmp(method, "UEFI") == 0) {
499            ErrorF("vesa: Refusing to run, UEFI booted\n");
500            return FALSE;
501        }
502    }
503#endif
504
505    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL,
506				NULL, NULL, NULL, NULL, NULL);
507    if (pScrn != NULL) {
508	VESAPtr pVesa;
509
510	if (pci_device_has_kernel_driver(dev)) {
511	    ErrorF("vesa: Ignoring device with a bound kernel driver\n");
512	    return FALSE;
513	}
514
515	pVesa = VESAGetRec(pScrn);
516	VESAInitScrn(pScrn);
517	pVesa->pciInfo = dev;
518    }
519
520    return (pScrn != NULL);
521}
522#endif
523
524#ifndef VESAProbe
525static Bool
526VESAProbe(DriverPtr drv, int flags)
527{
528    Bool foundScreen = FALSE;
529    int numDevSections, numUsed;
530    GDevPtr *devSections;
531    int *usedChips;
532    int i;
533
534    /*
535     * Find the config file Device sections that match this
536     * driver, and return if there are none.
537     */
538    if ((numDevSections = xf86MatchDevice(VESA_NAME,
539					  &devSections)) <= 0)
540	return (FALSE);
541
542#ifndef XSERVER_LIBPCIACCESS
543    /* PCI BUS */
544    if (xf86GetPciVideoInfo()) {
545	numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC,
546					VESAChipsets, VESAPCIchipsets,
547					devSections, numDevSections,
548					drv, &usedChips);
549	if (numUsed > 0) {
550	    if (flags & PROBE_DETECT)
551		foundScreen = TRUE;
552	    else {
553		for (i = 0; i < numUsed; i++) {
554		    ScrnInfoPtr pScrn = NULL;
555		    /* Allocate a ScrnInfoRec  */
556		    if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
557						     VESAPCIchipsets,NULL,
558						     NULL,NULL,NULL,NULL))) {
559			VESAInitScrn(pScrn);
560			foundScreen = TRUE;
561		    }
562		}
563	    }
564	    free(usedChips);
565	}
566    }
567#endif
568
569#ifdef HAVE_ISA
570    /* Isa Bus */
571    numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets,
572				    VESAISAchipsets, drv,
573				    VESAFindIsaDevice, devSections,
574				    numDevSections, &usedChips);
575    if(numUsed > 0) {
576	if (flags & PROBE_DETECT)
577	    foundScreen = TRUE;
578	else for (i = 0; i < numUsed; i++) {
579	    ScrnInfoPtr pScrn = NULL;
580	    if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i],
581					     VESAISAchipsets, NULL,
582					     NULL, NULL, NULL, NULL))) {
583		VESAInitScrn(pScrn);
584		foundScreen = TRUE;
585	    }
586	}
587	free(usedChips);
588    }
589#endif
590
591    free(devSections);
592
593    return (foundScreen);
594}
595#endif
596
597#ifdef HAVE_ISA
598static int
599VESAFindIsaDevice(GDevPtr dev)
600{
601#ifndef PC98_EGC
602    CARD16 GenericIOBase = VGAHW_GET_IOBASE();
603    CARD8 CurrentValue, TestValue;
604
605    /* There's no need to unlock VGA CRTC registers here */
606
607    /* VGA has one more read/write attribute register than EGA */
608    (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET);  /* Reset flip-flop */
609    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
610    CurrentValue = inb(VGA_ATTR_DATA_R);
611    outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
612    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
613    TestValue = inb(VGA_ATTR_DATA_R);
614    outb(VGA_ATTR_DATA_R, CurrentValue);
615
616    /* Quit now if no VGA is present */
617    if ((CurrentValue ^ 0x0F) != TestValue)
618      return -1;
619#endif
620    return (int)CHIP_VESA_GENERIC;
621}
622#endif
623
624static void
625VESAFreeRec(ScrnInfoPtr pScrn)
626{
627    VESAPtr pVesa = VESAGetRec(pScrn);
628#if 0
629    DisplayModePtr mode = pScrn->modes;
630    /* I am not sure if the modes will ever get freed.
631     * Anyway, the data unknown to other modules is being freed here.
632     */
633    if (mode) {
634	do {
635	    if (mode->Private) {
636		VbeModeInfoData *data = (VbeModeInfoData*)mode->Private;
637
638		if (data->block)
639		    free(data->block);
640
641		free(data);
642
643		mode->Private = NULL;
644	    }
645	    mode = mode->next;
646	} while (mode && mode != pScrn->modes);
647    }
648#endif
649    free(pVesa->monitor);
650    if (pVesa->vbeInfo)
651	VBEFreeVBEInfo(pVesa->vbeInfo);
652    free(pVesa->pal);
653    free(pVesa->savedPal);
654    free(pVesa->fonts);
655    free(pScrn->driverPrivate);
656    pScrn->driverPrivate = NULL;
657}
658
659static int
660VESAValidateModes(ScrnInfoPtr pScrn)
661{
662    VESAPtr pVesa = VESAGetRec(pScrn);
663    DisplayModePtr mode;
664
665    for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
666	mode->status = MODE_OK;
667
668    return VBEValidateModes(pScrn, NULL, pScrn->display->modes,
669			    NULL, NULL, 0, 32767, 1, 0, 32767,
670			    pScrn->display->virtualX,
671			    pScrn->display->virtualY,
672			    pVesa->mapSize, LOOKUP_BEST_REFRESH);
673}
674
675/*
676 * This function is called once for each screen at the start of the first
677 * server generation to initialise the screen for all server generations.
678 */
679static Bool
680VESAPreInit(ScrnInfoPtr pScrn, int flags)
681{
682    VESAPtr pVesa;
683    VbeInfoBlock *vbe;
684    DisplayModePtr pMode;
685    VbeModeInfoBlock *mode;
686    Gamma gzeros = {0.0, 0.0, 0.0};
687    rgb rzeros = {0, 0, 0};
688    pointer pDDCModule;
689    int i;
690    int flags24 = 0;
691    int defaultDepth = 0;
692    int defaultBpp = 0;
693    int depths = 0;
694
695    if (flags & PROBE_DETECT)
696	return (FALSE);
697
698    pVesa = VESAGetRec(pScrn);
699    pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
700
701    /* Load vbe module */
702    if (!xf86LoadSubModule(pScrn, "vbe"))
703        return (FALSE);
704
705    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
706				       SET_BIOS_SCRATCH
707				       | RESTORE_BIOS_SCRATCH)) == NULL)
708        return (FALSE);
709
710#ifndef XSERVER_LIBPCIACCESS
711    if (pVesa->pEnt->location.type == BUS_PCI) {
712	pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index);
713	pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device,
714			       pVesa->pciInfo->func);
715    }
716#endif
717
718    pScrn->chipset = "vesa";
719    pScrn->monitor = pScrn->confScreen->monitor;
720    pScrn->progClock = TRUE;
721    pScrn->rgbBits = 8;
722
723    if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL)
724	return (FALSE);
725    pVesa->major = (unsigned)(vbe->VESAVersion >> 8);
726    pVesa->minor = vbe->VESAVersion & 0xff;
727    pVesa->vbeInfo = vbe;
728    pScrn->videoRam = vbe->TotalMemory * 64;
729
730    /*
731     * Find what depths are available.
732     */
733    depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24,
734				    V_MODETYPE_VBE);
735
736    /* Preferred order for default depth selection. */
737    if (depths & V_DEPTH_24 && (flags24 & Support32bppFb))
738	defaultDepth = 24;
739    else if (depths & V_DEPTH_16)
740	defaultDepth = 16;
741    else if (depths & V_DEPTH_15)
742	defaultDepth = 15;
743    else if (depths & V_DEPTH_24)
744        defaultDepth = 24; /* ew though */
745    else if (depths & V_DEPTH_8)
746	defaultDepth = 8;
747    else if (depths & V_DEPTH_4)
748	defaultDepth = 4;
749    else if (depths & V_DEPTH_1)
750	defaultDepth = 1;
751
752    if (defaultDepth == 24 && !(flags24 & Support32bppFb))
753	defaultBpp = 24;
754
755    /* Prefer 32bpp because 1999 called and wants its packed pixels back */
756    if (flags24 & Support32bppFb)
757	flags24 |= SupportConvert24to32 | PreferConvert24to32;
758    if (flags24 & Support24bppFb)
759	flags24 |= SupportConvert32to24;
760
761    if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) {
762        vbeFree(pVesa->pVbe);
763	return (FALSE);
764    }
765    xf86PrintDepthBpp(pScrn);
766
767    /* color weight */
768    if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) {
769        vbeFree(pVesa->pVbe);
770	return (FALSE);
771    }
772    /* visual init */
773    if (!xf86SetDefaultVisual(pScrn, -1)) {
774        vbeFree(pVesa->pVbe);
775	return (FALSE);
776    }
777
778    xf86SetGamma(pScrn, gzeros);
779
780    /* set up options before loading any modules that may look at them */
781    xf86CollectOptions(pScrn, NULL);
782
783    if (pVesa->major >= 2) {
784	/* Load ddc module */
785	if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
786	    vbeFree(pVesa->pVbe);
787	    return (FALSE);
788	}
789
790	if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) {
791	    xf86PrintEDID(pVesa->monitor);
792	}
793
794	xf86UnloadSubModule(pDDCModule);
795    }
796
797    if ((pScrn->monitor->DDC = pVesa->monitor) != NULL)
798	xf86SetDDCproperties(pScrn, pVesa->monitor);
799    else {
800	void *panelid = VBEReadPanelID(pVesa->pVbe);
801	VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid);
802	free(panelid);
803    }
804
805    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
806			"Searching for matching VESA mode(s):\n");
807
808    /*
809     * Check the available BIOS modes, and extract those that match the
810     * requirements into the modePool.  Note: modePool is a NULL-terminated
811     * list.
812     */
813    pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo,
814				      V_MODETYPE_VBE);
815
816    xf86ErrorFVerb(DEBUG_VERB, "\n");
817    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
818		   "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory,
819		   (vbe->TotalMemory * 65536) / 1024);
820
821    pVesa->mapSize = vbe->TotalMemory * 65536;
822    if (pScrn->modePool == NULL) {
823	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n");
824        vbeFree(pVesa->pVbe);
825	return (FALSE);
826    }
827
828    VBESetModeNames(pScrn->modePool);
829
830    pVesa->strict_validation = TRUE;
831    i = VESAValidateModes(pScrn);
832
833    if (i <= 0) {
834	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
835		"No valid modes left. Trying less strict filter...\n");
836	pVesa->strict_validation = FALSE;
837	i = VESAValidateModes(pScrn);
838    }
839
840    if (i <= 0) do {
841	Bool changed = FALSE;
842	/* maybe there's more modes at the bottom... */
843	if (pScrn->monitor->vrefresh[0].lo > 50) {
844	    changed = TRUE;
845	    pScrn->monitor->vrefresh[0].lo = 50;
846	}
847	if (pScrn->monitor->hsync[0].lo > 31.5) {
848	    changed = TRUE;
849	    pScrn->monitor->hsync[0].lo = 31.5;
850	}
851
852	if (!changed)
853	    break;
854
855	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
856		   "No valid modes left. Trying aggressive sync range...\n");
857	i = VESAValidateModes(pScrn);
858    } while (0);
859
860    if (i <= 0) {
861	/* alright, i'm out of ideas */
862	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n");
863        vbeFree(pVesa->pVbe);
864	return (FALSE);
865    }
866
867    xf86PruneDriverModes(pScrn);
868
869    pMode = pScrn->modes;
870    do {
871	mode = ((VbeModeInfoData*)pMode->Private)->data;
872	if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) {
873	    pVesa->maxBytesPerScanline = mode->BytesPerScanline;
874	}
875	pMode = pMode->next;
876    } while (pMode != pScrn->modes);
877
878    pScrn->currentMode = pScrn->modes;
879    pScrn->displayWidth = pScrn->virtualX;
880
881    VBEPrintModes(pScrn);
882
883    /* Set display resolution */
884    xf86SetDpi(pScrn, 0, 0);
885
886    if (pScrn->modes == NULL) {
887	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
888        vbeFree(pVesa->pVbe);
889	return (FALSE);
890    }
891
892    /* options */
893    if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) {
894        vbeFree(pVesa->pVbe);
895	return FALSE;
896    }
897    memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions));
898    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options);
899
900    /* Use shadow by default, for non-virt hardware */
901    if (!xf86GetOptValBool(pVesa->Options, OPTION_SHADOW_FB, &pVesa->shadowFB))
902    {
903	switch (pVesa->pciInfo->vendor_id) {
904	    case 0x1234: /* bochs vga (not in pci.ids) */
905	    case 0x15ad: /* vmware */
906	    case 0x1b36: /* qemu qxl */
907	    case 0x80ee: /* virtualbox */
908	    case 0xaaaa: /* parallels (not in pci.ids) */
909		pVesa->shadowFB = FALSE;
910		break;
911
912	    case 0x1013: /* qemu's cirrus emulation */
913		if (pVesa->pciInfo->subvendor_id == 0x1af4)
914		    pVesa->shadowFB = FALSE;
915		else
916		    pVesa->shadowFB = TRUE;
917		break;
918
919	    case 0x1414: /* microsoft hyper-v */
920		if (pVesa->pciInfo->device_id == 0x5353)
921		    pVesa->shadowFB = FALSE;
922		else
923		    pVesa->shadowFB = TRUE;
924		break;
925
926	    default:
927		pVesa->shadowFB = TRUE;
928		break;
929	}
930    }
931
932    /*  Use default refresh by default. Too many VBE 3.0
933     *   BIOSes are incorrectly implemented.
934     */
935    pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options,
936                                                 OPTION_DFLT_REFRESH, TRUE);
937
938    pVesa->ModeSetClearScreen =
939        xf86ReturnOptValBool(pVesa->Options,
940                             OPTION_MODESET_CLEAR_SCREEN, FALSE);
941
942    if (!pVesa->defaultRefresh && !pVesa->strict_validation)
943	VBESetModeParameters(pScrn, pVesa->pVbe);
944
945    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
946    switch (mode->MemoryModel) {
947	case 0x4:	/* Packed pixel */
948	case 0x6:	/* Direct Color */
949	    pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
950
951	    switch (pScrn->bitsPerPixel) {
952		case 8:
953		case 16:
954		case 24:
955		case 32:
956		    break;
957		default:
958		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
959			       "Unsupported bpp: %d\n", pScrn->bitsPerPixel);
960		    vbeFree(pVesa->pVbe);
961		    return FALSE;
962	    }
963	    break;
964	default:
965	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
966		       "Unsupported Memory Model: %d\n", mode->MemoryModel);
967	    return FALSE;
968    }
969
970    if (pVesa->shadowFB) {
971	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n");
972	if (!xf86LoadSubModule(pScrn, "shadow")) {
973	    vbeFree(pVesa->pVbe);
974	    return (FALSE);
975	}
976    }
977
978    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
979	VESAFreeRec(pScrn);
980        vbeFree(pVesa->pVbe);
981	return (FALSE);
982    }
983
984    vbeFree(pVesa->pVbe);
985
986    return (TRUE);
987}
988
989static Bool
990vesaCreateScreenResources(ScreenPtr pScreen)
991{
992    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
993    VESAPtr pVesa = VESAGetRec(pScrn);
994    Bool ret;
995
996    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
997    ret = pScreen->CreateScreenResources(pScreen);
998    pScreen->CreateScreenResources = vesaCreateScreenResources;
999
1000    shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update,
1001	      pVesa->window, 0, 0);
1002
1003    return ret;
1004}
1005
1006static void
1007vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable)
1008{
1009    SCRN_INFO_PTR(arg);
1010    VESAPtr pVesa = VESAGetRec(pScrn);
1011
1012    pVesa->accessEnabled = enable;
1013    pVesa->EnableDisableFBAccess(arg, enable);
1014}
1015
1016static Bool
1017VESAScreenInit(SCREEN_INIT_ARGS_DECL)
1018{
1019    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1020    VESAPtr pVesa = VESAGetRec(pScrn);
1021    VisualPtr visual;
1022    VbeModeInfoBlock *mode;
1023    int flags;
1024
1025    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
1026				       SET_BIOS_SCRATCH
1027				       | RESTORE_BIOS_SCRATCH)) == NULL)
1028        return (FALSE);
1029
1030    if (pVesa->mapPhys == 0) {
1031	mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
1032	pScrn->videoRam = pVesa->mapSize;
1033	pVesa->mapPhys = mode->PhysBasePtr;
1034	pVesa->mapOff = 0;
1035    }
1036
1037    if (pVesa->mapPhys == 0) {
1038	pVesa->mapPhys = 0xa0000;
1039	pVesa->mapSize = 0x10000;
1040    }
1041
1042    if (!VESAMapVidMem(pScrn)) {
1043	if (pVesa->mapPhys != 0xa0000) {
1044	    pVesa->mapPhys = 0xa0000;
1045	    pVesa->mapSize = 0x10000;
1046	    if (!VESAMapVidMem(pScrn))
1047		return (FALSE);
1048	}
1049	else
1050	    return (FALSE);
1051    }
1052
1053    /* Set bpp to 8 for depth 4 when using shadowfb. */
1054    if (pVesa->shadowFB && pScrn->bitsPerPixel == 4)
1055	pScrn->bitsPerPixel = 8;
1056
1057    if (pVesa->shadowFB) {
1058	pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY *
1059				   ((pScrn->bitsPerPixel + 7) / 8));
1060	if (!pVesa->shadow) {
1061	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1062		       "Failed to allocate shadow buffer\n");
1063	    return FALSE;
1064	}
1065    }
1066
1067    /* save current video state */
1068    VESASaveRestore(pScrn, MODE_SAVE);
1069    pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256,
1070					    NULL, FALSE, FALSE);
1071
1072    /* set first video mode */
1073    if (!VESASetMode(pScrn, pScrn->currentMode))
1074	return (FALSE);
1075
1076    /* set the viewport */
1077    VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1078
1079    /* Blank the screen for aesthetic reasons. */
1080    VESASaveScreen(pScreen, SCREEN_SAVER_ON);
1081
1082    /* mi layer */
1083    miClearVisualTypes();
1084    if (!xf86SetDefaultVisual(pScrn, -1))
1085	return (FALSE);
1086    if (pScrn->bitsPerPixel > 8) {
1087	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1088			      pScrn->rgbBits, TrueColor))
1089	    return (FALSE);
1090    }
1091    else {
1092	if (!miSetVisualTypes(pScrn->depth,
1093			      miGetDefaultVisualMask(pScrn->depth),
1094			      pScrn->rgbBits, pScrn->defaultVisual))
1095	    return (FALSE);
1096    }
1097    if (!miSetPixmapDepths())
1098	return (FALSE);
1099
1100    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
1101    switch (mode->MemoryModel) {
1102	case 0x4:	/* Packed pixel */
1103	case 0x6:	/* Direct Color */
1104	    switch (pScrn->bitsPerPixel) {
1105		case 8:
1106		case 16:
1107		case 24:
1108		case 32:
1109		    if (!fbScreenInit(pScreen,
1110				pVesa->shadowFB ? pVesa->shadow : pVesa->base,
1111				       pScrn->virtualX, pScrn->virtualY,
1112				       pScrn->xDpi, pScrn->yDpi,
1113				       pScrn->displayWidth, pScrn->bitsPerPixel))
1114			return (FALSE);
1115		    break;
1116		default:
1117		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1118			       "Unsupported bpp: %d", pScrn->bitsPerPixel);
1119		    return (FALSE);
1120	    }
1121	    break;
1122	default:
1123	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1124		       "Unsupported Memory Model: %d", mode->MemoryModel);
1125	    return (FALSE);
1126    }
1127
1128
1129    if (pScrn->bitsPerPixel > 8) {
1130	/* Fixup RGB ordering */
1131	visual = pScreen->visuals + pScreen->numVisuals;
1132	while (--visual >= pScreen->visuals) {
1133	    if ((visual->class | DynamicClass) == DirectColor) {
1134		visual->offsetRed   = pScrn->offset.red;
1135		visual->offsetGreen = pScrn->offset.green;
1136		visual->offsetBlue  = pScrn->offset.blue;
1137		visual->redMask     = pScrn->mask.red;
1138		visual->greenMask   = pScrn->mask.green;
1139		visual->blueMask    = pScrn->mask.blue;
1140	    }
1141	}
1142    }
1143
1144    /* must be after RGB ordering fixed */
1145    fbPictureInit(pScreen, 0, 0);
1146
1147    if (pVesa->shadowFB) {
1148	if (pVesa->mapPhys == 0xa0000) {	/* Windowed */
1149	    pVesa->update = vesaUpdatePacked;
1150	    pVesa->window = VESAWindowWindowed;
1151	}
1152	else {	/* Linear */
1153	    pVesa->update = vesaUpdatePacked;
1154	    pVesa->window = VESAWindowLinear;
1155	}
1156
1157	if (!shadowSetup(pScreen))
1158	    return FALSE;
1159	pVesa->CreateScreenResources = pScreen->CreateScreenResources;
1160	pScreen->CreateScreenResources = vesaCreateScreenResources;
1161    }
1162    else if (pVesa->mapPhys == 0xa0000) {
1163        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1164                   "Banked framebuffer requires ShadowFB\n");
1165        return FALSE;
1166    }
1167
1168    VESADGAInit(pScrn, pScreen);
1169
1170    xf86SetBlackWhitePixels(pScreen);
1171    xf86SetBackingStore(pScreen);
1172
1173    /* software cursor */
1174    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1175
1176    /* colormap */
1177    if (!miCreateDefColormap(pScreen))
1178	return (FALSE);
1179
1180    flags = CMAP_RELOAD_ON_MODE_SWITCH;
1181
1182    if(!xf86HandleColormaps(pScreen, 256,
1183	pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6,
1184	VESALoadPalette, NULL, flags))
1185	return (FALSE);
1186
1187    pVesa->accessEnabled = TRUE;
1188    pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
1189    pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess;
1190
1191    pVesa->CloseScreen = pScreen->CloseScreen;
1192    pScreen->CloseScreen = VESACloseScreen;
1193    pScreen->SaveScreen = VESASaveScreen;
1194
1195    xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0);
1196
1197    /* Report any unused options (only for the first generation) */
1198    if (serverGeneration == 1)
1199        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1200
1201    return (TRUE);
1202}
1203
1204static Bool
1205VESAEnterVT(VT_FUNC_ARGS_DECL)
1206{
1207    SCRN_INFO_PTR(arg);
1208
1209    if (!VESASetMode(pScrn, pScrn->currentMode))
1210	return FALSE;
1211    VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1212    return TRUE;
1213}
1214
1215static void
1216VESALeaveVT(VT_FUNC_ARGS_DECL)
1217{
1218    SCRN_INFO_PTR(arg);
1219    VESASaveRestore(pScrn, MODE_RESTORE);
1220}
1221
1222static Bool
1223VESACloseScreen(CLOSE_SCREEN_ARGS_DECL)
1224{
1225    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1226    VESAPtr pVesa = VESAGetRec(pScrn);
1227
1228    if (pScrn->vtSema) {
1229	VESASaveRestore(pScrn, MODE_RESTORE);
1230	if (pVesa->savedPal)
1231	    VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256,
1232				 pVesa->savedPal, FALSE, TRUE);
1233	VESAUnmapVidMem(pScrn);
1234    }
1235    if (pVesa->shadowFB && pVesa->shadow) {
1236	shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
1237	free(pVesa->shadow);
1238    }
1239    if (pVesa->pDGAMode) {
1240	free(pVesa->pDGAMode);
1241	pVesa->pDGAMode = NULL;
1242	pVesa->nDGAMode = 0;
1243    }
1244    pScrn->vtSema = FALSE;
1245
1246    pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess;
1247    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
1248    pScreen->CloseScreen = pVesa->CloseScreen;
1249    return pScreen->CloseScreen(CLOSE_SCREEN_ARGS);
1250}
1251
1252static Bool
1253VESASwitchMode(SWITCH_MODE_ARGS_DECL)
1254{
1255    SCRN_INFO_PTR(arg);
1256    VESAPtr pVesa = VESAGetRec(pScrn);
1257    Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled;
1258
1259    if (disableAccess)
1260        pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE);
1261    ret = VESASetMode(pScrn, mode);
1262    if (disableAccess)
1263	pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE);
1264    return ret;
1265}
1266
1267/* Set a graphics mode */
1268static Bool
1269VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1270{
1271    VESAPtr pVesa;
1272    VbeModeInfoData *data;
1273    int mode;
1274
1275    pVesa = VESAGetRec(pScrn);
1276
1277    data = (VbeModeInfoData*)pMode->Private;
1278
1279    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1280	       "Setting up VESA Mode 0x%X (%dx%d)\n",
1281	       data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay);
1282
1283    /* careful, setting the bit means don't clear the screen */
1284    mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15));
1285
1286    /* enable linear addressing */
1287    if (pVesa->mapPhys != 0xa0000)
1288	mode |= 1 << 14;
1289
1290    if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) {
1291	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed");
1292	if ((data->block || (data->mode & (1 << 11))) &&
1293	    VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) {
1294	    /* Some cards do not like setting the clock.
1295	     * Free it as it will not be any longer useful
1296	     */
1297	    xf86ErrorF(", mode set without customized refresh.\n");
1298	    free(data->block);
1299	    data->block = NULL;
1300	    data->mode &= ~(1 << 11);
1301	}
1302	else {
1303	    ErrorF("\n");
1304	    return (FALSE);
1305	}
1306    }
1307
1308    pVesa->bankSwitchWindowB =
1309	!((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0));
1310
1311    if (data->data->XResolution != pScrn->displayWidth)
1312	VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth);
1313
1314    if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 &&
1315        !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7))
1316	VBESetGetDACPaletteFormat(pVesa->pVbe, 8);
1317
1318    pScrn->vtSema = TRUE;
1319
1320    return (TRUE);
1321}
1322
1323static void
1324VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
1325{
1326    SCRN_INFO_PTR(arg);
1327    VESAPtr pVesa = VESAGetRec(pScrn);
1328
1329    VBESetDisplayStart(pVesa->pVbe, x, y, TRUE);
1330}
1331
1332static void
1333VESAFreeScreen(FREE_SCREEN_ARGS_DECL)
1334{
1335    SCRN_INFO_PTR(arg);
1336    VESAFreeRec(pScrn);
1337}
1338
1339static Bool
1340VESAMapVidMem(ScrnInfoPtr pScrn)
1341{
1342    VESAPtr pVesa = VESAGetRec(pScrn);
1343
1344    if (pVesa->base != NULL)
1345	return (TRUE);
1346
1347    pScrn->memPhysBase = pVesa->mapPhys;
1348    pScrn->fbOffset = pVesa->mapOff;
1349
1350#ifdef XSERVER_LIBPCIACCESS
1351    if (pVesa->pciInfo != NULL) {
1352	if (pVesa->mapPhys != 0xa0000) {
1353	    (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase,
1354	                                pVesa->mapSize,
1355				        (PCI_DEV_MAP_FLAG_WRITABLE
1356				         | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
1357				        & pVesa->base);
1358
1359	    if (pVesa->base)
1360		(void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000,
1361		                             PCI_DEV_MAP_FLAG_WRITABLE,
1362		                             & pVesa->VGAbase);
1363	}
1364	else {
1365	    (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase,
1366	                                 pVesa->mapSize,
1367	                                 PCI_DEV_MAP_FLAG_WRITABLE,
1368	                                 & pVesa->base);
1369
1370	    if (pVesa->base)
1371		pVesa->VGAbase = pVesa->base;
1372	}
1373    }
1374#else
1375    if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI)
1376	pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1377				    pVesa->pciTag, pScrn->memPhysBase,
1378				    pVesa->mapSize);
1379    else
1380	pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag,
1381					  pScrn->memPhysBase, pVesa->mapSize);
1382
1383    if (pVesa->base) {
1384	if (pVesa->mapPhys != 0xa0000)
1385	    pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
1386						 pVesa->pciTag,
1387						 0xa0000, 0x10000);
1388	else
1389	    pVesa->VGAbase = pVesa->base;
1390    }
1391#endif
1392
1393#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1394    pVesa->ioBase = pScrn->domainIOBase;
1395#else
1396    pVesa->ioBase = 0;
1397#endif
1398
1399    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
1400		   "virtual address = %p, VGAbase = %p\n"
1401		   "\tphysical address = 0x%lx, size = %ld\n",
1402		   pVesa->base, pVesa->VGAbase,
1403		   pScrn->memPhysBase, pVesa->mapSize);
1404
1405    return (pVesa->base != NULL);
1406}
1407
1408static void
1409VESAUnmapVidMem(ScrnInfoPtr pScrn)
1410{
1411    VESAPtr pVesa = VESAGetRec(pScrn);
1412
1413    if (pVesa->base == NULL)
1414	return;
1415
1416#ifdef XSERVER_LIBPCIACCESS
1417    if (pVesa->mapPhys != 0xa0000) {
1418	(void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base,
1419				      pVesa->mapSize);
1420	(void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase,
1421	                               0x10000);
1422    }
1423    else {
1424	(void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base,
1425	                               pVesa->mapSize);
1426    }
1427#else
1428    xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize);
1429    if (pVesa->mapPhys != 0xa0000)
1430	xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000);
1431#endif
1432    pVesa->base = NULL;
1433}
1434
1435/* This code works, but is very slow for programs that use it intensively */
1436static void
1437VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1438		LOCO *colors, VisualPtr pVisual)
1439{
1440    VESAPtr pVesa = VESAGetRec(pScrn);
1441    int i, idx;
1442    int base;
1443
1444    if (!pVesa->savedPal) {
1445#define VESADACDelay()							       \
1446	do {                                                                   \
1447	   (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
1448	   (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
1449	} while (0)
1450
1451	for (i = 0; i < numColors; i++) {
1452	   idx = indices[i];
1453	   outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx);
1454	   VESADACDelay();
1455	   outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red);
1456	   VESADACDelay();
1457	   outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green);
1458	   VESADACDelay();
1459	   outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue);
1460	   VESADACDelay();
1461	}
1462	return;
1463    }
1464
1465    if (pVesa->pal == NULL)
1466	pVesa->pal = calloc(1, sizeof(CARD32) * 256);
1467
1468    for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) {
1469	int j = indices[i];
1470
1471	if (j < 0 || j >= 256)
1472	    continue;
1473	pVesa->pal[j] = colors[j].blue |
1474			(colors[j].green << 8) |
1475			(colors[j].red << 16);
1476	if (j != idx) {
1477	    VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
1478				  pVesa->pal + base, FALSE, TRUE);
1479	    idx = base = j;
1480	}
1481    }
1482
1483    if (idx - 1 == indices[i - 1])
1484	VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
1485			      pVesa->pal + base, FALSE, TRUE);
1486}
1487
1488/*
1489 * Just adapted from the std* functions in vgaHW.c
1490 */
1491static void
1492WriteAttr(VESAPtr pVesa, int index, int value)
1493{
1494    (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1495
1496    index |= 0x20;
1497    outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
1498    outb(pVesa->ioBase + VGA_ATTR_DATA_W, value);
1499}
1500
1501static int
1502ReadAttr(VESAPtr pVesa, int index)
1503{
1504    (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1505
1506    index |= 0x20;
1507    outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
1508    return (inb(pVesa->ioBase + VGA_ATTR_DATA_R));
1509}
1510
1511#define WriteMiscOut(value)	outb(pVesa->ioBase + VGA_MISC_OUT_W, value)
1512#define ReadMiscOut()		inb(pVesa->ioBase + VGA_MISC_OUT_R)
1513#define WriteSeq(index, value)	outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\
1514				outb(pVesa->ioBase + VGA_SEQ_DATA, value)
1515
1516static int
1517ReadSeq(VESAPtr pVesa, int index)
1518{
1519    outb(pVesa->ioBase + VGA_SEQ_INDEX, index);
1520
1521    return (inb(pVesa->ioBase + VGA_SEQ_DATA));
1522}
1523
1524#define WriteGr(index, value)				\
1525    outb(pVesa->ioBase + VGA_GRAPH_INDEX, index);	\
1526    outb(pVesa->ioBase + VGA_GRAPH_DATA, value)
1527
1528static int
1529ReadGr(VESAPtr pVesa, int index)
1530{
1531    outb(pVesa->ioBase + VGA_GRAPH_INDEX, index);
1532
1533    return (inb(pVesa->ioBase + VGA_GRAPH_DATA));
1534}
1535
1536#define WriteCrtc(index, value)						     \
1537    outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1538    outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1539
1540static void
1541SeqReset(VESAPtr pVesa, Bool start)
1542{
1543    if (start) {
1544	WriteSeq(0x00, 0x01);		/* Synchronous Reset */
1545    }
1546    else {
1547	WriteSeq(0x00, 0x03);		/* End Reset */
1548    }
1549}
1550
1551static void
1552SaveFonts(ScrnInfoPtr pScrn)
1553{
1554    VESAPtr pVesa = VESAGetRec(pScrn);
1555    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1556
1557    if (pVesa->fonts != NULL)
1558	return;
1559
1560    /* If in graphics mode, don't save anything */
1561    attr10 = ReadAttr(pVesa, 0x10);
1562    if (attr10 & 0x01)
1563	return;
1564
1565    pVesa->fonts = malloc(16384);
1566
1567    /* save the registers that are needed here */
1568    miscOut = ReadMiscOut();
1569    gr4 = ReadGr(pVesa, 0x04);
1570    gr5 = ReadGr(pVesa, 0x05);
1571    gr6 = ReadGr(pVesa, 0x06);
1572    seq2 = ReadSeq(pVesa, 0x02);
1573    seq4 = ReadSeq(pVesa, 0x04);
1574
1575    /* Force into colour mode */
1576    WriteMiscOut(miscOut | 0x01);
1577
1578    scrn = ReadSeq(pVesa, 0x01) | 0x20;
1579    SeqReset(pVesa, TRUE);
1580    WriteSeq(0x01, scrn);
1581    SeqReset(pVesa, FALSE);
1582
1583    WriteAttr(pVesa, 0x10, 0x01);	/* graphics mode */
1584
1585    /*font1 */
1586    WriteSeq(0x02, 0x04);	/* write to plane 2 */
1587    WriteSeq(0x04, 0x06);	/* enable plane graphics */
1588    WriteGr(0x04, 0x02);	/* read plane 2 */
1589    WriteGr(0x05, 0x00);	/* write mode 0, read mode 0 */
1590    WriteGr(0x06, 0x05);	/* set graphics */
1591    slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192);
1592
1593    /* font2 */
1594    WriteSeq(0x02, 0x08);	/* write to plane 3 */
1595    WriteSeq(0x04, 0x06);	/* enable plane graphics */
1596    WriteGr(0x04, 0x03);	/* read plane 3 */
1597    WriteGr(0x05, 0x00);	/* write mode 0, read mode 0 */
1598    WriteGr(0x06, 0x05);	/* set graphics */
1599    slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192);
1600
1601    scrn = ReadSeq(pVesa, 0x01) & ~0x20;
1602    SeqReset(pVesa, TRUE);
1603    WriteSeq(0x01, scrn);
1604    SeqReset(pVesa, FALSE);
1605
1606    /* Restore clobbered registers */
1607    WriteAttr(pVesa, 0x10, attr10);
1608    WriteSeq(0x02, seq2);
1609    WriteSeq(0x04, seq4);
1610    WriteGr(0x04, gr4);
1611    WriteGr(0x05, gr5);
1612    WriteGr(0x06, gr6);
1613    WriteMiscOut(miscOut);
1614}
1615
1616static void
1617RestoreFonts(ScrnInfoPtr pScrn)
1618{
1619    VESAPtr pVesa = VESAGetRec(pScrn);
1620    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1621
1622    if (pVesa->fonts == NULL)
1623	return;
1624
1625    if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0)
1626	VESABankSwitch(pScrn->pScreen, 0);
1627
1628    /* save the registers that are needed here */
1629    miscOut = ReadMiscOut();
1630    attr10 = ReadAttr(pVesa, 0x10);
1631    gr1 = ReadGr(pVesa, 0x01);
1632    gr3 = ReadGr(pVesa, 0x03);
1633    gr4 = ReadGr(pVesa, 0x04);
1634    gr5 = ReadGr(pVesa, 0x05);
1635    gr6 = ReadGr(pVesa, 0x06);
1636    gr8 = ReadGr(pVesa, 0x08);
1637    seq2 = ReadSeq(pVesa, 0x02);
1638    seq4 = ReadSeq(pVesa, 0x04);
1639
1640    /* Force into colour mode */
1641    WriteMiscOut(miscOut | 0x01);
1642
1643    scrn = ReadSeq(pVesa, 0x01) | 0x20;
1644    SeqReset(pVesa, TRUE);
1645    WriteSeq(0x01, scrn);
1646    SeqReset(pVesa, FALSE);
1647
1648    WriteAttr(pVesa, 0x10, 0x01);	/* graphics mode */
1649    if (pScrn->depth == 4) {
1650	/* GJA */
1651	WriteGr(0x03, 0x00);	/* don't rotate, write unmodified */
1652	WriteGr(0x08, 0xFF);	/* write all bits in a byte */
1653	WriteGr(0x01, 0x00);	/* all planes come from CPU */
1654    }
1655
1656    WriteSeq(0x02, 0x04);   /* write to plane 2 */
1657    WriteSeq(0x04, 0x06);   /* enable plane graphics */
1658    WriteGr(0x04, 0x02);    /* read plane 2 */
1659    WriteGr(0x05, 0x00);    /* write mode 0, read mode 0 */
1660    WriteGr(0x06, 0x05);    /* set graphics */
1661    slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192);
1662
1663    WriteSeq(0x02, 0x08);   /* write to plane 3 */
1664    WriteSeq(0x04, 0x06);   /* enable plane graphics */
1665    WriteGr(0x04, 0x03);    /* read plane 3 */
1666    WriteGr(0x05, 0x00);    /* write mode 0, read mode 0 */
1667    WriteGr(0x06, 0x05);    /* set graphics */
1668    slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192);
1669
1670    scrn = ReadSeq(pVesa, 0x01) & ~0x20;
1671    SeqReset(pVesa, TRUE);
1672    WriteSeq(0x01, scrn);
1673    SeqReset(pVesa, FALSE);
1674
1675    /* restore the registers that were changed */
1676    WriteMiscOut(miscOut);
1677    WriteAttr(pVesa, 0x10, attr10);
1678    WriteGr(0x01, gr1);
1679    WriteGr(0x03, gr3);
1680    WriteGr(0x04, gr4);
1681    WriteGr(0x05, gr5);
1682    WriteGr(0x06, gr6);
1683    WriteGr(0x08, gr8);
1684    WriteSeq(0x02, seq2);
1685    WriteSeq(0x04, seq4);
1686}
1687
1688static Bool
1689VESASaveScreen(ScreenPtr pScreen, int mode)
1690{
1691    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1692    VESAPtr pVesa = VESAGetRec(pScrn);
1693    Bool on = xf86IsUnblank(mode);
1694
1695    if (on)
1696	SetTimeSinceLastInputEvent();
1697
1698    if (pScrn->vtSema) {
1699	unsigned char scrn = ReadSeq(pVesa, 0x01);
1700
1701	if (on)
1702	    scrn &= ~0x20;
1703	else
1704	    scrn |= 0x20;
1705	SeqReset(pVesa, TRUE);
1706	WriteSeq(0x01, scrn);
1707	SeqReset(pVesa, FALSE);
1708    }
1709
1710    return (TRUE);
1711}
1712
1713static int
1714VESABankSwitch(ScreenPtr pScreen, unsigned int iBank)
1715{
1716    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1717    VESAPtr pVesa = VESAGetRec(pScrn);
1718
1719    if (pVesa->curBank == iBank)
1720	return (0);
1721    if (!VBEBankSwitch(pVesa->pVbe, iBank, 0))
1722        return (1);
1723    if (pVesa->bankSwitchWindowB) {
1724        if (!VBEBankSwitch(pVesa->pVbe, iBank, 1))
1725	   return (1);
1726    }
1727    pVesa->curBank = iBank;
1728
1729    return (0);
1730}
1731
1732Bool
1733VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1734{
1735    VESAPtr pVesa;
1736
1737    if (function < MODE_QUERY || function > MODE_RESTORE)
1738	return (FALSE);
1739
1740    pVesa = VESAGetRec(pScrn);
1741
1742
1743    /* Query amount of memory to save state */
1744    if (function == MODE_QUERY ||
1745	(function == MODE_SAVE && pVesa->state == NULL)) {
1746
1747	/* Make sure we save at least this information in case of failure */
1748	(void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode);
1749	SaveFonts(pScrn);
1750
1751	if (pVesa->major > 1) {
1752	    if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state,
1753				&pVesa->stateSize,&pVesa->statePage))
1754	        return FALSE;
1755
1756	}
1757    }
1758
1759    /* Save/Restore Super VGA state */
1760    if (function != MODE_QUERY) {
1761        Bool retval = TRUE;
1762
1763	if (pVesa->major > 1) {
1764	    if (function == MODE_RESTORE)
1765		memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
1766
1767	    if ((retval = VBESaveRestore(pVesa->pVbe,function,
1768					 (pointer)&pVesa->state,
1769					 &pVesa->stateSize,&pVesa->statePage))
1770		&& function == MODE_SAVE) {
1771	        /* don't rely on the memory not being touched */
1772	        if (pVesa->pstate == NULL)
1773		    pVesa->pstate = malloc(pVesa->stateSize);
1774		memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
1775	    }
1776	}
1777
1778	if (function == MODE_RESTORE) {
1779	    VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL);
1780	    RestoreFonts(pScrn);
1781	}
1782
1783	if (!retval)
1784	    return (FALSE);
1785
1786    }
1787
1788    return (TRUE);
1789}
1790
1791static void
1792VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1793                int flags)
1794{
1795    VESAPtr pVesa = VESAGetRec(pScrn);
1796
1797    if (!pScrn->vtSema)
1798	return;
1799
1800    VBEDPMSSet(pVesa->pVbe, mode);
1801}
1802
1803/***********************************************************************
1804 * DGA stuff
1805 ***********************************************************************/
1806static Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1807				   unsigned char **ApertureBase,
1808				   int *ApertureSize, int *ApertureOffset,
1809				   int *flags);
1810static Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1811static void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1812
1813static Bool
1814VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1815		       unsigned char **ApertureBase, int *ApertureSize,
1816		       int *ApertureOffset, int *flags)
1817{
1818    VESAPtr pVesa = VESAGetRec(pScrn);
1819
1820    *DeviceName = NULL;		/* No special device */
1821    *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys);
1822    *ApertureSize = pVesa->mapSize;
1823    *ApertureOffset = pVesa->mapOff;
1824    *flags = DGA_NEED_ROOT;
1825
1826    return (TRUE);
1827}
1828
1829static Bool
1830VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1831{
1832    DisplayModePtr pMode;
1833    int frameX0, frameY0;
1834
1835    if (pDGAMode) {
1836	pMode = pDGAMode->mode;
1837	frameX0 = frameY0 = 0;
1838    }
1839    else {
1840	if (!(pMode = pScrn->currentMode))
1841	    return (TRUE);
1842
1843	frameX0 = pScrn->frameX0;
1844	frameY0 = pScrn->frameY0;
1845    }
1846
1847    if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode)))
1848	return (FALSE);
1849    (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0));
1850
1851    return (TRUE);
1852}
1853
1854static void
1855VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1856{
1857    (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
1858}
1859
1860static int
1861VESADGAGetViewport(ScrnInfoPtr pScrn)
1862{
1863    return (0);
1864}
1865
1866static DGAFunctionRec VESADGAFunctions =
1867{
1868    VESADGAOpenFramebuffer,
1869    NULL,       /* CloseFramebuffer */
1870    VESADGASetMode,
1871    VESADGASetViewport,
1872    VESADGAGetViewport,
1873    NULL,       /* Sync */
1874    NULL,       /* FillRect */
1875    NULL,       /* BlitRect */
1876    NULL,       /* BlitTransRect */
1877};
1878
1879static void
1880VESADGAAddModes(ScrnInfoPtr pScrn)
1881{
1882    VESAPtr pVesa = VESAGetRec(pScrn);
1883    DisplayModePtr pMode = pScrn->modes;
1884    DGAModePtr pDGAMode;
1885
1886    do {
1887	pDGAMode = realloc(pVesa->pDGAMode,
1888			    (pVesa->nDGAMode + 1) * sizeof(DGAModeRec));
1889	if (!pDGAMode)
1890	    break;
1891
1892	pVesa->pDGAMode = pDGAMode;
1893	pDGAMode += pVesa->nDGAMode;
1894	(void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1895
1896	++pVesa->nDGAMode;
1897	pDGAMode->mode = pMode;
1898	pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1899	pDGAMode->byteOrder = pScrn->imageByteOrder;
1900	pDGAMode->depth = pScrn->depth;
1901	pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1902	pDGAMode->red_mask = pScrn->mask.red;
1903	pDGAMode->green_mask = pScrn->mask.green;
1904	pDGAMode->blue_mask = pScrn->mask.blue;
1905	pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
1906	    TrueColor : PseudoColor;
1907	pDGAMode->xViewportStep = 1;
1908	pDGAMode->yViewportStep = 1;
1909	pDGAMode->viewportWidth = pMode->HDisplay;
1910	pDGAMode->viewportHeight = pMode->VDisplay;
1911
1912	pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline;
1913	pDGAMode->imageWidth = pMode->HDisplay;
1914	pDGAMode->imageHeight =  pMode->VDisplay;
1915	pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1916	pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1917	pDGAMode->maxViewportX = pScrn->virtualX -
1918				    pDGAMode->viewportWidth;
1919	pDGAMode->maxViewportY = pScrn->virtualY -
1920				    pDGAMode->viewportHeight;
1921
1922	pDGAMode->address = pVesa->base;
1923
1924	pMode = pMode->next;
1925    } while (pMode != pScrn->modes);
1926}
1927
1928static Bool
1929VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1930{
1931    VESAPtr pVesa = VESAGetRec(pScrn);
1932
1933    if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L)
1934	return (FALSE);
1935
1936    if (!pVesa->nDGAMode)
1937	VESADGAAddModes(pScrn);
1938
1939    return (DGAInit(pScreen, &VESADGAFunctions,
1940	    pVesa->pDGAMode, pVesa->nDGAMode));
1941}
1942