VirtualBox

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

Last change on this file since 8640 was 8472, checked in by vboxsync, 17 years ago

Additions/x11: fixed a bug in the X.org 7.0 graphics driver whereby invalid size hints were not ignored

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 <[email protected]>
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 pVBox))
474 {
475 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
476 if (cBits != 16)
477 cBits = 24;
478 if ((0 != cx) && (0 != cy)) {
479 cx -= cx % 8;
480 pcHostModeName = XNFprintf("%dx%d", cx, cy);
481 }
482 }
483 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
484 return FALSE;
485 }
486 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
487 {
488 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
489 "The VBox additions only support 16 and 32bpp graphics modes\n");
490 return FALSE;
491 }
492 xf86PrintDepthBpp(pScrn);
493
494 /* To get around the problem of SUSE specifying a single, invalid mode in their
495 * Xorg.conf by default, we add additional modes to the end of the user specified
496 * list. This means that if all user modes are invalid, X will try our mode before
497 * falling back to its standard mode list. */
498 if (pScrn->display->modes == NULL)
499 {
500 i = 0;
501 /* The user specified no modes at all. */
502 pScrn->display->modes = xnfalloc(5 * sizeof(char*));
503 }
504 else
505 {
506 for (i = 0; pScrn->display->modes[i] != NULL; i++);
507 pScrn->display->modes = xnfrealloc(pScrn->display->modes, (i + 5)
508 * sizeof(char *));
509 }
510 /* Add additional modes to the end of the mode list in case the others are
511 all invalid. */
512 if (pcHostModeName != NULL)
513 {
514 pScrn->display->modes[i] = pcHostModeName;
515 ++i;
516 }
517 if (vboxHostLikesVideoMode(1024, 768, pScrn->bitsPerPixel))
518 {
519 pScrn->display->modes[i] = "1024x768";
520 ++i;
521 }
522 if (vboxHostLikesVideoMode(800, 600, pScrn->bitsPerPixel))
523 {
524 pScrn->display->modes[i] = "800x600";
525 ++i;
526 }
527 /* A mode of last resort */
528 pScrn->display->modes[i] = "640x480";
529 ++i;
530 pScrn->display->modes[i] = NULL;
531
532 /* Create a builtin mode for every specified mode. This allows to specify arbitrary
533 * screen resolutions */
534 m_prev = NULL;
535 for (i = 0; pScrn->display->modes[i] != NULL; i++)
536 {
537 DisplayModePtr m;
538 int x = 0, y = 0;
539
540 sscanf(pScrn->display->modes[i], "%dx%d", &x, &y);
541 m = xnfcalloc(sizeof(DisplayModeRec), 1);
542 m->status = MODE_OK;
543 m->type = M_T_BUILTIN;
544 /* VBox does only support screen widths which are a multiple of 8 */
545 m->HDisplay = (x + 7) & ~7;
546 m->HSyncStart = m->HDisplay + 2;
547 m->HSyncEnd = m->HDisplay + 4;
548 m->HTotal = m->HDisplay + 6;
549 m->VDisplay = y;
550 m->VSyncStart = m->VDisplay + 2;
551 m->VSyncEnd = m->VDisplay + 4;
552 m->VTotal = m->VDisplay + 6;
553 m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
554 m->name = strdup(pScrn->display->modes[i]);
555 if (!m_prev)
556 pScrn->modePool = m;
557 else
558 m_prev->next = m;
559 m->prev = m_prev;
560 m_prev = m;
561 }
562
563 /* Colour weight - we always call this, since we are always in
564 truecolour. */
565 if (!xf86SetWeight(pScrn, rzeros, rzeros))
566 return (FALSE);
567
568 /* visual init */
569 if (!xf86SetDefaultVisual(pScrn, -1))
570 return (FALSE);
571
572 xf86SetGamma(pScrn, gzeros);
573
574 /* Set a sane minimum mode size and the maximum allowed by the available VRAM */
575 {
576 unsigned maxSize, trySize = 512;
577
578 do {
579 maxSize = trySize;
580 trySize += 128;
581 } while (trySize * trySize * pScrn->bitsPerPixel / 8 < pScrn->videoRam * 1024);
582
583 /* I don't know exactly what these are for (and they are only used in a couple
584 of places in the X server code). */
585 pScrn->display->virtualX = maxSize;
586 pScrn->display->virtualY = maxSize;
587 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
588 "The maximum supported resolution is currently %dx%d\n", maxSize, maxSize);
589 }
590
591 /* Filter out video modes not supported by the virtual hardware
592 we described. */
593 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
594 pScrn->display->modes,
595 clockRanges, NULL, 64, pScrn->display->virtualX, 1,
596 64, pScrn->display->virtualY, 0, 0,
597 pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
598
599 if (i <= 0) {
600 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
601 return (FALSE);
602 }
603 xf86PruneDriverModes(pScrn);
604
605 pScrn->currentMode = pScrn->modes;
606 pScrn->displayWidth = pScrn->virtualX;
607
608 xf86PrintModes(pScrn);
609
610 /* Set display resolution. Perhaps we should read this from the host. */
611 xf86SetDpi(pScrn, 96, 96);
612
613 if (pScrn->modes == NULL) {
614 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
615 return (FALSE);
616 }
617
618 /* options */
619 xf86CollectOptions(pScrn, NULL);
620 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
621 return FALSE;
622 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
623 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
624
625 /* Framebuffer-related setup */
626 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
627 return (TRUE);
628}
629
630/*
631 * QUOTE from the XFree86 DESIGN document:
632 *
633 * This is called at the start of each server generation.
634 *
635 * (...)
636 *
637 * Decide which operations need to be placed under resource access
638 * control. (...) Map any video memory or other memory regions. (...)
639 * Save the video card state. (...) Initialise the initial video
640 * mode.
641 *
642 * End QUOTE.Initialise the initial video mode.
643 */
644static Bool
645VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
646{
647 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
648 VBOXPtr pVBox = VBOXGetRec(pScrn);
649 VisualPtr visual;
650 unsigned flags;
651
652 /* We make use of the X11 VBE code to save and restore text mode, in
653 order to keep our code simple. */
654 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
655 SET_BIOS_SCRATCH
656 | RESTORE_BIOS_SCRATCH)) == NULL)
657 return (FALSE);
658
659 if (pVBox->mapPhys == 0) {
660 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
661/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
662 /* Using the PCI information caused problems with
663 non-powers-of-two sized video RAM configurations */
664 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
665 pVBox->mapOff = 0;
666 }
667
668 if (!VBOXMapVidMem(pScrn))
669 return (FALSE);
670
671 /* save current video state */
672 VBOXSaveRestore(pScrn, MODE_SAVE);
673 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
674 NULL, FALSE, FALSE);
675
676 /* set first video mode */
677 if (!VBOXSetMode(pScrn, pScrn->currentMode))
678 return FALSE;
679
680 /* set the viewport */
681 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
682
683 /* Blank the screen for aesthetic reasons. */
684 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
685
686 /* mi layer - reset the visual list (?)*/
687 miClearVisualTypes();
688 if (!xf86SetDefaultVisual(pScrn, -1))
689 return (FALSE);
690 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
691 pScrn->rgbBits, TrueColor))
692 return (FALSE);
693 if (!miSetPixmapDepths())
694 return (FALSE);
695
696 /* I checked in the sources, and XFree86 4.2 does seem to support
697 this function for 32bpp. */
698 if (!fbScreenInit(pScreen, pVBox->base,
699 pScrn->virtualX, pScrn->virtualY,
700 pScrn->xDpi, pScrn->yDpi,
701 pScrn->displayWidth, pScrn->bitsPerPixel))
702 return (FALSE);
703
704 /* Fixup RGB ordering */
705 visual = pScreen->visuals + pScreen->numVisuals;
706 while (--visual >= pScreen->visuals) {
707 if ((visual->class | DynamicClass) == DirectColor) {
708 visual->offsetRed = pScrn->offset.red;
709 visual->offsetGreen = pScrn->offset.green;
710 visual->offsetBlue = pScrn->offset.blue;
711 visual->redMask = pScrn->mask.red;
712 visual->greenMask = pScrn->mask.green;
713 visual->blueMask = pScrn->mask.blue;
714 }
715 }
716
717 /* must be after RGB ordering fixed */
718 fbPictureInit(pScreen, 0, 0);
719
720 VBOXDGAInit(pScrn, pScreen);
721
722 xf86SetBlackWhitePixels(pScreen);
723 miInitializeBackingStore(pScreen);
724 xf86SetBackingStore(pScreen);
725
726 /* software cursor */
727 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
728
729 /* colourmap code - apparently, we need this even in Truecolour */
730 if (!miCreateDefColormap(pScreen))
731 return (FALSE);
732
733 flags = CMAP_RELOAD_ON_MODE_SWITCH;
734
735 if(!xf86HandleColormaps(pScreen, 256,
736 8 /* DAC is switchable to 8 bits per primary color */,
737 VBOXLoadPalette, NULL, flags))
738 return (FALSE);
739
740 pVBox->CloseScreen = pScreen->CloseScreen;
741 pScreen->CloseScreen = VBOXCloseScreen;
742 pScreen->SaveScreen = VBOXSaveScreen;
743
744 /* However, we probably do want to support power management -
745 even if we just use a dummy function. */
746 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
747
748 /* Report any unused options (only for the first generation) */
749 if (serverGeneration == 1)
750 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
751
752 if (vbox_open (pScrn, pScreen, pVBox)) {
753 if (vbox_cursor_init(pScreen) != TRUE)
754 xf86DrvMsg(scrnIndex, X_ERROR,
755 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
756 if (vboxEnableVbva(pScrn) == TRUE)
757 xf86DrvMsg(scrnIndex, X_INFO,
758 "The VBox video extensions are now enabled.\n");
759 }
760 return (TRUE);
761}
762
763static Bool
764VBOXEnterVT(int scrnIndex, int flags)
765{
766 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
767 VBOXPtr pVBox = VBOXGetRec(pScrn);
768
769 if (!VBOXSetMode(pScrn, pScrn->currentMode))
770 return FALSE;
771 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
772 if (pVBox->useVbva == TRUE)
773 vboxEnableVbva(pScrn);
774 return TRUE;
775}
776
777static void
778VBOXLeaveVT(int scrnIndex, int flags)
779{
780 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
781 VBOXPtr pVBox = VBOXGetRec(pScrn);
782
783 VBOXSaveRestore(pScrn, MODE_RESTORE);
784 if (pVBox->useVbva == TRUE)
785 vboxDisableVbva(pScrn);
786}
787
788static Bool
789VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
790{
791 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
792 VBOXPtr pVBox = VBOXGetRec(pScrn);
793
794 if (pVBox->useVbva == TRUE)
795 vboxDisableVbva(pScrn);
796 if (pScrn->vtSema) {
797 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
798 if (pVBox->savedPal)
799 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
800 pVBox->savedPal, FALSE, TRUE);
801 VBOXUnmapVidMem(pScrn);
802 }
803 if (pVBox->pDGAMode) {
804 xfree(pVBox->pDGAMode);
805 pVBox->pDGAMode = NULL;
806 pVBox->nDGAMode = 0;
807 }
808 pScrn->vtSema = FALSE;
809
810 pScreen->CloseScreen = pVBox->CloseScreen;
811 return pScreen->CloseScreen(scrnIndex, pScreen);
812}
813
814static Bool
815VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
816{
817 ScrnInfoPtr pScrn;
818 VBOXPtr pVBox;
819
820 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
821 pVBox = VBOXGetRec(pScrn);
822 if (pVBox->useVbva == TRUE)
823 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
824 return FALSE;
825 if (VBOXSetMode(pScrn, pMode) != TRUE)
826 return FALSE;
827 if (pVBox->useVbva == TRUE)
828 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
829 pVBox->useVbva = FALSE;
830 return TRUE;
831}
832
833/* Set a graphics mode */
834static Bool
835VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
836{
837 VBOXPtr pVBox;
838
839 int bpp = pScrn->depth == 24 ? 32 : 16;
840 int xRes = pMode->HDisplay;
841 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
842 >= pScrn->videoRam * 1024)
843 {
844 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
845 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
846 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
847 return FALSE;
848 }
849 /* We only support horizontal resolutions which are a multiple of 8. Round down if
850 necessary. */
851 if (xRes % 8 != 0)
852 {
853 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
854 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
855 xRes, xRes - (xRes % 8));
856 xRes = xRes - (xRes % 8);
857 }
858 pVBox = VBOXGetRec(pScrn);
859 pScrn->vtSema = TRUE;
860 /* Disable linear framebuffer mode before making changes to the resolution. */
861 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
862 outw(VBE_DISPI_IOPORT_DATA,
863 VBE_DISPI_DISABLED);
864 /* Unlike the resolution, the depth is fixed for a given screen
865 for the lifetime of the X session. */
866 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
867 outw(VBE_DISPI_IOPORT_DATA, bpp);
868 /* HDisplay and VDisplay are actually monitor information about
869 the display part of the scanlines. */
870 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
871 outw(VBE_DISPI_IOPORT_DATA, xRes);
872 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
873 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
874 /* Enable linear framebuffer mode. */
875 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
876 outw(VBE_DISPI_IOPORT_DATA,
877 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
878 /* Set the virtual resolution. We are still using VESA to control
879 the virtual offset. */
880 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
881 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
882 return (TRUE);
883}
884
885static void
886VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
887{
888 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
889
890 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
891}
892
893static void
894VBOXFreeScreen(int scrnIndex, int flags)
895{
896 VBOXFreeRec(xf86Screens[scrnIndex]);
897}
898
899static Bool
900VBOXMapVidMem(ScrnInfoPtr pScrn)
901{
902 VBOXPtr pVBox = VBOXGetRec(pScrn);
903
904 if (pVBox->base != NULL)
905 return (TRUE);
906
907 pScrn->memPhysBase = pVBox->mapPhys;
908 pScrn->fbOffset = pVBox->mapOff;
909
910 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
911 VIDMEM_FRAMEBUFFER,
912 pVBox->pciTag, pVBox->mapPhys,
913 (unsigned) pVBox->mapSize);
914
915 if (pVBox->base) {
916 pScrn->memPhysBase = pVBox->mapPhys;
917 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
918 pVBox->pciTag,
919 0xa0000, 0x10000);
920 }
921 /* We need this for saving/restoring textmode */
922 pVBox->ioBase = pScrn->domainIOBase;
923
924 return (pVBox->base != NULL);
925}
926
927static void
928VBOXUnmapVidMem(ScrnInfoPtr pScrn)
929{
930 VBOXPtr pVBox = VBOXGetRec(pScrn);
931
932 if (pVBox->base == NULL)
933 return;
934
935 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
936 (unsigned) pVBox->mapSize);
937 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
938 pVBox->base = NULL;
939}
940
941static void
942VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
943 LOCO *colors, VisualPtr pVisual)
944{
945 VBOXPtr pVBox = VBOXGetRec(pScrn);
946 int i, idx;
947#define VBOXDACDelay() \
948 do { \
949 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
950 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
951 } while (0)
952
953 for (i = 0; i < numColors; i++) {
954 idx = indices[i];
955 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
956 VBOXDACDelay();
957 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
958 VBOXDACDelay();
959 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
960 VBOXDACDelay();
961 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
962 VBOXDACDelay();
963 }
964}
965
966/*
967 * Just adapted from the std* functions in vgaHW.c
968 */
969static void
970WriteAttr(VBOXPtr pVBox, int index, int value)
971{
972 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
973
974 index |= 0x20;
975 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
976 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
977}
978
979static int
980ReadAttr(VBOXPtr pVBox, int index)
981{
982 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
983
984 index |= 0x20;
985 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
986 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
987}
988
989#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
990#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
991#define WriteSeq(index, value) \
992 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
993 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
994
995static int
996ReadSeq(VBOXPtr pVBox, int index)
997{
998 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
999
1000 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1001}
1002
1003#define WriteGr(index, value) \
1004 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1005 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1006
1007static int
1008ReadGr(VBOXPtr pVBox, int index)
1009{
1010 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1011
1012 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1013}
1014
1015#define WriteCrtc(index, value) \
1016 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1017 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1018
1019static void
1020SeqReset(VBOXPtr pVBox, Bool start)
1021{
1022 if (start) {
1023 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1024 }
1025 else {
1026 WriteSeq(0x00, 0x03); /* End Reset */
1027 }
1028}
1029
1030static void
1031SaveFonts(ScrnInfoPtr pScrn)
1032{
1033 VBOXPtr pVBox = VBOXGetRec(pScrn);
1034 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1035
1036 if (pVBox->fonts != NULL)
1037 return;
1038
1039 /* If in graphics mode, don't save anything */
1040 attr10 = ReadAttr(pVBox, 0x10);
1041 if (attr10 & 0x01)
1042 return;
1043
1044 pVBox->fonts = xalloc(16384);
1045
1046 /* save the registers that are needed here */
1047 miscOut = ReadMiscOut();
1048 gr4 = ReadGr(pVBox, 0x04);
1049 gr5 = ReadGr(pVBox, 0x05);
1050 gr6 = ReadGr(pVBox, 0x06);
1051 seq2 = ReadSeq(pVBox, 0x02);
1052 seq4 = ReadSeq(pVBox, 0x04);
1053
1054 /* Force into colour mode */
1055 WriteMiscOut(miscOut | 0x01);
1056
1057 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1058 SeqReset(pVBox, TRUE);
1059 WriteSeq(0x01, scrn);
1060 SeqReset(pVBox, FALSE);
1061
1062 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1063
1064 /*font1 */
1065 WriteSeq(0x02, 0x04); /* write to plane 2 */
1066 WriteSeq(0x04, 0x06); /* enable plane graphics */
1067 WriteGr(0x04, 0x02); /* read plane 2 */
1068 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1069 WriteGr(0x06, 0x05); /* set graphics */
1070 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1071
1072 /* font2 */
1073 WriteSeq(0x02, 0x08); /* write to plane 3 */
1074 WriteSeq(0x04, 0x06); /* enable plane graphics */
1075 WriteGr(0x04, 0x03); /* read plane 3 */
1076 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1077 WriteGr(0x06, 0x05); /* set graphics */
1078 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1079
1080 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1081 SeqReset(pVBox, TRUE);
1082 WriteSeq(0x01, scrn);
1083 SeqReset(pVBox, FALSE);
1084
1085 /* Restore clobbered registers */
1086 WriteAttr(pVBox, 0x10, attr10);
1087 WriteSeq(0x02, seq2);
1088 WriteSeq(0x04, seq4);
1089 WriteGr(0x04, gr4);
1090 WriteGr(0x05, gr5);
1091 WriteGr(0x06, gr6);
1092 WriteMiscOut(miscOut);
1093}
1094
1095static void
1096RestoreFonts(ScrnInfoPtr pScrn)
1097{
1098 VBOXPtr pVBox = VBOXGetRec(pScrn);
1099 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1100
1101 if (pVBox->fonts == NULL)
1102 return;
1103
1104 /* save the registers that are needed here */
1105 miscOut = ReadMiscOut();
1106 attr10 = ReadAttr(pVBox, 0x10);
1107 gr1 = ReadGr(pVBox, 0x01);
1108 gr3 = ReadGr(pVBox, 0x03);
1109 gr4 = ReadGr(pVBox, 0x04);
1110 gr5 = ReadGr(pVBox, 0x05);
1111 gr6 = ReadGr(pVBox, 0x06);
1112 gr8 = ReadGr(pVBox, 0x08);
1113 seq2 = ReadSeq(pVBox, 0x02);
1114 seq4 = ReadSeq(pVBox, 0x04);
1115
1116 /* Force into colour mode */
1117 WriteMiscOut(miscOut | 0x01);
1118
1119 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1120 SeqReset(pVBox, TRUE);
1121 WriteSeq(0x01, scrn);
1122 SeqReset(pVBox, FALSE);
1123
1124 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1125 if (pScrn->depth == 4) {
1126 /* GJA */
1127 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1128 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1129 WriteGr(0x01, 0x00); /* all planes come from CPU */
1130 }
1131
1132 WriteSeq(0x02, 0x04); /* write to plane 2 */
1133 WriteSeq(0x04, 0x06); /* enable plane graphics */
1134 WriteGr(0x04, 0x02); /* read plane 2 */
1135 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1136 WriteGr(0x06, 0x05); /* set graphics */
1137 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1138
1139 WriteSeq(0x02, 0x08); /* write to plane 3 */
1140 WriteSeq(0x04, 0x06); /* enable plane graphics */
1141 WriteGr(0x04, 0x03); /* read plane 3 */
1142 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1143 WriteGr(0x06, 0x05); /* set graphics */
1144 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1145
1146 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1147 SeqReset(pVBox, TRUE);
1148 WriteSeq(0x01, scrn);
1149 SeqReset(pVBox, FALSE);
1150
1151 /* restore the registers that were changed */
1152 WriteMiscOut(miscOut);
1153 WriteAttr(pVBox, 0x10, attr10);
1154 WriteGr(0x01, gr1);
1155 WriteGr(0x03, gr3);
1156 WriteGr(0x04, gr4);
1157 WriteGr(0x05, gr5);
1158 WriteGr(0x06, gr6);
1159 WriteGr(0x08, gr8);
1160 WriteSeq(0x02, seq2);
1161 WriteSeq(0x04, seq4);
1162}
1163
1164static Bool
1165VBOXSaveScreen(ScreenPtr pScreen, int mode)
1166{
1167 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1168 VBOXPtr pVBox = VBOXGetRec(pScrn);
1169 Bool on = xf86IsUnblank(mode);
1170
1171 if (on)
1172 SetTimeSinceLastInputEvent();
1173
1174 if (pScrn->vtSema) {
1175 unsigned char scrn = ReadSeq(pVBox, 0x01);
1176
1177 if (on)
1178 scrn &= ~0x20;
1179 else
1180 scrn |= 0x20;
1181 SeqReset(pVBox, TRUE);
1182 WriteSeq(0x01, scrn);
1183 SeqReset(pVBox, FALSE);
1184 }
1185
1186 return (TRUE);
1187}
1188
1189Bool
1190VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1191{
1192 VBOXPtr pVBox;
1193
1194 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1195 return (FALSE);
1196
1197 pVBox = VBOXGetRec(pScrn);
1198
1199
1200 /* Query amount of memory to save state */
1201 if (function == MODE_QUERY ||
1202 (function == MODE_SAVE && pVBox->state == NULL))
1203 {
1204
1205 /* Make sure we save at least this information in case of failure */
1206 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1207 SaveFonts(pScrn);
1208
1209 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1210 &pVBox->stateSize,&pVBox->statePage))
1211 return FALSE;
1212 }
1213
1214 /* Save/Restore Super VGA state */
1215 if (function != MODE_QUERY) {
1216 Bool retval = TRUE;
1217
1218 if (function == MODE_RESTORE)
1219 memcpy(pVBox->state, pVBox->pstate,
1220 (unsigned) pVBox->stateSize);
1221
1222 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1223 (pointer)&pVBox->state,
1224 &pVBox->stateSize,&pVBox->statePage))
1225 && function == MODE_SAVE)
1226 {
1227 /* don't rely on the memory not being touched */
1228 if (pVBox->pstate == NULL)
1229 pVBox->pstate = xalloc(pVBox->stateSize);
1230 memcpy(pVBox->pstate, pVBox->state,
1231 (unsigned) pVBox->stateSize);
1232 }
1233
1234 if (function == MODE_RESTORE)
1235 {
1236 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1237 RestoreFonts(pScrn);
1238 }
1239
1240 if (!retval)
1241 return (FALSE);
1242
1243 }
1244
1245 return (TRUE);
1246}
1247
1248static void
1249VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1250 int flags)
1251{
1252 /* VBox is always power efficient... */
1253}
1254
1255
1256
1257
1258/***********************************************************************
1259 * DGA stuff
1260 ***********************************************************************/
1261static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1262 unsigned char **ApertureBase,
1263 int *ApertureSize, int *ApertureOffset,
1264 int *flags);
1265static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1266static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1267
1268static Bool
1269VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1270 unsigned char **ApertureBase, int *ApertureSize,
1271 int *ApertureOffset, int *flags)
1272{
1273 VBOXPtr pVBox = VBOXGetRec(pScrn);
1274
1275 *DeviceName = NULL; /* No special device */
1276 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1277 *ApertureSize = pVBox->mapSize;
1278 *ApertureOffset = pVBox->mapOff;
1279 *flags = DGA_NEED_ROOT;
1280
1281 return (TRUE);
1282}
1283
1284static Bool
1285VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1286{
1287 DisplayModePtr pMode;
1288 int scrnIdx = pScrn->pScreen->myNum;
1289 int frameX0, frameY0;
1290
1291 if (pDGAMode) {
1292 pMode = pDGAMode->mode;
1293 frameX0 = frameY0 = 0;
1294 }
1295 else {
1296 if (!(pMode = pScrn->currentMode))
1297 return (TRUE);
1298
1299 frameX0 = pScrn->frameX0;
1300 frameY0 = pScrn->frameY0;
1301 }
1302
1303 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1304 return (FALSE);
1305 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1306
1307 return (TRUE);
1308}
1309
1310static void
1311VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1312{
1313 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1314}
1315
1316static int
1317VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1318{
1319 return (0);
1320}
1321
1322static DGAFunctionRec VBOXDGAFunctions =
1323{
1324 VBOXDGAOpenFramebuffer,
1325 NULL, /* CloseFramebuffer */
1326 VBOXDGASetMode,
1327 VBOXDGASetViewport,
1328 VBOXDGAGetViewport,
1329 NULL, /* Sync */
1330 NULL, /* FillRect */
1331 NULL, /* BlitRect */
1332 NULL, /* BlitTransRect */
1333};
1334
1335static void
1336VBOXDGAAddModes(ScrnInfoPtr pScrn)
1337{
1338 VBOXPtr pVBox = VBOXGetRec(pScrn);
1339 DisplayModePtr pMode = pScrn->modes;
1340 DGAModePtr pDGAMode;
1341
1342 do {
1343 pDGAMode = xrealloc(pVBox->pDGAMode,
1344 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1345 if (!pDGAMode)
1346 break;
1347
1348 pVBox->pDGAMode = pDGAMode;
1349 pDGAMode += pVBox->nDGAMode;
1350 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1351
1352 ++pVBox->nDGAMode;
1353 pDGAMode->mode = pMode;
1354 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1355 pDGAMode->byteOrder = pScrn->imageByteOrder;
1356 pDGAMode->depth = pScrn->depth;
1357 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1358 pDGAMode->red_mask = pScrn->mask.red;
1359 pDGAMode->green_mask = pScrn->mask.green;
1360 pDGAMode->blue_mask = pScrn->mask.blue;
1361 pDGAMode->visualClass = TrueColor;
1362 pDGAMode->xViewportStep = 1;
1363 pDGAMode->yViewportStep = 1;
1364 pDGAMode->viewportWidth = pMode->HDisplay;
1365 pDGAMode->viewportHeight = pMode->VDisplay;
1366
1367 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1368 pDGAMode->imageWidth = pMode->HDisplay;
1369 pDGAMode->imageHeight = pMode->VDisplay;
1370 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1371 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1372 pDGAMode->maxViewportX = pScrn->virtualX -
1373 pDGAMode->viewportWidth;
1374 pDGAMode->maxViewportY = pScrn->virtualY -
1375 pDGAMode->viewportHeight;
1376
1377 pDGAMode->address = pVBox->base;
1378
1379 pMode = pMode->next;
1380 } while (pMode != pScrn->modes);
1381}
1382
1383static Bool
1384VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1385{
1386 VBOXPtr pVBox = VBOXGetRec(pScrn);
1387
1388 if (!pVBox->nDGAMode)
1389 VBOXDGAAddModes(pScrn);
1390
1391 return (DGAInit(pScreen, &VBOXDGAFunctions,
1392 pVBox->pDGAMode, pVBox->nDGAMode));
1393}
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