VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xgraphics/vboxvideo_70.c@ 4997

Last change on this file since 4997 was 4335, checked in by vboxsync, 17 years ago

Linux guest additions: clock frequency is kHz, not MHz

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