VirtualBox

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

Last change on this file since 34400 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

  • Property svn:eol-style set to native
File size: 33.7 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 function 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 xfree(pVBox->savedPal);
336 xfree(pVBox->fonts);
337 xfree(pScrn->driverPrivate);
338 pScrn->driverPrivate = NULL;
339}
340
341/*
342 * This function is called once, at the start of the first server generation to
343 * do a minimal probe for supported hardware.
344 */
345
346#ifdef PCIACCESS
347static Bool
348VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
349 intptr_t match_data)
350{
351 ScrnInfoPtr pScrn;
352
353 TRACE_ENTRY();
354 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
355 NULL, NULL, NULL, NULL, NULL);
356 if (pScrn != NULL) {
357 VBOXPtr pVBox = VBOXGetRec(pScrn);
358
359 pScrn->driverVersion = VBOX_VERSION;
360 pScrn->driverName = VBOX_DRIVER_NAME;
361 pScrn->name = VBOX_NAME;
362 pScrn->Probe = NULL;
363 pScrn->PreInit = VBOXPreInit;
364 pScrn->ScreenInit = VBOXScreenInit;
365 pScrn->SwitchMode = VBOXSwitchMode;
366 /* pScrn->ValidMode = VBOXValidMode; */
367 pScrn->AdjustFrame = VBOXAdjustFrame;
368 pScrn->EnterVT = VBOXEnterVT;
369 pScrn->LeaveVT = VBOXLeaveVT;
370 pScrn->FreeScreen = VBOXFreeScreen;
371
372 pVBox->pciInfo = dev;
373 }
374
375 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
376 return (pScrn != NULL);
377}
378#else /* !PCIACCESS */
379static Bool
380VBOXProbe(DriverPtr drv, int flags)
381{
382 Bool foundScreen = FALSE;
383 int numDevSections, numUsed;
384 GDevPtr *devSections;
385 int *usedChips;
386 int i;
387
388 /*
389 * Find the config file Device sections that match this
390 * driver, and return if there are none.
391 */
392 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
393 &devSections)) <= 0)
394 return (FALSE);
395
396 /* PCI BUS */
397 if (xf86GetPciVideoInfo()) {
398 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
399 VBOXChipsets, VBOXPCIchipsets,
400 devSections, numDevSections,
401 drv, &usedChips);
402 if (numUsed > 0) {
403 if (flags & PROBE_DETECT)
404 foundScreen = TRUE;
405 else {
406 for (i = 0; i < numUsed; i++) {
407 ScrnInfoPtr pScrn = NULL;
408 /* Allocate a ScrnInfoRec */
409 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
410 VBOXPCIchipsets,NULL,
411 NULL,NULL,NULL,NULL))) {
412 pScrn->driverVersion = VBOX_VERSION;
413 pScrn->driverName = VBOX_DRIVER_NAME;
414 pScrn->name = VBOX_NAME;
415 pScrn->Probe = VBOXProbe;
416 pScrn->PreInit = VBOXPreInit;
417 pScrn->ScreenInit = VBOXScreenInit;
418 pScrn->SwitchMode = VBOXSwitchMode;
419 pScrn->AdjustFrame = VBOXAdjustFrame;
420 pScrn->EnterVT = VBOXEnterVT;
421 pScrn->LeaveVT = VBOXLeaveVT;
422 pScrn->FreeScreen = VBOXFreeScreen;
423 foundScreen = TRUE;
424 }
425 }
426 }
427 xfree(usedChips);
428 }
429 }
430 xfree(devSections);
431
432 return (foundScreen);
433}
434#endif /* !PCIACCESS */
435
436/**
437 * This function hooks into the chain that is called when framebuffer access
438 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
439 * In other words, it observes when the server wishes access to the
440 * framebuffer to be enabled and when it should be disabled. We need to know
441 * this because we disable access ourselves during mode switches (presumably
442 * the server should do this but it doesn't) and want to know whether to
443 * restore it or not afterwards.
444 */
445static void
446vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
447{
448 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
449 VBOXPtr pVBox = VBOXGetRec(pScrn);
450
451 pVBox->accessEnabled = enable;
452 pVBox->EnableDisableFBAccess(scrnIndex, enable);
453}
454
455/*
456 * QUOTE from the XFree86 DESIGN document:
457 *
458 * The purpose of this function is to find out all the information
459 * required to determine if the configuration is usable, and to initialise
460 * those parts of the ScrnInfoRec that can be set once at the beginning of
461 * the first server generation.
462 *
463 * (...)
464 *
465 * This includes probing for video memory, clocks, ramdac, and all other
466 * HW info that is needed. It includes determining the depth/bpp/visual
467 * and related info. It includes validating and determining the set of
468 * video modes that will be used (and anything that is required to
469 * determine that).
470 *
471 * This information should be determined in the least intrusive way
472 * possible. The state of the HW must remain unchanged by this function.
473 * Although video memory (including MMIO) may be mapped within this
474 * function, it must be unmapped before returning.
475 *
476 * END QUOTE
477 */
478
479static Bool
480VBOXPreInit(ScrnInfoPtr pScrn, int flags)
481{
482 VBOXPtr pVBox;
483 Gamma gzeros = {0.0, 0.0, 0.0};
484 rgb rzeros = {0, 0, 0};
485 int i;
486 unsigned DispiId;
487 DisplayModePtr pMode;
488 enum { MODE_MIN_SIZE = 64 };
489
490 TRACE_ENTRY();
491 /* Are we really starting the server, or is this just a dummy run? */
492 if (flags & PROBE_DETECT)
493 return (FALSE);
494
495 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
496 "VirtualBox guest additions video driver version "
497 VBOX_VERSION_STRING "\n");
498
499 /* Get our private data from the ScrnInfoRec structure. */
500 pVBox = VBOXGetRec(pScrn);
501
502 /* Initialise the guest library */
503 vbox_init(pScrn->scrnIndex, pVBox);
504
505 /* Entity information seems to mean bus information. */
506 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
507
508 /* The ramdac module is needed for the hardware cursor. */
509 if (!xf86LoadSubModule(pScrn, "ramdac"))
510 return FALSE;
511
512 /* We need the vbe module because we use VBE code to save and restore
513 text mode, in order to keep our code simple. */
514 if (!xf86LoadSubModule(pScrn, "vbe"))
515 return (FALSE);
516
517 /* The framebuffer module. */
518 if (xf86LoadSubModule(pScrn, "fb") == NULL)
519 return (FALSE);
520
521 if (!xf86LoadSubModule(pScrn, "shadowfb"))
522 return FALSE;
523
524 if (!xf86LoadSubModule(pScrn, "vgahw"))
525 return FALSE;
526
527#ifdef VBOX_DRI
528 /* Load the dri module. */
529 if (!xf86LoadSubModule(pScrn, "dri"))
530 return FALSE;
531#endif
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 /* Check if the chip restricts horizontal resolution or not. */
570 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
571 outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
572 DispiId = inw(VBE_DISPI_IOPORT_DATA);
573 if (DispiId == VBE_DISPI_ID_ANYX)
574 pVBox->fAnyX = TRUE;
575 else
576 pVBox->fAnyX = FALSE;
577
578 /* Set up clock information that will support all modes we need. */
579 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
580 pScrn->clockRanges->minClock = 1000;
581 pScrn->clockRanges->maxClock = 1000000000;
582 pScrn->clockRanges->clockIndex = -1;
583 pScrn->clockRanges->ClockMulFactor = 1;
584 pScrn->clockRanges->ClockDivFactor = 1;
585
586 /* Determine the preferred size and colour depth and setup video modes */
587 {
588 uint32_t cx = 0, cy = 0, cBits = 0;
589
590 vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
591 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
592 if (cBits != 16)
593 cBits = 24;
594 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
595 return FALSE;
596 vboxAddModes(pScrn, cx, cy);
597 }
598 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
599 {
600 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
601 "The VBox additions only support 16 and 32bpp graphics modes\n");
602 return FALSE;
603 }
604 xf86PrintDepthBpp(pScrn);
605
606 /* Colour weight - we always call this, since we are always in
607 truecolour. */
608 if (!xf86SetWeight(pScrn, rzeros, rzeros))
609 return (FALSE);
610
611 /* visual init */
612 if (!xf86SetDefaultVisual(pScrn, -1))
613 return (FALSE);
614
615 xf86SetGamma(pScrn, gzeros);
616
617 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
618 * already know what we like and what we don't. */
619
620 pScrn->currentMode = pScrn->modes;
621
622 /* Set the right virtual resolution. */
623 pScrn->virtualX = pScrn->currentMode->HDisplay;
624 pScrn->virtualY = pScrn->currentMode->VDisplay;
625
626 pScrn->displayWidth = pScrn->virtualX;
627
628 xf86PrintModes(pScrn);
629
630 /* Set the DPI. Perhaps we should read this from the host? */
631 xf86SetDpi(pScrn, 96, 96);
632
633 /* options */
634 xf86CollectOptions(pScrn, NULL);
635 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
636 return FALSE;
637 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
638 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
639
640 /* Framebuffer-related setup */
641 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
642
643 /* VGA hardware initialisation */
644 if (!vgaHWGetHWRec(pScrn))
645 return FALSE;
646
647 TRACE_EXIT();
648 return (TRUE);
649}
650
651/*
652 * QUOTE from the XFree86 DESIGN document:
653 *
654 * This is called at the start of each server generation.
655 *
656 * (...)
657 *
658 * Decide which operations need to be placed under resource access
659 * control. (...) Map any video memory or other memory regions. (...)
660 * Save the video card state. (...) Initialise the initial video
661 * mode.
662 *
663 * End QUOTE.
664 */
665static Bool
666VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
667{
668 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
669 VBOXPtr pVBox = VBOXGetRec(pScrn);
670 VisualPtr visual;
671 unsigned flags;
672
673 TRACE_ENTRY();
674 /* We make use of the X11 VBE code to save and restore text mode, in
675 order to keep our code simple. */
676 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
677 SET_BIOS_SCRATCH
678 | RESTORE_BIOS_SCRATCH)) == NULL)
679 return (FALSE);
680
681 if (pScrn->memPhysBase == 0) {
682#ifdef PCIACCESS
683 pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
684#else
685 pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
686#endif
687/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
688 /* Using the PCI information caused problems with
689 non-powers-of-two sized video RAM configurations */
690 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
691 pScrn->fbOffset = 0;
692 }
693
694 if (!VBOXMapVidMem(pScrn))
695 return (FALSE);
696
697 /* save current video state */
698 VBOXSaveRestore(pScrn, MODE_SAVE);
699 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
700 NULL, FALSE, FALSE);
701
702 /* set the viewport */
703 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
704
705 /* Blank the screen for aesthetic reasons. */
706 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
707
708 /* mi layer - reset the visual list (?)*/
709 miClearVisualTypes();
710 if (!xf86SetDefaultVisual(pScrn, -1))
711 return (FALSE);
712 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
713 pScrn->rgbBits, TrueColor))
714 return (FALSE);
715 if (!miSetPixmapDepths())
716 return (FALSE);
717
718 /* Needed before we initialise DRI. */
719 pScrn->virtualX = (pScrn->virtualX + 7) & ~7;
720 pScrn->displayWidth = pScrn->virtualX;
721
722#ifdef VBOX_DRI
723 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
724#endif
725
726 /* I checked in the sources, and XFree86 4.2 does seem to support
727 this function for 32bpp. */
728 if (!fbScreenInit(pScreen, pVBox->base,
729 pScrn->virtualX, pScrn->virtualY,
730 pScrn->xDpi, pScrn->yDpi,
731 pScrn->displayWidth, pScrn->bitsPerPixel))
732 return (FALSE);
733
734 /* Fixup RGB ordering */
735 visual = pScreen->visuals + pScreen->numVisuals;
736 while (--visual >= pScreen->visuals) {
737 if ((visual->class | DynamicClass) == DirectColor) {
738 visual->offsetRed = pScrn->offset.red;
739 visual->offsetGreen = pScrn->offset.green;
740 visual->offsetBlue = pScrn->offset.blue;
741 visual->redMask = pScrn->mask.red;
742 visual->greenMask = pScrn->mask.green;
743 visual->blueMask = pScrn->mask.blue;
744 }
745 }
746
747 /* must be after RGB ordering fixed */
748 fbPictureInit(pScreen, 0, 0);
749
750 xf86SetBlackWhitePixels(pScreen);
751 miInitializeBackingStore(pScreen);
752 xf86SetBackingStore(pScreen);
753
754 /* We need to keep track of whether we are currently switched to a virtual
755 * terminal to know whether a mode set operation is currently safe to do.
756 */
757 pVBox->vtSwitch = FALSE;
758 /* software cursor */
759 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
760
761 /* colourmap code - apparently, we need this even in Truecolour */
762 if (!miCreateDefColormap(pScreen))
763 return (FALSE);
764
765 flags = CMAP_RELOAD_ON_MODE_SWITCH;
766
767 if(!vgaHWHandleColormaps(pScreen))
768 return (FALSE);
769
770 /* Hook our observer function ito the chain which is called when
771 * framebuffer access is enabled or disabled in the server, and
772 * assume an initial state of enabled. */
773 pVBox->accessEnabled = TRUE;
774 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
775 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
776
777 pVBox->CloseScreen = pScreen->CloseScreen;
778 pScreen->CloseScreen = VBOXCloseScreen;
779 pScreen->SaveScreen = VBOXSaveScreen;
780
781 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
782
783 /* Report any unused options (only for the first generation) */
784 if (serverGeneration == 1)
785 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
786
787 /* set first video mode */
788 if (!VBOXSetMode(pScrn, pScrn->currentMode))
789 return FALSE;
790 /* And make sure that a non-current dynamic mode is at the front of the
791 * list */
792 vboxWriteHostModes(pScrn, pScrn->currentMode);
793
794 if (vbox_open (pScrn, pScreen, pVBox)) {
795 if (vbox_cursor_init(pScreen) != TRUE)
796 xf86DrvMsg(scrnIndex, X_ERROR,
797 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
798 if (vboxEnableVbva(pScrn) == TRUE)
799 xf86DrvMsg(scrnIndex, X_INFO,
800 "The VBox video extensions are now enabled.\n");
801 vboxEnableGraphicsCap(pVBox);
802 }
803
804#ifdef VBOX_DRI
805 if (pVBox->useDRI)
806 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
807#endif
808 TRACE_EXIT();
809 return (TRUE);
810}
811
812static Bool
813VBOXEnterVT(int scrnIndex, int flags)
814{
815 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
816 VBOXPtr pVBox = VBOXGetRec(pScrn);
817
818 TRACE_ENTRY();
819 pVBox->vtSwitch = FALSE;
820#ifdef VBOX_DRI
821 if (pVBox->useDRI)
822 DRIUnlock(screenInfo.screens[scrnIndex]);
823#endif
824 if (!VBOXSetMode(pScrn, pScrn->currentMode))
825 return FALSE;
826 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
827 if (pVBox->useVbva == TRUE)
828 vboxEnableVbva(pScrn);
829 return TRUE;
830}
831
832static void
833VBOXLeaveVT(int scrnIndex, int flags)
834{
835 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
836 VBOXPtr pVBox = VBOXGetRec(pScrn);
837
838 TRACE_ENTRY();
839 VBOXSaveRestore(pScrn, MODE_RESTORE);
840 if (pVBox->useVbva == TRUE)
841 vboxDisableVbva(pScrn);
842 vboxDisableGraphicsCap(pVBox);
843 pVBox->vtSwitch = TRUE;
844#ifdef VBOX_DRI
845 if (pVBox->useDRI)
846 DRILock(screenInfo.screens[scrnIndex], 0);
847#endif
848}
849
850static Bool
851VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
852{
853 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
854 VBOXPtr pVBox = VBOXGetRec(pScrn);
855
856#ifdef VBOX_DRI
857 if (pVBox->useDRI)
858 VBOXDRICloseScreen(pScreen, pVBox);
859 pVBox->useDRI = false;
860#endif
861
862 if (pVBox->useVbva == TRUE)
863 vboxDisableVbva(pScrn);
864 vboxDisableGraphicsCap(pVBox);
865 if (pScrn->vtSema) {
866 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
867 if (pVBox->savedPal)
868 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
869 pVBox->savedPal, FALSE, TRUE);
870 VBOXUnmapVidMem(pScrn);
871 }
872 pScrn->vtSema = FALSE;
873
874 /* Destroy the VGA hardware record */
875 vgaHWFreeHWRec(pScrn);
876
877 /* And do additional bits which are separate for historical reasons */
878 vbox_close(pScrn, pVBox);
879
880 pScreen->CloseScreen = pVBox->CloseScreen;
881 return pScreen->CloseScreen(scrnIndex, pScreen);
882}
883
884static Bool
885VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
886{
887 ScrnInfoPtr pScrn;
888 VBOXPtr pVBox;
889 Bool rc = TRUE;
890
891 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of referring to the screen? */
892 pVBox = VBOXGetRec(pScrn);
893 if (pVBox->useVbva)
894 if (!vboxDisableVbva(pScrn)) /* This would be bad. */
895 rc = FALSE;
896 /* We want to disable access to the framebuffer before switching mode.
897 * After doing the switch, we allow access if it was allowed before. */
898 if (pVBox->accessEnabled)
899 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
900 if (rc && !VBOXSetMode(pScrn, pMode))
901 rc = FALSE;
902 if (rc && !VBOXAdjustScreenPixmap(pScrn, pMode))
903 rc = FALSE;
904 if (rc && !vboxGuestIsSeamless(pScrn))
905 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
906 pScrn->bitsPerPixel);
907 if (rc)
908 {
909 vboxWriteHostModes(pScrn, pMode);
910 xf86PrintModes(pScrn);
911 }
912 if (pVBox->accessEnabled)
913 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
914 if (pVBox->useVbva)
915 if (!vboxEnableVbva(pScrn)) /* Bad but not fatal */
916 pVBox->useVbva = FALSE;
917 return rc;
918}
919
920/* Set a graphics mode */
921static Bool
922VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
923{
924 TRACE_ENTRY();
925 int bpp = pScrn->depth == 24 ? 32 : 16;
926 VBOXPtr pVBox = VBOXGetRec(pScrn);
927
928 /* Don't fiddle with the hardware if we are switched
929 * to a virtual terminal. */
930 if (pVBox->vtSwitch == TRUE)
931 return TRUE;
932 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
933 >= pScrn->videoRam * 1024)
934 {
935 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
936 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
937 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
938 return FALSE;
939 }
940
941 pScrn->vtSema = TRUE;
942 /* Disable linear framebuffer mode before making changes to the resolution. */
943 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
944 outw(VBE_DISPI_IOPORT_DATA,
945 VBE_DISPI_DISABLED);
946 /* Unlike the resolution, the depth is fixed for a given screen
947 for the lifetime of the X session. */
948 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
949 outw(VBE_DISPI_IOPORT_DATA, bpp);
950 /* HDisplay and VDisplay are actually monitor information about
951 the display part of the scanlines. */
952 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
953 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
954 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
955 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
956 /* Enable linear framebuffer mode. */
957 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
958 outw(VBE_DISPI_IOPORT_DATA,
959 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
960 /* Set the virtual resolution. We are still using VESA to control
961 the virtual offset. */
962 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
963 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
964 vboxEnableGraphicsCap(pVBox);
965 TRACE_EXIT();
966 return (TRUE);
967}
968
969static bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, DisplayModePtr pMode)
970{
971 ScreenPtr pScreen = pScrn->pScreen;
972 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
973 VBOXPtr pVBox = VBOXGetRec(pScrn);
974 int bpp = pScrn->depth == 24 ? 32 : 16;
975 if (!pPixmap) {
976 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
977 "Failed to get the screen pixmap.\n");
978 return FALSE;
979 }
980 pScreen->ModifyPixmapHeader(pPixmap, pMode->HDisplay, pMode->VDisplay,
981 pScrn->depth, bpp, pMode->HDisplay * bpp / 8,
982 pVBox->base);
983#ifdef VBOX_DRI
984 if (pVBox->useDRI)
985 VBOXDRIUpdateStride(pScrn, pVBox);
986#endif
987 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
988 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
989 return TRUE;
990}
991
992static void
993VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
994{
995 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
996 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
997
998 /* Don't fiddle with the hardware if we are switched
999 * to a virtual terminal. */
1000 if (pVBox->vtSwitch == TRUE)
1001 return;
1002 pVBox->viewportX = x;
1003 pVBox->viewportY = y;
1004 /* If VBVA is enabled the graphics card will not notice the change. */
1005 if (pVBox->useVbva == TRUE)
1006 vboxDisableVbva(pScrn);
1007 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
1008 if (pVBox->useVbva == TRUE)
1009 vboxEnableVbva(pScrn);
1010}
1011
1012static void
1013VBOXFreeScreen(int scrnIndex, int flags)
1014{
1015 VBOXFreeRec(xf86Screens[scrnIndex]);
1016}
1017
1018static Bool
1019VBOXMapVidMem(ScrnInfoPtr pScrn)
1020{
1021 VBOXPtr pVBox = VBOXGetRec(pScrn);
1022
1023 if (pVBox->base != NULL)
1024 return (TRUE);
1025
1026#ifdef PCIACCESS
1027 (void) pci_device_map_range(pVBox->pciInfo,
1028 pScrn->memPhysBase,
1029 pVBox->mapSize,
1030 PCI_DEV_MAP_FLAG_WRITABLE,
1031 & pVBox->base);
1032#else
1033 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1034 VIDMEM_FRAMEBUFFER,
1035 pVBox->pciTag, pScrn->memPhysBase,
1036 (unsigned) pVBox->mapSize);
1037#endif
1038 if (pVBox->base)
1039 {
1040 /* We need this for saving/restoring textmode */
1041 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1042 return vgaHWMapMem(pScrn);
1043 }
1044 else
1045 return FALSE;
1046}
1047
1048static void
1049VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1050{
1051 VBOXPtr pVBox = VBOXGetRec(pScrn);
1052
1053 if (pVBox->base == NULL)
1054 return;
1055
1056#ifdef PCIACCESS
1057 (void) pci_device_unmap_range(pVBox->pciInfo,
1058 pVBox->base,
1059 pVBox->mapSize);
1060#else
1061 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1062 (unsigned) pVBox->mapSize);
1063#endif
1064 vgaHWUnmapMem(pScrn);
1065 pVBox->base = NULL;
1066}
1067
1068static Bool
1069VBOXSaveScreen(ScreenPtr pScreen, int mode)
1070{
1071 return vgaHWSaveScreen(pScreen, mode);
1072}
1073
1074Bool
1075VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1076{
1077 VBOXPtr pVBox;
1078
1079 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1080 return (FALSE);
1081
1082 pVBox = VBOXGetRec(pScrn);
1083
1084 /* Query amount of memory to save state */
1085 if (function == MODE_QUERY ||
1086 (function == MODE_SAVE && pVBox->state == NULL))
1087 {
1088 /* Make sure we save at least this information in case of failure */
1089 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1090 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1091
1092 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1093 &pVBox->stateSize,&pVBox->statePage))
1094 return FALSE;
1095 }
1096
1097 /* Save/Restore Super VGA state */
1098 if (function != MODE_QUERY) {
1099 Bool retval = TRUE;
1100
1101 if (function == MODE_RESTORE)
1102 memcpy(pVBox->state, pVBox->pstate,
1103 (unsigned) pVBox->stateSize);
1104
1105 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1106 (pointer)&pVBox->state,
1107 &pVBox->stateSize,&pVBox->statePage))
1108 && function == MODE_SAVE)
1109 {
1110 /* don't rely on the memory not being touched */
1111 if (pVBox->pstate == NULL)
1112 pVBox->pstate = xalloc(pVBox->stateSize);
1113 memcpy(pVBox->pstate, pVBox->state,
1114 (unsigned) pVBox->stateSize);
1115 }
1116
1117 if (function == MODE_RESTORE)
1118 {
1119 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1120 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1121 }
1122
1123 if (!retval)
1124 return (FALSE);
1125
1126 }
1127
1128 return (TRUE);
1129}
1130
1131static void
1132VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1133 int flags)
1134{
1135 vgaHWDPMSSet(pScrn, mode, flags);
1136}
Note: See TracBrowser for help on using the repository browser.

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