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 */
67 static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid);
68 static void VESAIdentify(int flags);
69 #if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA)
70 #define VESAProbe NULL
71 #else
72 static Bool VESAProbe(DriverPtr drv, int flags);
73 #endif
74 #ifdef XSERVER_LIBPCIACCESS
75 static Bool VESAPciProbe(DriverPtr drv, int entity_num,
76      struct pci_device *dev, intptr_t match_data);
77 #endif
78 static Bool VESAPreInit(ScrnInfoPtr pScrn, int flags);
79 static Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL);
80 static Bool VESAEnterVT(VT_FUNC_ARGS_DECL);
81 static void VESALeaveVT(VT_FUNC_ARGS_DECL);
82 static Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL);
83 static Bool VESASaveScreen(ScreenPtr pScreen, int mode);
84 
85 static Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL);
86 static Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
87 static void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL);
88 static void VESAFreeScreen(FREE_SCREEN_ARGS_DECL);
89 static void VESAFreeRec(ScrnInfoPtr pScrn);
90 static VESAPtr VESAGetRec(ScrnInfoPtr pScrn);
91 
92 static void
93 VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
94                 int flags);
95 
96 /* locally used functions */
97 #ifdef HAVE_ISA
98 static int VESAFindIsaDevice(GDevPtr dev);
99 #endif
100 static Bool VESAMapVidMem(ScrnInfoPtr pScrn);
101 static void VESAUnmapVidMem(ScrnInfoPtr pScrn);
102 static int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank);
103 static void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
104 			    LOCO *colors, VisualPtr pVisual);
105 static void SaveFonts(ScrnInfoPtr pScrn);
106 static void RestoreFonts(ScrnInfoPtr pScrn);
107 static Bool
108 VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function);
109 
110 static void *
VESAWindowLinear(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)111 VESAWindowLinear(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 
121 static void *
VESAWindowWindowed(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)122 VESAWindowWindowed(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 
140 static void
vesaUpdatePacked(ScreenPtr pScreen,shadowBufPtr pBuf)141 vesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
142 {
143     shadowUpdatePacked(pScreen, pBuf);
144 }
145 
146 static Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
147 
148 enum GenericTypes
149 {
150     CHIP_VESA_GENERIC
151 };
152 
153 #ifdef XSERVER_LIBPCIACCESS
154 static 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 */
165 static SymTabRec VESAChipsets[] =
166 {
167     {CHIP_VESA_GENERIC, "vesa"},
168     {-1,		 NULL}
169 };
170 
171 #ifndef XSERVER_LIBPCIACCESS
172 static 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
179 static 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 
210 typedef enum {
211     OPTION_SHADOW_FB,
212     OPTION_DFLT_REFRESH,
213     OPTION_MODESET_CLEAR_SCREEN
214 } VESAOpts;
215 
216 static 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 */
227 static MODULESETUPPROTO(vesaSetup);
228 
229 static 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 
249 static pointer
vesaSetup(pointer Module,pointer Options,int * ErrorMajor,int * ErrorMinor)250 vesaSetup(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 
268 static const OptionInfoRec *
VESAAvailableOptions(int chipid,int busid)269 VESAAvailableOptions(int chipid, int busid)
270 {
271     return (VESAOptions);
272 }
273 
274 static void
VESAIdentify(int flags)275 VESAIdentify(int flags)
276 {
277     xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
278 }
279 
280 static VESAPtr
VESAGetRec(ScrnInfoPtr pScrn)281 VESAGetRec(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 */
290 static void
VESASetModeParameters(vbeInfoPtr pVbe,DisplayModePtr vbemode,DisplayModePtr ddcmode)291 VESASetModeParameters(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  */
327 static Bool
vesaModesCloseEnough(DisplayModePtr edid,DisplayModePtr vbe)328 vesaModesCloseEnough(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 
344 static ModeStatus
VESAValidMode(SCRN_ARG_TYPE arg,DisplayModePtr p,Bool flag,int pass)345 VESAValidMode(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 
425 static void
VESAInitScrn(ScrnInfoPtr pScrn)426 VESAInitScrn(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
448 static Bool
VESAPciProbe(DriverPtr drv,int entity_num,struct pci_device * dev,intptr_t match_data)449 VESAPciProbe(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
482 static Bool
VESAProbe(DriverPtr drv,int flags)483 VESAProbe(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
555 static int
VESAFindIsaDevice(GDevPtr dev)556 VESAFindIsaDevice(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 
581 static void
VESAFreeRec(ScrnInfoPtr pScrn)582 VESAFreeRec(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 
616 static int
VESAValidateModes(ScrnInfoPtr pScrn)617 VESAValidateModes(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  */
636 static Bool
VESAPreInit(ScrnInfoPtr pScrn,int flags)637 VESAPreInit(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 
946 static Bool
vesaCreateScreenResources(ScreenPtr pScreen)947 vesaCreateScreenResources(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 
963 static void
vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg,Bool enable)964 vesaEnableDisableFBAccess(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 
973 static Bool
VESAScreenInit(SCREEN_INIT_ARGS_DECL)974 VESAScreenInit(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 
1161 static Bool
VESAEnterVT(VT_FUNC_ARGS_DECL)1162 VESAEnterVT(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 
1172 static void
VESALeaveVT(VT_FUNC_ARGS_DECL)1173 VESALeaveVT(VT_FUNC_ARGS_DECL)
1174 {
1175     SCRN_INFO_PTR(arg);
1176     VESASaveRestore(pScrn, MODE_RESTORE);
1177 }
1178 
1179 static Bool
VESACloseScreen(CLOSE_SCREEN_ARGS_DECL)1180 VESACloseScreen(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 
1209 static Bool
VESASwitchMode(SWITCH_MODE_ARGS_DECL)1210 VESASwitchMode(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 */
1225 static Bool
VESASetMode(ScrnInfoPtr pScrn,DisplayModePtr pMode)1226 VESASetMode(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 
1280 static void
VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL)1281 VESAAdjustFrame(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 
1289 static void
VESAFreeScreen(FREE_SCREEN_ARGS_DECL)1290 VESAFreeScreen(FREE_SCREEN_ARGS_DECL)
1291 {
1292     SCRN_INFO_PTR(arg);
1293     VESAFreeRec(pScrn);
1294 }
1295 
1296 static Bool
VESAMapVidMem(ScrnInfoPtr pScrn)1297 VESAMapVidMem(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 
1365 static void
VESAUnmapVidMem(ScrnInfoPtr pScrn)1366 VESAUnmapVidMem(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 */
1393 static void
VESALoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1394 VESALoadPalette(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  */
1448 static void
WriteAttr(VESAPtr pVesa,int index,int value)1449 WriteAttr(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 
1458 static int
ReadAttr(VESAPtr pVesa,int index)1459 ReadAttr(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 
1473 static int
ReadSeq(VESAPtr pVesa,int index)1474 ReadSeq(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 
1485 static int
ReadGr(VESAPtr pVesa,int index)1486 ReadGr(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 
1497 static void
SeqReset(VESAPtr pVesa,Bool start)1498 SeqReset(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 
1508 static void
SaveFonts(ScrnInfoPtr pScrn)1509 SaveFonts(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 
1573 static void
RestoreFonts(ScrnInfoPtr pScrn)1574 RestoreFonts(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 
1645 static Bool
VESASaveScreen(ScreenPtr pScreen,int mode)1646 VESASaveScreen(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 
1670 static int
VESABankSwitch(ScreenPtr pScreen,unsigned int iBank)1671 VESABankSwitch(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 
1689 Bool
VESASaveRestore(ScrnInfoPtr pScrn,vbeSaveRestoreFunction function)1690 VESASaveRestore(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 
1748 static void
VESADisplayPowerManagementSet(ScrnInfoPtr pScrn,int mode,int flags)1749 VESADisplayPowerManagementSet(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  ***********************************************************************/
1763 static Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1764 				   unsigned char **ApertureBase,
1765 				   int *ApertureSize, int *ApertureOffset,
1766 				   int *flags);
1767 static Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1768 static void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1769 
1770 static Bool
VESADGAOpenFramebuffer(ScrnInfoPtr pScrn,char ** DeviceName,unsigned char ** ApertureBase,int * ApertureSize,int * ApertureOffset,int * flags)1771 VESADGAOpenFramebuffer(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 
1786 static Bool
VESADGASetMode(ScrnInfoPtr pScrn,DGAModePtr pDGAMode)1787 VESADGASetMode(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 
1812 static void
VESADGASetViewport(ScrnInfoPtr pScrn,int x,int y,int flags)1813 VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1814 {
1815     (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
1816 }
1817 
1818 static int
VESADGAGetViewport(ScrnInfoPtr pScrn)1819 VESADGAGetViewport(ScrnInfoPtr pScrn)
1820 {
1821     return (0);
1822 }
1823 
1824 static 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 
1837 static void
VESADGAAddModes(ScrnInfoPtr pScrn)1838 VESADGAAddModes(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 
1886 static Bool
VESADGAInit(ScrnInfoPtr pScrn,ScreenPtr pScreen)1887 VESADGAInit(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