VirtualBox

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

Last change on this file since 22141 was 22093, checked in by vboxsync, 16 years ago

Additions/x11/vboxvideo_13: use the generic in-server VGA hardware routines instead of private ones

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