VirtualBox

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

Last change on this file since 21473 was 21292, checked in by vboxsync, 15 years ago

svn:eol-style native

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