VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo_13.c@ 34721

Last change on this file since 34721 was 34715, checked in by vboxsync, 14 years ago

Additions/x11/vboxvideo: switch to HGSMI and merge the two drivers into one file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.9 KB
Line 
1/* $Id: vboxvideo_13.c 34715 2010-12-03 23:25:52Z vboxsync $ */
2/** @file
3 *
4 * Linux Additions X11 graphics driver
5 */
6
7/*
8 * Copyright (C) 2006-2010 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 * --------------------------------------------------------------------
18 *
19 * This code is based on:
20 *
21 * X11 VESA driver
22 *
23 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
24 *
25 * Permission is hereby granted, free of charge, to any person obtaining a
26 * copy of this software and associated documentation files (the "Software"),
27 * to deal in the Software without restriction, including without limitation
28 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
29 * and/or sell copies of the Software, and to permit persons to whom the
30 * Software is furnished to do so, subject to the following conditions:
31 *
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
39 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
40 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41 * SOFTWARE.
42 *
43 * Except as contained in this notice, the name of Conectiva Linux shall
44 * not be used in advertising or otherwise to promote the sale, use or other
45 * dealings in this Software without prior written authorization from
46 * Conectiva Linux.
47 *
48 * Authors: Paulo César Pereira de Andrade <[email protected]>
49 */
50
51#ifdef XORG_7X
52# include "xorg-server.h"
53# include <string.h>
54#endif
55#include "vboxvideo.h"
56#include "version-generated.h"
57#include "product-generated.h"
58#include <xf86.h>
59
60/* All drivers initialising the SW cursor need this */
61#include "mipointer.h"
62
63/* All drivers implementing backing store need this */
64#include "mibstore.h"
65
66/* Colormap handling */
67#include "micmap.h"
68#include "xf86cmap.h"
69
70/* DPMS */
71/* #define DPMS_SERVER
72#include "extensions/dpms.h" */
73
74/* VGA hardware functions for setting and restoring text mode */
75#include "vgaHW.h"
76
77#ifdef VBOXVIDEO_13
78/* X.org 1.3+ mode setting */
79# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
80# include "xf86Crtc.h"
81# include "xf86Modes.h"
82#endif
83
84/* Mandatory functions */
85
86static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
87static void VBOXIdentify(int flags);
88#ifndef PCIACCESS
89static Bool VBOXProbe(DriverPtr drv, int flags);
90#else
91static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
92 struct pci_device *dev, intptr_t match_data);
93#endif
94static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
95static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
96 char **argv);
97static Bool VBOXEnterVT(int scrnIndex, int flags);
98static void VBOXLeaveVT(int scrnIndex, int flags);
99static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
100static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
101static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
102static Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
103 unsigned cHeight, int x, int y);
104static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
105static void VBOXFreeScreen(int scrnIndex, int flags);
106static void VBOXFreeRec(ScrnInfoPtr pScrn);
107static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
108 int flags);
109
110/* locally used functions */
111static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
112static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
113static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
114 vbeSaveRestoreFunction function);
115static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
116
117enum GenericTypes
118{
119 CHIP_VBOX_GENERIC
120};
121
122#ifdef PCIACCESS
123static const struct pci_id_match vbox_device_match[] = {
124 {
125 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
126 0, 0, 0
127 },
128
129 { 0, 0, 0 },
130};
131#endif
132
133/* Supported chipsets */
134static SymTabRec VBOXChipsets[] =
135{
136 {VBOX_DEVICEID, "vbox"},
137 {-1, NULL}
138};
139
140static PciChipsets VBOXPCIchipsets[] = {
141 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
142 { -1, -1, RES_UNDEFINED },
143};
144
145/*
146 * This contains the functions needed by the server after loading the
147 * driver module. It must be supplied, and gets added the driver list by
148 * the Module Setup function in the dynamic case. In the static case a
149 * reference to this is compiled in, and this requires that the name of
150 * this DriverRec be an upper-case version of the driver name.
151 */
152
153#ifdef XORG_7X
154_X_EXPORT
155#endif
156DriverRec VBOXVIDEO = {
157 VBOX_VERSION,
158 VBOX_DRIVER_NAME,
159 VBOXIdentify,
160#ifdef PCIACCESS
161 NULL,
162#else
163 VBOXProbe,
164#endif
165 VBOXAvailableOptions,
166 NULL,
167 0,
168#ifdef XORG_7X
169 NULL,
170#endif
171#ifdef PCIACCESS
172 vbox_device_match,
173 VBOXPciProbe
174#endif
175};
176
177/* No options for now */
178static const OptionInfoRec VBOXOptions[] = {
179 { -1, NULL, OPTV_NONE, {0}, FALSE }
180};
181
182#ifndef XORG_7X
183/*
184 * List of symbols from other modules that this module references. This
185 * list is used to tell the loader that it is OK for symbols here to be
186 * unresolved providing that it hasn't been told that they haven't been
187 * told that they are essential via a call to xf86LoaderReqSymbols() or
188 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
189 * unresolved symbols that are not required.
190 */
191static const char *fbSymbols[] = {
192 "fbPictureInit",
193 "fbScreenInit",
194 NULL
195};
196
197static const char *shadowfbSymbols[] = {
198 "ShadowFBInit2",
199 NULL
200};
201
202static const char *vbeSymbols[] = {
203 "VBEExtendedInit",
204 "VBEFindSupportedDepths",
205 "VBEGetModeInfo",
206 "VBEGetVBEInfo",
207 "VBEGetVBEMode",
208 "VBEPrintModes",
209 "VBESaveRestore",
210 "VBESetDisplayStart",
211 "VBESetGetDACPaletteFormat",
212 "VBESetGetLogicalScanlineLength",
213 "VBESetGetPaletteData",
214 "VBESetModeNames",
215 "VBESetModeParameters",
216 "VBESetVBEMode",
217 "VBEValidateModes",
218 "vbeDoEDID",
219 "vbeFree",
220 NULL
221};
222
223static const char *ramdacSymbols[] = {
224 "xf86InitCursor",
225 "xf86CreateCursorInfoRec",
226 NULL
227};
228
229static const char *vgahwSymbols[] = {
230 "vgaHWGetHWRec",
231 "vgaHWHandleColormaps",
232 "vgaHWFreeHWRec",
233 "vgaHWMapMem",
234 "vgaHWUnmapMem",
235 "vgaHWSaveFonts",
236 "vgaHWRestoreFonts",
237 "vgaHWGetIndex",
238 "vgaHWSaveScreen",
239 "vgaHWDPMSSet",
240 NULL
241};
242#endif /* !XORG_7X */
243
244static VBOXPtr
245VBOXGetRec(ScrnInfoPtr pScrn)
246{
247 if (!pScrn->driverPrivate)
248 {
249 pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);
250 }
251
252 return ((VBOXPtr)pScrn->driverPrivate);
253}
254
255static void
256VBOXFreeRec(ScrnInfoPtr pScrn)
257{
258 VBOXPtr pVBox = VBOXGetRec(pScrn);
259 free(pVBox->savedPal);
260 free(pVBox->fonts);
261 free(pScrn->driverPrivate);
262 pScrn->driverPrivate = NULL;
263}
264
265#ifdef VBOXVIDEO_13
266/* X.org 1.3+ mode-setting support ******************************************/
267
268/* For descriptions of these functions and structures, see
269 hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
270 X.Org source tree. */
271
272static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
273 VBOXAdjustScreenPixmap
274};
275
276static void
277vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
278{ (void) crtc; (void) mode; }
279
280static Bool
281vbox_crtc_lock (xf86CrtcPtr crtc)
282{ (void) crtc; return FALSE; }
283
284static Bool
285vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
286 DisplayModePtr adjusted_mode)
287{ (void) crtc; (void) mode; (void) adjusted_mode; return TRUE; }
288
289static void
290vbox_crtc_stub (xf86CrtcPtr crtc)
291{ (void) crtc; }
292
293static void
294vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
295 DisplayModePtr adjusted_mode, int x, int y)
296{
297 (void) mode;
298 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
299 int bpp = crtc->scrn->depth == 24 ? 32 : 16;
300
301 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
302 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
303 VBOXSetMode(crtc->scrn, 0, adjusted_mode->HDisplay, adjusted_mode->VDisplay,
304 x, y);
305 /* Don't remember any modes set while we are seamless, as they are
306 * just temporary. */
307 if (!vboxGuestIsSeamless(crtc->scrn))
308 vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
309 adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
310}
311
312static void
313vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
314 CARD16 *green, CARD16 *blue, int size)
315{ (void) crtc; (void) red; (void) green; (void) blue; (void) size; }
316
317static void *
318vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
319{ (void) crtc; (void) width; (void) height; return NULL; }
320
321static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
322 .dpms = vbox_crtc_dpms,
323 .save = NULL, /* These two are never called by the server. */
324 .restore = NULL,
325 .lock = vbox_crtc_lock,
326 .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
327 .mode_fixup = vbox_crtc_mode_fixup,
328 .prepare = vbox_crtc_stub,
329 .mode_set = vbox_crtc_mode_set,
330 .commit = vbox_crtc_stub,
331 .gamma_set = vbox_crtc_gamma_set,
332 .shadow_allocate = vbox_crtc_shadow_allocate,
333 .shadow_create = NULL, /* These two should not be invoked if allocate
334 returns NULL. */
335 .shadow_destroy = NULL,
336 .set_cursor_colors = NULL, /* We are still using the old cursor API. */
337 .set_cursor_position = NULL,
338 .show_cursor = NULL,
339 .hide_cursor = NULL,
340 .load_cursor_argb = NULL,
341 .destroy = vbox_crtc_stub
342};
343
344static void
345vbox_output_stub (xf86OutputPtr output)
346{ (void) output; }
347
348static void
349vbox_output_dpms (xf86OutputPtr output, int mode)
350{ (void) output; (void) mode; }
351
352static int
353vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
354{
355 ScrnInfoPtr pScrn = output->scrn;
356 int rc = MODE_OK;
357 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);
358 /* We always like modes specified by the user in the configuration
359 * file and modes requested by the host, as doing otherwise is likely to
360 * annoy people. */
361 if ( !(mode->type & M_T_USERDEF)
362 && !(mode->type & M_T_PREFERRED)
363 && vbox_device_available(VBOXGetRec(pScrn))
364 && !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,
365 pScrn->bitsPerPixel)
366 )
367 rc = MODE_BAD;
368 TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");
369 return rc;
370}
371
372static Bool
373vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
374 DisplayModePtr adjusted_mode)
375{ (void) output; (void) mode; (void) adjusted_mode; return TRUE; }
376
377static void
378vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
379 DisplayModePtr adjusted_mode)
380{ (void) output; (void) mode; (void) adjusted_mode; }
381
382/* A virtual monitor is always connected. */
383static xf86OutputStatus
384vbox_output_detect (xf86OutputPtr output)
385{
386 (void) output;
387 return XF86OutputStatusConnected;
388}
389
390static void
391vbox_output_add_mode (VBOXPtr pVBox, DisplayModePtr *pModes,
392 const char *pszName, int x, int y,
393 Bool isPreferred, Bool isUserDef)
394{
395 TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName, x, y);
396 DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
397
398 pMode->status = MODE_OK;
399 /* We don't ask the host whether it likes user defined modes,
400 * as we assume that the user really wanted that mode. */
401 pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
402 if (isPreferred)
403 pMode->type |= M_T_PREFERRED;
404 /* Older versions of VBox only support screen widths which are a multiple
405 * of 8 */
406 if (pVBox->fAnyX)
407 pMode->HDisplay = x;
408 else
409 pMode->HDisplay = x & ~7;
410 pMode->HSyncStart = pMode->HDisplay + 2;
411 pMode->HSyncEnd = pMode->HDisplay + 4;
412 pMode->HTotal = pMode->HDisplay + 6;
413 pMode->VDisplay = y;
414 pMode->VSyncStart = pMode->VDisplay + 2;
415 pMode->VSyncEnd = pMode->VDisplay + 4;
416 pMode->VTotal = pMode->VDisplay + 6;
417 pMode->Clock = pMode->HTotal * pMode->VTotal * 60 / 1000; /* kHz */
418 if (NULL == pszName) {
419 xf86SetModeDefaultName(pMode);
420 } else {
421 pMode->name = xnfstrdup(pszName);
422 }
423 *pModes = xf86ModesAdd(*pModes, pMode);
424}
425
426static DisplayModePtr
427vbox_output_get_modes (xf86OutputPtr output)
428{
429 bool rc;
430 unsigned i;
431 DisplayModePtr pModes = NULL;
432 ScrnInfoPtr pScrn = output->scrn;
433 VBOXPtr pVBox = VBOXGetRec(pScrn);
434
435 TRACE_ENTRY();
436 if (vbox_device_available(pVBox))
437 {
438 uint32_t x, y, bpp, iScreen;
439 rc = vboxGetDisplayChangeRequest(pScrn, &x, &y, &bpp, &iScreen);
440 /* @todo - check the display number once we support multiple displays. */
441 /* If we don't find a display request, see if we have a saved hint
442 * from a previous session. */
443 if (!rc || (0 == x) || (0 == y))
444 rc = vboxRetrieveVideoMode(pScrn, &x, &y, &bpp);
445 if (rc && (0 != x) && (0 != y))
446 vbox_output_add_mode(pVBox, &pModes, NULL, x, y, TRUE, FALSE);
447 }
448 /* Also report any modes the user may have requested in the xorg.conf
449 * configuration file. */
450 for (i = 0; pScrn->display->modes[i] != NULL; i++)
451 {
452 int x, y;
453 if (2 == sscanf(pScrn->display->modes[i], "%dx%d", &x, &y))
454 vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y,
455 FALSE, TRUE);
456 }
457 TRACE_EXIT();
458 return pModes;
459}
460
461#ifdef RANDR_12_INTERFACE
462/* We don't yet have mutable properties, whatever they are. */
463static Bool
464vbox_output_set_property(xf86OutputPtr output, Atom property,
465 RRPropertyValuePtr value)
466{ (void) output; (void) property; (void) value; return FALSE; }
467#endif
468
469static const xf86OutputFuncsRec VBOXOutputFuncs = {
470 .create_resources = vbox_output_stub,
471 .dpms = vbox_output_dpms,
472 .save = NULL, /* These two are never called by the server. */
473 .restore = NULL,
474 .mode_valid = vbox_output_mode_valid,
475 .mode_fixup = vbox_output_mode_fixup,
476 .prepare = vbox_output_stub,
477 .commit = vbox_output_stub,
478 .mode_set = vbox_output_mode_set,
479 .detect = vbox_output_detect,
480 .get_modes = vbox_output_get_modes,
481#ifdef RANDR_12_INTERFACE
482 .set_property = vbox_output_set_property,
483#endif
484 .destroy = vbox_output_stub
485};
486#endif /* VBOXVIDEO_13 */
487
488#ifdef XFree86LOADER
489/* Module loader interface */
490static MODULESETUPPROTO(vboxSetup);
491
492static XF86ModuleVersionInfo vboxVersionRec =
493{
494 VBOX_DRIVER_NAME,
495 VBOX_VENDOR,
496 MODINFOSTRING1,
497 MODINFOSTRING2,
498#ifdef XORG_7X
499 XORG_VERSION_CURRENT,
500#else
501 XF86_VERSION_CURRENT,
502#endif
503 1, /* Module major version. Xorg-specific */
504 0, /* Module minor version. Xorg-specific */
505 1, /* Module patchlevel. Xorg-specific */
506 ABI_CLASS_VIDEODRV, /* This is a video driver */
507 ABI_VIDEODRV_VERSION,
508 MOD_CLASS_VIDEODRV,
509 {0, 0, 0, 0}
510};
511
512/*
513 * This data is accessed by the loader. The name must be the module name
514 * followed by "ModuleData".
515 */
516#ifdef XORG_7X
517_X_EXPORT
518#endif
519XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
520
521static pointer
522vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
523{
524 static Bool Initialised = FALSE;
525
526 if (!Initialised)
527 {
528 Initialised = TRUE;
529#ifdef PCIACCESS
530 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
531#else
532 xf86AddDriver(&VBOXVIDEO, Module, 0);
533#endif
534#ifndef XORG_7X
535 LoaderRefSymLists(fbSymbols,
536 shadowfbSymbols,
537 vbeSymbols,
538 ramdacSymbols,
539 vgahwSymbols,
540 NULL);
541#endif
542 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
543 (void *)&VBOXVIDEO);
544 return (pointer)TRUE;
545 }
546
547 if (ErrorMajor)
548 *ErrorMajor = LDR_ONCEONLY;
549 return (NULL);
550}
551
552#endif /* XFree86Loader defined */
553
554static const OptionInfoRec *
555VBOXAvailableOptions(int chipid, int busid)
556{
557 return (VBOXOptions);
558}
559
560static void
561VBOXIdentify(int flags)
562{
563 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
564}
565
566/*
567 * This function is called once, at the start of the first server generation to
568 * do a minimal probe for supported hardware.
569 */
570
571#ifdef PCIACCESS
572static Bool
573VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
574 intptr_t match_data)
575{
576 ScrnInfoPtr pScrn;
577
578 TRACE_ENTRY();
579 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
580 NULL, NULL, NULL, NULL, NULL);
581 if (pScrn != NULL) {
582 VBOXPtr pVBox = VBOXGetRec(pScrn);
583
584 pScrn->driverVersion = VBOX_VERSION;
585 pScrn->driverName = VBOX_DRIVER_NAME;
586 pScrn->name = VBOX_NAME;
587 pScrn->Probe = NULL;
588 pScrn->PreInit = VBOXPreInit;
589 pScrn->ScreenInit = VBOXScreenInit;
590 pScrn->SwitchMode = VBOXSwitchMode;
591 pScrn->AdjustFrame = VBOXAdjustFrame;
592 pScrn->EnterVT = VBOXEnterVT;
593 pScrn->LeaveVT = VBOXLeaveVT;
594 pScrn->FreeScreen = VBOXFreeScreen;
595
596 pVBox->pciInfo = dev;
597 }
598
599 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
600 return (pScrn != NULL);
601}
602#endif
603
604#ifndef PCIACCESS
605static Bool
606VBOXProbe(DriverPtr drv, int flags)
607{
608 Bool foundScreen = FALSE;
609 int numDevSections;
610 GDevPtr *devSections;
611
612 /*
613 * Find the config file Device sections that match this
614 * driver, and return if there are none.
615 */
616 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
617 &devSections)) <= 0)
618 return (FALSE);
619
620 /* PCI BUS */
621 if (xf86GetPciVideoInfo()) {
622 int numUsed;
623 int *usedChips;
624 int i;
625 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
626 VBOXChipsets, VBOXPCIchipsets,
627 devSections, numDevSections,
628 drv, &usedChips);
629 if (numUsed > 0) {
630 if (flags & PROBE_DETECT)
631 foundScreen = TRUE;
632 else {
633 for (i = 0; i < numUsed; i++) {
634 ScrnInfoPtr pScrn = NULL;
635 /* Allocate a ScrnInfoRec */
636 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
637 VBOXPCIchipsets,NULL,
638 NULL,NULL,NULL,NULL))) {
639 pScrn->driverVersion = VBOX_VERSION;
640 pScrn->driverName = VBOX_DRIVER_NAME;
641 pScrn->name = VBOX_NAME;
642 pScrn->Probe = VBOXProbe;
643 pScrn->PreInit = VBOXPreInit;
644 pScrn->ScreenInit = VBOXScreenInit;
645 pScrn->SwitchMode = VBOXSwitchMode;
646 pScrn->AdjustFrame = VBOXAdjustFrame;
647 pScrn->EnterVT = VBOXEnterVT;
648 pScrn->LeaveVT = VBOXLeaveVT;
649 pScrn->FreeScreen = VBOXFreeScreen;
650 foundScreen = TRUE;
651 }
652 }
653 }
654 free(usedChips);
655 }
656 }
657
658 free(devSections);
659
660 return (foundScreen);
661}
662#endif
663
664/**
665 * This function hooks into the chain that is called when framebuffer access
666 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
667 * In other words, it observes when the server wishes access to the
668 * framebuffer to be enabled and when it should be disabled. We need to know
669 * this because we disable access ourselves during mode switches (presumably
670 * the server should do this but it doesn't) and want to know whether to
671 * restore it or not afterwards.
672 */
673static void
674vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
675{
676 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
677 VBOXPtr pVBox = VBOXGetRec(pScrn);
678
679 TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");
680 pVBox->accessEnabled = enable;
681 pVBox->EnableDisableFBAccess(scrnIndex, enable);
682 TRACE_EXIT();
683}
684
685/*
686 * QUOTE from the XFree86 DESIGN document:
687 *
688 * The purpose of this function is to find out all the information
689 * required to determine if the configuration is usable, and to initialise
690 * those parts of the ScrnInfoRec that can be set once at the beginning of
691 * the first server generation.
692 *
693 * (...)
694 *
695 * This includes probing for video memory, clocks, ramdac, and all other
696 * HW info that is needed. It includes determining the depth/bpp/visual
697 * and related info. It includes validating and determining the set of
698 * video modes that will be used (and anything that is required to
699 * determine that).
700 *
701 * This information should be determined in the least intrusive way
702 * possible. The state of the HW must remain unchanged by this function.
703 * Although video memory (including MMIO) may be mapped within this
704 * function, it must be unmapped before returning.
705 *
706 * END QUOTE
707 */
708
709static Bool
710VBOXPreInit(ScrnInfoPtr pScrn, int flags)
711{
712 VBOXPtr pVBox;
713 Gamma gzeros = {0.0, 0.0, 0.0};
714 rgb rzeros = {0, 0, 0};
715#ifdef VBOXVIDEO_13
716 xf86OutputPtr output;
717#endif
718 unsigned DispiId;
719
720 TRACE_ENTRY();
721 /* Are we really starting the server, or is this just a dummy run? */
722 if (flags & PROBE_DETECT)
723 return (FALSE);
724
725 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
726 "VirtualBox guest additions video driver version "
727 VBOX_VERSION_STRING "\n");
728
729 /* Get our private data from the ScrnInfoRec structure. */
730 pVBox = VBOXGetRec(pScrn);
731
732 /* Initialise the guest library */
733 vbox_init(pScrn->scrnIndex, pVBox);
734
735 /* Entity information seems to mean bus information. */
736 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
737
738 /* The ramdac module is needed for the hardware cursor. */
739 if (!xf86LoadSubModule(pScrn, "ramdac"))
740 return FALSE;
741
742 /* We need the vbe module because we use VBE code to save and restore
743 text mode, in order to keep our code simple. */
744 if (!xf86LoadSubModule(pScrn, "vbe"))
745 return (FALSE);
746
747 /* The framebuffer module. */
748 if (xf86LoadSubModule(pScrn, "fb") == NULL)
749 return (FALSE);
750
751 if (!xf86LoadSubModule(pScrn, "shadowfb"))
752 return FALSE;
753
754 if (!xf86LoadSubModule(pScrn, "vgahw"))
755 return FALSE;
756
757#ifdef VBOX_DRI
758 /* Load the dri module. */
759 if (!xf86LoadSubModule(pScrn, "dri"))
760 return FALSE;
761#endif
762
763#ifndef PCIACCESS
764 if (pVBox->pEnt->location.type != BUS_PCI)
765 return FALSE;
766
767 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
768 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
769 pVBox->pciInfo->device,
770 pVBox->pciInfo->func);
771#endif
772
773 /* Set up our ScrnInfoRec structure to describe our virtual
774 capabilities to X. */
775
776 pScrn->chipset = "vbox";
777 pScrn->rgbBits = 8;
778
779 /* Let's create a nice, capable virtual monitor.
780 * This *is* still needed, at least for server version 1.3 */
781 pScrn->monitor = pScrn->confScreen->monitor;
782 pScrn->monitor->DDC = NULL;
783 pScrn->monitor->nHsync = 1;
784 pScrn->monitor->hsync[0].lo = 1;
785 pScrn->monitor->hsync[0].hi = 10000;
786 pScrn->monitor->nVrefresh = 1;
787 pScrn->monitor->vrefresh[0].lo = 1;
788 pScrn->monitor->vrefresh[0].hi = 100;
789
790 pScrn->progClock = TRUE;
791
792 /* Using the PCI information caused problems with non-powers-of-two
793 sized video RAM configurations */
794 pVBox->cbFramebuffer = inl(VBE_DISPI_IOPORT_DATA);
795 pScrn->videoRam = pVBox->cbFramebuffer / 1024;
796
797 /* Check if the chip restricts horizontal resolution or not. */
798 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
799 outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
800 DispiId = inw(VBE_DISPI_IOPORT_DATA);
801 if (DispiId == VBE_DISPI_ID_ANYX)
802 pVBox->fAnyX = TRUE;
803 else
804 pVBox->fAnyX = FALSE;
805
806 /* Set up clock information that will support all modes we need. */
807 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
808 pScrn->clockRanges->minClock = 1000;
809 pScrn->clockRanges->maxClock = 1000000000;
810 pScrn->clockRanges->clockIndex = -1;
811 pScrn->clockRanges->ClockMulFactor = 1;
812 pScrn->clockRanges->ClockDivFactor = 1;
813
814 /* Query the host for the preferred colour depth */
815 {
816 uint32_t cx = 0, cy = 0, cBits = 0;
817
818 vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
819 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
820 if (cBits != 16)
821 cBits = 24;
822 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
823 return FALSE;
824#ifndef VBOXVIDEO_13
825 vboxAddModes(pScrn, cx, cy);
826#endif
827 }
828 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
829 {
830 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
831 "The VBox additions only support 16 and 32bpp graphics modes\n");
832 return FALSE;
833 }
834 xf86PrintDepthBpp(pScrn);
835
836#ifdef VBOXVIDEO_13
837 /* Work around a bug in the original X server modesetting code, which
838 * took the first valid values set to these two as maxima over the
839 * server lifetime. */
840 pScrn->virtualX = 32000;
841 pScrn->virtualY = 32000;
842
843 /* Initialise CRTC and output configuration for use with randr1.2. */
844 xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
845
846 /* Setup our single virtual CRTC. */
847 xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
848
849 /* Set up our single virtual output. */
850 output = xf86OutputCreate(pScrn, &VBOXOutputFuncs, "VBOX1");
851
852 /* Set a sane minimum and maximum mode size */
853 xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
854
855 /* We are not interested in the monitor section in the configuration file. */
856 xf86OutputUseScreenMonitor(output, FALSE);
857 output->possible_crtcs = 1;
858 output->possible_clones = 0;
859
860 /* Now create our initial CRTC/output configuration. */
861 if (!xf86InitialConfiguration(pScrn, TRUE)) {
862 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
863 return (FALSE);
864 }
865#else /* !VBOXVIDEO_13 */
866 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
867 * already know what we like and what we don't. */
868
869 pScrn->currentMode = pScrn->modes;
870
871 /* Set the right virtual resolution. */
872 pScrn->virtualX = pScrn->currentMode->HDisplay;
873 pScrn->virtualY = pScrn->currentMode->VDisplay;
874
875 pScrn->displayWidth = pScrn->virtualX;
876
877 xf86PrintModes(pScrn);
878
879#endif /* !VBOXVIDEO_13 */
880
881 /* Colour weight - we always call this, since we are always in
882 truecolour. */
883 if (!xf86SetWeight(pScrn, rzeros, rzeros))
884 return (FALSE);
885
886 /* visual init */
887 if (!xf86SetDefaultVisual(pScrn, -1))
888 return (FALSE);
889
890 xf86SetGamma(pScrn, gzeros);
891
892 /* Set the DPI. Perhaps we should read this from the host? */
893 xf86SetDpi(pScrn, 96, 96);
894
895 /* Framebuffer-related setup */
896 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
897
898 /* VGA hardware initialisation */
899 if (!vgaHWGetHWRec(pScrn))
900 return FALSE;
901
902 TRACE_EXIT();
903 return (TRUE);
904}
905
906/**
907 * Dummy function for setting the colour palette, which we actually never
908 * touch. However, the server still requires us to provide this.
909 */
910static void
911vboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
912 LOCO *colors, VisualPtr pVisual)
913{
914 (void)pScrn; (void) numColors; (void) indices; (void) colors;
915 (void)pVisual;
916}
917
918/*
919 * QUOTE from the XFree86 DESIGN document:
920 *
921 * This is called at the start of each server generation.
922 *
923 * (...)
924 *
925 * Decide which operations need to be placed under resource access
926 * control. (...) Map any video memory or other memory regions. (...)
927 * Save the video card state. (...) Initialise the initial video
928 * mode.
929 *
930 * End QUOTE.
931 */
932static Bool
933VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
934{
935 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
936 VBOXPtr pVBox = VBOXGetRec(pScrn);
937 VisualPtr visual;
938 unsigned flags;
939
940 TRACE_ENTRY();
941 /* We make use of the X11 VBE code to save and restore text mode, in
942 order to keep our code simple. */
943 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
944 SET_BIOS_SCRATCH
945 | RESTORE_BIOS_SCRATCH)) == NULL)
946 return (FALSE);
947
948 if (pScrn->memPhysBase == 0) {
949#ifdef PCIACCESS
950 pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
951#else
952 pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
953#endif
954 pScrn->fbOffset = 0;
955 }
956
957 if (!VBOXMapVidMem(pScrn))
958 return (FALSE);
959
960 /* save current video state */
961 VBOXSaveRestore(pScrn, MODE_SAVE);
962
963 /* mi layer - reset the visual list (?)*/
964 miClearVisualTypes();
965 if (!xf86SetDefaultVisual(pScrn, -1))
966 return (FALSE);
967 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
968 pScrn->rgbBits, TrueColor))
969 return (FALSE);
970 if (!miSetPixmapDepths())
971 return (FALSE);
972
973 /* Needed before we initialise DRI. */
974 pScrn->displayWidth = pScrn->virtualX;
975
976#ifdef VBOX_DRI
977 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
978#endif
979
980 /* I checked in the sources, and XFree86 4.2 does seem to support
981 this function for 32bpp. */
982 if (!fbScreenInit(pScreen, pVBox->base,
983 pScrn->virtualX, pScrn->virtualY,
984 pScrn->xDpi, pScrn->yDpi,
985 pScrn->displayWidth, pScrn->bitsPerPixel))
986 return (FALSE);
987
988 /* Fixup RGB ordering */
989 visual = pScreen->visuals + pScreen->numVisuals;
990 while (--visual >= pScreen->visuals) {
991 if ((visual->class | DynamicClass) == DirectColor) {
992 visual->offsetRed = pScrn->offset.red;
993 visual->offsetGreen = pScrn->offset.green;
994 visual->offsetBlue = pScrn->offset.blue;
995 visual->redMask = pScrn->mask.red;
996 visual->greenMask = pScrn->mask.green;
997 visual->blueMask = pScrn->mask.blue;
998 }
999 }
1000
1001 /* must be after RGB ordering fixed */
1002 fbPictureInit(pScreen, 0, 0);
1003
1004 xf86SetBlackWhitePixels(pScreen);
1005 miInitializeBackingStore(pScreen);
1006 xf86SetBackingStore(pScreen);
1007
1008 /* We need to keep track of whether we are currently switched to a virtual
1009 * terminal to know whether a mode set operation is currently safe to do.
1010 */
1011 pVBox->vtSwitch = FALSE;
1012
1013 if (vbox_device_available(pVBox) && vbox_open (pScrn, pScreen, pVBox)) {
1014 vboxEnableVbva(pScrn);
1015 vboxEnableGraphicsCap(pVBox);
1016 }
1017
1018#ifdef VBOXVIDEO_13
1019 /* Initialise randr 1.2 mode-setting functions and set first mode.
1020 * Note that the mode won't be usable until the server has resized the
1021 * framebuffer to something reasonable. */
1022 if (!xf86CrtcScreenInit(pScreen)) {
1023 return FALSE;
1024 }
1025
1026 if (!xf86SetDesiredModes(pScrn)) {
1027 return FALSE;
1028 }
1029#else /* !VBOXVIDEO_13 */
1030 /* set first video mode */
1031 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1032 pScrn->currentMode->VDisplay, pScrn->frameX0,
1033 pScrn->frameY0))
1034 return FALSE;
1035 /* And make sure that a non-current dynamic mode is at the front of the
1036 * list */
1037 vboxWriteHostModes(pScrn, pScrn->currentMode);
1038#endif /* !VBOXVIDEO_13 */
1039
1040 /* software cursor */
1041 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1042
1043 /* colourmap code */
1044 if (!miCreateDefColormap(pScreen))
1045 return (FALSE);
1046
1047 if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))
1048 return (FALSE);
1049
1050 /* Hook our observer function ito the chain which is called when
1051 * framebuffer access is enabled or disabled in the server, and
1052 * assume an initial state of enabled. */
1053 pVBox->accessEnabled = TRUE;
1054 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
1055 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
1056
1057 pVBox->CloseScreen = pScreen->CloseScreen;
1058 pScreen->CloseScreen = VBOXCloseScreen;
1059 pScreen->SaveScreen = VBOXSaveScreen;
1060
1061 /* We probably do want to support power management - even if we just use
1062 a dummy function. */
1063 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
1064
1065 /* Report any unused options (only for the first generation) */
1066 if (serverGeneration == 1)
1067 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1068
1069 if (vbox_cursor_init(pScreen) != TRUE)
1070 xf86DrvMsg(scrnIndex, X_ERROR,
1071 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
1072
1073#ifdef VBOX_DRI
1074 if (pVBox->useDRI)
1075 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
1076#endif
1077 return (TRUE);
1078}
1079
1080static Bool
1081VBOXEnterVT(int scrnIndex, int flags)
1082{
1083 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1084 VBOXPtr pVBox = VBOXGetRec(pScrn);
1085
1086 TRACE_ENTRY();
1087 pVBox->vtSwitch = FALSE;
1088#ifdef VBOX_DRI
1089 if (pVBox->useDRI)
1090 DRIUnlock(screenInfo.screens[scrnIndex]);
1091#endif
1092#ifdef VBOXVIDEO_13
1093 if (!xf86SetDesiredModes(pScrn))
1094 return FALSE;
1095#else
1096 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1097 pScrn->currentMode->VDisplay, pScrn->frameX0,
1098 pScrn->frameY0))
1099 return FALSE;
1100#endif
1101 if (pVBox->fHaveHGSMI)
1102 vboxEnableVbva(pScrn);
1103 return TRUE;
1104}
1105
1106static void
1107VBOXLeaveVT(int scrnIndex, int flags)
1108{
1109 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1110 VBOXPtr pVBox = VBOXGetRec(pScrn);
1111
1112 TRACE_ENTRY();
1113 pVBox->vtSwitch = TRUE;
1114 VBOXSaveRestore(pScrn, MODE_RESTORE);
1115 if (pVBox->fHaveHGSMI)
1116 vboxDisableVbva(pScrn);
1117 vboxDisableGraphicsCap(pVBox);
1118#ifdef VBOX_DRI
1119 if (pVBox->useDRI)
1120 DRILock(screenInfo.screens[scrnIndex], 0);
1121#endif
1122 TRACE_EXIT();
1123}
1124
1125static Bool
1126VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
1127{
1128 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1129 VBOXPtr pVBox = VBOXGetRec(pScrn);
1130
1131#ifdef VBOX_DRI
1132 if (pVBox->useDRI)
1133 VBOXDRICloseScreen(pScreen, pVBox);
1134 pVBox->useDRI = false;
1135#endif
1136
1137 if (pVBox->fHaveHGSMI)
1138 vboxDisableVbva(pScrn);
1139 vboxDisableGraphicsCap(pVBox);
1140 if (pScrn->vtSema) {
1141 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
1142 VBOXUnmapVidMem(pScrn);
1143 }
1144 pScrn->vtSema = FALSE;
1145
1146 /* Destroy the VGA hardware record */
1147 vgaHWFreeHWRec(pScrn);
1148
1149 /* And do additional bits which are separate for historical reasons */
1150 vbox_close(pScrn, pVBox);
1151
1152 /* Remove our observer functions from the X server call chains. */
1153 pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;
1154 pScreen->CloseScreen = pVBox->CloseScreen;
1155 return pScreen->CloseScreen(scrnIndex, pScreen);
1156}
1157
1158static Bool
1159VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
1160{
1161 ScrnInfoPtr pScrn;
1162 VBOXPtr pVBox;
1163 Bool rc;
1164
1165 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1166 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of referring to the screen? */
1167 pVBox = VBOXGetRec(pScrn);
1168 /* We want to disable access to the framebuffer before switching mode.
1169 * After doing the switch, we allow access if it was allowed before. */
1170 if (pVBox->accessEnabled)
1171 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
1172#ifdef VBOXVIDEO_13
1173 rc = xf86SetSingleMode(pScrn, pMode, 0);
1174#else
1175 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
1176 pScrn->frameX0, pScrn->frameY0);
1177 if (rc)
1178 {
1179 vboxWriteHostModes(pScrn, pMode);
1180 xf86PrintModes(pScrn);
1181 }
1182#endif
1183 if (rc && !vboxGuestIsSeamless(pScrn))
1184 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
1185 pScrn->bitsPerPixel);
1186 if (pVBox->accessEnabled)
1187 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
1188 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1189 return rc;
1190}
1191
1192/* Set a graphics mode. Poke the required values into registers, enable
1193 guest-host acceleration functions and tell the host we support advanced
1194 graphics functions. */
1195static Bool
1196VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
1197 unsigned cHeight, int x, int y)
1198{
1199 VBOXPtr pVBox;
1200 Bool rc = TRUE;
1201
1202 int bpp = pScrn->depth == 24 ? 32 : 16;
1203 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
1204 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
1205 pVBox = VBOXGetRec(pScrn);
1206 /* Don't fiddle with the hardware if we are switched
1207 * to a virtual terminal. */
1208 if (!pVBox->vtSwitch)
1209 {
1210 if (cDisplay == 0)
1211 VBoxVideoSetModeRegisters(cWidth, cHeight, pScrn->displayWidth,
1212 bpp, x, y);
1213 /* Tell the host we support graphics */
1214 if (vbox_device_available(pVBox))
1215 vboxEnableGraphicsCap(pVBox);
1216 }
1217 if ( vbox_device_available(pVBox)
1218 && (pVBox->fHaveHGSMI)
1219 && !pVBox->vtSwitch)
1220 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,
1221 (y * pScrn->displayWidth + x) * bpp / 8,
1222 pScrn->displayWidth * bpp / 8,
1223 cWidth, cHeight, bpp);
1224 pVBox->aScreenLocation[0].cx = cWidth;
1225 pVBox->aScreenLocation[0].cy = cHeight;
1226 pVBox->aScreenLocation[0].x = x;
1227 pVBox->aScreenLocation[0].y = y;
1228 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1229 return rc;
1230}
1231
1232static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
1233{
1234 ScreenPtr pScreen = pScrn->pScreen;
1235 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
1236 VBOXPtr pVBox = VBOXGetRec(pScrn);
1237 int bpp = pScrn->depth == 24 ? 32 : 16;
1238
1239 TRACE_LOG("width=%d, height=%d\n", width, height);
1240 if ((uint64_t)width * height * bpp / 8 >= pVBox->cbFramebuffer)
1241 {
1242 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1243 "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available. Please increase the video memory size.\n",
1244 width, height, pVBox->cbFramebuffer / 1024, pScrn->videoRam);
1245 return FALSE;
1246 }
1247 if (!pPixmap) {
1248 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1249 "Failed to get the screen pixmap.\n");
1250 return FALSE;
1251 }
1252 pScreen->ModifyPixmapHeader(pPixmap, width, height,
1253 pScrn->depth, bpp, width * bpp / 8,
1254 pVBox->base);
1255 pScrn->virtualX = width;
1256 pScrn->virtualY = height;
1257 pScrn->displayWidth = width;
1258#ifdef VBOX_DRI
1259 if (pVBox->useDRI)
1260 VBOXDRIUpdateStride(pScrn, pVBox);
1261#endif
1262#ifdef VBOXVIDEO_13
1263 /* Write the new values to the hardware */
1264 xf86SetDesiredModes(pScrn);
1265#else
1266 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
1267 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
1268#endif
1269 return TRUE;
1270}
1271
1272static void
1273VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
1274{
1275 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
1276 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1277
1278 TRACE_ENTRY();
1279 /* Don't fiddle with the hardware if we are switched
1280 * to a virtual terminal. */
1281 VBOXSetMode(pScrn, 0, pVBox->aScreenLocation[0].cx,
1282 pVBox->aScreenLocation[0].cy, x, y);
1283 TRACE_EXIT();
1284}
1285
1286static void
1287VBOXFreeScreen(int scrnIndex, int flags)
1288{
1289 VBOXFreeRec(xf86Screens[scrnIndex]);
1290}
1291
1292static Bool
1293VBOXMapVidMem(ScrnInfoPtr pScrn)
1294{
1295 VBOXPtr pVBox = VBOXGetRec(pScrn);
1296 Bool rc = TRUE;
1297
1298 TRACE_ENTRY();
1299 if (!pVBox->base)
1300 {
1301#ifdef PCIACCESS
1302 (void) pci_device_map_range(pVBox->pciInfo,
1303 pScrn->memPhysBase,
1304 pScrn->videoRam * 1024,
1305 PCI_DEV_MAP_FLAG_WRITABLE,
1306 & pVBox->base);
1307#else
1308 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1309 VIDMEM_FRAMEBUFFER,
1310 pVBox->pciTag, pScrn->memPhysBase,
1311 (unsigned) pScrn->videoRam * 1024);
1312#endif
1313 if (pVBox->base)
1314 {
1315 /* We need this for saving/restoring textmode */
1316 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1317 rc = vgaHWMapMem(pScrn);
1318 }
1319 else
1320 rc = FALSE;
1321 }
1322 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1323 return rc;
1324}
1325
1326static void
1327VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1328{
1329 VBOXPtr pVBox = VBOXGetRec(pScrn);
1330
1331 TRACE_ENTRY();
1332 if (pVBox->base == NULL)
1333 return;
1334
1335#ifdef PCIACCESS
1336 (void) pci_device_unmap_range(pVBox->pciInfo,
1337 pVBox->base,
1338 pScrn->videoRam * 1024);
1339#else
1340 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1341 (unsigned) pScrn->videoRam * 1024);
1342#endif
1343 vgaHWUnmapMem(pScrn);
1344 pVBox->base = NULL;
1345 TRACE_EXIT();
1346}
1347
1348static Bool
1349VBOXSaveScreen(ScreenPtr pScreen, int mode)
1350{
1351 (void)pScreen; (void)mode;
1352 return TRUE;
1353}
1354
1355Bool
1356VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1357{
1358 VBOXPtr pVBox;
1359 Bool rc = TRUE;
1360
1361 TRACE_ENTRY();
1362 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1363 rc = FALSE;
1364
1365 if (rc)
1366 {
1367 pVBox = VBOXGetRec(pScrn);
1368
1369 /* Query amount of memory to save state */
1370 if (function == MODE_QUERY ||
1371 (function == MODE_SAVE && pVBox->state == NULL))
1372 {
1373
1374 /* Make sure we save at least this information in case of failure */
1375 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1376 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1377
1378 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1379 &pVBox->stateSize,&pVBox->statePage)
1380 )
1381 rc = FALSE;
1382 }
1383 }
1384 if (rc)
1385 {
1386 /* Save/Restore Super VGA state */
1387 if (function != MODE_QUERY) {
1388
1389 if (function == MODE_RESTORE)
1390 memcpy(pVBox->state, pVBox->pstate,
1391 (unsigned) pVBox->stateSize);
1392
1393 if ( (rc = VBESaveRestore(pVBox->pVbe,function,
1394 (pointer)&pVBox->state,
1395 &pVBox->stateSize,&pVBox->statePage)
1396 )
1397 && (function == MODE_SAVE)
1398 )
1399 {
1400 /* don't rely on the memory not being touched */
1401 if (pVBox->pstate == NULL)
1402 pVBox->pstate = malloc(pVBox->stateSize);
1403 memcpy(pVBox->pstate, pVBox->state,
1404 (unsigned) pVBox->stateSize);
1405 }
1406
1407 if (function == MODE_RESTORE)
1408 {
1409 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1410 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1411 }
1412 }
1413 }
1414 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1415 return rc;
1416}
1417
1418static void
1419VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1420 int flags)
1421{
1422 (void)pScrn; (void)mode; (void) flags;
1423}
Note: See TracBrowser for help on using the repository browser.

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