~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

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