VirtualBox

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

Last change on this file since 17245 was 16753, checked in by vboxsync, 16 years ago

Additions/x11/vboxvideo: disable VBVA when the viewport is moved

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