VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_14.c@ 6356

Last change on this file since 6356 was 6202, checked in by vboxsync, 17 years ago

re-export x11

  • Property svn:eol-style set to native
File size: 42.7 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 ModeStatus VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass);
91static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
92static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
93static void VBOXFreeScreen(int scrnIndex, int flags);
94static void VBOXFreeRec(ScrnInfoPtr pScrn);
95static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
96 int flags);
97
98/* locally used functions */
99static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
100static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
101static void VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors,
102 int *indices,
103 LOCO *colors, VisualPtr pVisual);
104static void SaveFonts(ScrnInfoPtr pScrn);
105static void RestoreFonts(ScrnInfoPtr pScrn);
106static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
107 vbeSaveRestoreFunction function);
108
109/* Initialise DGA */
110
111static Bool VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
112
113/*
114 * This contains the functions needed by the server after loading the
115 * driver module. It must be supplied, and gets added the driver list by
116 * the Module Setup funtion in the dynamic case. In the static case a
117 * reference to this is compiled in, and this requires that the name of
118 * this DriverRec be an upper-case version of the driver name.
119 */
120
121_X_EXPORT DriverRec VBOXDRV = {
122 VBOX_VERSION,
123 VBOX_DRIVER_NAME,
124 VBOXIdentify,
125 VBOXProbe,
126 VBOXAvailableOptions,
127 NULL,
128 0,
129 NULL
130};
131
132/* Supported chipsets */
133static SymTabRec VBOXChipsets[] =
134{
135 {VBOX_VESA_DEVICEID, "vbox"},
136 {-1, NULL}
137};
138
139static PciChipsets VBOXPCIchipsets[] = {
140 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
141 { -1, -1, RES_UNDEFINED },
142};
143
144typedef enum {
145 OPTION_SHADOW_FB,
146 OPTION_DFLT_REFRESH,
147 OPTION_MODESET_CLEAR_SCREEN
148} VBOXOpts;
149
150/* No options for now */
151static const OptionInfoRec VBOXOptions[] = {
152 { -1, NULL, OPTV_NONE, {0}, FALSE }
153};
154
155/*
156 * List of symbols from other modules that this module references. This
157 * list is used to tell the loader that it is OK for symbols here to be
158 * unresolved providing that it hasn't been told that they haven't been
159 * told that they are essential via a call to xf86LoaderReqSymbols() or
160 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
161 * unresolved symbols that are not required.
162 */
163static const char *fbSymbols[] = {
164 "fbPictureInit",
165 "fbScreenInit",
166 NULL
167};
168
169static const char *shadowfbSymbols[] = {
170 "ShadowFBInit2",
171 NULL
172};
173
174static const char *vbeSymbols[] = {
175 "VBEExtendedInit",
176 "VBEFindSupportedDepths",
177 "VBEGetModeInfo",
178 "VBEGetVBEInfo",
179 "VBEGetVBEMode",
180 "VBEPrintModes",
181 "VBESaveRestore",
182 "VBESetDisplayStart",
183 "VBESetGetDACPaletteFormat",
184 "VBESetGetLogicalScanlineLength",
185 "VBESetGetPaletteData",
186 "VBESetModeNames",
187 "VBESetModeParameters",
188 "VBESetVBEMode",
189 "VBEValidateModes",
190 "vbeDoEDID",
191 "vbeFree",
192 NULL
193};
194
195static const char *ramdacSymbols[] = {
196 "xf86InitCursor",
197 "xf86CreateCursorInfoRec",
198 NULL
199};
200
201#ifdef XFree86LOADER
202/* Module loader interface */
203static MODULESETUPPROTO(vboxSetup);
204
205static XF86ModuleVersionInfo vboxVersionRec =
206{
207 VBOX_DRIVER_NAME,
208 "innotek GmbH",
209 MODINFOSTRING1,
210 MODINFOSTRING2,
211 XORG_VERSION_CURRENT,
212 1, /* Module major version. Xorg-specific */
213 0, /* Module minor version. Xorg-specific */
214 1, /* Module patchlevel. Xorg-specific */
215 ABI_CLASS_VIDEODRV, /* This is a video driver */
216 ABI_VIDEODRV_VERSION,
217 MOD_CLASS_VIDEODRV,
218 {0, 0, 0, 0}
219};
220
221/*
222 * This data is accessed by the loader. The name must be the module name
223 * followed by "ModuleData".
224 */
225_X_EXPORT XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
226
227static pointer
228vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
229{
230 static Bool Initialised = FALSE;
231
232 if (!Initialised)
233 {
234 Initialised = TRUE;
235 xf86AddDriver(&VBOXDRV, Module, 0);
236 LoaderRefSymLists(fbSymbols,
237 shadowfbSymbols,
238 vbeSymbols,
239 ramdacSymbols,
240 NULL);
241 return (pointer)TRUE;
242 }
243
244 if (ErrorMajor)
245 *ErrorMajor = LDR_ONCEONLY;
246 return (NULL);
247}
248
249#endif /* XFree86Loader defined */
250
251static const OptionInfoRec *
252VBOXAvailableOptions(int chipid, int busid)
253{
254 return (VBOXOptions);
255}
256
257static void
258VBOXIdentify(int flags)
259{
260 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
261}
262
263/*
264 * This function is called once, at the start of the first server generation to
265 * do a minimal probe for supported hardware.
266 */
267
268static Bool
269VBOXProbe(DriverPtr drv, int flags)
270{
271 Bool foundScreen = FALSE;
272 int numDevSections, numUsed;
273 GDevPtr *devSections;
274 int *usedChips;
275 int i;
276
277 /*
278 * Find the config file Device sections that match this
279 * driver, and return if there are none.
280 */
281 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
282 &devSections)) <= 0)
283 return (FALSE);
284
285 /* PCI BUS */
286 if (xf86GetPciVideoInfo()) {
287 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
288 VBOXChipsets, VBOXPCIchipsets,
289 devSections, numDevSections,
290 drv, &usedChips);
291 if (numUsed > 0) {
292 if (flags & PROBE_DETECT)
293 foundScreen = TRUE;
294 else {
295 for (i = 0; i < numUsed; i++) {
296 ScrnInfoPtr pScrn = NULL;
297 /* Allocate a ScrnInfoRec */
298 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
299 VBOXPCIchipsets,NULL,
300 NULL,NULL,NULL,NULL))) {
301 pScrn->driverVersion = VBOX_VERSION;
302 pScrn->driverName = VBOX_DRIVER_NAME;
303 pScrn->name = VBOX_NAME;
304 pScrn->Probe = VBOXProbe;
305 pScrn->PreInit = VBOXPreInit;
306 pScrn->ScreenInit = VBOXScreenInit;
307 pScrn->SwitchMode = VBOXSwitchMode;
308 pScrn->ValidMode = VBOXValidMode;
309 pScrn->AdjustFrame = VBOXAdjustFrame;
310 pScrn->EnterVT = VBOXEnterVT;
311 pScrn->LeaveVT = VBOXLeaveVT;
312 pScrn->FreeScreen = VBOXFreeScreen;
313 foundScreen = TRUE;
314 }
315 }
316 }
317 xfree(usedChips);
318 }
319 }
320 xfree(devSections);
321
322 return (foundScreen);
323}
324
325static VBOXPtr
326VBOXGetRec(ScrnInfoPtr pScrn)
327{
328 if (!pScrn->driverPrivate)
329 {
330 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
331 ((VBOXPtr)pScrn->driverPrivate)->vbox_fd = -1;
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
783/**
784 * Quoted from "How to add an (S)VGA driver to XFree86"
785 * (http://www.xfree86.org/3.3.6/VGADriver.html):
786 *
787 * The ValidMode() function is required. It is used to check for any
788 * chipset-dependent reasons why a graphics mode might not be valid. It gets
789 * called by higher levels of the code after the Probe() stage. In many cases
790 * no special checking will be required and this function will simply return
791 * TRUE always.
792 *
793 * Note: we check here that our generated video modes fulfil the X server's
794 * criteria for the monitor, since this can otherwise cause problems in
795 * randr 1.2.
796 */
797static ModeStatus
798VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
799{
800 static int warned = 0;
801 ScrnInfoPtr pScrn = xf86Screens[scrn];
802 MonPtr mon = pScrn->monitor;
803 ModeStatus ret = MODE_BAD;
804 DisplayModePtr mode;
805 float v;
806
807 if (pass != MODECHECK_FINAL) {
808 if (!warned) {
809 xf86DrvMsg(scrn, X_WARNING, "VBOXValidMode called unexpectedly\n");
810 warned = 1;
811 }
812 }
813 /*
814 * First off, if this isn't a mode we handed to the server (ie,
815 * M_T_BUILTIN), then we reject it out of hand.
816 */
817 if (!(p->type & M_T_BUILTIN))
818 return MODE_NOMODE;
819 /*
820 * Finally, walk through the vsync rates 1Hz at a time looking for a mode
821 * that will fit. This is assuredly a terrible way to do this, but
822 * there's no obvious method for computing a mode of a given size that
823 * will pass xf86CheckModeForMonitor.
824 */
825 for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
826 mode = xf86CVTMode(p->HDisplay, p->VDisplay, v, 0, 0);
827 ret = xf86CheckModeForMonitor(mode, mon);
828 xfree(mode);
829 if (ret == MODE_OK)
830 break;
831 }
832
833 if (ret != MODE_OK)
834 {
835 xf86DrvMsg(scrn, X_WARNING, "Graphics mode %s rejected by the X server\n", p->name);
836 }
837 return ret;
838}
839
840static Bool
841VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
842{
843 ScrnInfoPtr pScrn;
844 VBOXPtr pVBox;
845
846 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
847 pVBox = VBOXGetRec(pScrn);
848 if (pVBox->useVbva == TRUE)
849 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
850 return FALSE;
851 if (VBOXSetMode(pScrn, pMode) != TRUE)
852 return FALSE;
853 if (pVBox->useVbva == TRUE)
854 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
855 pVBox->useVbva = FALSE;
856 return TRUE;
857}
858
859/* Set a graphics mode */
860static Bool
861VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
862{
863 VBOXPtr pVBox;
864
865 int bpp = pScrn->depth == 24 ? 32 : 16;
866 int xRes = pMode->HDisplay;
867 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
868 >= pScrn->videoRam * 1024)
869 {
870 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
871 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
872 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
873 return FALSE;
874 }
875 /* We only support horizontal resolutions which are a multiple of 8. Round down if
876 necessary. */
877 if (xRes % 8 != 0)
878 {
879 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
880 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
881 xRes, xRes - (xRes % 8));
882 xRes = xRes - (xRes % 8);
883 }
884 pVBox = VBOXGetRec(pScrn);
885 pScrn->vtSema = TRUE;
886 /* Disable linear framebuffer mode before making changes to the resolution. */
887 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
888 outw(VBE_DISPI_IOPORT_DATA,
889 VBE_DISPI_DISABLED);
890 /* Unlike the resolution, the depth is fixed for a given screen
891 for the lifetime of the X session. */
892 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
893 outw(VBE_DISPI_IOPORT_DATA, bpp);
894 /* HDisplay and VDisplay are actually monitor information about
895 the display part of the scanlines. */
896 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
897 outw(VBE_DISPI_IOPORT_DATA, xRes);
898 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
899 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
900 /* Enable linear framebuffer mode. */
901 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
902 outw(VBE_DISPI_IOPORT_DATA,
903 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
904 /* Set the virtual resolution. We are still using VESA to control
905 the virtual offset. */
906 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
907 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
908 return (TRUE);
909}
910
911static void
912VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
913{
914 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
915
916 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
917}
918
919static void
920VBOXFreeScreen(int scrnIndex, int flags)
921{
922 VBOXFreeRec(xf86Screens[scrnIndex]);
923}
924
925static Bool
926VBOXMapVidMem(ScrnInfoPtr pScrn)
927{
928 VBOXPtr pVBox = VBOXGetRec(pScrn);
929
930 if (pVBox->base != NULL)
931 return (TRUE);
932
933 pScrn->memPhysBase = pVBox->mapPhys;
934 pScrn->fbOffset = pVBox->mapOff;
935
936 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
937 VIDMEM_FRAMEBUFFER,
938 pVBox->pciTag, pVBox->mapPhys,
939 (unsigned) pVBox->mapSize);
940
941 if (pVBox->base) {
942 pScrn->memPhysBase = pVBox->mapPhys;
943 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
944 pVBox->pciTag,
945 0xa0000, 0x10000);
946 }
947 /* We need this for saving/restoring textmode */
948 pVBox->ioBase = pScrn->domainIOBase;
949
950 return (pVBox->base != NULL);
951}
952
953static void
954VBOXUnmapVidMem(ScrnInfoPtr pScrn)
955{
956 VBOXPtr pVBox = VBOXGetRec(pScrn);
957
958 if (pVBox->base == NULL)
959 return;
960
961 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
962 (unsigned) pVBox->mapSize);
963 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
964 pVBox->base = NULL;
965}
966
967static void
968VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
969 LOCO *colors, VisualPtr pVisual)
970{
971 VBOXPtr pVBox = VBOXGetRec(pScrn);
972 int i, idx;
973#define VBOXDACDelay() \
974 do { \
975 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
976 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
977 } while (0)
978
979 for (i = 0; i < numColors; i++) {
980 idx = indices[i];
981 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
982 VBOXDACDelay();
983 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
984 VBOXDACDelay();
985 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
986 VBOXDACDelay();
987 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
988 VBOXDACDelay();
989 }
990}
991
992/*
993 * Just adapted from the std* functions in vgaHW.c
994 */
995static void
996WriteAttr(VBOXPtr pVBox, int index, int value)
997{
998 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
999
1000 index |= 0x20;
1001 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1002 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
1003}
1004
1005static int
1006ReadAttr(VBOXPtr pVBox, int index)
1007{
1008 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1009
1010 index |= 0x20;
1011 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1012 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
1013}
1014
1015#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
1016#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
1017#define WriteSeq(index, value) \
1018 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
1019 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
1020
1021static int
1022ReadSeq(VBOXPtr pVBox, int index)
1023{
1024 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
1025
1026 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1027}
1028
1029#define WriteGr(index, value) \
1030 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1031 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1032
1033static int
1034ReadGr(VBOXPtr pVBox, int index)
1035{
1036 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1037
1038 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1039}
1040
1041#define WriteCrtc(index, value) \
1042 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1043 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1044
1045static void
1046SeqReset(VBOXPtr pVBox, Bool start)
1047{
1048 if (start) {
1049 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1050 }
1051 else {
1052 WriteSeq(0x00, 0x03); /* End Reset */
1053 }
1054}
1055
1056static void
1057SaveFonts(ScrnInfoPtr pScrn)
1058{
1059 VBOXPtr pVBox = VBOXGetRec(pScrn);
1060 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1061
1062 if (pVBox->fonts != NULL)
1063 return;
1064
1065 /* If in graphics mode, don't save anything */
1066 attr10 = ReadAttr(pVBox, 0x10);
1067 if (attr10 & 0x01)
1068 return;
1069
1070 pVBox->fonts = xalloc(16384);
1071
1072 /* save the registers that are needed here */
1073 miscOut = ReadMiscOut();
1074 gr4 = ReadGr(pVBox, 0x04);
1075 gr5 = ReadGr(pVBox, 0x05);
1076 gr6 = ReadGr(pVBox, 0x06);
1077 seq2 = ReadSeq(pVBox, 0x02);
1078 seq4 = ReadSeq(pVBox, 0x04);
1079
1080 /* Force into colour mode */
1081 WriteMiscOut(miscOut | 0x01);
1082
1083 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1084 SeqReset(pVBox, TRUE);
1085 WriteSeq(0x01, scrn);
1086 SeqReset(pVBox, FALSE);
1087
1088 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1089
1090 /*font1 */
1091 WriteSeq(0x02, 0x04); /* write to plane 2 */
1092 WriteSeq(0x04, 0x06); /* enable plane graphics */
1093 WriteGr(0x04, 0x02); /* read plane 2 */
1094 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1095 WriteGr(0x06, 0x05); /* set graphics */
1096 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1097
1098 /* font2 */
1099 WriteSeq(0x02, 0x08); /* write to plane 3 */
1100 WriteSeq(0x04, 0x06); /* enable plane graphics */
1101 WriteGr(0x04, 0x03); /* read plane 3 */
1102 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1103 WriteGr(0x06, 0x05); /* set graphics */
1104 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1105
1106 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1107 SeqReset(pVBox, TRUE);
1108 WriteSeq(0x01, scrn);
1109 SeqReset(pVBox, FALSE);
1110
1111 /* Restore clobbered registers */
1112 WriteAttr(pVBox, 0x10, attr10);
1113 WriteSeq(0x02, seq2);
1114 WriteSeq(0x04, seq4);
1115 WriteGr(0x04, gr4);
1116 WriteGr(0x05, gr5);
1117 WriteGr(0x06, gr6);
1118 WriteMiscOut(miscOut);
1119}
1120
1121static void
1122RestoreFonts(ScrnInfoPtr pScrn)
1123{
1124 VBOXPtr pVBox = VBOXGetRec(pScrn);
1125 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1126
1127 if (pVBox->fonts == NULL)
1128 return;
1129
1130 /* save the registers that are needed here */
1131 miscOut = ReadMiscOut();
1132 attr10 = ReadAttr(pVBox, 0x10);
1133 gr1 = ReadGr(pVBox, 0x01);
1134 gr3 = ReadGr(pVBox, 0x03);
1135 gr4 = ReadGr(pVBox, 0x04);
1136 gr5 = ReadGr(pVBox, 0x05);
1137 gr6 = ReadGr(pVBox, 0x06);
1138 gr8 = ReadGr(pVBox, 0x08);
1139 seq2 = ReadSeq(pVBox, 0x02);
1140 seq4 = ReadSeq(pVBox, 0x04);
1141
1142 /* Force into colour mode */
1143 WriteMiscOut(miscOut | 0x01);
1144
1145 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1146 SeqReset(pVBox, TRUE);
1147 WriteSeq(0x01, scrn);
1148 SeqReset(pVBox, FALSE);
1149
1150 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1151 if (pScrn->depth == 4) {
1152 /* GJA */
1153 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1154 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1155 WriteGr(0x01, 0x00); /* all planes come from CPU */
1156 }
1157
1158 WriteSeq(0x02, 0x04); /* write to plane 2 */
1159 WriteSeq(0x04, 0x06); /* enable plane graphics */
1160 WriteGr(0x04, 0x02); /* read plane 2 */
1161 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1162 WriteGr(0x06, 0x05); /* set graphics */
1163 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1164
1165 WriteSeq(0x02, 0x08); /* write to plane 3 */
1166 WriteSeq(0x04, 0x06); /* enable plane graphics */
1167 WriteGr(0x04, 0x03); /* read plane 3 */
1168 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1169 WriteGr(0x06, 0x05); /* set graphics */
1170 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1171
1172 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1173 SeqReset(pVBox, TRUE);
1174 WriteSeq(0x01, scrn);
1175 SeqReset(pVBox, FALSE);
1176
1177 /* restore the registers that were changed */
1178 WriteMiscOut(miscOut);
1179 WriteAttr(pVBox, 0x10, attr10);
1180 WriteGr(0x01, gr1);
1181 WriteGr(0x03, gr3);
1182 WriteGr(0x04, gr4);
1183 WriteGr(0x05, gr5);
1184 WriteGr(0x06, gr6);
1185 WriteGr(0x08, gr8);
1186 WriteSeq(0x02, seq2);
1187 WriteSeq(0x04, seq4);
1188}
1189
1190static Bool
1191VBOXSaveScreen(ScreenPtr pScreen, int mode)
1192{
1193 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1194 VBOXPtr pVBox = VBOXGetRec(pScrn);
1195 Bool on = xf86IsUnblank(mode);
1196
1197 if (on)
1198 SetTimeSinceLastInputEvent();
1199
1200 if (pScrn->vtSema) {
1201 unsigned char scrn = ReadSeq(pVBox, 0x01);
1202
1203 if (on)
1204 scrn &= ~0x20;
1205 else
1206 scrn |= 0x20;
1207 SeqReset(pVBox, TRUE);
1208 WriteSeq(0x01, scrn);
1209 SeqReset(pVBox, FALSE);
1210 }
1211
1212 return (TRUE);
1213}
1214
1215Bool
1216VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1217{
1218 VBOXPtr pVBox;
1219
1220 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1221 return (FALSE);
1222
1223 pVBox = VBOXGetRec(pScrn);
1224
1225
1226 /* Query amount of memory to save state */
1227 if (function == MODE_QUERY ||
1228 (function == MODE_SAVE && pVBox->state == NULL))
1229 {
1230
1231 /* Make sure we save at least this information in case of failure */
1232 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1233 SaveFonts(pScrn);
1234
1235 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1236 &pVBox->stateSize,&pVBox->statePage))
1237 return FALSE;
1238 }
1239
1240 /* Save/Restore Super VGA state */
1241 if (function != MODE_QUERY) {
1242 Bool retval = TRUE;
1243
1244 if (function == MODE_RESTORE)
1245 memcpy(pVBox->state, pVBox->pstate,
1246 (unsigned) pVBox->stateSize);
1247
1248 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1249 (pointer)&pVBox->state,
1250 &pVBox->stateSize,&pVBox->statePage))
1251 && function == MODE_SAVE)
1252 {
1253 /* don't rely on the memory not being touched */
1254 if (pVBox->pstate == NULL)
1255 pVBox->pstate = xalloc(pVBox->stateSize);
1256 memcpy(pVBox->pstate, pVBox->state,
1257 (unsigned) pVBox->stateSize);
1258 }
1259
1260 if (function == MODE_RESTORE)
1261 {
1262 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1263 RestoreFonts(pScrn);
1264 }
1265
1266 if (!retval)
1267 return (FALSE);
1268
1269 }
1270
1271 return (TRUE);
1272}
1273
1274static void
1275VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1276 int flags)
1277{
1278 /* VBox is always power efficient... */
1279}
1280
1281
1282
1283
1284/***********************************************************************
1285 * DGA stuff
1286 ***********************************************************************/
1287static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1288 unsigned char **ApertureBase,
1289 int *ApertureSize, int *ApertureOffset,
1290 int *flags);
1291static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1292static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1293
1294static Bool
1295VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1296 unsigned char **ApertureBase, int *ApertureSize,
1297 int *ApertureOffset, int *flags)
1298{
1299 VBOXPtr pVBox = VBOXGetRec(pScrn);
1300
1301 *DeviceName = NULL; /* No special device */
1302 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1303 *ApertureSize = pVBox->mapSize;
1304 *ApertureOffset = pVBox->mapOff;
1305 *flags = DGA_NEED_ROOT;
1306
1307 return (TRUE);
1308}
1309
1310static Bool
1311VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1312{
1313 DisplayModePtr pMode;
1314 int scrnIdx = pScrn->pScreen->myNum;
1315 int frameX0, frameY0;
1316
1317 if (pDGAMode) {
1318 pMode = pDGAMode->mode;
1319 frameX0 = frameY0 = 0;
1320 }
1321 else {
1322 if (!(pMode = pScrn->currentMode))
1323 return (TRUE);
1324
1325 frameX0 = pScrn->frameX0;
1326 frameY0 = pScrn->frameY0;
1327 }
1328
1329 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1330 return (FALSE);
1331 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1332
1333 return (TRUE);
1334}
1335
1336static void
1337VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1338{
1339 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1340}
1341
1342static int
1343VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1344{
1345 return (0);
1346}
1347
1348static DGAFunctionRec VBOXDGAFunctions =
1349{
1350 VBOXDGAOpenFramebuffer,
1351 NULL, /* CloseFramebuffer */
1352 VBOXDGASetMode,
1353 VBOXDGASetViewport,
1354 VBOXDGAGetViewport,
1355 NULL, /* Sync */
1356 NULL, /* FillRect */
1357 NULL, /* BlitRect */
1358 NULL, /* BlitTransRect */
1359};
1360
1361static void
1362VBOXDGAAddModes(ScrnInfoPtr pScrn)
1363{
1364 VBOXPtr pVBox = VBOXGetRec(pScrn);
1365 DisplayModePtr pMode = pScrn->modes;
1366 DGAModePtr pDGAMode;
1367
1368 do {
1369 pDGAMode = xrealloc(pVBox->pDGAMode,
1370 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1371 if (!pDGAMode)
1372 break;
1373
1374 pVBox->pDGAMode = pDGAMode;
1375 pDGAMode += pVBox->nDGAMode;
1376 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1377
1378 ++pVBox->nDGAMode;
1379 pDGAMode->mode = pMode;
1380 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1381 pDGAMode->byteOrder = pScrn->imageByteOrder;
1382 pDGAMode->depth = pScrn->depth;
1383 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1384 pDGAMode->red_mask = pScrn->mask.red;
1385 pDGAMode->green_mask = pScrn->mask.green;
1386 pDGAMode->blue_mask = pScrn->mask.blue;
1387 pDGAMode->visualClass = TrueColor;
1388 pDGAMode->xViewportStep = 1;
1389 pDGAMode->yViewportStep = 1;
1390 pDGAMode->viewportWidth = pMode->HDisplay;
1391 pDGAMode->viewportHeight = pMode->VDisplay;
1392
1393 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1394 pDGAMode->imageWidth = pMode->HDisplay;
1395 pDGAMode->imageHeight = pMode->VDisplay;
1396 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1397 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1398 pDGAMode->maxViewportX = pScrn->virtualX -
1399 pDGAMode->viewportWidth;
1400 pDGAMode->maxViewportY = pScrn->virtualY -
1401 pDGAMode->viewportHeight;
1402
1403 pDGAMode->address = pVBox->base;
1404
1405 pMode = pMode->next;
1406 } while (pMode != pScrn->modes);
1407}
1408
1409static Bool
1410VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1411{
1412 VBOXPtr pVBox = VBOXGetRec(pScrn);
1413
1414 if (!pVBox->nDGAMode)
1415 VBOXDGAAddModes(pScrn);
1416
1417 return (DGAInit(pScreen, &VBOXDGAFunctions,
1418 pVBox->pDGAMode, pVBox->nDGAMode));
1419}
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