VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xgraphics/vboxvideo_70.c@ 3261

Last change on this file since 3261 was 3261, checked in by vboxsync, 18 years ago

export files

File size: 42.7 KB
Line 
1/** @file
2 *
3 * Linux Additions X11 graphics driver
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 *
21 * --------------------------------------------------------------------
22 *
23 * This code is based on:
24 *
25 * X11 VESA driver
26 *
27 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
28 *
29 * Permission is hereby granted, free of charge, to any person obtaining a
30 * copy of this software and associated documentation files (the "Software"),
31 * to deal in the Software without restriction, including without limitation
32 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
33 * and/or sell copies of the Software, and to permit persons to whom the
34 * Software is furnished to do so, subject to the following conditions:
35 *
36 * The above copyright notice and this permission notice shall be included in
37 * all copies or substantial portions of the Software.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
43 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
44 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
45 * SOFTWARE.
46 *
47 * Except as contained in this notice, the name of Conectiva Linux shall
48 * not be used in advertising or otherwise to promote the sale, use or other
49 * dealings in this Software without prior written authorization from
50 * Conectiva Linux.
51 *
52 * Authors: Paulo César Pereira de Andrade <[email protected]>
53 */
54
55#define DEBUG_VERB 2
56
57#ifdef XFree86LOADER
58# include "xorg-server.h"
59#else
60# ifdef HAVE_CONFIG_H
61# include "config.h"
62# endif
63#endif
64#include "vboxvideo.h"
65#include "version-generated.h"
66#include <xf86.h>
67
68/* All drivers initialising the SW cursor need this */
69#include "mipointer.h"
70
71/* All drivers implementing backing store need this */
72#include "mibstore.h"
73
74/* Colormap handling */
75#include "micmap.h"
76#include "xf86cmap.h"
77
78/* DPMS */
79/* #define DPMS_SERVER
80#include "extensions/dpms.h" */
81
82/* Mandatory functions */
83
84static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
85static void VBOXIdentify(int flags);
86static Bool VBOXProbe(DriverPtr drv, int flags);
87static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
88static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
89 char **argv);
90static Bool VBOXEnterVT(int scrnIndex, int flags);
91static void VBOXLeaveVT(int scrnIndex, int flags);
92static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
93static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
94static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
95static ModeStatus VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass);
96static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
97static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
98static void VBOXFreeScreen(int scrnIndex, int flags);
99static void VBOXFreeRec(ScrnInfoPtr pScrn);
100static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
101 int flags);
102
103/* locally used functions */
104static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
105static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
106static void VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors,
107 int *indices,
108 LOCO *colors, VisualPtr pVisual);
109static void SaveFonts(ScrnInfoPtr pScrn);
110static void RestoreFonts(ScrnInfoPtr pScrn);
111static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
112 vbeSaveRestoreFunction function);
113
114/* Initialise DGA */
115
116static Bool VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
117
118/*
119 * This contains the functions needed by the server after loading the
120 * driver module. It must be supplied, and gets added the driver list by
121 * the Module Setup funtion in the dynamic case. In the static case a
122 * reference to this is compiled in, and this requires that the name of
123 * this DriverRec be an upper-case version of the driver name.
124 */
125
126_X_EXPORT DriverRec VBOXDRV = {
127 VBOX_VERSION,
128 VBOX_DRIVER_NAME,
129 VBOXIdentify,
130 VBOXProbe,
131 VBOXAvailableOptions,
132 NULL,
133 0,
134 NULL
135};
136
137/* Supported chipsets */
138static SymTabRec VBOXChipsets[] =
139{
140 {VBOX_VESA_DEVICEID, "vbox"},
141 {-1, NULL}
142};
143
144static PciChipsets VBOXPCIchipsets[] = {
145 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
146 { -1, -1, RES_UNDEFINED },
147};
148
149typedef enum {
150 OPTION_SHADOW_FB,
151 OPTION_DFLT_REFRESH,
152 OPTION_MODESET_CLEAR_SCREEN
153} VBOXOpts;
154
155/* No options for now */
156static const OptionInfoRec VBOXOptions[] = {
157 { -1, NULL, OPTV_NONE, {0}, FALSE }
158};
159
160/*
161 * List of symbols from other modules that this module references. This
162 * list is used to tell the loader that it is OK for symbols here to be
163 * unresolved providing that it hasn't been told that they haven't been
164 * told that they are essential via a call to xf86LoaderReqSymbols() or
165 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
166 * unresolved symbols that are not required.
167 */
168static const char *fbSymbols[] = {
169 "fbPictureInit",
170 "fbScreenInit",
171 NULL
172};
173
174static const char *shadowfbSymbols[] = {
175 "ShadowFBInit2",
176 NULL
177};
178
179static const char *vbeSymbols[] = {
180 "VBEExtendedInit",
181 "VBEFindSupportedDepths",
182 "VBEGetModeInfo",
183 "VBEGetVBEInfo",
184 "VBEGetVBEMode",
185 "VBEPrintModes",
186 "VBESaveRestore",
187 "VBESetDisplayStart",
188 "VBESetGetDACPaletteFormat",
189 "VBESetGetLogicalScanlineLength",
190 "VBESetGetPaletteData",
191 "VBESetModeNames",
192 "VBESetModeParameters",
193 "VBESetVBEMode",
194 "VBEValidateModes",
195 "vbeDoEDID",
196 "vbeFree",
197 NULL
198};
199
200static const char *ramdacSymbols[] = {
201 "xf86InitCursor",
202 "xf86CreateCursorInfoRec",
203 NULL
204};
205
206#ifdef XFree86LOADER
207/* Module loader interface */
208static MODULESETUPPROTO(vboxSetup);
209
210static XF86ModuleVersionInfo vboxVersionRec =
211{
212 VBOX_DRIVER_NAME,
213 "innotek GmbH",
214 MODINFOSTRING1,
215 MODINFOSTRING2,
216 XORG_VERSION_CURRENT,
217 1, /* Module major version. Xorg-specific */
218 0, /* Module minor version. Xorg-specific */
219 1, /* Module patchlevel. Xorg-specific */
220 ABI_CLASS_VIDEODRV, /* This is a video driver */
221 ABI_VIDEODRV_VERSION,
222 MOD_CLASS_VIDEODRV,
223 {0, 0, 0, 0}
224};
225
226/*
227 * This data is accessed by the loader. The name must be the module name
228 * followed by "ModuleData".
229 */
230_X_EXPORT XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
231
232static pointer
233vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
234{
235 static Bool Initialised = FALSE;
236
237 if (!Initialised)
238 {
239 Initialised = TRUE;
240 xf86AddDriver(&VBOXDRV, Module, 0);
241 LoaderRefSymLists(fbSymbols,
242 shadowfbSymbols,
243 vbeSymbols,
244 ramdacSymbols,
245 NULL);
246 return (pointer)TRUE;
247 }
248
249 if (ErrorMajor)
250 *ErrorMajor = LDR_ONCEONLY;
251 return (NULL);
252}
253
254#endif /* XFree86Loader defined */
255
256static const OptionInfoRec *
257VBOXAvailableOptions(int chipid, int busid)
258{
259 return (VBOXOptions);
260}
261
262static void
263VBOXIdentify(int flags)
264{
265 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
266}
267
268/*
269 * This function is called once, at the start of the first server generation to
270 * do a minimal probe for supported hardware.
271 */
272
273static Bool
274VBOXProbe(DriverPtr drv, int flags)
275{
276 Bool foundScreen = FALSE;
277 int numDevSections, numUsed;
278 GDevPtr *devSections;
279 int *usedChips;
280 int i;
281
282 /*
283 * Find the config file Device sections that match this
284 * driver, and return if there are none.
285 */
286 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
287 &devSections)) <= 0)
288 return (FALSE);
289
290 /* PCI BUS */
291 if (xf86GetPciVideoInfo()) {
292 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
293 VBOXChipsets, VBOXPCIchipsets,
294 devSections, numDevSections,
295 drv, &usedChips);
296 if (numUsed > 0) {
297 if (flags & PROBE_DETECT)
298 foundScreen = TRUE;
299 else {
300 for (i = 0; i < numUsed; i++) {
301 ScrnInfoPtr pScrn = NULL;
302 /* Allocate a ScrnInfoRec */
303 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
304 VBOXPCIchipsets,NULL,
305 NULL,NULL,NULL,NULL))) {
306 pScrn->driverVersion = VBOX_VERSION;
307 pScrn->driverName = VBOX_DRIVER_NAME;
308 pScrn->name = VBOX_NAME;
309 pScrn->Probe = VBOXProbe;
310 pScrn->PreInit = VBOXPreInit;
311 pScrn->ScreenInit = VBOXScreenInit;
312 pScrn->SwitchMode = VBOXSwitchMode;
313 pScrn->ValidMode = VBOXValidMode;
314 pScrn->AdjustFrame = VBOXAdjustFrame;
315 pScrn->EnterVT = VBOXEnterVT;
316 pScrn->LeaveVT = VBOXLeaveVT;
317 pScrn->FreeScreen = VBOXFreeScreen;
318 foundScreen = TRUE;
319 }
320 }
321 }
322 xfree(usedChips);
323 }
324 }
325 xfree(devSections);
326
327 return (foundScreen);
328}
329
330static VBOXPtr
331VBOXGetRec(ScrnInfoPtr pScrn)
332{
333 if (!pScrn->driverPrivate)
334 {
335 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
336 ((VBOXPtr)pScrn->driverPrivate)->vbox_fd = -1;
337 }
338
339 return ((VBOXPtr)pScrn->driverPrivate);
340}
341
342static void
343VBOXFreeRec(ScrnInfoPtr pScrn)
344{
345 VBOXPtr pVBox = VBOXGetRec(pScrn);
346#if 0
347 xfree(pVBox->vbeInfo);
348#endif
349 xfree(pVBox->savedPal);
350 xfree(pVBox->fonts);
351 xfree(pScrn->driverPrivate);
352 pScrn->driverPrivate = NULL;
353}
354
355/*
356 * QUOTE from the XFree86 DESIGN document:
357 *
358 * The purpose of this function is to find out all the information
359 * required to determine if the configuration is usable, and to initialise
360 * those parts of the ScrnInfoRec that can be set once at the beginning of
361 * the first server generation.
362 *
363 * (...)
364 *
365 * This includes probing for video memory, clocks, ramdac, and all other
366 * HW info that is needed. It includes determining the depth/bpp/visual
367 * and related info. It includes validating and determining the set of
368 * video modes that will be used (and anything that is required to
369 * determine that).
370 *
371 * This information should be determined in the least intrusive way
372 * possible. The state of the HW must remain unchanged by this function.
373 * Although video memory (including MMIO) may be mapped within this
374 * function, it must be unmapped before returning.
375 *
376 * END QUOTE
377 */
378
379static Bool
380VBOXPreInit(ScrnInfoPtr pScrn, int flags)
381{
382 VBOXPtr pVBox;
383 Gamma gzeros = {0.0, 0.0, 0.0};
384 rgb rzeros = {0, 0, 0};
385 ClockRange *clockRanges;
386 int i;
387 DisplayModePtr m_prev;
388
389 /* Are we really starting the server, or is this just a dummy run? */
390 if (flags & PROBE_DETECT)
391 return (FALSE);
392
393 xf86Msg(X_INFO,
394 "VirtualBox guest additions video driver version "
395 VBOX_VERSION_STRING "\n");
396
397 /* Get our private data from the ScrnInfoRec structure. */
398 pVBox = VBOXGetRec(pScrn);
399
400 /* Entity information seems to mean bus information. */
401 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
402 if (pVBox->pEnt->location.type != BUS_PCI)
403 return FALSE;
404
405 /* The ramdac module is needed for the hardware cursor. */
406 if (!xf86LoadSubModule(pScrn, "ramdac"))
407 return FALSE;
408 xf86LoaderReqSymLists(ramdacSymbols, NULL);
409
410 /* We need the vbe module because we use VBE code to save and restore
411 text mode, in order to keep our code simple. */
412 if (!xf86LoadSubModule(pScrn, "vbe"))
413 return (FALSE);
414 xf86LoaderReqSymLists(vbeSymbols, NULL);
415
416 /* The framebuffer module. */
417 if (xf86LoadSubModule(pScrn, "fb") == NULL)
418 return (FALSE);
419 xf86LoaderReqSymLists(fbSymbols, NULL);
420
421 if (!xf86LoadSubModule(pScrn, "shadowfb"))
422 return FALSE;
423 xf86LoaderReqSymLists(shadowfbSymbols, NULL);
424
425 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
426 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
427 pVBox->pciInfo->device,
428 pVBox->pciInfo->func);
429
430 /* Set up our ScrnInfoRec structure to describe our virtual
431 capabilities to X. */
432
433 pScrn->rgbBits = 8;
434
435 /* Let's create a nice, capable virtual monitor. */
436 pScrn->monitor = pScrn->confScreen->monitor;
437 pScrn->monitor->DDC = NULL;
438 pScrn->monitor->nHsync = 1;
439 pScrn->monitor->hsync[0].lo = 1;
440 pScrn->monitor->hsync[0].hi = 10000;
441 pScrn->monitor->nVrefresh = 1;
442 pScrn->monitor->vrefresh[0].lo = 1;
443 pScrn->monitor->vrefresh[0].hi = 100;
444
445 pScrn->chipset = "vbox";
446 pScrn->progClock = TRUE;
447
448 /* Determine the size of the VBox video RAM from PCI data*/
449#if 0
450 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
451#endif
452 /* Using the PCI information caused problems with non-powers-of-two
453 sized video RAM configurations */
454 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
455
456 /* Set up clock information that will support all modes we need. */
457 clockRanges = xnfcalloc(sizeof(ClockRange), 1);
458 clockRanges->next = NULL;
459 clockRanges->minClock = 1000;
460 clockRanges->maxClock = 1000000000;
461 clockRanges->clockIndex = -1;
462 clockRanges->ClockMulFactor = 1;
463 clockRanges->ClockDivFactor = 1;
464
465 /* This function asks X to choose a depth and bpp based on the
466 config file and the command line, and gives a default in
467 case none is specified. Note that we only support 32bpp, not
468 24bpp. After spending ages looking through the XFree86 4.2
469 source code however, I realised that it automatically uses
470 32bpp for depth 24 unless you explicitly add a "24 24"
471 format to its internal list. */
472 if (!xf86SetDepthBpp(pScrn, pScrn->videoRam >= 2048 ? 24 : 16, 0, 0,
473 Support32bppFb))
474 return FALSE;
475 if (pScrn->depth != 24 && pScrn->depth != 16)
476 {
477 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
478 "The VBox additions only support 16 and 32bpp graphics modes\n");
479 return FALSE;
480 }
481 xf86PrintDepthBpp(pScrn);
482
483 /* Colour weight - we always call this, since we are always in
484 truecolour. */
485 if (!xf86SetWeight(pScrn, rzeros, rzeros))
486 return (FALSE);
487
488 /* visual init */
489 if (!xf86SetDefaultVisual(pScrn, -1))
490 return (FALSE);
491
492 xf86SetGamma(pScrn, gzeros);
493
494 /* To get around the problem of SUSE specifying a single, invalid mode in their
495 * Xorg.conf by default, we add an additional mode to the end of the user specified
496 * list. This means that if all user modes are invalid, X will try our mode before
497 * falling back to its standard mode list. */
498 if (pScrn->display->modes == NULL)
499 {
500 /* The user specified no modes at all - specify 1024x768 as a default. */
501 pScrn->display->modes = xnfalloc(2 * sizeof(char*));
502 pScrn->display->modes[0] = "1024x768";
503 pScrn->display->modes[1] = NULL;
504 }
505 else
506 {
507 /* Add 1024x768 to the end of the mode list in case the others are all invalid. */
508 for (i = 0; pScrn->display->modes[i] != NULL; i++);
509 pScrn->display->modes = xnfrealloc(pScrn->display->modes, (i + 2)
510 * sizeof(char *));
511 pScrn->display->modes[i ] = "1024x768";
512 pScrn->display->modes[i+1] = NULL;
513 }
514
515 /* Determine the virtual screen resolution from the first mode (which will be selected) */
516 sscanf(pScrn->display->modes[0], "%dx%d",
517 &pScrn->display->virtualX, &pScrn->display->virtualY);
518 pScrn->display->virtualX = (pScrn->display->virtualX + 7) & ~7;
519
520 /* Create a builtin mode for every specified mode. This allows to specify arbitrary
521 * screen resolutions */
522 m_prev = NULL;
523 for (i = 0; pScrn->display->modes[i] != NULL; i++)
524 {
525 DisplayModePtr m;
526 int x = 0, y = 0;
527
528 sscanf(pScrn->display->modes[i], "%dx%d", &x, &y);
529 /* sanity check, smaller resolutions does not make sense */
530 if (x < 64 || y < 64)
531 {
532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring mode \"%s\"\n",
533 pScrn->display->modes[i]);
534 continue;
535 }
536 m = xnfcalloc(sizeof(DisplayModeRec), 1);
537 m->status = MODE_OK;
538 m->type = M_T_BUILTIN;
539 /* VBox does only support screen widths which are a multiple of 8 */
540 m->HDisplay = (x + 7) & ~7;
541 m->HSyncStart = m->HDisplay + 2;
542 m->HSyncEnd = m->HDisplay + 4;
543 m->HTotal = m->HDisplay + 6;
544 m->VDisplay = y;
545 m->VSyncStart = m->VDisplay + 2;
546 m->VSyncEnd = m->VDisplay + 4;
547 m->VTotal = m->VDisplay + 6;
548 m->Clock = m->HTotal * m->VTotal * 60 / 1000000;
549 m->name = strdup(pScrn->display->modes[i]);
550 if (!m_prev)
551 pScrn->modePool = m;
552 else
553 m_prev->next = m;
554 m->prev = m_prev;
555 m_prev = m;
556 }
557
558 /* Filter out video modes not supported by the virtual hardware
559 we described. All modes used by the Windows additions should
560 work fine. */
561 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
562 pScrn->display->modes,
563 clockRanges, NULL, 0, 6400, 1, 0, 1440,
564 pScrn->display->virtualX,
565 pScrn->display->virtualY,
566 pScrn->videoRam, LOOKUP_BEST_REFRESH);
567
568 if (i <= 0) {
569 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
570 return (FALSE);
571 }
572 xf86PruneDriverModes(pScrn);
573
574 pScrn->currentMode = pScrn->modes;
575 pScrn->displayWidth = pScrn->virtualX;
576
577 xf86PrintModes(pScrn);
578
579 /* Set display resolution. This was arbitrarily chosen to be about the same as my monitor. */
580 xf86SetDpi(pScrn, 100, 100);
581
582 if (pScrn->modes == NULL) {
583 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
584 return (FALSE);
585 }
586
587 /* options */
588 xf86CollectOptions(pScrn, NULL);
589 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
590 return FALSE;
591 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
592 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
593
594 /* Framebuffer-related setup */
595 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
596 return (TRUE);
597}
598
599/*
600 * QUOTE from the XFree86 DESIGN document:
601 *
602 * This is called at the start of each server generation.
603 *
604 * (...)
605 *
606 * Decide which operations need to be placed under resource access
607 * control. (...) Map any video memory or other memory regions. (...)
608 * Save the video card state. (...) Initialise the initial video
609 * mode.
610 *
611 * End QUOTE.Initialise the initial video mode.
612 */
613static Bool
614VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
615{
616 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
617 VBOXPtr pVBox = VBOXGetRec(pScrn);
618 VisualPtr visual;
619 unsigned flags;
620
621 /* We make use of the X11 VBE code to save and restore text mode, in
622 order to keep our code simple. */
623 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
624 SET_BIOS_SCRATCH
625 | RESTORE_BIOS_SCRATCH)) == NULL)
626 return (FALSE);
627
628 if (pVBox->mapPhys == 0) {
629 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
630/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
631 /* Using the PCI information caused problems with
632 non-powers-of-two sized video RAM configurations */
633 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
634 pVBox->mapOff = 0;
635 }
636
637 if (!VBOXMapVidMem(pScrn))
638 return (FALSE);
639
640 /* save current video state */
641 VBOXSaveRestore(pScrn, MODE_SAVE);
642 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
643 NULL, FALSE, FALSE);
644
645 /* set first video mode */
646 if (!VBOXSetMode(pScrn, pScrn->currentMode))
647 return FALSE;
648
649 /* set the viewport */
650 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
651
652 /* Blank the screen for aesthetic reasons. */
653 VBOXSaveScreen(pScreen, SCREEN_SAVER_ON);
654
655 /* mi layer - reset the visual list (?)*/
656 miClearVisualTypes();
657 if (!xf86SetDefaultVisual(pScrn, -1))
658 return (FALSE);
659 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
660 pScrn->rgbBits, TrueColor))
661 return (FALSE);
662 if (!miSetPixmapDepths())
663 return (FALSE);
664
665 /* I checked in the sources, and XFree86 4.2 does seem to support
666 this function for 32bpp. */
667 if (!fbScreenInit(pScreen, pVBox->base,
668 pScrn->virtualX, pScrn->virtualY,
669 pScrn->xDpi, pScrn->yDpi,
670 pScrn->displayWidth, pScrn->bitsPerPixel))
671 return (FALSE);
672
673 /* Fixup RGB ordering */
674 visual = pScreen->visuals + pScreen->numVisuals;
675 while (--visual >= pScreen->visuals) {
676 if ((visual->class | DynamicClass) == DirectColor) {
677 visual->offsetRed = pScrn->offset.red;
678 visual->offsetGreen = pScrn->offset.green;
679 visual->offsetBlue = pScrn->offset.blue;
680 visual->redMask = pScrn->mask.red;
681 visual->greenMask = pScrn->mask.green;
682 visual->blueMask = pScrn->mask.blue;
683 }
684 }
685
686 /* must be after RGB ordering fixed */
687 fbPictureInit(pScreen, 0, 0);
688
689 VBOXDGAInit(pScrn, pScreen);
690
691 xf86SetBlackWhitePixels(pScreen);
692 miInitializeBackingStore(pScreen);
693 xf86SetBackingStore(pScreen);
694
695 /* software cursor */
696 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
697
698 /* colourmap code - apparently, we need this even in Truecolour */
699 if (!miCreateDefColormap(pScreen))
700 return (FALSE);
701
702 flags = CMAP_RELOAD_ON_MODE_SWITCH;
703
704 if(!xf86HandleColormaps(pScreen, 256,
705 8 /* DAC is switchable to 8 bits per primary color */,
706 VBOXLoadPalette, NULL, flags))
707 return (FALSE);
708
709 pVBox->CloseScreen = pScreen->CloseScreen;
710 pScreen->CloseScreen = VBOXCloseScreen;
711 pScreen->SaveScreen = VBOXSaveScreen;
712
713 /* However, we probably do want to support power management -
714 even if we just use a dummy function. */
715 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
716
717 /* Report any unused options (only for the first generation) */
718 if (serverGeneration == 1)
719 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
720
721 if (vbox_open (pScrn, pScreen, pVBox)) {
722 if (vbox_cursor_init(pScreen) != TRUE)
723 xf86DrvMsg(scrnIndex, X_ERROR,
724 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
725 if (vboxEnableVbva(pScrn) == TRUE)
726 xf86DrvMsg(scrnIndex, X_INFO,
727 "The VBox video extensions are now enabled.\n");
728 } else
729 xf86DrvMsg(scrnIndex, X_ERROR, "Failed to open the VBox system device - make sure that the VirtualBox guest additions are properly installed. If you are not sure, try reinstalling them.\n");
730 return (TRUE);
731}
732
733static Bool
734VBOXEnterVT(int scrnIndex, int flags)
735{
736 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
737 VBOXPtr pVBox = VBOXGetRec(pScrn);
738
739 if (!VBOXSetMode(pScrn, pScrn->currentMode))
740 return FALSE;
741 VBOXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
742 if (pVBox->useVbva == TRUE)
743 vboxEnableVbva(pScrn);
744 return TRUE;
745}
746
747static void
748VBOXLeaveVT(int scrnIndex, int flags)
749{
750 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
751 VBOXPtr pVBox = VBOXGetRec(pScrn);
752
753 VBOXSaveRestore(pScrn, MODE_RESTORE);
754 if (pVBox->useVbva == TRUE)
755 vboxDisableVbva(pScrn);
756}
757
758static Bool
759VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
760{
761 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
762 VBOXPtr pVBox = VBOXGetRec(pScrn);
763
764 if (pVBox->useVbva == TRUE)
765 vboxDisableVbva(pScrn);
766 if (pScrn->vtSema) {
767 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
768 if (pVBox->savedPal)
769 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
770 pVBox->savedPal, FALSE, TRUE);
771 VBOXUnmapVidMem(pScrn);
772 }
773 if (pVBox->pDGAMode) {
774 xfree(pVBox->pDGAMode);
775 pVBox->pDGAMode = NULL;
776 pVBox->nDGAMode = 0;
777 }
778 pScrn->vtSema = FALSE;
779
780 pScreen->CloseScreen = pVBox->CloseScreen;
781 return pScreen->CloseScreen(scrnIndex, pScreen);
782}
783
784/**
785 * Quoted from "How to add an (S)VGA driver to XFree86"
786 * (http://www.xfree86.org/3.3.6/VGADriver.html):
787 *
788 * The ValidMode() function is required. It is used to check for any
789 * chipset-dependent reasons why a graphics mode might not be valid. It gets
790 * called by higher levels of the code after the Probe() stage. In many cases
791 * no special checking will be required and this function will simply return
792 * TRUE always.
793 *
794 * Note: we check here that our generated video modes fulfil the X server's
795 * criteria for the monitor, since this can otherwise cause problems in
796 * randr 1.2.
797 */
798static ModeStatus
799VBOXValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
800{
801 static int warned = 0;
802 ScrnInfoPtr pScrn = xf86Screens[scrn];
803 MonPtr mon = pScrn->monitor;
804 ModeStatus ret;
805 DisplayModePtr mode;
806 float v;
807
808 if (pass != MODECHECK_FINAL) {
809 if (!warned) {
810 xf86DrvMsg(scrn, X_WARNING, "VBOXValidMode called unexpectedly\n");
811 warned = 1;
812 }
813 }
814 /*
815 * First off, if this isn't a mode we handed to the server (ie,
816 * M_T_BUILTIN), then we reject it out of hand.
817 */
818 if (!(p->type & M_T_BUILTIN))
819 return MODE_NOMODE;
820 /*
821 * Finally, walk through the vsync rates 1Hz at a time looking for a mode
822 * that will fit. This is assuredly a terrible way to do this, but
823 * there's no obvious method for computing a mode of a given size that
824 * will pass xf86CheckModeForMonitor.
825 */
826 for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
827 mode = xf86CVTMode(p->HDisplay, p->VDisplay, v, 0, 0);
828 ret = xf86CheckModeForMonitor(mode, mon);
829 xfree(mode);
830 if (ret == MODE_OK)
831 break;
832 }
833
834 if (ret != MODE_OK)
835 {
836 xf86DrvMsg(scrn, X_WARNING, "Graphics mode %s rejected by the X server\n", p->name);
837 }
838 return ret;
839}
840
841static Bool
842VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
843{
844 ScrnInfoPtr pScrn;
845 VBOXPtr pVBox;
846
847 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
848 pVBox = VBOXGetRec(pScrn);
849 if (pVBox->useVbva == TRUE)
850 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
851 return FALSE;
852 if (VBOXSetMode(pScrn, pMode) != TRUE)
853 return FALSE;
854 if (pVBox->useVbva == TRUE)
855 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
856 pVBox->useVbva = FALSE;
857 return TRUE;
858}
859
860/* Set a graphics mode */
861static Bool
862VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
863{
864 VBOXPtr pVBox;
865
866 int bpp = pScrn->depth == 24 ? 32 : 16;
867 int xRes = pMode->HDisplay;
868 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
869 >= pScrn->videoRam * 1024)
870 {
871 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
872 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
873 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
874 return FALSE;
875 }
876 /* We only support horizontal resolutions which are a multiple of 8. Round down if
877 necessary. */
878 if (xRes % 8 != 0)
879 {
880 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
881 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
882 xRes, xRes - (xRes % 8));
883 xRes = xRes - (xRes % 8);
884 }
885 pVBox = VBOXGetRec(pScrn);
886 pScrn->vtSema = TRUE;
887 /* Disable linear framebuffer mode before making changes to the resolution. */
888 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
889 outw(VBE_DISPI_IOPORT_DATA,
890 VBE_DISPI_DISABLED);
891 /* Unlike the resolution, the depth is fixed for a given screen
892 for the lifetime of the X session. */
893 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
894 outw(VBE_DISPI_IOPORT_DATA, bpp);
895 /* HDisplay and VDisplay are actually monitor information about
896 the display part of the scanlines. */
897 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
898 outw(VBE_DISPI_IOPORT_DATA, xRes);
899 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
900 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
901 /* Enable linear framebuffer mode. */
902 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
903 outw(VBE_DISPI_IOPORT_DATA,
904 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
905 /* Set the virtual resolution. We are still using VESA to control
906 the virtual offset. */
907 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
908 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
909 return (TRUE);
910}
911
912static void
913VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
914{
915 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
916
917 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
918}
919
920static void
921VBOXFreeScreen(int scrnIndex, int flags)
922{
923 VBOXFreeRec(xf86Screens[scrnIndex]);
924}
925
926static Bool
927VBOXMapVidMem(ScrnInfoPtr pScrn)
928{
929 VBOXPtr pVBox = VBOXGetRec(pScrn);
930
931 if (pVBox->base != NULL)
932 return (TRUE);
933
934 pScrn->memPhysBase = pVBox->mapPhys;
935 pScrn->fbOffset = pVBox->mapOff;
936
937 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
938 VIDMEM_FRAMEBUFFER,
939 pVBox->pciTag, pVBox->mapPhys,
940 (unsigned) pVBox->mapSize);
941
942 if (pVBox->base) {
943 pScrn->memPhysBase = pVBox->mapPhys;
944 pVBox->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
945 pVBox->pciTag,
946 0xa0000, 0x10000);
947 }
948 /* We need this for saving/restoring textmode */
949 pVBox->ioBase = pScrn->domainIOBase;
950
951 return (pVBox->base != NULL);
952}
953
954static void
955VBOXUnmapVidMem(ScrnInfoPtr pScrn)
956{
957 VBOXPtr pVBox = VBOXGetRec(pScrn);
958
959 if (pVBox->base == NULL)
960 return;
961
962 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
963 (unsigned) pVBox->mapSize);
964 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
965 pVBox->base = NULL;
966}
967
968static void
969VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
970 LOCO *colors, VisualPtr pVisual)
971{
972 VBOXPtr pVBox = VBOXGetRec(pScrn);
973 int i, idx;
974#define VBOXDACDelay() \
975 do { \
976 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
977 (void)inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
978 } while (0)
979
980 for (i = 0; i < numColors; i++) {
981 idx = indices[i];
982 outb(pVBox->ioBase + VGA_DAC_WRITE_ADDR, idx);
983 VBOXDACDelay();
984 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].red);
985 VBOXDACDelay();
986 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].green);
987 VBOXDACDelay();
988 outb(pVBox->ioBase + VGA_DAC_DATA, colors[idx].blue);
989 VBOXDACDelay();
990 }
991}
992
993/*
994 * Just adapted from the std* functions in vgaHW.c
995 */
996static void
997WriteAttr(VBOXPtr pVBox, int index, int value)
998{
999 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1000
1001 index |= 0x20;
1002 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1003 outb(pVBox->ioBase + VGA_ATTR_DATA_W, value);
1004}
1005
1006static int
1007ReadAttr(VBOXPtr pVBox, int index)
1008{
1009 (void) inb(pVBox->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1010
1011 index |= 0x20;
1012 outb(pVBox->ioBase + VGA_ATTR_INDEX, index);
1013 return (inb(pVBox->ioBase + VGA_ATTR_DATA_R));
1014}
1015
1016#define WriteMiscOut(value) outb(pVBox->ioBase + VGA_MISC_OUT_W, value)
1017#define ReadMiscOut() inb(pVBox->ioBase + VGA_MISC_OUT_R)
1018#define WriteSeq(index, value) \
1019 outb(pVBox->ioBase + VGA_SEQ_INDEX, (index));\
1020 outb(pVBox->ioBase + VGA_SEQ_DATA, value)
1021
1022static int
1023ReadSeq(VBOXPtr pVBox, int index)
1024{
1025 outb(pVBox->ioBase + VGA_SEQ_INDEX, index);
1026
1027 return (inb(pVBox->ioBase + VGA_SEQ_DATA));
1028}
1029
1030#define WriteGr(index, value) \
1031 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index); \
1032 outb(pVBox->ioBase + VGA_GRAPH_DATA, value)
1033
1034static int
1035ReadGr(VBOXPtr pVBox, int index)
1036{
1037 outb(pVBox->ioBase + VGA_GRAPH_INDEX, index);
1038
1039 return (inb(pVBox->ioBase + VGA_GRAPH_DATA));
1040}
1041
1042#define WriteCrtc(index, value) \
1043 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1044 outb(pVBox->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1045
1046static void
1047SeqReset(VBOXPtr pVBox, Bool start)
1048{
1049 if (start) {
1050 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1051 }
1052 else {
1053 WriteSeq(0x00, 0x03); /* End Reset */
1054 }
1055}
1056
1057static void
1058SaveFonts(ScrnInfoPtr pScrn)
1059{
1060 VBOXPtr pVBox = VBOXGetRec(pScrn);
1061 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1062
1063 if (pVBox->fonts != NULL)
1064 return;
1065
1066 /* If in graphics mode, don't save anything */
1067 attr10 = ReadAttr(pVBox, 0x10);
1068 if (attr10 & 0x01)
1069 return;
1070
1071 pVBox->fonts = xalloc(16384);
1072
1073 /* save the registers that are needed here */
1074 miscOut = ReadMiscOut();
1075 gr4 = ReadGr(pVBox, 0x04);
1076 gr5 = ReadGr(pVBox, 0x05);
1077 gr6 = ReadGr(pVBox, 0x06);
1078 seq2 = ReadSeq(pVBox, 0x02);
1079 seq4 = ReadSeq(pVBox, 0x04);
1080
1081 /* Force into colour mode */
1082 WriteMiscOut(miscOut | 0x01);
1083
1084 scrn = ReadSeq(pVBox, 0x01) | 0x20;
1085 SeqReset(pVBox, TRUE);
1086 WriteSeq(0x01, scrn);
1087 SeqReset(pVBox, FALSE);
1088
1089 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1090
1091 /*font1 */
1092 WriteSeq(0x02, 0x04); /* write to plane 2 */
1093 WriteSeq(0x04, 0x06); /* enable plane graphics */
1094 WriteGr(0x04, 0x02); /* read plane 2 */
1095 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1096 WriteGr(0x06, 0x05); /* set graphics */
1097 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1098
1099 /* font2 */
1100 WriteSeq(0x02, 0x08); /* write to plane 3 */
1101 WriteSeq(0x04, 0x06); /* enable plane graphics */
1102 WriteGr(0x04, 0x03); /* read plane 3 */
1103 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1104 WriteGr(0x06, 0x05); /* set graphics */
1105 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1106
1107 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1108 SeqReset(pVBox, TRUE);
1109 WriteSeq(0x01, scrn);
1110 SeqReset(pVBox, FALSE);
1111
1112 /* Restore clobbered registers */
1113 WriteAttr(pVBox, 0x10, attr10);
1114 WriteSeq(0x02, seq2);
1115 WriteSeq(0x04, seq4);
1116 WriteGr(0x04, gr4);
1117 WriteGr(0x05, gr5);
1118 WriteGr(0x06, gr6);
1119 WriteMiscOut(miscOut);
1120}
1121
1122static void
1123RestoreFonts(ScrnInfoPtr pScrn)
1124{
1125 VBOXPtr pVBox = VBOXGetRec(pScrn);
1126 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1127
1128 if (pVBox->fonts == NULL)
1129 return;
1130
1131 /* save the registers that are needed here */
1132 miscOut = ReadMiscOut();
1133 attr10 = ReadAttr(pVBox, 0x10);
1134 gr1 = ReadGr(pVBox, 0x01);
1135 gr3 = ReadGr(pVBox, 0x03);
1136 gr4 = ReadGr(pVBox, 0x04);
1137 gr5 = ReadGr(pVBox, 0x05);
1138 gr6 = ReadGr(pVBox, 0x06);
1139 gr8 = ReadGr(pVBox, 0x08);
1140 seq2 = ReadSeq(pVBox, 0x02);
1141 seq4 = ReadSeq(pVBox, 0x04);
1142
1143 /* Force into colour mode */
1144 WriteMiscOut(miscOut | 0x01);
1145
1146 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1147 SeqReset(pVBox, TRUE);
1148 WriteSeq(0x01, scrn);
1149 SeqReset(pVBox, FALSE);
1150
1151 WriteAttr(pVBox, 0x10, 0x01); /* graphics mode */
1152 if (pScrn->depth == 4) {
1153 /* GJA */
1154 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1155 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1156 WriteGr(0x01, 0x00); /* all planes come from CPU */
1157 }
1158
1159 WriteSeq(0x02, 0x04); /* write to plane 2 */
1160 WriteSeq(0x04, 0x06); /* enable plane graphics */
1161 WriteGr(0x04, 0x02); /* read plane 2 */
1162 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1163 WriteGr(0x06, 0x05); /* set graphics */
1164 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1165
1166 WriteSeq(0x02, 0x08); /* write to plane 3 */
1167 WriteSeq(0x04, 0x06); /* enable plane graphics */
1168 WriteGr(0x04, 0x03); /* read plane 3 */
1169 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1170 WriteGr(0x06, 0x05); /* set graphics */
1171 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1172
1173 scrn = ReadSeq(pVBox, 0x01) & ~0x20;
1174 SeqReset(pVBox, TRUE);
1175 WriteSeq(0x01, scrn);
1176 SeqReset(pVBox, FALSE);
1177
1178 /* restore the registers that were changed */
1179 WriteMiscOut(miscOut);
1180 WriteAttr(pVBox, 0x10, attr10);
1181 WriteGr(0x01, gr1);
1182 WriteGr(0x03, gr3);
1183 WriteGr(0x04, gr4);
1184 WriteGr(0x05, gr5);
1185 WriteGr(0x06, gr6);
1186 WriteGr(0x08, gr8);
1187 WriteSeq(0x02, seq2);
1188 WriteSeq(0x04, seq4);
1189}
1190
1191static Bool
1192VBOXSaveScreen(ScreenPtr pScreen, int mode)
1193{
1194 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1195 VBOXPtr pVBox = VBOXGetRec(pScrn);
1196 Bool on = xf86IsUnblank(mode);
1197
1198 if (on)
1199 SetTimeSinceLastInputEvent();
1200
1201 if (pScrn->vtSema) {
1202 unsigned char scrn = ReadSeq(pVBox, 0x01);
1203
1204 if (on)
1205 scrn &= ~0x20;
1206 else
1207 scrn |= 0x20;
1208 SeqReset(pVBox, TRUE);
1209 WriteSeq(0x01, scrn);
1210 SeqReset(pVBox, FALSE);
1211 }
1212
1213 return (TRUE);
1214}
1215
1216Bool
1217VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1218{
1219 VBOXPtr pVBox;
1220
1221 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1222 return (FALSE);
1223
1224 pVBox = VBOXGetRec(pScrn);
1225
1226
1227 /* Query amount of memory to save state */
1228 if (function == MODE_QUERY ||
1229 (function == MODE_SAVE && pVBox->state == NULL))
1230 {
1231
1232 /* Make sure we save at least this information in case of failure */
1233 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1234 SaveFonts(pScrn);
1235
1236 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1237 &pVBox->stateSize,&pVBox->statePage))
1238 return FALSE;
1239 }
1240
1241 /* Save/Restore Super VGA state */
1242 if (function != MODE_QUERY) {
1243 Bool retval = TRUE;
1244
1245 if (function == MODE_RESTORE)
1246 memcpy(pVBox->state, pVBox->pstate,
1247 (unsigned) pVBox->stateSize);
1248
1249 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1250 (pointer)&pVBox->state,
1251 &pVBox->stateSize,&pVBox->statePage))
1252 && function == MODE_SAVE)
1253 {
1254 /* don't rely on the memory not being touched */
1255 if (pVBox->pstate == NULL)
1256 pVBox->pstate = xalloc(pVBox->stateSize);
1257 memcpy(pVBox->pstate, pVBox->state,
1258 (unsigned) pVBox->stateSize);
1259 }
1260
1261 if (function == MODE_RESTORE)
1262 {
1263 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1264 RestoreFonts(pScrn);
1265 }
1266
1267 if (!retval)
1268 return (FALSE);
1269
1270 }
1271
1272 return (TRUE);
1273}
1274
1275static void
1276VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1277 int flags)
1278{
1279 /* VBox is always power efficient... */
1280}
1281
1282
1283
1284
1285/***********************************************************************
1286 * DGA stuff
1287 ***********************************************************************/
1288static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1289 unsigned char **ApertureBase,
1290 int *ApertureSize, int *ApertureOffset,
1291 int *flags);
1292static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1293static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1294
1295static Bool
1296VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1297 unsigned char **ApertureBase, int *ApertureSize,
1298 int *ApertureOffset, int *flags)
1299{
1300 VBOXPtr pVBox = VBOXGetRec(pScrn);
1301
1302 *DeviceName = NULL; /* No special device */
1303 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1304 *ApertureSize = pVBox->mapSize;
1305 *ApertureOffset = pVBox->mapOff;
1306 *flags = DGA_NEED_ROOT;
1307
1308 return (TRUE);
1309}
1310
1311static Bool
1312VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1313{
1314 DisplayModePtr pMode;
1315 int scrnIdx = pScrn->pScreen->myNum;
1316 int frameX0, frameY0;
1317
1318 if (pDGAMode) {
1319 pMode = pDGAMode->mode;
1320 frameX0 = frameY0 = 0;
1321 }
1322 else {
1323 if (!(pMode = pScrn->currentMode))
1324 return (TRUE);
1325
1326 frameX0 = pScrn->frameX0;
1327 frameY0 = pScrn->frameY0;
1328 }
1329
1330 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1331 return (FALSE);
1332 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1333
1334 return (TRUE);
1335}
1336
1337static void
1338VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1339{
1340 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1341}
1342
1343static int
1344VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1345{
1346 return (0);
1347}
1348
1349static DGAFunctionRec VBOXDGAFunctions =
1350{
1351 VBOXDGAOpenFramebuffer,
1352 NULL, /* CloseFramebuffer */
1353 VBOXDGASetMode,
1354 VBOXDGASetViewport,
1355 VBOXDGAGetViewport,
1356 NULL, /* Sync */
1357 NULL, /* FillRect */
1358 NULL, /* BlitRect */
1359 NULL, /* BlitTransRect */
1360};
1361
1362static void
1363VBOXDGAAddModes(ScrnInfoPtr pScrn)
1364{
1365 VBOXPtr pVBox = VBOXGetRec(pScrn);
1366 DisplayModePtr pMode = pScrn->modes;
1367 DGAModePtr pDGAMode;
1368
1369 do {
1370 pDGAMode = xrealloc(pVBox->pDGAMode,
1371 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1372 if (!pDGAMode)
1373 break;
1374
1375 pVBox->pDGAMode = pDGAMode;
1376 pDGAMode += pVBox->nDGAMode;
1377 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1378
1379 ++pVBox->nDGAMode;
1380 pDGAMode->mode = pMode;
1381 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1382 pDGAMode->byteOrder = pScrn->imageByteOrder;
1383 pDGAMode->depth = pScrn->depth;
1384 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1385 pDGAMode->red_mask = pScrn->mask.red;
1386 pDGAMode->green_mask = pScrn->mask.green;
1387 pDGAMode->blue_mask = pScrn->mask.blue;
1388 pDGAMode->visualClass = TrueColor;
1389 pDGAMode->xViewportStep = 1;
1390 pDGAMode->yViewportStep = 1;
1391 pDGAMode->viewportWidth = pMode->HDisplay;
1392 pDGAMode->viewportHeight = pMode->VDisplay;
1393
1394 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1395 pDGAMode->imageWidth = pMode->HDisplay;
1396 pDGAMode->imageHeight = pMode->VDisplay;
1397 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1398 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1399 pDGAMode->maxViewportX = pScrn->virtualX -
1400 pDGAMode->viewportWidth;
1401 pDGAMode->maxViewportY = pScrn->virtualY -
1402 pDGAMode->viewportHeight;
1403
1404 pDGAMode->address = pVBox->base;
1405
1406 pMode = pMode->next;
1407 } while (pMode != pScrn->modes);
1408}
1409
1410static Bool
1411VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1412{
1413 VBOXPtr pVBox = VBOXGetRec(pScrn);
1414
1415 if (!pVBox->nDGAMode)
1416 VBOXDGAAddModes(pScrn);
1417
1418 return (DGAInit(pScreen, &VBOXDGAFunctions,
1419 pVBox->pDGAMode, pVBox->nDGAMode));
1420}
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