VirtualBox

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

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

Additions/x11/vboxvideo: add DRI bits to vboxvideo_70

  • Property svn:eol-style set to native
File size: 33.5 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#ifdef VBOX_DRI
530 /* Load the dri module. */
531 if (!xf86LoadSubModule(pScrn, "dri"))
532 return FALSE;
533#endif
534
535#ifndef PCIACCESS
536 if (pVBox->pEnt->location.type != BUS_PCI)
537 return FALSE;
538
539 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
540 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
541 pVBox->pciInfo->device,
542 pVBox->pciInfo->func);
543#endif
544
545 /* Set up our ScrnInfoRec structure to describe our virtual
546 capabilities to X. */
547
548 pScrn->rgbBits = 8;
549
550 /* Let's create a nice, capable virtual monitor. */
551 pScrn->monitor = pScrn->confScreen->monitor;
552 pScrn->monitor->DDC = NULL;
553 pScrn->monitor->nHsync = 1;
554 pScrn->monitor->hsync[0].lo = 1;
555 pScrn->monitor->hsync[0].hi = 10000;
556 pScrn->monitor->nVrefresh = 1;
557 pScrn->monitor->vrefresh[0].lo = 1;
558 pScrn->monitor->vrefresh[0].hi = 100;
559
560 pScrn->chipset = "vbox";
561 pScrn->progClock = TRUE;
562
563 /* Determine the size of the VBox video RAM from PCI data*/
564#if 0
565 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
566#endif
567 /* Using the PCI information caused problems with non-powers-of-two
568 sized video RAM configurations */
569 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
570
571 /* Set up clock information that will support all modes we need. */
572 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
573 pScrn->clockRanges->minClock = 1000;
574 pScrn->clockRanges->maxClock = 1000000000;
575 pScrn->clockRanges->clockIndex = -1;
576 pScrn->clockRanges->ClockMulFactor = 1;
577 pScrn->clockRanges->ClockDivFactor = 1;
578
579 /* Determine the preferred size and colour depth and setup video modes */
580 {
581 uint32_t cx = 0, cy = 0, cBits = 0;
582
583 vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
584 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
585 if (cBits != 16)
586 cBits = 24;
587 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
588 return FALSE;
589 vboxAddModes(pScrn, cx, cy);
590 }
591 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
592 {
593 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
594 "The VBox additions only support 16 and 32bpp graphics modes\n");
595 return FALSE;
596 }
597 xf86PrintDepthBpp(pScrn);
598
599 /* Colour weight - we always call this, since we are always in
600 truecolour. */
601 if (!xf86SetWeight(pScrn, rzeros, rzeros))
602 return (FALSE);
603
604 /* visual init */
605 if (!xf86SetDefaultVisual(pScrn, -1))
606 return (FALSE);
607
608 xf86SetGamma(pScrn, gzeros);
609
610 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
611 * already know what we like and what we don't. */
612
613 pScrn->currentMode = pScrn->modes;
614
615 /* Set the right virtual resolution. */
616 pScrn->virtualX = pScrn->currentMode->HDisplay;
617 pScrn->virtualY = pScrn->currentMode->VDisplay;
618
619 pScrn->displayWidth = pScrn->virtualX;
620
621 xf86PrintModes(pScrn);
622
623 /* Set the DPI. Perhaps we should read this from the host? */
624 xf86SetDpi(pScrn, 96, 96);
625
626 /* options */
627 xf86CollectOptions(pScrn, NULL);
628 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
629 return FALSE;
630 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
631 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
632
633 /* Framebuffer-related setup */
634 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
635
636 /* VGA hardware initialisation */
637 if (!vgaHWGetHWRec(pScrn))
638 return FALSE;
639
640 TRACE_EXIT();
641 return (TRUE);
642}
643
644/*
645 * QUOTE from the XFree86 DESIGN document:
646 *
647 * This is called at the start of each server generation.
648 *
649 * (...)
650 *
651 * Decide which operations need to be placed under resource access
652 * control. (...) Map any video memory or other memory regions. (...)
653 * Save the video card state. (...) Initialise the initial video
654 * mode.
655 *
656 * End QUOTE.
657 */
658static Bool
659VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
660{
661 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
662 VBOXPtr pVBox = VBOXGetRec(pScrn);
663 VisualPtr visual;
664 unsigned flags;
665
666 TRACE_ENTRY();
667 /* We make use of the X11 VBE code to save and restore text mode, in
668 order to keep our code simple. */
669 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
670 SET_BIOS_SCRATCH
671 | RESTORE_BIOS_SCRATCH)) == NULL)
672 return (FALSE);
673
674 if (pVBox->mapPhys == 0) {
675#ifdef PCIACCESS
676 pVBox->mapPhys = pVBox->pciInfo->regions[0].base_addr;
677#else
678 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
679#endif
680/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
681 /* Using the PCI information caused problems with
682 non-powers-of-two sized video RAM configurations */
683 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
684 pVBox->mapOff = 0;
685 }
686
687 if (!VBOXMapVidMem(pScrn))
688 return (FALSE);
689
690 /* save current video state */
691 VBOXSaveRestore(pScrn, MODE_SAVE);
692 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
693 NULL, FALSE, FALSE);
694
695 /* set the viewport */
696 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
697
698 /* Blank the screen for aesthetic reasons. */
699 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
700
701 /* mi layer - reset the visual list (?)*/
702 miClearVisualTypes();
703 if (!xf86SetDefaultVisual(pScrn, -1))
704 return (FALSE);
705 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
706 pScrn->rgbBits, TrueColor))
707 return (FALSE);
708 if (!miSetPixmapDepths())
709 return (FALSE);
710
711 /* Needed before we initialise DRI. */
712 pScrn->virtualX = (pScrn->virtualX + 7) & ~7;
713 pScrn->displayWidth = pScrn->virtualX;
714
715#ifdef VBOX_DRI
716 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
717#endif
718
719 /* I checked in the sources, and XFree86 4.2 does seem to support
720 this function for 32bpp. */
721 if (!fbScreenInit(pScreen, pVBox->base,
722 pScrn->virtualX, pScrn->virtualY,
723 pScrn->xDpi, pScrn->yDpi,
724 pScrn->displayWidth, pScrn->bitsPerPixel))
725 return (FALSE);
726
727 /* Fixup RGB ordering */
728 visual = pScreen->visuals + pScreen->numVisuals;
729 while (--visual >= pScreen->visuals) {
730 if ((visual->class | DynamicClass) == DirectColor) {
731 visual->offsetRed = pScrn->offset.red;
732 visual->offsetGreen = pScrn->offset.green;
733 visual->offsetBlue = pScrn->offset.blue;
734 visual->redMask = pScrn->mask.red;
735 visual->greenMask = pScrn->mask.green;
736 visual->blueMask = pScrn->mask.blue;
737 }
738 }
739
740 /* must be after RGB ordering fixed */
741 fbPictureInit(pScreen, 0, 0);
742
743 xf86SetBlackWhitePixels(pScreen);
744 miInitializeBackingStore(pScreen);
745 xf86SetBackingStore(pScreen);
746
747 /* We need to keep track of whether we are currently switched to a virtual
748 * terminal to know whether a mode set operation is currently safe to do.
749 */
750 pVBox->vtSwitch = FALSE;
751 /* software cursor */
752 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
753
754 /* colourmap code - apparently, we need this even in Truecolour */
755 if (!miCreateDefColormap(pScreen))
756 return (FALSE);
757
758 flags = CMAP_RELOAD_ON_MODE_SWITCH;
759
760 if(!vgaHWHandleColormaps(pScreen))
761 return (FALSE);
762
763 /* Hook our observer function ito the chain which is called when
764 * framebuffer access is enabled or disabled in the server, and
765 * assume an initial state of enabled. */
766 pVBox->accessEnabled = TRUE;
767 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
768 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
769
770 pVBox->CloseScreen = pScreen->CloseScreen;
771 pScreen->CloseScreen = VBOXCloseScreen;
772 pScreen->SaveScreen = VBOXSaveScreen;
773
774 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
775
776 /* Report any unused options (only for the first generation) */
777 if (serverGeneration == 1)
778 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
779
780 /* set first video mode */
781 if (!VBOXSetMode(pScrn, pScrn->currentMode))
782 return FALSE;
783 /* And make sure that a non-current dynamic mode is at the front of the
784 * list */
785 vboxWriteHostModes(pScrn, pScrn->currentMode);
786
787 if (vbox_open (pScrn, pScreen, pVBox)) {
788 if (vbox_cursor_init(pScreen) != TRUE)
789 xf86DrvMsg(scrnIndex, X_ERROR,
790 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
791 if (vboxEnableVbva(pScrn) == TRUE)
792 xf86DrvMsg(scrnIndex, X_INFO,
793 "The VBox video extensions are now enabled.\n");
794 vboxEnableGraphicsCap(pVBox);
795 }
796
797#ifdef VBOX_DRI
798 if (pVBox->useDRI)
799 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
800#endif
801 TRACE_EXIT();
802 return (TRUE);
803}
804
805static Bool
806VBOXEnterVT(int scrnIndex, int flags)
807{
808 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
809 VBOXPtr pVBox = VBOXGetRec(pScrn);
810
811 TRACE_ENTRY();
812 pVBox->vtSwitch = FALSE;
813#ifdef VBOX_DRI
814 if (pVBox->useDRI)
815 DRIUnlock(screenInfo.screens[scrnIndex]);
816#endif
817 if (!VBOXSetMode(pScrn, pScrn->currentMode))
818 return FALSE;
819 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
820 if (pVBox->useVbva == TRUE)
821 vboxEnableVbva(pScrn);
822 return TRUE;
823}
824
825static void
826VBOXLeaveVT(int scrnIndex, int flags)
827{
828 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
829 VBOXPtr pVBox = VBOXGetRec(pScrn);
830
831 TRACE_ENTRY();
832 VBOXSaveRestore(pScrn, MODE_RESTORE);
833 if (pVBox->useVbva == TRUE)
834 vboxDisableVbva(pScrn);
835 vboxDisableGraphicsCap(pVBox);
836 pVBox->vtSwitch = TRUE;
837#ifdef VBOX_DRI
838 if (pVBox->useDRI)
839 DRILock(screenInfo.screens[scrnIndex], 0);
840#endif
841}
842
843static Bool
844VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
845{
846 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
847 VBOXPtr pVBox = VBOXGetRec(pScrn);
848
849#ifdef VBOX_DRI
850 if (pVBox->useDRI)
851 VBOXDRICloseScreen(pScreen, pVBox);
852 pVBox->useDRI = false;
853#endif
854
855 if (pVBox->useVbva == TRUE)
856 vboxDisableVbva(pScrn);
857 vboxDisableGraphicsCap(pVBox);
858 if (pScrn->vtSema) {
859 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
860 if (pVBox->savedPal)
861 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
862 pVBox->savedPal, FALSE, TRUE);
863 VBOXUnmapVidMem(pScrn);
864 }
865 pScrn->vtSema = FALSE;
866
867 /* Destroy the VGA hardware record */
868 vgaHWFreeHWRec(pScrn);
869
870 pScreen->CloseScreen = pVBox->CloseScreen;
871 return pScreen->CloseScreen(scrnIndex, pScreen);
872}
873
874static Bool
875VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
876{
877 ScrnInfoPtr pScrn;
878 VBOXPtr pVBox;
879 Bool rc = TRUE;
880
881 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
882 pVBox = VBOXGetRec(pScrn);
883 if (pVBox->useVbva)
884 if (!vboxDisableVbva(pScrn)) /* This would be bad. */
885 rc = FALSE;
886 /* We want to disable access to the framebuffer before switching mode.
887 * After doing the switch, we allow access if it was allowed before. */
888 if (pVBox->accessEnabled)
889 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
890 if (rc && !VBOXSetMode(pScrn, pMode))
891 rc = FALSE;
892 if (rc && !VBOXAdjustScreenPixmap(pScrn, pMode))
893 rc = FALSE;
894 if (rc && !vboxGuestIsSeamless(pScrn))
895 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
896 pScrn->bitsPerPixel);
897 if (rc)
898 {
899 vboxWriteHostModes(pScrn, pMode);
900 xf86PrintModes(pScrn);
901 }
902 if (pVBox->accessEnabled)
903 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
904 if (pVBox->useVbva)
905 if (!vboxEnableVbva(pScrn)) /* Bad but not fatal */
906 pVBox->useVbva = FALSE;
907 return rc;
908}
909
910/* Set a graphics mode */
911static Bool
912VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
913{
914 TRACE_ENTRY();
915 int bpp = pScrn->depth == 24 ? 32 : 16;
916 VBOXPtr pVBox = VBOXGetRec(pScrn);
917
918 /* Don't fiddle with the hardware if we are switched
919 * to a virtual terminal. */
920 if (pVBox->vtSwitch == TRUE)
921 return TRUE;
922 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
923 >= pScrn->videoRam * 1024)
924 {
925 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
926 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
927 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
928 return FALSE;
929 }
930
931 pScrn->vtSema = TRUE;
932 /* Disable linear framebuffer mode before making changes to the resolution. */
933 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
934 outw(VBE_DISPI_IOPORT_DATA,
935 VBE_DISPI_DISABLED);
936 /* Unlike the resolution, the depth is fixed for a given screen
937 for the lifetime of the X session. */
938 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
939 outw(VBE_DISPI_IOPORT_DATA, bpp);
940 /* HDisplay and VDisplay are actually monitor information about
941 the display part of the scanlines. */
942 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
943 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
944 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
945 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
946 /* Enable linear framebuffer mode. */
947 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
948 outw(VBE_DISPI_IOPORT_DATA,
949 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
950 /* Set the virtual resolution. We are still using VESA to control
951 the virtual offset. */
952 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
953 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
954 pVBox->cLastWidth = pMode->HDisplay;
955 pVBox->cLastHeight = pMode->VDisplay;
956 vboxEnableGraphicsCap(pVBox);
957 TRACE_EXIT();
958 return (TRUE);
959}
960
961static bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, DisplayModePtr pMode)
962{
963 ScreenPtr pScreen = pScrn->pScreen;
964 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
965 VBOXPtr pVBox = VBOXGetRec(pScrn);
966 int bpp = pScrn->depth == 24 ? 32 : 16;
967 if (!pPixmap) {
968 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
969 "Failed to get the screen pixmap.\n");
970 return FALSE;
971 }
972 pScreen->ModifyPixmapHeader(pPixmap, pMode->HDisplay, pMode->VDisplay,
973 pScrn->depth, bpp, pMode->HDisplay * bpp / 8,
974 pVBox->base);
975#ifdef VBOX_DRI
976 if (pVBox->useDRI)
977 VBOXDRIUpdateStride(pScrn, pVBox);
978#endif
979 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
980 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
981 return TRUE;
982}
983
984static void
985VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
986{
987 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
988 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
989
990 /* Don't fiddle with the hardware if we are switched
991 * to a virtual terminal. */
992 if (pVBox->vtSwitch == TRUE)
993 return;
994 pVBox->viewportX = x;
995 pVBox->viewportY = y;
996 /* If VBVA is enabled the graphics card will not notice the change. */
997 if (pVBox->useVbva == TRUE)
998 vboxDisableVbva(pScrn);
999 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
1000 if (pVBox->useVbva == TRUE)
1001 vboxEnableVbva(pScrn);
1002}
1003
1004static void
1005VBOXFreeScreen(int scrnIndex, int flags)
1006{
1007 VBOXFreeRec(xf86Screens[scrnIndex]);
1008}
1009
1010static Bool
1011VBOXMapVidMem(ScrnInfoPtr pScrn)
1012{
1013 VBOXPtr pVBox = VBOXGetRec(pScrn);
1014
1015 if (pVBox->base != NULL)
1016 return (TRUE);
1017
1018 pScrn->memPhysBase = pVBox->mapPhys;
1019 pScrn->fbOffset = pVBox->mapOff;
1020
1021#ifdef PCIACCESS
1022 (void) pci_device_map_range(pVBox->pciInfo,
1023 pScrn->memPhysBase,
1024 pVBox->mapSize,
1025 PCI_DEV_MAP_FLAG_WRITABLE,
1026 & pVBox->base);
1027#else
1028 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1029 VIDMEM_FRAMEBUFFER,
1030 pVBox->pciTag, pVBox->mapPhys,
1031 (unsigned) pVBox->mapSize);
1032#endif
1033 if (pVBox->base)
1034 {
1035 /* We need this for saving/restoring textmode */
1036 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1037 return vgaHWMapMem(pScrn);
1038 }
1039 else
1040 return FALSE;
1041}
1042
1043static void
1044VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1045{
1046 VBOXPtr pVBox = VBOXGetRec(pScrn);
1047
1048 if (pVBox->base == NULL)
1049 return;
1050
1051#ifdef PCIACCESS
1052 (void) pci_device_unmap_range(pVBox->pciInfo,
1053 pVBox->base,
1054 pVBox->mapSize);
1055#else
1056 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1057 (unsigned) pVBox->mapSize);
1058#endif
1059 vgaHWUnmapMem(pScrn);
1060 pVBox->base = NULL;
1061}
1062
1063static Bool
1064VBOXSaveScreen(ScreenPtr pScreen, int mode)
1065{
1066 return vgaHWSaveScreen(pScreen, mode);
1067}
1068
1069Bool
1070VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1071{
1072 VBOXPtr pVBox;
1073
1074 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1075 return (FALSE);
1076
1077 pVBox = VBOXGetRec(pScrn);
1078
1079 /* Query amount of memory to save state */
1080 if (function == MODE_QUERY ||
1081 (function == MODE_SAVE && pVBox->state == NULL))
1082 {
1083 /* Make sure we save at least this information in case of failure */
1084 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1085 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1086
1087 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1088 &pVBox->stateSize,&pVBox->statePage))
1089 return FALSE;
1090 }
1091
1092 /* Save/Restore Super VGA state */
1093 if (function != MODE_QUERY) {
1094 Bool retval = TRUE;
1095
1096 if (function == MODE_RESTORE)
1097 memcpy(pVBox->state, pVBox->pstate,
1098 (unsigned) pVBox->stateSize);
1099
1100 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1101 (pointer)&pVBox->state,
1102 &pVBox->stateSize,&pVBox->statePage))
1103 && function == MODE_SAVE)
1104 {
1105 /* don't rely on the memory not being touched */
1106 if (pVBox->pstate == NULL)
1107 pVBox->pstate = xalloc(pVBox->stateSize);
1108 memcpy(pVBox->pstate, pVBox->state,
1109 (unsigned) pVBox->stateSize);
1110 }
1111
1112 if (function == MODE_RESTORE)
1113 {
1114 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1115 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1116 }
1117
1118 if (!retval)
1119 return (FALSE);
1120
1121 }
1122
1123 return (TRUE);
1124}
1125
1126static void
1127VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1128 int flags)
1129{
1130 vgaHWDPMSSet(pScrn, mode, flags);
1131}
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