VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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