VirtualBox

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

Last change on this file since 3827 was 3270, checked in by vboxsync, 18 years ago

Removed code from the xorg 7 video Additions which uses a function which may not be present in xorg 7.0 and 7.1

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

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