VirtualBox

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

Last change on this file since 6484 was 6301, checked in by vboxsync, 17 years ago

Solaris guest additions: Got x11 vboxvideo working. Changed guest kernel driver ioctl, verified with previously working additions.

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