VirtualBox

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

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

Additions/x11/vboxvideo: backport various changes from vboxvideo_13 to vboxvideo_70 and fix an issue with VT switching

  • Property svn:eol-style set to native
File size: 32.8 KB
Line 
1/** @file
2 *
3 * Linux Additions X11 graphics driver
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 * --------------------------------------------------------------------
21 *
22 * This code is based on:
23 *
24 * X11 VESA driver
25 *
26 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a
29 * copy of this software and associated documentation files (the "Software"),
30 * to deal in the Software without restriction, including without limitation
31 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32 * and/or sell copies of the Software, and to permit persons to whom the
33 * Software is furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
43 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44 * SOFTWARE.
45 *
46 * Except as contained in this notice, the name of Conectiva Linux shall
47 * not be used in advertising or otherwise to promote the sale, use or other
48 * dealings in this Software without prior written authorization from
49 * Conectiva Linux.
50 *
51 * Authors: Paulo César Pereira de Andrade <[email protected]>
52 */
53
54#ifdef XORG_7X
55# include "xorg-server.h"
56# include <string.h>
57#endif
58#include "vboxvideo.h"
59#include "version-generated.h"
60#include <xf86.h>
61
62/* All drivers initialising the SW cursor need this */
63#include "mipointer.h"
64
65/* All drivers implementing backing store need this */
66#include "mibstore.h"
67
68/* Colormap handling */
69#include "micmap.h"
70#include "xf86cmap.h"
71
72/* DPMS */
73/* #define DPMS_SERVER
74#include "extensions/dpms.h" */
75
76/* VGA hardware functions for setting and restoring text mode */
77#include "vgaHW.h"
78
79/* Mandatory functions */
80
81static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
82static void VBOXIdentify(int flags);
83#ifndef PCIACCESS
84static Bool VBOXProbe(DriverPtr drv, int flags);
85#else
86static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
87 struct pci_device *dev, intptr_t match_data);
88#endif
89static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
90static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
91 char **argv);
92static Bool VBOXEnterVT(int scrnIndex, int flags);
93static void VBOXLeaveVT(int scrnIndex, int flags);
94static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
95static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
96static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
97static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
98static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
99static void VBOXFreeScreen(int scrnIndex, int flags);
100static void VBOXFreeRec(ScrnInfoPtr pScrn);
101static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
102 int flags);
103
104/* locally used functions */
105static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
106static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
107static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
108 vbeSaveRestoreFunction function);
109static bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, DisplayModePtr pMode);
110
111enum GenericTypes
112{
113 CHIP_VBOX_GENERIC
114};
115
116#ifdef PCIACCESS
117static const struct pci_id_match vbox_device_match[] = {
118 {
119 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
120 0, 0, 0
121 },
122
123 { 0, 0, 0 },
124};
125#endif
126
127/*
128 * This contains the functions needed by the server after loading the
129 * driver module. It must be supplied, and gets added the driver list by
130 * the Module Setup funtion in the dynamic case. In the static case a
131 * reference to this is compiled in, and this requires that the name of
132 * this DriverRec be an upper-case version of the driver name.
133 */
134
135#ifdef XORG_7X
136_X_EXPORT
137#endif
138DriverRec VBOXVIDEO = {
139 VBOX_VERSION,
140 VBOX_DRIVER_NAME,
141 VBOXIdentify,
142#ifdef PCIACCESS
143 NULL,
144#else
145 VBOXProbe,
146#endif
147 VBOXAvailableOptions,
148 NULL,
149 0,
150#ifdef XORG_7X
151 NULL,
152#endif
153#ifdef PCIACCESS
154 vbox_device_match,
155 VBOXPciProbe
156#endif
157};
158
159/* Supported chipsets */
160static SymTabRec VBOXChipsets[] =
161{
162 {VBOX_VESA_DEVICEID, "vbox"},
163 {-1, NULL}
164};
165
166static PciChipsets VBOXPCIchipsets[] = {
167 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
168 { -1, -1, RES_UNDEFINED },
169};
170
171typedef enum {
172 OPTION_SHADOW_FB,
173 OPTION_DFLT_REFRESH,
174 OPTION_MODESET_CLEAR_SCREEN
175} VBOXOpts;
176
177/* No options for now */
178static const OptionInfoRec VBOXOptions[] = {
179 { -1, NULL, OPTV_NONE, {0}, FALSE }
180};
181
182/*
183 * List of symbols from other modules that this module references. This
184 * list is used to tell the loader that it is OK for symbols here to be
185 * unresolved providing that it hasn't been told that they haven't been
186 * told that they are essential via a call to xf86LoaderReqSymbols() or
187 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
188 * unresolved symbols that are not required.
189 */
190static const char *fbSymbols[] = {
191 "fbPictureInit",
192 "fbScreenInit",
193 NULL
194};
195
196static const char *shadowfbSymbols[] = {
197 "ShadowFBInit2",
198 NULL
199};
200
201static const char *vbeSymbols[] = {
202 "VBEExtendedInit",
203 "VBEFindSupportedDepths",
204 "VBEGetModeInfo",
205 "VBEGetVBEInfo",
206 "VBEGetVBEMode",
207 "VBEPrintModes",
208 "VBESaveRestore",
209 "VBESetDisplayStart",
210 "VBESetGetDACPaletteFormat",
211 "VBESetGetLogicalScanlineLength",
212 "VBESetGetPaletteData",
213 "VBESetModeNames",
214 "VBESetModeParameters",
215 "VBESetVBEMode",
216 "VBEValidateModes",
217 "vbeDoEDID",
218 "vbeFree",
219 NULL
220};
221
222static const char *ramdacSymbols[] = {
223 "xf86InitCursor",
224 "xf86CreateCursorInfoRec",
225 NULL
226};
227
228static const char *vgahwSymbols[] = {
229 "vgaHWGetHWRec",
230 "vgaHWHandleColormaps",
231 "vgaHWFreeHWRec",
232 "vgaHWMapMem",
233 "vgaHWUnmapMem",
234 "vgaHWSaveFonts",
235 "vgaHWRestoreFonts",
236 "vgaHWGetIndex",
237 "vgaHWSaveScreen",
238 "vgaHWDPMSSet",
239 NULL
240};
241
242#ifdef XFree86LOADER
243/* Module loader interface */
244static MODULESETUPPROTO(vboxSetup);
245
246static XF86ModuleVersionInfo vboxVersionRec =
247{
248 VBOX_DRIVER_NAME,
249 "Sun Microsystems, Inc.",
250 MODINFOSTRING1,
251 MODINFOSTRING2,
252#ifdef XORG_7X
253 XORG_VERSION_CURRENT,
254#else
255 XF86_VERSION_CURRENT,
256#endif
257 1, /* Module major version. Xorg-specific */
258 0, /* Module minor version. Xorg-specific */
259 1, /* Module patchlevel. Xorg-specific */
260 ABI_CLASS_VIDEODRV, /* This is a video driver */
261 ABI_VIDEODRV_VERSION,
262 MOD_CLASS_VIDEODRV,
263 {0, 0, 0, 0}
264};
265
266/*
267 * This data is accessed by the loader. The name must be the module name
268 * followed by "ModuleData".
269 */
270#ifdef XORG_7X
271_X_EXPORT
272#endif
273XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
274
275static pointer
276vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
277{
278 static Bool Initialised = FALSE;
279
280 if (!Initialised)
281 {
282 Initialised = TRUE;
283#ifdef PCIACCESS
284 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
285#else
286 xf86AddDriver(&VBOXVIDEO, Module, 0);
287#endif
288#ifndef XORG_7X
289 LoaderRefSymLists(fbSymbols,
290 shadowfbSymbols,
291 vbeSymbols,
292 ramdacSymbols,
293 vgahwSymbols,
294 NULL);
295#endif
296 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
297 (void *)&VBOXVIDEO);
298 return (pointer)TRUE;
299 }
300
301 if (ErrorMajor)
302 *ErrorMajor = LDR_ONCEONLY;
303 return (NULL);
304}
305
306#endif /* XFree86Loader defined */
307
308static const OptionInfoRec *
309VBOXAvailableOptions(int chipid, int busid)
310{
311 return (VBOXOptions);
312}
313
314static void
315VBOXIdentify(int flags)
316{
317 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
318}
319
320static VBOXPtr
321VBOXGetRec(ScrnInfoPtr pScrn)
322{
323 if (!pScrn->driverPrivate)
324 {
325 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
326#if 0
327 ((VBOXPtr)pScrn->driverPrivate)->vbox_fd = -1;
328#endif
329 }
330
331 return ((VBOXPtr)pScrn->driverPrivate);
332}
333
334static void
335VBOXFreeRec(ScrnInfoPtr pScrn)
336{
337 VBOXPtr pVBox = VBOXGetRec(pScrn);
338#if 0
339 xfree(pVBox->vbeInfo);
340#endif
341 xfree(pVBox->savedPal);
342 xfree(pVBox->fonts);
343 xfree(pScrn->driverPrivate);
344 pScrn->driverPrivate = NULL;
345}
346
347/*
348 * This function is called once, at the start of the first server generation to
349 * do a minimal probe for supported hardware.
350 */
351
352#ifdef PCIACCESS
353static Bool
354VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
355 intptr_t match_data)
356{
357 ScrnInfoPtr pScrn;
358
359 TRACE_ENTRY();
360 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
361 NULL, NULL, NULL, NULL, NULL);
362 if (pScrn != NULL) {
363 VBOXPtr pVBox = VBOXGetRec(pScrn);
364
365 pScrn->driverVersion = VBOX_VERSION;
366 pScrn->driverName = VBOX_DRIVER_NAME;
367 pScrn->name = VBOX_NAME;
368 pScrn->Probe = NULL;
369 pScrn->PreInit = VBOXPreInit;
370 pScrn->ScreenInit = VBOXScreenInit;
371 pScrn->SwitchMode = VBOXSwitchMode;
372 /* pScrn->ValidMode = VBOXValidMode; */
373 pScrn->AdjustFrame = VBOXAdjustFrame;
374 pScrn->EnterVT = VBOXEnterVT;
375 pScrn->LeaveVT = VBOXLeaveVT;
376 pScrn->FreeScreen = VBOXFreeScreen;
377
378 pVBox->pciInfo = dev;
379 }
380
381 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
382 return (pScrn != NULL);
383}
384#else /* !PCIACCESS */
385static Bool
386VBOXProbe(DriverPtr drv, int flags)
387{
388 Bool foundScreen = FALSE;
389 int numDevSections, numUsed;
390 GDevPtr *devSections;
391 int *usedChips;
392 int i;
393
394 /*
395 * Find the config file Device sections that match this
396 * driver, and return if there are none.
397 */
398 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
399 &devSections)) <= 0)
400 return (FALSE);
401
402 /* PCI BUS */
403 if (xf86GetPciVideoInfo()) {
404 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
405 VBOXChipsets, VBOXPCIchipsets,
406 devSections, numDevSections,
407 drv, &usedChips);
408 if (numUsed > 0) {
409 if (flags & PROBE_DETECT)
410 foundScreen = TRUE;
411 else {
412 for (i = 0; i < numUsed; i++) {
413 ScrnInfoPtr pScrn = NULL;
414 /* Allocate a ScrnInfoRec */
415 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
416 VBOXPCIchipsets,NULL,
417 NULL,NULL,NULL,NULL))) {
418 pScrn->driverVersion = VBOX_VERSION;
419 pScrn->driverName = VBOX_DRIVER_NAME;
420 pScrn->name = VBOX_NAME;
421 pScrn->Probe = VBOXProbe;
422 pScrn->PreInit = VBOXPreInit;
423 pScrn->ScreenInit = VBOXScreenInit;
424 pScrn->SwitchMode = VBOXSwitchMode;
425 pScrn->AdjustFrame = VBOXAdjustFrame;
426 pScrn->EnterVT = VBOXEnterVT;
427 pScrn->LeaveVT = VBOXLeaveVT;
428 pScrn->FreeScreen = VBOXFreeScreen;
429 foundScreen = TRUE;
430 }
431 }
432 }
433 xfree(usedChips);
434 }
435 }
436 xfree(devSections);
437
438 return (foundScreen);
439}
440#endif /* !PCIACCESS */
441
442/**
443 * This function hooks into the chain that is called when framebuffer access
444 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
445 * In other words, it observes when the server wishes access to the
446 * framebuffer to be enabled and when it should be disabled. We need to know
447 * this because we disable access ourselves during mode switches (presumably
448 * the server should do this but it doesn't) and want to know whether to
449 * restore it or not afterwards.
450 */
451static void
452vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
453{
454 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
455 VBOXPtr pVBox = VBOXGetRec(pScrn);
456
457 pVBox->accessEnabled = enable;
458 pVBox->EnableDisableFBAccess(scrnIndex, enable);
459}
460
461/*
462 * QUOTE from the XFree86 DESIGN document:
463 *
464 * The purpose of this function is to find out all the information
465 * required to determine if the configuration is usable, and to initialise
466 * those parts of the ScrnInfoRec that can be set once at the beginning of
467 * the first server generation.
468 *
469 * (...)
470 *
471 * This includes probing for video memory, clocks, ramdac, and all other
472 * HW info that is needed. It includes determining the depth/bpp/visual
473 * and related info. It includes validating and determining the set of
474 * video modes that will be used (and anything that is required to
475 * determine that).
476 *
477 * This information should be determined in the least intrusive way
478 * possible. The state of the HW must remain unchanged by this function.
479 * Although video memory (including MMIO) may be mapped within this
480 * function, it must be unmapped before returning.
481 *
482 * END QUOTE
483 */
484
485static Bool
486VBOXPreInit(ScrnInfoPtr pScrn, int flags)
487{
488 VBOXPtr pVBox;
489 Gamma gzeros = {0.0, 0.0, 0.0};
490 rgb rzeros = {0, 0, 0};
491 int i;
492 DisplayModePtr pMode;
493 enum { MODE_MIN_SIZE = 64 };
494
495 TRACE_ENTRY();
496 /* Are we really starting the server, or is this just a dummy run? */
497 if (flags & PROBE_DETECT)
498 return (FALSE);
499
500 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
501 "VirtualBox guest additions video driver version "
502 VBOX_VERSION_STRING "\n");
503
504 /* Get our private data from the ScrnInfoRec structure. */
505 pVBox = VBOXGetRec(pScrn);
506
507 /* Initialise the guest library */
508 vbox_init(pScrn->scrnIndex, pVBox);
509
510 /* Entity information seems to mean bus information. */
511 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
512
513 /* The ramdac module is needed for the hardware cursor. */
514 if (!xf86LoadSubModule(pScrn, "ramdac"))
515 return FALSE;
516
517 /* We need the vbe module because we use VBE code to save and restore
518 text mode, in order to keep our code simple. */
519 if (!xf86LoadSubModule(pScrn, "vbe"))
520 return (FALSE);
521
522 /* The framebuffer module. */
523 if (xf86LoadSubModule(pScrn, "fb") == NULL)
524 return (FALSE);
525
526 if (!xf86LoadSubModule(pScrn, "shadowfb"))
527 return FALSE;
528
529 if (!xf86LoadSubModule(pScrn, "vgahw"))
530 return FALSE;
531
532#ifndef PCIACCESS
533 if (pVBox->pEnt->location.type != BUS_PCI)
534 return FALSE;
535
536 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
537 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
538 pVBox->pciInfo->device,
539 pVBox->pciInfo->func);
540#endif
541
542 /* Set up our ScrnInfoRec structure to describe our virtual
543 capabilities to X. */
544
545 pScrn->rgbBits = 8;
546
547 /* Let's create a nice, capable virtual monitor. */
548 pScrn->monitor = pScrn->confScreen->monitor;
549 pScrn->monitor->DDC = NULL;
550 pScrn->monitor->nHsync = 1;
551 pScrn->monitor->hsync[0].lo = 1;
552 pScrn->monitor->hsync[0].hi = 10000;
553 pScrn->monitor->nVrefresh = 1;
554 pScrn->monitor->vrefresh[0].lo = 1;
555 pScrn->monitor->vrefresh[0].hi = 100;
556
557 pScrn->chipset = "vbox";
558 pScrn->progClock = TRUE;
559
560 /* Determine the size of the VBox video RAM from PCI data*/
561#if 0
562 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
563#endif
564 /* Using the PCI information caused problems with non-powers-of-two
565 sized video RAM configurations */
566 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
567
568 /* Set up clock information that will support all modes we need. */
569 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
570 pScrn->clockRanges->minClock = 1000;
571 pScrn->clockRanges->maxClock = 1000000000;
572 pScrn->clockRanges->clockIndex = -1;
573 pScrn->clockRanges->ClockMulFactor = 1;
574 pScrn->clockRanges->ClockDivFactor = 1;
575
576 /* Determine the preferred size and colour depth and setup video modes */
577 {
578 uint32_t cx = 0, cy = 0, cBits = 0;
579
580 vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
581 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
582 if (cBits != 16)
583 cBits = 24;
584 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
585 return FALSE;
586 vboxAddModes(pScrn, cx, cy);
587 }
588 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
589 {
590 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
591 "The VBox additions only support 16 and 32bpp graphics modes\n");
592 return FALSE;
593 }
594 xf86PrintDepthBpp(pScrn);
595
596 /* Colour weight - we always call this, since we are always in
597 truecolour. */
598 if (!xf86SetWeight(pScrn, rzeros, rzeros))
599 return (FALSE);
600
601 /* visual init */
602 if (!xf86SetDefaultVisual(pScrn, -1))
603 return (FALSE);
604
605 xf86SetGamma(pScrn, gzeros);
606
607 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
608 * already know what we like and what we don't. */
609
610 pScrn->currentMode = pScrn->modes;
611
612 /* Set the right virtual resolution. */
613 pScrn->virtualX = pScrn->currentMode->HDisplay;
614 pScrn->virtualY = pScrn->currentMode->VDisplay;
615
616 pScrn->displayWidth = pScrn->virtualX;
617
618 xf86PrintModes(pScrn);
619
620 /* Set the DPI. Perhaps we should read this from the host? */
621 xf86SetDpi(pScrn, 96, 96);
622
623 /* options */
624 xf86CollectOptions(pScrn, NULL);
625 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
626 return FALSE;
627 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
628 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
629
630 /* Framebuffer-related setup */
631 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
632
633 /* VGA hardware initialisation */
634 if (!vgaHWGetHWRec(pScrn))
635 return FALSE;
636
637 TRACE_EXIT();
638 return (TRUE);
639}
640
641/*
642 * QUOTE from the XFree86 DESIGN document:
643 *
644 * This is called at the start of each server generation.
645 *
646 * (...)
647 *
648 * Decide which operations need to be placed under resource access
649 * control. (...) Map any video memory or other memory regions. (...)
650 * Save the video card state. (...) Initialise the initial video
651 * mode.
652 *
653 * End QUOTE.
654 */
655static Bool
656VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
657{
658 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
659 VBOXPtr pVBox = VBOXGetRec(pScrn);
660 VisualPtr visual;
661 unsigned flags;
662
663 TRACE_ENTRY();
664 /* We make use of the X11 VBE code to save and restore text mode, in
665 order to keep our code simple. */
666 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
667 SET_BIOS_SCRATCH
668 | RESTORE_BIOS_SCRATCH)) == NULL)
669 return (FALSE);
670
671 if (pVBox->mapPhys == 0) {
672#ifdef PCIACCESS
673 pVBox->mapPhys = pVBox->pciInfo->regions[0].base_addr;
674#else
675 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
676#endif
677/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
678 /* Using the PCI information caused problems with
679 non-powers-of-two sized video RAM configurations */
680 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
681 pVBox->mapOff = 0;
682 }
683
684 if (!VBOXMapVidMem(pScrn))
685 return (FALSE);
686
687 /* save current video state */
688 VBOXSaveRestore(pScrn, MODE_SAVE);
689 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
690 NULL, FALSE, FALSE);
691
692 /* set the viewport */
693 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
694
695 /* Blank the screen for aesthetic reasons. */
696 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
697
698 /* mi layer - reset the visual list (?)*/
699 miClearVisualTypes();
700 if (!xf86SetDefaultVisual(pScrn, -1))
701 return (FALSE);
702 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
703 pScrn->rgbBits, TrueColor))
704 return (FALSE);
705 if (!miSetPixmapDepths())
706 return (FALSE);
707
708 /* I checked in the sources, and XFree86 4.2 does seem to support
709 this function for 32bpp. */
710 if (!fbScreenInit(pScreen, pVBox->base,
711 pScrn->virtualX, pScrn->virtualY,
712 pScrn->xDpi, pScrn->yDpi,
713 pScrn->displayWidth, pScrn->bitsPerPixel))
714 return (FALSE);
715
716 /* Fixup RGB ordering */
717 visual = pScreen->visuals + pScreen->numVisuals;
718 while (--visual >= pScreen->visuals) {
719 if ((visual->class | DynamicClass) == DirectColor) {
720 visual->offsetRed = pScrn->offset.red;
721 visual->offsetGreen = pScrn->offset.green;
722 visual->offsetBlue = pScrn->offset.blue;
723 visual->redMask = pScrn->mask.red;
724 visual->greenMask = pScrn->mask.green;
725 visual->blueMask = pScrn->mask.blue;
726 }
727 }
728
729 /* must be after RGB ordering fixed */
730 fbPictureInit(pScreen, 0, 0);
731
732 xf86SetBlackWhitePixels(pScreen);
733 miInitializeBackingStore(pScreen);
734 xf86SetBackingStore(pScreen);
735
736 /* We need to keep track of whether we are currently switched to a virtual
737 * terminal to know whether a mode set operation is currently safe to do.
738 */
739 pVBox->vtSwitch = FALSE;
740 /* software cursor */
741 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
742
743 /* colourmap code - apparently, we need this even in Truecolour */
744 if (!miCreateDefColormap(pScreen))
745 return (FALSE);
746
747 flags = CMAP_RELOAD_ON_MODE_SWITCH;
748
749 if(!vgaHWHandleColormaps(pScreen))
750 return (FALSE);
751
752 /* Hook our observer function ito the chain which is called when
753 * framebuffer access is enabled or disabled in the server, and
754 * assume an initial state of enabled. */
755 pVBox->accessEnabled = TRUE;
756 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
757 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
758
759 pVBox->CloseScreen = pScreen->CloseScreen;
760 pScreen->CloseScreen = VBOXCloseScreen;
761 pScreen->SaveScreen = VBOXSaveScreen;
762
763 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
764
765 /* Report any unused options (only for the first generation) */
766 if (serverGeneration == 1)
767 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
768
769 /* set first video mode */
770 if (!VBOXSetMode(pScrn, pScrn->currentMode))
771 return FALSE;
772 /* And make sure that a non-current dynamic mode is at the front of the
773 * list */
774 vboxWriteHostModes(pScrn, pScrn->currentMode);
775
776 if (vbox_open (pScrn, pScreen, pVBox)) {
777 if (vbox_cursor_init(pScreen) != TRUE)
778 xf86DrvMsg(scrnIndex, X_ERROR,
779 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
780 if (vboxEnableVbva(pScrn) == TRUE)
781 xf86DrvMsg(scrnIndex, X_INFO,
782 "The VBox video extensions are now enabled.\n");
783 vboxEnableGraphicsCap(pVBox);
784 }
785 TRACE_EXIT();
786 return (TRUE);
787}
788
789static Bool
790VBOXEnterVT(int scrnIndex, int flags)
791{
792 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
793 VBOXPtr pVBox = VBOXGetRec(pScrn);
794
795 TRACE_ENTRY();
796 pVBox->vtSwitch = FALSE;
797 if (!VBOXSetMode(pScrn, pScrn->currentMode))
798 return FALSE;
799 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
800 if (pVBox->useVbva == TRUE)
801 vboxEnableVbva(pScrn);
802 return TRUE;
803}
804
805static void
806VBOXLeaveVT(int scrnIndex, int flags)
807{
808 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
809 VBOXPtr pVBox = VBOXGetRec(pScrn);
810
811 TRACE_ENTRY();
812 VBOXSaveRestore(pScrn, MODE_RESTORE);
813 if (pVBox->useVbva == TRUE)
814 vboxDisableVbva(pScrn);
815 vboxDisableGraphicsCap(pVBox);
816 pVBox->vtSwitch = TRUE;
817}
818
819static Bool
820VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
821{
822 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
823 VBOXPtr pVBox = VBOXGetRec(pScrn);
824
825 if (pVBox->useVbva == TRUE)
826 vboxDisableVbva(pScrn);
827 vboxDisableGraphicsCap(pVBox);
828 if (pScrn->vtSema) {
829 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
830 if (pVBox->savedPal)
831 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
832 pVBox->savedPal, FALSE, TRUE);
833 VBOXUnmapVidMem(pScrn);
834 }
835 pScrn->vtSema = FALSE;
836
837 /* Destroy the VGA hardware record */
838 vgaHWFreeHWRec(pScrn);
839
840 pScreen->CloseScreen = pVBox->CloseScreen;
841 return pScreen->CloseScreen(scrnIndex, pScreen);
842}
843
844static Bool
845VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
846{
847 ScrnInfoPtr pScrn;
848 VBOXPtr pVBox;
849 Bool rc = TRUE;
850
851 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
852 pVBox = VBOXGetRec(pScrn);
853 if (pVBox->useVbva)
854 if (!vboxDisableVbva(pScrn)) /* This would be bad. */
855 rc = FALSE;
856 /* We want to disable access to the framebuffer before switching mode.
857 * After doing the switch, we allow access if it was allowed before. */
858 if (pVBox->accessEnabled)
859 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
860 if (rc && !VBOXSetMode(pScrn, pMode))
861 rc = FALSE;
862 if (rc && !VBOXAdjustScreenPixmap(pScrn, pMode))
863 rc = FALSE;
864 if (rc && !vboxGuestIsSeamless(pScrn))
865 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
866 pScrn->bitsPerPixel);
867 if (rc)
868 {
869 vboxWriteHostModes(pScrn, pMode);
870 xf86PrintModes(pScrn);
871 }
872 if (pVBox->accessEnabled)
873 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
874 if (pVBox->useVbva)
875 if (!vboxEnableVbva(pScrn)) /* Bad but not fatal */
876 pVBox->useVbva = FALSE;
877 return rc;
878}
879
880/* Set a graphics mode */
881static Bool
882VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
883{
884 TRACE_ENTRY();
885 int bpp = pScrn->depth == 24 ? 32 : 16;
886 VBOXPtr pVBox = VBOXGetRec(pScrn);
887
888 /* Don't fiddle with the hardware if we are switched
889 * to a virtual terminal. */
890 if (pVBox->vtSwitch == TRUE)
891 return TRUE;
892 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
893 >= pScrn->videoRam * 1024)
894 {
895 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
896 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
897 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
898 return FALSE;
899 }
900
901 pScrn->vtSema = TRUE;
902 /* Disable linear framebuffer mode before making changes to the resolution. */
903 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
904 outw(VBE_DISPI_IOPORT_DATA,
905 VBE_DISPI_DISABLED);
906 /* Unlike the resolution, the depth is fixed for a given screen
907 for the lifetime of the X session. */
908 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
909 outw(VBE_DISPI_IOPORT_DATA, bpp);
910 /* HDisplay and VDisplay are actually monitor information about
911 the display part of the scanlines. */
912 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
913 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
914 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
915 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
916 /* Enable linear framebuffer mode. */
917 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
918 outw(VBE_DISPI_IOPORT_DATA,
919 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
920 /* Set the virtual resolution. We are still using VESA to control
921 the virtual offset. */
922 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
923 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
924 pVBox->cLastWidth = pMode->HDisplay;
925 pVBox->cLastHeight = pMode->VDisplay;
926 vboxEnableGraphicsCap(pVBox);
927 TRACE_EXIT();
928 return (TRUE);
929}
930
931static bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, DisplayModePtr pMode)
932{
933 ScreenPtr pScreen = pScrn->pScreen;
934 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
935 VBOXPtr pVBox = VBOXGetRec(pScrn);
936 int bpp = pScrn->depth == 24 ? 32 : 16;
937 if (!pPixmap) {
938 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
939 "Failed to get the screen pixmap.\n");
940 return FALSE;
941 }
942 pScreen->ModifyPixmapHeader(pPixmap, pMode->HDisplay, pMode->VDisplay,
943 pScrn->depth, bpp, pMode->HDisplay * bpp / 8,
944 pVBox->base);
945 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
946 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
947 return TRUE;
948}
949
950static void
951VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
952{
953 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
954 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
955
956 /* Don't fiddle with the hardware if we are switched
957 * to a virtual terminal. */
958 if (pVBox->vtSwitch == TRUE)
959 return;
960 pVBox->viewportX = x;
961 pVBox->viewportY = y;
962 /* If VBVA is enabled the graphics card will not notice the change. */
963 if (pVBox->useVbva == TRUE)
964 vboxDisableVbva(pScrn);
965 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
966 if (pVBox->useVbva == TRUE)
967 vboxEnableVbva(pScrn);
968}
969
970static void
971VBOXFreeScreen(int scrnIndex, int flags)
972{
973 VBOXFreeRec(xf86Screens[scrnIndex]);
974}
975
976static Bool
977VBOXMapVidMem(ScrnInfoPtr pScrn)
978{
979 VBOXPtr pVBox = VBOXGetRec(pScrn);
980
981 if (pVBox->base != NULL)
982 return (TRUE);
983
984 pScrn->memPhysBase = pVBox->mapPhys;
985 pScrn->fbOffset = pVBox->mapOff;
986
987#ifdef PCIACCESS
988 (void) pci_device_map_range(pVBox->pciInfo,
989 pScrn->memPhysBase,
990 pVBox->mapSize,
991 PCI_DEV_MAP_FLAG_WRITABLE,
992 & pVBox->base);
993#else
994 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
995 VIDMEM_FRAMEBUFFER,
996 pVBox->pciTag, pVBox->mapPhys,
997 (unsigned) pVBox->mapSize);
998#endif
999 if (pVBox->base)
1000 {
1001 /* We need this for saving/restoring textmode */
1002 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1003 return vgaHWMapMem(pScrn);
1004 }
1005 else
1006 return FALSE;
1007}
1008
1009static void
1010VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1011{
1012 VBOXPtr pVBox = VBOXGetRec(pScrn);
1013
1014 if (pVBox->base == NULL)
1015 return;
1016
1017#ifdef PCIACCESS
1018 (void) pci_device_unmap_range(pVBox->pciInfo,
1019 pVBox->base,
1020 pVBox->mapSize);
1021#else
1022 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1023 (unsigned) pVBox->mapSize);
1024#endif
1025 vgaHWUnmapMem(pScrn);
1026 pVBox->base = NULL;
1027}
1028
1029static Bool
1030VBOXSaveScreen(ScreenPtr pScreen, int mode)
1031{
1032 return vgaHWSaveScreen(pScreen, mode);
1033}
1034
1035Bool
1036VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1037{
1038 VBOXPtr pVBox;
1039
1040 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1041 return (FALSE);
1042
1043 pVBox = VBOXGetRec(pScrn);
1044
1045 /* Query amount of memory to save state */
1046 if (function == MODE_QUERY ||
1047 (function == MODE_SAVE && pVBox->state == NULL))
1048 {
1049 /* Make sure we save at least this information in case of failure */
1050 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1051 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1052
1053 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1054 &pVBox->stateSize,&pVBox->statePage))
1055 return FALSE;
1056 }
1057
1058 /* Save/Restore Super VGA state */
1059 if (function != MODE_QUERY) {
1060 Bool retval = TRUE;
1061
1062 if (function == MODE_RESTORE)
1063 memcpy(pVBox->state, pVBox->pstate,
1064 (unsigned) pVBox->stateSize);
1065
1066 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1067 (pointer)&pVBox->state,
1068 &pVBox->stateSize,&pVBox->statePage))
1069 && function == MODE_SAVE)
1070 {
1071 /* don't rely on the memory not being touched */
1072 if (pVBox->pstate == NULL)
1073 pVBox->pstate = xalloc(pVBox->stateSize);
1074 memcpy(pVBox->pstate, pVBox->state,
1075 (unsigned) pVBox->stateSize);
1076 }
1077
1078 if (function == MODE_RESTORE)
1079 {
1080 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1081 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1082 }
1083
1084 if (!retval)
1085 return (FALSE);
1086
1087 }
1088
1089 return (TRUE);
1090}
1091
1092static void
1093VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1094 int flags)
1095{
1096 vgaHWDPMSSet(pScrn, mode, flags);
1097}
Note: See TracBrowser for help on using the repository browser.

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