VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_13.c@ 6642

Last change on this file since 6642 was 6642, checked in by vboxsync, 17 years ago

Additions/x11: Disabled unused vboxutils.c specific fields.

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