VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_70.c@ 16701

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

Additions/x11/vboxvideo: dirty rectangles should be adjusted for the viewport position if the guest is using a virtual desktop larger than the current resolution

File size: 41.8 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#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 sscanf(pScrn->display->modes[i], "%dx%d", &x, &y);
567 m = xnfcalloc(sizeof(DisplayModeRec), 1);
568 m->status = MODE_OK;
569 m->type = M_T_BUILTIN;
570 /* VBox does only support screen widths which are a multiple of 8 */
571 m->HDisplay = (x + 7) & ~7;
572 m->HSyncStart = m->HDisplay + 2;
573 m->HSyncEnd = m->HDisplay + 4;
574 m->HTotal = m->HDisplay + 6;
575 m->VDisplay = y;
576 m->VSyncStart = m->VDisplay + 2;
577 m->VSyncEnd = m->VDisplay + 4;
578 m->VTotal = m->VDisplay + 6;
579 m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
580 m->name = strdup(pScrn->display->modes[i]);
581 if (!m_prev)
582 pScrn->modePool = m;
583 else
584 m_prev->next = m;
585 m->prev = m_prev;
586 m_prev = m;
587 }
588
589 /* Colour weight - we always call this, since we are always in
590 truecolour. */
591 if (!xf86SetWeight(pScrn, rzeros, rzeros))
592 return (FALSE);
593
594 /* visual init */
595 if (!xf86SetDefaultVisual(pScrn, -1))
596 return (FALSE);
597
598 xf86SetGamma(pScrn, gzeros);
599
600 /* Set a sane minimum mode size and the maximum allowed by the available VRAM */
601 {
602 unsigned maxSize, trySize = 512;
603
604 do {
605 maxSize = trySize;
606 trySize += 128;
607 } while (trySize * trySize * pScrn->bitsPerPixel / 8 < (unsigned)pScrn->videoRam * 1024);
608
609 /* I don't know exactly what these are for (and they are only used in a couple
610 of places in the X server code). */
611 pScrn->display->virtualX = maxSize;
612 pScrn->display->virtualY = maxSize;
613 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
614 "The maximum supported resolution is currently %dx%d\n", maxSize, maxSize);
615 }
616
617 /* Filter out video modes not supported by the virtual hardware
618 we described. */
619 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
620 pScrn->display->modes,
621 clockRanges, NULL, 64, pScrn->display->virtualX, 1,
622 64, pScrn->display->virtualY, 0, 0,
623 pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
624
625 if (i <= 0) {
626 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
627 return (FALSE);
628 }
629 xf86PruneDriverModes(pScrn);
630
631 pScrn->currentMode = pScrn->modes;
632 pScrn->displayWidth = pScrn->virtualX;
633
634 xf86PrintModes(pScrn);
635
636 /* Set display resolution. Perhaps we should read this from the host. */
637 xf86SetDpi(pScrn, 96, 96);
638
639 if (pScrn->modes == NULL) {
640 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
641 return (FALSE);
642 }
643
644 /* options */
645 xf86CollectOptions(pScrn, NULL);
646 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
647 return FALSE;
648 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
649 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
650
651 /* Framebuffer-related setup */
652 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
653 return (TRUE);
654}
655
656/*
657 * QUOTE from the XFree86 DESIGN document:
658 *
659 * This is called at the start of each server generation.
660 *
661 * (...)
662 *
663 * Decide which operations need to be placed under resource access
664 * control. (...) Map any video memory or other memory regions. (...)
665 * Save the video card state. (...) Initialise the initial video
666 * mode.
667 *
668 * End QUOTE.Initialise the initial video mode.
669 */
670static Bool
671VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
672{
673 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
674 VBOXPtr pVBox = VBOXGetRec(pScrn);
675 VisualPtr visual;
676 unsigned flags;
677
678 /* We make use of the X11 VBE code to save and restore text mode, in
679 order to keep our code simple. */
680 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
681 SET_BIOS_SCRATCH
682 | RESTORE_BIOS_SCRATCH)) == NULL)
683 return (FALSE);
684
685 if (pVBox->mapPhys == 0) {
686 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
687/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
688 /* Using the PCI information caused problems with
689 non-powers-of-two sized video RAM configurations */
690 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
691 pVBox->mapOff = 0;
692 }
693
694 if (!VBOXMapVidMem(pScrn))
695 return (FALSE);
696
697 /* save current video state */
698 VBOXSaveRestore(pScrn, MODE_SAVE);
699 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
700 NULL, FALSE, FALSE);
701
702 /* set first video mode */
703 if (!VBOXSetMode(pScrn, pScrn->currentMode))
704 return FALSE;
705
706 /* set the viewport */
707 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
708
709 /* Blank the screen for aesthetic reasons. */
710 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
711
712 /* mi layer - reset the visual list (?)*/
713 miClearVisualTypes();
714 if (!xf86SetDefaultVisual(pScrn, -1))
715 return (FALSE);
716 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
717 pScrn->rgbBits, TrueColor))
718 return (FALSE);
719 if (!miSetPixmapDepths())
720 return (FALSE);
721
722 /* I checked in the sources, and XFree86 4.2 does seem to support
723 this function for 32bpp. */
724 if (!fbScreenInit(pScreen, pVBox->base,
725 pScrn->virtualX, pScrn->virtualY,
726 pScrn->xDpi, pScrn->yDpi,
727 pScrn->displayWidth, pScrn->bitsPerPixel))
728 return (FALSE);
729
730 /* Fixup RGB ordering */
731 visual = pScreen->visuals + pScreen->numVisuals;
732 while (--visual >= pScreen->visuals) {
733 if ((visual->class | DynamicClass) == DirectColor) {
734 visual->offsetRed = pScrn->offset.red;
735 visual->offsetGreen = pScrn->offset.green;
736 visual->offsetBlue = pScrn->offset.blue;
737 visual->redMask = pScrn->mask.red;
738 visual->greenMask = pScrn->mask.green;
739 visual->blueMask = pScrn->mask.blue;
740 }
741 }
742
743 /* must be after RGB ordering fixed */
744 fbPictureInit(pScreen, 0, 0);
745
746 VBOXDGAInit(pScrn, pScreen);
747
748 xf86SetBlackWhitePixels(pScreen);
749 miInitializeBackingStore(pScreen);
750 xf86SetBackingStore(pScreen);
751
752 /* software cursor */
753 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
754
755 /* colourmap code - apparently, we need this even in Truecolour */
756 if (!miCreateDefColormap(pScreen))
757 return (FALSE);
758
759 flags = CMAP_RELOAD_ON_MODE_SWITCH;
760
761 if(!xf86HandleColormaps(pScreen, 256,
762 8 /* DAC is switchable to 8 bits per primary color */,
763 VBOXLoadPalette, NULL, flags))
764 return (FALSE);
765
766 pVBox->CloseScreen = pScreen->CloseScreen;
767 pScreen->CloseScreen = VBOXCloseScreen;
768 pScreen->SaveScreen = VBOXSaveScreen;
769
770 /* However, we probably do want to support power management -
771 even if we just use a dummy function. */
772 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
773
774 /* Report any unused options (only for the first generation) */
775 if (serverGeneration == 1)
776 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
777
778 if (vbox_open (pScrn, pScreen, pVBox)) {
779 if (vbox_cursor_init(pScreen) != TRUE)
780 xf86DrvMsg(scrnIndex, X_ERROR,
781 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
782 if (vboxEnableVbva(pScrn) == TRUE)
783 xf86DrvMsg(scrnIndex, X_INFO,
784 "The VBox video extensions are now enabled.\n");
785 }
786 return (TRUE);
787}
788
789static Bool
790VBOXEnterVT(int scrnIndex, int flags)
791{
792 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
793 VBOXPtr pVBox = VBOXGetRec(pScrn);
794
795 if (!VBOXSetMode(pScrn, pScrn->currentMode))
796 return FALSE;
797 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
798 if (pVBox->useVbva == TRUE)
799 vboxEnableVbva(pScrn);
800 return TRUE;
801}
802
803static void
804VBOXLeaveVT(int scrnIndex, int flags)
805{
806 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
807 VBOXPtr pVBox = VBOXGetRec(pScrn);
808
809 VBOXSaveRestore(pScrn, MODE_RESTORE);
810 if (pVBox->useVbva == TRUE)
811 vboxDisableVbva(pScrn);
812}
813
814static Bool
815VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
816{
817 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
818 VBOXPtr pVBox = VBOXGetRec(pScrn);
819
820 if (pVBox->useVbva == TRUE)
821 vboxDisableVbva(pScrn);
822 if (pScrn->vtSema) {
823 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
824 if (pVBox->savedPal)
825 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
826 pVBox->savedPal, FALSE, TRUE);
827 VBOXUnmapVidMem(pScrn);
828 }
829 if (pVBox->pDGAMode) {
830 xfree(pVBox->pDGAMode);
831 pVBox->pDGAMode = NULL;
832 pVBox->nDGAMode = 0;
833 }
834 pScrn->vtSema = FALSE;
835
836 pScreen->CloseScreen = pVBox->CloseScreen;
837 return pScreen->CloseScreen(scrnIndex, pScreen);
838}
839
840static Bool
841VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
842{
843 ScrnInfoPtr pScrn;
844 VBOXPtr pVBox;
845
846 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
847 pVBox = VBOXGetRec(pScrn);
848 if (pVBox->useVbva == TRUE)
849 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
850 return FALSE;
851 if (VBOXSetMode(pScrn, pMode) != TRUE)
852 return FALSE;
853 if (pVBox->useVbva == TRUE)
854 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
855 pVBox->useVbva = FALSE;
856 return TRUE;
857}
858
859/* Set a graphics mode */
860static Bool
861VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
862{
863 VBOXPtr pVBox;
864
865 int bpp = pScrn->depth == 24 ? 32 : 16;
866 int xRes = pMode->HDisplay;
867 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
868 >= pScrn->videoRam * 1024)
869 {
870 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
871 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
872 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
873 return FALSE;
874 }
875 /* We only support horizontal resolutions which are a multiple of 8. Round down if
876 necessary. */
877 if (xRes % 8 != 0)
878 {
879 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
880 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
881 xRes, xRes - (xRes % 8));
882 xRes = xRes - (xRes % 8);
883 }
884 pVBox = VBOXGetRec(pScrn);
885 pScrn->vtSema = TRUE;
886 /* Disable linear framebuffer mode before making changes to the resolution. */
887 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
888 outw(VBE_DISPI_IOPORT_DATA,
889 VBE_DISPI_DISABLED);
890 /* Unlike the resolution, the depth is fixed for a given screen
891 for the lifetime of the X session. */
892 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
893 outw(VBE_DISPI_IOPORT_DATA, bpp);
894 /* HDisplay and VDisplay are actually monitor information about
895 the display part of the scanlines. */
896 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
897 outw(VBE_DISPI_IOPORT_DATA, xRes);
898 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
899 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
900 /* Enable linear framebuffer mode. */
901 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
902 outw(VBE_DISPI_IOPORT_DATA,
903 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
904 /* Set the virtual resolution. We are still using VESA to control
905 the virtual offset. */
906 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
907 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
908 return (TRUE);
909}
910
911static void
912VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
913{
914 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
915 TRACE3("scrnIndex=%d, x=%d, y=%d, flags=%d\n", scrnIndex, x, y, flags);
916
917 pVBox->viewportX = x;
918 pVBox->viewportY = y;
919 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
920}
921
922static void
923VBOXFreeScreen(int scrnIndex, int flags)
924{
925 VBOXFreeRec(xf86Screens[scrnIndex]);
926}
927
928static Bool
929VBOXMapVidMem(ScrnInfoPtr pScrn)
930{
931 VBOXPtr pVBox = VBOXGetRec(pScrn);
932
933 if (pVBox->base != NULL)
934 return (TRUE);
935
936 pScrn->memPhysBase = pVBox->mapPhys;
937 pScrn->fbOffset = pVBox->mapOff;
938
939 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
940 VIDMEM_FRAMEBUFFER,
941 pVBox->pciTag, pVBox->mapPhys,
942 (unsigned) pVBox->mapSize);
943
944 if (pVBox->base) {
945 pScrn->memPhysBase = pVBox->mapPhys;
946 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
947 pVBox->pciTag,
948 0xa0000, 0x10000);
949 }
950 /* We need this for saving/restoring textmode */
951 pVBox->ioBase = pScrn->domainIOBase;
952
953 return (pVBox->base != NULL);
954}
955
956static void
957VBOXUnmapVidMem(ScrnInfoPtr pScrn)
958{
959 VBOXPtr pVBox = VBOXGetRec(pScrn);
960
961 if (pVBox->base == NULL)
962 return;
963
964 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
965 (unsigned) pVBox->mapSize);
966 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
967 pVBox->base = NULL;
968}
969
970static void
971VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
972 LOCO *colors, VisualPtr pVisual)
973{
974 VBOXPtr pVBox = VBOXGetRec(pScrn);
975 int i, idx;
976#define VBOXDACDelay() \
977 do { \
978 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
979 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
980 } while (0)
981
982 for (i = 0; i < numColors; i++) {
983 idx = indices[i];
984 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
985 VBOXDACDelay();
986 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
987 VBOXDACDelay();
988 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
989 VBOXDACDelay();
990 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
991 VBOXDACDelay();
992 }
993}
994
995/*
996 * Just adapted from the std* functions in vgaHW.c
997 */
998static void
999WriteAttr(VBOXPtr pVBox, int index, int value)
1000{
1001 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1002
1003 index |= 0x20;
1004 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1005 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
1006}
1007
1008static int
1009ReadAttr(VBOXPtr pVBox, int index)
1010{
1011 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1012
1013 index |= 0x20;
1014 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1015 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
1016}
1017
1018#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
1019#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
1020#define WriteSeq(index, value) \
1021 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
1022 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
1023
1024static int
1025ReadSeq(VBOXPtr pVBox, int index)
1026{
1027 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
1028
1029 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1030}
1031
1032#define WriteGr(index, value) \
1033 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1034 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1035
1036static int
1037ReadGr(VBOXPtr pVBox, int index)
1038{
1039 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1040
1041 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1042}
1043
1044#define WriteCrtc(index, value) \
1045 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1046 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1047
1048static void
1049SeqReset(VBOXPtr pVBox, Bool start)
1050{
1051 if (start) {
1052 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1053 }
1054 else {
1055 WriteSeq(0x00, 0x03); /* End Reset */
1056 }
1057}
1058
1059static void
1060SaveFonts(ScrnInfoPtr pScrn)
1061{
1062 VBOXPtr pVBox = VBOXGetRec(pScrn);
1063 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1064
1065 if (pVBox->fonts != NULL)
1066 return;
1067
1068 /* If in graphics mode, don't save anything */
1069 attr10 = ReadAttr(pVBox, 0x10);
1070 if (attr10 & 0x01)
1071 return;
1072
1073 pVBox->fonts = xalloc(16384);
1074
1075 /* save the registers that are needed here */
1076 miscOut = ReadMiscOut();
1077 gr4 = ReadGr(pVBox, 0x04);
1078 gr5 = ReadGr(pVBox, 0x05);
1079 gr6 = ReadGr(pVBox, 0x06);
1080 seq2 = ReadSeq(pVBox, 0x02);
1081 seq4 = ReadSeq(pVBox, 0x04);
1082
1083 /* Force into colour mode */
1084 WriteMiscOut(miscOut | 0x01);
1085
1086 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1087 SeqReset(pVBox, TRUE);
1088 WriteSeq(0x01, scrn);
1089 SeqReset(pVBox, FALSE);
1090
1091 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1092
1093 /*font1 */
1094 WriteSeq(0x02, 0x04); /* write to plane 2 */
1095 WriteSeq(0x04, 0x06); /* enable plane graphics */
1096 WriteGr(0x04, 0x02); /* read plane 2 */
1097 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1098 WriteGr(0x06, 0x05); /* set graphics */
1099 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1100
1101 /* font2 */
1102 WriteSeq(0x02, 0x08); /* write to plane 3 */
1103 WriteSeq(0x04, 0x06); /* enable plane graphics */
1104 WriteGr(0x04, 0x03); /* read plane 3 */
1105 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1106 WriteGr(0x06, 0x05); /* set graphics */
1107 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1108
1109 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1110 SeqReset(pVBox, TRUE);
1111 WriteSeq(0x01, scrn);
1112 SeqReset(pVBox, FALSE);
1113
1114 /* Restore clobbered registers */
1115 WriteAttr(pVBox, 0x10, attr10);
1116 WriteSeq(0x02, seq2);
1117 WriteSeq(0x04, seq4);
1118 WriteGr(0x04, gr4);
1119 WriteGr(0x05, gr5);
1120 WriteGr(0x06, gr6);
1121 WriteMiscOut(miscOut);
1122}
1123
1124static void
1125RestoreFonts(ScrnInfoPtr pScrn)
1126{
1127 VBOXPtr pVBox = VBOXGetRec(pScrn);
1128 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1129
1130 if (pVBox->fonts == NULL)
1131 return;
1132
1133 /* save the registers that are needed here */
1134 miscOut = ReadMiscOut();
1135 attr10 = ReadAttr(pVBox, 0x10);
1136 gr1 = ReadGr(pVBox, 0x01);
1137 gr3 = ReadGr(pVBox, 0x03);
1138 gr4 = ReadGr(pVBox, 0x04);
1139 gr5 = ReadGr(pVBox, 0x05);
1140 gr6 = ReadGr(pVBox, 0x06);
1141 gr8 = ReadGr(pVBox, 0x08);
1142 seq2 = ReadSeq(pVBox, 0x02);
1143 seq4 = ReadSeq(pVBox, 0x04);
1144
1145 /* Force into colour mode */
1146 WriteMiscOut(miscOut | 0x01);
1147
1148 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1149 SeqReset(pVBox, TRUE);
1150 WriteSeq(0x01, scrn);
1151 SeqReset(pVBox, FALSE);
1152
1153 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1154 if (pScrn->depth == 4) {
1155 /* GJA */
1156 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1157 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1158 WriteGr(0x01, 0x00); /* all planes come from CPU */
1159 }
1160
1161 WriteSeq(0x02, 0x04); /* write to plane 2 */
1162 WriteSeq(0x04, 0x06); /* enable plane graphics */
1163 WriteGr(0x04, 0x02); /* read plane 2 */
1164 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1165 WriteGr(0x06, 0x05); /* set graphics */
1166 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1167
1168 WriteSeq(0x02, 0x08); /* write to plane 3 */
1169 WriteSeq(0x04, 0x06); /* enable plane graphics */
1170 WriteGr(0x04, 0x03); /* read plane 3 */
1171 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1172 WriteGr(0x06, 0x05); /* set graphics */
1173 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1174
1175 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1176 SeqReset(pVBox, TRUE);
1177 WriteSeq(0x01, scrn);
1178 SeqReset(pVBox, FALSE);
1179
1180 /* restore the registers that were changed */
1181 WriteMiscOut(miscOut);
1182 WriteAttr(pVBox, 0x10, attr10);
1183 WriteGr(0x01, gr1);
1184 WriteGr(0x03, gr3);
1185 WriteGr(0x04, gr4);
1186 WriteGr(0x05, gr5);
1187 WriteGr(0x06, gr6);
1188 WriteGr(0x08, gr8);
1189 WriteSeq(0x02, seq2);
1190 WriteSeq(0x04, seq4);
1191}
1192
1193static Bool
1194VBOXSaveScreen(ScreenPtr pScreen, int mode)
1195{
1196 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1197 VBOXPtr pVBox = VBOXGetRec(pScrn);
1198 Bool on = xf86IsUnblank(mode);
1199
1200 if (on)
1201 SetTimeSinceLastInputEvent();
1202
1203 if (pScrn->vtSema) {
1204 unsigned char scrn = ReadSeq(pVBox, 0x01);
1205
1206 if (on)
1207 scrn &= ~0x20;
1208 else
1209 scrn |= 0x20;
1210 SeqReset(pVBox, TRUE);
1211 WriteSeq(0x01, scrn);
1212 SeqReset(pVBox, FALSE);
1213 }
1214
1215 return (TRUE);
1216}
1217
1218Bool
1219VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1220{
1221 VBOXPtr pVBox;
1222
1223 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1224 return (FALSE);
1225
1226 pVBox = VBOXGetRec(pScrn);
1227
1228
1229 /* Query amount of memory to save state */
1230 if (function == MODE_QUERY ||
1231 (function == MODE_SAVE && pVBox->state == NULL))
1232 {
1233
1234 /* Make sure we save at least this information in case of failure */
1235 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1236 SaveFonts(pScrn);
1237
1238 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1239 &pVBox->stateSize,&pVBox->statePage))
1240 return FALSE;
1241 }
1242
1243 /* Save/Restore Super VGA state */
1244 if (function != MODE_QUERY) {
1245 Bool retval = TRUE;
1246
1247 if (function == MODE_RESTORE)
1248 memcpy(pVBox->state, pVBox->pstate,
1249 (unsigned) pVBox->stateSize);
1250
1251 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1252 (pointer)&pVBox->state,
1253 &pVBox->stateSize,&pVBox->statePage))
1254 && function == MODE_SAVE)
1255 {
1256 /* don't rely on the memory not being touched */
1257 if (pVBox->pstate == NULL)
1258 pVBox->pstate = xalloc(pVBox->stateSize);
1259 memcpy(pVBox->pstate, pVBox->state,
1260 (unsigned) pVBox->stateSize);
1261 }
1262
1263 if (function == MODE_RESTORE)
1264 {
1265 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1266 RestoreFonts(pScrn);
1267 }
1268
1269 if (!retval)
1270 return (FALSE);
1271
1272 }
1273
1274 return (TRUE);
1275}
1276
1277static void
1278VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1279 int flags)
1280{
1281 /* VBox is always power efficient... */
1282}
1283
1284
1285
1286
1287/***********************************************************************
1288 * DGA stuff
1289 ***********************************************************************/
1290static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1291 unsigned char **ApertureBase,
1292 int *ApertureSize, int *ApertureOffset,
1293 int *flags);
1294static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1295static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1296
1297static Bool
1298VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1299 unsigned char **ApertureBase, int *ApertureSize,
1300 int *ApertureOffset, int *flags)
1301{
1302 VBOXPtr pVBox = VBOXGetRec(pScrn);
1303
1304 *DeviceName = NULL; /* No special device */
1305 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1306 *ApertureSize = pVBox->mapSize;
1307 *ApertureOffset = pVBox->mapOff;
1308 *flags = DGA_NEED_ROOT;
1309
1310 return (TRUE);
1311}
1312
1313static Bool
1314VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1315{
1316 DisplayModePtr pMode;
1317 int scrnIdx = pScrn->pScreen->myNum;
1318 int frameX0, frameY0;
1319
1320 if (pDGAMode) {
1321 pMode = pDGAMode->mode;
1322 frameX0 = frameY0 = 0;
1323 }
1324 else {
1325 if (!(pMode = pScrn->currentMode))
1326 return (TRUE);
1327
1328 frameX0 = pScrn->frameX0;
1329 frameY0 = pScrn->frameY0;
1330 }
1331
1332 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1333 return (FALSE);
1334 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1335
1336 return (TRUE);
1337}
1338
1339static void
1340VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1341{
1342 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1343}
1344
1345static int
1346VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1347{
1348 return (0);
1349}
1350
1351static DGAFunctionRec VBOXDGAFunctions =
1352{
1353 VBOXDGAOpenFramebuffer,
1354 NULL, /* CloseFramebuffer */
1355 VBOXDGASetMode,
1356 VBOXDGASetViewport,
1357 VBOXDGAGetViewport,
1358 NULL, /* Sync */
1359 NULL, /* FillRect */
1360 NULL, /* BlitRect */
1361 NULL, /* BlitTransRect */
1362};
1363
1364static void
1365VBOXDGAAddModes(ScrnInfoPtr pScrn)
1366{
1367 VBOXPtr pVBox = VBOXGetRec(pScrn);
1368 DisplayModePtr pMode = pScrn->modes;
1369 DGAModePtr pDGAMode;
1370
1371 do {
1372 pDGAMode = xrealloc(pVBox->pDGAMode,
1373 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1374 if (!pDGAMode)
1375 break;
1376
1377 pVBox->pDGAMode = pDGAMode;
1378 pDGAMode += pVBox->nDGAMode;
1379 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1380
1381 ++pVBox->nDGAMode;
1382 pDGAMode->mode = pMode;
1383 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1384 pDGAMode->byteOrder = pScrn->imageByteOrder;
1385 pDGAMode->depth = pScrn->depth;
1386 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1387 pDGAMode->red_mask = pScrn->mask.red;
1388 pDGAMode->green_mask = pScrn->mask.green;
1389 pDGAMode->blue_mask = pScrn->mask.blue;
1390 pDGAMode->visualClass = TrueColor;
1391 pDGAMode->xViewportStep = 1;
1392 pDGAMode->yViewportStep = 1;
1393 pDGAMode->viewportWidth = pMode->HDisplay;
1394 pDGAMode->viewportHeight = pMode->VDisplay;
1395
1396 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1397 pDGAMode->imageWidth = pMode->HDisplay;
1398 pDGAMode->imageHeight = pMode->VDisplay;
1399 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1400 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1401 pDGAMode->maxViewportX = pScrn->virtualX -
1402 pDGAMode->viewportWidth;
1403 pDGAMode->maxViewportY = pScrn->virtualY -
1404 pDGAMode->viewportHeight;
1405
1406 pDGAMode->address = pVBox->base;
1407
1408 pMode = pMode->next;
1409 } while (pMode != pScrn->modes);
1410}
1411
1412static Bool
1413VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1414{
1415 VBOXPtr pVBox = VBOXGetRec(pScrn);
1416
1417 if (!pVBox->nDGAMode)
1418 VBOXDGAAddModes(pScrn);
1419
1420 return (DGAInit(pScreen, &VBOXDGAFunctions,
1421 pVBox->pDGAMode, pVBox->nDGAMode));
1422}
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