VirtualBox

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

最後變更 在這個檔案從53442是 53426,由 vboxsync 提交於 10 年 前

Additions/x11/vboxvideo: fix VT switching without a kernel driver.

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

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