VirtualBox

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

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

*: whitespace cleanups by scm and two manually picked nits.

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