VirtualBox

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

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

Cleaned up EOL style and uppercase names

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