VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_70.c@ 10541

Last change on this file since 10541 was 9811, checked in by vboxsync, 16 years ago

Additions/x11: use the guest/host registry to save the last resolution on machine shutdown and to restore it at startup

File size: 41.1 KB
Line 
1/** @file
2 *
3 * Linux Additions X11 graphics driver
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 * --------------------------------------------------------------------
21 *
22 * This code is based on:
23 *
24 * X11 VESA driver
25 *
26 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a
29 * copy of this software and associated documentation files (the "Software"),
30 * to deal in the Software without restriction, including without limitation
31 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32 * and/or sell copies of the Software, and to permit persons to whom the
33 * Software is furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
43 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44 * SOFTWARE.
45 *
46 * Except as contained in this notice, the name of Conectiva Linux shall
47 * not be used in advertising or otherwise to promote the sale, use or other
48 * dealings in this Software without prior written authorization from
49 * Conectiva Linux.
50 *
51 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
52 */
53
54#define DEBUG_VERB 2
55
56#ifdef XFree86LOADER
57# include "xorg-server.h"
58#else
59# ifdef HAVE_CONFIG_H
60# include "config.h"
61# endif
62#endif
63#include "vboxvideo.h"
64#include "version-generated.h"
65#include <xf86.h>
66
67/* All drivers initialising the SW cursor need this */
68#include "mipointer.h"
69
70/* All drivers implementing backing store need this */
71#include "mibstore.h"
72
73/* Colormap handling */
74#include "micmap.h"
75#include "xf86cmap.h"
76
77/* DPMS */
78/* #define DPMS_SERVER
79#include "extensions/dpms.h" */
80
81/* Mandatory functions */
82
83static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
84static void VBOXIdentify(int flags);
85static Bool VBOXProbe(DriverPtr drv, int flags);
86static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
87static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
88 char **argv);
89static Bool VBOXEnterVT(int scrnIndex, int flags);
90static void VBOXLeaveVT(int scrnIndex, int flags);
91static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
92static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
93static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
94static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
95static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
96static void VBOXFreeScreen(int scrnIndex, int flags);
97static void VBOXFreeRec(ScrnInfoPtr pScrn);
98static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
99 int flags);
100
101/* locally used functions */
102static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
103static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
104static void VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors,
105 int *indices,
106 LOCO *colors, VisualPtr pVisual);
107static void SaveFonts(ScrnInfoPtr pScrn);
108static void RestoreFonts(ScrnInfoPtr pScrn);
109static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
110 vbeSaveRestoreFunction function);
111
112/* Initialise DGA */
113
114static Bool VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
115
116/*
117 * This contains the functions needed by the server after loading the
118 * driver module. It must be supplied, and gets added the driver list by
119 * the Module Setup funtion in the dynamic case. In the static case a
120 * reference to this is compiled in, and this requires that the name of
121 * this DriverRec be an upper-case version of the driver name.
122 */
123
124_X_EXPORT DriverRec VBOXDRV = {
125 VBOX_VERSION,
126 VBOX_DRIVER_NAME,
127 VBOXIdentify,
128 VBOXProbe,
129 VBOXAvailableOptions,
130 NULL,
131 0,
132 NULL
133};
134
135/* Supported chipsets */
136static SymTabRec VBOXChipsets[] =
137{
138 {VBOX_VESA_DEVICEID, "vbox"},
139 {-1, NULL}
140};
141
142static PciChipsets VBOXPCIchipsets[] = {
143 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
144 { -1, -1, RES_UNDEFINED },
145};
146
147typedef enum {
148 OPTION_SHADOW_FB,
149 OPTION_DFLT_REFRESH,
150 OPTION_MODESET_CLEAR_SCREEN
151} VBOXOpts;
152
153/* No options for now */
154static const OptionInfoRec VBOXOptions[] = {
155 { -1, NULL, OPTV_NONE, {0}, FALSE }
156};
157
158/*
159 * List of symbols from other modules that this module references. This
160 * list is used to tell the loader that it is OK for symbols here to be
161 * unresolved providing that it hasn't been told that they haven't been
162 * told that they are essential via a call to xf86LoaderReqSymbols() or
163 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
164 * unresolved symbols that are not required.
165 */
166static const char *fbSymbols[] = {
167 "fbPictureInit",
168 "fbScreenInit",
169 NULL
170};
171
172static const char *shadowfbSymbols[] = {
173 "ShadowFBInit2",
174 NULL
175};
176
177static const char *vbeSymbols[] = {
178 "VBEExtendedInit",
179 "VBEFindSupportedDepths",
180 "VBEGetModeInfo",
181 "VBEGetVBEInfo",
182 "VBEGetVBEMode",
183 "VBEPrintModes",
184 "VBESaveRestore",
185 "VBESetDisplayStart",
186 "VBESetGetDACPaletteFormat",
187 "VBESetGetLogicalScanlineLength",
188 "VBESetGetPaletteData",
189 "VBESetModeNames",
190 "VBESetModeParameters",
191 "VBESetVBEMode",
192 "VBEValidateModes",
193 "vbeDoEDID",
194 "vbeFree",
195 NULL
196};
197
198static const char *ramdacSymbols[] = {
199 "xf86InitCursor",
200 "xf86CreateCursorInfoRec",
201 NULL
202};
203
204#ifdef XFree86LOADER
205/* Module loader interface */
206static MODULESETUPPROTO(vboxSetup);
207
208static XF86ModuleVersionInfo vboxVersionRec =
209{
210 VBOX_DRIVER_NAME,
211 "Sun Microsystems, Inc.",
212 MODINFOSTRING1,
213 MODINFOSTRING2,
214 XORG_VERSION_CURRENT,
215 1, /* Module major version. Xorg-specific */
216 0, /* Module minor version. Xorg-specific */
217 1, /* Module patchlevel. Xorg-specific */
218 ABI_CLASS_VIDEODRV, /* This is a video driver */
219 ABI_VIDEODRV_VERSION,
220 MOD_CLASS_VIDEODRV,
221 {0, 0, 0, 0}
222};
223
224/*
225 * This data is accessed by the loader. The name must be the module name
226 * followed by "ModuleData".
227 */
228_X_EXPORT XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
229
230static pointer
231vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
232{
233 static Bool Initialised = FALSE;
234
235 if (!Initialised)
236 {
237 Initialised = TRUE;
238 xf86AddDriver(&VBOXDRV, Module, 0);
239 LoaderRefSymLists(fbSymbols,
240 shadowfbSymbols,
241 vbeSymbols,
242 ramdacSymbols,
243 NULL);
244 return (pointer)TRUE;
245 }
246
247 if (ErrorMajor)
248 *ErrorMajor = LDR_ONCEONLY;
249 return (NULL);
250}
251
252#endif /* XFree86Loader defined */
253
254static const OptionInfoRec *
255VBOXAvailableOptions(int chipid, int busid)
256{
257 return (VBOXOptions);
258}
259
260static void
261VBOXIdentify(int flags)
262{
263 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
264}
265
266/*
267 * This function is called once, at the start of the first server generation to
268 * do a minimal probe for supported hardware.
269 */
270
271static Bool
272VBOXProbe(DriverPtr drv, int flags)
273{
274 Bool foundScreen = FALSE;
275 int numDevSections, numUsed;
276 GDevPtr *devSections;
277 int *usedChips;
278 int i;
279
280 /*
281 * Find the config file Device sections that match this
282 * driver, and return if there are none.
283 */
284 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
285 &devSections)) <= 0)
286 return (FALSE);
287
288 /* PCI BUS */
289 if (xf86GetPciVideoInfo()) {
290 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
291 VBOXChipsets, VBOXPCIchipsets,
292 devSections, numDevSections,
293 drv, &usedChips);
294 if (numUsed > 0) {
295 if (flags & PROBE_DETECT)
296 foundScreen = TRUE;
297 else {
298 for (i = 0; i < numUsed; i++) {
299 ScrnInfoPtr pScrn = NULL;
300 /* Allocate a ScrnInfoRec */
301 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
302 VBOXPCIchipsets,NULL,
303 NULL,NULL,NULL,NULL))) {
304 pScrn->driverVersion = VBOX_VERSION;
305 pScrn->driverName = VBOX_DRIVER_NAME;
306 pScrn->name = VBOX_NAME;
307 pScrn->Probe = VBOXProbe;
308 pScrn->PreInit = VBOXPreInit;
309 pScrn->ScreenInit = VBOXScreenInit;
310 pScrn->SwitchMode = VBOXSwitchMode;
311 pScrn->AdjustFrame = VBOXAdjustFrame;
312 pScrn->EnterVT = VBOXEnterVT;
313 pScrn->LeaveVT = VBOXLeaveVT;
314 pScrn->FreeScreen = VBOXFreeScreen;
315 foundScreen = TRUE;
316 }
317 }
318 }
319 xfree(usedChips);
320 }
321 }
322 xfree(devSections);
323
324 return (foundScreen);
325}
326
327static VBOXPtr
328VBOXGetRec(ScrnInfoPtr pScrn)
329{
330 if (!pScrn->driverPrivate)
331 {
332 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
333#if 0
334 ((VBOXPtr)pScrn->driverPrivate)->vbox_fd = -1;
335#endif
336 }
337
338 return ((VBOXPtr)pScrn->driverPrivate);
339}
340
341static void
342VBOXFreeRec(ScrnInfoPtr pScrn)
343{
344 VBOXPtr pVBox = VBOXGetRec(pScrn);
345#if 0
346 xfree(pVBox->vbeInfo);
347#endif
348 xfree(pVBox->savedPal);
349 xfree(pVBox->fonts);
350 xfree(pScrn->driverPrivate);
351 pScrn->driverPrivate = NULL;
352}
353
354/*
355 * QUOTE from the XFree86 DESIGN document:
356 *
357 * The purpose of this function is to find out all the information
358 * required to determine if the configuration is usable, and to initialise
359 * those parts of the ScrnInfoRec that can be set once at the beginning of
360 * the first server generation.
361 *
362 * (...)
363 *
364 * This includes probing for video memory, clocks, ramdac, and all other
365 * HW info that is needed. It includes determining the depth/bpp/visual
366 * and related info. It includes validating and determining the set of
367 * video modes that will be used (and anything that is required to
368 * determine that).
369 *
370 * This information should be determined in the least intrusive way
371 * possible. The state of the HW must remain unchanged by this function.
372 * Although video memory (including MMIO) may be mapped within this
373 * function, it must be unmapped before returning.
374 *
375 * END QUOTE
376 */
377
378static Bool
379VBOXPreInit(ScrnInfoPtr pScrn, int flags)
380{
381 VBOXPtr pVBox;
382 Gamma gzeros = {0.0, 0.0, 0.0};
383 rgb rzeros = {0, 0, 0};
384 ClockRange *clockRanges;
385 int i;
386 DisplayModePtr m_prev;
387 char *pcHostModeName = NULL;
388
389 /* Are we really starting the server, or is this just a dummy run? */
390 if (flags & PROBE_DETECT)
391 return (FALSE);
392
393 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
394 "VirtualBox guest additions video driver version "
395 VBOX_VERSION_STRING "\n");
396
397 /* Get our private data from the ScrnInfoRec structure. */
398 pVBox = VBOXGetRec(pScrn);
399
400 /* Initialise the guest library */
401 vbox_init(pScrn->scrnIndex, pVBox);
402
403 /* Entity information seems to mean bus information. */
404 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
405 if (pVBox->pEnt->location.type != BUS_PCI)
406 return FALSE;
407
408 /* The ramdac module is needed for the hardware cursor. */
409 if (!xf86LoadSubModule(pScrn, "ramdac"))
410 return FALSE;
411 xf86LoaderReqSymLists(ramdacSymbols, NULL);
412
413 /* We need the vbe module because we use VBE code to save and restore
414 text mode, in order to keep our code simple. */
415 if (!xf86LoadSubModule(pScrn, "vbe"))
416 return (FALSE);
417 xf86LoaderReqSymLists(vbeSymbols, NULL);
418
419 /* The framebuffer module. */
420 if (xf86LoadSubModule(pScrn, "fb") == NULL)
421 return (FALSE);
422 xf86LoaderReqSymLists(fbSymbols, NULL);
423
424 if (!xf86LoadSubModule(pScrn, "shadowfb"))
425 return FALSE;
426 xf86LoaderReqSymLists(shadowfbSymbols, NULL);
427
428 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
429 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
430 pVBox->pciInfo->device,
431 pVBox->pciInfo->func);
432
433 /* Set up our ScrnInfoRec structure to describe our virtual
434 capabilities to X. */
435
436 pScrn->rgbBits = 8;
437
438 /* Let's create a nice, capable virtual monitor. */
439 pScrn->monitor = pScrn->confScreen->monitor;
440 pScrn->monitor->DDC = NULL;
441 pScrn->monitor->nHsync = 1;
442 pScrn->monitor->hsync[0].lo = 1;
443 pScrn->monitor->hsync[0].hi = 10000;
444 pScrn->monitor->nVrefresh = 1;
445 pScrn->monitor->vrefresh[0].lo = 1;
446 pScrn->monitor->vrefresh[0].hi = 100;
447
448 pScrn->chipset = "vbox";
449 pScrn->progClock = TRUE;
450
451 /* Determine the size of the VBox video RAM from PCI data*/
452#if 0
453 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
454#endif
455 /* Using the PCI information caused problems with non-powers-of-two
456 sized video RAM configurations */
457 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
458
459 /* Set up clock information that will support all modes we need. */
460 clockRanges = xnfcalloc(sizeof(ClockRange), 1);
461 clockRanges->next = NULL;
462 clockRanges->minClock = 1000;
463 clockRanges->maxClock = 1000000000;
464 clockRanges->clockIndex = -1;
465 clockRanges->ClockMulFactor = 1;
466 clockRanges->ClockDivFactor = 1;
467
468 /* Query the host for the preferred resolution and colour depth */
469 {
470 uint32_t cx = 0, cy = 0, iDisplay = 0, cBits = 24;
471
472 if (vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits, &iDisplay))
473 {
474 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
475 if (cBits != 16)
476 cBits = 24;
477 if ((0 != cx) && (0 != cy)) {
478 cx -= cx % 8;
479 pcHostModeName = XNFprintf("%dx%d", cx, cy);
480 }
481 }
482 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
483 return FALSE;
484 }
485 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
486 {
487 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
488 "The VBox additions only support 16 and 32bpp graphics modes\n");
489 return FALSE;
490 }
491 xf86PrintDepthBpp(pScrn);
492
493 /* To get around the problem of SUSE specifying a single, invalid mode in their
494 * Xorg.conf by default, we add additional modes to the end of the user specified
495 * list. This means that if all user modes are invalid, X will try our mode before
496 * falling back to its standard mode list. */
497 if (pScrn->display->modes == NULL)
498 {
499 i = 0;
500 /* The user specified no modes at all. */
501 pScrn->display->modes = xnfalloc(5 * sizeof(char*));
502 }
503 else
504 {
505 for (i = 0; pScrn->display->modes[i] != NULL; i++);
506 pScrn->display->modes = xnfrealloc(pScrn->display->modes, (i + 5)
507 * sizeof(char *));
508 }
509 /* Add additional modes to the end of the mode list in case the others are
510 all invalid. */
511 if (pcHostModeName != NULL)
512 {
513 pScrn->display->modes[i] = pcHostModeName;
514 ++i;
515 }
516 if (vboxHostLikesVideoMode(pScrn, 1024, 768, pScrn->bitsPerPixel))
517 {
518 pScrn->display->modes[i] = "1024x768";
519 ++i;
520 }
521 if (vboxHostLikesVideoMode(pScrn, 800, 600, pScrn->bitsPerPixel))
522 {
523 pScrn->display->modes[i] = "800x600";
524 ++i;
525 }
526 /* A mode of last resort */
527 pScrn->display->modes[i] = "640x480";
528 ++i;
529 pScrn->display->modes[i] = NULL;
530
531 /* Create a builtin mode for every specified mode. This allows to specify arbitrary
532 * screen resolutions */
533 m_prev = NULL;
534 for (i = 0; pScrn->display->modes[i] != NULL; i++)
535 {
536 DisplayModePtr m;
537 int x = 0, y = 0;
538
539 sscanf(pScrn->display->modes[i], "%dx%d", &x, &y);
540 m = xnfcalloc(sizeof(DisplayModeRec), 1);
541 m->status = MODE_OK;
542 m->type = M_T_BUILTIN;
543 /* VBox does only support screen widths which are a multiple of 8 */
544 m->HDisplay = (x + 7) & ~7;
545 m->HSyncStart = m->HDisplay + 2;
546 m->HSyncEnd = m->HDisplay + 4;
547 m->HTotal = m->HDisplay + 6;
548 m->VDisplay = y;
549 m->VSyncStart = m->VDisplay + 2;
550 m->VSyncEnd = m->VDisplay + 4;
551 m->VTotal = m->VDisplay + 6;
552 m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
553 m->name = strdup(pScrn->display->modes[i]);
554 if (!m_prev)
555 pScrn->modePool = m;
556 else
557 m_prev->next = m;
558 m->prev = m_prev;
559 m_prev = m;
560 }
561
562 /* Colour weight - we always call this, since we are always in
563 truecolour. */
564 if (!xf86SetWeight(pScrn, rzeros, rzeros))
565 return (FALSE);
566
567 /* visual init */
568 if (!xf86SetDefaultVisual(pScrn, -1))
569 return (FALSE);
570
571 xf86SetGamma(pScrn, gzeros);
572
573 /* Set a sane minimum mode size and the maximum allowed by the available VRAM */
574 {
575 unsigned maxSize, trySize = 512;
576
577 do {
578 maxSize = trySize;
579 trySize += 128;
580 } while (trySize * trySize * pScrn->bitsPerPixel / 8 < pScrn->videoRam * 1024);
581
582 /* I don't know exactly what these are for (and they are only used in a couple
583 of places in the X server code). */
584 pScrn->display->virtualX = maxSize;
585 pScrn->display->virtualY = maxSize;
586 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
587 "The maximum supported resolution is currently %dx%d\n", maxSize, maxSize);
588 }
589
590 /* Filter out video modes not supported by the virtual hardware
591 we described. */
592 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
593 pScrn->display->modes,
594 clockRanges, NULL, 64, pScrn->display->virtualX, 1,
595 64, pScrn->display->virtualY, 0, 0,
596 pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
597
598 if (i <= 0) {
599 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
600 return (FALSE);
601 }
602 xf86PruneDriverModes(pScrn);
603
604 pScrn->currentMode = pScrn->modes;
605 pScrn->displayWidth = pScrn->virtualX;
606
607 xf86PrintModes(pScrn);
608
609 /* Set display resolution. Perhaps we should read this from the host. */
610 xf86SetDpi(pScrn, 96, 96);
611
612 if (pScrn->modes == NULL) {
613 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
614 return (FALSE);
615 }
616
617 /* options */
618 xf86CollectOptions(pScrn, NULL);
619 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
620 return FALSE;
621 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
622 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
623
624 /* Framebuffer-related setup */
625 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
626 return (TRUE);
627}
628
629/*
630 * QUOTE from the XFree86 DESIGN document:
631 *
632 * This is called at the start of each server generation.
633 *
634 * (...)
635 *
636 * Decide which operations need to be placed under resource access
637 * control. (...) Map any video memory or other memory regions. (...)
638 * Save the video card state. (...) Initialise the initial video
639 * mode.
640 *
641 * End QUOTE.Initialise the initial video mode.
642 */
643static Bool
644VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
645{
646 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
647 VBOXPtr pVBox = VBOXGetRec(pScrn);
648 VisualPtr visual;
649 unsigned flags;
650
651 /* We make use of the X11 VBE code to save and restore text mode, in
652 order to keep our code simple. */
653 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
654 SET_BIOS_SCRATCH
655 | RESTORE_BIOS_SCRATCH)) == NULL)
656 return (FALSE);
657
658 if (pVBox->mapPhys == 0) {
659 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
660/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
661 /* Using the PCI information caused problems with
662 non-powers-of-two sized video RAM configurations */
663 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
664 pVBox->mapOff = 0;
665 }
666
667 if (!VBOXMapVidMem(pScrn))
668 return (FALSE);
669
670 /* save current video state */
671 VBOXSaveRestore(pScrn, MODE_SAVE);
672 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
673 NULL, FALSE, FALSE);
674
675 /* set first video mode */
676 if (!VBOXSetMode(pScrn, pScrn->currentMode))
677 return FALSE;
678
679 /* set the viewport */
680 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
681
682 /* Blank the screen for aesthetic reasons. */
683 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
684
685 /* mi layer - reset the visual list (?)*/
686 miClearVisualTypes();
687 if (!xf86SetDefaultVisual(pScrn, -1))
688 return (FALSE);
689 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
690 pScrn->rgbBits, TrueColor))
691 return (FALSE);
692 if (!miSetPixmapDepths())
693 return (FALSE);
694
695 /* I checked in the sources, and XFree86 4.2 does seem to support
696 this function for 32bpp. */
697 if (!fbScreenInit(pScreen, pVBox->base,
698 pScrn->virtualX, pScrn->virtualY,
699 pScrn->xDpi, pScrn->yDpi,
700 pScrn->displayWidth, pScrn->bitsPerPixel))
701 return (FALSE);
702
703 /* Fixup RGB ordering */
704 visual = pScreen->visuals + pScreen->numVisuals;
705 while (--visual >= pScreen->visuals) {
706 if ((visual->class | DynamicClass) == DirectColor) {
707 visual->offsetRed = pScrn->offset.red;
708 visual->offsetGreen = pScrn->offset.green;
709 visual->offsetBlue = pScrn->offset.blue;
710 visual->redMask = pScrn->mask.red;
711 visual->greenMask = pScrn->mask.green;
712 visual->blueMask = pScrn->mask.blue;
713 }
714 }
715
716 /* must be after RGB ordering fixed */
717 fbPictureInit(pScreen, 0, 0);
718
719 VBOXDGAInit(pScrn, pScreen);
720
721 xf86SetBlackWhitePixels(pScreen);
722 miInitializeBackingStore(pScreen);
723 xf86SetBackingStore(pScreen);
724
725 /* software cursor */
726 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
727
728 /* colourmap code - apparently, we need this even in Truecolour */
729 if (!miCreateDefColormap(pScreen))
730 return (FALSE);
731
732 flags = CMAP_RELOAD_ON_MODE_SWITCH;
733
734 if(!xf86HandleColormaps(pScreen, 256,
735 8 /* DAC is switchable to 8 bits per primary color */,
736 VBOXLoadPalette, NULL, flags))
737 return (FALSE);
738
739 pVBox->CloseScreen = pScreen->CloseScreen;
740 pScreen->CloseScreen = VBOXCloseScreen;
741 pScreen->SaveScreen = VBOXSaveScreen;
742
743 /* However, we probably do want to support power management -
744 even if we just use a dummy function. */
745 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
746
747 /* Report any unused options (only for the first generation) */
748 if (serverGeneration == 1)
749 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
750
751 if (vbox_open (pScrn, pScreen, pVBox)) {
752 if (vbox_cursor_init(pScreen) != TRUE)
753 xf86DrvMsg(scrnIndex, X_ERROR,
754 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
755 if (vboxEnableVbva(pScrn) == TRUE)
756 xf86DrvMsg(scrnIndex, X_INFO,
757 "The VBox video extensions are now enabled.\n");
758 }
759 return (TRUE);
760}
761
762static Bool
763VBOXEnterVT(int scrnIndex, int flags)
764{
765 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
766 VBOXPtr pVBox = VBOXGetRec(pScrn);
767
768 if (!VBOXSetMode(pScrn, pScrn->currentMode))
769 return FALSE;
770 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
771 if (pVBox->useVbva == TRUE)
772 vboxEnableVbva(pScrn);
773 return TRUE;
774}
775
776static void
777VBOXLeaveVT(int scrnIndex, int flags)
778{
779 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
780 VBOXPtr pVBox = VBOXGetRec(pScrn);
781
782 VBOXSaveRestore(pScrn, MODE_RESTORE);
783 if (pVBox->useVbva == TRUE)
784 vboxDisableVbva(pScrn);
785}
786
787static Bool
788VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
789{
790 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
791 VBOXPtr pVBox = VBOXGetRec(pScrn);
792
793 if (pVBox->useVbva == TRUE)
794 vboxDisableVbva(pScrn);
795 if (pScrn->vtSema) {
796 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
797 if (pVBox->savedPal)
798 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
799 pVBox->savedPal, FALSE, TRUE);
800 VBOXUnmapVidMem(pScrn);
801 }
802 if (pVBox->pDGAMode) {
803 xfree(pVBox->pDGAMode);
804 pVBox->pDGAMode = NULL;
805 pVBox->nDGAMode = 0;
806 }
807 pScrn->vtSema = FALSE;
808
809 pScreen->CloseScreen = pVBox->CloseScreen;
810 return pScreen->CloseScreen(scrnIndex, pScreen);
811}
812
813static Bool
814VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
815{
816 ScrnInfoPtr pScrn;
817 VBOXPtr pVBox;
818
819 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
820 pVBox = VBOXGetRec(pScrn);
821 if (pVBox->useVbva == TRUE)
822 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
823 return FALSE;
824 if (VBOXSetMode(pScrn, pMode) != TRUE)
825 return FALSE;
826 if (pVBox->useVbva == TRUE)
827 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
828 pVBox->useVbva = FALSE;
829 return TRUE;
830}
831
832/* Set a graphics mode */
833static Bool
834VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
835{
836 VBOXPtr pVBox;
837
838 int bpp = pScrn->depth == 24 ? 32 : 16;
839 int xRes = pMode->HDisplay;
840 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
841 >= pScrn->videoRam * 1024)
842 {
843 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
844 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
845 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
846 return FALSE;
847 }
848 /* We only support horizontal resolutions which are a multiple of 8. Round down if
849 necessary. */
850 if (xRes % 8 != 0)
851 {
852 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
853 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
854 xRes, xRes - (xRes % 8));
855 xRes = xRes - (xRes % 8);
856 }
857 pVBox = VBOXGetRec(pScrn);
858 pScrn->vtSema = TRUE;
859 /* Disable linear framebuffer mode before making changes to the resolution. */
860 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
861 outw(VBE_DISPI_IOPORT_DATA,
862 VBE_DISPI_DISABLED);
863 /* Unlike the resolution, the depth is fixed for a given screen
864 for the lifetime of the X session. */
865 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
866 outw(VBE_DISPI_IOPORT_DATA, bpp);
867 /* HDisplay and VDisplay are actually monitor information about
868 the display part of the scanlines. */
869 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
870 outw(VBE_DISPI_IOPORT_DATA, xRes);
871 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
872 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
873 /* Enable linear framebuffer mode. */
874 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
875 outw(VBE_DISPI_IOPORT_DATA,
876 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
877 /* Set the virtual resolution. We are still using VESA to control
878 the virtual offset. */
879 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
880 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
881 return (TRUE);
882}
883
884static void
885VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
886{
887 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
888
889 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
890}
891
892static void
893VBOXFreeScreen(int scrnIndex, int flags)
894{
895 VBOXFreeRec(xf86Screens[scrnIndex]);
896}
897
898static Bool
899VBOXMapVidMem(ScrnInfoPtr pScrn)
900{
901 VBOXPtr pVBox = VBOXGetRec(pScrn);
902
903 if (pVBox->base != NULL)
904 return (TRUE);
905
906 pScrn->memPhysBase = pVBox->mapPhys;
907 pScrn->fbOffset = pVBox->mapOff;
908
909 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
910 VIDMEM_FRAMEBUFFER,
911 pVBox->pciTag, pVBox->mapPhys,
912 (unsigned) pVBox->mapSize);
913
914 if (pVBox->base) {
915 pScrn->memPhysBase = pVBox->mapPhys;
916 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
917 pVBox->pciTag,
918 0xa0000, 0x10000);
919 }
920 /* We need this for saving/restoring textmode */
921 pVBox->ioBase = pScrn->domainIOBase;
922
923 return (pVBox->base != NULL);
924}
925
926static void
927VBOXUnmapVidMem(ScrnInfoPtr pScrn)
928{
929 VBOXPtr pVBox = VBOXGetRec(pScrn);
930
931 if (pVBox->base == NULL)
932 return;
933
934 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
935 (unsigned) pVBox->mapSize);
936 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
937 pVBox->base = NULL;
938}
939
940static void
941VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
942 LOCO *colors, VisualPtr pVisual)
943{
944 VBOXPtr pVBox = VBOXGetRec(pScrn);
945 int i, idx;
946#define VBOXDACDelay() \
947 do { \
948 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
949 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
950 } while (0)
951
952 for (i = 0; i < numColors; i++) {
953 idx = indices[i];
954 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
955 VBOXDACDelay();
956 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
957 VBOXDACDelay();
958 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
959 VBOXDACDelay();
960 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
961 VBOXDACDelay();
962 }
963}
964
965/*
966 * Just adapted from the std* functions in vgaHW.c
967 */
968static void
969WriteAttr(VBOXPtr pVBox, int index, int value)
970{
971 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
972
973 index |= 0x20;
974 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
975 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
976}
977
978static int
979ReadAttr(VBOXPtr pVBox, int index)
980{
981 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
982
983 index |= 0x20;
984 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
985 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
986}
987
988#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
989#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
990#define WriteSeq(index, value) \
991 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
992 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
993
994static int
995ReadSeq(VBOXPtr pVBox, int index)
996{
997 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
998
999 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1000}
1001
1002#define WriteGr(index, value) \
1003 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1004 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1005
1006static int
1007ReadGr(VBOXPtr pVBox, int index)
1008{
1009 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1010
1011 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1012}
1013
1014#define WriteCrtc(index, value) \
1015 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1016 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1017
1018static void
1019SeqReset(VBOXPtr pVBox, Bool start)
1020{
1021 if (start) {
1022 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1023 }
1024 else {
1025 WriteSeq(0x00, 0x03); /* End Reset */
1026 }
1027}
1028
1029static void
1030SaveFonts(ScrnInfoPtr pScrn)
1031{
1032 VBOXPtr pVBox = VBOXGetRec(pScrn);
1033 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1034
1035 if (pVBox->fonts != NULL)
1036 return;
1037
1038 /* If in graphics mode, don't save anything */
1039 attr10 = ReadAttr(pVBox, 0x10);
1040 if (attr10 & 0x01)
1041 return;
1042
1043 pVBox->fonts = xalloc(16384);
1044
1045 /* save the registers that are needed here */
1046 miscOut = ReadMiscOut();
1047 gr4 = ReadGr(pVBox, 0x04);
1048 gr5 = ReadGr(pVBox, 0x05);
1049 gr6 = ReadGr(pVBox, 0x06);
1050 seq2 = ReadSeq(pVBox, 0x02);
1051 seq4 = ReadSeq(pVBox, 0x04);
1052
1053 /* Force into colour mode */
1054 WriteMiscOut(miscOut | 0x01);
1055
1056 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1057 SeqReset(pVBox, TRUE);
1058 WriteSeq(0x01, scrn);
1059 SeqReset(pVBox, FALSE);
1060
1061 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1062
1063 /*font1 */
1064 WriteSeq(0x02, 0x04); /* write to plane 2 */
1065 WriteSeq(0x04, 0x06); /* enable plane graphics */
1066 WriteGr(0x04, 0x02); /* read plane 2 */
1067 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1068 WriteGr(0x06, 0x05); /* set graphics */
1069 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1070
1071 /* font2 */
1072 WriteSeq(0x02, 0x08); /* write to plane 3 */
1073 WriteSeq(0x04, 0x06); /* enable plane graphics */
1074 WriteGr(0x04, 0x03); /* read plane 3 */
1075 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1076 WriteGr(0x06, 0x05); /* set graphics */
1077 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1078
1079 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1080 SeqReset(pVBox, TRUE);
1081 WriteSeq(0x01, scrn);
1082 SeqReset(pVBox, FALSE);
1083
1084 /* Restore clobbered registers */
1085 WriteAttr(pVBox, 0x10, attr10);
1086 WriteSeq(0x02, seq2);
1087 WriteSeq(0x04, seq4);
1088 WriteGr(0x04, gr4);
1089 WriteGr(0x05, gr5);
1090 WriteGr(0x06, gr6);
1091 WriteMiscOut(miscOut);
1092}
1093
1094static void
1095RestoreFonts(ScrnInfoPtr pScrn)
1096{
1097 VBOXPtr pVBox = VBOXGetRec(pScrn);
1098 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1099
1100 if (pVBox->fonts == NULL)
1101 return;
1102
1103 /* save the registers that are needed here */
1104 miscOut = ReadMiscOut();
1105 attr10 = ReadAttr(pVBox, 0x10);
1106 gr1 = ReadGr(pVBox, 0x01);
1107 gr3 = ReadGr(pVBox, 0x03);
1108 gr4 = ReadGr(pVBox, 0x04);
1109 gr5 = ReadGr(pVBox, 0x05);
1110 gr6 = ReadGr(pVBox, 0x06);
1111 gr8 = ReadGr(pVBox, 0x08);
1112 seq2 = ReadSeq(pVBox, 0x02);
1113 seq4 = ReadSeq(pVBox, 0x04);
1114
1115 /* Force into colour mode */
1116 WriteMiscOut(miscOut | 0x01);
1117
1118 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1119 SeqReset(pVBox, TRUE);
1120 WriteSeq(0x01, scrn);
1121 SeqReset(pVBox, FALSE);
1122
1123 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1124 if (pScrn->depth == 4) {
1125 /* GJA */
1126 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1127 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1128 WriteGr(0x01, 0x00); /* all planes come from CPU */
1129 }
1130
1131 WriteSeq(0x02, 0x04); /* write to plane 2 */
1132 WriteSeq(0x04, 0x06); /* enable plane graphics */
1133 WriteGr(0x04, 0x02); /* read plane 2 */
1134 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1135 WriteGr(0x06, 0x05); /* set graphics */
1136 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1137
1138 WriteSeq(0x02, 0x08); /* write to plane 3 */
1139 WriteSeq(0x04, 0x06); /* enable plane graphics */
1140 WriteGr(0x04, 0x03); /* read plane 3 */
1141 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1142 WriteGr(0x06, 0x05); /* set graphics */
1143 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1144
1145 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1146 SeqReset(pVBox, TRUE);
1147 WriteSeq(0x01, scrn);
1148 SeqReset(pVBox, FALSE);
1149
1150 /* restore the registers that were changed */
1151 WriteMiscOut(miscOut);
1152 WriteAttr(pVBox, 0x10, attr10);
1153 WriteGr(0x01, gr1);
1154 WriteGr(0x03, gr3);
1155 WriteGr(0x04, gr4);
1156 WriteGr(0x05, gr5);
1157 WriteGr(0x06, gr6);
1158 WriteGr(0x08, gr8);
1159 WriteSeq(0x02, seq2);
1160 WriteSeq(0x04, seq4);
1161}
1162
1163static Bool
1164VBOXSaveScreen(ScreenPtr pScreen, int mode)
1165{
1166 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1167 VBOXPtr pVBox = VBOXGetRec(pScrn);
1168 Bool on = xf86IsUnblank(mode);
1169
1170 if (on)
1171 SetTimeSinceLastInputEvent();
1172
1173 if (pScrn->vtSema) {
1174 unsigned char scrn = ReadSeq(pVBox, 0x01);
1175
1176 if (on)
1177 scrn &= ~0x20;
1178 else
1179 scrn |= 0x20;
1180 SeqReset(pVBox, TRUE);
1181 WriteSeq(0x01, scrn);
1182 SeqReset(pVBox, FALSE);
1183 }
1184
1185 return (TRUE);
1186}
1187
1188Bool
1189VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1190{
1191 VBOXPtr pVBox;
1192
1193 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1194 return (FALSE);
1195
1196 pVBox = VBOXGetRec(pScrn);
1197
1198
1199 /* Query amount of memory to save state */
1200 if (function == MODE_QUERY ||
1201 (function == MODE_SAVE && pVBox->state == NULL))
1202 {
1203
1204 /* Make sure we save at least this information in case of failure */
1205 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1206 SaveFonts(pScrn);
1207
1208 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1209 &pVBox->stateSize,&pVBox->statePage))
1210 return FALSE;
1211 }
1212
1213 /* Save/Restore Super VGA state */
1214 if (function != MODE_QUERY) {
1215 Bool retval = TRUE;
1216
1217 if (function == MODE_RESTORE)
1218 memcpy(pVBox->state, pVBox->pstate,
1219 (unsigned) pVBox->stateSize);
1220
1221 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1222 (pointer)&pVBox->state,
1223 &pVBox->stateSize,&pVBox->statePage))
1224 && function == MODE_SAVE)
1225 {
1226 /* don't rely on the memory not being touched */
1227 if (pVBox->pstate == NULL)
1228 pVBox->pstate = xalloc(pVBox->stateSize);
1229 memcpy(pVBox->pstate, pVBox->state,
1230 (unsigned) pVBox->stateSize);
1231 }
1232
1233 if (function == MODE_RESTORE)
1234 {
1235 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1236 RestoreFonts(pScrn);
1237 }
1238
1239 if (!retval)
1240 return (FALSE);
1241
1242 }
1243
1244 return (TRUE);
1245}
1246
1247static void
1248VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1249 int flags)
1250{
1251 /* VBox is always power efficient... */
1252}
1253
1254
1255
1256
1257/***********************************************************************
1258 * DGA stuff
1259 ***********************************************************************/
1260static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1261 unsigned char **ApertureBase,
1262 int *ApertureSize, int *ApertureOffset,
1263 int *flags);
1264static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1265static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1266
1267static Bool
1268VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1269 unsigned char **ApertureBase, int *ApertureSize,
1270 int *ApertureOffset, int *flags)
1271{
1272 VBOXPtr pVBox = VBOXGetRec(pScrn);
1273
1274 *DeviceName = NULL; /* No special device */
1275 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1276 *ApertureSize = pVBox->mapSize;
1277 *ApertureOffset = pVBox->mapOff;
1278 *flags = DGA_NEED_ROOT;
1279
1280 return (TRUE);
1281}
1282
1283static Bool
1284VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1285{
1286 DisplayModePtr pMode;
1287 int scrnIdx = pScrn->pScreen->myNum;
1288 int frameX0, frameY0;
1289
1290 if (pDGAMode) {
1291 pMode = pDGAMode->mode;
1292 frameX0 = frameY0 = 0;
1293 }
1294 else {
1295 if (!(pMode = pScrn->currentMode))
1296 return (TRUE);
1297
1298 frameX0 = pScrn->frameX0;
1299 frameY0 = pScrn->frameY0;
1300 }
1301
1302 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1303 return (FALSE);
1304 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1305
1306 return (TRUE);
1307}
1308
1309static void
1310VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1311{
1312 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1313}
1314
1315static int
1316VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1317{
1318 return (0);
1319}
1320
1321static DGAFunctionRec VBOXDGAFunctions =
1322{
1323 VBOXDGAOpenFramebuffer,
1324 NULL, /* CloseFramebuffer */
1325 VBOXDGASetMode,
1326 VBOXDGASetViewport,
1327 VBOXDGAGetViewport,
1328 NULL, /* Sync */
1329 NULL, /* FillRect */
1330 NULL, /* BlitRect */
1331 NULL, /* BlitTransRect */
1332};
1333
1334static void
1335VBOXDGAAddModes(ScrnInfoPtr pScrn)
1336{
1337 VBOXPtr pVBox = VBOXGetRec(pScrn);
1338 DisplayModePtr pMode = pScrn->modes;
1339 DGAModePtr pDGAMode;
1340
1341 do {
1342 pDGAMode = xrealloc(pVBox->pDGAMode,
1343 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1344 if (!pDGAMode)
1345 break;
1346
1347 pVBox->pDGAMode = pDGAMode;
1348 pDGAMode += pVBox->nDGAMode;
1349 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1350
1351 ++pVBox->nDGAMode;
1352 pDGAMode->mode = pMode;
1353 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1354 pDGAMode->byteOrder = pScrn->imageByteOrder;
1355 pDGAMode->depth = pScrn->depth;
1356 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1357 pDGAMode->red_mask = pScrn->mask.red;
1358 pDGAMode->green_mask = pScrn->mask.green;
1359 pDGAMode->blue_mask = pScrn->mask.blue;
1360 pDGAMode->visualClass = TrueColor;
1361 pDGAMode->xViewportStep = 1;
1362 pDGAMode->yViewportStep = 1;
1363 pDGAMode->viewportWidth = pMode->HDisplay;
1364 pDGAMode->viewportHeight = pMode->VDisplay;
1365
1366 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1367 pDGAMode->imageWidth = pMode->HDisplay;
1368 pDGAMode->imageHeight = pMode->VDisplay;
1369 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1370 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1371 pDGAMode->maxViewportX = pScrn->virtualX -
1372 pDGAMode->viewportWidth;
1373 pDGAMode->maxViewportY = pScrn->virtualY -
1374 pDGAMode->viewportHeight;
1375
1376 pDGAMode->address = pVBox->base;
1377
1378 pMode = pMode->next;
1379 } while (pMode != pScrn->modes);
1380}
1381
1382static Bool
1383VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1384{
1385 VBOXPtr pVBox = VBOXGetRec(pScrn);
1386
1387 if (!pVBox->nDGAMode)
1388 VBOXDGAAddModes(pScrn);
1389
1390 return (DGAInit(pScreen, &VBOXDGAFunctions,
1391 pVBox->pDGAMode, pVBox->nDGAMode));
1392}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette