VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xgraphics/vboxvideo.c@ 1260

Last change on this file since 1260 was 1260, checked in by vboxsync, 18 years ago

display VBOX_VERSION_STRING in Xorg.log.0 for better bug reports from end-users

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