VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo_13.c@ 22149

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

Additions/x11/vboxvideo: applied patch by Lubomir Rintel to make vboxvideo build on the X.Org 1.7 pre-release

  • Property svn:eol-style set to native
File size: 42.4 KB
Line 
1/** @file
2 *
3 * Linux Additions X11 graphics driver
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 * --------------------------------------------------------------------
21 *
22 * This code is based on:
23 *
24 * X11 VESA driver
25 *
26 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a
29 * copy of this software and associated documentation files (the "Software"),
30 * to deal in the Software without restriction, including without limitation
31 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32 * and/or sell copies of the Software, and to permit persons to whom the
33 * Software is furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
43 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44 * SOFTWARE.
45 *
46 * Except as contained in this notice, the name of Conectiva Linux shall
47 * not be used in advertising or otherwise to promote the sale, use or other
48 * dealings in this Software without prior written authorization from
49 * Conectiva Linux.
50 *
51 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
52 */
53
54#include "xorg-server.h"
55#include "vboxvideo.h"
56#include "version-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/* X.org 1.3+ mode setting */
77#include "xf86Crtc.h"
78#include "xf86Modes.h"
79
80/* Mandatory functions */
81
82static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
83static void VBOXIdentify(int flags);
84#ifndef PCIACCESS
85static Bool VBOXProbe(DriverPtr drv, int flags);
86#else
87static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
88 struct pci_device *dev, intptr_t match_data);
89#endif
90static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
91static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
92 char **argv);
93static Bool VBOXEnterVT(int scrnIndex, int flags);
94static void VBOXLeaveVT(int scrnIndex, int flags);
95static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
96static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
97static ModeStatus VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass);
98static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
99static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
100static void VBOXFreeScreen(int scrnIndex, int flags);
101static void VBOXFreeRec(ScrnInfoPtr pScrn);
102
103/* locally used functions */
104static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
105static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
106static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
107 vbeSaveRestoreFunction function);
108
109enum GenericTypes
110{
111 CHIP_VBOX_GENERIC
112};
113
114#ifdef PCIACCESS
115static const struct pci_id_match vbox_device_match[] = {
116 {
117 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
118 0, 0, 0
119 },
120
121 { 0, 0, 0 },
122};
123#endif
124
125/* Supported chipsets */
126static SymTabRec VBOXChipsets[] =
127{
128 {VBOX_DEVICEID, "vbox"},
129 {-1, NULL}
130};
131
132static PciChipsets VBOXPCIchipsets[] = {
133 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
134 { -1, -1, RES_UNDEFINED },
135};
136
137/*
138 * This contains the functions needed by the server after loading the
139 * driver module. It must be supplied, and gets added the driver list by
140 * the Module Setup funtion in the dynamic case. In the static case a
141 * reference to this is compiled in, and this requires that the name of
142 * this DriverRec be an upper-case version of the driver name.
143 */
144
145_X_EXPORT DriverRec VBOXVIDEO = {
146 VBOX_VERSION,
147 VBOX_DRIVER_NAME,
148 VBOXIdentify,
149#ifdef PCIACCESS
150 NULL,
151#else
152 VBOXProbe,
153#endif
154 VBOXAvailableOptions,
155 NULL,
156 0,
157 NULL,
158
159#ifdef PCIACCESS
160 vbox_device_match,
161 VBOXPciProbe
162#endif
163};
164
165/* No options for now */
166static const OptionInfoRec VBOXOptions[] = {
167 { -1, NULL, OPTV_NONE, {0}, FALSE }
168};
169
170static VBOXPtr
171VBOXGetRec(ScrnInfoPtr pScrn)
172{
173 if (!pScrn->driverPrivate) {
174 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
175 }
176
177 return ((VBOXPtr)pScrn->driverPrivate);
178}
179
180static void
181VBOXFreeRec(ScrnInfoPtr pScrn)
182{
183 VBOXPtr pVBox = VBOXGetRec(pScrn);
184 xfree(pVBox->savedPal);
185 xfree(pVBox->fonts);
186 xfree(pScrn->driverPrivate);
187 pScrn->driverPrivate = NULL;
188}
189
190/* X.org 1.3+ mode-setting support ******************************************/
191
192/* For descriptions of these functions and structures, see
193 hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
194 X.Org source tree. */
195
196static Bool
197VBOXCrtcResize(ScrnInfoPtr scrn, int width, int height)
198{
199 int bpp = scrn->bitsPerPixel;
200 ScreenPtr pScreen = scrn->pScreen;
201 PixmapPtr pPixmap = NULL;
202 VBOXPtr pVBox = VBOXGetRec(scrn);
203 Bool rc = TRUE;
204
205 TRACE_LOG("width=%d, height=%d\n", width, height);
206 /* We only support horizontal resolutions which are a multiple of 8.
207 * Round up if necessary. */
208 width = (width + 7) & ~7;
209 if (width * height * bpp / 8 >= scrn->videoRam * 1024)
210 {
211 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
212 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
213 width, height, scrn->videoRam);
214 rc = FALSE;
215 }
216 if (rc) {
217 pPixmap = pScreen->GetScreenPixmap(pScreen);
218 if (NULL == pPixmap) {
219 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
220 "Failed to get the screen pixmap.\n");
221 rc = FALSE;
222 }
223 }
224 if (rc) {
225 if (
226 !pScreen->ModifyPixmapHeader(pPixmap, width, height,
227 scrn->depth, bpp, width * bpp / 8,
228 pVBox->base)
229 ) {
230 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
231 "Failed to set up the screen pixmap.\n");
232 rc = FALSE;
233 }
234 }
235 if (rc) {
236 scrn->virtualX = width;
237 scrn->virtualY = height;
238 scrn->displayWidth = width;
239#ifdef VBOX_DRI
240 if (pVBox->useDRI)
241 VBOXDRIUpdateStride(scrn, pVBox);
242#endif
243 /* Write the new values to the hardware */
244 rc = xf86SetDesiredModes(scrn);
245 }
246 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
247 return rc;
248}
249
250static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
251 VBOXCrtcResize
252};
253
254static void
255vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
256{ (void) crtc; (void) mode; }
257
258static Bool
259vbox_crtc_lock (xf86CrtcPtr crtc)
260{ (void) crtc; return FALSE; }
261
262static Bool
263vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
264 DisplayModePtr adjusted_mode)
265{
266 ScrnInfoPtr pScrn = crtc->scrn;
267 int xRes = adjusted_mode->HDisplay;
268
269 (void) mode;
270 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d\n", adjusted_mode->name,
271 adjusted_mode->HDisplay, adjusted_mode->VDisplay);
272 /* We only support horizontal resolutions which are a multiple of 8. Round down if
273 necessary. */
274 if (xRes % 8 != 0)
275 {
276 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
277 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
278 xRes, xRes - (xRes % 8));
279 adjusted_mode->HDisplay = xRes - (xRes % 8);
280 }
281 return TRUE;
282}
283
284static void
285vbox_crtc_stub (xf86CrtcPtr crtc)
286{ (void) crtc; }
287
288static void
289vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
290 DisplayModePtr adjusted_mode, int x, int y)
291{
292 (void) mode;
293 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
294 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
295 VBOXSetMode(crtc->scrn, adjusted_mode);
296 VBOXAdjustFrame(crtc->scrn->scrnIndex, x, y, 0);
297 vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
298 adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
299}
300
301static void
302vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
303 CARD16 *green, CARD16 *blue, int size)
304{ (void) crtc; (void) red; (void) green; (void) blue; (void) size; }
305
306static void *
307vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
308{ (void) crtc; (void) width; (void) height; return NULL; }
309
310static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
311 .dpms = vbox_crtc_dpms,
312 .save = NULL, /* These two are never called by the server. */
313 .restore = NULL,
314 .lock = vbox_crtc_lock,
315 .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
316 .mode_fixup = vbox_crtc_mode_fixup,
317 .prepare = vbox_crtc_stub,
318 .mode_set = vbox_crtc_mode_set,
319 .commit = vbox_crtc_stub,
320 .gamma_set = vbox_crtc_gamma_set,
321 .shadow_allocate = vbox_crtc_shadow_allocate,
322 .shadow_create = NULL, /* These two should not be invoked if allocate
323 returns NULL. */
324 .shadow_destroy = NULL,
325 .set_cursor_colors = NULL, /* We are still using the old cursor API. */
326 .set_cursor_position = NULL,
327 .show_cursor = NULL,
328 .hide_cursor = NULL,
329 .load_cursor_argb = NULL,
330 .destroy = vbox_crtc_stub
331};
332
333static void
334vbox_output_stub (xf86OutputPtr output)
335{ (void) output; }
336
337static void
338vbox_output_dpms (xf86OutputPtr output, int mode)
339{ (void) output; (void) mode; }
340
341static int
342vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
343{
344 ScrnInfoPtr pScrn = output->scrn;
345 int rc = MODE_OK;
346 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);
347 /* We always like modes specified by the user in the configuration
348 * file, as doing otherwise is likely to annoy people. */
349 if ( !(mode->type & M_T_USERDEF)
350 && vbox_device_available(VBOXGetRec(pScrn))
351 && !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,
352 pScrn->bitsPerPixel)
353 )
354 rc = MODE_BAD;
355 TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");
356 return rc;
357}
358
359static Bool
360vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
361 DisplayModePtr adjusted_mode)
362{ (void) output; (void) mode; (void) adjusted_mode; return TRUE; }
363
364static void
365vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
366 DisplayModePtr adjusted_mode)
367{ (void) output; (void) mode; (void) adjusted_mode; }
368
369/* A virtual monitor is always connected. */
370static xf86OutputStatus
371vbox_output_detect (xf86OutputPtr output)
372{
373 (void) output;
374 return XF86OutputStatusConnected;
375}
376
377static void
378vbox_output_add_mode (DisplayModePtr *pModes, const char *pszName, int x, int y,
379 Bool isPreferred, Bool isUserDef)
380{
381 TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName, x, y);
382 DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
383
384 pMode->status = MODE_OK;
385 /* We don't ask the host whether it likes user defined modes,
386 * as we assume that the user really wanted that mode. */
387 pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
388 if (isPreferred)
389 pMode->type |= M_T_PREFERRED;
390 /* VBox only supports screen widths which are a multiple of 8 */
391 pMode->HDisplay = (x + 7) & ~7;
392 pMode->HSyncStart = pMode->HDisplay + 2;
393 pMode->HSyncEnd = pMode->HDisplay + 4;
394 pMode->HTotal = pMode->HDisplay + 6;
395 pMode->VDisplay = y;
396 pMode->VSyncStart = pMode->VDisplay + 2;
397 pMode->VSyncEnd = pMode->VDisplay + 4;
398 pMode->VTotal = pMode->VDisplay + 6;
399 pMode->Clock = pMode->HTotal * pMode->VTotal * 60 / 1000; /* kHz */
400 if (NULL == pszName) {
401 xf86SetModeDefaultName(pMode);
402 } else {
403 pMode->name = xnfstrdup(pszName);
404 }
405 *pModes = xf86ModesAdd(*pModes, pMode);
406}
407
408static DisplayModePtr
409vbox_output_get_modes (xf86OutputPtr output)
410{
411 bool rc;
412 unsigned i;
413 DisplayModePtr pModes = NULL;
414 ScrnInfoPtr pScrn = output->scrn;
415 VBOXPtr pVBox = VBOXGetRec(pScrn);
416
417 TRACE_ENTRY();
418 if (vbox_device_available(pVBox))
419 {
420 uint32_t x, y, bpp, display;
421 rc = vboxGetDisplayChangeRequest(pScrn, &x, &y, &bpp, &display);
422 /* @todo - check the display number once we support multiple displays. */
423 /* If we don't find a display request, see if we have a saved hint
424 * from a previous session. */
425 if (!rc || (0 == x) || (0 == y))
426 rc = vboxRetrieveVideoMode(pScrn, &x, &y, &bpp);
427 if (rc && (0 != x) && (0 != y)) {
428 /* We prefer a slightly smaller size to a slightly larger one */
429 x -= (x % 8);
430 vbox_output_add_mode(&pModes, NULL, x, y, TRUE, FALSE);
431 }
432 }
433 /* Also report any modes the user may have requested in the xorg.conf
434 * configuration file. */
435 for (i = 0; pScrn->display->modes[i] != NULL; i++)
436 {
437 int x, y;
438 if (2 == sscanf(pScrn->display->modes[i], "%dx%d", &x, &y))
439 vbox_output_add_mode(&pModes, pScrn->display->modes[i], x, y,
440 FALSE, TRUE);
441 }
442 TRACE_EXIT();
443 return pModes;
444}
445
446#ifdef RANDR_12_INTERFACE
447/* We don't yet have mutable properties, whatever they are. */
448static Bool
449vbox_output_set_property(xf86OutputPtr output, Atom property,
450 RRPropertyValuePtr value)
451{ (void) output; (void) property; (void) value; return FALSE; }
452#endif
453
454static const xf86OutputFuncsRec VBOXOutputFuncs = {
455 .create_resources = vbox_output_stub,
456 .dpms = vbox_output_dpms,
457 .save = NULL, /* These two are never called by the server. */
458 .restore = NULL,
459 .mode_valid = vbox_output_mode_valid,
460 .mode_fixup = vbox_output_mode_fixup,
461 .prepare = vbox_output_stub,
462 .commit = vbox_output_stub,
463 .mode_set = vbox_output_mode_set,
464 .detect = vbox_output_detect,
465 .get_modes = vbox_output_get_modes,
466#ifdef RANDR_12_INTERFACE
467 .set_property = vbox_output_set_property,
468#endif
469 .destroy = vbox_output_stub
470};
471
472#ifdef XFree86LOADER
473/* Module loader interface */
474static MODULESETUPPROTO(vboxSetup);
475
476static XF86ModuleVersionInfo vboxVersionRec =
477{
478 VBOX_DRIVER_NAME,
479 "Sun Microsystems, Inc.",
480 MODINFOSTRING1,
481 MODINFOSTRING2,
482 XORG_VERSION_CURRENT,
483 1, /* Module major version. Xorg-specific */
484 0, /* Module minor version. Xorg-specific */
485 1, /* Module patchlevel. Xorg-specific */
486 ABI_CLASS_VIDEODRV, /* This is a video driver */
487 ABI_VIDEODRV_VERSION,
488 MOD_CLASS_VIDEODRV,
489 {0, 0, 0, 0}
490};
491
492/*
493 * This data is accessed by the loader. The name must be the module name
494 * followed by "ModuleData".
495 */
496_X_EXPORT XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
497
498static pointer
499vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
500{
501 static Bool Initialised = FALSE;
502
503 if (!Initialised)
504 {
505 Initialised = TRUE;
506#ifdef PCIACCESS
507 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
508#else
509 xf86AddDriver(&VBOXVIDEO, Module, 0);
510#endif
511 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
512 (void *)&VBOXVIDEO);
513 return (pointer)TRUE;
514 }
515
516 if (ErrorMajor)
517 *ErrorMajor = LDR_ONCEONLY;
518 return (NULL);
519}
520
521#endif /* XFree86Loader defined */
522
523static const OptionInfoRec *
524VBOXAvailableOptions(int chipid, int busid)
525{
526 return (VBOXOptions);
527}
528
529static void
530VBOXIdentify(int flags)
531{
532 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
533}
534
535/*
536 * This function is called once, at the start of the first server generation to
537 * do a minimal probe for supported hardware.
538 */
539
540#ifdef PCIACCESS
541static Bool
542VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
543 intptr_t match_data)
544{
545 ScrnInfoPtr pScrn;
546
547 TRACE_ENTRY();
548 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
549 NULL, NULL, NULL, NULL, NULL);
550 if (pScrn != NULL) {
551 VBOXPtr pVBox = VBOXGetRec(pScrn);
552
553 pScrn->driverVersion = VBOX_VERSION;
554 pScrn->driverName = VBOX_DRIVER_NAME;
555 pScrn->name = VBOX_NAME;
556 pScrn->Probe = NULL;
557 pScrn->PreInit = VBOXPreInit;
558 pScrn->ScreenInit = VBOXScreenInit;
559 pScrn->SwitchMode = VBOXSwitchMode;
560 pScrn->ValidMode = VBOXValidMode;
561 pScrn->AdjustFrame = VBOXAdjustFrame;
562 pScrn->EnterVT = VBOXEnterVT;
563 pScrn->LeaveVT = VBOXLeaveVT;
564 pScrn->FreeScreen = VBOXFreeScreen;
565
566 pVBox->pciInfo = dev;
567 }
568
569 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
570 return (pScrn != NULL);
571}
572#endif
573
574#ifndef PCIACCESS
575static Bool
576VBOXProbe(DriverPtr drv, int flags)
577{
578 Bool foundScreen = FALSE;
579 int numDevSections;
580 GDevPtr *devSections;
581
582 /*
583 * Find the config file Device sections that match this
584 * driver, and return if there are none.
585 */
586 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
587 &devSections)) <= 0)
588 return (FALSE);
589
590 /* PCI BUS */
591 if (xf86GetPciVideoInfo()) {
592 int numUsed;
593 int *usedChips;
594 int i;
595 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
596 VBOXChipsets, VBOXPCIchipsets,
597 devSections, numDevSections,
598 drv, &usedChips);
599 if (numUsed > 0) {
600 if (flags & PROBE_DETECT)
601 foundScreen = TRUE;
602 else {
603 for (i = 0; i < numUsed; i++) {
604 ScrnInfoPtr pScrn = NULL;
605 /* Allocate a ScrnInfoRec */
606 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
607 VBOXPCIchipsets,NULL,
608 NULL,NULL,NULL,NULL))) {
609 pScrn->driverVersion = VBOX_VERSION;
610 pScrn->driverName = VBOX_DRIVER_NAME;
611 pScrn->name = VBOX_NAME;
612 pScrn->Probe = VBOXProbe;
613 pScrn->PreInit = VBOXPreInit;
614 pScrn->ScreenInit = VBOXScreenInit;
615 pScrn->SwitchMode = VBOXSwitchMode;
616 pScrn->ValidMode = VBOXValidMode;
617 pScrn->AdjustFrame = VBOXAdjustFrame;
618 pScrn->EnterVT = VBOXEnterVT;
619 pScrn->LeaveVT = VBOXLeaveVT;
620 pScrn->FreeScreen = VBOXFreeScreen;
621 foundScreen = TRUE;
622 }
623 }
624 }
625 xfree(usedChips);
626 }
627 }
628
629 xfree(devSections);
630
631 return (foundScreen);
632}
633#endif
634
635/*
636 * QUOTE from the XFree86 DESIGN document:
637 *
638 * The purpose of this function is to find out all the information
639 * required to determine if the configuration is usable, and to initialise
640 * those parts of the ScrnInfoRec that can be set once at the beginning of
641 * the first server generation.
642 *
643 * (...)
644 *
645 * This includes probing for video memory, clocks, ramdac, and all other
646 * HW info that is needed. It includes determining the depth/bpp/visual
647 * and related info. It includes validating and determining the set of
648 * video modes that will be used (and anything that is required to
649 * determine that).
650 *
651 * This information should be determined in the least intrusive way
652 * possible. The state of the HW must remain unchanged by this function.
653 * Although video memory (including MMIO) may be mapped within this
654 * function, it must be unmapped before returning.
655 *
656 * END QUOTE
657 */
658
659static Bool
660VBOXPreInit(ScrnInfoPtr pScrn, int flags)
661{
662 VBOXPtr pVBox;
663 Gamma gzeros = {0.0, 0.0, 0.0};
664 rgb rzeros = {0, 0, 0};
665 xf86OutputPtr output;
666
667 /* Are we really starting the server, or is this just a dummy run? */
668 if (flags & PROBE_DETECT)
669 return (FALSE);
670
671 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
672 "VirtualBox guest additions video driver version "
673 VBOX_VERSION_STRING "\n");
674
675 /* Get our private data from the ScrnInfoRec structure. */
676 pVBox = VBOXGetRec(pScrn);
677
678 /* Initialise the guest library */
679 vbox_init(pScrn->scrnIndex, pVBox);
680
681 /* Entity information seems to mean bus information. */
682 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
683
684 /* We need the vbe module because we use VBE code to save and restore
685 text mode, in order to keep our code simple. */
686 if (!xf86LoadSubModule(pScrn, "vbe"))
687 return (FALSE);
688
689 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
690 SET_BIOS_SCRATCH
691 | RESTORE_BIOS_SCRATCH)) == NULL)
692 return (FALSE);
693
694#ifndef PCIACCESS
695 if (pVBox->pEnt->location.type != BUS_PCI)
696 return FALSE;
697
698 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
699 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
700 pVBox->pciInfo->device,
701 pVBox->pciInfo->func);
702#endif
703
704 /* The ramdac module is needed for the hardware cursor. */
705 if (!xf86LoadSubModule(pScrn, "ramdac"))
706 return FALSE;
707
708 /* The framebuffer module. */
709 if (xf86LoadSubModule(pScrn, "fb") == NULL)
710 return (FALSE);
711
712 if (!xf86LoadSubModule(pScrn, "shadowfb"))
713 return FALSE;
714
715 if (!xf86LoadSubModule(pScrn, "vgahw"))
716 return FALSE;
717
718 /* Set up our ScrnInfoRec structure to describe our virtual
719 capabilities to X. */
720
721 pScrn->chipset = "vbox";
722
723 /* I assume that this is no longer a requirement in the config file. */
724 pScrn->monitor = pScrn->confScreen->monitor;
725
726 pScrn->progClock = TRUE;
727 pScrn->rgbBits = 8;
728
729 /* Using the PCI information caused problems with non-powers-of-two
730 sized video RAM configurations */
731 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
732
733 /* Query the host for the preferred colour depth */
734 {
735 uint32_t cx, cy, iDisplay, cBits = 24;
736
737 if (vbox_device_available(pVBox))
738 {
739 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
740 if ( vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,
741 &iDisplay)
742 && (cBits != 16)
743 )
744 cBits = 24;
745 }
746 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
747 return FALSE;
748 }
749 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
750 {
751 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
752 "The VBox additions only support 16 and 32bpp graphics modes\n");
753 return FALSE;
754 }
755 xf86PrintDepthBpp(pScrn);
756
757 /* options */
758 xf86CollectOptions(pScrn, NULL);
759 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
760 return FALSE;
761 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
762 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
763
764 /* Initialise CRTC and output configuration for use with randr1.2. */
765 xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
766
767 /* Setup our single virtual CRTC. */
768 xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
769
770 /* Set up our single virtual output. */
771 output = xf86OutputCreate(pScrn, &VBOXOutputFuncs, "VBOX1");
772
773 /* Set a sane minimum and maximum mode size */
774 xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
775
776 /* We are not interested in the monitor section in the configuration file. */
777 xf86OutputUseScreenMonitor(output, FALSE);
778 output->possible_crtcs = 1;
779 output->possible_clones = 0;
780
781 /* Now create our initial CRTC/output configuration. */
782 if (!xf86InitialConfiguration(pScrn, TRUE)) {
783 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
784 return (FALSE);
785 }
786
787 /* Colour weight - we always call this, since we are always in
788 truecolour. */
789 if (!xf86SetWeight(pScrn, rzeros, rzeros))
790 return (FALSE);
791
792 /* visual init */
793 if (!xf86SetDefaultVisual(pScrn, -1))
794 return (FALSE);
795
796 xf86SetGamma(pScrn, gzeros);
797
798 /* Set a default display resolution. */
799 xf86SetDpi(pScrn, 96, 96);
800
801 /* Framebuffer-related setup */
802 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
803
804 /* VGA hardware initialisation */
805 if (!vgaHWGetHWRec(pScrn))
806 return FALSE;
807
808#ifdef VBOX_DRI
809 /* Load the dri module. */
810 if (!xf86LoadSubModule(pScrn, "dri"))
811 return FALSE;
812#endif
813 return (TRUE);
814}
815
816/**
817 * This function hooks into the chain that is called when framebuffer access
818 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
819 * In other words, it observes when the server wishes access to the
820 * framebuffer to be enabled and when it should be disabled. We need to know
821 * this because we disable access ourselves during mode switches (presumably
822 * the server should do this but it doesn't) and want to know whether to
823 * restore it or not afterwards.
824 */
825static void
826vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
827{
828 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
829 VBOXPtr pVBox = VBOXGetRec(pScrn);
830
831 TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");
832 pVBox->accessEnabled = enable;
833 pVBox->EnableDisableFBAccess(scrnIndex, enable);
834 TRACE_EXIT();
835}
836
837/*
838 * QUOTE from the XFree86 DESIGN document:
839 *
840 * This is called at the start of each server generation.
841 *
842 * (...)
843 *
844 * Decide which operations need to be placed under resource access
845 * control. (...) Map any video memory or other memory regions. (...)
846 * Save the video card state. (...) Initialise the initial video
847 * mode.
848 *
849 * End QUOTE.Initialise the initial video mode.
850 */
851static Bool
852VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
853{
854 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
855 VBOXPtr pVBox = VBOXGetRec(pScrn);
856 VisualPtr visual;
857 unsigned flags;
858
859 if (pVBox->mapPhys == 0) {
860#ifdef PCIACCESS
861 pVBox->mapPhys = pVBox->pciInfo->regions[0].base_addr;
862#else
863 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
864#endif
865/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
866 /* Using the PCI information caused problems with
867 non-powers-of-two sized video RAM configurations */
868 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
869 pVBox->mapOff = 0;
870 }
871
872 if (!VBOXMapVidMem(pScrn))
873 return (FALSE);
874
875 /* save current video state */
876 VBOXSaveRestore(pScrn, MODE_SAVE);
877 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
878 NULL, FALSE, FALSE);
879
880 /* mi layer - reset the visual list (?)*/
881 miClearVisualTypes();
882 if (!xf86SetDefaultVisual(pScrn, -1))
883 return (FALSE);
884 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
885 pScrn->rgbBits, TrueColor))
886 return (FALSE);
887 if (!miSetPixmapDepths())
888 return (FALSE);
889
890 /* Needed before we initialise DRI. */
891 pScrn->virtualX = (pScrn->virtualX + 7) & ~7;
892 pScrn->displayWidth = pScrn->virtualX;
893
894#ifdef VBOX_DRI
895 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
896#endif
897
898 /* I checked in the sources, and XFree86 4.2 does seem to support
899 this function for 32bpp. */
900 if (!fbScreenInit(pScreen, pVBox->base,
901 pScrn->virtualX, pScrn->virtualY,
902 pScrn->xDpi, pScrn->yDpi,
903 pScrn->displayWidth, pScrn->bitsPerPixel))
904 return (FALSE);
905
906 /* Fixup RGB ordering */
907 visual = pScreen->visuals + pScreen->numVisuals;
908 while (--visual >= pScreen->visuals) {
909 if ((visual->class | DynamicClass) == DirectColor) {
910 visual->offsetRed = pScrn->offset.red;
911 visual->offsetGreen = pScrn->offset.green;
912 visual->offsetBlue = pScrn->offset.blue;
913 visual->redMask = pScrn->mask.red;
914 visual->greenMask = pScrn->mask.green;
915 visual->blueMask = pScrn->mask.blue;
916 }
917 }
918
919 /* must be after RGB ordering fixed */
920 fbPictureInit(pScreen, 0, 0);
921
922 xf86SetBlackWhitePixels(pScreen);
923 miInitializeBackingStore(pScreen);
924 xf86SetBackingStore(pScreen);
925
926 /* We need to keep track of whether we are currently switched to a virtual
927 * terminal to know whether a mode set operation is currently safe to do.
928 */
929 pVBox->vtSwitch = FALSE;
930 /* Initialise DGA. The cast is unfortunately correct - it gets cast back
931 to (unsigned char *) later. */
932 xf86DiDGAInit(pScreen, (unsigned long) pVBox->base);
933
934 /* Initialise randr 1.2 mode-setting functions and set first mode. */
935 if (!xf86CrtcScreenInit(pScreen)) {
936 return FALSE;
937 }
938
939 if (!xf86SetDesiredModes(pScrn)) {
940 return FALSE;
941 }
942
943 /* software cursor */
944 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
945
946 /* colourmap code */
947 if (!miCreateDefColormap(pScreen))
948 return (FALSE);
949
950 flags = CMAP_RELOAD_ON_MODE_SWITCH;
951
952 if(!vgaHWHandleColormaps(pScreen))
953 return (FALSE);
954
955 /* Hook our observer function ito the chain which is called when
956 * framebuffer access is enabled or disabled in the server, and
957 * assume an initial state of enabled. */
958 pVBox->accessEnabled = TRUE;
959 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
960 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
961
962 pVBox->CloseScreen = pScreen->CloseScreen;
963 pScreen->CloseScreen = VBOXCloseScreen;
964 pScreen->SaveScreen = xf86SaveScreen;
965
966 /* We probably do want to support power management - even if we just use
967 a dummy function. */
968 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
969
970 /* Report any unused options (only for the first generation) */
971 if (serverGeneration == 1)
972 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
973
974 if (vbox_device_available(pVBox) && vbox_open (pScrn, pScreen, pVBox)) {
975 if (vbox_cursor_init(pScreen) != TRUE)
976 xf86DrvMsg(scrnIndex, X_ERROR,
977 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
978 if (vboxEnableVbva(pScrn) == TRUE)
979 xf86DrvMsg(scrnIndex, X_INFO,
980 "The VBox video extensions are now enabled.\n");
981 vboxEnableGraphicsCap(pVBox);
982 }
983
984#ifdef VBOX_DRI
985 if (pVBox->useDRI)
986 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
987#endif
988 return (TRUE);
989}
990
991static Bool
992VBOXEnterVT(int scrnIndex, int flags)
993{
994 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
995 VBOXPtr pVBox = VBOXGetRec(pScrn);
996 bool rc;
997
998 TRACE_ENTRY();
999 pVBox->vtSwitch = FALSE;
1000#ifdef VBOX_DRI
1001 if (pVBox->useDRI)
1002 DRIUnlock(screenInfo.screens[scrnIndex]);
1003#endif
1004 rc = xf86SetDesiredModes(pScrn);
1005 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1006 return rc;
1007}
1008
1009static void
1010VBOXLeaveVT(int scrnIndex, int flags)
1011{
1012 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1013 VBOXPtr pVBox = VBOXGetRec(pScrn);
1014
1015 TRACE_ENTRY();
1016 pVBox->vtSwitch = TRUE;
1017 VBOXSaveRestore(pScrn, MODE_RESTORE);
1018 if (vbox_device_available(pVBox))
1019 {
1020 if (pVBox->useVbva == TRUE)
1021 vboxDisableVbva(pScrn);
1022 vboxDisableGraphicsCap(pVBox);
1023 }
1024#ifdef VBOX_DRI
1025 if (pVBox->useDRI)
1026 DRILock(screenInfo.screens[scrnIndex], 0);
1027#endif
1028 TRACE_EXIT();
1029}
1030
1031static Bool
1032VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
1033{
1034 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1035 VBOXPtr pVBox = VBOXGetRec(pScrn);
1036
1037#ifdef VBOX_DRI
1038 if (pVBox->useDRI)
1039 VBOXDRICloseScreen(pScreen, pVBox);
1040 pVBox->useDRI = false;
1041#endif
1042
1043 if (vbox_device_available(pVBox))
1044 {
1045 if (TRUE == pVBox->useVbva)
1046 vboxDisableVbva(pScrn);
1047 vboxDisableGraphicsCap(pVBox);
1048 }
1049 if (pScrn->vtSema) {
1050 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
1051 if (pVBox->savedPal)
1052 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
1053 pVBox->savedPal, FALSE, TRUE);
1054 VBOXUnmapVidMem(pScrn);
1055 }
1056 pScrn->vtSema = FALSE;
1057
1058 /* Destroy the VGA hardware record */
1059 vgaHWFreeHWRec(pScrn);
1060
1061 /* Remove our observer functions from the X server call chains. */
1062 pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;
1063 pScreen->CloseScreen = pVBox->CloseScreen;
1064 return pScreen->CloseScreen(scrnIndex, pScreen);
1065}
1066
1067/**
1068 * Quoted from "How to add an (S)VGA driver to XFree86"
1069 * (http://www.xfree86.org/3.3.6/VGADriver.html):
1070 *
1071 * The ValidMode() function is required. It is used to check for any
1072 * chipset-dependent reasons why a graphics mode might not be valid. It gets
1073 * called by higher levels of the code after the Probe() stage. In many cases
1074 * no special checking will be required and this function will simply return
1075 * TRUE always.
1076 *
1077 * Note: we check here that our generated video modes fulfil the X server's
1078 * criteria for the monitor, since this can otherwise cause problems in
1079 * randr 1.2.
1080 */
1081static ModeStatus
1082VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
1083{
1084 static int warned = 0;
1085 ScrnInfoPtr pScrn = xf86Screens[scrn];
1086 MonPtr mon = pScrn->monitor;
1087 ModeStatus ret = MODE_BAD;
1088 DisplayModePtr mode;
1089 float v;
1090
1091 TRACE_LOG("HDisplay=%d, VDisplay=%d, flag=%s, pass=%d\n",
1092 p->HDisplay, p->VDisplay, flag ? "TRUE" : "FALSE", pass);
1093 if (pass != MODECHECK_FINAL) {
1094 if (!warned) {
1095 xf86DrvMsg(scrn, X_WARNING, "VBOXValidMode called unexpectedly\n");
1096 warned = 1;
1097 }
1098 }
1099#if 0
1100 /*
1101 * First off, if this isn't a mode we handed to the server (ie,
1102 * M_T_BUILTIN), then we reject it out of hand.
1103 */
1104 if (!(p->type & M_T_BUILTIN))
1105 return MODE_NOMODE;
1106#endif
1107 /*
1108 * Finally, walk through the vsync rates 1Hz at a time looking for a mode
1109 * that will fit. This is assuredly a terrible way to do this, but
1110 * there's no obvious method for computing a mode of a given size that
1111 * will pass xf86CheckModeForMonitor.
1112 */
1113 for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
1114 mode = xf86CVTMode(p->HDisplay, p->VDisplay, v, 0, 0);
1115 ret = xf86CheckModeForMonitor(mode, mon);
1116 xfree(mode);
1117 if (ret == MODE_OK)
1118 break;
1119 }
1120
1121 if (ret != MODE_OK)
1122 {
1123 xf86DrvMsg(scrn, X_WARNING, "Graphics mode %s rejected by the X server\n", p->name);
1124 }
1125 TRACE_LOG("returning %d\n", ret);
1126 return ret;
1127}
1128
1129static Bool
1130VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
1131{
1132 ScrnInfoPtr pScrn;
1133 VBOXPtr pVBox;
1134 Bool rc;
1135
1136 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1137 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
1138 pVBox = VBOXGetRec(pScrn);
1139 /* We want to disable access to the framebuffer before switching mode.
1140 * After doing the switch, we allow access if it was allowed before. */
1141 if (pVBox->accessEnabled)
1142 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
1143 rc = xf86SetSingleMode(pScrn, pMode, 0);
1144 if (pVBox->accessEnabled)
1145 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
1146 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1147 return rc;
1148}
1149
1150/* Set a graphics mode. Poke the required values into registers, enable
1151 guest-host acceleration functions and tell the host we support advanced
1152 graphics functions. */
1153static Bool
1154VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1155{
1156 VBOXPtr pVBox;
1157 Bool rc = TRUE;
1158
1159 int bpp = pScrn->depth == 24 ? 32 : 16;
1160 TRACE_LOG("HDisplay=%d, VDisplay=%d, displayWidth=%d\n",
1161 pMode->HDisplay, pMode->VDisplay, pScrn->displayWidth);
1162 pVBox = VBOXGetRec(pScrn);
1163 /* Don't fiddle with the hardware if we are switched
1164 * to a virtual terminal. */
1165 if (!pVBox->vtSwitch)
1166 {
1167 if ( vbox_device_available(pVBox)
1168 && (TRUE == pVBox->useVbva)
1169 && (vboxDisableVbva(pScrn) != TRUE)
1170 ) /* This would be bad. */
1171 rc = FALSE;
1172 if (rc)
1173 {
1174 /* Disable linear framebuffer mode before making changes to the resolution. */
1175 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
1176 outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
1177 /* Unlike the resolution, the depth is fixed for a given screen
1178 for the lifetime of the X session. */
1179 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
1180 outw(VBE_DISPI_IOPORT_DATA, bpp);
1181 /* HDisplay and VDisplay are actually monitor information about
1182 the display part of the scanlines. */
1183 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
1184 outw(VBE_DISPI_IOPORT_DATA, pMode->HDisplay);
1185 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
1186 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
1187 /* Set the virtual resolution. We are still using VESA to control
1188 the virtual offset. */
1189 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
1190 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
1191 /* Enable linear framebuffer mode. */
1192 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
1193 outw(VBE_DISPI_IOPORT_DATA,
1194 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
1195 /* Enable acceleration and tell the host we support graphics */
1196 if (vbox_device_available(pVBox))
1197 {
1198 if ((TRUE == pVBox->useVbva) && (vboxEnableVbva(pScrn) != TRUE))
1199 /* Bad but not fatal */
1200 pVBox->useVbva = FALSE;
1201 vboxEnableGraphicsCap(pVBox);
1202 }
1203 }
1204 }
1205 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1206 return rc;
1207}
1208
1209static void
1210VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
1211{
1212 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
1213 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1214
1215 TRACE_ENTRY();
1216 /* Don't fiddle with the hardware if we are switched
1217 * to a virtual terminal. */
1218 if (!pVBox->vtSwitch) {
1219 pVBox->viewportX = x;
1220 pVBox->viewportY = y;
1221 /* If VBVA is enabled the graphics card will not notice the change. */
1222 if (pVBox->useVbva == TRUE)
1223 vboxDisableVbva(pScrn);
1224 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
1225 if (pVBox->useVbva == TRUE)
1226 vboxEnableVbva(pScrn);
1227 }
1228 TRACE_EXIT();
1229}
1230
1231static void
1232VBOXFreeScreen(int scrnIndex, int flags)
1233{
1234 VBOXFreeRec(xf86Screens[scrnIndex]);
1235}
1236
1237static Bool
1238VBOXMapVidMem(ScrnInfoPtr pScrn)
1239{
1240 VBOXPtr pVBox = VBOXGetRec(pScrn);
1241 Bool rc = TRUE;
1242
1243 TRACE_ENTRY();
1244 if (!pVBox->base)
1245 {
1246 pScrn->memPhysBase = pVBox->mapPhys;
1247 pScrn->fbOffset = pVBox->mapOff;
1248
1249#ifdef PCIACCESS
1250 (void) pci_device_map_range(pVBox->pciInfo,
1251 pScrn->memPhysBase,
1252 pVBox->mapSize,
1253 PCI_DEV_MAP_FLAG_WRITABLE,
1254 & pVBox->base);
1255#else
1256 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1257 VIDMEM_FRAMEBUFFER,
1258 pVBox->pciTag, pVBox->mapPhys,
1259 (unsigned) pVBox->mapSize);
1260#endif
1261 if (pVBox->base)
1262 {
1263 /* We need this for saving/restoring textmode */
1264 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1265 rc = vgaHWMapMem(pScrn);
1266 }
1267 else
1268 rc = FALSE;
1269 }
1270 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1271 return rc;
1272}
1273
1274static void
1275VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1276{
1277 VBOXPtr pVBox = VBOXGetRec(pScrn);
1278
1279 TRACE_ENTRY();
1280 if (pVBox->base == NULL)
1281 return;
1282
1283#ifdef PCIACCESS
1284 (void) pci_device_unmap_range(pVBox->pciInfo,
1285 pVBox->base,
1286 pVBox->mapSize);
1287#else
1288 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1289 (unsigned) pVBox->mapSize);
1290#endif
1291 vgaHWUnmapMem(pScrn);
1292 pVBox->base = NULL;
1293 TRACE_EXIT();
1294}
1295
1296
1297Bool
1298VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1299{
1300 VBOXPtr pVBox;
1301 Bool rc = TRUE;
1302
1303 TRACE_ENTRY();
1304 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1305 rc = FALSE;
1306
1307 if (rc)
1308 {
1309 pVBox = VBOXGetRec(pScrn);
1310
1311 /* Query amount of memory to save state */
1312 if (function == MODE_QUERY ||
1313 (function == MODE_SAVE && pVBox->state == NULL))
1314 {
1315
1316 /* Make sure we save at least this information in case of failure */
1317 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1318 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1319
1320 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1321 &pVBox->stateSize,&pVBox->statePage)
1322 )
1323 rc = FALSE;
1324 }
1325 }
1326 if (rc)
1327 {
1328 /* Save/Restore Super VGA state */
1329 if (function != MODE_QUERY) {
1330
1331 if (function == MODE_RESTORE)
1332 memcpy(pVBox->state, pVBox->pstate,
1333 (unsigned) pVBox->stateSize);
1334
1335 if ( (rc = VBESaveRestore(pVBox->pVbe,function,
1336 (pointer)&pVBox->state,
1337 &pVBox->stateSize,&pVBox->statePage)
1338 )
1339 && (function == MODE_SAVE)
1340 )
1341 {
1342 /* don't rely on the memory not being touched */
1343 if (pVBox->pstate == NULL)
1344 pVBox->pstate = xalloc(pVBox->stateSize);
1345 memcpy(pVBox->pstate, pVBox->state,
1346 (unsigned) pVBox->stateSize);
1347 }
1348
1349 if (function == MODE_RESTORE)
1350 {
1351 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1352 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1353 }
1354 }
1355 }
1356 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1357 return rc;
1358}
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