VirtualBox

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

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

allow to specify arbitrary X resolutions + use the right virtual resolutions (#1891)

  • Property svn:eol-style set to native
File size: 44.8 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 DisplayModePtr m_prev;
420
421 /* Are we really starting the server, or is this just a dummy run? */
422 if (flags & PROBE_DETECT)
423 return (FALSE);
424
425 xf86Msg(X_INFO,
426 "VirtualBox guest additions video driver version "
427 VBOX_VERSION_STRING "\n");
428
429 /* Get our private data from the ScrnInfoRec structure. */
430 pVBox = VBOXGetRec(pScrn);
431
432 /* Entity information seems to mean bus information. */
433 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
434 if (pVBox->pEnt->location.type != BUS_PCI)
435 return FALSE;
436
437 /* The ramdac module is needed for the hardware cursor. */
438 if (!xf86LoadSubModule(pScrn, "ramdac"))
439 return FALSE;
440 xf86LoaderReqSymLists(ramdacSymbols, NULL);
441
442 /* We need the vbe module because we use VBE code to save and restore
443 text mode, in order to keep our code simple. */
444 if (!xf86LoadSubModule(pScrn, "vbe"))
445 return (FALSE);
446 xf86LoaderReqSymLists(vbeSymbols, NULL);
447
448 /* The framebuffer module. */
449 if (xf86LoadSubModule(pScrn, "fb") == NULL)
450 return (FALSE);
451 xf86LoaderReqSymLists(fbSymbols, NULL);
452
453 if (!xf86LoadSubModule(pScrn, "shadowfb"))
454 return FALSE;
455 xf86LoaderReqSymLists(shadowfbSymbols, NULL);
456
457 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
458 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
459 pVBox->pciInfo->device,
460 pVBox->pciInfo->func);
461
462 /* Set up our ScrnInfoRec structure to describe our virtual
463 capabilities to X. */
464
465 pScrn->rgbBits = 8;
466
467 /* Let's create a nice, capable virtual monitor. */
468 pScrn->monitor = pScrn->confScreen->monitor;
469 pScrn->monitor->DDC = NULL;
470 pScrn->monitor->nHsync = 1;
471 pScrn->monitor->hsync[0].lo = 1;
472 pScrn->monitor->hsync[0].hi = 10000;
473 pScrn->monitor->nVrefresh = 1;
474 pScrn->monitor->vrefresh[0].lo = 1;
475 pScrn->monitor->vrefresh[0].hi = 100;
476
477 pScrn->chipset = "vbox";
478 pScrn->progClock = TRUE;
479
480 /* Determine the size of the VBox video RAM from PCI data*/
481#if 0
482 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
483#endif
484 /* Using the PCI information caused problems with non-powers-of-two
485 sized video RAM configurations */
486 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
487
488 /* Set up clock information that will support all modes we need. */
489 clockRanges = xnfcalloc(sizeof(ClockRange), 1);
490 clockRanges->next = NULL;
491 clockRanges->minClock = 1000;
492 clockRanges->maxClock = 1000000000;
493 clockRanges->clockIndex = -1;
494 clockRanges->ClockMulFactor = 1;
495 clockRanges->ClockDivFactor = 1;
496
497 /* This function asks X to choose a depth and bpp based on the
498 config file and the command line, and gives a default in
499 case none is specified. Note that we only support 32bpp, not
500 24bpp. After spending ages looking through the XFree86 4.2
501 source code however, I realised that it automatically uses
502 32bpp for depth 24 unless you explicitly add a "24 24"
503 format to its internal list. */
504 if (!xf86SetDepthBpp(pScrn, pScrn->videoRam >= 2048 ? 24 : 16, 0, 0,
505 Support32bppFb))
506 return FALSE;
507 if (pScrn->depth != 24 && pScrn->depth != 16)
508 {
509 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
510 "The VBox additions only support 16 and 32bpp graphics modes\n");
511 return FALSE;
512 }
513 xf86PrintDepthBpp(pScrn);
514
515 /* Colour weight - we always call this, since we are always in
516 truecolour. */
517 if (!xf86SetWeight(pScrn, rzeros, rzeros))
518 return (FALSE);
519
520 /* visual init */
521 if (!xf86SetDefaultVisual(pScrn, -1))
522 return (FALSE);
523
524 xf86SetGamma(pScrn, gzeros);
525
526 /* To get around the problem of SUSE specifying a single, invalid mode in their
527 * Xorg.conf by default, we add an additional mode to the end of the user specified
528 * list. This means that if all user modes are invalid, X will try our mode before
529 * falling back to its standard mode list. */
530 if (pScrn->display->modes == NULL)
531 {
532 /* The user specified no modes at all - specify 1024x768 as a default. */
533 pScrn->display->modes = xnfalloc(2 * sizeof(char*));
534 pScrn->display->modes[0] = "1024x768";
535 pScrn->display->modes[1] = NULL;
536 }
537 else
538 {
539 /* Add 1024x768 to the end of the mode list in case the others are all invalid. */
540 for (i = 0; pScrn->display->modes[i] != NULL; i++);
541 pScrn->display->modes = xnfrealloc(pScrn->display->modes, (i + 2)
542 * sizeof(char *));
543 pScrn->display->modes[i ] = "1024x768";
544 pScrn->display->modes[i+1] = NULL;
545 }
546
547 /* Determine the virtual screen resolution from the first mode (which will be selected) */
548 sscanf(pScrn->display->modes[0], "%dx%d",
549 &pScrn->display->virtualX, &pScrn->display->virtualY);
550 pScrn->display->virtualX = (pScrn->display->virtualX + 7) & ~7;
551
552 /* Create a builtin mode for every specified mode. This allows to specify arbitrary
553 * screen resolutions */
554 m_prev = NULL;
555 for (i = 0; pScrn->display->modes[i] != NULL; i++)
556 {
557 DisplayModePtr m;
558 int x = 0, y = 0;
559
560 sscanf(pScrn->display->modes[i], "%dx%d", &x, &y);
561 /* sanity check, smaller resolutions does not make sense */
562 if (x < 64 || y < 64)
563 {
564 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring mode \"%s\"\n",
565 pScrn->display->modes[i]);
566 continue;
567 }
568 m = xnfcalloc(sizeof(DisplayModeRec), 1);
569 m->status = MODE_OK;
570 m->type = M_T_BUILTIN;
571 /* VBox does only support screen widths which are a multiple of 8 */
572 m->HDisplay = (x + 7) & ~7;
573 m->VDisplay = y;
574 m->name = strdup(pScrn->display->modes[i]);
575 if (!m_prev)
576 pScrn->modePool = m;
577 else
578 m_prev->next = m;
579 m->prev = m_prev;
580 m_prev = m;
581 }
582
583 /* Filter out video modes not supported by the virtual hardware
584 we described. All modes used by the Windows additions should
585 work fine. */
586 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
587 pScrn->display->modes,
588 clockRanges, NULL, 0, 6400, 1, 0, 1440,
589 pScrn->display->virtualX,
590 pScrn->display->virtualY,
591 pScrn->videoRam, LOOKUP_BEST_REFRESH);
592
593 if (i <= 0) {
594 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
595 return (FALSE);
596 }
597 xf86PruneDriverModes(pScrn);
598
599 pScrn->currentMode = pScrn->modes;
600 pScrn->displayWidth = pScrn->virtualX;
601
602 xf86PrintModes(pScrn);
603
604 /* Set display resolution. This was arbitrarily chosen to be about the same as my monitor. */
605 xf86SetDpi(pScrn, 100, 100);
606
607 if (pScrn->modes == NULL) {
608 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
609 return (FALSE);
610 }
611
612 /* options */
613 xf86CollectOptions(pScrn, NULL);
614 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
615 return FALSE;
616 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
617 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
618
619 /* Framebuffer-related setup */
620 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
621 return (TRUE);
622}
623
624/*
625 * QUOTE from the XFree86 DESIGN document:
626 *
627 * This is called at the start of each server generation.
628 *
629 * (...)
630 *
631 * Decide which operations need to be placed under resource access
632 * control. (...) Map any video memory or other memory regions. (...)
633 * Save the video card state. (...) Initialise the initial video
634 * mode.
635 *
636 * End QUOTE.Initialise the initial video mode.
637 */
638static Bool
639VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
640{
641 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
642 VBOXPtr pVBox = VBOXGetRec(pScrn);
643 VisualPtr visual;
644 unsigned flags;
645
646 /* We make use of the X11 VBE code to save and restore text mode, in
647 order to keep our code simple. */
648#ifdef XORG_7X
649 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
650 SET_BIOS_SCRATCH
651 | RESTORE_BIOS_SCRATCH)) == NULL)
652#else
653 if ((pVBox->pVbe = VBEInit(NULL, pVBox->pEnt->index)) == NULL)
654#endif
655 return (FALSE);
656
657 if (pVBox->mapPhys == 0) {
658 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
659/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
660 /* Using the PCI information caused problems with
661 non-powers-of-two sized video RAM configurations */
662 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
663 pVBox->mapOff = 0;
664 }
665
666 if (!VBOXMapVidMem(pScrn))
667 return (FALSE);
668
669 /* save current video state */
670 VBOXSaveRestore(pScrn, MODE_SAVE);
671 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
672 NULL, FALSE, FALSE);
673
674 /* set first video mode */
675 if (!VBOXSetMode(pScrn, pScrn->currentMode))
676 return FALSE;
677
678#ifdef XORG_7X
679 /* set the viewport */
680 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
681
682 /* Blank the screen for aesthetic reasons. */
683 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
684#endif
685
686 /* mi layer - reset the visual list (?)*/
687 miClearVisualTypes();
688 if (!xf86SetDefaultVisual(pScrn, -1))
689 return (FALSE);
690 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
691 pScrn->rgbBits, TrueColor))
692 return (FALSE);
693 if (!miSetPixmapDepths())
694 return (FALSE);
695
696 /* I checked in the sources, and XFree86 4.2 does seem to support
697 this function for 32bpp. */
698 if (!fbScreenInit(pScreen, pVBox->base,
699 pScrn->virtualX, pScrn->virtualY,
700 pScrn->xDpi, pScrn->yDpi,
701 pScrn->displayWidth, pScrn->bitsPerPixel))
702 return (FALSE);
703
704 /* Fixup RGB ordering */
705 visual = pScreen->visuals + pScreen->numVisuals;
706 while (--visual >= pScreen->visuals) {
707 if ((visual->class | DynamicClass) == DirectColor) {
708 visual->offsetRed = pScrn->offset.red;
709 visual->offsetGreen = pScrn->offset.green;
710 visual->offsetBlue = pScrn->offset.blue;
711 visual->redMask = pScrn->mask.red;
712 visual->greenMask = pScrn->mask.green;
713 visual->blueMask = pScrn->mask.blue;
714 }
715 }
716
717 /* must be after RGB ordering fixed */
718 fbPictureInit(pScreen, 0, 0);
719
720 VBOXDGAInit(pScrn, pScreen);
721
722 xf86SetBlackWhitePixels(pScreen);
723 miInitializeBackingStore(pScreen);
724 xf86SetBackingStore(pScreen);
725
726 /* software cursor */
727 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
728
729 /* colourmap code - apparently, we need this even in Truecolour */
730 if (!miCreateDefColormap(pScreen))
731 return (FALSE);
732
733 flags = CMAP_RELOAD_ON_MODE_SWITCH;
734
735 if(!xf86HandleColormaps(pScreen, 256,
736 pVBox->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6,
737 VBOXLoadPalette, NULL, flags))
738 return (FALSE);
739
740 pVBox->CloseScreen = pScreen->CloseScreen;
741 pScreen->CloseScreen = VBOXCloseScreen;
742 pScreen->SaveScreen = VBOXSaveScreen;
743
744 /* However, we probably do want to support power management -
745 even if we just use a dummy function. */
746 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
747
748 /* Report any unused options (only for the first generation) */
749 if (serverGeneration == 1)
750 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
751
752 if (vbox_open (pScrn, pScreen, pVBox)) {
753 if (vbox_cursor_init(pScreen) != TRUE)
754 xf86DrvMsg(scrnIndex, X_ERROR,
755 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
756 if (vboxEnableVbva(pScrn) == TRUE)
757 xf86DrvMsg(scrnIndex, X_INFO,
758 "The VBox video extensions are now enabled.\n");
759 } else
760 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");
761 return (TRUE);
762}
763
764static Bool
765VBOXEnterVT(int scrnIndex, int flags)
766{
767 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
768 VBOXPtr pVBox = VBOXGetRec(pScrn);
769
770 if (!VBOXSetMode(pScrn, pScrn->currentMode))
771 return FALSE;
772#ifdef XORG_7X
773 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
774#endif /* XORG_7X defined */
775 if (pVBox->useVbva == TRUE)
776 vboxEnableVbva(pScrn);
777 return TRUE;
778}
779
780static void
781VBOXLeaveVT(int scrnIndex, int flags)
782{
783 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
784 VBOXPtr pVBox = VBOXGetRec(pScrn);
785
786 VBOXSaveRestore(pScrn, MODE_RESTORE);
787 if (pVBox->useVbva == TRUE)
788 vboxDisableVbva(pScrn);
789}
790
791static Bool
792VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
793{
794 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
795 VBOXPtr pVBox = VBOXGetRec(pScrn);
796
797 if (pVBox->useVbva == TRUE)
798 vboxDisableVbva(pScrn);
799 if (pScrn->vtSema) {
800 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
801#ifdef XORG_7X
802 if (pVBox->savedPal)
803 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
804 pVBox->savedPal, FALSE, TRUE);
805#else
806 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
807 pVBox->savedPal, FALSE, TRUE);
808#endif
809 VBOXUnmapVidMem(pScrn);
810 }
811 if (pVBox->pDGAMode) {
812 xfree(pVBox->pDGAMode);
813 pVBox->pDGAMode = NULL;
814 pVBox->nDGAMode = 0;
815 }
816 pScrn->vtSema = FALSE;
817
818 pScreen->CloseScreen = pVBox->CloseScreen;
819 return pScreen->CloseScreen(scrnIndex, pScreen);
820}
821
822static Bool
823VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
824{
825 ScrnInfoPtr pScrn;
826 VBOXPtr pVBox;
827
828 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
829 pVBox = VBOXGetRec(pScrn);
830 if (pVBox->useVbva == TRUE)
831 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
832 return FALSE;
833 if (VBOXSetMode(pScrn, pMode) != TRUE)
834 return FALSE;
835 if (pVBox->useVbva == TRUE)
836 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
837 pVBox->useVbva = FALSE;
838 return TRUE;
839}
840
841/* Set a graphics mode */
842static Bool
843VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
844{
845 VBOXPtr pVBox;
846
847 int bpp = pScrn->depth == 24 ? 32 : 16;
848 int xRes = pMode->HDisplay;
849 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
850 >= pScrn->videoRam * 1024)
851 {
852 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
853 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
854 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
855 return FALSE;
856 }
857 /* We only support horizontal resolutions which are a multiple of 8. Round down if
858 necessary. */
859 if (xRes % 8 != 0)
860 {
861 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
862 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
863 xRes, xRes - (xRes % 8));
864 xRes = xRes - (xRes % 8);
865 }
866 pVBox = VBOXGetRec(pScrn);
867 pScrn->vtSema = TRUE;
868 /* Disable linear framebuffer mode before making changes to the resolution. */
869 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
870 outw(VBE_DISPI_IOPORT_DATA,
871 VBE_DISPI_DISABLED);
872 /* Unlike the resolution, the depth is fixed for a given screen
873 for the lifetime of the X session. */
874 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
875 outw(VBE_DISPI_IOPORT_DATA, bpp);
876 /* HDisplay and VDisplay are actually monitor information about
877 the display part of the scanlines. */
878 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
879 outw(VBE_DISPI_IOPORT_DATA, xRes);
880 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
881 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
882 /* Enable linear framebuffer mode. */
883 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
884 outw(VBE_DISPI_IOPORT_DATA,
885 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
886 /* Set the virtual resolution. We are still using VESA to control
887 the virtual offset. */
888 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
889 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
890 return (TRUE);
891}
892
893static void
894VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
895{
896 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
897
898 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
899}
900
901static void
902VBOXFreeScreen(int scrnIndex, int flags)
903{
904 VBOXFreeRec(xf86Screens[scrnIndex]);
905}
906
907static Bool
908VBOXMapVidMem(ScrnInfoPtr pScrn)
909{
910 VBOXPtr pVBox = VBOXGetRec(pScrn);
911
912 if (pVBox->base != NULL)
913 return (TRUE);
914
915 pScrn->memPhysBase = pVBox->mapPhys;
916 pScrn->fbOffset = pVBox->mapOff;
917
918 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
919 VIDMEM_FRAMEBUFFER,
920 pVBox->pciTag, pVBox->mapPhys,
921 (unsigned) pVBox->mapSize);
922
923 if (pVBox->base) {
924 pScrn->memPhysBase = pVBox->mapPhys;
925# ifdef XORG_7X
926 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
927 pVBox->pciTag,
928 0xa0000, 0x10000);
929# else
930 pVBox->VGAbase = xf86MapVidMem(pScrn->scrnIndex, 0,
931 0xa0000, 0x10000);
932# endif
933 }
934#ifdef XORG_7X
935 /* We need this for saving/restoring textmode */
936 pVBox->ioBase = pScrn->domainIOBase;
937#endif
938
939 return (pVBox->base != NULL);
940}
941
942static void
943VBOXUnmapVidMem(ScrnInfoPtr pScrn)
944{
945 VBOXPtr pVBox = VBOXGetRec(pScrn);
946
947 if (pVBox->base == NULL)
948 return;
949
950 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
951 (unsigned) pVBox->mapSize);
952 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
953 pVBox->base = NULL;
954}
955
956static void
957VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
958 LOCO *colors, VisualPtr pVisual)
959{
960#ifdef XORG_7X
961 VBOXPtr pVBox = VBOXGetRec(pScrn);
962 int i, idx;
963#endif
964#ifdef XORG_7X
965#define VBOXDACDelay() \
966 do { \
967 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
968 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
969 } while (0)
970#else
971#define WriteDacWriteAddr(value) outb(VGA_DAC_WRITE_ADDR, value)
972#define WriteDacData(value) outb(VGA_DAC_DATA, value);
973#undef DACDelay
974#define DACDelay() \
975 do { \
976 unsigned char temp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
977 temp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
978 } while (0)
979 int i, idx;
980#endif
981
982 for (i = 0; i < numColors; i++) {
983 idx = indices[i];
984#ifdef XORG_7X
985 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
986 VBOXDACDelay();
987 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
988 VBOXDACDelay();
989 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
990 VBOXDACDelay();
991 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
992 VBOXDACDelay();
993#else
994 WriteDacWriteAddr(idx);
995 DACDelay();
996 WriteDacData(colors[idx].red);
997 DACDelay();
998 WriteDacData(colors[idx].green);
999 DACDelay();
1000 WriteDacData(colors[idx].blue);
1001 DACDelay();
1002#endif
1003 }
1004}
1005
1006/*
1007 * Just adapted from the std* functions in vgaHW.c
1008 */
1009static void
1010#ifdef XORG_7X
1011WriteAttr(VBOXPtr pVBox, int index, int value)
1012{
1013 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1014
1015 index |= 0x20;
1016 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1017 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
1018#else
1019WriteAttr(int index, int value)
1020{
1021 CARD8 tmp;
1022
1023 tmp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1024
1025 index |= 0x20;
1026 outb(VGA_ATTR_INDEX, index);
1027 outb(VGA_ATTR_DATA_W, value);
1028#endif
1029}
1030
1031static int
1032#ifdef XORG_7X
1033ReadAttr(VBOXPtr pVBox, int index)
1034{
1035 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1036
1037 index |= 0x20;
1038 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1039 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
1040#else
1041ReadAttr(int index)
1042{
1043 CARD8 tmp;
1044
1045 tmp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1046
1047 index |= 0x20;
1048 outb(VGA_ATTR_INDEX, index);
1049 return (inb(VGA_ATTR_DATA_R));
1050#endif
1051}
1052
1053#ifdef XORG_7X
1054#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
1055#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
1056#define WriteSeq(index, value) \
1057 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
1058 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
1059#else
1060#define WriteMiscOut(value) outb(VGA_MISC_OUT_W, value)
1061#define ReadMiscOut() inb(VGA_MISC_OUT_R)
1062#define WriteSeq(index, value) \
1063 outb(VGA_SEQ_INDEX, (index));\
1064 outb(VGA_SEQ_DATA, value)
1065#endif
1066
1067static int
1068#ifdef XORG_7X
1069ReadSeq(VBOXPtr pVBox, int index)
1070{
1071 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
1072
1073 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1074#else
1075ReadSeq(int index)
1076{
1077 outb(VGA_SEQ_INDEX, index);
1078
1079 return (inb(VGA_SEQ_DATA));
1080#endif
1081}
1082
1083#ifdef XORG_7X
1084#define WriteGr(index, value) \
1085 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1086 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1087#else
1088#define WriteGr(index, value) outb(VGA_GRAPH_INDEX, index);\
1089 outb(VGA_GRAPH_DATA, value)
1090#endif
1091
1092static int
1093#ifdef XORG_7X
1094ReadGr(VBOXPtr pVBox, int index)
1095{
1096 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1097
1098 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1099#else
1100ReadGr(int index)
1101{
1102 outb(VGA_GRAPH_INDEX, index);
1103
1104 return (inb(VGA_GRAPH_DATA));
1105#endif
1106}
1107
1108#ifdef XORG_7X
1109#define WriteCrtc(index, value) \
1110 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1111 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1112#else
1113#define WriteCrtc(index, value) outb(VGA_CRTC_INDEX_OFFSET, index);\
1114 outb(VGA_CRTC_DATA_OFFSET, value)
1115#endif
1116
1117static void
1118#ifdef XORG_7X
1119SeqReset(VBOXPtr pVBox, Bool start)
1120{
1121 if (start) {
1122 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1123 }
1124 else {
1125 WriteSeq(0x00, 0x03); /* End Reset */
1126 }
1127#else
1128SeqReset(Bool start)
1129{
1130 if (start) {
1131 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1132 }
1133 else {
1134 WriteSeq(0x00, 0x03); /* End Reset */
1135 }
1136#endif
1137}
1138
1139static void
1140SaveFonts(ScrnInfoPtr pScrn)
1141{
1142 VBOXPtr pVBox = VBOXGetRec(pScrn);
1143 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1144
1145 if (pVBox->fonts != NULL)
1146 return;
1147
1148 /* If in graphics mode, don't save anything */
1149#ifdef XORG_7X
1150 attr10 = ReadAttr(pVBox, 0x10);
1151#else
1152 attr10 = ReadAttr(0x10);
1153#endif
1154 if (attr10 & 0x01)
1155 return;
1156
1157 pVBox->fonts = xalloc(16384);
1158
1159 /* save the registers that are needed here */
1160 miscOut = ReadMiscOut();
1161#ifdef XORG_7X
1162 gr4 = ReadGr(pVBox, 0x04);
1163 gr5 = ReadGr(pVBox, 0x05);
1164 gr6 = ReadGr(pVBox, 0x06);
1165 seq2 = ReadSeq(pVBox, 0x02);
1166 seq4 = ReadSeq(pVBox, 0x04);
1167#else
1168 gr4 = ReadGr(0x04);
1169 gr5 = ReadGr(0x05);
1170 gr6 = ReadGr(0x06);
1171 seq2 = ReadSeq(0x02);
1172 seq4 = ReadSeq(0x04);
1173#endif
1174
1175 /* Force into colour mode */
1176 WriteMiscOut(miscOut | 0x01);
1177
1178#ifdef XORG_7X
1179 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1180 SeqReset(pVBox, TRUE);
1181#else
1182 scrn = ReadSeq(0x01) | 0x20;
1183 SeqReset(TRUE);
1184#endif
1185 WriteSeq(0x01, scrn);
1186#ifdef XORG_7X
1187 SeqReset(pVBox, FALSE);
1188#else
1189 SeqReset(FALSE);
1190#endif
1191
1192#ifdef XORG_7X
1193 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1194#else
1195 WriteAttr(0x10, 0x01); /* graphics mode */
1196#endif
1197
1198 /*font1 */
1199 WriteSeq(0x02, 0x04); /* write to plane 2 */
1200 WriteSeq(0x04, 0x06); /* enable plane graphics */
1201 WriteGr(0x04, 0x02); /* read plane 2 */
1202 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1203 WriteGr(0x06, 0x05); /* set graphics */
1204 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1205
1206 /* font2 */
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_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1213
1214#ifdef XORG_7X
1215 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1216 SeqReset(pVBox, TRUE);
1217#else
1218 scrn = ReadSeq(0x01) & ~0x20;
1219 SeqReset(TRUE);
1220#endif
1221 WriteSeq(0x01, scrn);
1222#ifdef XORG_7X
1223 SeqReset(pVBox, FALSE);
1224#else
1225 SeqReset(FALSE);
1226#endif
1227
1228 /* Restore clobbered registers */
1229#ifdef XORG_7X
1230 WriteAttr(pVBox, 0x10, attr10);
1231#else
1232 WriteAttr(0x10, attr10);
1233#endif
1234 WriteSeq(0x02, seq2);
1235 WriteSeq(0x04, seq4);
1236 WriteGr(0x04, gr4);
1237 WriteGr(0x05, gr5);
1238 WriteGr(0x06, gr6);
1239 WriteMiscOut(miscOut);
1240}
1241
1242static void
1243RestoreFonts(ScrnInfoPtr pScrn)
1244{
1245 VBOXPtr pVBox = VBOXGetRec(pScrn);
1246 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1247
1248 if (pVBox->fonts == NULL)
1249 return;
1250
1251 /* save the registers that are needed here */
1252 miscOut = ReadMiscOut();
1253#ifdef XORG_7X
1254 attr10 = ReadAttr(pVBox, 0x10);
1255 gr1 = ReadGr(pVBox, 0x01);
1256 gr3 = ReadGr(pVBox, 0x03);
1257 gr4 = ReadGr(pVBox, 0x04);
1258 gr5 = ReadGr(pVBox, 0x05);
1259 gr6 = ReadGr(pVBox, 0x06);
1260 gr8 = ReadGr(pVBox, 0x08);
1261 seq2 = ReadSeq(pVBox, 0x02);
1262 seq4 = ReadSeq(pVBox, 0x04);
1263#else
1264 attr10 = ReadAttr(0x10);
1265 gr1 = ReadGr(0x01);
1266 gr3 = ReadGr(0x03);
1267 gr4 = ReadGr(0x04);
1268 gr5 = ReadGr(0x05);
1269 gr6 = ReadGr(0x06);
1270 gr8 = ReadGr(0x08);
1271 seq2 = ReadSeq(0x02);
1272 seq4 = ReadSeq(0x04);
1273#endif
1274
1275 /* Force into colour mode */
1276 WriteMiscOut(miscOut | 0x01);
1277
1278#ifdef XORG_7X
1279 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1280 SeqReset(pVBox, TRUE);
1281#else
1282 scrn = ReadSeq(0x01) | 0x20;
1283 SeqReset(TRUE);
1284#endif
1285 WriteSeq(0x01, scrn);
1286#ifdef XORG_7X
1287 SeqReset(pVBox, FALSE);
1288#else
1289 SeqReset(FALSE);
1290#endif
1291
1292#ifdef XORG_7X
1293 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1294#else
1295 WriteAttr(0x10, 0x01); /* graphics mode */
1296#endif
1297 if (pScrn->depth == 4) {
1298 /* GJA */
1299 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1300 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1301 WriteGr(0x01, 0x00); /* all planes come from CPU */
1302 }
1303
1304 WriteSeq(0x02, 0x04); /* write to plane 2 */
1305 WriteSeq(0x04, 0x06); /* enable plane graphics */
1306 WriteGr(0x04, 0x02); /* read plane 2 */
1307 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1308 WriteGr(0x06, 0x05); /* set graphics */
1309 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1310
1311 WriteSeq(0x02, 0x08); /* write to plane 3 */
1312 WriteSeq(0x04, 0x06); /* enable plane graphics */
1313 WriteGr(0x04, 0x03); /* read plane 3 */
1314 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1315 WriteGr(0x06, 0x05); /* set graphics */
1316 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1317
1318#ifdef XORG_7X
1319 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1320 SeqReset(pVBox, TRUE);
1321#else
1322 scrn = ReadSeq(0x01) & ~0x20;
1323 SeqReset(TRUE);
1324#endif
1325 WriteSeq(0x01, scrn);
1326#ifdef XORG_7X
1327 SeqReset(pVBox, FALSE);
1328#else
1329 SeqReset(FALSE);
1330#endif
1331
1332 /* restore the registers that were changed */
1333 WriteMiscOut(miscOut);
1334#ifdef XORG_7X
1335 WriteAttr(pVBox, 0x10, attr10);
1336#else
1337 WriteAttr(0x10, attr10);
1338#endif
1339 WriteGr(0x01, gr1);
1340 WriteGr(0x03, gr3);
1341 WriteGr(0x04, gr4);
1342 WriteGr(0x05, gr5);
1343 WriteGr(0x06, gr6);
1344 WriteGr(0x08, gr8);
1345 WriteSeq(0x02, seq2);
1346 WriteSeq(0x04, seq4);
1347}
1348
1349static Bool
1350VBOXSaveScreen(ScreenPtr pScreen, int mode)
1351{
1352 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1353#ifdef XORG_7X
1354 VBOXPtr pVBox = VBOXGetRec(pScrn);
1355#endif
1356 Bool on = xf86IsUnblank(mode);
1357
1358 if (on)
1359 SetTimeSinceLastInputEvent();
1360
1361 if (pScrn->vtSema) {
1362#ifdef XORG_7X
1363 unsigned char scrn = ReadSeq(pVBox, 0x01);
1364#else
1365 unsigned char scrn = ReadSeq(0x01);
1366#endif
1367
1368 if (on)
1369 scrn &= ~0x20;
1370 else
1371 scrn |= 0x20;
1372#ifdef XORG_7X
1373 SeqReset(pVBox, TRUE);
1374 WriteSeq(0x01, scrn);
1375 SeqReset(pVBox, FALSE);
1376#else
1377 SeqReset(TRUE);
1378 WriteSeq(0x01, scrn);
1379 SeqReset(FALSE);
1380#endif
1381 }
1382
1383 return (TRUE);
1384}
1385
1386Bool
1387VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1388{
1389 VBOXPtr pVBox;
1390
1391 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1392 return (FALSE);
1393
1394 pVBox = VBOXGetRec(pScrn);
1395
1396
1397 /* Query amount of memory to save state */
1398 if (function == MODE_QUERY ||
1399 (function == MODE_SAVE && pVBox->state == NULL))
1400 {
1401
1402 /* Make sure we save at least this information in case of failure */
1403 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1404 SaveFonts(pScrn);
1405
1406 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1407 &pVBox->stateSize,&pVBox->statePage))
1408 return FALSE;
1409 }
1410
1411 /* Save/Restore Super VGA state */
1412 if (function != MODE_QUERY) {
1413 Bool retval = TRUE;
1414
1415 if (function == MODE_RESTORE)
1416 memcpy(pVBox->state, pVBox->pstate,
1417 (unsigned) pVBox->stateSize);
1418
1419 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1420 (pointer)&pVBox->state,
1421 &pVBox->stateSize,&pVBox->statePage))
1422 && function == MODE_SAVE)
1423 {
1424 /* don't rely on the memory not being touched */
1425 if (pVBox->pstate == NULL)
1426 pVBox->pstate = xalloc(pVBox->stateSize);
1427 memcpy(pVBox->pstate, pVBox->state,
1428 (unsigned) pVBox->stateSize);
1429 }
1430
1431 if (function == MODE_RESTORE)
1432 {
1433 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1434 RestoreFonts(pScrn);
1435 }
1436
1437 if (!retval)
1438 return (FALSE);
1439
1440 }
1441
1442 return (TRUE);
1443}
1444
1445static void
1446VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1447 int flags)
1448{
1449 /* VBox is always power efficient... */
1450}
1451
1452
1453
1454
1455/***********************************************************************
1456 * DGA stuff
1457 ***********************************************************************/
1458static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1459 unsigned char **ApertureBase,
1460 int *ApertureSize, int *ApertureOffset,
1461 int *flags);
1462static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1463static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1464
1465static Bool
1466VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1467 unsigned char **ApertureBase, int *ApertureSize,
1468 int *ApertureOffset, int *flags)
1469{
1470 VBOXPtr pVBox = VBOXGetRec(pScrn);
1471
1472 *DeviceName = NULL; /* No special device */
1473 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1474 *ApertureSize = pVBox->mapSize;
1475 *ApertureOffset = pVBox->mapOff;
1476 *flags = DGA_NEED_ROOT;
1477
1478 return (TRUE);
1479}
1480
1481static Bool
1482VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1483{
1484 DisplayModePtr pMode;
1485 int scrnIdx = pScrn->pScreen->myNum;
1486 int frameX0, frameY0;
1487
1488 if (pDGAMode) {
1489 pMode = pDGAMode->mode;
1490 frameX0 = frameY0 = 0;
1491 }
1492 else {
1493 if (!(pMode = pScrn->currentMode))
1494 return (TRUE);
1495
1496 frameX0 = pScrn->frameX0;
1497 frameY0 = pScrn->frameY0;
1498 }
1499
1500 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1501 return (FALSE);
1502 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1503
1504 return (TRUE);
1505}
1506
1507static void
1508VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1509{
1510 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1511}
1512
1513static int
1514VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1515{
1516 return (0);
1517}
1518
1519static DGAFunctionRec VBOXDGAFunctions =
1520{
1521 VBOXDGAOpenFramebuffer,
1522 NULL, /* CloseFramebuffer */
1523 VBOXDGASetMode,
1524 VBOXDGASetViewport,
1525 VBOXDGAGetViewport,
1526 NULL, /* Sync */
1527 NULL, /* FillRect */
1528 NULL, /* BlitRect */
1529 NULL, /* BlitTransRect */
1530};
1531
1532static void
1533VBOXDGAAddModes(ScrnInfoPtr pScrn)
1534{
1535 VBOXPtr pVBox = VBOXGetRec(pScrn);
1536 DisplayModePtr pMode = pScrn->modes;
1537 DGAModePtr pDGAMode;
1538
1539 do {
1540 pDGAMode = xrealloc(pVBox->pDGAMode,
1541 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1542 if (!pDGAMode)
1543 break;
1544
1545 pVBox->pDGAMode = pDGAMode;
1546 pDGAMode += pVBox->nDGAMode;
1547 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1548
1549 ++pVBox->nDGAMode;
1550 pDGAMode->mode = pMode;
1551 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1552 pDGAMode->byteOrder = pScrn->imageByteOrder;
1553 pDGAMode->depth = pScrn->depth;
1554 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1555 pDGAMode->red_mask = pScrn->mask.red;
1556 pDGAMode->green_mask = pScrn->mask.green;
1557 pDGAMode->blue_mask = pScrn->mask.blue;
1558 pDGAMode->visualClass = TrueColor;
1559 pDGAMode->xViewportStep = 1;
1560 pDGAMode->yViewportStep = 1;
1561 pDGAMode->viewportWidth = pMode->HDisplay;
1562 pDGAMode->viewportHeight = pMode->VDisplay;
1563
1564 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1565 pDGAMode->imageWidth = pMode->HDisplay;
1566 pDGAMode->imageHeight = pMode->VDisplay;
1567 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1568 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1569 pDGAMode->maxViewportX = pScrn->virtualX -
1570 pDGAMode->viewportWidth;
1571 pDGAMode->maxViewportY = pScrn->virtualY -
1572 pDGAMode->viewportHeight;
1573
1574 pDGAMode->address = pVBox->base;
1575
1576 pMode = pMode->next;
1577 } while (pMode != pScrn->modes);
1578}
1579
1580static Bool
1581VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1582{
1583 VBOXPtr pVBox = VBOXGetRec(pScrn);
1584
1585 if (!pVBox->nDGAMode)
1586 VBOXDGAAddModes(pScrn);
1587
1588 return (DGAInit(pScreen, &VBOXDGAFunctions,
1589 pVBox->pDGAMode, pVBox->nDGAMode));
1590}
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