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