1
/* $Id: vboxvideo_13.c $ */
3
* Linux Additions X11 graphics driver
7
* Copyright (C) 2006-2010 Oracle Corporation
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
* --------------------------------------------------------------------
18
* This code is based on:
22
* Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
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:
31
* The above copyright notice and this permission notice shall be included in
32
* all copies or substantial portions of the Software.
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
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
47
* Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
50
#include "xorg-server.h"
51
#include "vboxvideo.h"
52
#include "version-generated.h"
53
#include "product-generated.h"
56
/* All drivers initialising the SW cursor need this */
57
#include "mipointer.h"
59
/* All drivers implementing backing store need this */
62
/* Colormap handling */
67
/* #define DPMS_SERVER
68
#include "extensions/dpms.h" */
70
/* VGA hardware functions for setting and restoring text mode */
73
/* X.org 1.3+ mode setting */
74
#define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
76
#include "xf86Modes.h"
78
/* Mandatory functions */
80
static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
81
static void VBOXIdentify(int flags);
83
static Bool VBOXProbe(DriverPtr drv, int flags);
85
static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
86
struct pci_device *dev, intptr_t match_data);
88
static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
89
static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
91
static Bool VBOXEnterVT(int scrnIndex, int flags);
92
static void VBOXLeaveVT(int scrnIndex, int flags);
93
static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
94
static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
95
static ModeStatus VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass);
96
static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
97
static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
98
static void VBOXFreeScreen(int scrnIndex, int flags);
99
static void VBOXFreeRec(ScrnInfoPtr pScrn);
101
/* locally used functions */
102
static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
103
static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
104
static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
105
vbeSaveRestoreFunction function);
113
static const struct pci_id_match vbox_device_match[] = {
115
VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
123
/* Supported chipsets */
124
static SymTabRec VBOXChipsets[] =
126
{VBOX_DEVICEID, "vbox"},
130
static PciChipsets VBOXPCIchipsets[] = {
131
{ VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
132
{ -1, -1, RES_UNDEFINED },
136
* This contains the functions needed by the server after loading the
137
* driver module. It must be supplied, and gets added the driver list by
138
* the Module Setup funtion in the dynamic case. In the static case a
139
* reference to this is compiled in, and this requires that the name of
140
* this DriverRec be an upper-case version of the driver name.
143
_X_EXPORT DriverRec VBOXVIDEO = {
152
VBOXAvailableOptions,
163
/* No options for now */
164
static const OptionInfoRec VBOXOptions[] = {
165
{ -1, NULL, OPTV_NONE, {0}, FALSE }
169
VBOXGetRec(ScrnInfoPtr pScrn)
171
if (!pScrn->driverPrivate) {
172
pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);
175
return ((VBOXPtr)pScrn->driverPrivate);
179
VBOXFreeRec(ScrnInfoPtr pScrn)
181
VBOXPtr pVBox = VBOXGetRec(pScrn);
182
free(pVBox->savedPal);
184
free(pScrn->driverPrivate);
185
pScrn->driverPrivate = NULL;
188
/* X.org 1.3+ mode-setting support ******************************************/
190
/* For descriptions of these functions and structures, see
191
hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
192
X.Org source tree. */
195
VBOXCrtcResize(ScrnInfoPtr scrn, int width, int height)
197
int bpp = scrn->bitsPerPixel;
198
ScreenPtr pScreen = scrn->pScreen;
199
PixmapPtr pPixmap = NULL;
200
VBOXPtr pVBox = VBOXGetRec(scrn);
203
TRACE_LOG("width=%d, height=%d\n", width, height);
204
if (width * height * bpp / 8 >= scrn->videoRam * 1024)
206
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
207
"Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
208
width, height, scrn->videoRam);
212
pPixmap = pScreen->GetScreenPixmap(pScreen);
213
if (NULL == pPixmap) {
214
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
215
"Failed to get the screen pixmap.\n");
221
!pScreen->ModifyPixmapHeader(pPixmap, width, height,
222
scrn->depth, bpp, width * bpp / 8,
225
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
226
"Failed to set up the screen pixmap.\n");
231
scrn->virtualX = width;
232
scrn->virtualY = height;
233
scrn->displayWidth = width;
236
VBOXDRIUpdateStride(scrn, pVBox);
238
/* Write the new values to the hardware */
239
rc = xf86SetDesiredModes(scrn);
241
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
245
static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
250
vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
251
{ (void) crtc; (void) mode; }
254
vbox_crtc_lock (xf86CrtcPtr crtc)
255
{ (void) crtc; return FALSE; }
258
vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
259
DisplayModePtr adjusted_mode)
260
{ (void) crtc; (void) mode; (void) adjusted_mode; return TRUE; }
263
vbox_crtc_stub (xf86CrtcPtr crtc)
267
vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
268
DisplayModePtr adjusted_mode, int x, int y)
271
TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
272
adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
273
VBOXSetMode(crtc->scrn, adjusted_mode);
274
VBOXAdjustFrame(crtc->scrn->scrnIndex, x, y, 0);
275
/* Don't remember any modes set while we are seamless, as they are
277
if (!vboxGuestIsSeamless(crtc->scrn))
278
vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
279
adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
283
vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
284
CARD16 *green, CARD16 *blue, int size)
285
{ (void) crtc; (void) red; (void) green; (void) blue; (void) size; }
288
vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
289
{ (void) crtc; (void) width; (void) height; return NULL; }
291
static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
292
.dpms = vbox_crtc_dpms,
293
.save = NULL, /* These two are never called by the server. */
295
.lock = vbox_crtc_lock,
296
.unlock = NULL, /* This will not be invoked if lock returns FALSE. */
297
.mode_fixup = vbox_crtc_mode_fixup,
298
.prepare = vbox_crtc_stub,
299
.mode_set = vbox_crtc_mode_set,
300
.commit = vbox_crtc_stub,
301
.gamma_set = vbox_crtc_gamma_set,
302
.shadow_allocate = vbox_crtc_shadow_allocate,
303
.shadow_create = NULL, /* These two should not be invoked if allocate
305
.shadow_destroy = NULL,
306
.set_cursor_colors = NULL, /* We are still using the old cursor API. */
307
.set_cursor_position = NULL,
310
.load_cursor_argb = NULL,
311
.destroy = vbox_crtc_stub
315
vbox_output_stub (xf86OutputPtr output)
319
vbox_output_dpms (xf86OutputPtr output, int mode)
320
{ (void) output; (void) mode; }
323
vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
325
ScrnInfoPtr pScrn = output->scrn;
327
TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);
328
/* We always like modes specified by the user in the configuration
329
* file and modes requested by the host, as doing otherwise is likely to
331
if ( !(mode->type & M_T_USERDEF)
332
&& !(mode->type & M_T_PREFERRED)
333
&& vbox_device_available(VBOXGetRec(pScrn))
334
&& !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,
338
TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");
343
vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
344
DisplayModePtr adjusted_mode)
345
{ (void) output; (void) mode; (void) adjusted_mode; return TRUE; }
348
vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
349
DisplayModePtr adjusted_mode)
350
{ (void) output; (void) mode; (void) adjusted_mode; }
352
/* A virtual monitor is always connected. */
353
static xf86OutputStatus
354
vbox_output_detect (xf86OutputPtr output)
357
return XF86OutputStatusConnected;
361
vbox_output_add_mode (VBOXPtr pVBox, DisplayModePtr *pModes,
362
const char *pszName, int x, int y,
363
Bool isPreferred, Bool isUserDef)
365
TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName, x, y);
366
DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
368
pMode->status = MODE_OK;
369
/* We don't ask the host whether it likes user defined modes,
370
* as we assume that the user really wanted that mode. */
371
pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
373
pMode->type |= M_T_PREFERRED;
374
/* Older versions of VBox only support screen widths which are a multiple
379
pMode->HDisplay = x & ~7;
380
pMode->HSyncStart = pMode->HDisplay + 2;
381
pMode->HSyncEnd = pMode->HDisplay + 4;
382
pMode->HTotal = pMode->HDisplay + 6;
384
pMode->VSyncStart = pMode->VDisplay + 2;
385
pMode->VSyncEnd = pMode->VDisplay + 4;
386
pMode->VTotal = pMode->VDisplay + 6;
387
pMode->Clock = pMode->HTotal * pMode->VTotal * 60 / 1000; /* kHz */
388
if (NULL == pszName) {
389
xf86SetModeDefaultName(pMode);
391
pMode->name = xnfstrdup(pszName);
393
*pModes = xf86ModesAdd(*pModes, pMode);
396
static DisplayModePtr
397
vbox_output_get_modes (xf86OutputPtr output)
401
DisplayModePtr pModes = NULL;
402
ScrnInfoPtr pScrn = output->scrn;
403
VBOXPtr pVBox = VBOXGetRec(pScrn);
406
if (vbox_device_available(pVBox))
408
uint32_t x, y, bpp, iScreen;
409
rc = vboxGetDisplayChangeRequest(pScrn, &x, &y, &bpp, &iScreen);
410
/* @todo - check the display number once we support multiple displays. */
411
/* If we don't find a display request, see if we have a saved hint
412
* from a previous session. */
413
if (!rc || (0 == x) || (0 == y))
414
rc = vboxRetrieveVideoMode(pScrn, &x, &y, &bpp);
415
if (rc && (0 != x) && (0 != y))
416
vbox_output_add_mode(pVBox, &pModes, NULL, x, y, TRUE, FALSE);
418
/* Also report any modes the user may have requested in the xorg.conf
419
* configuration file. */
420
for (i = 0; pScrn->display->modes[i] != NULL; i++)
423
if (2 == sscanf(pScrn->display->modes[i], "%dx%d", &x, &y))
424
vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y,
431
#ifdef RANDR_12_INTERFACE
432
/* We don't yet have mutable properties, whatever they are. */
434
vbox_output_set_property(xf86OutputPtr output, Atom property,
435
RRPropertyValuePtr value)
436
{ (void) output; (void) property; (void) value; return FALSE; }
439
static const xf86OutputFuncsRec VBOXOutputFuncs = {
440
.create_resources = vbox_output_stub,
441
.dpms = vbox_output_dpms,
442
.save = NULL, /* These two are never called by the server. */
444
.mode_valid = vbox_output_mode_valid,
445
.mode_fixup = vbox_output_mode_fixup,
446
.prepare = vbox_output_stub,
447
.commit = vbox_output_stub,
448
.mode_set = vbox_output_mode_set,
449
.detect = vbox_output_detect,
450
.get_modes = vbox_output_get_modes,
451
#ifdef RANDR_12_INTERFACE
452
.set_property = vbox_output_set_property,
454
.destroy = vbox_output_stub
458
/* Module loader interface */
459
static MODULESETUPPROTO(vboxSetup);
461
static XF86ModuleVersionInfo vboxVersionRec =
467
XORG_VERSION_CURRENT,
468
1, /* Module major version. Xorg-specific */
469
0, /* Module minor version. Xorg-specific */
470
1, /* Module patchlevel. Xorg-specific */
471
ABI_CLASS_VIDEODRV, /* This is a video driver */
472
ABI_VIDEODRV_VERSION,
478
* This data is accessed by the loader. The name must be the module name
479
* followed by "ModuleData".
481
_X_EXPORT XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
484
vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
486
static Bool Initialised = FALSE;
492
xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
494
xf86AddDriver(&VBOXVIDEO, Module, 0);
496
xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
498
return (pointer)TRUE;
502
*ErrorMajor = LDR_ONCEONLY;
506
#endif /* XFree86Loader defined */
508
static const OptionInfoRec *
509
VBOXAvailableOptions(int chipid, int busid)
511
return (VBOXOptions);
515
VBOXIdentify(int flags)
517
xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
521
* This function is called once, at the start of the first server generation to
522
* do a minimal probe for supported hardware.
527
VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
533
pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
534
NULL, NULL, NULL, NULL, NULL);
536
VBOXPtr pVBox = VBOXGetRec(pScrn);
538
pScrn->driverVersion = VBOX_VERSION;
539
pScrn->driverName = VBOX_DRIVER_NAME;
540
pScrn->name = VBOX_NAME;
542
pScrn->PreInit = VBOXPreInit;
543
pScrn->ScreenInit = VBOXScreenInit;
544
pScrn->SwitchMode = VBOXSwitchMode;
545
pScrn->ValidMode = VBOXValidMode;
546
pScrn->AdjustFrame = VBOXAdjustFrame;
547
pScrn->EnterVT = VBOXEnterVT;
548
pScrn->LeaveVT = VBOXLeaveVT;
549
pScrn->FreeScreen = VBOXFreeScreen;
551
pVBox->pciInfo = dev;
554
TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
555
return (pScrn != NULL);
561
VBOXProbe(DriverPtr drv, int flags)
563
Bool foundScreen = FALSE;
565
GDevPtr *devSections;
568
* Find the config file Device sections that match this
569
* driver, and return if there are none.
571
if ((numDevSections = xf86MatchDevice(VBOX_NAME,
576
if (xf86GetPciVideoInfo()) {
580
numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
581
VBOXChipsets, VBOXPCIchipsets,
582
devSections, numDevSections,
585
if (flags & PROBE_DETECT)
588
for (i = 0; i < numUsed; i++) {
589
ScrnInfoPtr pScrn = NULL;
590
/* Allocate a ScrnInfoRec */
591
if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
592
VBOXPCIchipsets,NULL,
593
NULL,NULL,NULL,NULL))) {
594
pScrn->driverVersion = VBOX_VERSION;
595
pScrn->driverName = VBOX_DRIVER_NAME;
596
pScrn->name = VBOX_NAME;
597
pScrn->Probe = VBOXProbe;
598
pScrn->PreInit = VBOXPreInit;
599
pScrn->ScreenInit = VBOXScreenInit;
600
pScrn->SwitchMode = VBOXSwitchMode;
601
pScrn->ValidMode = VBOXValidMode;
602
pScrn->AdjustFrame = VBOXAdjustFrame;
603
pScrn->EnterVT = VBOXEnterVT;
604
pScrn->LeaveVT = VBOXLeaveVT;
605
pScrn->FreeScreen = VBOXFreeScreen;
616
return (foundScreen);
621
* QUOTE from the XFree86 DESIGN document:
623
* The purpose of this function is to find out all the information
624
* required to determine if the configuration is usable, and to initialise
625
* those parts of the ScrnInfoRec that can be set once at the beginning of
626
* the first server generation.
630
* This includes probing for video memory, clocks, ramdac, and all other
631
* HW info that is needed. It includes determining the depth/bpp/visual
632
* and related info. It includes validating and determining the set of
633
* video modes that will be used (and anything that is required to
636
* This information should be determined in the least intrusive way
637
* possible. The state of the HW must remain unchanged by this function.
638
* Although video memory (including MMIO) may be mapped within this
639
* function, it must be unmapped before returning.
645
VBOXPreInit(ScrnInfoPtr pScrn, int flags)
648
Gamma gzeros = {0.0, 0.0, 0.0};
649
rgb rzeros = {0, 0, 0};
650
xf86OutputPtr output;
653
/* Are we really starting the server, or is this just a dummy run? */
654
if (flags & PROBE_DETECT)
657
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
658
"VirtualBox guest additions video driver version "
659
VBOX_VERSION_STRING "\n");
661
/* Get our private data from the ScrnInfoRec structure. */
662
pVBox = VBOXGetRec(pScrn);
664
/* Initialise the guest library */
665
vbox_init(pScrn->scrnIndex, pVBox);
667
/* Entity information seems to mean bus information. */
668
pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
670
/* We need the vbe module because we use VBE code to save and restore
671
text mode, in order to keep our code simple. */
672
if (!xf86LoadSubModule(pScrn, "vbe"))
675
if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
677
| RESTORE_BIOS_SCRATCH)) == NULL)
681
if (pVBox->pEnt->location.type != BUS_PCI)
684
pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
685
pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
686
pVBox->pciInfo->device,
687
pVBox->pciInfo->func);
690
/* The ramdac module is needed for the hardware cursor. */
691
if (!xf86LoadSubModule(pScrn, "ramdac"))
694
/* The framebuffer module. */
695
if (xf86LoadSubModule(pScrn, "fb") == NULL)
698
if (!xf86LoadSubModule(pScrn, "shadowfb"))
701
if (!xf86LoadSubModule(pScrn, "vgahw"))
704
/* Set up our ScrnInfoRec structure to describe our virtual
705
capabilities to X. */
707
pScrn->chipset = "vbox";
709
/* This *is* still needed, at least for server version 1.3 */
710
pScrn->monitor = pScrn->confScreen->monitor;
712
pScrn->progClock = TRUE;
715
/* Using the PCI information caused problems with non-powers-of-two
716
sized video RAM configurations */
717
pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
719
/* Check if the chip restricts horizontal resolution or not. */
720
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
721
outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
722
DispiId = inw(VBE_DISPI_IOPORT_DATA);
723
if (DispiId == VBE_DISPI_ID_ANYX)
726
pVBox->fAnyX = FALSE;
728
/* Query the host for the preferred colour depth */
730
uint32_t cx, cy, iDisplay, cBits = 24;
732
if (vbox_device_available(pVBox))
734
/* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
735
if ( vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,
741
if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
744
if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
746
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
747
"The VBox additions only support 16 and 32bpp graphics modes\n");
750
xf86PrintDepthBpp(pScrn);
753
xf86CollectOptions(pScrn, NULL);
754
if (!(pVBox->Options = malloc(sizeof(VBOXOptions))))
756
memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
757
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
759
/* Work around a bug in the original X server modesetting code, which
760
* took the first valid values set to these two as maxima over the
761
* server lifetime. */
762
pScrn->virtualX = 32000;
763
pScrn->virtualY = 32000;
765
/* Initialise CRTC and output configuration for use with randr1.2. */
766
xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
768
/* Setup our single virtual CRTC. */
769
xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
771
/* Set up our single virtual output. */
772
output = xf86OutputCreate(pScrn, &VBOXOutputFuncs, "VBOX1");
774
/* Set a sane minimum and maximum mode size */
775
xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
777
/* We are not interested in the monitor section in the configuration file. */
778
xf86OutputUseScreenMonitor(output, FALSE);
779
output->possible_crtcs = 1;
780
output->possible_clones = 0;
782
/* Now create our initial CRTC/output configuration. */
783
if (!xf86InitialConfiguration(pScrn, TRUE)) {
784
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
788
/* Colour weight - we always call this, since we are always in
790
if (!xf86SetWeight(pScrn, rzeros, rzeros))
794
if (!xf86SetDefaultVisual(pScrn, -1))
797
xf86SetGamma(pScrn, gzeros);
799
/* Set a default display resolution. */
800
xf86SetDpi(pScrn, 96, 96);
802
/* Framebuffer-related setup */
803
pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
805
/* VGA hardware initialisation */
806
if (!vgaHWGetHWRec(pScrn))
810
/* Load the dri module. */
811
if (!xf86LoadSubModule(pScrn, "dri"))
818
* This function hooks into the chain that is called when framebuffer access
819
* is allowed or disallowed by a call to EnableDisableFBAccess in the server.
820
* In other words, it observes when the server wishes access to the
821
* framebuffer to be enabled and when it should be disabled. We need to know
822
* this because we disable access ourselves during mode switches (presumably
823
* the server should do this but it doesn't) and want to know whether to
824
* restore it or not afterwards.
827
vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
829
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
830
VBOXPtr pVBox = VBOXGetRec(pScrn);
832
TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");
833
pVBox->accessEnabled = enable;
834
pVBox->EnableDisableFBAccess(scrnIndex, enable);
839
* QUOTE from the XFree86 DESIGN document:
841
* This is called at the start of each server generation.
845
* Decide which operations need to be placed under resource access
846
* control. (...) Map any video memory or other memory regions. (...)
847
* Save the video card state. (...) Initialise the initial video
850
* End QUOTE.Initialise the initial video mode.
853
VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
855
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
856
VBOXPtr pVBox = VBOXGetRec(pScrn);
860
if (pVBox->mapPhys == 0) {
862
pVBox->mapPhys = pVBox->pciInfo->regions[0].base_addr;
864
pVBox->mapPhys = pVBox->pciInfo->memBase[0];
866
/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
867
/* Using the PCI information caused problems with
868
non-powers-of-two sized video RAM configurations */
869
pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
873
if (!VBOXMapVidMem(pScrn))
876
/* save current video state */
877
VBOXSaveRestore(pScrn, MODE_SAVE);
878
pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
881
/* mi layer - reset the visual list (?)*/
882
miClearVisualTypes();
883
if (!xf86SetDefaultVisual(pScrn, -1))
885
if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
886
pScrn->rgbBits, TrueColor))
888
if (!miSetPixmapDepths())
891
/* Needed before we initialise DRI. */
892
pScrn->displayWidth = pScrn->virtualX;
895
pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
898
/* I checked in the sources, and XFree86 4.2 does seem to support
899
this function for 32bpp. */
900
if (!fbScreenInit(pScreen, pVBox->base,
901
pScrn->virtualX, pScrn->virtualY,
902
pScrn->xDpi, pScrn->yDpi,
903
pScrn->displayWidth, pScrn->bitsPerPixel))
906
/* Fixup RGB ordering */
907
visual = pScreen->visuals + pScreen->numVisuals;
908
while (--visual >= pScreen->visuals) {
909
if ((visual->class | DynamicClass) == DirectColor) {
910
visual->offsetRed = pScrn->offset.red;
911
visual->offsetGreen = pScrn->offset.green;
912
visual->offsetBlue = pScrn->offset.blue;
913
visual->redMask = pScrn->mask.red;
914
visual->greenMask = pScrn->mask.green;
915
visual->blueMask = pScrn->mask.blue;
919
/* must be after RGB ordering fixed */
920
fbPictureInit(pScreen, 0, 0);
922
xf86SetBlackWhitePixels(pScreen);
923
miInitializeBackingStore(pScreen);
924
xf86SetBackingStore(pScreen);
926
/* We need to keep track of whether we are currently switched to a virtual
927
* terminal to know whether a mode set operation is currently safe to do.
929
pVBox->vtSwitch = FALSE;
930
/* Initialise DGA. The cast is unfortunately correct - it gets cast back
931
to (unsigned char *) later. */
932
xf86DiDGAInit(pScreen, (unsigned long) pVBox->base);
934
/* Initialise randr 1.2 mode-setting functions and set first mode. */
935
if (!xf86CrtcScreenInit(pScreen)) {
939
if (!xf86SetDesiredModes(pScrn)) {
943
/* software cursor */
944
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
947
if (!miCreateDefColormap(pScreen))
950
flags = CMAP_RELOAD_ON_MODE_SWITCH;
952
if(!vgaHWHandleColormaps(pScreen))
955
/* Hook our observer function ito the chain which is called when
956
* framebuffer access is enabled or disabled in the server, and
957
* assume an initial state of enabled. */
958
pVBox->accessEnabled = TRUE;
959
pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
960
pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
962
pVBox->CloseScreen = pScreen->CloseScreen;
963
pScreen->CloseScreen = VBOXCloseScreen;
964
pScreen->SaveScreen = xf86SaveScreen;
966
/* We probably do want to support power management - even if we just use
968
xf86DPMSInit(pScreen, xf86DPMSSet, 0);
970
/* Report any unused options (only for the first generation) */
971
if (serverGeneration == 1)
972
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
974
if (vbox_device_available(pVBox) && vbox_open (pScrn, pScreen, pVBox)) {
975
if (vbox_cursor_init(pScreen) != TRUE)
976
xf86DrvMsg(scrnIndex, X_ERROR,
977
"Unable to start the VirtualBox mouse pointer integration with the host system.\n");
978
if (vboxEnableVbva(pScrn) == TRUE)
979
xf86DrvMsg(scrnIndex, X_INFO,
980
"The VBox video extensions are now enabled.\n");
981
vboxEnableGraphicsCap(pVBox);
986
pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
992
VBOXEnterVT(int scrnIndex, int flags)
994
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
995
VBOXPtr pVBox = VBOXGetRec(pScrn);
999
pVBox->vtSwitch = FALSE;
1002
DRIUnlock(screenInfo.screens[scrnIndex]);
1004
rc = xf86SetDesiredModes(pScrn);
1005
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1010
VBOXLeaveVT(int scrnIndex, int flags)
1012
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1013
VBOXPtr pVBox = VBOXGetRec(pScrn);
1016
pVBox->vtSwitch = TRUE;
1017
VBOXSaveRestore(pScrn, MODE_RESTORE);
1018
if (vbox_device_available(pVBox))
1020
if (pVBox->useVbva == TRUE)
1021
vboxDisableVbva(pScrn);
1022
vboxDisableGraphicsCap(pVBox);
1026
DRILock(screenInfo.screens[scrnIndex], 0);
1032
VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
1034
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1035
VBOXPtr pVBox = VBOXGetRec(pScrn);
1039
VBOXDRICloseScreen(pScreen, pVBox);
1040
pVBox->useDRI = false;
1043
if (vbox_device_available(pVBox))
1045
if (TRUE == pVBox->useVbva)
1046
vboxDisableVbva(pScrn);
1047
vboxDisableGraphicsCap(pVBox);
1049
if (pScrn->vtSema) {
1050
VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
1051
if (pVBox->savedPal)
1052
VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
1053
pVBox->savedPal, FALSE, TRUE);
1054
VBOXUnmapVidMem(pScrn);
1056
pScrn->vtSema = FALSE;
1058
/* Destroy the VGA hardware record */
1059
vgaHWFreeHWRec(pScrn);
1061
/* Remove our observer functions from the X server call chains. */
1062
pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;
1063
pScreen->CloseScreen = pVBox->CloseScreen;
1064
return pScreen->CloseScreen(scrnIndex, pScreen);
1068
* Quoted from "How to add an (S)VGA driver to XFree86"
1069
* (http://www.xfree86.org/3.3.6/VGADriver.html):
1071
* The ValidMode() function is required. It is used to check for any
1072
* chipset-dependent reasons why a graphics mode might not be valid. It gets
1073
* called by higher levels of the code after the Probe() stage. In many cases
1074
* no special checking will be required and this function will simply return
1077
* Note: we check here that our generated video modes fulfil the X server's
1078
* criteria for the monitor, since this can otherwise cause problems in
1082
VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
1084
static int warned = 0;
1085
ScrnInfoPtr pScrn = xf86Screens[scrn];
1086
MonPtr mon = pScrn->monitor;
1087
ModeStatus ret = MODE_BAD;
1088
DisplayModePtr mode;
1091
TRACE_LOG("HDisplay=%d, VDisplay=%d, flag=%s, pass=%d\n",
1092
p->HDisplay, p->VDisplay, flag ? "TRUE" : "FALSE", pass);
1093
if (pass != MODECHECK_FINAL) {
1095
xf86DrvMsg(scrn, X_WARNING, "VBOXValidMode called unexpectedly\n");
1101
* First off, if this isn't a mode we handed to the server (ie,
1102
* M_T_BUILTIN), then we reject it out of hand.
1104
if (!(p->type & M_T_BUILTIN))
1108
* Finally, walk through the vsync rates 1Hz at a time looking for a mode
1109
* that will fit. This is assuredly a terrible way to do this, but
1110
* there's no obvious method for computing a mode of a given size that
1111
* will pass xf86CheckModeForMonitor.
1113
for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
1114
mode = xf86CVTMode(p->HDisplay, p->VDisplay, v, 0, 0);
1115
ret = xf86CheckModeForMonitor(mode, mon);
1123
xf86DrvMsg(scrn, X_WARNING, "Graphics mode %s rejected by the X server\n", p->name);
1125
TRACE_LOG("returning %d\n", ret);
1130
VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
1136
TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1137
pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
1138
pVBox = VBOXGetRec(pScrn);
1139
/* We want to disable access to the framebuffer before switching mode.
1140
* After doing the switch, we allow access if it was allowed before. */
1141
if (pVBox->accessEnabled)
1142
pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
1143
rc = xf86SetSingleMode(pScrn, pMode, 0);
1144
if (pVBox->accessEnabled)
1145
pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
1146
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1150
/* Set a graphics mode. Poke the required values into registers, enable
1151
guest-host acceleration functions and tell the host we support advanced
1152
graphics functions. */
1154
VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1159
int bpp = pScrn->depth == 24 ? 32 : 16;
1160
TRACE_LOG("HDisplay=%d, VDisplay=%d, displayWidth=%d\n",
1161
pMode->HDisplay, pMode->VDisplay, pScrn->displayWidth);
1162
pVBox = VBOXGetRec(pScrn);
1163
/* Don't fiddle with the hardware if we are switched
1164
* to a virtual terminal. */
1165
if (!pVBox->vtSwitch)
1167
if ( vbox_device_available(pVBox)
1168
&& (TRUE == pVBox->useVbva)
1169
&& (vboxDisableVbva(pScrn) != TRUE)
1170
) /* This would be bad. */
1174
/* Disable linear framebuffer mode before making changes to the resolution. */
1175
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
1176
outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
1177
/* Unlike the resolution, the depth is fixed for a given screen
1178
for the lifetime of the X session. */
1179
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
1180
outw(VBE_DISPI_IOPORT_DATA, bpp);
1181
/* HDisplay and VDisplay are actually monitor information about
1182
the display part of the scanlines. */
1183
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
1184
outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
1185
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
1186
outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
1187
/* Set the virtual resolution. We are still using VESA to control
1188
the virtual offset. */
1189
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
1190
outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
1191
/* Enable linear framebuffer mode. */
1192
outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
1193
outw(VBE_DISPI_IOPORT_DATA,
1194
VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
1195
/* Enable acceleration and tell the host we support graphics */
1196
if (vbox_device_available(pVBox))
1198
if ((TRUE == pVBox->useVbva) && (vboxEnableVbva(pScrn) != TRUE))
1199
/* Bad but not fatal */
1200
pVBox->useVbva = FALSE;
1201
vboxEnableGraphicsCap(pVBox);
1205
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1210
VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
1212
VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
1213
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1216
/* Don't fiddle with the hardware if we are switched
1217
* to a virtual terminal. */
1218
if (!pVBox->vtSwitch) {
1219
pVBox->viewportX = x;
1220
pVBox->viewportY = y;
1221
/* If VBVA is enabled the graphics card will not notice the change. */
1222
if (pVBox->useVbva == TRUE)
1223
vboxDisableVbva(pScrn);
1224
VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
1225
if (pVBox->useVbva == TRUE)
1226
vboxEnableVbva(pScrn);
1232
VBOXFreeScreen(int scrnIndex, int flags)
1234
VBOXFreeRec(xf86Screens[scrnIndex]);
1238
VBOXMapVidMem(ScrnInfoPtr pScrn)
1240
VBOXPtr pVBox = VBOXGetRec(pScrn);
1246
pScrn->memPhysBase = pVBox->mapPhys;
1247
pScrn->fbOffset = pVBox->mapOff;
1250
(void) pci_device_map_range(pVBox->pciInfo,
1253
PCI_DEV_MAP_FLAG_WRITABLE,
1256
pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1258
pVBox->pciTag, pVBox->mapPhys,
1259
(unsigned) pVBox->mapSize);
1263
/* We need this for saving/restoring textmode */
1264
VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1265
rc = vgaHWMapMem(pScrn);
1270
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1275
VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1277
VBOXPtr pVBox = VBOXGetRec(pScrn);
1280
if (pVBox->base == NULL)
1284
(void) pci_device_unmap_range(pVBox->pciInfo,
1288
xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1289
(unsigned) pVBox->mapSize);
1291
vgaHWUnmapMem(pScrn);
1298
VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1304
if (MODE_QUERY < 0 || function > MODE_RESTORE)
1309
pVBox = VBOXGetRec(pScrn);
1311
/* Query amount of memory to save state */
1312
if (function == MODE_QUERY ||
1313
(function == MODE_SAVE && pVBox->state == NULL))
1316
/* Make sure we save at least this information in case of failure */
1317
(void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1318
vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1320
if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1321
&pVBox->stateSize,&pVBox->statePage)
1328
/* Save/Restore Super VGA state */
1329
if (function != MODE_QUERY) {
1331
if (function == MODE_RESTORE)
1332
memcpy(pVBox->state, pVBox->pstate,
1333
(unsigned) pVBox->stateSize);
1335
if ( (rc = VBESaveRestore(pVBox->pVbe,function,
1336
(pointer)&pVBox->state,
1337
&pVBox->stateSize,&pVBox->statePage)
1339
&& (function == MODE_SAVE)
1342
/* don't rely on the memory not being touched */
1343
if (pVBox->pstate == NULL)
1344
pVBox->pstate = malloc(pVBox->stateSize);
1345
memcpy(pVBox->pstate, pVBox->state,
1346
(unsigned) pVBox->stateSize);
1349
if (function == MODE_RESTORE)
1351
VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1352
vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1356
TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");