VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_15.c@ 10541

Last change on this file since 10541 was 9929, checked in by vboxsync, 16 years ago

warnings.

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

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