~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/Additions/x11/vboxvideo/vboxvideo_15.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

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