1/*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * Authors: Dirk Hohndel <hohndel@XFree86.Org>
30 *          David Dawes <dawes@XFree86.Org>
31 *          ... and others
32 *
33 * This file includes the helper functions that the server provides for
34 * different drivers.
35 */
36
37#ifdef HAVE_XORG_CONFIG_H
38#include <xorg-config.h>
39#endif
40
41#include <X11/X.h>
42#include "mi.h"
43#include "os.h"
44#include "servermd.h"
45#include "pixmapstr.h"
46#include "windowstr.h"
47#include "propertyst.h"
48#include "gcstruct.h"
49#include "loaderProcs.h"
50#include "xf86.h"
51#include "xf86Priv.h"
52#include "xf86_OSlib.h"
53#include "micmap.h"
54#include "xf86DDC.h"
55#include "xf86Xinput.h"
56#include "xf86InPriv.h"
57#include "mivalidate.h"
58
59/* For xf86GetClocks */
60#if defined(CSRG_BASED) || defined(__GNU__)
61#define HAS_SETPRIORITY
62#include <sys/resource.h>
63#endif
64
65static int xf86ScrnInfoPrivateCount = 0;
66
67/* Add a pointer to a new DriverRec to xf86DriverList */
68
69void
70xf86AddDriver(DriverPtr driver, void *module, int flags)
71{
72    /* Don't add null entries */
73    if (!driver)
74        return;
75
76    if (xf86DriverList == NULL)
77        xf86NumDrivers = 0;
78
79    xf86NumDrivers++;
80    xf86DriverList = xnfreallocarray(xf86DriverList,
81                                     xf86NumDrivers, sizeof(DriverPtr));
82    xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec));
83    *xf86DriverList[xf86NumDrivers - 1] = *driver;
84    xf86DriverList[xf86NumDrivers - 1]->module = module;
85    xf86DriverList[xf86NumDrivers - 1]->refCount = 0;
86}
87
88void
89xf86DeleteDriver(int drvIndex)
90{
91    if (xf86DriverList[drvIndex]
92        && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) {
93        if (xf86DriverList[drvIndex]->module)
94            UnloadModule(xf86DriverList[drvIndex]->module);
95        free(xf86DriverList[drvIndex]);
96        xf86DriverList[drvIndex] = NULL;
97    }
98}
99
100/* Add a pointer to a new InputDriverRec to xf86InputDriverList */
101
102void
103xf86AddInputDriver(InputDriverPtr driver, void *module, int flags)
104{
105    /* Don't add null entries */
106    if (!driver)
107        return;
108
109    if (xf86InputDriverList == NULL)
110        xf86NumInputDrivers = 0;
111
112    xf86NumInputDrivers++;
113    xf86InputDriverList = xnfreallocarray(xf86InputDriverList,
114                                          xf86NumInputDrivers,
115                                          sizeof(InputDriverPtr));
116    xf86InputDriverList[xf86NumInputDrivers - 1] =
117        xnfalloc(sizeof(InputDriverRec));
118    *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver;
119    xf86InputDriverList[xf86NumInputDrivers - 1]->module = module;
120}
121
122void
123xf86DeleteInputDriver(int drvIndex)
124{
125    if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module)
126        UnloadModule(xf86InputDriverList[drvIndex]->module);
127    free(xf86InputDriverList[drvIndex]);
128    xf86InputDriverList[drvIndex] = NULL;
129}
130
131InputDriverPtr
132xf86LookupInputDriver(const char *name)
133{
134    int i;
135
136    for (i = 0; i < xf86NumInputDrivers; i++) {
137        if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName &&
138            xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0)
139            return xf86InputDriverList[i];
140    }
141    return NULL;
142}
143
144InputInfoPtr
145xf86LookupInput(const char *name)
146{
147    InputInfoPtr p;
148
149    for (p = xf86InputDevs; p != NULL; p = p->next) {
150        if (strcmp(name, p->name) == 0)
151            return p;
152    }
153
154    return NULL;
155}
156
157/* Allocate a new ScrnInfoRec in xf86Screens */
158
159ScrnInfoPtr
160xf86AllocateScreen(DriverPtr drv, int flags)
161{
162    int i;
163    ScrnInfoPtr pScrn;
164
165    if (flags & XF86_ALLOCATE_GPU_SCREEN) {
166        if (xf86GPUScreens == NULL)
167            xf86NumGPUScreens = 0;
168        i = xf86NumGPUScreens++;
169        xf86GPUScreens = xnfreallocarray(xf86GPUScreens, xf86NumGPUScreens,
170                                         sizeof(ScrnInfoPtr));
171        xf86GPUScreens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
172        pScrn = xf86GPUScreens[i];
173        pScrn->scrnIndex = i + GPU_SCREEN_OFFSET;      /* Changes when a screen is removed */
174        pScrn->is_gpu = TRUE;
175    } else {
176        if (xf86Screens == NULL)
177            xf86NumScreens = 0;
178
179        i = xf86NumScreens++;
180        xf86Screens = xnfreallocarray(xf86Screens, xf86NumScreens,
181                                      sizeof(ScrnInfoPtr));
182        xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
183        pScrn = xf86Screens[i];
184
185        pScrn->scrnIndex = i;      /* Changes when a screen is removed */
186    }
187
188    pScrn->origIndex = pScrn->scrnIndex;      /* This never changes */
189    pScrn->privates = xnfcalloc(sizeof(DevUnion), xf86ScrnInfoPrivateCount);
190    /*
191     * EnableDisableFBAccess now gets initialized in InitOutput()
192     * pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
193     */
194
195    pScrn->drv = drv;
196    drv->refCount++;
197    pScrn->module = DuplicateModule(drv->module, NULL);
198
199    pScrn->DriverFunc = drv->driverFunc;
200
201    return pScrn;
202}
203
204/*
205 * Remove an entry from xf86Screens.  Ideally it should free all allocated
206 * data.  To do this properly may require a driver hook.
207 */
208
209void
210xf86DeleteScreen(ScrnInfoPtr pScrn)
211{
212    int i;
213    int scrnIndex;
214    Bool is_gpu = FALSE;
215
216    if (!pScrn)
217        return;
218
219    if (pScrn->is_gpu) {
220        /* First check if the screen is valid */
221        if (xf86NumGPUScreens == 0 || xf86GPUScreens == NULL)
222            return;
223        is_gpu = TRUE;
224    } else {
225        /* First check if the screen is valid */
226        if (xf86NumScreens == 0 || xf86Screens == NULL)
227            return;
228    }
229
230    scrnIndex = pScrn->scrnIndex;
231    /* If a FreeScreen function is defined, call it here */
232    if (pScrn->FreeScreen != NULL)
233        pScrn->FreeScreen(pScrn);
234
235    while (pScrn->modes)
236        xf86DeleteMode(&pScrn->modes, pScrn->modes);
237
238    while (pScrn->modePool)
239        xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
240
241    xf86OptionListFree(pScrn->options);
242
243    if (pScrn->module)
244        UnloadModule(pScrn->module);
245
246    if (pScrn->drv)
247        pScrn->drv->refCount--;
248
249    free(pScrn->privates);
250
251    xf86ClearEntityListForScreen(pScrn);
252
253    free(pScrn);
254
255    /* Move the other entries down, updating their scrnIndex fields */
256
257    if (is_gpu) {
258        xf86NumGPUScreens--;
259        scrnIndex -= GPU_SCREEN_OFFSET;
260        for (i = scrnIndex; i < xf86NumGPUScreens; i++) {
261            xf86GPUScreens[i] = xf86GPUScreens[i + 1];
262            xf86GPUScreens[i]->scrnIndex = i + GPU_SCREEN_OFFSET;
263            /* Also need to take care of the screen layout settings */
264        }
265    }
266    else {
267        xf86NumScreens--;
268
269        for (i = scrnIndex; i < xf86NumScreens; i++) {
270            xf86Screens[i] = xf86Screens[i + 1];
271            xf86Screens[i]->scrnIndex = i;
272            /* Also need to take care of the screen layout settings */
273        }
274    }
275}
276
277/*
278 * Allocate a private in ScrnInfoRec.
279 */
280
281int
282xf86AllocateScrnInfoPrivateIndex(void)
283{
284    int idx, i;
285    ScrnInfoPtr pScr;
286    DevUnion *nprivs;
287
288    idx = xf86ScrnInfoPrivateCount++;
289    for (i = 0; i < xf86NumScreens; i++) {
290        pScr = xf86Screens[i];
291        nprivs = xnfreallocarray(pScr->privates,
292                                 xf86ScrnInfoPrivateCount, sizeof(DevUnion));
293        /* Zero the new private */
294        memset(&nprivs[idx], 0, sizeof(DevUnion));
295        pScr->privates = nprivs;
296    }
297    for (i = 0; i < xf86NumGPUScreens; i++) {
298        pScr = xf86GPUScreens[i];
299        nprivs = xnfreallocarray(pScr->privates,
300                                 xf86ScrnInfoPrivateCount, sizeof(DevUnion));
301        /* Zero the new private */
302        memset(&nprivs[idx], 0, sizeof(DevUnion));
303        pScr->privates = nprivs;
304    }
305    return idx;
306}
307
308Bool
309xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad)
310{
311    int i;
312
313    if (pScrn->numFormats >= MAXFORMATS)
314        return FALSE;
315
316    if (bpp <= 0) {
317        if (depth == 1)
318            bpp = 1;
319        else if (depth <= 8)
320            bpp = 8;
321        else if (depth <= 16)
322            bpp = 16;
323        else if (depth <= 32)
324            bpp = 32;
325        else
326            return FALSE;
327    }
328    if (pad <= 0)
329        pad = BITMAP_SCANLINE_PAD;
330
331    i = pScrn->numFormats++;
332    pScrn->formats[i].depth = depth;
333    pScrn->formats[i].bitsPerPixel = bpp;
334    pScrn->formats[i].scanlinePad = pad;
335    return TRUE;
336}
337
338/*
339 * Set the depth we are using based on (in the following order of preference):
340 *  - values given on the command line
341 *  - values given in the config file
342 *  - values provided by the driver
343 *  - an overall default when nothing else is given
344 *
345 * Also find a Display subsection matching the depth/bpp found.
346 *
347 * Sets the following ScrnInfoRec fields:
348 *     bitsPerPixel, depth, display, imageByteOrder,
349 *     bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats,
350 *     formats, fbFormat.
351 */
352
353/* Can the screen handle 32 bpp pixmaps */
354#define DO_PIX32(f) ((f & Support32bppFb) || \
355		     ((f & Support24bppFb) && (f & SupportConvert32to24)))
356
357#ifndef GLOBAL_DEFAULT_DEPTH
358#define GLOBAL_DEFAULT_DEPTH 24
359#endif
360
361Bool
362xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp,
363                int depth24flags)
364{
365    int i;
366    DispPtr disp;
367
368    scrp->bitsPerPixel = -1;
369    scrp->depth = -1;
370    scrp->bitsPerPixelFrom = X_DEFAULT;
371    scrp->depthFrom = X_DEFAULT;
372
373    if (xf86FbBpp > 0) {
374        if (xf86FbBpp == 24) /* lol no */
375            xf86FbBpp = 32;
376        scrp->bitsPerPixel = xf86FbBpp;
377        scrp->bitsPerPixelFrom = X_CMDLINE;
378    }
379
380    if (xf86Depth > 0) {
381        scrp->depth = xf86Depth;
382        scrp->depthFrom = X_CMDLINE;
383    }
384
385    if (xf86FbBpp < 0 && xf86Depth < 0) {
386        if (scrp->confScreen->defaultfbbpp > 0) {
387            scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp;
388            scrp->bitsPerPixelFrom = X_CONFIG;
389        }
390        if (scrp->confScreen->defaultdepth > 0) {
391            scrp->depth = scrp->confScreen->defaultdepth;
392            scrp->depthFrom = X_CONFIG;
393        }
394
395        if (scrp->confScreen->defaultfbbpp <= 0 &&
396            scrp->confScreen->defaultdepth <= 0) {
397            /*
398             * Check for DefaultDepth and DefaultFbBpp options in the
399             * Device sections.
400             */
401            GDevPtr device;
402            Bool found = FALSE;
403
404            for (i = 0; i < scrp->numEntities; i++) {
405                device = xf86GetDevFromEntity(scrp->entityList[i],
406                                              scrp->entityInstanceList[i]);
407                if (device && device->options) {
408                    if (xf86FindOption(device->options, "DefaultDepth")) {
409                        scrp->depth = xf86SetIntOption(device->options,
410                                                       "DefaultDepth", -1);
411                        scrp->depthFrom = X_CONFIG;
412                        found = TRUE;
413                    }
414                    if (xf86FindOption(device->options, "DefaultFbBpp")) {
415                        scrp->bitsPerPixel = xf86SetIntOption(device->options,
416                                                              "DefaultFbBpp",
417                                                              -1);
418                        scrp->bitsPerPixelFrom = X_CONFIG;
419                        found = TRUE;
420                    }
421                }
422                if (found)
423                    break;
424            }
425        }
426    }
427
428    /* If none of these is set, pick a default */
429    if (scrp->bitsPerPixel < 0 && scrp->depth < 0) {
430        if (fbbpp > 0 || depth > 0) {
431            if (fbbpp > 0)
432                scrp->bitsPerPixel = fbbpp;
433            if (depth > 0)
434                scrp->depth = depth;
435        }
436        else {
437            scrp->depth = GLOBAL_DEFAULT_DEPTH;
438        }
439    }
440
441    /* If any are not given, determine a default for the others */
442
443    if (scrp->bitsPerPixel < 0) {
444        /* The depth must be set */
445        if (scrp->depth > -1) {
446            if (scrp->depth == 1)
447                scrp->bitsPerPixel = 1;
448            else if (scrp->depth <= 4)
449                scrp->bitsPerPixel = 4;
450            else if (scrp->depth <= 8)
451                scrp->bitsPerPixel = 8;
452            else if (scrp->depth <= 16)
453                scrp->bitsPerPixel = 16;
454            else if (scrp->depth <= 24 && DO_PIX32(depth24flags)) {
455                scrp->bitsPerPixel = 32;
456            }
457            else if (scrp->depth <= 32)
458                scrp->bitsPerPixel = 32;
459            else {
460                xf86DrvMsg(scrp->scrnIndex, X_ERROR,
461                           "No bpp for depth (%d)\n", scrp->depth);
462                return FALSE;
463            }
464        }
465        else {
466            xf86DrvMsg(scrp->scrnIndex, X_ERROR,
467                       "xf86SetDepthBpp: internal error: depth and fbbpp"
468                       " are both not set\n");
469            return FALSE;
470        }
471        if (scrp->bitsPerPixel < 0) {
472            if ((depth24flags & (Support24bppFb | Support32bppFb)) ==
473                     NoDepth24Support)
474                xf86DrvMsg(scrp->scrnIndex, X_ERROR,
475                           "Driver can't support depth 24\n");
476            else
477                xf86DrvMsg(scrp->scrnIndex, X_ERROR,
478                           "Can't find fbbpp for depth 24\n");
479            return FALSE;
480        }
481        scrp->bitsPerPixelFrom = X_PROBED;
482    }
483
484    if (scrp->depth <= 0) {
485        /* bitsPerPixel is already set */
486        switch (scrp->bitsPerPixel) {
487        case 32:
488            scrp->depth = 24;
489            break;
490        default:
491            /* 1, 4, 8, 16 and 24 */
492            scrp->depth = scrp->bitsPerPixel;
493            break;
494        }
495        scrp->depthFrom = X_PROBED;
496    }
497
498    /* Sanity checks */
499    if (scrp->depth < 1 || scrp->depth > 32) {
500        xf86DrvMsg(scrp->scrnIndex, X_ERROR,
501                   "Specified depth (%d) is not in the range 1-32\n",
502                   scrp->depth);
503        return FALSE;
504    }
505    switch (scrp->bitsPerPixel) {
506    case 1:
507    case 4:
508    case 8:
509    case 16:
510    case 32:
511        break;
512    default:
513        xf86DrvMsg(scrp->scrnIndex, X_ERROR,
514                   "Specified fbbpp (%d) is not a permitted value\n",
515                   scrp->bitsPerPixel);
516        return FALSE;
517    }
518    if (scrp->depth > scrp->bitsPerPixel) {
519        xf86DrvMsg(scrp->scrnIndex, X_ERROR,
520                   "Specified depth (%d) is greater than the fbbpp (%d)\n",
521                   scrp->depth, scrp->bitsPerPixel);
522        return FALSE;
523    }
524
525    /*
526     * Find the Display subsection matching the depth/fbbpp and initialise
527     * scrp->display with it.
528     */
529    for (i = 0; i < scrp->confScreen->numdisplays; i++) {
530        disp = scrp->confScreen->displays[i];
531        if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel)
532            || (disp->depth == scrp->depth && disp->fbbpp <= 0)
533            || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) {
534            scrp->display = disp;
535            break;
536        }
537    }
538
539    /*
540     * If an exact match can't be found, see if there is one with no
541     * depth or fbbpp specified.
542     */
543    if (i == scrp->confScreen->numdisplays) {
544        for (i = 0; i < scrp->confScreen->numdisplays; i++) {
545            disp = scrp->confScreen->displays[i];
546            if (disp->depth <= 0 && disp->fbbpp <= 0) {
547                scrp->display = disp;
548                break;
549            }
550        }
551    }
552
553    /*
554     * If all else fails, create a default one.
555     */
556    if (i == scrp->confScreen->numdisplays) {
557        scrp->confScreen->numdisplays++;
558        scrp->confScreen->displays =
559            xnfreallocarray(scrp->confScreen->displays,
560                            scrp->confScreen->numdisplays, sizeof(DispPtr));
561        xf86DrvMsg(scrp->scrnIndex, X_INFO,
562                   "Creating default Display subsection in Screen section\n"
563                   "\t\"%s\" for depth/fbbpp %d/%d\n",
564                   scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel);
565        scrp->confScreen->displays[i] = xnfcalloc(1, sizeof(DispRec));
566        memset(scrp->confScreen->displays[i], 0, sizeof(DispRec));
567        scrp->confScreen->displays[i]->blackColour.red = -1;
568        scrp->confScreen->displays[i]->blackColour.green = -1;
569        scrp->confScreen->displays[i]->blackColour.blue = -1;
570        scrp->confScreen->displays[i]->whiteColour.red = -1;
571        scrp->confScreen->displays[i]->whiteColour.green = -1;
572        scrp->confScreen->displays[i]->whiteColour.blue = -1;
573        scrp->confScreen->displays[i]->defaultVisual = -1;
574        scrp->confScreen->displays[i]->modes = xnfalloc(sizeof(char *));
575        scrp->confScreen->displays[i]->modes[0] = NULL;
576        scrp->confScreen->displays[i]->depth = depth;
577        scrp->confScreen->displays[i]->fbbpp = fbbpp;
578        scrp->display = scrp->confScreen->displays[i];
579    }
580
581    /*
582     * Setup defaults for the display-wide attributes the framebuffer will
583     * need.  These defaults should eventually be set globally, and not
584     * dependent on the screens.
585     */
586    scrp->imageByteOrder = IMAGE_BYTE_ORDER;
587    scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
588    if (scrp->depth < 8) {
589        /* Planar modes need these settings */
590        scrp->bitmapScanlineUnit = 8;
591        scrp->bitmapBitOrder = MSBFirst;
592    }
593    else {
594        scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
595        scrp->bitmapBitOrder = BITMAP_BIT_ORDER;
596    }
597
598    /*
599     * If an unusual depth is required, add it to scrp->formats.  The formats
600     * for the common depths are handled globally in InitOutput
601     */
602    switch (scrp->depth) {
603    case 1:
604    case 4:
605    case 8:
606    case 15:
607    case 16:
608    case 24:
609        /* Common depths.  Nothing to do for them */
610        break;
611    default:
612        if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) {
613            xf86DrvMsg(scrp->scrnIndex, X_ERROR,
614                       "Can't add pixmap format for depth %d\n", scrp->depth);
615            return FALSE;
616        }
617    }
618
619    /* Initialise the framebuffer format for this screen */
620    scrp->fbFormat.depth = scrp->depth;
621    scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel;
622    scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD;
623
624    return TRUE;
625}
626
627/*
628 * Print out the selected depth and bpp.
629 */
630void
631xf86PrintDepthBpp(ScrnInfoPtr scrp)
632{
633    xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth);
634    xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel);
635}
636
637/*
638 * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths
639 * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits.
640 */
641Bool
642xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)
643{
644    MessageType weightFrom = X_DEFAULT;
645
646    scrp->weight.red = 0;
647    scrp->weight.green = 0;
648    scrp->weight.blue = 0;
649
650    if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) {
651        scrp->weight = xf86Weight;
652        weightFrom = X_CMDLINE;
653    }
654    else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0
655             && scrp->display->weight.blue > 0) {
656        scrp->weight = scrp->display->weight;
657        weightFrom = X_CONFIG;
658    }
659    else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) {
660        scrp->weight = weight;
661    }
662    else {
663        switch (scrp->depth) {
664        case 1:
665        case 4:
666        case 8:
667            scrp->weight.red = scrp->weight.green =
668                scrp->weight.blue = scrp->rgbBits;
669            break;
670        case 15:
671            scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5;
672            break;
673        case 16:
674            scrp->weight.red = scrp->weight.blue = 5;
675            scrp->weight.green = 6;
676            break;
677        case 18:
678            scrp->weight.red = scrp->weight.green = scrp->weight.blue = 6;
679            break;
680        case 24:
681            scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8;
682            break;
683        case 30:
684            scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10;
685            break;
686        }
687    }
688
689    if (scrp->weight.red)
690        xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n",
691                   (int) scrp->weight.red, (int) scrp->weight.green,
692                   (int) scrp->weight.blue);
693
694    if (scrp->depth > MAX_PSEUDO_DEPTH &&
695        (scrp->depth != scrp->weight.red + scrp->weight.green +
696         scrp->weight.blue)) {
697        xf86DrvMsg(scrp->scrnIndex, X_ERROR,
698                   "Weight given (%d%d%d) is inconsistent with the "
699                   "depth (%d)\n",
700                   (int) scrp->weight.red, (int) scrp->weight.green,
701                   (int) scrp->weight.blue, scrp->depth);
702        return FALSE;
703    }
704    if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) {
705        /*
706         * XXX Does this even mean anything for TrueColor visuals?
707         * If not, we shouldn't even be setting it here.  However, this
708         * matches the behaviour of 3.x versions of XFree86.
709         */
710        scrp->rgbBits = scrp->weight.red;
711        if (scrp->weight.green > scrp->rgbBits)
712            scrp->rgbBits = scrp->weight.green;
713        if (scrp->weight.blue > scrp->rgbBits)
714            scrp->rgbBits = scrp->weight.blue;
715    }
716
717    /* Set the mask and offsets */
718    if (mask.red == 0 || mask.green == 0 || mask.blue == 0) {
719        /* Default to a setting common to PC hardware */
720        scrp->offset.red = scrp->weight.green + scrp->weight.blue;
721        scrp->offset.green = scrp->weight.blue;
722        scrp->offset.blue = 0;
723        scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red;
724        scrp->mask.green = ((1 << scrp->weight.green) - 1)
725            << scrp->offset.green;
726        scrp->mask.blue = (1 << scrp->weight.blue) - 1;
727    }
728    else {
729        /* Initialise to the values passed */
730        scrp->mask.red = mask.red;
731        scrp->mask.green = mask.green;
732        scrp->mask.blue = mask.blue;
733        scrp->offset.red = ffs(mask.red) - 1;
734        scrp->offset.green = ffs(mask.green) - 1;
735        scrp->offset.blue = ffs(mask.blue) - 1;
736    }
737    return TRUE;
738}
739
740Bool
741xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)
742{
743    MessageType visualFrom = X_DEFAULT;
744
745    if (defaultColorVisualClass >= 0) {
746        scrp->defaultVisual = defaultColorVisualClass;
747        visualFrom = X_CMDLINE;
748    }
749    else if (scrp->display->defaultVisual >= 0) {
750        scrp->defaultVisual = scrp->display->defaultVisual;
751        visualFrom = X_CONFIG;
752    }
753    else if (visual >= 0) {
754        scrp->defaultVisual = visual;
755    }
756    else {
757        if (scrp->depth == 1)
758            scrp->defaultVisual = StaticGray;
759        else if (scrp->depth == 4)
760            scrp->defaultVisual = StaticColor;
761        else if (scrp->depth <= MAX_PSEUDO_DEPTH)
762            scrp->defaultVisual = PseudoColor;
763        else
764            scrp->defaultVisual = TrueColor;
765    }
766    switch (scrp->defaultVisual) {
767    case StaticGray:
768    case GrayScale:
769    case StaticColor:
770    case PseudoColor:
771    case TrueColor:
772    case DirectColor:
773        xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n",
774                   xf86VisualNames[scrp->defaultVisual]);
775        return TRUE;
776    default:
777
778        xf86DrvMsg(scrp->scrnIndex, X_ERROR,
779                   "Invalid default visual class (%d)\n", scrp->defaultVisual);
780        return FALSE;
781    }
782}
783
784#define TEST_GAMMA(g) \
785	(g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO
786
787#define SET_GAMMA(g) \
788	(g) > GAMMA_ZERO ? (g) : 1.0
789
790Bool
791xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)
792{
793    MessageType from = X_DEFAULT;
794
795#if 0
796    xf86MonPtr DDC = (xf86MonPtr) (scrp->monitor->DDC);
797#endif
798    if (TEST_GAMMA(xf86Gamma)) {
799        from = X_CMDLINE;
800        scrp->gamma.red = SET_GAMMA(xf86Gamma.red);
801        scrp->gamma.green = SET_GAMMA(xf86Gamma.green);
802        scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue);
803    }
804    else if (TEST_GAMMA(scrp->monitor->gamma)) {
805        from = X_CONFIG;
806        scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red);
807        scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green);
808        scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue);
809#if 0
810    }
811    else if (DDC && DDC->features.gamma > GAMMA_ZERO) {
812        from = X_PROBED;
813        scrp->gamma.red = SET_GAMMA(DDC->features.gamma);
814        scrp->gamma.green = SET_GAMMA(DDC->features.gamma);
815        scrp->gamma.blue = SET_GAMMA(DDC->features.gamma);
816        /* EDID structure version 2 gives optional separate red, green & blue
817         * gamma values in bytes 0x57-0x59 */
818#endif
819    }
820    else if (TEST_GAMMA(gamma)) {
821        scrp->gamma.red = SET_GAMMA(gamma.red);
822        scrp->gamma.green = SET_GAMMA(gamma.green);
823        scrp->gamma.blue = SET_GAMMA(gamma.blue);
824    }
825    else {
826        scrp->gamma.red = 1.0;
827        scrp->gamma.green = 1.0;
828        scrp->gamma.blue = 1.0;
829    }
830
831    xf86DrvMsg(scrp->scrnIndex, from,
832               "Using gamma correction (%.1f, %.1f, %.1f)\n",
833               scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue);
834
835    return TRUE;
836}
837
838#undef TEST_GAMMA
839#undef SET_GAMMA
840
841/*
842 * Set the DPI from the command line option.  XXX should allow it to be
843 * calculated from the widthmm/heightmm values.
844 */
845
846#undef MMPERINCH
847#define MMPERINCH 25.4
848
849void
850xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)
851{
852    MessageType from = X_DEFAULT;
853    xf86MonPtr DDC = (xf86MonPtr) (pScrn->monitor->DDC);
854    int ddcWidthmm, ddcHeightmm;
855    int widthErr, heightErr;
856
857    /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */
858    pScrn->widthmm = pScrn->monitor->widthmm;
859    pScrn->heightmm = pScrn->monitor->heightmm;
860
861    if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0)) {
862        /* DDC gives display size in mm for individual modes,
863         * but cm for monitor
864         */
865        ddcWidthmm = DDC->features.hsize * 10;  /* 10mm in 1cm */
866        ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */
867    }
868    else {
869        ddcWidthmm = ddcHeightmm = 0;
870    }
871
872    if (monitorResolution > 0) {
873        pScrn->xDpi = monitorResolution;
874        pScrn->yDpi = monitorResolution;
875        from = X_CMDLINE;
876    }
877    else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) {
878        from = X_CONFIG;
879        if (pScrn->widthmm > 0) {
880            pScrn->xDpi =
881                (int) ((double) pScrn->virtualX * MMPERINCH / pScrn->widthmm);
882        }
883        if (pScrn->heightmm > 0) {
884            pScrn->yDpi =
885                (int) ((double) pScrn->virtualY * MMPERINCH / pScrn->heightmm);
886        }
887        if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
888            pScrn->yDpi = pScrn->xDpi;
889        if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
890            pScrn->xDpi = pScrn->yDpi;
891        xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
892                   pScrn->widthmm, pScrn->heightmm);
893
894        /* Warn if config and probe disagree about display size */
895        if (ddcWidthmm && ddcHeightmm) {
896            if (pScrn->widthmm > 0) {
897                widthErr = abs(ddcWidthmm - pScrn->widthmm);
898            }
899            else {
900                widthErr = 0;
901            }
902            if (pScrn->heightmm > 0) {
903                heightErr = abs(ddcHeightmm - pScrn->heightmm);
904            }
905            else {
906                heightErr = 0;
907            }
908            if (widthErr > 10 || heightErr > 10) {
909                /* Should include config file name for monitor here */
910                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
911                           "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n",
912                           ddcWidthmm, ddcHeightmm, pScrn->widthmm,
913                           pScrn->heightmm);
914            }
915        }
916    }
917    else if (ddcWidthmm && ddcHeightmm) {
918        from = X_PROBED;
919        xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
920                   ddcWidthmm, ddcHeightmm);
921        pScrn->widthmm = ddcWidthmm;
922        pScrn->heightmm = ddcHeightmm;
923        if (pScrn->widthmm > 0) {
924            pScrn->xDpi =
925                (int) ((double) pScrn->virtualX * MMPERINCH / pScrn->widthmm);
926        }
927        if (pScrn->heightmm > 0) {
928            pScrn->yDpi =
929                (int) ((double) pScrn->virtualY * MMPERINCH / pScrn->heightmm);
930        }
931        if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
932            pScrn->yDpi = pScrn->xDpi;
933        if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
934            pScrn->xDpi = pScrn->yDpi;
935    }
936    else {
937        if (x > 0)
938            pScrn->xDpi = x;
939        else
940            pScrn->xDpi = DEFAULT_DPI;
941        if (y > 0)
942            pScrn->yDpi = y;
943        else
944            pScrn->yDpi = DEFAULT_DPI;
945    }
946    xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n",
947               pScrn->xDpi, pScrn->yDpi);
948}
949
950#undef MMPERINCH
951
952void
953xf86SetBlackWhitePixels(ScreenPtr pScreen)
954{
955    if (xf86FlipPixels) {
956        pScreen->whitePixel = 0;
957        pScreen->blackPixel = 1;
958    }
959    else {
960        pScreen->whitePixel = 1;
961        pScreen->blackPixel = 0;
962    }
963}
964
965/*
966 * Function to enable/disable access to the frame buffer
967 *
968 * This is used when VT switching and when entering/leaving DGA direct mode.
969 *
970 * This has been rewritten again to eliminate the saved pixmap.  The
971 * devPrivate field in the screen pixmap is set to NULL to catch code
972 * accidentally referencing the frame buffer while the X server is not
973 * supposed to touch it.
974 *
975 * Here, we exchange the pixmap private data, rather than the pixmaps
976 * themselves to avoid having to find and change any references to the screen
977 * pixmap such as GC's, window privates etc.  This also means that this code
978 * does not need to know exactly how the pixmap pixels are accessed.  Further,
979 * this exchange is >not< done through the screen's ModifyPixmapHeader()
980 * vector.  This means the called frame buffer code layers can determine
981 * whether they are switched in or out by keeping track of the root pixmap's
982 * private data, and therefore don't need to access pScrnInfo->vtSema.
983 */
984void
985xf86EnableDisableFBAccess(ScrnInfoPtr pScrnInfo, Bool enable)
986{
987    ScreenPtr pScreen = pScrnInfo->pScreen;
988
989    if (enable) {
990        /*
991         * Restore all of the clip lists on the screen
992         */
993        if (!xf86Resetting)
994            SetRootClip(pScreen, ROOT_CLIP_FULL);
995
996    }
997    else {
998        /*
999         * Empty all of the clip lists on the screen
1000         */
1001        SetRootClip(pScreen, ROOT_CLIP_NONE);
1002    }
1003}
1004
1005/* Print driver messages in the standard format of
1006   (<type>) <screen name>(<screen index>): <message> */
1007void
1008xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1009                va_list args)
1010{
1011    /* Prefix the scrnIndex name to the format string. */
1012    if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
1013        xf86Screens[scrnIndex]->name)
1014        LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
1015                          xf86Screens[scrnIndex]->name, scrnIndex);
1016    else if (scrnIndex >= GPU_SCREEN_OFFSET &&
1017             scrnIndex < GPU_SCREEN_OFFSET + xf86NumGPUScreens &&
1018             xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name)
1019        LogHdrMessageVerb(type, verb, format, args, "%s(G%d): ",
1020                          xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name, scrnIndex - GPU_SCREEN_OFFSET);
1021    else
1022        LogVMessageVerb(type, verb, format, args);
1023}
1024
1025/* Print driver messages, with verbose level specified directly */
1026void
1027xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1028               ...)
1029{
1030    va_list ap;
1031
1032    va_start(ap, format);
1033    xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap);
1034    va_end(ap);
1035}
1036
1037/* Print driver messages, with verbose level of 1 (default) */
1038void
1039xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
1040{
1041    va_list ap;
1042
1043    va_start(ap, format);
1044    xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap);
1045    va_end(ap);
1046}
1047
1048/* Print input driver messages in the standard format of
1049   (<type>) <driver>: <device name>: <message> */
1050void
1051xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb,
1052                 const char *format, va_list args)
1053{
1054    const char *driverName = NULL;
1055    const char *deviceName = NULL;
1056
1057    /* Prefix driver and device names to formatted message. */
1058    if (dev) {
1059        deviceName = dev->name;
1060        if (dev->drv)
1061            driverName = dev->drv->driverName;
1062    }
1063
1064    LogHdrMessageVerb(type, verb, format, args, "%s: %s: ", driverName,
1065                      deviceName);
1066}
1067
1068/* Print input driver message, with verbose level specified directly */
1069void
1070xf86IDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb,
1071                const char *format, ...)
1072{
1073    va_list ap;
1074
1075    va_start(ap, format);
1076    xf86VIDrvMsgVerb(dev, type, verb, format, ap);
1077    va_end(ap);
1078}
1079
1080/* Print input driver messages, with verbose level of 1 (default) */
1081void
1082xf86IDrvMsg(InputInfoPtr dev, MessageType type, const char *format, ...)
1083{
1084    va_list ap;
1085
1086    va_start(ap, format);
1087    xf86VIDrvMsgVerb(dev, type, 1, format, ap);
1088    va_end(ap);
1089}
1090
1091/* Print non-driver messages with verbose level specified directly */
1092void
1093xf86MsgVerb(MessageType type, int verb, const char *format, ...)
1094{
1095    va_list ap;
1096
1097    va_start(ap, format);
1098    LogVMessageVerb(type, verb, format, ap);
1099    va_end(ap);
1100}
1101
1102/* Print non-driver messages with verbose level of 1 (default) */
1103void
1104xf86Msg(MessageType type, const char *format, ...)
1105{
1106    va_list ap;
1107
1108    va_start(ap, format);
1109    LogVMessageVerb(type, 1, format, ap);
1110    va_end(ap);
1111}
1112
1113/* Just like ErrorF, but with the verbose level checked */
1114void
1115xf86ErrorFVerb(int verb, const char *format, ...)
1116{
1117    va_list ap;
1118
1119    va_start(ap, format);
1120    if (xf86Verbose >= verb || xf86LogVerbose >= verb)
1121        LogVWrite(verb, format, ap);
1122    va_end(ap);
1123}
1124
1125/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */
1126void
1127xf86ErrorF(const char *format, ...)
1128{
1129    va_list ap;
1130
1131    va_start(ap, format);
1132    if (xf86Verbose >= 1 || xf86LogVerbose >= 1)
1133        LogVWrite(1, format, ap);
1134    va_end(ap);
1135}
1136
1137/* Note temporarily modifies the passed in buffer! */
1138static void xf86_mkdir_p(char *path)
1139{
1140    char *sep = path;
1141
1142    while ((sep = strchr(sep + 1, '/'))) {
1143        *sep = 0;
1144        (void)mkdir(path, 0777);
1145        *sep = '/';
1146    }
1147    (void)mkdir(path, 0777);
1148}
1149
1150void
1151xf86LogInit(void)
1152{
1153    char *env, *lf = NULL;
1154    char buf[PATH_MAX];
1155
1156#define LOGSUFFIX ".log"
1157#define LOGOLDSUFFIX ".old"
1158
1159    /* Get the log file name */
1160    if (xf86LogFileFrom == X_DEFAULT) {
1161        /* When not running as root, we won't be able to write to /var/log */
1162        if (geteuid() != 0) {
1163            if ((env = getenv("XDG_DATA_HOME")))
1164                snprintf(buf, sizeof(buf), "%s/%s", env,
1165                         DEFAULT_XDG_DATA_HOME_LOGDIR);
1166            else if ((env = getenv("HOME")))
1167                snprintf(buf, sizeof(buf), "%s/%s/%s", env,
1168                         DEFAULT_XDG_DATA_HOME, DEFAULT_XDG_DATA_HOME_LOGDIR);
1169
1170            if (env) {
1171                xf86_mkdir_p(buf);
1172                strlcat(buf, "/" DEFAULT_LOGPREFIX, sizeof(buf));
1173                xf86LogFile = buf;
1174            }
1175        }
1176        /* Append the display number and ".log" */
1177        if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1)
1178            FatalError("Cannot allocate space for the log file name\n");
1179        xf86LogFile = lf;
1180    }
1181
1182    xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX);
1183    xf86LogFileWasOpened = TRUE;
1184
1185    xf86SetVerbosity(xf86Verbose);
1186    xf86SetLogVerbosity(xf86LogVerbose);
1187
1188#undef LOGSUFFIX
1189#undef LOGOLDSUFFIX
1190
1191    free(lf);
1192}
1193
1194void
1195xf86CloseLog(enum ExitCode error)
1196{
1197    LogClose(error);
1198}
1199
1200/*
1201 * Drivers can use these for using their own SymTabRecs.
1202 */
1203
1204const char *
1205xf86TokenToString(SymTabPtr table, int token)
1206{
1207    int i;
1208
1209    for (i = 0; table[i].token >= 0 && table[i].token != token; i++);
1210
1211    if (table[i].token < 0)
1212        return NULL;
1213    else
1214        return table[i].name;
1215}
1216
1217int
1218xf86StringToToken(SymTabPtr table, const char *string)
1219{
1220    int i;
1221
1222    if (string == NULL)
1223        return -1;
1224
1225    for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++);
1226
1227    return table[i].token;
1228}
1229
1230/*
1231 * helper to display the clocks found on a card
1232 */
1233void
1234xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)
1235{
1236    int j;
1237
1238    xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:");
1239    for (j = 0; j < scrp->numClocks; j++) {
1240        if ((j % 4) == 0) {
1241            xf86ErrorF("\n");
1242            xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:");
1243        }
1244        xf86ErrorF(" %7.3f", (double) scrp->clock[j] / 1000.0);
1245    }
1246    xf86ErrorF("\n");
1247}
1248
1249/*
1250 * This prints out the driver identify message, including the names of
1251 * the supported chipsets.
1252 *
1253 * XXX This makes assumptions about the line width, etc.  Maybe we could
1254 * use a more general "pretty print" function for messages.
1255 */
1256void
1257xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips)
1258{
1259    int len, i;
1260
1261    len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2;
1262    xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg);
1263    for (i = 0; chips[i].name != NULL; i++) {
1264        if (i != 0) {
1265            xf86ErrorF(",");
1266            len++;
1267        }
1268        if (len + 2 + strlen(chips[i].name) < 78) {
1269            xf86ErrorF(" ");
1270            len++;
1271        }
1272        else {
1273            xf86ErrorF("\n\t");
1274            len = 8;
1275        }
1276        xf86ErrorF("%s", chips[i].name);
1277        len += strlen(chips[i].name);
1278    }
1279    xf86ErrorF("\n");
1280}
1281
1282int
1283xf86MatchDevice(const char *drivername, GDevPtr ** sectlist)
1284{
1285    GDevPtr gdp, *pgdp = NULL;
1286    confScreenPtr screensecptr;
1287    int i, j, k;
1288
1289    if (sectlist)
1290        *sectlist = NULL;
1291
1292    /*
1293     * 20111009 jmcneill: This line was removed with the following commit upstream:
1294     *  http://cgit.freedesktop.org/xorg/xserver/commit/hw/xfree86/common/xf86Helper.c?id=0ceac6f64f5ad9bc2ac4b19be2dd245ffba78b05
1295     *
1296     * However, the log message is inaccurate: xf86MatchDevice will get called at
1297     * configuration time by drivers who still implement the legacy probing
1298     * API.
1299     */
1300    if (xf86DoConfigure && xf86DoConfigurePass1) return 1;
1301
1302    /*
1303     * This can happen when running Xorg -showopts and a module like ati
1304     * or vmware tries to load its submodules when xf86ConfigLayout is empty
1305     */
1306    if (!xf86ConfigLayout.screens)
1307        return 0;
1308
1309    /*
1310     * This is a very important function that matches the device sections
1311     * as they show up in the config file with the drivers that the server
1312     * loads at run time.
1313     *
1314     * ChipProbe can call
1315     * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
1316     * with its driver name. The function allocates an array of GDevPtr and
1317     * returns this via sectlist and returns the number of elements in
1318     * this list as return value. 0 means none found, -1 means fatal error.
1319     *
1320     * It can figure out which of the Device sections to use for which card
1321     * (using things like the Card statement, etc). For single headed servers
1322     * there will of course be just one such Device section.
1323     */
1324    i = 0;
1325
1326    /*
1327     * first we need to loop over all the Screens sections to get to all
1328     * 'active' device sections
1329     */
1330    for (j = 0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
1331        screensecptr = xf86ConfigLayout.screens[j].screen;
1332        if ((screensecptr->device != NULL)
1333            && (screensecptr->device->driver != NULL)
1334            && (xf86NameCmp(screensecptr->device->driver, drivername) == 0)
1335            && (!screensecptr->device->claimed)) {
1336            /*
1337             * we have a matching driver that wasn't claimed, yet
1338             */
1339            pgdp = xnfreallocarray(pgdp, i + 2, sizeof(GDevPtr));
1340            pgdp[i++] = screensecptr->device;
1341        }
1342        for (k = 0; k < screensecptr->num_gpu_devices; k++) {
1343            if ((screensecptr->gpu_devices[k]->driver != NULL)
1344            && (xf86NameCmp(screensecptr->gpu_devices[k]->driver, drivername) == 0)
1345                && (!screensecptr->gpu_devices[k]->claimed)) {
1346                /*
1347                 * we have a matching driver that wasn't claimed, yet
1348                 */
1349                pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1350                pgdp[i++] = screensecptr->gpu_devices[k];
1351            }
1352        }
1353    }
1354
1355    /* Then handle the inactive devices */
1356    j = 0;
1357    while (xf86ConfigLayout.inactives[j].identifier) {
1358        gdp = &xf86ConfigLayout.inactives[j];
1359        if (gdp->driver && !gdp->claimed &&
1360            !xf86NameCmp(gdp->driver, drivername)) {
1361            /* we have a matching driver that wasn't claimed yet */
1362            pgdp = xnfreallocarray(pgdp, i + 2, sizeof(GDevPtr));
1363            pgdp[i++] = gdp;
1364        }
1365        j++;
1366    }
1367
1368    /*
1369     * make the array NULL terminated and return its address
1370     */
1371    if (i)
1372        pgdp[i] = NULL;
1373
1374    if (sectlist)
1375        *sectlist = pgdp;
1376    else
1377        free(pgdp);
1378    return i;
1379}
1380
1381const char *
1382xf86GetVisualName(int visual)
1383{
1384    if (visual < 0 || visual > DirectColor)
1385        return NULL;
1386
1387    return xf86VisualNames[visual];
1388}
1389
1390int
1391xf86GetVerbosity(void)
1392{
1393    return max(xf86Verbose, xf86LogVerbose);
1394}
1395
1396int
1397xf86GetDepth(void)
1398{
1399    return xf86Depth;
1400}
1401
1402rgb
1403xf86GetWeight(void)
1404{
1405    return xf86Weight;
1406}
1407
1408Gamma
1409xf86GetGamma(void)
1410{
1411    return xf86Gamma;
1412}
1413
1414Bool
1415xf86GetFlipPixels(void)
1416{
1417    return xf86FlipPixels;
1418}
1419
1420Bool
1421xf86ServerIsExiting(void)
1422{
1423    return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
1424}
1425
1426Bool
1427xf86ServerIsResetting(void)
1428{
1429    return xf86Resetting;
1430}
1431
1432Bool
1433xf86ServerIsOnlyDetecting(void)
1434{
1435    return xf86DoConfigure;
1436}
1437
1438Bool
1439xf86GetVidModeAllowNonLocal(void)
1440{
1441    return xf86Info.vidModeAllowNonLocal;
1442}
1443
1444Bool
1445xf86GetVidModeEnabled(void)
1446{
1447    return xf86Info.vidModeEnabled;
1448}
1449
1450Bool
1451xf86GetModInDevAllowNonLocal(void)
1452{
1453    return xf86Info.miscModInDevAllowNonLocal;
1454}
1455
1456Bool
1457xf86GetModInDevEnabled(void)
1458{
1459    return xf86Info.miscModInDevEnabled;
1460}
1461
1462Bool
1463xf86GetAllowMouseOpenFail(void)
1464{
1465    return xf86Info.allowMouseOpenFail;
1466}
1467
1468CARD32
1469xf86GetModuleVersion(void *module)
1470{
1471    return (CARD32) LoaderGetModuleVersion(module);
1472}
1473
1474void *
1475xf86LoadDrvSubModule(DriverPtr drv, const char *name)
1476{
1477    void *ret;
1478    int errmaj = 0, errmin = 0;
1479
1480    ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
1481                        &errmaj, &errmin);
1482    if (!ret)
1483        LoaderErrorMsg(NULL, name, errmaj, errmin);
1484    return ret;
1485}
1486
1487void *
1488xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
1489{
1490    void *ret;
1491    int errmaj = 0, errmin = 0;
1492
1493    ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
1494                        &errmaj, &errmin);
1495    if (!ret)
1496        LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
1497    return ret;
1498}
1499
1500/*
1501 * xf86LoadOneModule loads a single module.
1502 */
1503void *
1504xf86LoadOneModule(const char *name, void *opt)
1505{
1506    int errmaj;
1507    char *Name;
1508    void *mod;
1509
1510    if (!name)
1511        return NULL;
1512
1513    /* Normalise the module name */
1514    Name = xf86NormalizeName(name);
1515
1516    /* Skip empty names */
1517    if (Name == NULL)
1518        return NULL;
1519    if (*Name == '\0') {
1520        free(Name);
1521        return NULL;
1522    }
1523
1524    mod = LoadModule(Name, opt, NULL, &errmaj);
1525    if (!mod)
1526        LoaderErrorMsg(NULL, Name, errmaj, 0);
1527    free(Name);
1528    return mod;
1529}
1530
1531void
1532xf86UnloadSubModule(void *mod)
1533{
1534    UnloadSubModule(mod);
1535}
1536
1537Bool
1538xf86LoaderCheckSymbol(const char *name)
1539{
1540    return LoaderSymbol(name) != NULL;
1541}
1542
1543typedef enum {
1544    OPTION_BACKING_STORE
1545} BSOpts;
1546
1547static const OptionInfoRec BSOptions[] = {
1548    {OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE},
1549    {-1, NULL, OPTV_NONE, {0}, FALSE}
1550};
1551
1552void
1553xf86SetBackingStore(ScreenPtr pScreen)
1554{
1555    Bool useBS = FALSE;
1556    MessageType from = X_DEFAULT;
1557    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1558    OptionInfoPtr options;
1559
1560    options = xnfalloc(sizeof(BSOptions));
1561    (void) memcpy(options, BSOptions, sizeof(BSOptions));
1562    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1563
1564    /* check for commandline option here */
1565    if (xf86bsEnableFlag) {
1566        from = X_CMDLINE;
1567        useBS = TRUE;
1568    }
1569    else if (xf86bsDisableFlag) {
1570        from = X_CMDLINE;
1571        useBS = FALSE;
1572    }
1573    else {
1574        if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
1575            from = X_CONFIG;
1576#ifdef COMPOSITE
1577        if (from != X_CONFIG)
1578            useBS = xf86ReturnOptValBool(options, OPTION_BACKING_STORE,
1579                                         !noCompositeExtension);
1580#endif
1581    }
1582    free(options);
1583    pScreen->backingStoreSupport = useBS ? WhenMapped : NotUseful;
1584    if (serverGeneration == 1)
1585        xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
1586                   useBS ? "enabled" : "disabled");
1587}
1588
1589typedef enum {
1590    OPTION_SILKEN_MOUSE
1591} SMOpts;
1592
1593static const OptionInfoRec SMOptions[] = {
1594    {OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE},
1595    {-1, NULL, OPTV_NONE, {0}, FALSE}
1596};
1597
1598void
1599xf86SetSilkenMouse(ScreenPtr pScreen)
1600{
1601    Bool useSM = TRUE;
1602    MessageType from = X_DEFAULT;
1603    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1604    OptionInfoPtr options;
1605
1606    options = xnfalloc(sizeof(SMOptions));
1607    (void) memcpy(options, SMOptions, sizeof(SMOptions));
1608    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1609
1610    /* check for commandline option here */
1611    /* disable if screen shares resources */
1612    /* TODO VGA arb disable silken mouse */
1613    if (xf86silkenMouseDisableFlag) {
1614        from = X_CMDLINE;
1615        useSM = FALSE;
1616    }
1617    else {
1618        if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
1619            from = X_CONFIG;
1620    }
1621    free(options);
1622    /*
1623     * Use silken mouse if requested and if we have threaded input
1624     */
1625    pScrn->silkenMouse = useSM && InputThreadEnable;
1626    if (serverGeneration == 1)
1627        xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
1628                   pScrn->silkenMouse ? "enabled" : "disabled");
1629}
1630
1631/* Wrote this function for the PM2 Xv driver, preliminary. */
1632
1633void *
1634xf86FindXvOptions(ScrnInfoPtr pScrn, int adaptor_index, const char *port_name,
1635                  const char **adaptor_name, void **adaptor_options)
1636{
1637    confXvAdaptorPtr adaptor;
1638    int i;
1639
1640    if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
1641        if (adaptor_name)
1642            *adaptor_name = NULL;
1643        if (adaptor_options)
1644            *adaptor_options = NULL;
1645        return NULL;
1646    }
1647
1648    adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
1649    if (adaptor_name)
1650        *adaptor_name = adaptor->identifier;
1651    if (adaptor_options)
1652        *adaptor_options = adaptor->options;
1653
1654    for (i = 0; i < adaptor->numports; i++)
1655        if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
1656            return adaptor->ports[i].options;
1657
1658    return NULL;
1659}
1660
1661static void
1662xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
1663                           EntityProc enter, EntityProc leave, void *private)
1664{
1665    ScrnInfoPtr pScrn;
1666
1667    if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1668        xf86RemoveEntityFromScreen(pScrn, pEnt->index);
1669}
1670
1671ScrnInfoPtr
1672xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1673                   EntityProc init, EntityProc enter, EntityProc leave,
1674                   void *private)
1675{
1676    EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1677
1678    if (init || enter || leave)
1679        FatalError("Legacy entity access functions are unsupported\n");
1680
1681    if (!pEnt)
1682        return pScrn;
1683
1684    if (!(pEnt->location.type == BUS_NONE)) {
1685        free(pEnt);
1686        return pScrn;
1687    }
1688
1689    if (!pEnt->active) {
1690        xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private);
1691        free(pEnt);
1692        return pScrn;
1693    }
1694
1695    if (!pScrn)
1696        pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
1697    xf86AddEntityToScreen(pScrn, entityIndex);
1698
1699    free(pEnt);
1700    return pScrn;
1701}
1702
1703Bool
1704xf86IsScreenPrimary(ScrnInfoPtr pScrn)
1705{
1706    int i;
1707
1708    for (i = 0; i < pScrn->numEntities; i++) {
1709        if (xf86IsEntityPrimary(i))
1710            return TRUE;
1711    }
1712    return FALSE;
1713}
1714
1715Bool
1716xf86IsUnblank(int mode)
1717{
1718    switch (mode) {
1719    case SCREEN_SAVER_OFF:
1720    case SCREEN_SAVER_FORCER:
1721        return TRUE;
1722    case SCREEN_SAVER_ON:
1723    case SCREEN_SAVER_CYCLE:
1724        return FALSE;
1725    default:
1726        xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
1727        return TRUE;
1728    }
1729}
1730
1731void
1732xf86MotionHistoryAllocate(InputInfoPtr pInfo)
1733{
1734    AllocateMotionHistory(pInfo->dev);
1735}
1736
1737ScrnInfoPtr
1738xf86ScreenToScrn(ScreenPtr pScreen)
1739{
1740    if (pScreen->isGPU) {
1741        assert(pScreen->myNum - GPU_SCREEN_OFFSET < xf86NumGPUScreens);
1742        return xf86GPUScreens[pScreen->myNum - GPU_SCREEN_OFFSET];
1743    } else {
1744        assert(pScreen->myNum < xf86NumScreens);
1745        return xf86Screens[pScreen->myNum];
1746    }
1747}
1748
1749ScreenPtr
1750xf86ScrnToScreen(ScrnInfoPtr pScrn)
1751{
1752    if (pScrn->is_gpu) {
1753        assert(pScrn->scrnIndex - GPU_SCREEN_OFFSET < screenInfo.numGPUScreens);
1754        return screenInfo.gpuscreens[pScrn->scrnIndex - GPU_SCREEN_OFFSET];
1755    } else {
1756        assert(pScrn->scrnIndex < screenInfo.numScreens);
1757        return screenInfo.screens[pScrn->scrnIndex];
1758    }
1759}
1760
1761void
1762xf86UpdateDesktopDimensions(void)
1763{
1764    update_desktop_dimensions();
1765}
1766
1767
1768void
1769xf86AddInputEventDrainCallback(CallbackProcPtr callback, void *param)
1770{
1771    mieqAddCallbackOnDrained(callback, param);
1772}
1773
1774void
1775xf86RemoveInputEventDrainCallback(CallbackProcPtr callback, void *param)
1776{
1777    mieqRemoveCallbackOnDrained(callback, param);
1778}
1779