VirtualBox

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

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

Additions/x11/vboxvideo: use vboxvideo_70 for the XFree86 driver too

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

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